Bug 1103623 - Port most remaining gfxContext::Fill() calls to Moz2D. r=mattwoodrow
authorJonathan Watt <jwatt@jwatt.org>
Mon, 24 Nov 2014 00:04:33 +0000
changeset 241345 e497957b79b228deef38b8c62bd4893093cb13df
parent 241344 4019b458cab756d7c8fddadccafa1fb089c0019c
child 241346 d2da8df5dd047f7b7631937e4a29173aea1af268
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1103623
milestone36.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 1103623 - Port most remaining gfxContext::Fill() calls to Moz2D. r=mattwoodrow
embedding/browser/nsWebBrowser.cpp
gfx/layers/ReadbackProcessor.cpp
gfx/thebes/gfxContext.cpp
gfx/thebes/gfxContext.h
layout/base/DisplayItemClip.cpp
layout/base/DisplayItemClip.h
layout/base/FrameLayerBuilder.cpp
layout/base/nsCSSRendering.cpp
layout/base/nsDisplayList.cpp
layout/generic/nsFrame.cpp
layout/mathml/nsMathMLChar.cpp
layout/mathml/nsMathMLChar.h
layout/mathml/nsMathMLmfracFrame.cpp
--- a/embedding/browser/nsWebBrowser.cpp
+++ b/embedding/browser/nsWebBrowser.cpp
@@ -5,16 +5,19 @@
 
 // Local Includes
 #include "nsWebBrowser.h"
 
 // Helper Classes
 #include "nsGfxCIID.h"
 #include "nsWidgetsCID.h"
 
+#include "gfxUtils.h"
+#include "mozilla/gfx/2D.h"
+
 //Interfaces Needed
 #include "nsReadableUtils.h"
 #include "nsIComponentManager.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMElement.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
@@ -46,16 +49,17 @@
 #include "nsIContentViewer.h"
 #endif
 
 // PSM2 includes
 #include "nsISecureBrowserUI.h"
 #include "nsXULAppAPI.h"
 
 using namespace mozilla;
+using namespace mozilla::gfx;
 using namespace mozilla::layers;
 
 static NS_DEFINE_CID(kChildCID, NS_CHILD_CID);
 
 
 //*****************************************************************************
 //***    nsWebBrowser: Object Management
 //*****************************************************************************
