Bug 1127114, part 2 - Unify SVGTextFrame's NotifyBeforeSelectionBackground and NotifySelectionBackgroundPathEmitted callbacks. r=heycam
authorJonathan Watt <jwatt@jwatt.org>
Tue, 27 Jan 2015 16:32:24 +0000
changeset 226549 3716775c5a2b908132bfcad59fe9b59346b970d5
parent 226548 640111b4c868b95ce167b9ab95e08797d1c0b6b2
child 226550 1e5647b23d2eac3ef087c77b5de6a828c83a8217
push id28200
push userkwierso@gmail.com
push dateThu, 29 Jan 2015 23:01:46 +0000
treeherdermozilla-central@4380ed39de3a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1127114
milestone38.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1127114, part 2 - Unify SVGTextFrame's NotifyBeforeSelectionBackground and NotifySelectionBackgroundPathEmitted callbacks. r=heycam
layout/generic/nsTextFrame.cpp
layout/generic/nsTextFrame.h
layout/svg/SVGTextFrame.cpp
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -3,18 +3,20 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* rendering object for textual content of elements */
 
 #include "nsTextFrame.h"
 
 #include "gfx2DGlue.h"
+#include "gfxUtils.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
+#include "mozilla/gfx/2D.h"
 #include "mozilla/Likely.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/BinarySearch.h"
 
 #include "nsCOMPtr.h"
 #include "nsBlockFrame.h"
 #include "nsCRT.h"
@@ -4737,39 +4739,30 @@ nsTextFrame::GetSelectionDetails()
     // The entire text is selected!
     sd->mStart = GetContentOffset();
     sd->mEnd = GetContentEnd();
   }
   return details;
 }
 
 static void
-PaintSelectionBackground(gfxContext* aCtx,
+PaintSelectionBackground(DrawTarget& aDrawTarget,
                          nscolor aColor,
                          const LayoutDeviceRect& aDirtyRect,
                          const LayoutDeviceRect& aRect,
                          nsTextFrame::DrawPathCallbacks* aCallbacks)
 {
-  DrawTarget& aDrawTarget = *aCtx->GetDrawTarget();
+  Rect rect = aRect.Intersect(aDirtyRect).ToUnknownRect();
+  MaybeSnapToDevicePixels(rect, aDrawTarget);
 
   if (aCallbacks) {
-    aCallbacks->NotifyBeforeSelectionBackground(aColor);
-  }
-
-  Rect rect = aRect.Intersect(aDirtyRect).ToUnknownRect();
-  // For now, we need to put this in pixel coordinates
-  aCtx->NewPath();
-  // pixel-snap
-  aCtx->Rectangle(ThebesRect(rect), true);
-
-  if (aCallbacks) {
-    aCallbacks->NotifySelectionBackgroundPathEmitted();
+    aCallbacks->NotifySelectionBackgroundNeedsFill(rect, aColor, aDrawTarget);
   } else {
-    aCtx->SetColor(gfxRGBA(aColor));
-    aCtx->Fill();
+    ColorPattern color(ToDeviceColor(aColor));
+    aDrawTarget.FillRect(rect, color);
   }
 }
 
 // Attempt to get the LineBaselineOffset property of aChildFrame
 // If not set, calculate this value for all child frames of aBlockFrame
 static nscoord
 LazyGetLineBaselineOffset(nsIFrame* aChildFrame, nsBlockFrame* aBlockFrame)
 {
@@ -5692,17 +5685,17 @@ nsTextFrame::PaintTextWithSelectionColor
         gfxFloat offs = iOffset - (mTextRun->IsRightToLeft() ? advance : 0);
         if (vertical) {
           bgRect = gfxRect(aFramePt.x, aFramePt.y + offs,
                            GetSize().width, advance);
         } else {
           bgRect = gfxRect(aFramePt.x + offs, aFramePt.y,
                            advance, GetSize().height);
         }
-        PaintSelectionBackground(aCtx, background, dirtyRect,
+        PaintSelectionBackground(*aCtx->GetDrawTarget(), background, dirtyRect,
                                  AppUnitGfxRectToDevRect(bgRect, appUnitsPerDevPixel),
                                  aCallbacks);
       }
       iterator.UpdateWithAdvance(advance);
     }
   }
   
   // Draw text
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsTextFrame_h__
 #define nsTextFrame_h__
 
 #include "mozilla/Attributes.h"
