diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -97,18 +97,18 @@ class nsBindingManager;
 class nsIDOMNodeList;
 class mozAutoSubtreeModified;
 struct JSObject;
 class nsFrameLoader;
 class nsIBoxObject;
 
 // IID for the nsIDocument interface
 #define NS_IDOCUMENT_IID      \
-{ 0x62579239, 0xb619, 0x4bf2, \
-  { 0x8d, 0x39, 0x0b, 0x73, 0xe8, 0x66, 0x3a, 0x85 } }
+{ 0x11bfea51, 0x8916, 0x4caa, \
+  { 0xa6, 0x00, 0x27, 0xc3, 0x5d, 0x8b, 0x88, 0x5b } }
 
 // Flag for AddStyleSheet().
 #define NS_STYLESHEET_FROM_CATALOG                (1 << 0)
 
 //----------------------------------------------------------------------
 
 // Document interface.  This is implemented by all document objects in
 // Gecko.
@@ -1133,16 +1133,19 @@ public:
   /**
    * Unsuppress event handling.
    * @param aFireEvents If PR_TRUE, delayed events (focus/blur) will be fired
    *                    asynchronously.
    */
   virtual void UnsuppressEventHandlingAndFireEvents(PRBool aFireEvents) = 0;
 
   PRUint32 EventHandlingSuppressed() { return mEventsSuppressed; }
+
+  void SetCloningForPrinting(PRBool aClone) { mCloningForPrinting = aClone; }
+  PRBool CloningForPrinting() { return mCloningForPrinting; }
 protected:
   ~nsIDocument()
   {
     // XXX The cleanup of mNodeInfoManager (calling DropDocumentReference and
     //     releasing it) happens in the nsDocument destructor. We'd prefer to
     //     do it here but nsNodeInfoManager is a concrete class that we don't
     //     want to expose to users of the nsIDocument API outside of Gecko.
   }
@@ -1208,17 +1211,19 @@ protected:
   // point where it's safe to start layout on it.
   PRPackedBool mMayStartLayout;
   
   // True iff we've ever fired a DOMTitleChanged event for this document
   PRPackedBool mHaveFiredTitleChange;
 
   // True iff IsShowing() should be returning true
   PRPackedBool mIsShowing;
-  
+
+  PRPackedBool mCloningForPrinting;
+
   // The bidi options for this document.  What this bitfield means is
   // defined in nsBidiUtils.h
   PRUint32 mBidiOptions;
 
   nsCString mContentLanguage;
   nsCString mContentType;
 
   // The document's security info
diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -2996,16 +2996,19 @@ nsDocument::doCreateShell(nsPresContext*
   }
 
   rv = shell->Init(this, aContext, aViewManager, aStyleSet, aCompatMode);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Note: we don't hold a ref to the shell (it holds a ref to us)
   NS_ENSURE_TRUE(mPresShells.AppendElementUnlessExists(shell),
                  NS_ERROR_OUT_OF_MEMORY);
+
+  NS_WARN_IF_FALSE(mPresShells.Length() == 1, "More than one presshell!");
+
   shell.swap(*aInstancePtrResult);
 
   return NS_OK;
 }
 
 PRBool
 nsDocument::DeleteShell(nsIPresShell* aShell)
 {
@@ -7383,16 +7386,28 @@ nsDocument::CloneDocHelper(nsDocument* c
   // Init document
   nsresult rv = clone->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Set URI/principal
   clone->nsDocument::SetDocumentURI(nsIDocument::GetDocumentURI());
   // Must set the principal first, since SetBaseURI checks it.
   clone->SetPrincipal(NodePrincipal());
+
+  nsCOMPtr<nsIChannel> channel = GetChannel();
+  nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
+  if (channel && loadGroup) {
+    clone->Reset(channel, loadGroup);
+  } else {
+    nsIURI* uri = static_cast<const nsIDocument*>(this)->GetDocumentURI();
+    if (uri) {
+      clone->ResetToURI(uri, loadGroup, NodePrincipal());
+    }
+  }
+
   clone->mDocumentBaseURI = mDocumentBaseURI;
 
   // Set scripting object
   PRBool hasHadScriptObject = PR_TRUE;
   nsIScriptGlobalObject* scriptObject =
     GetScriptHandlingObject(hasHadScriptObject);
   NS_ENSURE_STATE(scriptObject || !hasHadScriptObject);
   clone->SetScriptHandlingObject(scriptObject);
diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -192,17 +192,16 @@ GK_ATOM(circle, "circle")
 GK_ATOM(cite, "cite")
 GK_ATOM(_class, "class")
 GK_ATOM(classid, "classid")
 GK_ATOM(clear, "clear")
 GK_ATOM(click, "click")
 GK_ATOM(clickcount, "clickcount")
 GK_ATOM(movetoclick, "movetoclick")
 GK_ATOM(clip, "clip")
-GK_ATOM(clonedTextForPrint, "clonedTextForPrint")
 GK_ATOM(close, "close")
 GK_ATOM(closed, "closed")
 GK_ATOM(closemenu, "closemenu")
 GK_ATOM(coalesceduplicatearcs, "coalesceduplicatearcs")
 GK_ATOM(code, "code")
 GK_ATOM(codebase, "codebase")
 GK_ATOM(codetype, "codetype")
 GK_ATOM(col, "col")
@@ -736,16 +735,17 @@ GK_ATOM(preceding, "preceding")
 GK_ATOM(precedingSibling, "preceding-sibling")
 GK_ATOM(predicate, "predicate")
 GK_ATOM(prefix, "prefix")
 GK_ATOM(preserve, "preserve")
 GK_ATOM(preserveSpace, "preserve-space")
 GK_ATOM(preventdefault, "preventdefault")
 GK_ATOM(primary, "primary")
 GK_ATOM(print, "print")
+GK_ATOM(printNode, "printNode")
 GK_ATOM(priority, "priority")
 GK_ATOM(processingInstruction, "processing-instruction")
 GK_ATOM(profile, "profile")
 GK_ATOM(progressmeter, "progressmeter")
 GK_ATOM(progressNormal, "progressNormal")
 GK_ATOM(progressUndetermined, "progressUndetermined")
 GK_ATOM(projection, "projection")
 GK_ATOM(prompt, "prompt")
diff --git a/content/base/src/nsNodeUtils.cpp b/content/base/src/nsNodeUtils.cpp
--- a/content/base/src/nsNodeUtils.cpp
+++ b/content/base/src/nsNodeUtils.cpp
@@ -49,16 +49,17 @@
 #include "pldhash.h"
 #include "nsIDOMAttr.h"
 #include "nsCOMArray.h"
 #include "nsPIDOMWindow.h"
 #ifdef MOZ_XUL
 #include "nsXULElement.h"
 #endif
 #include "nsBindingManager.h"
+#include "nsPropertyTable.h"
 
 // This macro expects the ownerDocument of content_ to be in scope as
 // |nsIDocument* doc|
 #define IMPL_MUTATION_NOTIFICATION(func_, content_, params_)      \
   PR_BEGIN_MACRO                                                  \
   nsINode* node = content_;                                       \
   NS_ASSERTION(node->GetOwnerDoc() == doc, "Bogus document");     \
   if (doc) {                                                      \
@@ -558,16 +559,24 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
       NS_ENSURE_SUCCESS(rv, rv);
     }
     else if (aDeep && clone->IsNodeOfType(nsINode::eDOCUMENT)) {
       // After cloning the document itself, we want to clone the children into
       // the cloned document (somewhat like cloning and importing them into the
       // cloned document).
       nodeInfoManager = clone->mNodeInfo->NodeInfoManager();
     }
+    nsIDocument* doc = aNode->GetOwnerDoc();
+    if (doc && doc->CloningForPrinting()) {
+      rv = aNode->SetProperty(nsGkAtoms::printNode, clone.get(),
+                              nsPropertyTable::SupportsDtorFunc);
+      if (NS_SUCCEEDED(rv)) {
+        NS_ADDREF(clone.get());
+      }
+    }
   }
   else if (nodeInfoManager) {
     nsIDocument* oldDoc = aNode->GetOwnerDoc();
     if (oldDoc && aNode->IsNodeOfType(nsINode::eELEMENT)) {
       oldDoc->ClearBoxObjectFor(static_cast<nsIContent*>(aNode));
     }
 
     aNode->mNodeInfo.swap(newNodeInfo);
diff --git a/content/base/src/nsTextFragment.cpp b/content/base/src/nsTextFragment.cpp
--- a/content/base/src/nsTextFragment.cpp
+++ b/content/base/src/nsTextFragment.cpp
@@ -101,17 +101,16 @@ nsTextFragment::Shutdown()
     sSpaceSharedString[i] = nsnull;
     sTabSharedString[i] = nsnull;
   }
 }
 
 nsTextFragment::~nsTextFragment()
 {
   ReleaseText();
-  MOZ_COUNT_DTOR(nsTextFragment);
 }
 
 void
 nsTextFragment::ReleaseText()
 {
   if (mState.mLength && m1b && mState.mInHeap) {
     nsMemory::Free(m2b); // m1b == m2b as far as nsMemory is concerned
   }
diff --git a/content/base/src/nsTextFragment.h b/content/base/src/nsTextFragment.h
--- a/content/base/src/nsTextFragment.h
+++ b/content/base/src/nsTextFragment.h
@@ -40,17 +40,16 @@
  * node); if only codepoints below 256 are used, the text is stored as
  * a char*; otherwise the text is stored as a PRUnichar*
  */
 
 #ifndef nsTextFragment_h___
 #define nsTextFragment_h___
 
 #include "nsAString.h"