@@ -1645,22 +1649,23 @@ NS_IMETHODIMP nsWebBrowser::EnsureDocShe
 
 static void DrawPaintedLayer(PaintedLayer* aLayer,
                             gfxContext* aContext,
                             const nsIntRegion& aRegionToDraw,
                             DrawRegionClip aClip,
                             const nsIntRegion& aRegionToInvalidate,
                             void* aCallbackData)
 {
-  nscolor* color = static_cast<nscolor*>(aCallbackData);
-  aContext->NewPath();
-  aContext->SetColor(gfxRGBA(*color));
+  DrawTarget& aDrawTarget = *aContext->GetDrawTarget();
+
+  ColorPattern color(ToDeviceColor(*static_cast<nscolor*>(aCallbackData)));
   nsIntRect dirtyRect = aRegionToDraw.GetBounds();
-  aContext->Rectangle(gfxRect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height));
-  aContext->Fill();  
+  aDrawTarget.FillRect(Rect(dirtyRect.x, dirtyRect.y,
+                            dirtyRect.width, dirtyRect.height),
+                       color);
 }
 
 void nsWebBrowser::WindowRaised(nsIWidget* aWidget)
 {
 #if defined(DEBUG_smaug)
   nsCOMPtr<nsIDocument> document = mDocShell->GetDocument();
   nsAutoString documentURI;
   document->GetDocumentURI(documentURI);
--- a/gfx/layers/ReadbackProcessor.cpp
+++ b/gfx/layers/ReadbackProcessor.cpp
@@ -4,26 +4,30 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ReadbackProcessor.h"
 #include <sys/types.h>                  // for int32_t
 #include "Layers.h"                     // for Layer, PaintedLayer, etc
 #include "ReadbackLayer.h"              // for ReadbackLayer, ReadbackSink
 #include "gfxColor.h"                   // for gfxRGBA
 #include "gfxContext.h"                 // for gfxContext
+#include "gfxUtils.h"
 #include "gfxRect.h"                    // for gfxRect
+#include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/BasePoint.h"      // for BasePoint
 #include "mozilla/gfx/BaseRect.h"       // for BaseRect
 #include "nsAutoPtr.h"                  // for nsRefPtr, nsAutoPtr
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for gfxContext::Release, etc
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nsSize.h"                     // for nsIntSize
 
+using namespace mozilla::gfx;
+
 namespace mozilla {
 namespace layers {
 
 void
 ReadbackProcessor::BuildUpdates(ContainerLayer* aContainer)
 {
   NS_ASSERTION(mAllUpdates.IsEmpty(), "Some updates not processed?");
 
@@ -106,20 +110,20 @@ ReadbackProcessor::BuildUpdatesForLayer(
       aLayer->mBackgroundLayer = nullptr;
       aLayer->mBackgroundColor = colorLayer->GetColor();
       NS_ASSERTION(aLayer->mBackgroundColor.a == 1.0,
                    "Color layer said it was opaque!");
       nsRefPtr<gfxContext> ctx =
           aLayer->mSink->BeginUpdate(aLayer->GetRect(),
                                      aLayer->AllocateSequenceNumber());
       if (ctx) {
-        ctx->SetColor(aLayer->mBackgroundColor);
+        ColorPattern color(ToDeviceColor(aLayer->mBackgroundColor));
         nsIntSize size = aLayer->GetSize();
-        ctx->Rectangle(gfxRect(0, 0, size.width, size.height));
-        ctx->Fill();
+        ctx->GetDrawTarget()->FillRect(Rect(0, 0, size.width, size.height),
+                                       color);
         aLayer->mSink->EndUpdate(ctx, aLayer->GetRect());
       }
     }
   } else {
     NS_ASSERTION(newBackground->AsPaintedLayer(), "Must be PaintedLayer");
     PaintedLayer* paintedLayer = static_cast<PaintedLayer*>(newBackground);
     // updateRect is relative to the PaintedLayer
     nsIntRect updateRect = aLayer->GetRect() - offset;
--- a/gfx/thebes/gfxContext.cpp
+++ b/gfx/thebes/gfxContext.cpp
@@ -654,16 +654,25 @@ gfxContext::ResetClip()
   CurrentState().clipWasReset = true;
 }
 
 void
 gfxContext::UpdateSurfaceClip()
 {
 }
 
+void
+gfxContext::PopClip()
+{
+  MOZ_ASSERT(CurrentState().pushedClips.Length() > 0);
+
+  CurrentState().pushedClips.RemoveElementAt(CurrentState().pushedClips.Length() - 1);
+  mDT->PopClip();
+}
+
 gfxRect
 gfxContext::GetClipExtents()
 {
   Rect rect = GetAzureDeviceSpaceClipBounds();
 
   if (rect.width == 0 || rect.height == 0) {
     return gfxRect(0, 0, 0, 0);
   }
--- a/gfx/thebes/gfxContext.h
+++ b/gfx/thebes/gfxContext.h
@@ -462,16 +462,18 @@ public:
     /**
      * Helper functions that will create a rect path and call Clip().
      * Any current path will be destroyed by these functions!
      */
     void Clip(const Rect& rect);
     void Clip(const gfxRect& rect); // will clip to a rect
     void Clip(Path* aPath);
 
+    void PopClip();
+
     /**
      * This will ensure that the surface actually has its clip set.
      * Useful if you are doing native drawing.
      */
     void UpdateSurfaceClip();
 
     /**
      * This will return the current bounds of the clip region in user
--- a/layout/base/DisplayItemClip.cpp
+++ b/layout/base/DisplayItemClip.cpp
@@ -1,16 +1,18 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * 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/. */
 
 #include "DisplayItemClip.h"
 
 #include "gfxContext.h"
+#include "gfxUtils.h"
+#include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/PathHelpers.h"
 #include "nsPresContext.h"
 #include "nsCSSRendering.h"
 #include "nsLayoutUtils.h"
 #include "nsRegion.h"
 
 using namespace mozilla::gfx;
 
@@ -113,34 +115,44 @@ DisplayItemClip::ApplyRoundedRectClipsTo
   for (uint32_t i = aBegin; i < aEnd; ++i) {
     RefPtr<Path> roundedRect =
       MakeRoundedRectPath(aDrawTarget, A2D, mRoundedClipRects[i]);
     aContext->Clip(roundedRect);
   }
 }
 
 void
-DisplayItemClip::DrawRoundedRectsTo(gfxContext* aContext,
-                                    int32_t A2D,
-                                    uint32_t aBegin, uint32_t aEnd) const
+DisplayItemClip::FillIntersectionOfRoundedRectClips(gfxContext* aContext,
+                                                    const Color& aColor,
+                                                    int32_t aAppUnitsPerDevPixel,
+                                                    uint32_t aBegin,
+                                                    uint32_t aEnd) const
 {
   DrawTarget& aDrawTarget = *aContext->GetDrawTarget();
 
   aEnd = std::min<uint32_t>(aEnd, mRoundedClipRects.Length());
 
-  if (aEnd - aBegin == 0)
+  if (aBegin >= aEnd) {
     return;
+  }
+
+  // Push clips for any rects that come BEFORE the rect at |aEnd - 1|, if any:
+  ApplyRoundedRectClipsTo(aContext, aAppUnitsPerDevPixel, aBegin, aEnd - 1);
 
-  // If there is just one rounded rect we can just fill it, if there are more then we
-  // must clip the rest to get the intersection of clips
-  ApplyRoundedRectClipsTo(aContext, A2D, aBegin, aEnd - 1);
-  RefPtr<Path> roundedRect =
-    MakeRoundedRectPath(aDrawTarget, A2D, mRoundedClipRects[aEnd - 1]);
-  aContext->SetPath(roundedRect);
-  aContext->Fill();
+  // Now fill the rect at |aEnd - 1|:
+  RefPtr<Path> roundedRect = MakeRoundedRectPath(aDrawTarget,
+                                                 aAppUnitsPerDevPixel,
+                                                 mRoundedClipRects[aEnd - 1]);
+  ColorPattern color(ToDeviceColor(aColor));
+  aDrawTarget.Fill(roundedRect, color);
+
+  // Finally, pop any clips that we may have pushed:
+  for (uint32_t i = aBegin; i < aEnd - 1; ++i) {
+    aContext->PopClip();
+  }
 }
 
 TemporaryRef<Path>
 DisplayItemClip::MakeRoundedRectPath(DrawTarget& aDrawTarget,
                                      int32_t A2D,
                                      const RoundedRect &aRoundRect) const
 {
   RectCornerRadii pixelRadii;
--- a/layout/base/DisplayItemClip.h
+++ b/layout/base/DisplayItemClip.h
@@ -27,16 +27,17 @@ namespace mozilla {
 
 /**
  * An DisplayItemClip represents the intersection of an optional rectangle
  * with a list of rounded rectangles (which is often empty), all in appunits.
  * It can represent everything CSS clipping can do to an element (except for
  * SVG clip-path), including no clipping at all.
  */
 class DisplayItemClip {
+  typedef mozilla::gfx::Color Color;
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::gfx::Path Path;
 
 public:
   struct RoundedRect {
     nsRect mRect;
     // Indices into mRadii are the NS_CORNER_* constants in nsStyleConsts.h
     nscoord mRadii[8];
@@ -80,18 +81,21 @@ public:
   void ApplyRectTo(gfxContext* aContext, int32_t A2D) const;
   // Applies the rounded rects in this Clip to aContext
   // Will only apply rounded rects from aBegin (inclusive) to aEnd
   // (exclusive) or the number of rounded rects, whichever is smaller.
   void ApplyRoundedRectClipsTo(gfxContext* aContext, int32_t A2DPRInt32,
                                uint32_t aBegin, uint32_t aEnd) const;
 
   // Draw (fill) the rounded rects in this clip to aContext
-  void DrawRoundedRectsTo(gfxContext* aContext, int32_t A2D,
-                          uint32_t aBegin, uint32_t aEnd) const;
+  void FillIntersectionOfRoundedRectClips(gfxContext* aContext,
+                                          const Color& aColor,
+                                          int32_t aAppUnitsPerDevPixel,
+                                          uint32_t aBegin,
+                                          uint32_t aEnd) const;
   // 'Draw' (create as a path, does not stroke or fill) aRoundRect to aContext
   mozilla::TemporaryRef<Path> MakeRoundedRectPath(DrawTarget& aDrawTarget,
                                                   int32_t A2D,
                                                   const RoundedRect &aRoundRect) const;
 
   // Returns true if the intersection of aRect and this clip region is
   // non-empty. This is precise for DisplayItemClips with at most one
   // rounded rectangle. When multiple rounded rectangles are present, we just
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -4405,24 +4405,24 @@ static bool ShouldDrawRectsSeparately(gf
       aClip == DrawRegionClip::NONE) {
     return false;
   }
 
   DrawTarget *dt = aContext->GetDrawTarget();
   return !dt->SupportsRegionClipping();
 }
 
-static void DrawForcedBackgroundColor(gfxContext* aContext, Layer* aLayer, nscolor aBackgroundColor)
+static void DrawForcedBackgroundColor(DrawTarget& aDrawTarget,
+                                      Layer* aLayer, nscolor
+                                      aBackgroundColor)
 {
   if (NS_GET_A(aBackgroundColor) > 0) {
     nsIntRect r = aLayer->GetVisibleRegion().GetBounds();
-    aContext->NewPath();
-    aContext->Rectangle(gfxRect(r.x, r.y, r.width, r.height));
-    aContext->SetColor(gfxRGBA(aBackgroundColor));
-    aContext->Fill();
+    ColorPattern color(ToDeviceColor(aBackgroundColor));
+    aDrawTarget.FillRect(Rect(r.x, r.y, r.width, r.height), color);
   }
 }
 
 /*
  * A note on residual transforms:
  *
  * In a transformed subtree we sometimes apply the PaintedLayer's
  * "residual transform" when drawing content into the PaintedLayer.
@@ -4452,16 +4452,18 @@ static void DrawForcedBackgroundColor(gf
 /* static */ void
 FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer,
                                    gfxContext* aContext,
                                    const nsIntRegion& aRegionToDraw,
                                    DrawRegionClip aClip,
                                    const nsIntRegion& aRegionToInvalidate,
                                    void* aCallbackData)
 {
+  DrawTarget& aDrawTarget = *aContext->GetDrawTarget();
+
   PROFILER_LABEL("FrameLayerBuilder", "DrawPaintedLayer",
     js::ProfileEntry::Category::GRAPHICS);
 
   nsDisplayListBuilder* builder = static_cast<nsDisplayListBuilder*>
     (aCallbackData);
 
   FrameLayerBuilder *layerBuilder = aLayer->Manager()->GetLayerBuilder();
   NS_ASSERTION(layerBuilder, "Unexpectedly null layer builder!");
@@ -4483,17 +4485,18 @@ FrameLayerBuilder::DrawPaintedLayer(Pain
 
   bool shouldDrawRectsSeparately = ShouldDrawRectsSeparately(aContext, aClip);
 
   if (!shouldDrawRectsSeparately) {
     if (aClip == DrawRegionClip::DRAW) {
       gfxUtils::ClipToRegion(aContext, aRegionToDraw);
     }
 
-    DrawForcedBackgroundColor(aContext, aLayer, userData->mForcedBackgroundColor);
+    DrawForcedBackgroundColor(aDrawTarget, aLayer,
+                              userData->mForcedBackgroundColor);
   }
 
   if (NS_GET_A(userData->mFontSmoothingBackgroundColor) > 0) {
     aContext->SetFontSmoothingBackgroundColor(
       Color::FromABGR(userData->mFontSmoothingBackgroundColor));
   }
 
   // make the origin of the context coincide with the origin of the
@@ -4517,17 +4520,18 @@ FrameLayerBuilder::DrawPaintedLayer(Pain
   if (shouldDrawRectsSeparately) {
     nsIntRegionRectIterator it(aRegionToDraw);
     while (const nsIntRect* iterRect = it.Next()) {
       gfxContextAutoSaveRestore save(aContext);
       aContext->NewPath();
       aContext->Rectangle(*iterRect);
       aContext->Clip();
 
-      DrawForcedBackgroundColor(aContext, aLayer, userData->mForcedBackgroundColor);
+      DrawForcedBackgroundColor(aDrawTarget, aLayer,
+                                userData->mForcedBackgroundColor);
 
       // Apply the residual transform if it has been enabled, to ensure that
       // snapping when we draw into aContext exactly matches the ideal transform.
       // See above for why this is OK.
       aContext->SetMatrix(
         aContext->CurrentMatrix().Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y)).
                                   Scale(userData->mXScale, userData->mYScale));
 
@@ -4715,21 +4719,21 @@ ContainerState::SetupMaskLayer(Layer *aL
       SetClipCount(paintedData, 0);
       return;
     }
 
     nsRefPtr<gfxContext> context = new gfxContext(dt);
     context->Multiply(ThebesMatrix(imageTransform));
 
     // paint the clipping rects with alpha to create the mask
-    context->SetColor(gfxRGBA(1, 1, 1, 1));
-    aClip.DrawRoundedRectsTo(context,
-                             newData.mAppUnitsPerDevPixel,
-                             0,
-                             aRoundedRectClipCount);
+    aClip.FillIntersectionOfRoundedRectClips(context,
+                                             Color(1.f, 1.f, 1.f, 1.f),
+                                             newData.mAppUnitsPerDevPixel,
+                                             0,
+                                             aRoundedRectClipCount);
 
     RefPtr<SourceSurface> surface = dt->Snapshot();
 
     // build the image and container
     container = aLayer->Manager()->CreateImageContainer();
     NS_ASSERTION(container, "Could not create image container for mask layer.");
     nsRefPtr<Image> image = container->CreateImage(ImageFormat::CAIRO_SURFACE);
     NS_ASSERTION(image, "Could not create image container for mask layer.");
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -627,16 +627,18 @@ nsCSSRendering::PaintBorderWithStyleBord
                                            nsRenderingContext& aRenderingContext,
                                            nsIFrame* aForFrame,
                                            const nsRect& aDirtyRect,
                                            const nsRect& aBorderArea,
                                            const nsStyleBorder& aStyleBorder,
                                            nsStyleContext* aStyleContext,
                                            Sides aSkipSides)
 {
+  DrawTarget& aDrawTarget = *aRenderingContext.GetDrawTarget();
+
   PrintAsStringNewline("++ PaintBorder");
 
   // Check to see if we have an appearance defined.  If so, we let the theme
   // renderer draw the border.  DO not get the data from aForFrame, since the passed in style context
   // may be different!  Always use |aStyleContext|!
   const nsStyleDisplay* displayData = aStyleContext->StyleDisplay();
   if (displayData->mAppearance) {
     nsITheme *theme = aPresContext->GetTheme();
@@ -687,17 +689,17 @@ nsCSSRendering::PaintBorderWithStyleBord
       // No need for a clip, just skip the sides we don't want.
       border.ApplySkipSides(aSkipSides);
     } else {
       // We're drawing borders around the joined continuation boxes so we need
       // to clip that to the slice that we want for this frame.
       aRenderingContext.ThebesContext()->
         Clip(NSRectToSnappedRect(aBorderArea,
                                  aForFrame->PresContext()->AppUnitsPerDevPixel(),
-                                 *aRenderingContext.GetDrawTarget()));
+                                 aDrawTarget));
     }
   } else {
     MOZ_ASSERT(joinedBorderArea.IsEqualEdges(aBorderArea),
                "Should use aBorderArea for box-decoration-break:clone");
     MOZ_ASSERT(aForFrame->GetSkipSides().IsEmpty(),
                "Should not skip sides for box-decoration-break:clone except "
                "::first-letter/line continuations or other frame types that "
                "don't have borders but those shouldn't reach this point.");
@@ -726,24 +728,21 @@ nsCSSRendering::PaintBorderWithStyleBord
       borderColors[i] = ourColor->mColor;
   }
 
   PrintAsFormatString(" borderStyles: %d %d %d %d\n", borderStyles[0], borderStyles[1], borderStyles[2], borderStyles[3]);
   //PrintAsFormatString ("bgRadii: %f %f %f %f\n", bgRadii[0], bgRadii[1], bgRadii[2], bgRadii[3]);
 
 #if 0
   // this will draw a transparent red backround underneath the border area
-  ctx->Save();
-  ctx->Rectangle(ThebesRect(joinedBorderAreaPx));
-  ctx->SetColor(gfxRGBA(1.0, 0.0, 0.0, 0.5));
-  ctx->Fill();
-  ctx->Restore();
+  ColorPattern color(ToDeviceColor(Color(1.f, 0.f, 0.f, 0.5f)));
+  aDrawTarget.FillRect(joinedBorderAreaPx, color);
 #endif
 
-  nsCSSBorderRenderer br(ctx->GetDrawTarget(),
+  nsCSSBorderRenderer br(&aDrawTarget,
                          joinedBorderAreaPx,
                          borderStyles,
                          borderWidths,
                          bgRadii,
                          borderColors,
                          compositeColors,
                          bgColor);
   br.DrawBorders();
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2806,30 +2806,29 @@ nsDisplayBackgroundColor::ApplyOpacity(n
   }
   return true;
 }
 
 void
 nsDisplayBackgroundColor::Paint(nsDisplayListBuilder* aBuilder,
                                 nsRenderingContext* aCtx)
 {
+  DrawTarget& aDrawTarget = *aCtx->GetDrawTarget();
+
   if (mColor == NS_RGBA(0, 0, 0, 0)) {
     return;
   }
 
-  gfxContext* ctx = aCtx->ThebesContext();
   nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
 
-  gfxRect bounds =
-    nsLayoutUtils::RectToGfxRect(borderBox, mFrame->PresContext()->AppUnitsPerDevPixel());
-
-  ctx->SetColor(mColor);
-  ctx->NewPath();
-  ctx->Rectangle(bounds, true);
-  ctx->Fill();
+  Rect rect = NSRectToSnappedRect(borderBox,
+                                  mFrame->PresContext()->AppUnitsPerDevPixel(),
+                                  aDrawTarget);
+  ColorPattern color(ToDeviceColor(mColor));
+  aDrawTarget.FillRect(rect, color);
 }
 
 nsRegion
 nsDisplayBackgroundColor::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                           bool* aSnap)
 {
   if (mColor.a != 1) {
     return nsRegion();
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -10,16 +10,17 @@
 
 #include <stdarg.h>
 #include <algorithm>
 
 #include "gfxUtils.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/gfx/2D.h"
+#include "mozilla/gfx/PathHelpers.h"
 
 #include "nsCOMPtr.h"
 #include "nsFrameList.h"
 #include "nsPlaceholderFrame.h"
 #include "nsIContent.h"
 #include "nsContentUtils.h"
 #include "nsIAtom.h"
 #include "nsString.h"
@@ -1458,38 +1459,37 @@ public:
   NS_DISPLAY_DECL_NAME("SelectionOverlay", TYPE_SELECTION_OVERLAY)
 private:
   int16_t mSelectionValue;
 };
 
 void nsDisplaySelectionOverlay::Paint(nsDisplayListBuilder* aBuilder,
                                       nsRenderingContext* aCtx)
 {
+  DrawTarget& aDrawTarget = *aCtx->GetDrawTarget();
+
   LookAndFeel::ColorID colorID;
   if (mSelectionValue == nsISelectionController::SELECTION_ON) {
     colorID = LookAndFeel::eColorID_TextSelectBackground;
   } else if (mSelectionValue == nsISelectionController::SELECTION_ATTENTION) {
     colorID = LookAndFeel::eColorID_TextSelectBackgroundAttention;
   } else {
     colorID = LookAndFeel::eColorID_TextSelectBackgroundDisabled;
   }
 
-  nscolor color = LookAndFeel::GetColor(colorID, NS_RGB(255, 255, 255));
-
-  gfxRGBA c(color);
+  Color c = Color::FromABGR(LookAndFeel::GetColor(colorID, NS_RGB(255, 255, 255)));
   c.a = .5;
-
-  gfxContext *ctx = aCtx->ThebesContext();
-  ctx->SetColor(c);
+  ColorPattern color(ToDeviceColor(c));
 
   nsIntRect pxRect =
     mVisibleRect.ToOutsidePixels(mFrame->PresContext()->AppUnitsPerDevPixel());
-  ctx->NewPath();
-  ctx->Rectangle(gfxRect(pxRect.x, pxRect.y, pxRect.width, pxRect.height), true);
-  ctx->Fill();
+  Rect rect(pxRect.x, pxRect.y, pxRect.width, pxRect.height);
+  MaybeSnapToDevicePixels(rect, aDrawTarget);
+
+  aDrawTarget.FillRect(rect, color);
 }
 
 /********************************************************
 * Refreshes each content's frame
 *********************************************************/
 
 void
 nsFrame::DisplaySelectionOverlay(nsDisplayListBuilder*   aBuilder,
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -2114,19 +2114,19 @@ nsMathMLChar::PaintForeground(nsPresCont
         mGlyphs[0]->Draw(thebesContext, gfxPoint(0.0, mUnscaledAscent),
                          DrawMode::GLYPH_FILL, 0, mGlyphs[0]->GetLength(),
                          nullptr, nullptr, nullptr);
       }
       break;
     case DRAW_PARTS: {
       // paint by parts
       if (NS_STRETCH_DIRECTION_VERTICAL == mDirection)
-        PaintVertically(aPresContext, thebesContext, r);
+        PaintVertically(aPresContext, thebesContext, r, fgColor);
       else if (NS_STRETCH_DIRECTION_HORIZONTAL == mDirection)
-        PaintHorizontally(aPresContext, thebesContext, r);
+        PaintHorizontally(aPresContext, thebesContext, r, fgColor);
       break;
     }
     default:
       NS_NOTREACHED("Unknown drawing method");
       break;
   }
 
   thebesContext->Restore();
@@ -2162,32 +2162,35 @@ SnapToDevPixels(const gfxContext* aThebe
   pt = aThebesContext->UserToDevice(pt);
   pt.Round();
   pt = aThebesContext->DeviceToUser(pt);
   return nsPoint(NSFloatPixelsToAppUnits(pt.x, aAppUnitsPerGfxUnit),
                  NSFloatPixelsToAppUnits(pt.y, aAppUnitsPerGfxUnit));
 }
 
 static void
-PaintRule(gfxContext* aThebesContext,
+PaintRule(DrawTarget& aDrawTarget,
           int32_t     aAppUnitsPerGfxUnit,
-          nsRect&     aRect)
+          nsRect&     aRect,
+          nscolor     aColor)
 {
-  aThebesContext->NewPath();
-  gfxRect rect = nsLayoutUtils::RectToGfxRect(aRect, aAppUnitsPerGfxUnit);
-  aThebesContext->SnappedRectangle(rect);
-  aThebesContext->Fill();
+  Rect rect = NSRectToSnappedRect(aRect, aAppUnitsPerGfxUnit, aDrawTarget);
+  ColorPattern color(ToDeviceColor(aColor));
+  aDrawTarget.FillRect(rect, color);
 }
 
 // paint a stretchy char by assembling glyphs vertically
 nsresult
 nsMathMLChar::PaintVertically(nsPresContext* aPresContext,
                               gfxContext*    aThebesContext,
-                              nsRect&        aRect)
+                              nsRect&        aRect,
+                              nscolor        aColor)
 {
+  DrawTarget& aDrawTarget = *aThebesContext->GetDrawTarget();
+
   // Get the device pixel size in the vertical direction.
   // (This makes no effort to optimize for non-translation transformations.)
   nscoord oneDevPixel = aPresContext->AppUnitsPerDevPixel();
 
   // get metrics data to be re-used later
   int32_t i = 0;
   nscoord dx = aRect.x;
   nscoord offset[3], start[3], end[3];
@@ -2301,17 +2304,17 @@ nsMathMLChar::PaintVertically(nsPresCont
       }
       else {
         NS_ERROR("Cannot stretch - All parts missing");
         return NS_ERROR_UNEXPECTED;
       }
       // paint the rule between the parts
       nsRect rule(aRect.x + lbearing, end[first],
                   rbearing - lbearing, start[last] - end[first]);
-      PaintRule(aThebesContext, oneDevPixel, rule);
+      PaintRule(aDrawTarget, oneDevPixel, rule, aColor);
       first = last;
       last++;
     }
   }
   else if (mBmData[3].ascent + mBmData[3].descent > 0) {
     // glue is present
     nsBoundingMetrics& bm = mBmData[3];
     // Ensure the stride for the glue is not reduced to less than one pixel
@@ -2350,18 +2353,21 @@ nsMathMLChar::PaintVertically(nsPresCont
 #endif
   return NS_OK;
 }
 
 // paint a stretchy char by assembling glyphs horizontally
 nsresult
 nsMathMLChar::PaintHorizontally(nsPresContext* aPresContext,
                                 gfxContext*    aThebesContext,
-                                nsRect&        aRect)
+                                nsRect&        aRect,
+                                nscolor        aColor)
 {
+  DrawTarget& aDrawTarget = *aThebesContext->GetDrawTarget();
+
   // Get the device pixel size in the horizontal direction.
   // (This makes no effort to optimize for non-translation transformations.)
   nscoord oneDevPixel = aPresContext->AppUnitsPerDevPixel();
 
   // get metrics data to be re-used later
   int32_t i = 0;
   nscoord dy = aRect.y + mBoundingMetrics.ascent;
   nscoord offset[3], start[3], end[3];
@@ -2468,17 +2474,17 @@ nsMathMLChar::PaintHorizontally(nsPresCo
       }
       else {
         NS_ERROR("Cannot stretch - All parts missing");
         return NS_ERROR_UNEXPECTED;
       }
       // paint the rule between the parts
       nsRect rule(end[first], dy - ascent,
                   start[last] - end[first], ascent + descent);
-      PaintRule(aThebesContext, oneDevPixel, rule);
+      PaintRule(aDrawTarget, oneDevPixel, rule, aColor);
       first = last;
       last++;
     }
   }
   else if (mBmData[3].rightBearing - mBmData[3].leftBearing > 0) {
     // glue is present
     nsBoundingMetrics& bm = mBmData[3];
     // Ensure the stride for the glue is not reduced to less than one pixel
--- a/layout/mathml/nsMathMLChar.h
+++ b/layout/mathml/nsMathMLChar.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 nsMathMLChar_h___
 #define nsMathMLChar_h___
 
 #include "nsAutoPtr.h"
+#include "nsColor.h"
 #include "nsMathMLOperators.h"
 #include "nsPoint.h"
 #include "nsRect.h"
 #include "nsString.h"
 #include "nsBoundingMetrics.h"
 #include "gfxFont.h"
 
 class nsGlyphTable;
@@ -253,21 +254,23 @@ private:
                   nsBoundingMetrics&       aDesiredStretchSize,
                   uint32_t                 aStretchHint,
                   float           aMaxSize = NS_MATHML_OPERATOR_SIZE_INFINITY,
                   bool            aMaxSizeIsAbsolute = false);
 
   nsresult
   PaintVertically(nsPresContext* aPresContext,
                   gfxContext*    aThebesContext,
-                  nsRect&        aRect);
+                  nsRect&        aRect,
+                  nscolor        aColor);
 
   nsresult
   PaintHorizontally(nsPresContext* aPresContext,
                     gfxContext*    aThebesContext,
-                    nsRect&        aRect);
+                    nsRect&        aRect,
+                    nscolor        aColor);
 
   void
   ApplyTransforms(gfxContext* aThebesContext, int32_t aAppUnitsPerGfxUnit,
                   nsRect &r);
 };
 
 #endif /* nsMathMLChar_h___ */
