Backed out 2 changesets (bug 878032) because of Windows build bustage
authorEhsan Akhgari <ehsan@mozilla.com>
Wed, 19 Jun 2013 17:35:21 -0400
changeset 135707 5b3196ad66f40b7ca578461155f279fa0c6fca8e
parent 135706 72a95da7099f2c843131be85109815b54f676d07
child 135708 f0380ec657f82a13f37732d1b4c8d99d99c2ce78
push idunknown
push userunknown
push dateunknown
bugs878032
milestone24.0a1
backs out3cb61a7d57461117b4140c10c1c0cfcff5c3d0bd
627c03f469d882f08cb0d4a2c557d1e0396ea2d1
Backed out 2 changesets (bug 878032) because of Windows build bustage Backed out changeset 3cb61a7d5746 (bug 878032) Backed out changeset 627c03f469d8 (bug 878032) Landed on a CLOSED TREE
gfx/2d/BaseRect.h
gfx/2d/DrawTargetD2D.cpp
gfx/2d/DrawTargetD2D.h
gfx/2d/HelpersD2D.h
gfx/2d/PathD2D.cpp
gfx/2d/unittest/TestDrawTargetBase.cpp
--- a/gfx/2d/BaseRect.h
+++ b/gfx/2d/BaseRect.h
@@ -84,20 +84,20 @@ struct BaseRect {
   }
   // Returns the rectangle containing the intersection of the points
   // (including edges) of *this and aRect. If there are no points in that
   // intersection, returns an empty rectangle with x/y set to the std::max of the x/y
   // of *this and aRect.
   Sub Intersect(const Sub& aRect) const
   {
     Sub result;
-    result.x = std::max<T>(x, aRect.x);
-    result.y = std::max<T>(y, aRect.y);
-    result.width = std::min<T>(XMost(), aRect.XMost()) - result.x;
-    result.height = std::min<T>(YMost(), aRect.YMost()) - result.y;
+    result.x = std::max(x, aRect.x);
+    result.y = std::max(y, aRect.y);
+    result.width = std::min(XMost(), aRect.XMost()) - result.x;
+    result.height = std::min(YMost(), aRect.YMost()) - result.y;
     if (result.width < 0 || result.height < 0) {
       result.SizeTo(0, 0);
     }
     return result;
   }
   // Sets *this to be the rectangle containing the intersection of the points
   // (including edges) of *this and aRect. If there are no points in that
   // intersection, sets *this to be an empty rectangle with x/y set to the std::max
--- a/gfx/2d/DrawTargetD2D.cpp
+++ b/gfx/2d/DrawTargetD2D.cpp
@@ -108,17 +108,17 @@ public:
       // clipping information.
       RefPtr<ID2D1RectangleGeometry> rectGeom;
       factory()->CreateRectangleGeometry(D2D1::Rect(Float(clipBounds.x),
                                                     Float(clipBounds.y),
                                                     Float(clipBounds.XMost()),
                                                     Float(clipBounds.YMost())),
                                          byRef(rectGeom));
 
-      mClippedArea = IntersectGeometry(mClippedArea, rectGeom);
+      mClippedArea = mDT->Intersect(mClippedArea, rectGeom);
     }
   }
 
   ID2D1Factory *factory() { return mDT->factory(); }
 
   ~AutoSaveRestoreClippedOut()
   {
     if (!mOldSurfBitmap) {
@@ -157,21 +157,16 @@ private:
 
   // If we have an operator unbound by the source, this will contain a bitmap
   // with the old dest surface data.
   RefPtr<ID2D1Bitmap> mOldSurfBitmap;
   // This contains the area drawing is clipped to.
   RefPtr<ID2D1Geometry> mClippedArea;
 };
 
-ID2D1Factory *D2DFactory()
-{
-  return DrawTargetD2D::factory();
-}
-
 DrawTargetD2D::DrawTargetD2D()
   : mCurrentCachedLayer(0)
   , mClipsArePushed(false)
   , mPrivateData(nullptr)
 {
 }
 
 DrawTargetD2D::~DrawTargetD2D()
@@ -1722,16 +1717,50 @@ DrawTargetD2D::FinalizeRTForOperation(Co
   }
 
   mDevice->OMSetBlendState(GetBlendStateForOperator(aOperator), nullptr, 0xffffffff);
   
   SetScissorToRect(nullptr);
   mDevice->Draw(4, 0);
 }
 
