Bug 1399274 - Block invisible text optimizations when using WebRender. r?jrmuizel draft
authorAlexis Beingessner <a.beingessner@gmail.com>
Wed, 13 Sep 2017 14:05:51 -0400
changeset 664245 55f6170684888c6ca42f65ca3c37b75e1d84598e
parent 663134 a73cc4e08bf5a005722c95b43f84ab0c8ff2bc7c
child 731399 02499f98e26c2cb8a7c17356e6060864262e3bc8
push id79649
push userbmo:a.beingessner@gmail.com
push dateWed, 13 Sep 2017 20:01:05 +0000
reviewersjrmuizel
bugs1399274
milestone57.0a1
Bug 1399274 - Block invisible text optimizations when using WebRender. r?jrmuizel Mostly just threading the TextDrawTarget deeper into the code to use a boolean. A lot of places are trying to optimize away invisible text! MozReview-Commit-ID: 89sDAwUv0HA
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFont.h
gfx/thebes/gfxTextRun.cpp
gfx/thebes/gfxTextRun.h
layout/generic/nsTextFrame.cpp
layout/generic/nsTextFrame.h
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -2001,16 +2001,17 @@ gfxFont::DrawGlyphs(const gfxShapedText 
 void
 gfxFont::DrawEmphasisMarks(const gfxTextRun* aShapedText, gfxPoint* aPt,
                            uint32_t aOffset, uint32_t aCount,
                            const EmphasisMarkDrawParams& aParams)
 {
     gfxFloat& inlineCoord = aParams.isVertical ? aPt->y : aPt->x;
     gfxTextRun::Range markRange(aParams.mark);
     gfxTextRun::DrawParams params(aParams.context);
+    params.textDrawer = aParams.textDrawer;
 
     gfxFloat clusterStart = -std::numeric_limits<gfxFloat>::infinity();
     bool shouldDrawEmphasisMark = false;
     for (uint32_t i = 0, idx = aOffset; i < aCount; ++i, ++idx) {
         if (aParams.spacing) {
             inlineCoord += aParams.direction * aParams.spacing[i].mBefore;
         }
         if (aShapedText->IsClusterStart(idx) ||
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -70,16 +70,19 @@ class gfxMathTable;
 
 struct gfxTextRunDrawCallbacks;
 
 namespace mozilla {
 class SVGContextPaint;
 namespace gfx {
 class GlyphRenderingOptions;
 } // namespace gfx
+namespace layout {
+class TextDrawTarget;
+} // namespace layout
 } // namespace mozilla
 
 struct gfxFontStyle {
     gfxFontStyle();
     gfxFontStyle(uint8_t aStyle, uint16_t aWeight, int16_t aStretch,
                  gfxFloat aSize, nsIAtom *aLanguage, bool aExplicitLanguage,
                  float aSizeAdjust, bool aSystemFont,
                  bool aPrinterFont,
@@ -2305,16 +2308,17 @@ struct MOZ_STACK_CLASS FontDrawParams {
     mozilla::gfx::DrawOptions drawOptions;
     bool                      isVerticalFont;
     bool                      haveSVGGlyphs;
     bool                      haveColorGlyphs;
 };
 
 struct MOZ_STACK_CLASS EmphasisMarkDrawParams {
     gfxContext* context;
+    mozilla::layout::TextDrawTarget* textDrawer = nullptr;
     gfxFont::Spacing* spacing;
     gfxTextRun* mark;
     gfxFloat advance;
     gfxFloat direction;
     bool isVertical;
 };
 
 #endif
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -602,17 +602,17 @@ gfxTextRun::Draw(Range aRange, gfxPoint 
                  "GLYPH_PATH cannot be used with GLYPH_FILL, GLYPH_STROKE or GLYPH_STROKE_UNDERNEATH");
     NS_ASSERTION(aParams.drawMode == DrawMode::GLYPH_PATH || !aParams.callbacks,
                  "callback must not be specified unless using GLYPH_PATH");
 
     bool skipDrawing = mSkipDrawing;
     if (aParams.drawMode & DrawMode::GLYPH_FILL) {
         Color currentColor;
         if (aParams.context->GetDeviceColor(currentColor) &&
-            currentColor.a == 0) {
+            currentColor.a == 0 && !aParams.textDrawer) {
             skipDrawing = true;
         }
     }
 
     gfxFloat direction = GetDirection();
 
     if (skipDrawing) {
         // We don't need to draw anything;
@@ -719,24 +719,27 @@ gfxTextRun::Draw(Range aRange, gfxPoint 
 
     if (aParams.advanceWidth) {
         *aParams.advanceWidth = advance;
     }
 }
 
 // This method is mostly parallel to Draw().
 void
-gfxTextRun::DrawEmphasisMarks(gfxContext *aContext, gfxTextRun* aMark,
+gfxTextRun::DrawEmphasisMarks(gfxContext *aContext,
+                              mozilla::layout::TextDrawTarget* aTextDrawer,
+                              gfxTextRun* aMark,
                               gfxFloat aMarkAdvance, gfxPoint aPt,
                               Range aRange, PropertyProvider* aProvider) const
 {
     MOZ_ASSERT(aRange.end <= GetLength());
 
     EmphasisMarkDrawParams params;
     params.context = aContext;
+    params.textDrawer = aTextDrawer;
     params.mark = aMark;
     params.advance = aMarkAdvance;
     params.direction = GetDirection();
     params.isVertical = IsVertical();
 
     gfxFloat& inlineCoord = params.isVertical ? aPt.y : aPt.x;
     gfxFloat direction = params.direction;
 
--- a/gfx/thebes/gfxTextRun.h
+++ b/gfx/thebes/gfxTextRun.h
@@ -37,16 +37,19 @@ class gfxUserFontEntry;
 class gfxUserFontSet;
 class nsIAtom;
 class nsLanguageAtomService;
 class gfxMissingFontRecorder;
 
 namespace mozilla {
 class SVGContextPaint;
 enum class StyleHyphens : uint8_t;
+namespace layout {
+class TextDrawTarget;
+};
 };
 
 /**
  * Callback for Draw() to use when drawing text with mode
  * DrawMode::GLYPH_PATH.
  */
 struct gfxTextRunDrawCallbacks {
 
@@ -239,16 +242,17 @@ public:
         // Return the appUnitsPerDevUnit value to be used when measuring.
         // Only called if the hyphen width is requested.
         virtual uint32_t GetAppUnitsPerDevUnit() const = 0;
     };
 
     struct MOZ_STACK_CLASS DrawParams
     {
         gfxContext* context;
+        mozilla::layout::TextDrawTarget* textDrawer = nullptr;
         DrawMode drawMode = DrawMode::GLYPH_FILL;
         nscolor textStrokeColor = 0;
         gfxPattern* textStrokePattern = nullptr;
         const mozilla::gfx::StrokeOptions *strokeOpts = nullptr;
         const mozilla::gfx::DrawOptions *drawOpts = nullptr;
         PropertyProvider* provider = nullptr;
         // If non-null, the advance width of the substring is set.
         gfxFloat* advanceWidth = nullptr;
@@ -279,17 +283,19 @@ public:
      */
     void Draw(Range aRange, gfxPoint aPt, const DrawParams& aParams) const;
 
     /**
      * Draws the emphasis marks for this text run. Uses only GetSpacing
      * from aProvider. The provided point is the baseline origin of the
      * line of emphasis marks.
      */
-    void DrawEmphasisMarks(gfxContext* aContext, gfxTextRun* aMark,
+    void DrawEmphasisMarks(gfxContext* aContext,
+                           mozilla::layout::TextDrawTarget* aTextDrawer,
+                           gfxTextRun* aMark,
                            gfxFloat aMarkAdvance, gfxPoint aPt,
                            Range aRange, PropertyProvider* aProvider) const;
 
     /**
      * Computes the ReflowMetrics for a substring.
      * Uses GetSpacing from aBreakProvider.
      * @param aBoundingBoxType which kind of bounding box (loose/tight)
      */
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -6851,17 +6851,19 @@ nsTextFrame::PaintTextWithSelection(
       PaintTextSelectionDecorations(aParams, details, selectionType);
     }
   }
 
   return true;
 }
 
 void
-nsTextFrame::DrawEmphasisMarks(gfxContext* aContext, WritingMode aWM,
+nsTextFrame::DrawEmphasisMarks(gfxContext* aContext,
+                               TextDrawTarget* aTextDrawer,
+                               WritingMode aWM,
                                const gfxPoint& aTextBaselinePt,
                                const gfxPoint& aFramePt, Range aRange,
                                const nscolor* aDecorationOverrideColor,
                                PropertyProvider* aProvider)
 {
   const EmphasisMarkInfo* info = GetProperty(EmphasisMarkProperty());
   if (!info) {
     return;
@@ -6888,22 +6890,24 @@ nsTextFrame::DrawEmphasisMarks(gfxContex
   } else {
     if (aWM.IsVerticalRL()) {
       pt.x -= info->baselineOffset;
     } else {
       pt.x += info->baselineOffset;
     }
   }
   if (!isTextCombined) {
-    mTextRun->DrawEmphasisMarks(aContext, info->textRun.get(), info->advance,
-                                pt, aRange, aProvider);
+    mTextRun->DrawEmphasisMarks(aContext, aTextDrawer, info->textRun.get(),
+                                info->advance, pt, aRange, aProvider);
   } else {
     pt.y += (GetSize().height - info->advance) / 2;
+    gfxTextRun::DrawParams params(aContext);
+    params.textDrawer = aTextDrawer;
     info->textRun->Draw(Range(info->textRun.get()), pt,
-                        gfxTextRun::DrawParams(aContext));
+                        params);
   }
 }
 
 nscolor
 nsTextFrame::GetCaretColorAt(int32_t aOffset)
 {
   NS_PRECONDITION(aOffset >= 0, "aOffset must be positive");
 
@@ -7287,33 +7291,34 @@ nsTextFrame::PaintText(const PaintTextPa
 
 static void
 DrawTextRun(const gfxTextRun* aTextRun,
             const gfxPoint& aTextBaselinePt,
             gfxTextRun::Range aRange,
             const nsTextFrame::DrawTextRunParams& aParams)
 {
   gfxTextRun::DrawParams params(aParams.context);
+  params.textDrawer = aParams.textDrawer;
   params.provider = aParams.provider;
   params.advanceWidth = aParams.advanceWidth;
   params.contextPaint = aParams.contextPaint;
   params.callbacks = aParams.callbacks;
   if (aParams.callbacks) {
     aParams.callbacks->NotifyBeforeText(aParams.textColor);
     params.drawMode = DrawMode::GLYPH_PATH;
     aTextRun->Draw(aRange, aTextBaselinePt, params);
     aParams.callbacks->NotifyAfterText();
   } else {
-    if (NS_GET_A(aParams.textColor) != 0) {
+    if (NS_GET_A(aParams.textColor) != 0 || aParams.textDrawer) {
       aParams.context->SetColor(Color::FromABGR(aParams.textColor));
     } else {
       params.drawMode = DrawMode::GLYPH_STROKE;
     }
 
-    if (NS_GET_A(aParams.textStrokeColor) != 0 &&
+    if ((NS_GET_A(aParams.textStrokeColor) != 0 || aParams.textDrawer) &&
         aParams.textStrokeWidth != 0.0f) {
       StrokeOptions strokeOpts;
       params.drawMode |= DrawMode::GLYPH_STROKE;
       params.textStrokeColor = aParams.textStrokeColor;
       strokeOpts.mLineWidth = aParams.textStrokeWidth;
       params.strokeOpts = &strokeOpts;
       aTextRun->Draw(aRange, aTextBaselinePt, params);
     } else {
@@ -7494,17 +7499,17 @@ nsTextFrame::DrawTextRunAndDecorations(R
       // and *then* line-throughs
       DrawTextRun(aRange, aTextBaselinePt, aParams);
     }
 
     // Emphasis marks
     if (aParams.textDrawer) {
       aParams.textDrawer->StartDrawing(TextDrawTarget::Phase::eEmphasisMarks);
     }
-    DrawEmphasisMarks(aParams.context, wm,
+    DrawEmphasisMarks(aParams.context, aParams.textDrawer, wm,
                       aTextBaselinePt, aParams.framePt, aRange,
                       aParams.decorationOverrideColor, aParams.provider);
 
     // Line-throughs
     if (aParams.textDrawer && aDecorations.mStrikes.Length() > 0) {
       aParams.textDrawer->StartDrawing(TextDrawTarget::Phase::eLineThrough);
     }
     params.decoration = NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -533,16 +533,17 @@ public:
     SelectionTypeMask* aAllSelectionTypeMask,
     const nsCharClipDisplayItem::ClipEdges& aClipEdges);
   // helper: paint text decorations for text selected by aSelectionType
   void PaintTextSelectionDecorations(const PaintTextSelectionParams& aParams,
                                      const mozilla::UniquePtr<SelectionDetails>& aDetails,
                                      SelectionType aSelectionType);
 
   void DrawEmphasisMarks(gfxContext* aContext,
+                         TextDrawTarget* aTextDrawer,
                          mozilla::WritingMode aWM,
                          const gfxPoint& aTextBaselinePt,
                          const gfxPoint& aFramePt,
                          Range aRange,
                          const nscolor* aDecorationOverrideColor,
                          PropertyProvider* aProvider);
 
   nscolor GetCaretColorAt(int32_t aOffset) override;