-#include "nsTraceRefcnt.h"
 class nsString;
 class nsCString;
 
 // XXX should this normalize the code to keep a \u0000 at the end?
 
 // XXX nsTextFragmentPool?
 
 // XXX these need I18N spankage
@@ -84,17 +83,16 @@ public:
   static void Shutdown();
 
   /**
    * Default constructor. Initialize the fragment to be empty.
    */
   nsTextFragment()
     : m1b(nsnull), mAllBits(0)
   {
-    MOZ_COUNT_CTOR(nsTextFragment);
     NS_ASSERTION(sizeof(FragmentBits) == 4, "Bad field packing!");
   }
 
   ~nsTextFragment();
 
   /**
    * Change the contents of this fragment to be a copy of the
    * the argument fragment.
diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -11469,18 +11469,17 @@ nsCSSFrameConstructor::RebuildAllStyleDa
   NS_ASSERTION(!(aExtraHint & nsChangeHint_ReconstructFrame),
                "Should not reconstruct the root of the frame tree.  "
                "Use ReconstructDocElementHierarchy instead.");
 
   mRebuildAllStyleData = PR_FALSE;
   NS_UpdateHint(aExtraHint, mRebuildAllExtraHint);
   mRebuildAllExtraHint = nsChangeHint(0);
 
-  if (!mPresShell || !mPresShell->GetRootFrame() ||
-      !mPresShell->GetPresContext()->IsDynamic())
+  if (!mPresShell || !mPresShell->GetRootFrame())
     return;
 
   nsAutoScriptBlocker scriptBlocker;
 
   // Make sure that the viewmanager will outlive the presshell
   nsIViewManager::UpdateViewBatch batch(mPresShell->GetViewManager());
 
   // Processing the style changes could cause a flush that propagates to
diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -1672,24 +1672,28 @@ DocumentViewerImpl::GetDocument(nsIDocum
 }
 
 nsIPresShell*
 DocumentViewerImpl::GetPresShell()
 {
   if (!GetIsPrintPreview()) {
     return mPresShell;
   }
-  NS_ENSURE_TRUE(mDocument, nsnull);
-  nsCOMPtr<nsIPresShell> shell;
-  nsCOMPtr<nsIPresShell> currentShell;
-  nsPresShellIterator iter(mDocument);
-  while ((shell = iter.GetNextShell())) {
-    currentShell.swap(shell);
-  }
-  return currentShell.get();
+#if NS_PRINT_PREVIEW
+  if (mPrintEngine) {
+    nsIDocument* printDocument = mPrintEngine->GetPrintPreviewDocument();
+    if (printDocument) {
+      nsIPresShell* shell = printDocument->GetPrimaryShell();
+      if (shell) {
+        return shell;
+      }
+    }
+  }
+#endif
+  return mPresShell;
 }
 
 nsPresContext*
 DocumentViewerImpl::GetPresContext()
 {
   if (!GetIsPrintPreview()) {
     return mPresContext;
   }
diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -75,17 +75,16 @@
 #include "nsIBaseWindow.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIWidget.h"
 #include "gfxMatrix.h"
 #include "gfxTypes.h"
 #include "gfxUserFontSet.h"
 #include "nsTArray.h"
-#include "nsTextFragment.h"
 
 #ifdef MOZ_SVG
 #include "nsSVGUtils.h"
 #include "nsSVGIntegrationUtils.h"
 #include "nsSVGForeignObjectFrame.h"
 #include "nsSVGOuterSVGFrame.h"
 #endif
 
@@ -3217,58 +3216,16 @@ nsLayoutUtils::IsReallyFixedPos(nsIFrame
                     NS_STYLE_POSITION_FIXED,
                   "IsReallyFixedPos called on non-'position:fixed' frame");
 
   nsIAtom *parentType = aFrame->GetParent()->GetType();
   return parentType == nsGkAtoms::viewportFrame ||
          parentType == nsGkAtoms::pageContentFrame;
 }
 
-static void DeleteTextFragment(void* aObject, nsIAtom* aPropertyName,
-                               void* aPropertyValue, void* aData)
-{
-  delete static_cast<nsTextFragment*>(aPropertyValue);
-}
-
-/* static */ nsTextFragment*
-nsLayoutUtils::GetTextFragmentForPrinting(const nsIFrame* aFrame)
-{
-  nsPresContext* presContext = aFrame->PresContext();
-  NS_PRECONDITION(!presContext->IsDynamic(),
-                  "Shouldn't call this with dynamic PresContext");
-#ifdef MOZ_SVG
-  NS_PRECONDITION(aFrame->GetType() == nsGkAtoms::textFrame ||
-                  aFrame->GetType() == nsGkAtoms::svgGlyphFrame,
-                  "Wrong frame type!");
-#else
-  NS_PRECONDITION(aFrame->GetType() == nsGkAtoms::textFrame,
-                  "Wrong frame type!");
-#endif // MOZ_SVG
-
-  nsIContent* content = aFrame->GetContent();
-  nsTextFragment* frag =
-    static_cast<nsTextFragment*>(presContext->PropertyTable()->
-      GetProperty(content, nsGkAtoms::clonedTextForPrint));
-
-  if (!frag) {
-    frag = new nsTextFragment();
-    NS_ENSURE_TRUE(frag, nsnull);
-    *frag = *content->GetText();
-    nsresult rv = presContext->PropertyTable()->
-                    SetProperty(content, nsGkAtoms::clonedTextForPrint, frag,
-                                DeleteTextFragment, nsnull);
-    if (NS_FAILED(rv)) {
-      delete frag;
-      return nsnull;
-    }
-  }
-
-  return frag;
-}
-
 nsSetAttrRunnable::nsSetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName,
                                      const nsAString& aValue)
   : mContent(aContent),
     mAttrName(aAttrName),
     mValue(aValue)
 {
   NS_ASSERTION(aContent && aAttrName, "Missing stuff, prepare to crash");
 }
diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -58,17 +58,16 @@ class nsIFontMetrics;
 #include "nsStyleSet.h"
 #include "nsIView.h"
 #include "nsIFrame.h"
 #include "nsThreadUtils.h"
 #include "nsIPresShell.h"
 #include "gfxPattern.h"
 
 class nsBlockFrame;