+TemporaryRef<ID2D1Geometry>
+DrawTargetD2D::ConvertRectToGeometry(const D2D1_RECT_F& aRect)
+{
+  RefPtr<ID2D1RectangleGeometry> rectGeom;
+  factory()->CreateRectangleGeometry(&aRect, byRef(rectGeom));
+  return rectGeom.forget();
+}
+
+TemporaryRef<ID2D1Geometry>
+DrawTargetD2D::GetTransformedGeometry(ID2D1Geometry *aGeometry, const D2D1_MATRIX_3X2_F &aTransform)
+{
+  RefPtr<ID2D1PathGeometry> tmpGeometry;
+  factory()->CreatePathGeometry(byRef(tmpGeometry));
+  RefPtr<ID2D1GeometrySink> currentSink;
+  tmpGeometry->Open(byRef(currentSink));
+  aGeometry->Simplify(D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
+                      aTransform, currentSink);
+  currentSink->Close();
+  return tmpGeometry;
+}
+
+TemporaryRef<ID2D1Geometry>
+DrawTargetD2D::Intersect(ID2D1Geometry *aGeometryA, ID2D1Geometry *aGeometryB)
+{
+  RefPtr<ID2D1PathGeometry> pathGeom;
+  factory()->CreatePathGeometry(byRef(pathGeom));
+  RefPtr<ID2D1GeometrySink> sink;
+  pathGeom->Open(byRef(sink));
+  aGeometryA->CombineWithGeometry(aGeometryB, D2D1_COMBINE_MODE_INTERSECT, nullptr, sink);
+  sink->Close();
+
+  return pathGeom;
+}
+
 static D2D1_RECT_F
 IntersectRect(const D2D1_RECT_F& aRect1, const D2D1_RECT_F& aRect2)
 {
   D2D1_RECT_F result;
   result.left = max(aRect1.left, aRect2.left);
   result.top = max(aRect1.top, aRect2.top);
   result.right = min(aRect1.right, aRect2.right);
   result.bottom = min(aRect1.bottom, aRect2.bottom);
@@ -2257,17 +2286,17 @@ DrawTargetD2D::CreateBrushForPattern(con
     default:
       {
         RefPtr<DataSourceSurface> dataSurf = pat->mSurface->GetDataSurface();
         if (!dataSurf) {
           gfxWarning() << "Invalid surface type.";
           return nullptr;
         }
 
-        bitmap = CreatePartialBitmapForSurface(dataSurf, mTransform, mSize, pat->mExtendMode, mat, mRT); 
+        bitmap = CreatePartialBitmapForSurface(dataSurf, mat, pat->mExtendMode); 
         if (!bitmap) {
           return nullptr;
         }
       }
       break;
     }
     
     mRT->CreateBitmapBrush(bitmap,
@@ -2279,16 +2308,90 @@ DrawTargetD2D::CreateBrushForPattern(con
 
     return bmBrush;
   }
 
   gfxWarning() << "Invalid pattern type detected.";
   return nullptr;
 }
 
+TemporaryRef<ID2D1StrokeStyle>
+DrawTargetD2D::CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions)
+{
+  RefPtr<ID2D1StrokeStyle> style;
+
+  D2D1_CAP_STYLE capStyle;
+  D2D1_LINE_JOIN joinStyle;
+
+  switch (aStrokeOptions.mLineCap) {
+  case CAP_BUTT:
+    capStyle = D2D1_CAP_STYLE_FLAT;
+    break;
+  case CAP_ROUND:
+    capStyle = D2D1_CAP_STYLE_ROUND;
+    break;
+  case CAP_SQUARE:
+    capStyle = D2D1_CAP_STYLE_SQUARE;
+    break;
+  }
+
+  switch (aStrokeOptions.mLineJoin) {
+  case JOIN_MITER:
+    joinStyle = D2D1_LINE_JOIN_MITER;
+    break;
+  case JOIN_MITER_OR_BEVEL:
+    joinStyle = D2D1_LINE_JOIN_MITER_OR_BEVEL;
+    break;
+  case JOIN_ROUND:
+    joinStyle = D2D1_LINE_JOIN_ROUND;
+    break;
+  case JOIN_BEVEL:
+    joinStyle = D2D1_LINE_JOIN_BEVEL;
+    break;
+  }
+
+
+  HRESULT hr;
+  if (aStrokeOptions.mDashPattern) {
+    typedef vector<Float> FloatVector;
+    // D2D "helpfully" multiplies the dash pattern by the line width.
+    // That's not what cairo does, or is what <canvas>'s dash wants.
+    // So fix the multiplication in advance.
+    Float lineWidth = aStrokeOptions.mLineWidth;
+    FloatVector dash(aStrokeOptions.mDashPattern,
+                     aStrokeOptions.mDashPattern + aStrokeOptions.mDashLength);
+    for (FloatVector::iterator it = dash.begin(); it != dash.end(); ++it) {
+      *it /= lineWidth;
+    }
+
+    hr = factory()->CreateStrokeStyle(
+      D2D1::StrokeStyleProperties(capStyle, capStyle,
+                                  capStyle, joinStyle,
+                                  aStrokeOptions.mMiterLimit,
+                                  D2D1_DASH_STYLE_CUSTOM,
+                                  aStrokeOptions.mDashOffset),
+      &dash[0], // data() is not C++98, although it's in recent gcc
+                // and VC10's STL
+      dash.size(),
+      byRef(style));
+  } else {
+    hr = factory()->CreateStrokeStyle(
+      D2D1::StrokeStyleProperties(capStyle, capStyle,
+                                  capStyle, joinStyle,
+                                  aStrokeOptions.mMiterLimit),
+      nullptr, 0, byRef(style));
+  }
+
+  if (FAILED(hr)) {
+    gfxWarning() << "Failed to create Direct2D stroke style.";
+  }
+
+  return style;
+}
+
 TemporaryRef<ID3D10Texture2D>
 DrawTargetD2D::CreateGradientTexture(const GradientStopsD2D *aStops)
 {
   CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, 4096, 1, 1, 1);
 
   std::vector<D2D1_GRADIENT_STOP> rawStops;
   rawStops.resize(aStops->mStopCollection->GetGradientStopCount());
   aStops->mStopCollection->GetGradientStops(&rawStops.front(), rawStops.size());