+#include "mozilla/gfx/2D.h"
 #include "nsFrame.h"
 #include "nsSplittableFrame.h"
 #include "nsLineBox.h"
 #include "gfxSkipChars.h"
 #include "gfxTextRun.h"
 #include "nsDisplayList.h"
 #include "JustificationUtils.h"
 
@@ -32,16 +33,19 @@ class nsDisplayText;
 
 class nsTextFrameTextRunCache {
 public:
   static void Init();
   static void Shutdown();
 };
 
 class nsTextFrame : public nsTextFrameBase {
+  typedef mozilla::gfx::DrawTarget DrawTarget;
+  typedef mozilla::gfx::Rect Rect;
+
 public:
   NS_DECL_QUERYFRAME_TARGET(nsTextFrame)
   NS_DECL_FRAMEARENA_HELPERS
 
   friend class nsContinuingTextFrame;
   friend class nsDisplayTextGeometry;
   friend class nsDisplayText;
 
@@ -295,17 +299,17 @@ public:
 
   /**
    * Object with various callbacks for PaintText() to invoke for different parts
    * of the frame's text rendering, when we're generating paths rather than
    * painting.
    *
    * Callbacks are invoked in the following order:
    *
-   *   (NotifyBeforeSelectionBackground NotifySelectionBackgroundPathEmitted)?
+   *   (NotifySelectionBackgroundNeedsFill)?
    *   (NotifyBeforeDecorationLine NotifyDecorationLinePathEmitted)*
    *   NotifyBeforeText
    *   (NotifyGlyphPathEmitted |
    *    (NotifyBeforeSVGGlyphPainted NotifyAfterSVGGlyphPainted))*
    *   NotifyAfterText
    *   (NotifyBeforeDecorationLine NotifyDecorationLinePathEmitted)*
    *   (NotifyBeforeSelectionDecorationLine NotifySelectionDecorationLinePathEmitted)*
    *
@@ -321,40 +325,36 @@ public:
      * @param aShouldPaintSVGGlyphs Whether SVG glyphs should be painted.
      */
     explicit DrawPathCallbacks(bool aShouldPaintSVGGlyphs = false)
       : gfxTextRunDrawCallbacks(aShouldPaintSVGGlyphs)
     {
     }
 
     /**
+     * Called to have the selection highlight drawn before the text is drawn
+     * over the top.
+     */
+    virtual void NotifySelectionBackgroundNeedsFill(const Rect& aBackgroundRect,
+                                                    nscolor aColor,
+                                                    DrawTarget& aDrawTarget) { }
+
+    /**
      * Called just before any paths have been emitted to the gfxContext
      * for the glyphs of the frame's text.
      */
     virtual void NotifyBeforeText(nscolor aColor) { }
 
     /**
      * Called just after all the paths have been emitted to the gfxContext
      * for the glyphs of the frame's text.
      */
     virtual void NotifyAfterText() { }
 
     /**
-     * Called just before a path corresponding to the selection background
-     * has been emitted to the gfxContext.
-     */
-    virtual void NotifyBeforeSelectionBackground(nscolor aColor) { }
-
-    /**
-     * Called just after a path corresponding to the selection background
-     * has been emitted to the gfxContext.
-     */
-    virtual void NotifySelectionBackgroundPathEmitted() { }
-
-    /**
      * Called just before a path corresponding to a text decoration line
      * has been emitted to the gfxContext.
      */
     virtual void NotifyBeforeDecorationLine(nscolor aColor) { }
 
     /**
      * Called just after a path corresponding to a text decoration line
      * has been emitted to the gfxContext.
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -2718,23 +2718,24 @@ public:
                            bool aShouldPaintSVGGlyphs)
     : DrawPathCallbacks(aShouldPaintSVGGlyphs),
       gfx(aContext->ThebesContext()),
       mFrame(aFrame),
       mCanvasTM(aCanvasTM)
   {
   }
 
+  void NotifySelectionBackgroundNeedsFill(const Rect& aBackgroundRect,
+                                          nscolor aColor,
+                                          DrawTarget& aDrawTarget) MOZ_OVERRIDE;
   void NotifyBeforeText(nscolor aColor) MOZ_OVERRIDE;
   void NotifyGlyphPathEmitted() MOZ_OVERRIDE;
   void NotifyBeforeSVGGlyphPainted() MOZ_OVERRIDE;
   void NotifyAfterSVGGlyphPainted() MOZ_OVERRIDE;
   void NotifyAfterText() MOZ_OVERRIDE;
-  void NotifyBeforeSelectionBackground(nscolor aColor) MOZ_OVERRIDE;
-  void NotifySelectionBackgroundPathEmitted() MOZ_OVERRIDE;
   void NotifyBeforeDecorationLine(nscolor aColor) MOZ_OVERRIDE;
   void NotifyDecorationLinePathEmitted() MOZ_OVERRIDE;
   void NotifyBeforeSelectionDecorationLine(nscolor aColor) MOZ_OVERRIDE;
   void NotifySelectionDecorationLinePathEmitted() MOZ_OVERRIDE;
 
 private:
   void SetupContext();
 
@@ -2782,16 +2783,37 @@ private:
    * This color can be the special NS_SAME_AS_FOREGROUND_COLOR,
    * NS_40PERCENT_FOREGROUND_COLOR and NS_TRANSPARENT colors when we are
    * painting selections or IME decorations.
    */
   nscolor mColor;
 };
 
 void