-class nsTextFragment;
 
 /**
  * nsLayoutUtils is a namespace class used for various helper
  * functions that are useful in multiple places in layout.  The goal
  * is not to define multiple copies of the same static helper.
  */
 class nsLayoutUtils
 {
@@ -986,22 +985,16 @@ public:
    */
   static PRBool IsReallyFixedPos(nsIFrame* aFrame);
 
   /**
    * Indicates if the nsIFrame::GetUsedXXX assertions in nsFrame.cpp should
    * disabled.
    */
   static PRBool sDisableGetUsedXAssertions;
-
-  /**
-   * Returns the text fragment, which aFrame should use for printing.
-   * @param aFrame The nsIFrame object, which uses text fragment data.
-   */
-  static nsTextFragment* GetTextFragmentForPrinting(const nsIFrame* aFrame);
 };
 
 class nsAutoDisableGetUsedXAssertions
 {
 public:
   nsAutoDisableGetUsedXAssertions()
     : mOldValue(nsLayoutUtils::sDisableGetUsedXAssertions)
   {
diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1198,17 +1198,17 @@ nsPresContext::GetDefaultFont(PRUint8 aF
       break;
   }
   return font;
 }
 
 void
 nsPresContext::SetFullZoom(float aZoom)
 {
-  if (!mShell || mFullZoom == aZoom || !IsDynamic()) {
+  if (!mShell || mFullZoom == aZoom) {
     return;
   }
   // Re-fetch the view manager's window dimensions in case there's a deferred
   // resize which hasn't affected our mVisibleArea yet
   nscoord oldWidthAppUnits, oldHeightAppUnits;
   mShell->GetViewManager()->GetWindowDimensions(&oldWidthAppUnits, &oldHeightAppUnits);
   float oldWidthDevPixels = oldWidthAppUnits / float(mCurAppUnitsPerDevPixel);
   float oldHeightDevPixels = oldHeightAppUnits / float(mCurAppUnitsPerDevPixel);
diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -761,129 +761,16 @@ FrameArena::FreeFrame(size_t aSize, void
 }
 
 struct nsCallbackEventRequest
 {
   nsIReflowCallback* callback;
   nsCallbackEventRequest* next;
 };
 
-
-class nsDocumentObserverForNonDynamicPresContext : public nsStubDocumentObserver
-{
-public:
-  nsDocumentObserverForNonDynamicPresContext(nsIDocumentObserver* aBaseObserver)
-  : mBaseObserver(aBaseObserver)
-  {
-    NS_ASSERTION(aBaseObserver, "Null document observer!");
-  }
-
-  NS_DECL_ISUPPORTS
-
-  virtual void BeginUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType)
-  {
-    mBaseObserver->BeginUpdate(aDocument, aUpdateType);
-  }
-  virtual void EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType)
-  {
-    mBaseObserver->EndUpdate(aDocument, aUpdateType);
-  }
-  virtual void BeginLoad(nsIDocument* aDocument)
-  {
-    mBaseObserver->BeginLoad(aDocument);
-  }
-  virtual void EndLoad(nsIDocument* aDocument)
-  {
-    mBaseObserver->EndLoad(aDocument);
-  }
-  virtual void ContentStatesChanged(nsIDocument* aDocument,
-                                    nsIContent* aContent1,
-                                    nsIContent* aContent2,
-                                    PRInt32 aStateMask)
-  {
-    if ((!aContent1 || IsInRootScrollbar(aContent1)) &&
-        (!aContent2 || IsInRootScrollbar(aContent2))) {
-      mBaseObserver->ContentStatesChanged(aDocument, aContent1, aContent2,
-                                          aStateMask);
-    }
-  }
-
-  // nsIMutationObserver
-  virtual void CharacterDataChanged(nsIDocument* aDocument,
-                                    nsIContent* aContent,
-                                    CharacterDataChangeInfo* aInfo)
-  {
-    if (IsInRootScrollbar(aContent)) {
-      mBaseObserver->CharacterDataChanged(aDocument, aContent, aInfo);
-    }
-  }
-  virtual void AttributeChanged(nsIDocument* aDocument,
-                                nsIContent* aContent,
-                                PRInt32 aNameSpaceID,
-                                nsIAtom* aAttribute,
-                                PRInt32 aModType,
-                                PRUint32 aStateMask)
-  {
-    if (IsInRootScrollbar(aContent)) {
-      mBaseObserver->AttributeChanged(aDocument, aContent, aNameSpaceID,
-                                      aAttribute, aModType, aStateMask);
-    }
-  }
-  virtual void ContentAppended(nsIDocument* aDocument,
-                               nsIContent* aContainer,
-                               PRInt32 aNewIndexInContainer)
-  {
-    if (IsInRootScrollbar(aContainer)) {
-      mBaseObserver->ContentAppended(aDocument, aContainer,
-                                     aNewIndexInContainer);
-    }
-  }
-  virtual void ContentInserted(nsIDocument* aDocument,
-                               nsIContent* aContainer,
-                               nsIContent* aChild,
-                               PRInt32 aIndexInContainer)
-  {
-    if (IsInRootScrollbar(aContainer)) {
-      mBaseObserver->ContentInserted(aDocument, aContainer, aChild,
-                                     aIndexInContainer);
-    }
-  }
-  virtual void ContentRemoved(nsIDocument* aDocument,
-                              nsIContent* aContainer,
-                              nsIContent* aChild,
-                              PRInt32 aIndexInContainer)
-  {
-    if (IsInRootScrollbar(aContainer)) {
-      mBaseObserver->ContentRemoved(aDocument, aContainer, aChild, 
-                                    aIndexInContainer);
-    }
-  }
-
-  PRBool IsInRootScrollbar(nsIContent* aContent) {
-    if(aContent && aContent->IsInDoc()) {
-       nsIContent* root = aContent->GetCurrentDoc()->GetRootContent();
-       while (aContent && aContent->IsInNativeAnonymousSubtree()) {
-         nsIContent* parent = aContent->GetParent();
-         if (parent == root && aContent->IsNodeOfType(nsINode::eXUL)) {
-           nsIAtom* tag = aContent->Tag();
-           return tag == nsGkAtoms::scrollbar || tag == nsGkAtoms::scrollcorner;
-         }
-         aContent = parent;
-       }
-    }
-    return PR_FALSE;
-  }
-protected:
-  nsCOMPtr<nsIDocumentObserver> mBaseObserver;
-};
-
-NS_IMPL_ISUPPORTS2(nsDocumentObserverForNonDynamicPresContext,
-                   nsIDocumentObserver,
-                   nsIMutationObserver)
-
 // ----------------------------------------------------------------------------
 class nsPresShellEventCB;
 
 class PresShell : public nsIPresShell, public nsIViewObserver,
                   public nsStubDocumentObserver,
                   public nsISelectionController, public nsIObserver,
                   public nsSupportsWeakReference
 {
@@ -1306,19 +1193,16 @@ protected:
   MOZ_TIMER_DECLARE(mFrameCreationWatch)  // Used for measuring time spent in frame creation 
 
 #ifdef MOZ_REFLOW_PERF
   ReflowCountMgr * mReflowCountMgr;
 #endif
 
   static PRBool sDisableNonTestMouseEvents;
 
-
-  nsCOMPtr<nsIDocumentObserver> mDocumentObserverForNonDynamicContext;
-
 private:
 
   PRBool InZombieDocument(nsIContent *aContent);
   nsresult RetargetEventToParent(nsGUIEvent* aEvent,
                                  nsEventStatus*  aEventStatus);
 
   //helper funcs for event handling
 protected:
@@ -2379,24 +2263,17 @@ PresShell::RepaintSelection(SelectionTyp
   return mSelection->RepaintSelection(aType);
 }
 
 // Make shell be a document observer
 NS_IMETHODIMP
 PresShell::BeginObservingDocument()
 {
   if (mDocument && !mIsDestroying) {
-    if (mPresContext->IsDynamic()) {
-      mDocument->AddObserver(this);
-    } else {
-      mDocumentObserverForNonDynamicContext =
-        new nsDocumentObserverForNonDynamicPresContext(this);
-      NS_ENSURE_TRUE(mDocumentObserverForNonDynamicContext, NS_ERROR_OUT_OF_MEMORY);
-      mDocument->AddObserver(mDocumentObserverForNonDynamicContext);
-    }
+    mDocument->AddObserver(this);
     if (mIsDocumentGone) {
       NS_WARNING("Adding a presshell that was disconnected from the document "
                  "as a document observer?  Sounds wrong...");
       mIsDocumentGone = PR_FALSE;
     }
   }
   return NS_OK;
 }
@@ -2404,20 +2281,17 @@ PresShell::BeginObservingDocument()
 // Make shell stop being a document observer
 NS_IMETHODIMP
 PresShell::EndObservingDocument()
 {
   // XXXbz do we need to tell the frame constructor that the document
   // is gone, perhaps?  Except for printing it's NOT gone, sometimes.
   mIsDocumentGone = PR_TRUE;
   if (mDocument) {
-    mDocument->RemoveObserver(mDocumentObserverForNonDynamicContext ?
-                              mDocumentObserverForNonDynamicContext.get() :
-                              this);
-    mDocumentObserverForNonDynamicContext = nsnull;
+    mDocument->RemoveObserver(this);
   }
   return NS_OK;
 }
 
 #ifdef DEBUG_kipp
 char* nsPresShell_ReflowStackPointerTop;
 #endif
 
@@ -3478,20 +3352,16 @@ PresShell::RecreateFramesFor(nsIContent*
 {
   NS_ENSURE_TRUE(mPresContext, NS_ERROR_FAILURE);
   if (!mDidInitialReflow) {
     // Nothing to do here.  In fact, if we proceed and aContent is the
     // root we will crash.
     return NS_OK;
   }
 
-  if (!mPresContext->IsDynamic()) {
-    return NS_OK;
-  }
-
   // Don't call RecreateFramesForContent since that is not exported and we want
   // to keep the number of entrypoints down.
 
   NS_ASSERTION(mViewManager, "Should have view manager");
   nsIViewManager::UpdateViewBatch batch(mViewManager);
 
   // Have to make sure that the content notifications are flushed before we
   // start messing with the frame model; otherwise we can get content doubling.
@@ -4895,19 +4765,16 @@ PresShell::ContentRemoved(nsIDocument *a
                                     aIndexInContainer, &didReconstruct);
 
   VERIFY_STYLE_TREE;
 }
 
 nsresult
 PresShell::ReconstructFrames(void)
 {
-  if (!mPresContext || !mPresContext->IsDynamic()) {
-    return NS_OK;
-  }
   nsAutoScriptBlocker scriptBlocker;
   mFrameConstructor->BeginUpdate();
   nsresult rv = mFrameConstructor->ReconstructDocElementHierarchy();
   VERIFY_STYLE_TREE;
   mFrameConstructor->EndUpdate();
 
   return rv;
 }
diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -54,20 +54,16 @@
 #include "nsLineBox.h"
 #include "gfxFont.h"
 #include "gfxSkipChars.h"
 #include "gfxContext.h"
 
 class nsTextPaintStyle;
 class PropertyProvider;
 
-// This bit is set while the frame is registered as a blinking frame or if
-// frame is within a non-dynamic PresContext.
-#define TEXT_BLINK_ON_OR_PRINTING  0x20000000
-
 // This state bit is set on frames that have some non-collapsed characters after
 // reflow
 #define TEXT_HAS_NONCOLLAPSED_CHARACTERS 0x80000000
 
 class nsTextFrame : public nsFrame {
 public:
   friend class nsContinuingTextFrame;
 
@@ -352,27 +348,19 @@ public:
   struct TrimmedOffsets {
     PRInt32 mStart;
     PRInt32 mLength;
     PRInt32 GetEnd() { return mStart + mLength; }
   };
   TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag,
                                    PRBool aTrimAfter);
 
-  const nsTextFragment* GetFragment() const
-  {
-    return !(GetStateBits() & TEXT_BLINK_ON_OR_PRINTING) ?
-      mContent->GetText() : GetFragmentInternal();
-  }
-
 protected:
   virtual ~nsTextFrame();
 
-  const nsTextFragment* GetFragmentInternal() const;
-
   nsIFrame*   mNextContinuation;
   // The key invariant here is that mContentOffset never decreases along
   // a next-continuation chain. And of course mContentOffset is always <= the
   // the text node's content length, and the mContentOffset for the first frame
   // is always 0. Furthermore the text mapped by a frame is determined by
   // GetContentOffset() and GetContentLength()/GetContentEnd(), which get
   // the length from the difference between this frame's offset and the next
   // frame's offset, or the text length if there is no next frame. This means
diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -158,19 +158,18 @@
 
 // Cache bits for IsEmpty().
 // Set this bit if the textframe is known to be only collapsible whitespace.
 #define TEXT_IS_ONLY_WHITESPACE    0x08000000
 // Set this bit if the textframe is known to be not only collapsible whitespace.
 #define TEXT_ISNOT_ONLY_WHITESPACE 0x10000000
 
 #define TEXT_WHITESPACE_FLAGS      0x18000000
-
-// nsTextFrame.h has
-// #define TEXT_BLINK_ON_OR_PRINTING  0x20000000
+// This bit is set while the frame is registered as a blinking frame.
+#define TEXT_BLINK_ON              0x20000000
 
 // Set when this text frame is mentioned in the userdata for a textrun
 #define TEXT_IN_TEXTRUN_USER_DATA  0x40000000
 
 // nsTextFrame.h has
 // #define TEXT_HAS_NONCOLLAPSED_CHARACTERS 0x80000000
 
 /*
@@ -477,33 +476,33 @@ nsTextFrameTextRunCache::Init() {
 void
 nsTextFrameTextRunCache::Shutdown() {
     delete gTextRuns;
     gTextRuns = nsnull;
 }
 
 PRInt32 nsTextFrame::GetContentEnd() const {
   nsTextFrame* next = static_cast<nsTextFrame*>(GetNextContinuation());
-  return next ? next->GetContentOffset() : GetFragment()->GetLength();
+  return next ? next->GetContentOffset() : mContent->GetText()->GetLength();
 }
 
 PRInt32 nsTextFrame::GetInFlowContentLength() {
 #ifdef IBMBIDI
   nsTextFrame* nextBidi = nsnull;
   PRInt32      start = -1, end;
 
   if (mState & NS_FRAME_IS_BIDI) {
     nextBidi = static_cast<nsTextFrame*>(GetLastInFlow()->GetNextContinuation());
     if (nextBidi) {
       nextBidi->GetOffsets(start, end);
       return start - mContentOffset;
     }
   }
 #endif //IBMBIDI
-  return GetFragment()->GetLength() - mContentOffset;
+  return mContent->TextLength() - mContentOffset;
 }
 
 // Smarter versions of XP_IS_SPACE.
 // Unicode is really annoying; sometimes a space character isn't whitespace ---
 // when it combines with another character
 // So we have several versions of IsSpace for use in different contexts.
 
 static PRBool IsSpaceCombiningSequenceTail(const nsTextFragment* aFrag, PRUint32 aPos)
@@ -722,17 +721,17 @@ public:
     // ancestor of the elements containing the characters is the one whose
     // CSS 'white-space' property governs. So this records the nearest common
     // ancestor of mStartFrame and the previous text frame, or null if there
     // was no previous text frame on this line.
     nsIFrame*    mAncestorControllingInitialBreak;
     
     PRInt32 GetContentEnd() {
       return mEndFrame ? mEndFrame->GetContentOffset()
-          : mStartFrame->GetFragment()->GetLength();
+          : mStartFrame->GetContent()->GetText()->GetLength();
     }
   };
 
   class BreakSink : public nsILineBreakSink {
   public:
     BreakSink(gfxTextRun* aTextRun, gfxContext* aContext, PRUint32 aOffsetIntoTextRun,
               PRBool aExistingTextRun) :
                 mTextRun(aTextRun), mContext(aContext),
@@ -928,17 +927,17 @@ BuildTextRunsScanner::FindBoundaries(nsI
     aState->mLastTextFrame = textFrame;
   }
   
   if (aFrame == aState->mStopAtFrame)
     return FB_STOPPED_AT_STOP_FRAME;
 
   if (textFrame) {
     if (!aState->mSeenSpaceForLineBreakingOnThisLine) {
-      const nsTextFragment* frag = textFrame->GetFragment();
+      const nsTextFragment* frag = textFrame->GetContent()->GetText();
       PRUint32 start = textFrame->GetContentOffset();
       const void* text = frag->Is2b()
           ? static_cast<const void*>(frag->Get2b() + start)
           : static_cast<const void*>(frag->Get1b() + start);
       if (TextContainsLineBreakerWhiteSpace(text, textFrame->GetContentLength(),
                                             frag->Is2b())) {
         aState->mSeenSpaceForLineBreakingOnThisLine = PR_TRUE;
         if (aState->mSeenTextRunBoundaryOnLaterLine)
@@ -1253,17 +1252,17 @@ void BuildTextRunsScanner::FlushLineBrea
   }
   mTextRunsToDelete.Clear();
 }
 
 void BuildTextRunsScanner::AccumulateRunInfo(nsTextFrame* aFrame)
 {
   NS_ASSERTION(mMaxTextLength <= mMaxTextLength + aFrame->GetContentLength(), "integer overflow");
   mMaxTextLength += aFrame->GetContentLength();
-  mDoubleByteText |= aFrame->GetFragment()->Is2b();
+  mDoubleByteText |= aFrame->GetContent()->GetText()->Is2b();
   mLastFrame = aFrame;
   mCommonAncestorWithLastFrame = aFrame->GetParent();
 
   MappedFlow* mappedFlow = &mMappedFlows[mMappedFlows.Length() - 1];
   NS_ASSERTION(mappedFlow->mStartFrame == aFrame ||
                mappedFlow->GetContentEnd() == aFrame->GetContentOffset(),
                "Overlapping or discontiguous frames => BAD");
   mappedFlow->mEndFrame = static_cast<nsTextFrame*>(aFrame->GetNextContinuation());
@@ -1286,17 +1285,17 @@ static nscoord StyleToCoord(const nsStyl
   }
 }
 
 static PRBool
 HasTerminalNewline(const nsTextFrame* aFrame)
 {
   if (aFrame->GetContentLength() == 0)
     return PR_FALSE;
-  const nsTextFragment* frag = aFrame->GetFragment();
+  const nsTextFragment* frag = aFrame->GetContent()->GetText();
   return frag->CharAt(aFrame->GetContentEnd() - 1) == '\n';
 }
 
 PRBool
 BuildTextRunsScanner::ContinueTextRunAcrossFrames(nsTextFrame* aFrame1, nsTextFrame* aFrame2)
 {
   if (mBidiEnabled &&
       NS_GET_EMBEDDING_LEVEL(aFrame1) != NS_GET_EMBEDDING_LEVEL(aFrame2))
@@ -1613,17 +1612,17 @@ BuildTextRunsScanner::BuildTextRunForFra
     }
     fontStyle = f->GetStyleFont();
     if (NS_STYLE_FONT_VARIANT_SMALL_CAPS == fontStyle->mFont.variant) {
       anySmallcapsStyle = PR_TRUE;
     }
 
     // Figure out what content is included in this flow.
     nsIContent* content = f->GetContent();
-    const nsTextFragment* frag = f->GetFragment();
+    const nsTextFragment* frag = content->GetText();
     PRInt32 contentStart = mappedFlow->mStartFrame->GetContentOffset();
     PRInt32 contentEnd = mappedFlow->GetContentEnd();
     PRInt32 contentLength = contentEnd - contentStart;
 
     TextRunMappedFlow* newFlow = &userData->mMappedFlows[i];
     newFlow->mStartFrame = mappedFlow->mStartFrame;
     newFlow->mDOMOffsetToBeforeTransformOffset = builder.GetCharCount() -
       mappedFlow->mStartFrame->GetContentOffset();
@@ -1859,17 +1858,17 @@ HasCompressedLeadingWhitespace(nsTextFra
                                PRInt32 aContentEndOffset,
                                const gfxSkipCharsIterator& aIterator)
 {
   if (!aIterator.IsOriginalCharSkipped())
     return PR_FALSE;
 
   gfxSkipCharsIterator iter = aIterator;
   PRInt32 frameContentOffset = aFrame->GetContentOffset();
-  const nsTextFragment* frag = aFrame->GetFragment();
+  const nsTextFragment* frag = aFrame->GetContent()->GetText();
   while (frameContentOffset < aContentEndOffset && iter.IsOriginalCharSkipped()) {
     if (IsTrimmableSpace(frag, frameContentOffset, aStyleText))
       return PR_TRUE;
     ++frameContentOffset;
     iter.AdvanceOriginal(1);
   }
   return PR_FALSE;
 }
@@ -2231,17 +2230,17 @@ public:
   /**
    * Use this constructor after the frame has been reflowed and we don't
    * have other data around. Gets everything from the frame. EnsureTextRun
    * *must* be called before this!!!
    */
   PropertyProvider(nsTextFrame* aFrame, const gfxSkipCharsIterator& aStart)
     : mTextRun(aFrame->GetTextRun()), mFontGroup(nsnull),
       mTextStyle(aFrame->GetStyleText()),
-      mFrag(aFrame->GetFragment()),
+      mFrag(aFrame->GetContent()->GetText()),
       mLineContainer(nsnull),
       mFrame(aFrame), mStart(aStart), mTempIterator(aStart),
       mTabWidths(nsnull),
       mLength(aFrame->GetContentLength()),
       mWordSpacing(mTextStyle->mWordSpacing),
       mLetterSpacing(StyleToCoord(mTextStyle->mLetterSpacing)),
       mJustificationSpacing(0),
       mHyphenWidth(-1),
@@ -3404,21 +3403,16 @@ NS_IMETHODIMP nsTextFrame::GetAccessible
 NS_IMETHODIMP
 nsTextFrame::Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow)
 {
   NS_ASSERTION(!aPrevInFlow, "Can't be a continuation!");
   NS_PRECONDITION(aContent->IsNodeOfType(nsINode::eTEXT),
                   "Bogus content!");
-
-  if (!PresContext()->IsDynamic()) {
-    AddStateBits(TEXT_BLINK_ON_OR_PRINTING);
-  }
-
   // We're not a continuing frame.
   // mContentOffset = 0; not necessary since we get zeroed out at init
   return nsFrame::Init(aContent, aParent, aPrevInFlow);
 }
 
 void
 nsTextFrame::Destroy()
 {
@@ -3488,34 +3482,29 @@ protected:
 };
 
 NS_IMETHODIMP
 nsContinuingTextFrame::Init(nsIContent* aContent,
                             nsIFrame*   aParent,
                             nsIFrame*   aPrevInFlow)
 {
   NS_ASSERTION(aPrevInFlow, "Must be a continuation!");
-
-  if (!PresContext()->IsDynamic()) {
-    AddStateBits(TEXT_BLINK_ON_OR_PRINTING);
-  }
-
   // NOTE: bypassing nsTextFrame::Init!!!
   nsresult rv = nsFrame::Init(aContent, aParent, aPrevInFlow);
 
 #ifdef IBMBIDI
   nsTextFrame* nextContinuation =
     static_cast<nsTextFrame*>(aPrevInFlow->GetNextContinuation());
 #endif // IBMBIDI
   // Hook the frame into the flow
   SetPrevInFlow(aPrevInFlow);
   aPrevInFlow->SetNextInFlow(this);
   nsTextFrame* prev = static_cast<nsTextFrame*>(aPrevInFlow);
   mContentOffset = prev->GetContentOffset() + prev->GetContentLengthHint();
-  NS_ASSERTION(mContentOffset < PRInt32(GetFragment()->GetLength()),
+  NS_ASSERTION(mContentOffset < PRInt32(aContent->GetText()->GetLength()),
                "Creating ContinuingTextFrame, but there is no more content");
   if (prev->GetStyleContext() != GetStyleContext()) {
     // We're taking part of prev's text, and its style may be different
     // so clear its textrun which may no longer be valid (and don't set ours)
     prev->ClearTextRun();
   } else {
     mTextRun = prev->GetTextRun();
   }
@@ -3685,17 +3674,17 @@ NS_NewTextFrame(nsIPresShell* aPresShell
 nsIFrame*
 NS_NewContinuingTextFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsContinuingTextFrame(aContext);
 }
 
 nsTextFrame::~nsTextFrame()
 {
-  if (0 != (mState & TEXT_BLINK_ON_OR_PRINTING) && PresContext()->IsDynamic())
+  if (0 != (mState & TEXT_BLINK_ON))
   {
     nsBlinkTimer::RemoveBlinkFrame(this);
   }
 }
 
 NS_IMETHODIMP
 nsTextFrame::GetCursor(const nsPoint& aPoint,
                        nsIFrame::Cursor& aCursor)
@@ -3869,17 +3858,17 @@ nsTextFrame::BuildDisplayList(nsDisplayL
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists)
 {
   if (!IsVisibleForPainting(aBuilder))
     return NS_OK;
   
   DO_GLOBAL_REFLOW_COUNT_DSP("nsTextFrame");
 
-  if ((0 != (mState & TEXT_BLINK_ON_OR_PRINTING)) && nsBlinkTimer::GetBlinkIsOff() &&
+  if ((0 != (mState & TEXT_BLINK_ON)) && nsBlinkTimer::GetBlinkIsOff() &&
       PresContext()->IsDynamic())
     return NS_OK;
     
   return aLists.Content()->AppendNewToTop(new (aBuilder) nsDisplayText(this));
 }
 
 static nsIFrame*
 GetGeneratedContentOwner(nsIFrame* aFrame, PRBool* aIsBefore)
@@ -5052,17 +5041,17 @@ PRBool
 nsTextFrame::PeekOffsetNoAmount(PRBool aForward, PRInt32* aOffset)
 {
   NS_ASSERTION(aOffset && *aOffset <= GetContentLength(), "aOffset out of range");
 
   gfxSkipCharsIterator iter = EnsureTextRun();
   if (!mTextRun)
     return PR_FALSE;
 
-  TrimmedOffsets trimmed = GetTrimmedOffsets(GetFragment(), PR_TRUE);
+  TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), PR_TRUE);
   // Check whether there are nonskipped characters in the trimmmed range
   return iter.ConvertOriginalToSkipped(trimmed.GetEnd()) >
          iter.ConvertOriginalToSkipped(trimmed.mStart);
 }
 
 /**
  * This class iterates through the clusters before or after the given
  * aPosition (which is a content offset). You can test each cluster
@@ -5119,17 +5108,17 @@ nsTextFrame::PeekOffsetCharacter(PRBool 
   IsSelectable(&selectable, &selectStyle);
   if (selectStyle == NS_STYLE_USER_SELECT_ALL)
     return PR_FALSE;
 
   gfxSkipCharsIterator iter = EnsureTextRun();
   if (!mTextRun)
     return PR_FALSE;
 
-  TrimmedOffsets trimmed = GetTrimmedOffsets(GetFragment(), PR_FALSE);
+  TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), PR_FALSE);
 
   // A negative offset means "end of frame".
   PRInt32 startOffset = GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset);
 
   if (!aForward) {
     PRInt32 i;
     for (i = PR_MIN(trimmed.GetEnd(), startOffset) - 1;
          i >= trimmed.mStart; --i) {
@@ -5234,17 +5223,17 @@ ClusterIterator::ClusterIterator(nsTextF
   if (!aTextFrame->GetTextRun()) {
     mDirection = 0; // signal failure
     return;
   }
   mIterator.SetOriginalOffset(aPosition);
 
   mCategories = do_GetService(NS_UNICHARCATEGORY_CONTRACTID);
   
-  mFrag = aTextFrame->GetFragment();
+  mFrag = aTextFrame->GetContent()->GetText();
   mTrimmed = aTextFrame->GetTrimmedOffsets(mFrag, PR_TRUE);
 
   PRInt32 textOffset = aTextFrame->GetContentOffset();
   PRInt32 textLen = aTextFrame->GetContentLength();
   if (!mWordBreaks.AppendElements(textLen + 1)) {
     mDirection = 0; // signal failure
     return;
   }
@@ -5475,17 +5464,17 @@ nsTextFrame::AddInlineMinWidthForFlow(ns
   gfxSkipCharsIterator iter =
     EnsureTextRun(ctx, aData->lineContainer, aData->line, &flowEndInTextRun);
   if (!mTextRun)
     return;
 
   // Pass null for the line container. This will disable tab spacing, but that's
   // OK since we can't really handle tabs for intrinsic sizing anyway.
   const nsStyleText* textStyle = GetStyleText();
-  const nsTextFragment* frag = GetFragment();
+  const nsTextFragment* frag = mContent->GetText();
   PropertyProvider provider(mTextRun, textStyle, frag, this,
                             iter, PR_INT32_MAX, nsnull, 0);
 
   PRBool collapseWhitespace = !textStyle->WhiteSpaceIsSignificant();
   PRBool preformatNewlines = textStyle->NewlineIsSignificant();
   PRBool preformatTabs = textStyle->WhiteSpaceIsSignificant();
   gfxFloat tabWidth = -1;
   PRUint32 start =
@@ -5603,17 +5592,17 @@ nsTextFrame::AddInlinePrefWidthForFlow(n
     EnsureTextRun(ctx, aData->lineContainer, aData->line, &flowEndInTextRun);
   if (!mTextRun)
     return;
 
   // Pass null for the line container. This will disable tab spacing, but that's
   // OK since we can't really handle tabs for intrinsic sizing anyway.
   
   const nsStyleText* textStyle = GetStyleText();
-  const nsTextFragment* frag = GetFragment();
+  const nsTextFragment* frag = mContent->GetText();
   PropertyProvider provider(mTextRun, textStyle, frag, this,
                             iter, PR_INT32_MAX, nsnull, 0);
 
   PRBool collapseWhitespace = !textStyle->WhiteSpaceIsSignificant();
   PRBool preformatNewlines = textStyle->NewlineIsSignificant();
   PRBool preformatTabs = textStyle->WhiteSpaceIsSignificant();
   gfxFloat tabWidth = -1;
   PRUint32 start =
@@ -5841,18 +5830,18 @@ nsTextFrame::Reflow(nsPresContext*      
          aReflowState.availableWidth, aReflowState.availableHeight);
 #endif
 
   /////////////////////////////////////////////////////////////////////
   // Set up flags and clear out state
   /////////////////////////////////////////////////////////////////////
 
   // Clear out the reflow state flags in mState (without destroying
-  // the TEXT_BLINK_ON_OR_PRINTING bit). We also clear the whitespace flags
-  // because this can change whether the frame maps whitespace-only text or not.
+  // the TEXT_BLINK_ON bit). We also clear the whitespace flags because this
+  // can change whether the frame maps whitespace-only text or not.
   RemoveStateBits(TEXT_REFLOW_FLAGS | TEXT_WHITESPACE_FLAGS);
 
   // Temporarily map all possible content while we construct our new textrun.
   // so that when doing reflow our styles prevail over any part of the
   // textrun we look at. Note that next-in-flows may be mapping the same
   // content; gfxTextRun construction logic will ensure that we take priority.
   PRInt32 maxContentLength = GetInFlowContentLength();
 
@@ -5864,39 +5853,39 @@ nsTextFrame::Reflow(nsPresContext*      
     ClearMetrics(aMetrics);
     aStatus = NS_FRAME_COMPLETE;
     return NS_OK;
   }
 
   nsLineLayout& lineLayout = *aReflowState.mLineLayout;
 
   if (aReflowState.mFlags.mBlinks) {
-    if (0 == (mState & TEXT_BLINK_ON_OR_PRINTING) && PresContext()->IsDynamic()) {
-      mState |= TEXT_BLINK_ON_OR_PRINTING;
+    if (0 == (mState & TEXT_BLINK_ON)) {
+      mState |= TEXT_BLINK_ON;
       nsBlinkTimer::AddBlinkFrame(aPresContext, this);
     }
   }
   else {
-    if (0 != (mState & TEXT_BLINK_ON_OR_PRINTING) && PresContext()->IsDynamic()) {
-      mState &= ~TEXT_BLINK_ON_OR_PRINTING;
+    if (0 != (mState & TEXT_BLINK_ON)) {
+      mState &= ~TEXT_BLINK_ON;
       nsBlinkTimer::RemoveBlinkFrame(this);
     }
   }
 
   const nsStyleText* textStyle = GetStyleText();
 
   PRBool atStartOfLine = lineLayout.LineIsEmpty();
   if (atStartOfLine) {
     AddStateBits(TEXT_START_OF_LINE);
   }
 
   PRUint32 flowEndInTextRun;
   nsIFrame* lineContainer = lineLayout.GetLineContainerFrame();
   gfxContext* ctx = aReflowState.rendContext->ThebesContext();
-  const nsTextFragment* frag = GetFragment();
+  const nsTextFragment* frag = mContent->GetText();
 
   // DOM offsets of the text range we need to measure, after trimming
   // whitespace, restricting to first-letter, and restricting preformatted text
   // to nearest newline
   PRInt32 length = maxContentLength;
   PRInt32 offset = GetContentOffset();
 
   // Restrict preformatted text to the nearest newline
@@ -6296,17 +6285,17 @@ nsTextFrame::TrimTrailingWhiteSpace(nsIR
     return result;
 
   gfxContext* ctx = aRC->ThebesContext();
   gfxSkipCharsIterator start = EnsureTextRun(ctx);
   NS_ENSURE_TRUE(mTextRun, result);
 
   PRUint32 trimmedStart = start.GetSkippedOffset();
 
-  const nsTextFragment* frag = GetFragment();
+  const nsTextFragment* frag = mContent->GetText();
   TrimmedOffsets trimmed = GetTrimmedOffsets(frag, PR_TRUE);
   gfxSkipCharsIterator trimmedEndIter = start;
   const nsStyleText* textStyle = GetStyleText();
   gfxFloat delta = 0;
   PRUint32 trimmedEnd = trimmedEndIter.ConvertOriginalToSkipped(trimmed.GetEnd());
   
   if (GetStateBits() & TEXT_TRIMMED_TRAILING_WHITESPACE) {
     // We pre-trimmed this frame, so the last character is justifiable
@@ -6433,17 +6422,17 @@ nsresult nsTextFrame::GetRenderedText(ns
                                       gfxSkipChars* aSkipChars,
                                       gfxSkipCharsIterator* aSkipIter,
                                       PRUint32 aSkippedStartOffset,
                                       PRUint32 aSkippedMaxLength)
 {
   // The handling of aSkippedStartOffset and aSkippedMaxLength could be more efficient...
   gfxSkipCharsBuilder skipCharsBuilder;
   nsTextFrame* textFrame;
-  const nsTextFragment* textFrag = GetFragment();
+  const nsTextFragment* textFrag = mContent->GetText();
   PRUint32 keptCharsLength = 0;
   PRUint32 validCharsLength = 0;
 
   // Build skipChars and copy text, for each text frame in this continuation block
   for (textFrame = this; textFrame;
        textFrame = static_cast<nsTextFrame*>(textFrame->GetNextContinuation())) {
     // For each text frame continuation in this block ...
 
@@ -6499,17 +6488,17 @@ nsresult nsTextFrame::GetRenderedText(ns
 }
 
 #ifdef DEBUG
 // Translate the mapped content into a string that's printable
 void
 nsTextFrame::ToCString(nsCString& aBuf, PRInt32* aTotalContentLength) const
 {
   // Get the frames text content
-  const nsTextFragment* frag = GetFragment();
+  const nsTextFragment* frag = mContent->GetText();
   if (!frag) {
     return;
   }
 
   // Compute the total length of the text content.
   *aTotalContentLength = frag->GetLength();
 
   PRInt32 contentLength = GetContentLength();
@@ -6559,17 +6548,17 @@ nsTextFrame::IsEmpty()
   if (mState & TEXT_ISNOT_ONLY_WHITESPACE) {
     return PR_FALSE;
   }
 
   if (mState & TEXT_IS_ONLY_WHITESPACE) {
     return PR_TRUE;
   }
   
-  PRBool isEmpty = IsAllWhitespace(GetFragment(),
+  PRBool isEmpty = IsAllWhitespace(mContent->GetText(),
           textStyle->mWhiteSpace != NS_STYLE_WHITESPACE_PRE_LINE);
   mState |= (isEmpty ? TEXT_IS_ONLY_WHITESPACE : TEXT_ISNOT_ONLY_WHITESPACE);
   return isEmpty;
 }
 
 #ifdef DEBUG
 NS_IMETHODIMP
 nsTextFrame::GetFrameName(nsAString& aResult) const
@@ -6696,15 +6685,8 @@ nsTextFrame::HasTerminalNewline() const
   return ::HasTerminalNewline(this);
 }
 
 PRBool
 nsTextFrame::IsAtEndOfLine() const
 {
   return (GetStateBits() & TEXT_END_OF_LINE) != 0;
 }
-
-const nsTextFragment*
-nsTextFrame::GetFragmentInternal() const
-{
-  return PresContext()->IsDynamic() ? mContent->GetText() :
-    nsLayoutUtils::GetTextFragmentForPrinting(this);
-}
diff --git a/layout/printing/nsPrintEngine.cpp b/layout/printing/nsPrintEngine.cpp
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -1153,20 +1153,20 @@ nsPrintEngine::BuildDocTree(nsIDocShellT
       nsCOMPtr<nsIContentViewer>  viewer;
       childAsShell->GetContentViewer(getter_AddRefs(viewer));
       if (viewer) {
         nsCOMPtr<nsIContentViewerFile> viewerFile(do_QueryInterface(viewer));
         if (viewerFile) {
           nsCOMPtr<nsIDocShell> childDocShell(do_QueryInterface(child));
           nsCOMPtr<nsIDocShellTreeNode> childNode(do_QueryInterface(child));
           nsPrintObject * po = new nsPrintObject();
+          po->mParent = aPO;
           nsresult rv = po->Init(childDocShell);
           if (NS_FAILED(rv))
             NS_NOTREACHED("Init failed?");
-          po->mParent = aPO;
           aPO->mKids.AppendElement(po);
           aDocList->AppendElement(po);
           BuildDocTree(childNode, aDocList, po);
         }
       }
     }
   }
 }
@@ -1218,17 +1218,27 @@ nsPrintEngine::MapContentToWebShells(nsP
                                      nsPrintObject* aPO)
 {
   NS_ASSERTION(aRootPO, "Pointer is null!");
   NS_ASSERTION(aPO, "Pointer is null!");
 
   // Recursively walk the content from the root item
   // XXX Would be faster to enumerate the subdocuments, although right now
   //     nsIDocument doesn't expose quite what would be needed.
-  nsIContent *rootContent = aPO->mDocument->GetRootContent();
+  
+  nsCOMPtr<nsIContentViewer> viewer;
+  aPO->mDocShell->GetContentViewer(getter_AddRefs(viewer));
+  if (!viewer) return;
+
+  nsCOMPtr<nsIDOMDocument> domDoc;
+  viewer->GetDOMDocument(getter_AddRefs(domDoc));
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
+  if (!doc) return;
+
+  nsIContent *rootContent = doc->GetRootContent();
   if (rootContent) {
     MapContentForPO(aPO, rootContent);
   } else {
     NS_WARNING("Null root content on (sub)document.");
   }
 
   // Continue recursively walking the chilren of this PO
   for (PRUint32 i=0;i<aPO->mKids.Length();i++) {
@@ -1302,26 +1312,26 @@ nsPrintEngine::MapContentForPO(nsPrintOb
     nsCOMPtr<nsISupports> container = subDoc->GetContainer();
     nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
 
     if (docShell) {
       nsPrintObject * po = nsnull;
       PRInt32 cnt = aPO->mKids.Length();
       for (PRInt32 i=0;i<cnt;i++) {
         nsPrintObject* kid = aPO->mKids.ElementAt(i);
-        if (kid->mDocument == subDoc) {
+        if (kid->mOriginalDocument == subDoc) {
           po = kid;
           break;
         }
       }
 
       // XXX If a subdocument has no onscreen presentation, there will be no PO
       //     This is even if there should be a print presentation
       if (po) {
-        po->mContent  = aContent;
+        //po->mContent  = aContent;
 
         nsCOMPtr<nsIDOMHTMLFrameElement> frame(do_QueryInterface(aContent));
         // "frame" elements not in a frameset context should be treated
         // as iframes
         if (frame && po->mParent->mFrameType == eFrameSet) {
           po->mFrameType = eFrame;
         } else {
           // Assume something iframe-like, i.e. iframe, object, or embed
@@ -1864,18 +1874,21 @@ nsPrintEngine::ReflowPrintObject(nsPrint
 
   if (aPO->mParent && aPO->mParent->IsPrintable()) {
     if (aPO->mParent->mPresShell) {
       frame = aPO->mParent->mPresShell->FrameManager()->
         GetPrimaryFrameFor(aPO->mContent, -1);
     }
     // Without a frame, this document can't be displayed; therefore, there is no
     // point to reflowing it
-    if (!frame)
+    if (!frame) {
+      static int c = 0;
+      printf("No frame %i\n\n", ++c);
       return NS_OK;
+    }
 
     adjSize = frame->GetContentRect().Size();
     documentIsTopLevel = PR_FALSE;
     // presshell exists because parent is printable
   } else {
     nscoord pageWidth, pageHeight;
     mPrt->mPrintDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight);
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
diff --git a/layout/printing/nsPrintEngine.h b/layout/printing/nsPrintEngine.h
--- a/layout/printing/nsPrintEngine.h
+++ b/layout/printing/nsPrintEngine.h
@@ -192,16 +192,21 @@ public:
 
   static PRBool HasFramesetChild(nsIContent* aContent);
 
   PRBool   CheckBeforeDestroy();
   nsresult Cancelled();
 
   nsIWidget* GetPrintPreviewWindow() {return mPrtPreview->mPrintObject->mWindow;}
 
+  nsIDocument* GetPrintPreviewDocument()
+  {
+    return mPrtPreview ? mPrtPreview->mPrintObject->mDocument : nsnull;
+  }
+
   nsIViewManager* GetPrintPreviewViewManager() {return mPrtPreview->mPrintObject->mViewManager;}
 
   float GetPrintPreviewScale() { return mPrtPreview->mPrintObject->
                                         mPresContext->GetPrintPreviewScale(); }
   
   static nsIPresShell* GetPresShellFor(nsIDocShell* aDocShell);
 
   // These calls also update the DocViewer
diff --git a/layout/printing/nsPrintObject.cpp b/layout/printing/nsPrintObject.cpp
--- a/layout/printing/nsPrintObject.cpp
+++ b/layout/printing/nsPrintObject.cpp
@@ -33,16 +33,19 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsPrintObject.h"
 #include "nsIContentViewer.h"
 #include "nsIDOMDocument.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsPIDOMWindow.h"
+#include "nsGkAtoms.h"
 
 //---------------------------------------------------
 //-- nsPrintObject Class Impl
 //---------------------------------------------------
 nsPrintObject::nsPrintObject() :
   mContent(nsnull), mFrameType(eFrame), mParent(nsnull),
   mHasBeenPrinted(PR_FALSE), mDontPrint(PR_TRUE), mPrintAsIs(PR_FALSE),
   mSharedPresShell(PR_FALSE), mInvisible(PR_FALSE),
@@ -69,22 +72,66 @@ nsPrintObject::Init(nsIDocShell* aDocShe
   mDocShell = aDocShell;
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
   
   nsresult rv;
   nsCOMPtr<nsIContentViewer> viewer;
   rv = mDocShell->GetContentViewer(getter_AddRefs(viewer));
   NS_ENSURE_SUCCESS(rv, rv);
   
-  nsCOMPtr<nsIDOMDocument> doc;
-  viewer->GetDOMDocument(getter_AddRefs(doc));
+  nsCOMPtr<nsIDOMDocument> domDoc;
+  viewer->GetDOMDocument(getter_AddRefs(domDoc));
   NS_ENSURE_SUCCESS(rv, rv);
-  
-  mDocument = do_QueryInterface(doc);
-  NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
+
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
+  NS_ENSURE_STATE(doc);
+  doc->SetCloningForPrinting(PR_TRUE);
+
+  nsCOMPtr<nsIDOMNode> clonedNode;
+  rv = domDoc->CloneNode(PR_TRUE, getter_AddRefs(clonedNode));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIDocument> clonedDoc = do_QueryInterface(clonedNode);
+  NS_ENSURE_STATE(clonedDoc);
+  clonedDoc->SetScriptGlobalObject(doc->GetScriptGlobalObject());
+
+  PRInt32 sheetsCount = doc->GetNumberOfStyleSheets();
+  for (PRInt32 i = 0; i < sheetsCount; ++i) {
+    nsCOMPtr<nsICSSStyleSheet> sheet =
+      do_QueryInterface(doc->GetStyleSheetAt(i));
+    if (sheet) {
+      PRBool applicable = PR_TRUE;
+      sheet->GetApplicable(applicable);
+      if (applicable) {
+        nsCOMPtr<nsICSSStyleSheet> clonedSheet;
+        sheet->Clone(nsnull, nsnull, clonedDoc, nsnull,
+                     getter_AddRefs(clonedSheet));
+        NS_WARN_IF_FALSE(clonedSheet, "Cloning didn't work!");
+        if (clonedSheet) {
+          clonedDoc->AddStyleSheet(clonedSheet);
+        }
+      }
+    }
+  }
+
+  static int c = 0;
+  printf("Did clone a document %i\n\n", ++c);
+
+  mDocument = clonedDoc;
+  mOriginalDocument = doc;
+  doc->SetCloningForPrinting(PR_FALSE);
+  if (mParent) {
+    nsCOMPtr<nsPIDOMWindow> window = doc->GetWindow();
+    if (window) {
+      nsCOMPtr<nsIContent> frame = do_QueryInterface(window->GetFrameElementInternal());
+      if (frame) {
+        mContent = static_cast<nsIContent*>(frame->GetProperty(nsGkAtoms::printNode));
+      }
+    }
+  }
 
   return NS_OK;
 }
 
 //------------------------------------------------------------------
 // Resets PO by destroying the presentation
 void 
 nsPrintObject::DestroyPresentation()
diff --git a/layout/printing/nsPrintObject.h b/layout/printing/nsPrintObject.h
--- a/layout/printing/nsPrintObject.h
+++ b/layout/printing/nsPrintObject.h
@@ -65,23 +65,24 @@ public:
   nsresult Init(nsIDocShell* aDocShell);
 
   PRBool IsPrintable()  { return !mDontPrint; }
   void   DestroyPresentation();
 
   // Data Members
   nsCOMPtr<nsIDocShell>    mDocShell;
   nsCOMPtr<nsIDocument>    mDocument;
+  nsCOMPtr<nsIDocument>    mOriginalDocument;
 
   nsCOMPtr<nsPresContext>  mPresContext;
   nsCOMPtr<nsIPresShell>   mPresShell;
   nsCOMPtr<nsIViewManager> mViewManager;
   nsCOMPtr<nsIWidget>      mWindow;
 
-  nsIContent*      mContent;
+  nsCOMPtr<nsIContent>      mContent;
   PrintObjectType  mFrameType;
   
   nsTArray<nsPrintObject*> mKids;
   nsPrintObject*   mParent;
   PRPackedBool     mHasBeenPrinted;
   PRPackedBool     mDontPrint;
   PRPackedBool     mPrintAsIs;
   PRPackedBool     mSharedPresShell;
diff --git a/layout/svg/base/src/nsSVGGlyphFrame.cpp b/layout/svg/base/src/nsSVGGlyphFrame.cpp
--- a/layout/svg/base/src/nsSVGGlyphFrame.cpp
+++ b/layout/svg/base/src/nsSVGGlyphFrame.cpp
@@ -49,17 +49,16 @@
 #include "nsSVGPathElement.h"
 #include "nsSVGPoint.h"
 #include "nsSVGRect.h"
 #include "nsDOMError.h"
 #include "gfxContext.h"
 #include "gfxMatrix.h"
 #include "gfxPlatform.h"
 #include "gfxTextRunWordCache.h"
-#include "nsTextFrame.h"
 
 struct CharacterPosition {
   gfxPoint pos;
   gfxFloat angle;
   PRBool draw;
 };
   
 /**
@@ -295,20 +294,16 @@ nsSVGGlyphFrame::Init(nsIContent* aConte
   nsISVGTextContentMetrics *metrics = do_QueryFrame(ancestorFrame);
   NS_ASSERTION(metrics,
                "trying to construct an SVGGlyphFrame for an invalid container");
 
   NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
                "trying to construct an SVGGlyphFrame for wrong content element");
 #endif /* DEBUG */
 
-  if (!PresContext()->IsDynamic()) {
-    AddStateBits(NS_STATE_SVG_PRINTING);
-  }
-
   return nsSVGGlyphFrameBase::Init(aContent, aParent, aPrevInFlow);
 }
 
 nsIAtom *
 nsSVGGlyphFrame::GetType() const
 {
   return nsGkAtoms::svgGlyphFrame;
 }
@@ -631,17 +626,17 @@ nsSVGGlyphFrame::GetCanvasTM(nsIDOMSVGMa
 
 //----------------------------------------------------------------------
 // nsSVGGlyphFrame methods:
 
 PRBool
 nsSVGGlyphFrame::GetCharacterData(nsAString & aCharacterData)
 {
   nsAutoString characterData;
-  GetFragment()->AppendTo(characterData);
+  mContent->AppendTextTo(characterData);
 
   if (mWhitespaceHandling & COMPRESS_WHITESPACE) {
     PRBool trimLeadingWhitespace, trimTrailingWhitespace;
     trimLeadingWhitespace = ((mWhitespaceHandling & TRIM_LEADING_WHITESPACE) != 0);
     trimTrailingWhitespace = ((mWhitespaceHandling & TRIM_TRAILING_WHITESPACE) != 0);
     characterData.CompressWhitespace(trimLeadingWhitespace, 
                                      trimTrailingWhitespace);
   } else {
@@ -783,17 +778,17 @@ nsSVGGlyphFrame::GetHighlight(PRUint32 *
     NS_ERROR("nsSVGGlyphFrame::GetHighlight() called by renderer when there is no highlight");
     return NS_ERROR_FAILURE;
   }
 
   nsPresContext *presContext = PresContext();
 
   // The selection ranges are relative to the uncompressed text in
   // the content element. We'll need the text fragment:
-  const nsTextFragment* fragment = GetFragment();
+  const nsTextFragment *fragment = mContent->GetText();
   NS_ASSERTION(fragment, "no text");
   
   // get the selection details 
   SelectionDetails *details = nsnull;
   {
     nsCOMPtr<nsFrameSelection> frameSelection;
     {
       nsCOMPtr<nsISelectionController> controller;
@@ -1101,17 +1096,17 @@ nsSVGGlyphFrame::IsAbsolutelyPositioned(
 
 //----------------------------------------------------------------------
 // nsISVGGlyphFragmentNode interface:
 
 NS_IMETHODIMP_(PRUint32)
 nsSVGGlyphFrame::GetNumberOfChars()
 {
   if (mWhitespaceHandling == PRESERVE_WHITESPACE)
-    return GetFragment()->GetLength();
+    return mContent->TextLength();
 
   nsAutoString text;
   GetCharacterData(text);
   return text.Length();
 }
 
 NS_IMETHODIMP_(float)
 nsSVGGlyphFrame::GetComputedTextLength()
diff --git a/layout/svg/base/src/nsSVGGlyphFrame.h b/layout/svg/base/src/nsSVGGlyphFrame.h
--- a/layout/svg/base/src/nsSVGGlyphFrame.h
+++ b/layout/svg/base/src/nsSVGGlyphFrame.h
@@ -208,21 +208,16 @@ protected:
                       gfxContext *aContext);
 
   void NotifyGlyphMetricsChange();
   PRBool ContainsPoint(const nsPoint &aPoint);
   PRBool GetGlobalTransform(gfxMatrix *aMatrix);
   void SetupGlobalTransform(gfxContext *aContext);
   nsresult GetHighlight(PRUint32 *charnum, PRUint32 *nchars,
                         nscolor *foreground, nscolor *background);
-  const nsTextFragment* GetFragment() const
-  {
-    return !(GetStateBits() & NS_STATE_SVG_PRINTING) ?
-      mContent->GetText() : nsLayoutUtils::GetTextFragmentForPrinting(this);
-  }
 
   // Owning pointer, must call gfxTextRunWordCache::RemoveTextRun before deleting
   gfxTextRun *mTextRun;
   gfxPoint mPosition;
   PRUint8 mWhitespaceHandling;
 };
 
 #endif
diff --git a/layout/svg/base/src/nsSVGUtils.h b/layout/svg/base/src/nsSVGUtils.h
--- a/layout/svg/base/src/nsSVGUtils.h
+++ b/layout/svg/base/src/nsSVGUtils.h
@@ -89,19 +89,16 @@ class nsSVGGeometryFrame;
 
 #define NS_STATE_SVG_DIRTY            0x00200000
 
 /* are we the child of a non-display container? */
 #define NS_STATE_SVG_NONDISPLAY_CHILD 0x00400000
 
 #define NS_STATE_SVG_PROPAGATE_TRANSFORM 0x00800000
 
-// nsSVGGlyphFrame uses this when the frame is within a non-dynamic PresContext.
-#define NS_STATE_SVG_PRINTING 0x01000000
-
 /**
  * Byte offsets of channels in a native packed gfxColor or cairo image surface.
  */
 #ifdef IS_BIG_ENDIAN
 #define GFX_ARGB32_OFFSET_A 0
 #define GFX_ARGB32_OFFSET_R 1
 #define GFX_ARGB32_OFFSET_G 2
 #define GFX_ARGB32_OFFSET_B 3