@@ -2416,16 +2519,141 @@ DrawTargetD2D::CreateTextureForAnalysis(
 
   if (FAILED(hr)) {
     return nullptr;
   }
 
   return tex;
 }
 
+TemporaryRef<ID2D1Bitmap>
+DrawTargetD2D::CreatePartialBitmapForSurface(DataSourceSurface *aSurface, Matrix &aMatrix, ExtendMode aExtendMode)
+{
+  RefPtr<ID2D1Bitmap> bitmap;
+
+  // This is where things get complicated. The source surface was
+  // created for a surface that was too large to fit in a texture.
+  // We'll need to figure out if we can work with a partial upload
+  // or downsample in software.
+
+  Matrix transform = mTransform;
+  Matrix invTransform = transform = aMatrix * transform;
+  if (!invTransform.Invert()) {
+    // Singular transform, nothing to be drawn.
+    return nullptr;
+  }
+
+  Rect rect(0, 0, Float(mSize.width), Float(mSize.height));
+
+  // Calculate the rectangle of the source mapped to our surface.
+  rect = invTransform.TransformBounds(rect);
+  rect.RoundOut();
+
+  IntSize size = aSurface->GetSize();
+
+  Rect uploadRect(0, 0, Float(size.width), Float(size.height));
+
+  // Limit the uploadRect as much as possible without supporting discontiguous uploads 
+  //
+  //                               region we will paint from
+  //   uploadRect
+  //   .---------------.              .---------------.         resulting uploadRect
+  //   |               |rect          |               |
+  //   |          .---------.         .----.     .----.          .---------------.
+  //   |          |         |  ---->  |    |     |    |   ---->  |               |
+  //   |          '---------'         '----'     '----'          '---------------'
+  //   '---------------'              '---------------'
+  //
+  //
+
+  if (uploadRect.Contains(rect)) {
+    // Extend mode is irrelevant, the displayed rect is completely contained
+    // by the source bitmap.
+    uploadRect = rect;
+  } else if (aExtendMode == EXTEND_CLAMP && uploadRect.Intersects(rect)) {
+    // Calculate the rectangle on the source bitmap that touches our
+    // surface, and upload that, for EXTEND_CLAMP we can actually guarantee
+    // correct behaviour in this case.
+    uploadRect = uploadRect.Intersect(rect);
+
+    // We now proceed to check if we can limit at least one dimension of the
+    // upload rect safely without looking at extend mode.
+  } else if (rect.x >= 0 && rect.XMost() < size.width) {
+    uploadRect.x = rect.x;
+    uploadRect.width = rect.width;
+  } else if (rect.y >= 0 && rect.YMost() < size.height) {
+    uploadRect.y = rect.y;
+    uploadRect.height = rect.height;
+  }
+
+
+  int stride = aSurface->Stride();
+
+  if (uploadRect.width <= mRT->GetMaximumBitmapSize() &&
+      uploadRect.height <= mRT->GetMaximumBitmapSize()) {
+
+    // A partial upload will suffice.
+    mRT->CreateBitmap(D2D1::SizeU(uint32_t(uploadRect.width), uint32_t(uploadRect.height)),
+                      aSurface->GetData() + int(uploadRect.x) * 4 + int(uploadRect.y) * stride,
+                      stride,
+                      D2D1::BitmapProperties(D2DPixelFormat(aSurface->GetFormat())),
+                      byRef(bitmap));
+
+    aMatrix.Translate(uploadRect.x, uploadRect.y);
+
+    return bitmap;
+  } else {
+    int Bpp = BytesPerPixel(aSurface->GetFormat());
+
+    if (Bpp != 4) {
+      // This shouldn't actually happen in practice!
+      MOZ_ASSERT(false);
+      return nullptr;
+    }
+
+    ImageHalfScaler scaler(aSurface->GetData(), stride, size);
+
+    // Calculate the maximum width/height of the image post transform.
+    Point topRight = transform * Point(Float(size.width), 0);
+    Point topLeft = transform * Point(0, 0);
+    Point bottomRight = transform * Point(Float(size.width), Float(size.height));
+    Point bottomLeft = transform * Point(0, Float(size.height));
+    
+    IntSize scaleSize;
+
+    scaleSize.width = int32_t(max(Distance(topRight, topLeft),
+                                  Distance(bottomRight, bottomLeft)));
+    scaleSize.height = int32_t(max(Distance(topRight, bottomRight),
+                                   Distance(topLeft, bottomLeft)));
+
+    if (unsigned(scaleSize.width) > mRT->GetMaximumBitmapSize()) {
+      // Ok, in this case we'd really want a downscale of a part of the bitmap,
+      // perhaps we can do this later but for simplicity let's do something
+      // different here and assume it's good enough, this should be rare!
+      scaleSize.width = 4095;
+    }
+    if (unsigned(scaleSize.height) > mRT->GetMaximumBitmapSize()) {
+      scaleSize.height = 4095;
+    }
+
+    scaler.ScaleForSize(scaleSize);
+
+    IntSize newSize = scaler.GetSize();
+    
+    mRT->CreateBitmap(D2D1::SizeU(newSize.width, newSize.height),
+                      scaler.GetScaledData(), scaler.GetStride(),
+                      D2D1::BitmapProperties(D2DPixelFormat(aSurface->GetFormat())),
+                      byRef(bitmap));
+
+    aMatrix.Scale(Float(size.width / newSize.width),
+                  Float(size.height / newSize.height));
+    return bitmap;
+  }
+}
+
 void
 DrawTargetD2D::SetupEffectForRadialGradient(const RadialGradientPattern *aPattern)
 {
   mPrivateData->mEffect->GetTechniqueByName("SampleRadialGradient")->GetPassByIndex(0)->Apply(0);
   mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()->
     SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
 
   float dimensions[] = { float(mSize.width), float(mSize.height), 0, 0 };
--- a/gfx/2d/DrawTargetD2D.h
+++ b/gfx/2d/DrawTargetD2D.h
@@ -129,16 +129,17 @@ public:
   bool Init(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
   bool InitD3D10Data();
   uint32_t GetByteSize() const;
   TemporaryRef<ID2D1Layer> GetCachedLayer();
   void PopCachedLayer(ID2D1RenderTarget *aRT);
 
   static ID2D1Factory *factory();
   static void CleanupD2D();
+  static TemporaryRef<ID2D1StrokeStyle> CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions);
   static IDWriteFactory *GetDWriteFactory();
 
   operator std::string() const {
     std::stringstream stream;
     stream << "DrawTargetD2D(" << this << ")";
     return stream.str();
   }
 
@@ -186,28 +187,37 @@ private:
 
   bool FillGlyphsManual(ScaledFontDWrite *aFont,
                         const GlyphBuffer &aBuffer,
                         const Color &aColor,
                         IDWriteRenderingParams *aParams,
                         const DrawOptions &aOptions = DrawOptions());
 
   TemporaryRef<ID2D1RenderTarget> CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
+  TemporaryRef<ID2D1Geometry> ConvertRectToGeometry(const D2D1_RECT_F& aRect);
+  TemporaryRef<ID2D1Geometry> GetTransformedGeometry(ID2D1Geometry *aGeometry, const D2D1_MATRIX_3X2_F &aTransform);
+  TemporaryRef<ID2D1Geometry> Intersect(ID2D1Geometry *aGeometryA, ID2D1Geometry *aGeometryB);
 
   // This returns the clipped geometry, in addition it returns aClipBounds which
   // represents the intersection of all pixel-aligned rectangular clips that
   // are currently set. The returned clipped geometry must be clipped by these
   // bounds to correctly reflect the total clip. This is in device space.
   TemporaryRef<ID2D1Geometry> GetClippedGeometry(IntRect *aClipBounds);
 
   TemporaryRef<ID2D1Brush> CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f);
 
   TemporaryRef<ID3D10Texture2D> CreateGradientTexture(const GradientStopsD2D *aStops);
   TemporaryRef<ID3D10Texture2D> CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds);
 
