Index: wp-includes/default-filters.php
===================================================================
--- wp-includes/default-filters.php	(revision 24277)
+++ wp-includes/default-filters.php	(working copy)
@@ -136,7 +136,7 @@
 add_filter( 'the_title', 'trim'          );
 add_filter( 'the_title', '_post_formats_title', 10, 2 );
 
-add_filter( 'the_content', 'post_formats_compat', 7 );
+add_filter( 'the_content', 'post_formats_compat', 7, 2 );
 add_filter( 'the_content', 'wptexturize'            );
 add_filter( 'the_content', 'convert_smilies'        );
 add_filter( 'the_content', 'convert_chars'          );
Index: wp-includes/post-template.php
===================================================================
--- wp-includes/post-template.php	(revision 24277)
+++ wp-includes/post-template.php	(working copy)
@@ -160,9 +160,20 @@
  *
  * @param string $more_link_text Optional. Content for when there is more text.
  * @param bool $strip_teaser Optional. Strip teaser content before the more text. Default is false.
+ * @param int $id Optional. A post id. Defaults to the current post when in The Loop, undefined otherwise.
  */
-function the_content( $more_link_text = null, $strip_teaser = false ) {
-	$content = apply_filters( 'the_content', get_the_content( $more_link_text, $strip_teaser ) );
+function the_content( $more_link_text = null, $strip_teaser = false, $id = 0 ) {
+	$post = get_post( $id );
+
+	/*
+	 * Filter: the_content
+	 *
+	 * param string Post content as returned by get_the_content()
+	 * param int The ID of the post to which the content belongs. This was introduced
+	 *           in 3.6.0 and is not reliably passed by all plugins and themes that
+	 *           directly apply the_content. As such, it is not considered portable.
+	 */
+	$content = apply_filters( 'the_content', get_the_content( $more_link_text, $strip_teaser, $post->ID ), $post->ID );
 	echo str_replace( ']]>', ']]&gt;', $content );
 }
 
@@ -173,12 +184,19 @@
  *
  * @param string $more_link_text Optional. Content for when there is more text.
  * @param bool $stripteaser Optional. Strip teaser content before the more text. Default is false.
+ * @param int $id Optional. A post id. Defaults to the current post when in The Loop, undefined otherwise.
  * @return string
  */
-function get_the_content( $more_link_text = null, $strip_teaser = false ) {
-	global $more, $page, $pages, $multipage, $preview;
+function get_the_content( $more_link_text = null, $strip_teaser = false, $id = 0 ) {
+	global $page, $more, $preview;
 
-	$post = get_post();
+	$post = get_post( $id );
+	// Avoid parsing again if the post is the same one parsed by setup_postdata().
+	// The extract() will set up $pages and $multipage.
+	if ( $post->ID != $GLOBALS['id'] )
+		extract( wp_parse_post_content( $post, false ) );
+	else
+		global $pages, $multipage;
 
 	if ( null === $more_link_text )
 		$more_link_text = __( '(more&hellip;)' );
@@ -187,8 +205,8 @@
 	$has_teaser = false;
 
 	// If post password required and it doesn't match the cookie.
-	if ( post_password_required() )
-		return get_the_password_form();
+	if ( post_password_required( $post ) )
+		return get_the_password_form( $post );
 
 	if ( $page > count( $pages ) ) // if the requested page doesn't exist
 		$page = count( $pages ); // give them the highest numbered page that DOES exist
@@ -1225,11 +1243,11 @@
  *
  * @since 1.0.0
  * @uses apply_filters() Calls 'the_password_form' filter on output.
- *
+ * @param int $id Optional. A post id. Defaults to the current post when in The Loop, undefined otherwise.
  * @return string HTML content for password form for password protected post.
  */
-function get_the_password_form() {
-	$post = get_post();
+function get_the_password_form( $id = 0 ) {
+	$post = get_post( $id );
 	$label = 'pwbox-' . ( empty($post->ID) ? rand() : $post->ID );
 	$output = '<form action="' . esc_url( site_url( 'wp-login.php?action=postpass', 'login_post' ) ) . '" method="post">
 	<p>' . __("This post is password protected. To view it please enter your password below:") . '</p>
Index: wp-includes/post.php
===================================================================
--- wp-includes/post.php	(revision 24277)
+++ wp-includes/post.php	(working copy)
@@ -567,6 +567,26 @@
 	 */
 	public $filter;
 
+	/**
+	 * Private variable used by post formats to cache parsed content.
+	 *
+	 * @since 3.6.0
+	 *
+	 * @var array
+	 * @access private
+	 */
+	public $format_content;
+
+	/**
+	 * Private variable used by post formats to cache parsed content.
+	 *
+	 * @since 3.6.0
+	 *
+	 * @var string
+	 * @access private
+	 */
+	public $split_content;
+
 	public static function get_instance( $post_id ) {
 		global $wpdb;
 
@@ -4962,3 +4982,56 @@
 		update_post_caches( $fresh_posts, 'any', $update_term_cache, $update_meta_cache );
 	}
 }
+
+/**
+ * Parse post content for pagination
+ *
+ * @since 3.6.0
+ *
+ * @uses paginate_content()
+ *
+ * @param object $post The post object.
+ * @param bool $remaining Whether to parse post formats from the content. Defaults to false.
+ * @return array An array of values used for paginating the parsed content.
+ */
+function wp_parse_post_content( $post, $remaining = false ) {
+	$numpages = 1;
+
+	if ( $remaining ) {
+		$format = get_post_format( $post );
+		if ( $format && in_array( $format, array( 'image', 'audio', 'video', 'quote' ) ) ) {
+			// Call get_the_post_format_*() to set $post->split_content
+			switch ( $format ) {
+				case 'image':
+					get_the_post_format_image( 'full', $post );
+					break;
+				case 'audio':
+					get_the_post_format_media( 'audio', $post, 1 );
+					break;
+				case 'video':
+					get_the_post_format_media( 'video', $post, 1 );
+					break;
+				case 'quote':
+					get_the_post_format_quote( $post );
+					break;
+			}
+		}
+	}
+
+	if ( strpos( $post->post_content, '<!--nextpage-->' ) ) {
+		$multipage = 1;
+		if ( $remaining && isset( $post->split_content ) )
+			$pages = paginate_content( $post->split_content );
+		else
+			$pages = paginate_content( $post->post_content );
+		$numpages = count( $pages );
+	} else {
+		if ( $remaining && isset( $post->split_content ) )
+			$pages = array( $post->split_content );
+		else
+			$pages = array( $post->post_content );
+		$multipage = 0;
+	}
+
+	return compact( 'multipage', 'pages', 'numpages' );
+}
Index: wp-includes/post-formats.php
===================================================================
--- wp-includes/post-formats.php	(revision 24277)
+++ wp-includes/post-formats.php	(working copy)
@@ -866,13 +866,16 @@
  *
  * @param string $more_link_text Optional. Content for when there is more text.
  * @param bool $strip_teaser Optional. Strip teaser content before the more text. Default is false.
+ * @param int $id Optional. A post id. Defaults to the current post when in The Loop, undefined otherwise.
  * @return string The content minus the extracted post format content.
  */
-function get_the_remaining_content( $more_link_text = null, $strip_teaser = false ) {
-	global $more, $page, $format_pages, $multipage, $preview;
+function get_the_remaining_content( $more_link_text = null, $strip_teaser = false, $id = 0 ) {
+	global $more, $page, $preview;
 
-	$post = get_post();
+	$post = get_post( $id );
 
+	extract( wp_parse_post_content( $post, true ) );
+
 	if ( null === $more_link_text )
 		$more_link_text = __( '(more&hellip;)' );
 
@@ -880,13 +883,13 @@
 	$has_teaser = false;
 
 	// If post password required and it doesn't match the cookie.
-	if ( post_password_required() )
-		return get_the_password_form();
+	if ( post_password_required( $post ) )
+		return get_the_password_form( $post );
 
-	if ( $page > count( $format_pages ) ) // if the requested page doesn't exist
-		$page = count( $format_pages ); // give them the highest numbered page that DOES exist
+	if ( $page > count( $pages ) ) // if the requested page doesn't exist
+		$page = count( $pages ); // give them the highest numbered page that DOES exist
 
-	$content = $format_pages[$page-1];
+	$content = $pages[$page-1];
 	if ( preg_match( '/<!--more(.*?)?-->/', $content, $matches ) ) {
 		$content = explode( $matches[0], $content, 2 );
 		if ( ! empty( $matches[1] ) && ! empty( $more_link_text ) )
@@ -931,12 +934,15 @@
  *
  * @param string $more_link_text Optional. Content for when there is more text.
  * @param bool $strip_teaser Optional. Strip teaser content before the more text. Default is false.
+ * @param int $id Optional. A post id. Defaults to the current post when in The Loop, undefined otherwise.
  */
-function the_remaining_content( $more_link_text = null, $strip_teaser = false ) {
-	$extra = get_the_remaining_content( $more_link_text, $strip_teaser );
+function the_remaining_content( $more_link_text = null, $strip_teaser = false, $id = 0 ) {
+	$post = get_post( $id );
 
+	$extra = get_the_remaining_content( $more_link_text, $strip_teaser, $post->ID );
+
 	remove_filter( 'the_content', 'post_formats_compat', 7 );
-	$content = apply_filters( 'the_content', $extra );
+	$content = apply_filters( 'the_content', $extra, $post->ID );
 	add_filter( 'the_content', 'post_formats_compat', 7 );
 
 	echo str_replace( ']]>', ']]&gt;', $content );
Index: wp-includes/comment.php
===================================================================
--- wp-includes/comment.php	(revision 24277)
+++ wp-includes/comment.php	(working copy)
@@ -1749,7 +1749,7 @@
 	}
 
 	if ( empty($post->post_excerpt) )
-		$excerpt = apply_filters('the_content', $post->post_content);
+		$excerpt = apply_filters('the_content', $post->post_content, $post->ID);
 	else
 		$excerpt = apply_filters('the_excerpt', $post->post_excerpt);
 	$excerpt = str_replace(']]>', ']]&gt;', $excerpt);
Index: wp-includes/query.php
===================================================================
--- wp-includes/query.php	(revision 24277)
+++ wp-includes/query.php	(working copy)
@@ -3681,8 +3681,8 @@
  * @uses do_action_ref_array() Calls 'the_post'
  * @return bool True when finished.
  */
-function setup_postdata($post) {
-	global $id, $authordata, $currentday, $currentmonth, $page, $pages, $format_pages, $multipage, $more, $numpages;
+function setup_postdata( $post ) {
+	global $id, $authordata, $currentday, $currentmonth, $page, $pages, $multipage, $more, $numpages;
 
 	$id = (int) $post->ID;
 
@@ -3692,49 +3692,15 @@
 	$currentmonth = mysql2date('m', $post->post_date, false);
 	$numpages = 1;
 	$page = get_query_var('page');
-	if ( !$page )
+	if ( ! $page )
 		$page = 1;
 	if ( is_single() || is_page() || is_feed() )
 		$more = 1;
-	$split_content = $content = $post->post_content;
-	$format = get_post_format( $post );
-	if ( $format && in_array( $format, array( 'image', 'audio', 'video', 'quote' ) ) ) {
-		switch ( $format ) {
-		case 'image':
-			get_the_post_format_image( 'full', $post );
-			if ( isset( $post->split_content ) )
-				$split_content = $post->split_content;
-			break;
-		case 'audio':
-			get_the_post_format_media( 'audio', $post, 1 );
-			if ( isset( $post->split_content ) )
-				$split_content = $post->split_content;
-			break;
-		case 'video':
-			get_the_post_format_media( 'video', $post, 1 );
-			if ( isset( $post->split_content ) )
-				$split_content = $post->split_content;
-			break;
-		case 'quote':
-			get_the_post_format_quote( $post );
-			if ( isset( $post->split_content ) )
-				$split_content = $post->split_content;
-			break;
-		}
-	}
 
-	if ( strpos( $content, '<!--nextpage-->' ) ) {
-		if ( $page > 1 )
+	extract( wp_parse_post_content( $post, false ) );
+
+	if ( $multipage && ( $page > 1 ) )
 			$more = 1;
-		$multipage = 1;
-		$pages = paginate_content( $content );
-		$format_pages = paginate_content( $split_content );
-		$numpages = count( $pages );
-	} else {
-		$pages = array( $post->post_content );
-		$format_pages = array( $split_content );
-		$multipage = 0;
-	}
 
 	do_action_ref_array('the_post', array(&$post));
 
