Bug 585817. Part 2: Change nsIPresShell::CreateRenderingContext to GetReferenceRenderingContext, that uses the shared 1x1 surface, and use it all over the place. r=mats,sr=dbaron
☠☠ backed out by 62d6d6d5f723 ☠ ☠
authorRobert O'Callahan <roc@ocallahan.org>
Thu, 19 Aug 2010 13:49:35 -0500
changeset 50914 7b3726c3a580a4be272b8c7ea35ef4d87f99e239
parent 50913 b3e968d831ecb10a1368b5afc2f7efecbb26fb0a
child 50915 cebb111fbfc49506798a97c389519b1ead2fe0f4
child 50976 62d6d6d5f723bf624b36a9f210ccb14fd5a2aca7
push idunknown
push userunknown
push dateunknown
reviewersmats, dbaron
bugs585817
milestone2.0b5pre
Bug 585817. Part 2: Change nsIPresShell::CreateRenderingContext to GetReferenceRenderingContext, that uses the shared 1x1 surface, and use it all over the place. r=mats,sr=dbaron
accessible/src/msaa/nsTextAccessibleWrap.cpp
layout/base/nsDocumentViewer.cpp
layout/base/nsIPresShell.h
layout/base/nsPresShell.cpp
layout/generic/nsSimplePageSequence.cpp
layout/generic/nsTextFrameThebes.cpp
layout/inspector/src/inFlasher.cpp
layout/svg/base/src/nsSVGForeignObjectFrame.cpp
layout/xul/base/src/nsSplitterFrame.cpp
layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
--- a/accessible/src/msaa/nsTextAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsTextAccessibleWrap.cpp
@@ -254,18 +254,17 @@ STDMETHODIMP nsTextAccessibleWrap::get_f
   *aFontFamily = NULL;
 
   nsIFrame *frame = GetFrame();
   nsCOMPtr<nsIPresShell> presShell = GetPresShell();
   if (!frame || !presShell || !presShell->GetPresContext()) {
     return E_FAIL;
   }
 
-  nsCOMPtr<nsIRenderingContext> rc;
-  presShell->CreateRenderingContext(frame, getter_AddRefs(rc));
+  nsCOMPtr<nsIRenderingContext> rc = presShell->GetReferenceRenderingContext();
   if (!rc) {
     return E_FAIL;
   }
 
   const nsStyleFont *font = frame->GetStyleFont();
 
   const nsStyleVisibility *visibility = frame->GetStyleVisibility();
 
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -3259,18 +3259,18 @@ NS_IMETHODIMP DocumentViewerImpl::SizeTo
    // because it won't change some sizes that a style change reflow will.
    mDocument->FlushPendingNotifications(Flush_Layout);
 
   nsIFrame *root = presShell->GetRootFrame();
   NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
 
   nscoord prefWidth;
   {
-    nsCOMPtr<nsIRenderingContext> rcx;
-    presShell->CreateRenderingContext(root, getter_AddRefs(rcx));
+    nsCOMPtr<nsIRenderingContext> rcx =
+      presShell->GetReferenceRenderingContext();
     NS_ENSURE_TRUE(rcx, NS_ERROR_FAILURE);
     prefWidth = root->GetPrefWidth(rcx);
   }
 
   nsresult rv = presShell->ResizeReflow(prefWidth, NS_UNCONSTRAINEDSIZE);
   NS_ENSURE_SUCCESS(rv, rv);
 
    nsRefPtr<nsPresContext> presContext;
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -134,18 +134,18 @@ typedef struct CapturingContentInfo {
   nsIContent* mContent;
 
   CapturingContentInfo() :
     mAllowed(PR_FALSE), mRetargetToElement(PR_FALSE), mPreventDrag(PR_FALSE),
     mContent(nsnull) { }
 } CapturingContentInfo;
 
 #define NS_IPRESSHELL_IID     \