+  // This creates a (partially) uploaded bitmap for a DataSourceSurface. It
+  // uploads the minimum requirement and possibly downscales. It adjusts the
+  // input Matrix to compensate.
+  TemporaryRef<ID2D1Bitmap> CreatePartialBitmapForSurface(DataSourceSurface *aSurface, Matrix &aMatrix,
+                                                          ExtendMode aExtendMode);
+
   void SetupEffectForRadialGradient(const RadialGradientPattern *aPattern);
   void SetupStateForRendering();
 
   // Set the scissor rect to a certain IntRects, resets the scissor rect to
   // surface bounds when NULL is specified.
   void SetScissorToRect(IntRect *aRect);
 
   void PushD2DLayer(ID2D1RenderTarget *aRT, ID2D1Geometry *aGeometry, ID2D1Layer *aLayer, const D2D1_MATRIX_3X2_F &aTransform);
--- a/gfx/2d/HelpersD2D.h
+++ b/gfx/2d/HelpersD2D.h
@@ -3,31 +3,24 @@
  * 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 MOZILLA_GFX_HELPERSD2D_H_
 #define MOZILLA_GFX_HELPERSD2D_H_
 
 #include "moz-d2d1-1.h"
 
-#include <vector>
-
 #include <dwrite.h>
 #include "2D.h"
