bug 621918 - part 1 - eliminate aDirtyRect parameter from gfxTextRun::Draw etc. r=roc a=roc
authorJonathan Kew <jfkthame@gmail.com>
Tue, 11 Jan 2011 11:17:00 +0000
changeset 60285 8e1487c6e663aa104986c40058c2ded96f686a67
parent 60284 fd860ead307768d027e819831f42710211741778
child 60286 119ef8681a16fd7eb79d515cebaa4800faab4bf3
push idunknown
push userunknown
push dateunknown
reviewersroc, roc
bugs621918
milestone2.0b10pre
bug 621918 - part 1 - eliminate aDirtyRect parameter from gfxTextRun::Draw etc. r=roc a=roc
content/canvas/src/nsCanvasRenderingContext2D.cpp
gfx/src/thebes/nsThebesFontMetrics.cpp
gfx/tests/gfxFontSelectionTest.cpp
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFont.h
layout/generic/nsTextFrameThebes.cpp
layout/svg/base/src/nsSVGGlyphFrame.cpp
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -2571,17 +2571,16 @@ struct NS_STACK_CLASS nsCanvasBidiProces
                                  nsnull);
         else
             // mOp == TEXT_DRAW_OPERATION_FILL
             mTextRun->Draw(mThebes,
                            point,
                            0,
                            mTextRun->GetLength(),
                            nsnull,
-                           nsnull,
                            nsnull);
     }
 
     // current text run
     gfxTextRunCache::AutoTextRun mTextRun;
 
     // pointer to the context, may not be the canvas's context
     // if an intermediate surface is being used
@@ -2919,17 +2918,16 @@ nsCanvasRenderingContext2D::MozDrawText(
     // Fill color is text color
     ApplyStyle(STYLE_FILL);
 
     textRun->Draw(mThebes,
                   pt,
                   /* offset = */ 0,
                   textToDraw.Length(),
                   nsnull,
-                  nsnull,
                   nsnull);
 
     return Redraw();
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::MozMeasureText(const nsAString& textToMeasure, float *retVal)
 {
@@ -3056,17 +3054,17 @@ nsCanvasRenderingContext2D::MozTextAlong
 
         rot.Invert();
         rot.Scale(aupdp,aupdp);
         gfxPoint pt = rot.Transform(cp[i].pos);
 
         if(stroke) {
             textRun->DrawToPath(mThebes, pt, i, 1, nsnull, nsnull);
         } else {
-            textRun->Draw(mThebes, pt, i, 1, nsnull, nsnull, nsnull);
+            textRun->Draw(mThebes, pt, i, 1, nsnull, nsnull);
         }
         mThebes->SetMatrix(matrix);
     }
 
     if (stroke)
         mThebes->Stroke();
 
     delete [] cp;
--- a/gfx/src/thebes/nsThebesFontMetrics.cpp
+++ b/gfx/src/thebes/nsThebesFontMetrics.cpp
@@ -394,17 +394,17 @@ nsThebesFontMetrics::DrawString(const ch
     AutoTextRun textRun(this, aContext, aString, aLength);
     if (!textRun.get())
         return NS_ERROR_FAILURE;
     gfxPoint pt(aX, aY);
     if (mTextRunRTL) {
         pt.x += textRun->GetAdvanceWidth(0, aLength, &provider);
     }
     textRun->Draw(aContext->ThebesContext(), pt, 0, aLength,
-                  nsnull, &provider, nsnull);
+                  &provider, nsnull);
     return NS_OK;
 }
 
 nsresult
 nsThebesFontMetrics::DrawString(const PRUnichar* aString, PRUint32 aLength,
                                 nscoord aX, nscoord aY,
                                 PRInt32 aFontID,
                                 const nscoord* aSpacing,
@@ -418,17 +418,17 @@ nsThebesFontMetrics::DrawString(const PR
     AutoTextRun textRun(this, aContext, aString, aLength);
     if (!textRun.get())
         return NS_ERROR_FAILURE;
     gfxPoint pt(aX, aY);
     if (mTextRunRTL) {
         pt.x += textRun->GetAdvanceWidth(0, aLength, &provider);
     }
     textRun->Draw(aContext->ThebesContext(), pt, 0, aLength,
-                  nsnull, &provider, nsnull);
+                  &provider, nsnull);
     return NS_OK;
 }
 
 #ifdef MOZ_MATHML
 
 static void
 GetTextRunBoundingMetrics(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aLength,
                           nsThebesRenderingContext *aContext,
--- a/gfx/tests/gfxFontSelectionTest.cpp
+++ b/gfx/tests/gfxFontSelectionTest.cpp
@@ -307,17 +307,17 @@ RunTest (TestEntry *test, gfxContext *ct
         textRun = gfxTextRunWordCache::MakeTextRun(reinterpret_cast<const PRUint8*>(test->string), length, fontGroup, &params, flags);
     } else {
         NS_ConvertUTF8toUTF16 str(nsDependentCString(test->string));
         length = str.Length();
         textRun = gfxTextRunWordCache::MakeTextRun(str.get(), length, fontGroup, &params, flags);
     }
 
     gfxFontTestStore::NewStore();
-    textRun->Draw(ctx, gfxPoint(0,0), 0, length, nsnull, nsnull, nsnull);
+    textRun->Draw(ctx, gfxPoint(0,0), 0, length, nsnull, nsnull);
     gfxFontTestStore *s = gfxFontTestStore::CurrentStore();
 
     gTextRunCache->RemoveTextRun(textRun);
 
     if (!test->Check(s)) {
         DumpStore(s);
         printf ("  expected:\n");
         DumpTestExpect(test);
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -3242,43 +3242,45 @@ ClipPartialLigature(gfxTextRun *aTextRun
             *aLeft = PR_MAX(*aLeft, endEdge);
         } else {
             *aRight = PR_MIN(*aRight, endEdge);
         }
     }    
 }
 
 void