-  { 0xe82aae32, 0x2d68, 0x452a, \
-    { 0x88, 0x95, 0x86, 0xc6, 0x07, 0xe1, 0xec, 0x91 } }
+  { 0xe63a350c, 0x4e04, 0x4056, \
+    { 0x8d, 0xa0, 0x51, 0xcc, 0x55, 0x68, 0x68, 0x42 } }
 
 // Constants for ScrollContentIntoView() function
 #define NS_PRESSHELL_SCROLL_TOP      0
 #define NS_PRESSHELL_SCROLL_BOTTOM   100
 #define NS_PRESSHELL_SCROLL_LEFT     0
 #define NS_PRESSHELL_SCROLL_RIGHT    100
 #define NS_PRESSHELL_SCROLL_CENTER   50
 #define NS_PRESSHELL_SCROLL_ANYWHERE -1
@@ -474,21 +474,21 @@ public:
    * some reason.
    */
   virtual NS_HIDDEN_(nsresult) PostReflowCallback(nsIReflowCallback* aCallback) = 0;
   virtual NS_HIDDEN_(void) CancelReflowCallback(nsIReflowCallback* aCallback) = 0;
 
   virtual NS_HIDDEN_(void) ClearFrameRefs(nsIFrame* aFrame) = 0;
 
   /**
-   * Given a frame, create a rendering context suitable for use with
-   * the frame.
+   * Get a reference rendering context. This is a context that should not
+   * be rendered to, but is suitable for measuring text and performing
+   * other non-rendering operations.
    */
-  virtual NS_HIDDEN_(nsresult) CreateRenderingContext(nsIFrame *aFrame,
-                                                      nsIRenderingContext** aContext) = 0;
+  virtual already_AddRefed<nsIRenderingContext> GetReferenceRenderingContext() = 0;
 
   /**
    * Informs the pres shell that the document is now at the anchor with
    * the given name.  If |aScroll| is true, scrolls the view of the
    * document so that the anchor with the specified name is displayed at
    * the top of the window.  If |aAnchorName| is empty, then this informs
    * the pres shell that there is no current target, and |aScroll| must
    * be false.
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -748,18 +748,17 @@ public:
 
   /**
    * Post a callback that should be handled after reflow has finished.
    */
   virtual NS_HIDDEN_(nsresult) PostReflowCallback(nsIReflowCallback* aCallback);
   virtual NS_HIDDEN_(void) CancelReflowCallback(nsIReflowCallback* aCallback);
 
   virtual NS_HIDDEN_(void) ClearFrameRefs(nsIFrame* aFrame);
-  virtual NS_HIDDEN_(nsresult) CreateRenderingContext(nsIFrame *aFrame,
-                                                      nsIRenderingContext** aContext);
+  virtual NS_HIDDEN_(already_AddRefed<nsIRenderingContext>) GetReferenceRenderingContext();
   virtual NS_HIDDEN_(nsresult) GoToAnchor(const nsAString& aAnchorName, PRBool aScroll);
   virtual NS_HIDDEN_(nsresult) ScrollToAnchor();
 
   virtual NS_HIDDEN_(nsresult) ScrollContentIntoView(nsIContent* aContent,
                                                      PRIntn      aVPercent,
                                                      PRIntn      aHPercent);
   virtual PRBool ScrollFrameRectIntoView(nsIFrame*     aFrame,
                                          const nsRect& aRect,
@@ -3670,61 +3669,32 @@ PresShell::ClearFrameRefs(nsIFrame* aFra
     if (weakFrame->GetFrame() == aFrame) {
       // This removes weakFrame from mWeakFrames.
       weakFrame->Clear(this);
     }
     weakFrame = prev;
   }
 }
 