+SVGTextDrawPathCallbacks::NotifySelectionBackgroundNeedsFill(
+                                                      const Rect& aBackgroundRect,
+                                                      nscolor aColor,
+                                                      DrawTarget& aDrawTarget)
+{
+  if (IsClipPathChild()) {
+    // Don't paint selection backgrounds when in a clip path.
+    return;
+  }
+
+  mColor = aColor; // currently needed by MakeFillPattern
+
+  GeneralPattern fillPattern;
+  MakeFillPattern(&fillPattern);
+  if (fillPattern.GetPattern()) {
+    DrawOptions drawOptions(aColor == NS_40PERCENT_FOREGROUND_COLOR ? 0.4 : 1.0);
+    aDrawTarget.FillRect(aBackgroundRect, fillPattern, drawOptions);
+  }
+}
+
+void
 SVGTextDrawPathCallbacks::NotifyBeforeText(nscolor aColor)
 {
   mColor = aColor;
   SetupContext();
   gfx->NewPath();
 }
 
 void
@@ -2816,51 +2838,16 @@ SVGTextDrawPathCallbacks::NotifyAfterSVG
 
 void
 SVGTextDrawPathCallbacks::NotifyAfterText()
 {
   gfx->Restore();
 }
 
 void
-SVGTextDrawPathCallbacks::NotifyBeforeSelectionBackground(nscolor aColor)
-{
-  if (IsClipPathChild()) {
-    // Don't paint selection backgrounds when in a clip path.
-    return;
-  }
-
-  mColor = aColor;
-  gfx->Save();
-}
-
-void
-SVGTextDrawPathCallbacks::NotifySelectionBackgroundPathEmitted()
-{
-  if (IsClipPathChild()) {
-    // Don't paint selection backgrounds when in a clip path.
-    return;
-  }
-
-  GeneralPattern fillPattern;
-  MakeFillPattern(&fillPattern);
-  if (fillPattern.GetPattern()) {
-    RefPtr<Path> path = gfx->GetPath();
-    FillRule fillRule = nsSVGUtils::ToFillRule(mFrame->StyleSVG()->mFillRule);
-    if (fillRule != path->GetFillRule()) {
-      RefPtr<PathBuilder> builder = path->CopyToBuilder(fillRule);
-      path = builder->Finish();
-    }
-    DrawOptions drawOptions(mColor == NS_40PERCENT_FOREGROUND_COLOR ? 0.4 : 1.0);
-    gfx->GetDrawTarget()->Fill(path, fillPattern, drawOptions);
-  }
-  gfx->Restore();
-}
-
-void
 SVGTextDrawPathCallbacks::NotifyBeforeDecorationLine(nscolor aColor)
 {
   mColor = aColor;
   SetupContext();
 }
 
 void
 SVGTextDrawPathCallbacks::NotifyDecorationLinePathEmitted()