-#include "Logging.h"
-#include "Tools.h"
-#include "ImageScaling.h"
 
 #include "ScaledFontDWrite.h"
 
 namespace mozilla {
 namespace gfx {
 
-ID2D1Factory* D2DFactory();
-
 static inline D2D1_POINT_2F D2DPoint(const Point &aPoint)
 {
   return D2D1::Point2F(aPoint.x, aPoint.y);
 }
 
 static inline D2D1_SIZE_U D2DIntSize(const IntSize &aSize)
 {
   return D2D1::SizeU(aSize.width, aSize.height);
@@ -250,250 +243,12 @@ DWriteGlyphRunFromGlyphs(const GlyphBuff
     
   run->bidiLevel = 0;
   run->fontFace = aFont->mFontFace;
   run->fontEmSize = aFont->GetSize();
   run->glyphCount = aGlyphs.mNumGlyphs;
   run->isSideways = FALSE;
 }
 
-static TemporaryRef<ID2D1Geometry>
-ConvertRectToGeometry(const D2D1_RECT_F& aRect)
-{
-  RefPtr<ID2D1RectangleGeometry> rectGeom;
-  D2DFactory()->CreateRectangleGeometry(&aRect, byRef(rectGeom));
-  return rectGeom.forget();
-}
-
-static TemporaryRef<ID2D1Geometry>
-GetTransformedGeometry(ID2D1Geometry *aGeometry, const D2D1_MATRIX_3X2_F &aTransform)
-{
-  RefPtr<ID2D1PathGeometry> tmpGeometry;
-  D2DFactory()->CreatePathGeometry(byRef(tmpGeometry));
-  RefPtr<ID2D1GeometrySink> currentSink;
-  tmpGeometry->Open(byRef(currentSink));
-  aGeometry->Simplify(D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
-                      aTransform, currentSink);
-  currentSink->Close();
-  return tmpGeometry;
-}
-
-static TemporaryRef<ID2D1Geometry>
-IntersectGeometry(ID2D1Geometry *aGeometryA, ID2D1Geometry *aGeometryB)
-{
-  RefPtr<ID2D1PathGeometry> pathGeom;
-  D2DFactory()->CreatePathGeometry(byRef(pathGeom));
-  RefPtr<ID2D1GeometrySink> sink;
-  pathGeom->Open(byRef(sink));
-  aGeometryA->CombineWithGeometry(aGeometryB, D2D1_COMBINE_MODE_INTERSECT, nullptr, sink);
-  sink->Close();
-
-  return pathGeom;
-}
-
-static TemporaryRef<ID2D1StrokeStyle>
-CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions)
-{
-  RefPtr<ID2D1StrokeStyle> style;
-
-  D2D1_CAP_STYLE capStyle;
-  D2D1_LINE_JOIN joinStyle;
-
-  switch (aStrokeOptions.mLineCap) {
-  case CAP_BUTT:
-    capStyle = D2D1_CAP_STYLE_FLAT;
-    break;
-  case CAP_ROUND:
-    capStyle = D2D1_CAP_STYLE_ROUND;
-    break;
-  case CAP_SQUARE:
-    capStyle = D2D1_CAP_STYLE_SQUARE;
-    break;
-  }
-
-  switch (aStrokeOptions.mLineJoin) {
-  case JOIN_MITER:
-    joinStyle = D2D1_LINE_JOIN_MITER;
-    break;
-  case JOIN_MITER_OR_BEVEL:
-    joinStyle = D2D1_LINE_JOIN_MITER_OR_BEVEL;
-    break;
-  case JOIN_ROUND:
-    joinStyle = D2D1_LINE_JOIN_ROUND;
-    break;
-  case JOIN_BEVEL:
-    joinStyle = D2D1_LINE_JOIN_BEVEL;
-    break;
-  }
-
-
-  HRESULT hr;
-  if (aStrokeOptions.mDashPattern) {
-    typedef std::vector<Float> FloatVector;
-    // D2D "helpfully" multiplies the dash pattern by the line width.
-    // That's not what cairo does, or is what <canvas>'s dash wants.
-    // So fix the multiplication in advance.
-    Float lineWidth = aStrokeOptions.mLineWidth;
-    FloatVector dash(aStrokeOptions.mDashPattern,
-                     aStrokeOptions.mDashPattern + aStrokeOptions.mDashLength);
-    for (FloatVector::iterator it = dash.begin(); it != dash.end(); ++it) {
-      *it /= lineWidth;
-    }
-
-    hr = D2DFactory()->CreateStrokeStyle(
-      D2D1::StrokeStyleProperties(capStyle, capStyle,
-                                  capStyle, joinStyle,
-                                  aStrokeOptions.mMiterLimit,
-                                  D2D1_DASH_STYLE_CUSTOM,
-                                  aStrokeOptions.mDashOffset),
-      &dash[0], // data() is not C++98, although it's in recent gcc
-                // and VC10's STL
-      dash.size(),
-      byRef(style));
-  } else {
-    hr = D2DFactory()->CreateStrokeStyle(
-      D2D1::StrokeStyleProperties(capStyle, capStyle,
-                                  capStyle, joinStyle,
-                                  aStrokeOptions.mMiterLimit),
-      nullptr, 0, byRef(style));
-  }
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to create Direct2D stroke style.";
-  }
-
-  return style;
-}
-
-// This creates a (partially) uploaded bitmap for a DataSourceSurface. It
-// uploads the minimum requirement and possibly downscales. It adjusts the
-// input Matrix to compensate.
-static TemporaryRef<ID2D1Bitmap>
-CreatePartialBitmapForSurface(DataSourceSurface *aSurface, const Matrix &aDestinationTransform,
-                              const IntSize &aDestinationSize, ExtendMode aExtendMode,
-                              Matrix &aSourceTransform, ID2D1RenderTarget *aRT)
-{
-  RefPtr<ID2D1Bitmap> bitmap;
-
-  // This is where things get complicated. The source surface was
-  // created for a surface that was too large to fit in a texture.
-  // We'll need to figure out if we can work with a partial upload
-  // or downsample in software.
-
-  Matrix transform = aDestinationTransform;
-  Matrix invTransform = transform = aSourceTransform * transform;
-  if (!invTransform.Invert()) {
-    // Singular transform, nothing to be drawn.
-    return nullptr;
-  }
-
-  Rect rect(0, 0, Float(aDestinationSize.width), Float(aDestinationSize.height));
-
-  // Calculate the rectangle of the source mapped to our surface.
-  rect = invTransform.TransformBounds(rect);
-  rect.RoundOut();
-
-  IntSize size = aSurface->GetSize();
-
-  Rect uploadRect(0, 0, Float(size.width), Float(size.height));
-
-  // Limit the uploadRect as much as possible without supporting discontiguous uploads 
-  //
-  //                               region we will paint from
-  //   uploadRect
-  //   .---------------.              .---------------.         resulting uploadRect
-  //   |               |rect          |               |
-  //   |          .---------.         .----.     .----.          .---------------.
-  //   |          |         |  ---->  |    |     |    |   ---->  |               |
-  //   |          '---------'         '----'     '----'          '---------------'
-  //   '---------------'              '---------------'
-  //
-  //
-
-  if (uploadRect.Contains(rect)) {
-    // Extend mode is irrelevant, the displayed rect is completely contained
-    // by the source bitmap.
-    uploadRect = rect;
-  } else if (aExtendMode == EXTEND_CLAMP && uploadRect.Intersects(rect)) {
-    // Calculate the rectangle on the source bitmap that touches our
-    // surface, and upload that, for EXTEND_CLAMP we can actually guarantee
-    // correct behaviour in this case.
-    uploadRect = uploadRect.Intersect(rect);
-
-    // We now proceed to check if we can limit at least one dimension of the
-    // upload rect safely without looking at extend mode.
-  } else if (rect.x >= 0 && rect.XMost() < size.width) {
-    uploadRect.x = rect.x;
-    uploadRect.width = rect.width;
-  } else if (rect.y >= 0 && rect.YMost() < size.height) {
-    uploadRect.y = rect.y;
-    uploadRect.height = rect.height;
-  }
-
-
-  int stride = aSurface->Stride();
-
-  if (uploadRect.width <= aRT->GetMaximumBitmapSize() &&
-      uploadRect.height <= aRT->GetMaximumBitmapSize()) {
-
-    // A partial upload will suffice.
-    aRT->CreateBitmap(D2D1::SizeU(uint32_t(uploadRect.width), uint32_t(uploadRect.height)),
-                      aSurface->GetData() + int(uploadRect.x) * 4 + int(uploadRect.y) * stride,
-                      stride,
-                      D2D1::BitmapProperties(D2DPixelFormat(aSurface->GetFormat())),
-                      byRef(bitmap));
-
-    aSourceTransform.Translate(uploadRect.x, uploadRect.y);
-
-    return bitmap;
-  } else {
-    int Bpp = BytesPerPixel(aSurface->GetFormat());
-
-    if (Bpp != 4) {
-      // This shouldn't actually happen in practice!
-      MOZ_ASSERT(false);
-      return nullptr;
-    }
-
-    ImageHalfScaler scaler(aSurface->GetData(), stride, size);
-
-    // Calculate the maximum width/height of the image post transform.
-    Point topRight = transform * Point(Float(size.width), 0);
-    Point topLeft = transform * Point(0, 0);
-    Point bottomRight = transform * Point(Float(size.width), Float(size.height));
-    Point bottomLeft = transform * Point(0, Float(size.height));
-    
-    IntSize scaleSize;
-
-    scaleSize.width = int32_t(max(Distance(topRight, topLeft),
-                                  Distance(bottomRight, bottomLeft)));
-    scaleSize.height = int32_t(max(Distance(topRight, bottomRight),
-                                   Distance(topLeft, bottomLeft)));
-
-    if (unsigned(scaleSize.width) > aRT->GetMaximumBitmapSize()) {
-      // Ok, in this case we'd really want a downscale of a part of the bitmap,
-      // perhaps we can do this later but for simplicity let's do something
-      // different here and assume it's good enough, this should be rare!
-      scaleSize.width = 4095;
-    }
-    if (unsigned(scaleSize.height) > aRT->GetMaximumBitmapSize()) {
-      scaleSize.height = 4095;
-    }
-
-    scaler.ScaleForSize(scaleSize);
-
-    IntSize newSize = scaler.GetSize();
-    
-    aRT->CreateBitmap(D2D1::SizeU(newSize.width, newSize.height),
-                      scaler.GetScaledData(), scaler.GetStride(),
-                      D2D1::BitmapProperties(D2DPixelFormat(aSurface->GetFormat())),
-                      byRef(bitmap));
-
-    aSourceTransform.Scale(Float(size.width / newSize.width),
-                           Float(size.height / newSize.height));
-    return bitmap;
-  }
-}
-
 }
 }
 
 #endif /* MOZILLA_GFX_HELPERSD2D_H_ */