-gfxTextRun::DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx, PRUint32 aStart,
-                                PRUint32 aEnd,
-                                const gfxRect *aDirtyRect, gfxPoint *aPt,
+gfxTextRun::DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx,
+                                PRUint32 aStart, PRUint32 aEnd,
+                                gfxPoint *aPt,
                                 PropertyProvider *aProvider)
 {
     if (aStart >= aEnd)
         return;
-    if (!aDirtyRect) {
-        NS_ERROR("Cannot draw partial ligatures without a dirty rect");
-        return;
-    }
+
+    // Need to preserve the path, otherwise this can break canvas text-on-path;
+    // in general it seems like a good thing, as naive callers probably won't
+    // expect gfxTextRun::Draw to implicitly destroy the current path.
+    gfxContextPathAutoSaveRestore savePath(aCtx);
 
     // Draw partial ligature. We hack this by clipping the ligature.
     LigatureData data = ComputeLigatureData(aStart, aEnd, aProvider);
-    gfxFloat left = aDirtyRect->X();
-    gfxFloat right = aDirtyRect->XMost();
+    gfxRect clipExtents = aCtx->GetClipExtents();
+    gfxFloat left = clipExtents.X()*mAppUnitsPerDevUnit;
+    gfxFloat right = clipExtents.XMost()*mAppUnitsPerDevUnit;
     ClipPartialLigature(this, &left, &right, aPt->x, &data);
 
     aCtx->Save();
     aCtx->NewPath();
     // use division here to ensure that when the rect is aligned on multiples
     // of mAppUnitsPerDevUnit, we clip to true device unit boundaries.
     // Also, make sure we snap the rectangle to device pixels.
     aCtx->Rectangle(gfxRect(left/mAppUnitsPerDevUnit,
-                            aDirtyRect->Y()/mAppUnitsPerDevUnit,
+                            clipExtents.Y(),
                             (right - left)/mAppUnitsPerDevUnit,
-                            aDirtyRect->Height()/mAppUnitsPerDevUnit), PR_TRUE);
+                            clipExtents.Height()), PR_TRUE);
     aCtx->Clip();
     gfxFloat direction = GetDirection();
     gfxPoint pt(aPt->x - direction*data.mPartAdvance, aPt->y);
     DrawGlyphs(aFont, aCtx, PR_FALSE, &pt, data.mLigatureStart,
                data.mLigatureEnd, aProvider, aStart, aEnd);
     aCtx->Restore();
 
     aPt->x += direction*data.mPartWidth;
@@ -3395,17 +3397,17 @@ gfxTextRun::AdjustAdvancesForSyntheticBo
                 }
             }
         }
     }
 }
 
 void
 gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt,