--- a/layout/mathml/nsMathMLmfracFrame.cpp
+++ b/layout/mathml/nsMathMLmfracFrame.cpp
@@ -1,22 +1,30 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 
 #include "nsMathMLmfracFrame.h"
+
+#include "gfxUtils.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/RefPtr.h"
+#include "nsLayoutUtils.h"
 #include "nsPresContext.h"
 #include "nsRenderingContext.h"
 #include "nsDisplayList.h"
 #include "gfxContext.h"
 #include "nsMathMLElement.h"
 #include <algorithm>
 
+using namespace mozilla;
+using namespace mozilla::gfx;
+
 //
 // <mfrac> -- form a fraction from two subexpressions - implementation
 //
 
 // various fraction line thicknesses (multiplicative values of the default rule thickness)
 
 #define THIN_FRACTION_LINE                   0.5f
 #define THIN_FRACTION_LINE_MINIMUM_PIXELS    1  // minimum of 1 pixel
@@ -597,42 +605,42 @@ private:
   nsRect    mRect;
   nscoord   mThickness;
   bool      mRTL;
 };
 
 void nsDisplayMathMLSlash::Paint(nsDisplayListBuilder* aBuilder,
                                  nsRenderingContext* aCtx)
 {
+  DrawTarget& aDrawTarget = *aCtx->GetDrawTarget();
+
   // get the gfxRect
   nsPresContext* presContext = mFrame->PresContext();
-  gfxRect rect = presContext->AppUnitsToGfxUnits(mRect + ToReferenceFrame());
+  Rect rect = NSRectToRect(mRect + ToReferenceFrame(),
+                           presContext->AppUnitsPerDevPixel());
   
-  // paint with the current text color
-  aCtx->ThebesContext()->SetColor(mFrame->GetVisitedDependentColor(eCSSProperty_color));
+  ColorPattern color(ToDeviceColor(
+                       mFrame->GetVisitedDependentColor(eCSSProperty_color)));
  
   // draw the slash as a parallelogram 
-  gfxContext *gfxCtx = aCtx->ThebesContext();
-  gfxPoint delta = gfxPoint(presContext->AppUnitsToGfxUnits(mThickness), 0);
-  gfxCtx->NewPath();
-
+  Point delta = Point(presContext->AppUnitsToGfxUnits(mThickness), 0);
+  RefPtr<PathBuilder> builder = aDrawTarget.CreatePathBuilder();
   if (mRTL) {
-    gfxCtx->MoveTo(rect.TopLeft());
-    gfxCtx->LineTo(rect.TopLeft() + delta);
-    gfxCtx->LineTo(rect.BottomRight());
-    gfxCtx->LineTo(rect.BottomRight() - delta);
+    builder->MoveTo(rect.TopLeft());
+    builder->LineTo(rect.TopLeft() + delta);
+    builder->LineTo(rect.BottomRight());
+    builder->LineTo(rect.BottomRight() - delta);
   } else {
-    gfxCtx->MoveTo(rect.BottomLeft());
-    gfxCtx->LineTo(rect.BottomLeft() + delta);
-    gfxCtx->LineTo(rect.TopRight());
-    gfxCtx->LineTo(rect.TopRight() - delta);
+    builder->MoveTo(rect.BottomLeft());
+    builder->LineTo(rect.BottomLeft() + delta);
+    builder->LineTo(rect.TopRight());
+    builder->LineTo(rect.TopRight() - delta);
   }
-
-  gfxCtx->ClosePath();
-  gfxCtx->Fill();
+  RefPtr<Path> path = builder->Finish();
+  aDrawTarget.Fill(path, color);
 }
 
 void
 nsMathMLmfracFrame::DisplaySlash(nsDisplayListBuilder* aBuilder,
                                  nsIFrame* aFrame, const nsRect& aRect,
                                  nscoord aThickness,
                                  const nsDisplayListSet& aLists) {
   if (!aFrame->StyleVisibility()->IsVisible() || aRect.IsEmpty())