--- a/gfx/2d/PathD2D.cpp
+++ b/gfx/2d/PathD2D.cpp
@@ -309,17 +309,18 @@ PathD2D::ContainsPoint(const Point &aPoi
 
 bool
 PathD2D::StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
                              const Point &aPoint,
                              const Matrix &aTransform) const
 {
   BOOL result;
 
-  RefPtr<ID2D1StrokeStyle> strokeStyle = CreateStrokeStyleForOptions(aStrokeOptions);
+  RefPtr<ID2D1StrokeStyle> strokeStyle =
+    DrawTargetD2D::CreateStrokeStyleForOptions(aStrokeOptions);
   HRESULT hr = mGeometry->StrokeContainsPoint(D2DPoint(aPoint),
                                               aStrokeOptions.mLineWidth,
                                               strokeStyle,
                                               D2DMatrix(aTransform),
                                               &result);
 
   if (FAILED(hr)) {
     // Log
@@ -345,17 +346,18 @@ PathD2D::GetBounds(const Matrix &aTransf
 }
 
 Rect
 PathD2D::GetStrokedBounds(const StrokeOptions &aStrokeOptions,
                           const Matrix &aTransform) const
 {
   D2D1_RECT_F bounds;
 
-  RefPtr<ID2D1StrokeStyle> strokeStyle = CreateStrokeStyleForOptions(aStrokeOptions);
+  RefPtr<ID2D1StrokeStyle> strokeStyle =
+    DrawTargetD2D::CreateStrokeStyleForOptions(aStrokeOptions);
   HRESULT hr =
     mGeometry->GetWidenedBounds(aStrokeOptions.mLineWidth, strokeStyle,
                                 D2DMatrix(aTransform), &bounds);
 
   if (FAILED(hr)) {
     gfxWarning() << "Failed to get stroked bounds for path. Code: " << hr;
     bounds.bottom = bounds.left = bounds.right = bounds.top = 0;
   }
--- a/gfx/2d/unittest/TestDrawTargetBase.cpp
+++ b/gfx/2d/unittest/TestDrawTargetBase.cpp
@@ -1,109 +1,109 @@
 /* -*- 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 "TestDrawTargetBase.h"
-#include <sstream>
-
-using namespace mozilla;
-using namespace mozilla::gfx;
-using namespace std;
-
-TestDrawTargetBase::TestDrawTargetBase()
-{
-  REGISTER_TEST(TestDrawTargetBase, Initialized);
-  REGISTER_TEST(TestDrawTargetBase, FillCompletely);
-  REGISTER_TEST(TestDrawTargetBase, FillRect);
-}
-
-void
-TestDrawTargetBase::Initialized()
-{
-  VERIFY(mDT);
-}
-
-void
-TestDrawTargetBase::FillCompletely()
-{
-  mDT->FillRect(Rect(0, 0, DT_WIDTH, DT_HEIGHT), ColorPattern(Color(0, 0.5f, 0, 1.0f)));
-
-  RefreshSnapshot();
-
-  VerifyAllPixels(Color(0, 0.5f, 0, 1.0f));
-}
-
-void
-TestDrawTargetBase::FillRect()
-{
-  mDT->FillRect(Rect(0, 0, DT_WIDTH, DT_HEIGHT), ColorPattern(Color(0, 0.5f, 0, 1.0f)));
-  mDT->FillRect(Rect(50, 50, 50, 50), ColorPattern(Color(0.5f, 0, 0, 1.0f)));
-
-  RefreshSnapshot();
-
-  VerifyPixel(IntPoint(49, 49), Color(0, 0.5f, 0, 1.0f));
-  VerifyPixel(IntPoint(50, 50), Color(0.5f, 0, 0, 1.0f));
-  VerifyPixel(IntPoint(99, 99), Color(0.5f, 0, 0, 1.0f));
-  VerifyPixel(IntPoint(100, 100), Color(0, 0.5f, 0, 1.0f));
-}
-
-void
-TestDrawTargetBase::RefreshSnapshot()
-{
-  RefPtr<SourceSurface> snapshot = mDT->Snapshot();
-  mDataSnapshot = snapshot->GetDataSurface();
-}
-
-void
-TestDrawTargetBase::VerifyAllPixels(const Color &aColor)
-{
-  uint32_t *colVal = (uint32_t*)mDataSnapshot->GetData();
-
-  uint32_t expected = RGBAPixelFromColor(aColor);
-
-  for (int y = 0; y < DT_HEIGHT; y++) {
-    for (int x = 0; x < DT_WIDTH; x++) {
-      if (colVal[y * (mDataSnapshot->Stride() / 4) + x] != expected) {
-        LogMessage("VerifyAllPixels Failed\n");
-        mTestFailed = true;
-        return;
-      }
-    }
-  }
-}
-
-void
-TestDrawTargetBase::VerifyPixel(const IntPoint &aPoint, mozilla::gfx::Color &aColor)
-{
-  uint32_t *colVal = (uint32_t*)mDataSnapshot->GetData();
-
-  uint32_t expected = RGBAPixelFromColor(aColor);
-  uint32_t rawActual = colVal[aPoint.y * (mDataSnapshot->Stride() / 4) + aPoint.x];
-
-  if (rawActual != expected) {
-    stringstream message;
-    uint32_t actb = rawActual & 0xFF;
-    uint32_t actg = (rawActual & 0xFF00) >> 8;
-    uint32_t actr = (rawActual & 0xFF0000) >> 16;
-    uint32_t acta = (rawActual & 0xFF000000) >> 24;
-    uint32_t expb = expected & 0xFF;
-    uint32_t expg = (expected & 0xFF00) >> 8;
-    uint32_t expr = (expected & 0xFF0000) >> 16;
-    uint32_t expa = (expected & 0xFF000000) >> 24;
-
-    message << "Verify Pixel (" << aPoint.x << "x" << aPoint.y << ") Failed."
-      " Expected (" << expr << "," << expg << "," << expb << "," << expa << ") "
-      " Got (" << actr << "," << actg << "," << actb << "," << acta << ")\n";
-
-    LogMessage(message.str());
-    mTestFailed = true;
-    return;
-  }
-}
-
-uint32_t
-TestDrawTargetBase::RGBAPixelFromColor(const Color &aColor)
-{
-  return uint8_t((aColor.b * 255) + 0.5f) | uint8_t((aColor.g * 255) + 0.5f) << 8 |
-         uint8_t((aColor.r * 255) + 0.5f) << 16 | uint8_t((aColor.a * 255) + 0.5f) << 24;
-}
+
+#include "TestDrawTargetBase.h"
+#include <sstream>
+
+using namespace mozilla;
+using namespace mozilla::gfx;
+using namespace std;
+
+TestDrawTargetBase::TestDrawTargetBase()
+{
+  REGISTER_TEST(TestDrawTargetBase, Initialized);
+  REGISTER_TEST(TestDrawTargetBase, FillCompletely);
+  REGISTER_TEST(TestDrawTargetBase, FillRect);
+}
+
+void
+TestDrawTargetBase::Initialized()
+{
+  VERIFY(mDT);
+}
+
+void
+TestDrawTargetBase::FillCompletely()
+{
+  mDT->FillRect(Rect(0, 0, DT_WIDTH, DT_HEIGHT), ColorPattern(Color(0, 0.5f, 0, 1.0f)));
+
+  RefreshSnapshot();
+
+  VerifyAllPixels(Color(0, 0.5f, 0, 1.0f));
+}
+
+void
+TestDrawTargetBase::FillRect()
+{
+  mDT->FillRect(Rect(0, 0, DT_WIDTH, DT_HEIGHT), ColorPattern(Color(0, 0.5f, 0, 1.0f)));
+  mDT->FillRect(Rect(50, 50, 50, 50), ColorPattern(Color(0.5f, 0, 0, 1.0f)));
+
+  RefreshSnapshot();
+
+  VerifyPixel(IntPoint(49, 49), Color(0, 0.5f, 0, 1.0f));
+  VerifyPixel(IntPoint(50, 50), Color(0.5f, 0, 0, 1.0f));
+  VerifyPixel(IntPoint(99, 99), Color(0.5f, 0, 0, 1.0f));
+  VerifyPixel(IntPoint(100, 100), Color(0, 0.5f, 0, 1.0f));
+}
+
+void
+TestDrawTargetBase::RefreshSnapshot()
+{
+  RefPtr<SourceSurface> snapshot = mDT->Snapshot();
+  mDataSnapshot = snapshot->GetDataSurface();
+}
+
+void
+TestDrawTargetBase::VerifyAllPixels(const Color &aColor)
+{
+  uint32_t *colVal = (uint32_t*)mDataSnapshot->GetData();
+
+  uint32_t expected = RGBAPixelFromColor(aColor);
+
+  for (int y = 0; y < DT_HEIGHT; y++) {
+    for (int x = 0; x < DT_WIDTH; x++) {
+      if (colVal[y * (mDataSnapshot->Stride() / 4) + x] != expected) {
+        LogMessage("VerifyAllPixels Failed\n");
+        mTestFailed = true;
+        return;
+      }
+    }
+  }
+}
+
+void
+TestDrawTargetBase::VerifyPixel(const IntPoint &aPoint, mozilla::gfx::Color &aColor)
+{
+  uint32_t *colVal = (uint32_t*)mDataSnapshot->GetData();
+
+  uint32_t expected = RGBAPixelFromColor(aColor);
+  uint32_t rawActual = colVal[aPoint.y * (mDataSnapshot->Stride() / 4) + aPoint.x];
+
+  if (rawActual != expected) {
+    stringstream message;
+    uint32_t actb = rawActual & 0xFF;
+    uint32_t actg = (rawActual & 0xFF00) >> 8;
+    uint32_t actr = (rawActual & 0xFF0000) >> 16;
+    uint32_t acta = (rawActual & 0xFF000000) >> 24;
+    uint32_t expb = expected & 0xFF;
+    uint32_t expg = (expected & 0xFF00) >> 8;
+    uint32_t expr = (expected & 0xFF0000) >> 16;
+    uint32_t expa = (expected & 0xFF000000) >> 24;
+
+    message << "Verify Pixel (" << aPoint.x << "x" << aPoint.y << ") Failed."
+      " Expected (" << expr << "," << expg << "," << expb << "," << expa << ") "
+      " Got (" << actr << "," << actg << "," << actb << "," << acta << ")\n";
+
+    LogMessage(message.str());
+    mTestFailed = true;
+    return;
+  }
+}
+
+uint32_t
+TestDrawTargetBase::RGBAPixelFromColor(const Color &aColor)
+{
+  return uint8_t((aColor.b * 255) + 0.5f) | uint8_t((aColor.g * 255) + 0.5f) << 8 |
+         uint8_t((aColor.r * 255) + 0.5f) << 16 | uint8_t((aColor.a * 255) + 0.5f) << 24;
+}