-                 PRUint32 aStart, PRUint32 aLength, const gfxRect *aDirtyRect,
+                 PRUint32 aStart, PRUint32 aLength,
                  PropertyProvider *aProvider, gfxFloat *aAdvanceWidth)
 {
     NS_ASSERTION(aStart + aLength <= mCharacterCount, "Substring out of range");
 
     gfxFloat direction = GetDirection();
     gfxPoint pt = aPt;
 
     // synthetic bolding draws glyphs twice ==> colors with opacity won't draw correctly unless first drawn without alpha
@@ -3426,20 +3428,20 @@ gfxTextRun::Draw(gfxContext *aContext, g
     while (iter.NextRun()) {
         gfxFont *font = iter.GetGlyphRun()->mFont;
         PRUint32 start = iter.GetStringStart();
         PRUint32 end = iter.GetStringEnd();
         PRUint32 ligatureRunStart = start;
         PRUint32 ligatureRunEnd = end;
         ShrinkToLigatureBoundaries(&ligatureRunStart, &ligatureRunEnd);
         
-        DrawPartialLigature(font, aContext, start, ligatureRunStart, aDirtyRect, &pt, aProvider);
+        DrawPartialLigature(font, aContext, start, ligatureRunStart, &pt, aProvider);
         DrawGlyphs(font, aContext, PR_FALSE, &pt, ligatureRunStart,
                    ligatureRunEnd, aProvider, ligatureRunStart, ligatureRunEnd);
-        DrawPartialLigature(font, aContext, ligatureRunEnd, end, aDirtyRect, &pt, aProvider);
+        DrawPartialLigature(font, aContext, ligatureRunEnd, end, &pt, aProvider);
     }
 
     // composite result when synthetic bolding used
     if (needToRestore) {
         syntheticBoldBuffer.PopAlpha();
     }
 
     if (aAdvanceWidth) {
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -1462,20 +1462,16 @@ public:
         virtual void GetSpacing(PRUint32 aStart, PRUint32 aLength,
                                 Spacing *aSpacing) = 0;
     };
 
     /**
      * Draws a substring. Uses only GetSpacing from aBreakProvider.
      * The provided point is the baseline origin on the left of the string
      * for LTR, on the right of the string for RTL.
-     * @param aDirtyRect if non-null, drawing outside of the rectangle can be
-     * (but does not need to be) dropped. Note that if this is null, we cannot
-     * draw partial ligatures and we will assert if partial ligatures
-     * are detected.
      * @param aAdvanceWidth if non-null, the advance width of the substring
      * is returned here.
      * 
      * Drawing should respect advance widths in the sense that for LTR runs,
      * Draw(ctx, pt, offset1, length1, dirty, &provider, &advance) followed by
      * Draw(ctx, gfxPoint(pt.x + advance, pt.y), offset1 + length1, length2,
      *      dirty, &provider, nsnull) should have the same effect as
      * Draw(ctx, pt, offset1, length1+length2, dirty, &provider, nsnull).
@@ -1485,17 +1481,16 @@ public:
      *      dirty, &provider, nsnull) should have the same effect as
      * Draw(ctx, pt, offset1, length1+length2, dirty, &provider, nsnull).
      * 
      * Glyphs should be drawn in logical content order, which can be significant
      * if they overlap (perhaps due to negative spacing).
      */
     void Draw(gfxContext *aContext, gfxPoint aPt,
               PRUint32 aStart, PRUint32 aLength,
-              const gfxRect *aDirtyRect,
               PropertyProvider *aProvider,
               gfxFloat *aAdvanceWidth);
 
     /**
      * Renders a substring to a path. Uses only GetSpacing from aBreakProvider.
      * The provided point is the baseline origin on the left of the string
      * for LTR, on the right of the string for RTL.
      * @param aAdvanceWidth if non-null, the advance width of the substring
@@ -2025,18 +2020,18 @@ private:
     // (Platforms do the actual ligaturization, but we need to do a bunch of stuff
     // to handle requests that begin or end inside a ligature)
 
     // if aProvider is null then mBeforeSpacing and mAfterSpacing are set to zero
     LigatureData ComputeLigatureData(PRUint32 aPartStart, PRUint32 aPartEnd,
                                      PropertyProvider *aProvider);
     gfxFloat ComputePartialLigatureWidth(PRUint32 aPartStart, PRUint32 aPartEnd,
                                          PropertyProvider *aProvider);
-    void DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx, PRUint32 aStart,
-                             PRUint32 aEnd, const gfxRect *aDirtyRect, gfxPoint *aPt,
+    void DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx,
+                             PRUint32 aStart, PRUint32 aEnd, gfxPoint *aPt,
                              PropertyProvider *aProvider);
     // Advance aStart to the start of the nearest ligature; back up aEnd
     // to the nearest ligature end; may result in *aStart == *aEnd
     void ShrinkToLigatureBoundaries(PRUint32 *aStart, PRUint32 *aEnd);
     // result in appunits
     gfxFloat GetPartialLigatureWidth(PRUint32 aStart, PRUint32 aEnd, PropertyProvider *aProvider);
     void AccumulatePartialLigatureMetrics(gfxFont *aFont,
                                           PRUint32 aStart, PRUint32 aEnd,
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -5078,29 +5078,29 @@ nsTextFrame::PaintText(nsIRenderingConte
 void
 nsTextFrame::DrawText(gfxContext* aCtx, const gfxPoint& aTextBaselinePt,
                       PRUint32 aOffset, PRUint32 aLength,
                       const gfxRect* aDirtyRect, PropertyProvider* aProvider,
                       gfxFloat& aAdvanceWidth, PRBool aDrawSoftHyphen)
 {
   // Paint the text and soft-hyphen (if any) onto the given graphics context
   mTextRun->Draw(aCtx, aTextBaselinePt, aOffset, aLength,
-                 aDirtyRect, aProvider, &aAdvanceWidth);
+                 aProvider, &aAdvanceWidth);
 
   if (aDrawSoftHyphen) {
     // Don't use ctx as the context, because we need a reference context here,
     // ctx may be transformed.
     gfxTextRunCache::AutoTextRun hyphenTextRun(GetHyphenTextRun(mTextRun, nsnull, this));
     if (hyphenTextRun.get()) {
       // For right-to-left text runs, the soft-hyphen is positioned at the left
       // of the text, minus its own width
       gfxFloat hyphenBaselineX = aTextBaselinePt.x + mTextRun->GetDirection() * aAdvanceWidth -
         (mTextRun->IsRightToLeft() ? hyphenTextRun->GetAdvanceWidth(0, hyphenTextRun->GetLength(), nsnull) : 0);
       hyphenTextRun->Draw(aCtx, gfxPoint(hyphenBaselineX, aTextBaselinePt.y),
-                          0, hyphenTextRun->GetLength(), aDirtyRect, nsnull, nsnull);
+                          0, hyphenTextRun->GetLength(), nsnull, nsnull);
     }
   }
 }
 
 PRInt16
 nsTextFrame::GetSelectionStatus(PRInt16* aSelectionFlags)
 {
   // get the selection controller
--- a/layout/svg/base/src/nsSVGGlyphFrame.cpp
+++ b/layout/svg/base/src/nsSVGGlyphFrame.cpp
@@ -598,24 +598,24 @@ nsSVGGlyphFrame::AddBoundingBoxesToPath(
 }
 
 void
 nsSVGGlyphFrame::FillCharacters(CharacterIterator *aIter,
                                 gfxContext *aContext)
 {
   if (aIter->SetupForDirectTextRunDrawing(aContext)) {
     mTextRun->Draw(aContext, gfxPoint(0, 0), 0,
-                   mTextRun->GetLength(), nsnull, nsnull, nsnull);
+                   mTextRun->GetLength(), nsnull, nsnull);
     return;
   }
 
   PRInt32 i;
   while ((i = aIter->NextChar()) >= 0) {
     aIter->SetupForDrawing(aContext);
-    mTextRun->Draw(aContext, gfxPoint(0, 0), i, 1, nsnull, nsnull, nsnull);
+    mTextRun->Draw(aContext, gfxPoint(0, 0), i, 1, nsnull, nsnull);
   }
 }
 
 gfxRect
 nsSVGGlyphFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace)
 {
   mOverrideCanvasTM = NS_NewSVGMatrix(aToBBoxUserspace);