-nsresult
-PresShell::CreateRenderingContext(nsIFrame *aFrame,
-                                  nsIRenderingContext** aResult)
+already_AddRefed<nsIRenderingContext>
+PresShell::GetReferenceRenderingContext()
 {
   NS_TIME_FUNCTION_MIN(1.0);
 
-  NS_PRECONDITION(nsnull != aResult, "null ptr");
-  if (nsnull == aResult) {
-    return NS_ERROR_NULL_POINTER;
-  }
-
-  nsIWidget* widget = nsnull;
-  nsPoint offset(0,0);
+  nsIDeviceContext* devCtx = mPresContext->DeviceContext();
+  nsRefPtr<nsIRenderingContext> rc;
   if (mPresContext->IsScreen()) {
-    // Get the widget to create the rendering context for and calculate
-    // the offset from the frame to it.
-    nsPoint viewOffset;
-    nsIView* view = aFrame->GetClosestView(&viewOffset);
-    nsPoint widgetOffset;
-    widget = view->GetNearestWidget(&widgetOffset);
-    offset = viewOffset + widgetOffset;
+    devCtx->CreateRenderingContextInstance(*getter_AddRefs(rc));
+    if (rc) {
+      rc->Init(devCtx, gfxPlatform::GetPlatform()->ScreenReferenceSurface());
+    }
   } else {
-    nsIFrame* pageFrame = nsLayoutUtils::GetPageFrame(aFrame);
-    // This might not always come up with a frame, i.e. during reflow;
-    // that's fine, because the translation doesn't matter during reflow.
-    if (pageFrame)
-      offset = aFrame->GetOffsetTo(pageFrame);
-  }
-
-  nsresult rv;
-  nsIRenderingContext* result = nsnull;
-  nsIDeviceContext *deviceContext = mPresContext->DeviceContext();
-  if (widget) {
-    rv = deviceContext->CreateRenderingContext(widget, result);
-  }
-  else {
-    rv = deviceContext->CreateRenderingContext(result);
-  }
-  *aResult = result;
-
-  if (NS_SUCCEEDED(rv)) {
-    result->Translate(offset.x, offset.y);
-  }
-
-  return rv;
+    devCtx->CreateRenderingContext(*getter_AddRefs(rc));
+  }
+  return rc.forget();
 }
 
 nsresult
 PresShell::GoToAnchor(const nsAString& aAnchorName, PRBool aScroll)
 {
   if (!mDocument) {
     return NS_ERROR_FAILURE;
   }
@@ -7513,21 +7483,18 @@ PresShell::DoReflow(nsIFrame* target, PR
 
   if (mReflowContinueTimer) {
     mReflowContinueTimer->Cancel();
     mReflowContinueTimer = nsnull;
   }
 
   nsIFrame* rootFrame = FrameManager()->GetRootFrame();
 
-  nsCOMPtr<nsIRenderingContext> rcx;
-  // Always create the rendering context relative to the root frame during
-  // reflow; otherwise, it crashes on the mac (I'm not quite sure why)
-  nsresult rv = CreateRenderingContext(rootFrame, getter_AddRefs(rcx));
-  if (NS_FAILED(rv)) {
+  nsCOMPtr<nsIRenderingContext> rcx = GetReferenceRenderingContext();
+  if (!rcx) {
     NS_NOTREACHED("CreateRenderingContext failure");
     return PR_FALSE;
   }
 
 #ifdef DEBUG
   mCurrentReflowRoot = target;
 #endif
 
--- a/layout/generic/nsSimplePageSequence.cpp
+++ b/layout/generic/nsSimplePageSequence.cpp
@@ -602,19 +602,18 @@ nsSimplePageSequenceFrame::PrintNextPage
         PR_PL(("***************** BeginPage *****************\n"));
         rv = dc->BeginPage();
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
       PR_PL(("SeqFr::PrintNextPage -> %p PageNo: %d", pf, mPageNum));
 
       nsCOMPtr<nsIRenderingContext> renderingContext;
-      PresContext()->PresShell()->
-              CreateRenderingContext(mCurrentPageFrame,
-                                     getter_AddRefs(renderingContext));
+      dc->CreateRenderingContext(*getter_AddRefs(renderingContext));
+      NS_ENSURE_TRUE(renderingContext, NS_ERROR_OUT_OF_MEMORY);
 
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
       // On linux, need to rotate landscape-mode output on printed surfaces
       PRInt32 orientation;
       mPageData->mPrintSettings->GetOrientation(&orientation);
       if (nsIPrintSettings::kLandscapeOrientation == orientation) {
         // Shift up by one landscape-page-height (in points) before we rotate.
         float offset = POINTS_PER_INCH_FLOAT *
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -1488,19 +1488,18 @@ GetFontGroupForFrame(nsIFrame* aFrame,
   return fm->GetThebesFontGroup();
 }
 
 static already_AddRefed<gfxContext>
 GetReferenceRenderingContext(nsTextFrame* aTextFrame, nsIRenderingContext* aRC)
 {
   nsCOMPtr<nsIRenderingContext> tmp = aRC;
   if (!tmp) {
-    nsresult rv = aTextFrame->PresContext()->PresShell()->
-      CreateRenderingContext(aTextFrame, getter_AddRefs(tmp));
-    if (NS_FAILED(rv))
+    tmp = aTextFrame->PresContext()->PresShell()->GetReferenceRenderingContext();
+    if (!tmp)
       return nsnull;
   }
 
   gfxContext* ctx = tmp->ThebesContext();
   NS_ADDREF(ctx);
   return ctx;
 }
 
--- a/layout/inspector/src/inFlasher.cpp
+++ b/layout/inspector/src/inFlasher.cpp
@@ -150,32 +150,35 @@ inFlasher::DrawElementOutline(nsIDOMElem
   nsCOMPtr<nsIPresShell> presShell = inLayoutUtils::GetPresShellFor(window);
   if (!presShell) return NS_OK;
 
   nsIFrame* frame = inLayoutUtils::GetFrameFor(aElement);
 
   PRBool isFirstFrame = PR_TRUE;
 
   while (frame) {
-    nsCOMPtr<nsIRenderingContext> rcontext;
-    nsresult rv =
-      presShell->CreateRenderingContext(frame, getter_AddRefs(rcontext));
-    NS_ENSURE_SUCCESS(rv, rv);
+    nsPoint offset;
+    nsIWidget* widget = frame->GetNearestWidget(offset);
+    if (widget) {
+      nsCOMPtr<nsIRenderingContext> rcontext;
+      frame->PresContext()->DeviceContext()->
+        CreateRenderingContext(widget, *getter_AddRefs(rcontext));
+      if (rcontext) {
+        nsRect rect(offset, frame->GetSize());
+        if (mInvert) {
+          rcontext->InvertRect(rect);
+        }
 
-    nsRect rect(nsPoint(0,0), frame->GetSize());
-    if (mInvert) {
-      rcontext->InvertRect(rect);
+        PRBool isLastFrame = frame->GetNextContinuation() == nsnull;
+        DrawOutline(rect.x, rect.y, rect.width, rect.height, rcontext,
+                    isFirstFrame, isLastFrame);
+        isFirstFrame = PR_FALSE;
+      }
     }
-
     frame = frame->GetNextContinuation();
-
-    PRBool isLastFrame = (frame == nsnull);
-    DrawOutline(rect.x, rect.y, rect.width, rect.height, rcontext,
-                isFirstFrame, isLastFrame);
-    isFirstFrame = PR_FALSE;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 inFlasher::ScrollElementIntoView(nsIDOMElement *aElement)
 {
--- a/layout/svg/base/src/nsSVGForeignObjectFrame.cpp
+++ b/layout/svg/base/src/nsSVGForeignObjectFrame.cpp
@@ -564,20 +564,20 @@ nsSVGForeignObjectFrame::DoReflow()
 
   nsPresContext *presContext = PresContext();
   nsIFrame* kid = GetFirstChild(nsnull);
   if (!kid)
     return;
 
   // initiate a synchronous reflow here and now:  
   nsSize availableSpace(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
-  nsCOMPtr<nsIRenderingContext> renderingContext;
   nsIPresShell* presShell = presContext->PresShell();
   NS_ASSERTION(presShell, "null presShell");
-  presShell->CreateRenderingContext(this,getter_AddRefs(renderingContext));
+  nsCOMPtr<nsIRenderingContext> renderingContext =
+    presShell->GetReferenceRenderingContext();
   if (!renderingContext)
     return;
 
   nsSVGForeignObjectElement *fO = static_cast<nsSVGForeignObjectElement*>
                                              (mContent);
 
   float width =
     fO->mLengthAttributes[nsSVGForeignObjectElement::WIDTH].GetAnimValue(fO);
--- a/layout/xul/base/src/nsSplitterFrame.cpp
+++ b/layout/xul/base/src/nsSplitterFrame.cpp
@@ -659,20 +659,19 @@ nsSplitterFrameInner::MouseDown(nsIDOMEv
   if (childIndex <= 0)
     return NS_OK;
 
   PRInt32 childCount = siblingList.GetLength();
   // if it's the last index then we need to allow for resizeafter="grow"
   if (childIndex == childCount - 1 && GetResizeAfter() != Grow)
     return NS_OK;
 
-  nsCOMPtr<nsIRenderingContext> rc;
-  nsresult rv = outerPresContext->PresShell()->
-                  CreateRenderingContext(mOuter, getter_AddRefs(rc));
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIRenderingContext> rc =
+    outerPresContext->PresShell()->GetReferenceRenderingContext();
+  NS_ENSURE_TRUE(rc, NS_ERROR_FAILURE);
   nsBoxLayoutState state(outerPresContext, rc);
   mCurrentPos = 0;
   mPressed = PR_TRUE;
 
   mDidDrag = PR_FALSE;
 
   EnsureOrient();
   PRBool isHorizontal = !mOuter->IsHorizontal();
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
@@ -265,18 +265,20 @@ nsTreeBodyFrame::CalcMaxRowWidth()
 
   nsStyleContext* rowContext = GetPseudoStyleContext(nsCSSAnonBoxes::moztreerow);
   nsMargin rowMargin(0,0,0,0);
   GetBorderPadding(rowContext, rowMargin);
 
   nscoord rowWidth;
   nsTreeColumn* col;
 
-  nsCOMPtr<nsIRenderingContext> rc;
-  PresContext()->PresShell()->CreateRenderingContext(this, getter_AddRefs(rc));
+  nsCOMPtr<nsIRenderingContext> rc =
+    PresContext()->PresShell()->GetReferenceRenderingContext();
+  if (!rc)
+    return 0;
 
   for (PRInt32 row = 0; row < mRowCount; ++row) {
     rowWidth = 0;
 
     for (col = mColumns->GetFirstColumn(); col; col = col->GetNext()) {
       nscoord desiredWidth, currentWidth;
       nsresult rv = GetCellWidth(row, col, rc, desiredWidth, currentWidth);
       if (NS_FAILED(rv)) {
@@ -1168,18 +1170,20 @@ nsTreeBodyFrame::GetCoordsForCellItem(PR
     }
 
     // Since we're not looking for the cell, and since the cell isn't a cycler,
     // we're looking for some subcomponent, and now we need to subtract the 
     // borders and padding of the cell from cellRect so this does not 
     // interfere with our computations.
     AdjustForBorderPadding(cellContext, cellRect);
 
-    nsCOMPtr<nsIRenderingContext> rc;
-    presContext->PresShell()->CreateRenderingContext(this, getter_AddRefs(rc));
+    nsCOMPtr<nsIRenderingContext> rc =
+      presContext->PresShell()->GetReferenceRenderingContext();
+    if (!rc)
+      return NS_ERROR_OUT_OF_MEMORY;
 
     // Now we'll start making our way across the cell, starting at the edge of 
     // the cell and proceeding until we hit the right edge. |cellX| is the 
     // working X value that we will increment as we crawl from left to right.
     nscoord cellX = cellRect.x;
     nscoord remainWidth = cellRect.width;
 
     if (currCol->IsPrimary()) {
@@ -1516,16 +1520,22 @@ nsTreeBodyFrame::GetItemWithinCellAt(nsc
   }
 
   nscoord currX = cellRect.x;
   nscoord remainingWidth = cellRect.width;
 
   // Handle right alignment hit testing.
   PRBool isRTL = GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL;
 
+  nsPresContext* presContext = PresContext();
+  nsCOMPtr<nsIRenderingContext> rc =
+    presContext->PresShell()->GetReferenceRenderingContext();
+  if (!rc)
+    return nsCSSAnonBoxes::moztreecell;
+
   if (aColumn->IsPrimary()) {
     // If we're the primary column, we have indentation and a twisty.
     PRInt32 level;
     mView->GetLevel(aRowIndex, &level);
 
     if (!isRTL)
       currX += mIndentation*level;
     remainingWidth -= mIndentation*level;
@@ -1543,20 +1553,16 @@ nsTreeBodyFrame::GetItemWithinCellAt(nsc
     mView->IsContainer(aRowIndex, &isContainer);
     if (isContainer) {
       PRBool isContainerEmpty = PR_FALSE;
       mView->IsContainerEmpty(aRowIndex, &isContainerEmpty);
       if (!isContainerEmpty)
         hasTwisty = PR_TRUE;
     }
 
-    nsPresContext* presContext = PresContext();
-    nsCOMPtr<nsIRenderingContext> rc;
-    presContext->PresShell()->CreateRenderingContext(this, getter_AddRefs(rc));
-
     // Resolve style for the twisty.
     nsStyleContext* twistyContext = GetPseudoStyleContext(nsCSSAnonBoxes::moztreetwisty);
 
     nsRect imageSize;
     GetTwistyRect(aRowIndex, aColumn, imageSize, twistyRect, presContext,
                   *rc, twistyContext);
 
     // We will treat a click as hitting the twisty if it happens on the margins, borders, padding,
@@ -1617,22 +1623,19 @@ nsTreeBodyFrame::GetItemWithinCellAt(nsc
   nsStyleContext* textContext = GetPseudoStyleContext(nsCSSAnonBoxes::moztreecelltext);
 
   nsMargin textMargin;
   textContext->GetStyleMargin()->GetMargin(textMargin);
   textRect.Deflate(textMargin);
 
   AdjustForBorderPadding(textContext, textRect);
 
-  nsCOMPtr<nsIRenderingContext> renderingContext;
-  PresContext()->PresShell()->CreateRenderingContext(this, getter_AddRefs(renderingContext));
-
-  nsLayoutUtils::SetFontFromStyle(renderingContext, textContext);
-
-  AdjustForCellText(cellText, aRowIndex, aColumn, *renderingContext, textRect);
+  nsLayoutUtils::SetFontFromStyle(rc, textContext);
+
+  AdjustForCellText(cellText, aRowIndex, aColumn, *rc, textRect);
   if (isRTL)
     textRect.x = currX + remainingWidth - textRect.width;
 
   if (aX >= textRect.x && aX < textRect.x + textRect.width)
     return nsCSSAnonBoxes::moztreecelltext;
   else
     return nsCSSAnonBoxes::moztreecell;
 }
@@ -1770,20 +1773,19 @@ nsTreeBodyFrame::IsCellCropped(PRInt32 a
 {  
   nscoord currentSize, desiredSize;
   nsresult rv;
 
   nsRefPtr<nsTreeColumn> col = GetColumnImpl(aCol);
   if (!col)
     return NS_ERROR_INVALID_ARG;
 
-  nsCOMPtr<nsIRenderingContext> rc;
-  rv = PresContext()->PresShell()->
-    CreateRenderingContext(this, getter_AddRefs(rc));
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIRenderingContext> rc =
+    PresContext()->PresShell()->GetReferenceRenderingContext();
+  NS_ENSURE_TRUE(rc, NS_ERROR_FAILURE);
 
   rv = GetCellWidth(aRow, col, rc, desiredSize, currentSize);
   NS_ENSURE_SUCCESS(rv, rv);
 
   *_retval = desiredSize > currentSize;
 
   return NS_OK;
 }