Bug 688367 - Add Skia backend to Azure. r=jrmuizel
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 03 Nov 2011 08:55:03 +1300
changeset 80982 58e6c346c72ab29a450bfddd7e85c1a11a96c071
parent 80981 cf97283ed45fdc984c619583620c34fce906bfc7
child 80983 6c91cf9c721baa6e8c7c9bbd0d698d18c24b0869
push id434
push userclegnitto@mozilla.com
push dateWed, 21 Dec 2011 12:10:54 +0000
treeherdermozilla-beta@bddb6ed8dd47 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs688367
milestone10.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 688367 - Add Skia backend to Azure. r=jrmuizel
content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
gfx/2d/2D.h
gfx/2d/DrawTargetSkia.cpp
gfx/2d/DrawTargetSkia.h
gfx/2d/Factory.cpp
gfx/2d/HelpersSkia.h
gfx/2d/Makefile.in
gfx/2d/PathSkia.cpp
gfx/2d/PathSkia.h
gfx/2d/ScaledFontMac.cpp
gfx/2d/ScaledFontMac.h
gfx/2d/ScaledFontSkia.cpp
gfx/2d/ScaledFontSkia.h
gfx/2d/SourceSurfaceSkia.cpp
gfx/2d/SourceSurfaceSkia.h
gfx/2d/Types.h
gfx/thebes/gfxAndroidPlatform.cpp
gfx/thebes/gfxAndroidPlatform.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatformMac.cpp
gfx/thebes/gfxPlatformMac.h
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -989,17 +989,17 @@ nsresult
 NS_NewCanvasRenderingContext2DAzure(nsIDOMCanvasRenderingContext2D** aResult)
 {
 #ifdef XP_WIN
   if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() !=
       gfxWindowsPlatform::RENDER_DIRECT2D ||
       !gfxWindowsPlatform::GetPlatform()->DWriteEnabled()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
-#elif !defined XP_MACOSX
+#elif !defined(XP_MACOSX) && !defined(ANDROID)
   return NS_ERROR_NOT_AVAILABLE;
 #endif
 
   nsRefPtr<nsIDOMCanvasRenderingContext2D> ctx = new nsCanvasRenderingContext2DAzure();
   if (!ctx)
     return NS_ERROR_OUT_OF_MEMORY;
 
   *aResult = ctx.forget().get();
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -609,18 +609,20 @@ public:
   virtual void PushClip(const Path *aPath) = 0;
 
   /* Pop a clip from the DrawTarget. A pop without a corresponding push will
    * be ignored.
    */
   virtual void PopClip() = 0;
 
   /*
-   * Create a SourceSurface optimized for use with this DrawTarget for
+   * Create a SourceSurface optimized for use with this DrawTarget from
    * existing bitmap data in memory.
+   *
+   * The SourceSurface does not take ownership of aData, and may be freed at any time.
    */
   virtual TemporaryRef<SourceSurface> CreateSourceSurfaceFromData(unsigned char *aData,
                                                             const IntSize &aSize,
                                                             int32_t aStride,
                                                             SurfaceFormat aFormat) const = 0;
 
   /*
    * Create a SourceSurface optimized for use with this DrawTarget from
@@ -671,17 +673,17 @@ public:
   virtual void SetTransform(const Matrix &aTransform)
     { mTransform = aTransform; mTransformDirty = true; }
 
   SurfaceFormat GetFormat() { return mFormat; }
 
   /* Tries to get a native surface for a DrawTarget, this may fail if the
    * draw target cannot convert to this surface type.
    */
-  virtual void *GetNativeSurface(NativeSurfaceType aType) = 0;
+  virtual void *GetNativeSurface(NativeSurfaceType aType) { return NULL; }
 
 protected:
   Matrix mTransform;
   bool mTransformDirty : 1;
 
   SurfaceFormat mFormat;
 };
 
new file mode 100644
--- /dev/null
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -0,0 +1,708 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *     Matt Woodrow <mwoodrow@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "DrawTargetSkia.h"
+#include "SourceSurfaceSkia.h"
+#include "ScaledFontSkia.h"
+#include "skia/SkDevice.h"
+#include "skia/SkTypeface.h"
+#include "skia/SkGradientShader.h"
+#include "skia/SkBlurDrawLooper.h"
+#include "skia/SkBlurMaskFilter.h"
+#include "skia/SkColorFilter.h"
+#include "skia/SkLayerRasterizer.h"
+#include "skia/SkLayerDrawLooper.h"
+#include "skia/SkDashPathEffect.h"
+#include "Logging.h"
+#include "HelpersSkia.h"
+#include "gfxImageSurface.h"
+#include "Tools.h"
+#include <algorithm>
+
+namespace mozilla {
+namespace gfx {
+
+SkColor ColorToSkColor(const Color &color, Float aAlpha)
+{
+  return SkColorSetARGB(color.a*aAlpha*255.0, color.r*255.0, color.g*255.0, color.b*255.0);
+}
+
+class GradientStopsSkia : public GradientStops
+{
+public:
+  GradientStopsSkia(const std::vector<GradientStop>& aStops, uint32_t aNumStops)
+    : mCount(aNumStops)
+  {
+    if (mCount == 0) {
+      return;
+    }
+
+    // Skia gradients always require a stop at 0.0 and 1.0, insert these if
+    // we don't have them.
+    uint32_t shift = 0;
+    if (aStops[0].offset != 0) {
+      mCount++;
+      shift = 1;
+    }
+    if (aStops[aNumStops-1].offset != 1) {
+      mCount++;
+    }
+    mColors.resize(mCount);
+    mPositions.resize(mCount);
+    if (aStops[0].offset != 0) {
+      mColors[0] = ColorToSkColor(aStops[0].color, 1.0);
+      mPositions[0] = 0;
+    }
+    for (uint32_t i = 0; i < aNumStops; i++) {
+      mColors[i + shift] = ColorToSkColor(aStops[i].color, 1.0);
+      mPositions[i + shift] = SkFloatToScalar(aStops[i].offset);
+    }
+    if (aStops[aNumStops-1].offset != 1) {
+      mColors[mCount-1] = ColorToSkColor(aStops[aNumStops-1].color, 1.0);
+      mPositions[mCount-1] = SK_Scalar1;
+    }
+  }
+
+  BackendType GetBackendType() const { return BACKEND_SKIA; }
+
+  std::vector<SkColor> mColors;
+  std::vector<SkScalar> mPositions;
+  int mCount;
+};
+
+SkXfermode::Mode
+GfxOpToSkiaOp(CompositionOp op)
+{
+  switch (op)
+  {
+    case OP_OVER:
+      return SkXfermode::kSrcOver_Mode;
+    case OP_ADD:
+      return SkXfermode::kPlus_Mode;
+    case OP_ATOP:
+      return SkXfermode::kSrcATop_Mode;
+    case OP_OUT:
+      return SkXfermode::kSrcOut_Mode;
+    case OP_IN:
+      return SkXfermode::kSrcIn_Mode;
+    case OP_SOURCE:
+      return SkXfermode::kSrc_Mode;
+    case OP_DEST_IN:
+      return SkXfermode::kDstIn_Mode;
+    case OP_DEST_OUT:
+      return SkXfermode::kDstOut_Mode;
+    case OP_DEST_OVER:
+      return SkXfermode::kDstOver_Mode;
+    case OP_DEST_ATOP:
+      return SkXfermode::kDstATop_Mode;
+    case OP_XOR:
+      return SkXfermode::kXor_Mode;
+    case OP_COUNT:
+      return SkXfermode::kSrcOver_Mode;
+  }
+  return SkXfermode::kSrcOver_Mode;
+}
+
+SkPaint::Cap
+CapStyleToSkiaCap(CapStyle aCap)
+{
+  switch (aCap)
+  {
+    case CAP_BUTT:
+      return SkPaint::kButt_Cap;
+    case CAP_ROUND:
+      return SkPaint::kRound_Cap;
+    case CAP_SQUARE:
+      return SkPaint::kSquare_Cap;
+  }
+  return SkPaint::kDefault_Cap;
+}
+
+SkPaint::Join
+JoinStyleToSkiaJoin(JoinStyle aJoin)
+{
+  switch (aJoin)
+  {
+    case JOIN_BEVEL:
+      return SkPaint::kBevel_Join;
+    case JOIN_ROUND:
+      return SkPaint::kRound_Join;
+    case JOIN_MITER:
+    case JOIN_MITER_OR_BEVEL:
+      return SkPaint::kMiter_Join;
+  }
+  return SkPaint::kDefault_Join;
+}
+
+SkRect
+RectToSkRect(const Rect& aRect)
+{
+  return SkRect::MakeXYWH(SkFloatToScalar(aRect.x), SkFloatToScalar(aRect.y), 
+                          SkFloatToScalar(aRect.width), SkFloatToScalar(aRect.height));
+}
+
+SkRect
+IntRectToSkRect(const IntRect& aRect)
+{
+  return SkRect::MakeXYWH(SkIntToScalar(aRect.x), SkIntToScalar(aRect.y), 
+                          SkIntToScalar(aRect.width), SkIntToScalar(aRect.height));
+}
+
+SkIRect
+RectToSkIRect(const Rect& aRect)
+{
+  return SkIRect::MakeXYWH(aRect.x, aRect.y, aRect.width, aRect.height);
+}
+
+SkIRect
+IntRectToSkIRect(const IntRect& aRect)
+{
+  return SkIRect::MakeXYWH(aRect.x, aRect.y, aRect.width, aRect.height);
+}
+
+
+DrawTargetSkia::DrawTargetSkia()
+{
+}
+
+DrawTargetSkia::~DrawTargetSkia()
+{
+}
+
+TemporaryRef<SourceSurface>
+DrawTargetSkia::Snapshot()
+{
+  //TODO: Wrong! Copy the pixels, preferably lazily
+  RefPtr<SourceSurfaceSkia> source = new SourceSurfaceSkia();
+  if (!source->InitWithBitmap(mCanvas.get(), mFormat)) {
+    return NULL;
+  }
+  return source;
+}
+
+SkShader::TileMode
+ExtendModeToTileMode(ExtendMode aMode)
+{
+  switch (aMode)
+  {
+    case EXTEND_CLAMP:
+      return SkShader::kClamp_TileMode;
+    case EXTEND_WRAP:
+      return SkShader::kRepeat_TileMode;
+    case EXTEND_MIRROR:
+      return SkShader::kMirror_TileMode;
+  }
+  return SkShader::kClamp_TileMode;
+}
+
+struct AutoPaintSetup {
+  AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Pattern& aPattern)
+    : mNeedsRestore(false), mAlpha(1.0)
+  {
+    Init(aCanvas, aOptions);
+    SetPattern(aPattern);
+  }
+
+  AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions)
+    : mNeedsRestore(false), mAlpha(1.0)
+  {
+    Init(aCanvas, aOptions);
+  }
+
+  ~AutoPaintSetup()
+  {
+    if (mNeedsRestore) {
+      mCanvas->restore();
+    }
+  }
+
+  void Init(SkCanvas *aCanvas, const DrawOptions& aOptions)
+  {
+    mPaint.setXfermodeMode(GfxOpToSkiaOp(aOptions.mCompositionOp));
+    mCanvas = aCanvas;
+
+    //TODO: Can we set greyscale somehow?
+    if (aOptions.mAntialiasMode != AA_NONE) {
+      mPaint.setAntiAlias(true);
+    } else {
+      mPaint.setAntiAlias(false);
+    }
+
+    NS_ASSERTION(aOptions.mSnapping == SNAP_NONE, "Pixel snapping not supported yet!");
+    
+    // TODO: We could skip the temporary for operator_source and just
+    // clear the clip rect. The other operators would be harder
+    // but could be worth it to skip pushing a group.
+    if (!IsOperatorBoundByMask(aOptions.mCompositionOp)) {
+      mPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
+      SkPaint temp;
+      temp.setXfermodeMode(GfxOpToSkiaOp(aOptions.mCompositionOp));
+      temp.setAlpha(aOptions.mAlpha*255);
+      //TODO: Get a rect here
+      mCanvas->saveLayer(NULL, &temp);
+      mNeedsRestore = true;
+    } else {
+      mPaint.setAlpha(aOptions.mAlpha*255.0);
+      mAlpha = aOptions.mAlpha;
+    }
+  }
+
+  void SetPattern(const Pattern& aPattern)
+  {
+    if (aPattern.GetType() == PATTERN_COLOR) {
+      Color color = static_cast<const ColorPattern&>(aPattern).mColor;
+      mPaint.setColor(ColorToSkColor(color, mAlpha));
+    } else if (aPattern.GetType() == PATTERN_LINEAR_GRADIENT) {
+      const LinearGradientPattern& pat = static_cast<const LinearGradientPattern&>(aPattern);
+      GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
+
+      if (stops->mCount >= 2) {
+        SkPoint points[2];
+        points[0] = SkPoint::Make(SkFloatToScalar(pat.mBegin.x), SkFloatToScalar(pat.mBegin.y));
+        points[1] = SkPoint::Make(SkFloatToScalar(pat.mEnd.x), SkFloatToScalar(pat.mEnd.y));
+
+        SkShader* shader = SkGradientShader::CreateLinear(points, 
+                                                          &stops->mColors.front(), 
+                                                          &stops->mPositions.front(), 
+                                                          stops->mCount, 
+                                                          SkShader::kClamp_TileMode);
+        SkSafeUnref(mPaint.setShader(shader));
+      } else {
+        mPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
+      }
+    } else if (aPattern.GetType() == PATTERN_RADIAL_GRADIENT) {
+      const RadialGradientPattern& pat = static_cast<const RadialGradientPattern&>(aPattern);
+      GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
+
+      if (stops->mCount >= 2) {
+        SkPoint points[2];
+        points[0] = SkPoint::Make(SkFloatToScalar(pat.mCenter1.x), SkFloatToScalar(pat.mCenter1.y));
+        points[1] = SkPoint::Make(SkFloatToScalar(pat.mCenter2.x), SkFloatToScalar(pat.mCenter2.y));
+
+        SkShader* shader = SkGradientShader::CreateTwoPointRadial(points[0], 
+                                                                  SkFloatToScalar(pat.mRadius1),
+                                                                  points[1], 
+                                                                  SkFloatToScalar(pat.mRadius2),
+                                                                  &stops->mColors.front(), 
+                                                                  &stops->mPositions.front(), 
+                                                                  stops->mCount, 
+                                                                  SkShader::kClamp_TileMode);
+        SkSafeUnref(mPaint.setShader(shader));
+      } else {
+        mPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
+      }
+    } else {
+      const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
+      const SkBitmap& bitmap = static_cast<SourceSurfaceSkia*>(pat.mSurface.get())->GetBitmap();
+
+      SkShader::TileMode mode = ExtendModeToTileMode(pat.mExtendMode);
+      SkShader* shader = SkShader::CreateBitmapShader(bitmap, mode, mode);
+      SkSafeUnref(mPaint.setShader(shader));
+    }
+  }
+
+  void SetStroke(const StrokeOptions &aOptions)
+  {
+    mPaint.setStrokeWidth(SkFloatToScalar(aOptions.mLineWidth));
+    mPaint.setStrokeMiter(SkFloatToScalar(aOptions.mMiterLimit));
+    mPaint.setStrokeCap(CapStyleToSkiaCap(aOptions.mLineCap));
+    mPaint.setStrokeJoin(JoinStyleToSkiaJoin(aOptions.mLineJoin));
+    if (aOptions.mDashLength) {
+      std::vector<SkScalar> pattern;
+      pattern.resize(aOptions.mDashLength);
+      for (uint32_t i = 0; i < aOptions.mDashLength; i++) {
+        pattern[i] = SkFloatToScalar(aOptions.mDashPattern[i]);
+      }
+
+      SkDashPathEffect* dash = new SkDashPathEffect(&pattern.front(), 
+                                                    aOptions.mDashLength, 
+                                                    SkFloatToScalar(aOptions.mDashOffset));
+      SkSafeUnref(mPaint.setPathEffect(dash));
+    }
+    mPaint.setStyle(SkPaint::kStroke_Style);
+  }
+
+  // TODO: Maybe add an operator overload to access this easier?
+  SkPaint mPaint;
+  bool mNeedsRestore;
+  SkCanvas* mCanvas;
+  Float mAlpha;
+};
+
+void
+DrawTargetSkia::Flush()
+{
+}
+
+void
+DrawTargetSkia::DrawSurface(SourceSurface *aSurface,
+                            const Rect &aDest,
+                            const Rect &aSource,
+                            const DrawSurfaceOptions &aSurfOptions,
+                            const DrawOptions &aOptions)
+{
+  if (aSurface->GetType() != SURFACE_SKIA) {
+    return;
+  }
+
+  if (aSource.IsEmpty()) {
+    return;
+  }
+
+  NS_ASSERTION(aSurfOptions.mFilter == FILTER_LINEAR, "Only linear filtering supported currently!");
+  SkRect destRect = RectToSkRect(aDest);
+  SkRect sourceRect = RectToSkRect(aSource);
+
+  SkMatrix matrix;
+  matrix.setRectToRect(sourceRect, destRect, SkMatrix::kFill_ScaleToFit);
+  
+  const SkBitmap& bitmap = static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap();
+ 
+  AutoPaintSetup paint(mCanvas.get(), aOptions);
+  SkShader *shader = SkShader::CreateBitmapShader(bitmap, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
+  shader->setLocalMatrix(matrix);
+  SkSafeUnref(paint.mPaint.setShader(shader));
+  mCanvas->drawRect(destRect, paint.mPaint);
+}
+
+void
+DrawTargetSkia::DrawSurfaceWithShadow(SourceSurface *aSurface,
+                                      const Point &aDest,
+                                      const Color &aColor,
+                                      const Point &aOffset,
+                                      Float aSigma,
+                                      CompositionOp aOperator)
+{
+  mCanvas->save(SkCanvas::kMatrix_SaveFlag);
+  mCanvas->resetMatrix();
+
+  uint32_t blurFlags = SkBlurMaskFilter::kHighQuality_BlurFlag |
+                       SkBlurMaskFilter::kIgnoreTransform_BlurFlag;
+  const SkBitmap& bitmap = static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap();
+  SkShader* shader = SkShader::CreateBitmapShader(bitmap, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
+  SkMatrix matrix;
+  matrix.reset();
+  matrix.setTranslateX(SkFloatToScalar(aDest.x));
+  matrix.setTranslateY(SkFloatToScalar(aDest.y));
+  shader->setLocalMatrix(matrix);
+  SkLayerDrawLooper* dl = new SkLayerDrawLooper;
+  SkLayerDrawLooper::LayerInfo info;
+  info.fPaintBits |= SkLayerDrawLooper::kShader_Bit;
+  SkPaint *layerPaint = dl->addLayer(info);
+  layerPaint->setShader(shader);
+
+  info.fPaintBits = 0;
+  info.fPaintBits |= SkLayerDrawLooper::kMaskFilter_Bit;
+  info.fPaintBits |= SkLayerDrawLooper::kColorFilter_Bit;
+  info.fColorMode = SkXfermode::kDst_Mode;
+  info.fOffset.set(SkFloatToScalar(aOffset.x), SkFloatToScalar(aOffset.y));
+  info.fPostTranslate = true;
+
+  SkMaskFilter* mf = SkBlurMaskFilter::Create(aSigma, SkBlurMaskFilter::kNormal_BlurStyle, blurFlags);
+  SkColor color = ColorToSkColor(aColor, 1);
+  SkColorFilter* cf = SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcIn_Mode);
+
+
+  layerPaint = dl->addLayer(info);
+  SkSafeUnref(layerPaint->setMaskFilter(mf));
+  SkSafeUnref(layerPaint->setColorFilter(cf));
+  layerPaint->setColor(color);
+  
+  // TODO: This is using the rasterizer to calculate an alpha mask
+  // on both the shadow and normal layers. We should fix this
+  // properly so it only happens for the shadow layer
+  SkLayerRasterizer *raster = new SkLayerRasterizer();
+  SkPaint maskPaint;
+  SkSafeUnref(maskPaint.setShader(shader));
+  raster->addLayer(maskPaint, 0, 0);
+  
+  SkPaint paint;
+  paint.setAntiAlias(true);
+  SkSafeUnref(paint.setRasterizer(raster));
+  paint.setXfermodeMode(GfxOpToSkiaOp(aOperator));
+  SkSafeUnref(paint.setLooper(dl));
+
+  SkRect rect = RectToSkRect(Rect(aDest.x, aDest.y, bitmap.width(), bitmap.height()));
+  mCanvas->drawRect(rect, paint);
+  mCanvas->restore();
+}
+
+void
+DrawTargetSkia::FillRect(const Rect &aRect,
+                         const Pattern &aPattern,
+                         const DrawOptions &aOptions)
+{
+  SkRect rect = RectToSkRect(aRect);
+  AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
+
+  mCanvas->drawRect(rect, paint.mPaint);
+}
+
+void
+DrawTargetSkia::Stroke(const Path *aPath,
+                       const Pattern &aPattern,
+                       const StrokeOptions &aStrokeOptions,
+                       const DrawOptions &aOptions)
+{
+  if (aPath->GetBackendType() != BACKEND_SKIA) {
+    return;
+  }
+
+  const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath);
+
+
+  AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
+  paint.SetStroke(aStrokeOptions);
+
+  mCanvas->drawPath(skiaPath->GetPath(), paint.mPaint);
+}
+
+void
+DrawTargetSkia::StrokeRect(const Rect &aRect,
+                           const Pattern &aPattern,
+                           const StrokeOptions &aStrokeOptions,
+                           const DrawOptions &aOptions)
+{
+  AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
+  paint.SetStroke(aStrokeOptions);
+
+  mCanvas->drawRect(RectToSkRect(aRect), paint.mPaint);
+}
+
+void 
+DrawTargetSkia::StrokeLine(const Point &aStart,
+                           const Point &aEnd,
+                           const Pattern &aPattern,
+                           const StrokeOptions &aStrokeOptions,
+                           const DrawOptions &aOptions)
+{
+  AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
+  paint.SetStroke(aStrokeOptions);
+
+  mCanvas->drawLine(SkFloatToScalar(aStart.x), SkFloatToScalar(aStart.y), 
+                    SkFloatToScalar(aEnd.x), SkFloatToScalar(aEnd.y), 
+                    paint.mPaint);
+}
+
+void
+DrawTargetSkia::Fill(const Path *aPath,
+                    const Pattern &aPattern,
+                    const DrawOptions &aOptions)
+{
+  if (aPath->GetBackendType() != BACKEND_SKIA) {
+    return;
+  }
+
+  const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath);
+
+  AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
+
+  mCanvas->drawPath(skiaPath->GetPath(), paint.mPaint);
+}
+
+void
+DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
+                           const GlyphBuffer &aBuffer,
+                           const Pattern &aPattern,
+                           const DrawOptions &aOptions)
+{
+  if (aFont->GetType() != FONT_MAC && aFont->GetType() != FONT_SKIA) {
+    return;
+  }
+
+  ScaledFontSkia* skiaFont = static_cast<ScaledFontSkia*>(aFont);
+
+  AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
+  paint.mPaint.setTypeface(skiaFont->mTypeface);
+  paint.mPaint.setTextSize(SkFloatToScalar(skiaFont->mSize));
+  paint.mPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+  
+  std::vector<uint16_t> indices;
+  std::vector<SkPoint> offsets;
+  indices.resize(aBuffer.mNumGlyphs);
+  offsets.resize(aBuffer.mNumGlyphs);
+
+  for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) {
+    indices[i] = aBuffer.mGlyphs[i].mIndex;
+    offsets[i].fX = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.x);
+    offsets[i].fY = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.y);
+  }
+
+  mCanvas->drawPosText(&indices.front(), aBuffer.mNumGlyphs*2, &offsets.front(), paint.mPaint);
+}
+
+TemporaryRef<SourceSurface>
+DrawTargetSkia::CreateSourceSurfaceFromData(unsigned char *aData,
+                                             const IntSize &aSize,
+                                             int32_t aStride,
+                                             SurfaceFormat aFormat) const
+{
+  RefPtr<SourceSurfaceSkia> newSurf = new SourceSurfaceSkia();
+
+  if (!newSurf->InitFromData(aData, aSize, aStride, aFormat)) {
+    gfxDebug() << *this << ": Failure to create source surface from data. Size: " << aSize;
+    return NULL;
+  }
+    
+  return newSurf;
+}
+
+TemporaryRef<DrawTarget>
+DrawTargetSkia::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
+{
+  RefPtr<DrawTargetSkia> target = new DrawTargetSkia();
+  if (!target->Init(aSize, aFormat)) {
+    return NULL;
+  }
+  return target;
+}
+
+TemporaryRef<SourceSurface>
+DrawTargetSkia::OptimizeSourceSurface(SourceSurface *aSurface) const
+{
+  return NULL;
+}
+
+TemporaryRef<SourceSurface>
+DrawTargetSkia::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
+{
+  return NULL;
+}
+
+void
+DrawTargetSkia::CopySurface(SourceSurface *aSurface,
+                            const IntRect& aSourceRect,
+                            const IntPoint &aDestination)
+{
+  //TODO: We could just use writePixels() here if the sourceRect is the entire source
+  
+    if (aSurface->GetType() != SURFACE_SKIA) {
+    return;
+  }
+  
+  const SkBitmap& bitmap = static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap();
+
+  mCanvas->save();
+  mCanvas->resetMatrix();
+  SkRect dest = IntRectToSkRect(IntRect(aDestination.x, aDestination.y, aSourceRect.width, aSourceRect.height)); 
+  SkIRect source = IntRectToSkIRect(aSourceRect);
+  mCanvas->clipRect(dest, SkRegion::kReplace_Op);
+  SkPaint paint;
+  paint.setXfermodeMode(GfxOpToSkiaOp(OP_SOURCE));
+  mCanvas->drawBitmapRect(bitmap, &source, dest, &paint);
+  mCanvas->restore();
+}
+
+bool
+DrawTargetSkia::Init(const IntSize &aSize, SurfaceFormat aFormat)
+{
+  mBitmap.setConfig(GfxFormatToSkiaConfig(aFormat), aSize.width, aSize.height);
+  if (!mBitmap.allocPixels()) {
+    return false;
+  }
+  mBitmap.eraseARGB(0, 0, 0, 0);
+  SkAutoTUnref<SkDevice> device(new SkDevice(mBitmap));
+  SkAutoTUnref<SkCanvas> canvas(new SkCanvas(device.get()));
+  mSize = aSize;
+
+  mDevice = device.get();
+  mCanvas = canvas.get();
+  mFormat = aFormat;
+  return true;
+}
+
+void
+DrawTargetSkia::SetTransform(const Matrix& aTransform)
+{
+  SkMatrix mat;
+  GfxMatrixToSkiaMatrix(aTransform, mat);
+  mCanvas->setMatrix(mat);
+  mTransform = aTransform;
+}
+
+TemporaryRef<PathBuilder> 
+DrawTargetSkia::CreatePathBuilder(FillRule aFillRule) const
+{
+  RefPtr<PathBuilderSkia> pb = new PathBuilderSkia(aFillRule);
+  return pb;
+}
+
+void
+DrawTargetSkia::ClearRect(const Rect &aRect)
+{
+  SkPaint paint;
+  mCanvas->save();
+  mCanvas->clipRect(RectToSkRect(aRect), SkRegion::kIntersect_Op);
+  paint.setColor(SkColorSetARGB(0, 0, 0, 0));
+  paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+  mCanvas->drawPaint(paint);
+  mCanvas->restore();
+}
+
+void
+DrawTargetSkia::PushClip(const Path *aPath)
+{
+  if (aPath->GetBackendType() != BACKEND_SKIA) {
+    return;
+  }
+
+  const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath);
+  mCanvas->save(SkCanvas::kClip_SaveFlag);
+  mCanvas->clipPath(skiaPath->GetPath());
+}
+
+void
+DrawTargetSkia::PopClip()
+{
+  mCanvas->restore();
+}
+
+TemporaryRef<GradientStops>
+DrawTargetSkia::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops) const
+{
+  std::vector<GradientStop> stops;
+  stops.resize(aNumStops);
+  for (uint32_t i = 0; i < aNumStops; i++) {
+    stops[i] = aStops[i];
+  }
+  std::stable_sort(stops.begin(), stops.end());
+  
+  return new GradientStopsSkia(stops, aNumStops);
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/2d/DrawTargetSkia.h
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Matt Woodrow <mwoodrow@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#pragma once
+
+#include "skia/SkCanvas.h"
+#include "2D.h"
+#include "Rect.h"
+#include "PathSkia.h"
+#include <sstream>
+using namespace std;
+#include "gfxImageSurface.h"
+
+namespace mozilla {
+namespace gfx {
+
+class DrawTargetSkia : public DrawTarget
+{
+public:
+  DrawTargetSkia();
+  virtual ~DrawTargetSkia();
+
+  virtual BackendType GetType() const { return BACKEND_SKIA; }
+  virtual TemporaryRef<SourceSurface> Snapshot();
+  virtual IntSize GetSize() { return mSize; }
+  virtual void Flush();
+  virtual void DrawSurface(SourceSurface *aSurface,
+                           const Rect &aDest,
+                           const Rect &aSource,
+                           const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(),
+                           const DrawOptions &aOptions = DrawOptions());
+  virtual void DrawSurfaceWithShadow(SourceSurface *aSurface,
+                                     const Point &aDest,
+                                     const Color &aColor,
+                                     const Point &aOffset,
+                                     Float aSigma,
+                                     CompositionOp aOperator);
+  virtual void ClearRect(const Rect &aRect);
+  virtual void CopySurface(SourceSurface *aSurface,
+                           const IntRect &aSourceRect,
+                           const IntPoint &aDestination);
+  virtual void FillRect(const Rect &aRect,
+                        const Pattern &aPattern,
+                        const DrawOptions &aOptions = DrawOptions());
+  virtual void StrokeRect(const Rect &aRect,
+                          const Pattern &aPattern,
+                          const StrokeOptions &aStrokeOptions = StrokeOptions(),
+                          const DrawOptions &aOptions = DrawOptions());
+  virtual void StrokeLine(const Point &aStart,
+                          const Point &aEnd,
+                          const Pattern &aPattern,
+                          const StrokeOptions &aStrokeOptions = StrokeOptions(),
+                          const DrawOptions &aOptions = DrawOptions());
+  virtual void Stroke(const Path *aPath,
+                      const Pattern &aPattern,
+                      const StrokeOptions &aStrokeOptions = StrokeOptions(),
+                      const DrawOptions &aOptions = DrawOptions());
+  virtual void Fill(const Path *aPath,
+                    const Pattern &aPattern,
+                    const DrawOptions &aOptions = DrawOptions());
+  virtual void FillGlyphs(ScaledFont *aFont,
+                          const GlyphBuffer &aBuffer,
+                          const Pattern &aPattern,
+                          const DrawOptions &aOptions = DrawOptions());
+  virtual void PushClip(const Path *aPath);
+  virtual void PopClip();
+  virtual TemporaryRef<SourceSurface> CreateSourceSurfaceFromData(unsigned char *aData,
+                                                            const IntSize &aSize,
+                                                            int32_t aStride,
+                                                            SurfaceFormat aFormat) const;
+  virtual TemporaryRef<SourceSurface> OptimizeSourceSurface(SourceSurface *aSurface) const;
+  virtual TemporaryRef<SourceSurface>
+    CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const;
+  virtual TemporaryRef<DrawTarget>
+    CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const;
+  virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FILL_WINDING) const;
+  virtual TemporaryRef<GradientStops> CreateGradientStops(GradientStop *aStops, uint32_t aNumStops) const;
+  virtual void SetTransform(const Matrix &aTransform);
+
+  bool Init(const IntSize &aSize, SurfaceFormat aFormat);
+  
+  operator std::string() const {
+    std::stringstream stream;
+    stream << "DrawTargetSkia(" << this << ")";
+    return stream.str();
+  }
+private:
+
+  IntSize mSize;
+  SkBitmap mBitmap;
+  SkRefPtr<SkCanvas> mCanvas;
+  SkRefPtr<SkDevice> mDevice;
+  nsRefPtr<gfxImageSurface> mImageSurface;
+  SurfaceFormat mFormat;
+};
+
+}
+}
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -36,22 +36,31 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "2D.h"
 
 #ifdef USE_CAIRO
 #include "DrawTargetCairo.h"
 #endif
 
+#ifdef USE_SKIA
+#include "DrawTargetSkia.h"
+#ifdef XP_MACOSX
+#include "ScaledFontMac.h"
+#endif
+#include "ScaledFontSkia.h"
+#endif
+
 #ifdef WIN32
 #include "DrawTargetD2D.h"
 #include "ScaledFontDWrite.h"
 #include <d3d10_1.h>
 #endif
 
+
 #include "Logging.h"
 
 #ifdef PR_LOGGING
 PRLogModuleInfo *sGFX2DLog = PR_NewLogModule("gfx2d");
 #endif
 
 namespace mozilla {
 namespace gfx {
@@ -73,16 +82,27 @@ Factory::CreateDrawTarget(BackendType aB
       RefPtr<DrawTargetD2D> newTarget;
       newTarget = new DrawTargetD2D();
       if (newTarget->Init(aSize, aFormat)) {
         return newTarget;
       }
       break;
     }
 #endif
+#ifdef USE_SKIA
+  case BACKEND_SKIA:
+    {
+      RefPtr<DrawTargetSkia> newTarget;
+      newTarget = new DrawTargetSkia();
+      if (newTarget->Init(aSize, aFormat)) {
+        return newTarget;
+      }
+      break;
+    }
+#endif
   default:
     gfxDebug() << "Invalid draw target type specified.";
     return NULL;
   }
 
   gfxDebug() << "Failed to create DrawTarget, Type: " << aBackend << " Size: " << aSize;
   // Failed
   return NULL;
@@ -93,16 +113,28 @@ Factory::CreateScaledFontForNativeFont(c
 {
   switch (aNativeFont.mType) {
 #ifdef WIN32
   case NATIVE_FONT_DWRITE_FONT_FACE:
     {
       return new ScaledFontDWrite(static_cast<IDWriteFontFace*>(aNativeFont.mFont), aSize);
     }
 #endif
+#ifdef USE_SKIA
+#ifdef XP_MACOSX
+  case NATIVE_FONT_MAC_FONT_FACE:
+    {
+      return new ScaledFontMac(static_cast<CGFontRef>(aNativeFont.mFont), aSize);
+    }
+#endif
+  case NATIVE_FONT_SKIA_FONT_FACE:
+    {
+      return new ScaledFontSkia(static_cast<gfxFont*>(aNativeFont.mFont), aSize);
+    }
+#endif
   default:
     gfxWarning() << "Invalid native font type specified.";
     return NULL;
   }
 }
 
 #ifdef WIN32
 TemporaryRef<DrawTarget>
new file mode 100644
--- /dev/null
+++ b/gfx/2d/HelpersSkia.h
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Matt Woodrow <mwoodrow@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef MOZILLA_GFX_HELPERSSKIA_H_
+#define MOZILLA_GFX_HELPERSSKIA_H_
+
+#include "2D.h"
+#include "skia/SkCanvas.h"
+
+namespace mozilla {
+namespace gfx {
+
+static inline SkBitmap::Config
+GfxFormatToSkiaConfig(SurfaceFormat format)
+{
+  switch (format)
+  {
+    case FORMAT_B8G8R8A8:
+      return SkBitmap::kARGB_8888_Config;
+    case FORMAT_B8G8R8X8:
+      // We probably need to do something here.
+      return SkBitmap::kARGB_8888_Config;
+    case FORMAT_R5G6B5:
+      return SkBitmap::kRGB_565_Config;
+    case FORMAT_A8:
+      return SkBitmap::kA8_Config;
+
+  }
+
+  return SkBitmap::kARGB_8888_Config;
+}
+
+static inline void
+GfxMatrixToSkiaMatrix(const Matrix& mat, SkMatrix& retval)
+{
+    retval.setAll(SkFloatToScalar(mat._11), SkFloatToScalar(mat._21), SkFloatToScalar(mat._31),
+                  SkFloatToScalar(mat._12), SkFloatToScalar(mat._22), SkFloatToScalar(mat._32),
+                  0, 0, SK_Scalar1);
+}
+
+}
+}
+
+#endif /* MOZILLA_GFX_HELPERSSKIA_H_ */
--- a/gfx/2d/Makefile.in
+++ b/gfx/2d/Makefile.in
@@ -64,18 +64,42 @@ EXPORTS_mozilla/gfx	= \
 
 CPPSRCS	= \
 	Factory.cpp \
         Matrix.cpp \
         DrawTargetCairo.cpp \
         SourceSurfaceCairo.cpp \
         $(NULL)
 
+
 DEFINES += -DMOZ_GFX -DUSE_CAIRO
 
+ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
+CPPSRCS	+= \
+		SourceSurfaceSkia.cpp \
+		DrawTargetSkia.cpp \
+		PathSkia.cpp \
+        ScaledFontSkia.cpp \
+		ScaledFontMac.cpp \
+        $(NULL)
+DEFINES += -DUSE_SKIA
+endif
+
+ifeq (android,$(MOZ_WIDGET_TOOLKIT))
+CPPSRCS	+= \
+		SourceSurfaceSkia.cpp \
+		DrawTargetSkia.cpp \
+        ScaledFontSkia.cpp \
+		PathSkia.cpp \
+        $(NULL)
+DEFINES += -DUSE_SKIA -DSK_BUILD_FOR_ANDROID_NDK
+endif
+
+DEFINES += -DSK_A32_SHIFT=24 -DSK_R32_SHIFT=16 -DSK_G32_SHIFT=8 -DSK_B32_SHIFT=0
+
 ifdef MOZ_DEBUG
 DEFINES += -DGFX_LOG_DEBUG -DGFX_LOG_WARNING
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 CPPSRCS	+= \
         DrawTargetD2D.cpp \
         SourceSurfaceD2D.cpp \
new file mode 100644
--- /dev/null
+++ b/gfx/2d/PathSkia.cpp
@@ -0,0 +1,266 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *     Matt Woodrow <mwoodrow@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "PathSkia.h"
+#include <math.h>
+#include "DrawTargetSkia.h"
+#include "Logging.h"
+#include "HelpersSkia.h"
+
+namespace mozilla {
+namespace gfx {
+
+PathBuilderSkia::PathBuilderSkia(const Matrix& aTransform, const SkPath& aPath, FillRule aFillRule)
+  : mPath(aPath)
+{
+  SkMatrix matrix;
+  GfxMatrixToSkiaMatrix(aTransform, matrix);
+  mPath.transform(matrix);
+  SetFillRule(aFillRule);
+}
+
+PathBuilderSkia::PathBuilderSkia(FillRule aFillRule)
+{
+  SetFillRule(aFillRule);
+}
+
+void
+PathBuilderSkia::SetFillRule(FillRule aFillRule)
+{
+  mFillRule = aFillRule;
+  if (mFillRule == FILL_WINDING) {
+    mPath.setFillType(SkPath::kWinding_FillType);
+  } else {
+    mPath.setFillType(SkPath::kEvenOdd_FillType);
+  }
+}
+
+void
+PathBuilderSkia::MoveTo(const Point &aPoint)
+{
+  mPath.moveTo(SkFloatToScalar(aPoint.x), SkFloatToScalar(aPoint.y));
+}
+
+void
+PathBuilderSkia::LineTo(const Point &aPoint)
+{
+  if (!mPath.countPoints()) {
+    MoveTo(aPoint);
+  } else {
+    mPath.lineTo(SkFloatToScalar(aPoint.x), SkFloatToScalar(aPoint.y));
+  }
+}
+
+void
+PathBuilderSkia::BezierTo(const Point &aCP1,
+                          const Point &aCP2,
+                          const Point &aCP3)
+{
+  if (!mPath.countPoints()) {
+    MoveTo(aCP1);
+  }
+  mPath.cubicTo(SkFloatToScalar(aCP1.x), SkFloatToScalar(aCP1.y),
+                SkFloatToScalar(aCP2.x), SkFloatToScalar(aCP2.y),
+                SkFloatToScalar(aCP3.x), SkFloatToScalar(aCP3.y));
+}
+
+void
+PathBuilderSkia::QuadraticBezierTo(const Point &aCP1,
+                                   const Point &aCP2)
+{
+  if (!mPath.countPoints()) {
+    MoveTo(aCP1);
+  }
+  mPath.quadTo(SkFloatToScalar(aCP1.x), SkFloatToScalar(aCP1.y),
+               SkFloatToScalar(aCP2.x), SkFloatToScalar(aCP2.y));
+}
+
+void
+PathBuilderSkia::Close()
+{
+  mPath.close();
+}
+
+void
+PathBuilderSkia::Arc(const Point &aOrigin, float aRadius, float aStartAngle,
+                     float aEndAngle, bool aAntiClockwise)
+{ 
+  //TODO: Taken directly from azure canvas, we should share this somewhere
+  Point startPoint(aOrigin.x + cos(aStartAngle) * aRadius, 
+                   aOrigin.y + sin(aStartAngle) * aRadius); 
+  
+  LineTo(startPoint); 
+
+  // Clockwise we always sweep from the smaller to the larger angle, ccw 
+  // it's vice versa.
+  if (!aAntiClockwise && (aEndAngle < aStartAngle)) {
+    Float correction = ceil((aStartAngle - aEndAngle) / (2.0f * M_PI));
+    aEndAngle += correction * 2.0f * M_PI;
+  } else if (aAntiClockwise && (aStartAngle < aEndAngle)) {
+    Float correction = ceil((aEndAngle - aStartAngle) / (2.0f * M_PI));
+    aStartAngle += correction * 2.0f * M_PI;
+  }                                                                                                                                     
+  
+  // Sweeping more than 2 * pi is a full circle.
+  if (!aAntiClockwise && (aEndAngle - aStartAngle > 2 * M_PI)) {
+    aEndAngle = aStartAngle + 2.0f * M_PI;
+  } else if (aAntiClockwise && (aStartAngle - aEndAngle > 2.0f * M_PI)) {
+    aEndAngle = aStartAngle - 2.0f * M_PI;
+  }
+
+  // Calculate the total arc we're going to sweep.
+  Float arcSweepLeft = fabs(aEndAngle - aStartAngle);
+  
+  Float sweepDirection = aAntiClockwise ? -1.0f : 1.0f;
+  
+  Float currentStartAngle = aStartAngle;
+  
+  while (arcSweepLeft > 0) {
+    // We guarantee here the current point is the start point of the next
+    // curve segment.
+    Float currentEndAngle;
+    
+    if (arcSweepLeft > M_PI / 2.0f) {
+      currentEndAngle = currentStartAngle + M_PI / 2.0f * sweepDirection;                                                               
+    } else {
+      currentEndAngle = currentStartAngle + arcSweepLeft * sweepDirection;
+    }
+    
+    Point currentStartPoint(aOrigin.x + cos(currentStartAngle) * aRadius,
+                            aOrigin.y + sin(currentStartAngle) * aRadius);
+    Point currentEndPoint(aOrigin.x + cos(currentEndAngle) * aRadius,
+                          aOrigin.y + sin(currentEndAngle) * aRadius);
+    
+    // Calculate kappa constant for partial curve. The sign of angle in the
+    // tangent will actually ensure this is negative for a counter clockwise                                                            
+    // sweep, so changing signs later isn't needed.
+    Float kappa = (4.0f / 3.0f) * tan((currentEndAngle - currentStartAngle) / 4.0f) * aRadius;
+    
+    Point tangentStart(-sin(currentStartAngle), cos(currentStartAngle));
+    Point cp1 = currentStartPoint;
+    cp1 += tangentStart * kappa;
+    
+    Point revTangentEnd(sin(currentEndAngle), -cos(currentEndAngle));
+    Point cp2 = currentEndPoint;
+    cp2 += revTangentEnd * kappa;
+    
+    BezierTo(cp1, cp2, currentEndPoint);
+    
+    arcSweepLeft -= M_PI / 2.0f;
+    currentStartAngle = currentEndAngle;
+  }
+}
+
+Point
+PathBuilderSkia::CurrentPoint() const
+{
+  int pointCount = mPath.countPoints();
+  if (!pointCount) {
+    return Point(0, 0);
+  }
+  SkPoint point = mPath.getPoint(pointCount - 1);
+  return Point(SkScalarToFloat(point.fX), SkScalarToFloat(point.fY));
+}
+
+TemporaryRef<Path>
+PathBuilderSkia::Finish()
+{
+  RefPtr<PathSkia> path = new PathSkia(mPath, mFillRule);
+  return path;
+}
+
+TemporaryRef<PathBuilder>
+PathSkia::CopyToBuilder(FillRule aFillRule) const
+{
+  return TransformedCopyToBuilder(Matrix(), aFillRule);
+}
+
+TemporaryRef<PathBuilder>
+PathSkia::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const
+{
+  RefPtr<PathBuilderSkia> builder = new PathBuilderSkia(aTransform, mPath, aFillRule);
+  return builder;
+}
+
+bool
+PathSkia::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const
+{
+  Matrix inverse = aTransform;
+  inverse.Invert();
+  Point transformed = inverse * aPoint;
+
+  Rect bounds = GetBounds(aTransform);
+
+  if (aPoint.x < bounds.x || aPoint.y < bounds.y ||
+      aPoint.x > bounds.XMost() || aPoint.y > bounds.YMost()) {
+    return false;
+  }
+
+  SkRegion pointRect;
+  pointRect.setRect(SkFloatToScalar(transformed.x - 1), SkFloatToScalar(transformed.y - 1), 
+                    SkFloatToScalar(transformed.x + 1), SkFloatToScalar(transformed.y + 1));
+
+  SkRegion pathRegion;
+  
+  return pathRegion.setPath(mPath, pointRect);
+}
+
+static Rect SkRectToRect(const SkRect& aBounds)
+{
+  return Rect(SkScalarToFloat(aBounds.fLeft),
+              SkScalarToFloat(aBounds.fTop),
+              SkScalarToFloat(aBounds.fRight - aBounds.fLeft),
+              SkScalarToFloat(aBounds.fBottom - aBounds.fTop));
+}
+
+Rect
+PathSkia::GetBounds(const Matrix &aTransform) const
+{
+  Rect bounds = SkRectToRect(mPath.getBounds());
+  return aTransform.TransformBounds(bounds);
+}
+
+Rect
+PathSkia::GetStrokedBounds(const StrokeOptions &aStrokeOptions,
+                           const Matrix &aTransform) const
+{
+  NS_ASSERTION(false, "GetStrokedBounds not supported yet!");
+  return Rect(0, 0, 0, 0);
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/2d/PathSkia.h
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *     Matt Woodrow <mwoodrow@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef MOZILLA_GFX_PATH_SKIA_H_
+#define MOZILLA_GFX_PATH_SKIA_H_
+
+#include "2D.h"
+#include "skia/SkPath.h"
+
+namespace mozilla {
+namespace gfx {
+
+class PathSkia;
+
+class PathBuilderSkia : public PathBuilder
+{
+public:
+  PathBuilderSkia(const Matrix& aTransform, const SkPath& aPath, FillRule aFillRule);
+  PathBuilderSkia(FillRule aFillRule);
+
+  virtual void MoveTo(const Point &aPoint);
+  virtual void LineTo(const Point &aPoint);
+  virtual void BezierTo(const Point &aCP1,
+                        const Point &aCP2,
+                        const Point &aCP3);
+  virtual void QuadraticBezierTo(const Point &aCP1,
+                                 const Point &aCP2);
+  virtual void Close();
+  virtual void Arc(const Point &aOrigin, float aRadius, float aStartAngle,
+                   float aEndAngle, bool aAntiClockwise = false);
+  virtual Point CurrentPoint() const;
+  virtual TemporaryRef<Path> Finish();
+
+private:
+  void SetFillRule(FillRule aFillRule);
+
+  SkPath mPath;
+  FillRule mFillRule;
+};
+
+class PathSkia : public Path
+{
+public:
+  PathSkia(SkPath& aPath, FillRule aFillRule)
+    : mFillRule(aFillRule)
+  {
+    mPath.swap(aPath);
+  }
+  
+  virtual BackendType GetBackendType() const { return BACKEND_SKIA; }
+
+  virtual TemporaryRef<PathBuilder> CopyToBuilder(FillRule aFillRule = FILL_WINDING) const;
+  virtual TemporaryRef<PathBuilder> TransformedCopyToBuilder(const Matrix &aTransform,
+                                                             FillRule aFillRule = FILL_WINDING) const;
+
+  virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const;
+  
+  virtual Rect GetBounds(const Matrix &aTransform = Matrix()) const;
+  
+  virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions,
+                                const Matrix &aTransform = Matrix()) const;
+
+  virtual FillRule GetFillRule() const { return mFillRule; }
+
+  const SkPath& GetPath() const { return mPath; }
+
+private:
+  friend class DrawTargetSkia;
+  
+  SkPath mPath;
+  FillRule mFillRule;
+};
+
+}
+}
+
+#endif /* MOZILLA_GFX_PATH_SKIA_H_ */
new file mode 100644
--- /dev/null
+++ b/gfx/2d/ScaledFontMac.cpp
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Matt Woodrow <mwoodrow@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "ScaledFontMac.h"
+#include "PathSkia.h"
+#include "skia/SkPaint.h"
+#include "skia/SkPath.h"
+#include "skia/SkTypeface_mac.h"
+#include <vector>
+
+namespace mozilla {
+namespace gfx {
+
+ScaledFontMac::ScaledFontMac(CGFontRef aFont, Float aSize)
+  : ScaledFontSkia(aSize)
+{
+  mFontFace = CTFontCreateWithGraphicsFont(aFont, aSize, NULL, NULL);
+  mTypeface = SkCreateTypefaceFromCTFont(mFontFace);
+}
+
+ScaledFontMac::~ScaledFontMac()
+{
+  CFRelease(mFontFace);
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/2d/ScaledFontMac.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Matt Woodrow <mwoodrow@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef MOZILLA_GFX_SCALEDFONTMAC_H_
+#define MOZILLA_GFX_SCALEDFONTMAC_H_
+
+#include "ScaledFontSkia.h"
+#import <ApplicationServices/ApplicationServices.h>
+
+
+namespace mozilla {
+namespace gfx {
+
+class ScaledFontMac : public ScaledFontSkia
+{
+public:
+  ScaledFontMac(CGFontRef aFont, Float aSize);
+  virtual ~ScaledFontMac();
+
+  virtual FontType GetType() const { return FONT_MAC; }
+
+private:
+  friend class DrawTargetSkia;
+
+  CTFontRef mFontFace;
+};
+
+}
+}
+
+#endif /* MOZILLA_GFX_SCALEDFONTMAC_H_ */
new file mode 100755
--- /dev/null
+++ b/gfx/2d/ScaledFontSkia.cpp
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Matt Woodrow <mwoodrow@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "ScaledFontSkia.h"
+#include "PathSkia.h"
+#include "skia/SkPaint.h"
+#include "skia/SkPath.h"
+#include <vector>
+#include <cmath>
+using namespace std;
+#include "gfxFont.h"
+
+namespace mozilla {
+namespace gfx {
+
+static SkTypeface::Style gfxFontStyleToSkia(const gfxFontStyle* aStyle)
+{
+  if (aStyle->style == NS_FONT_STYLE_ITALIC) {
+    if (aStyle->weight == NS_FONT_WEIGHT_BOLD) {
+      return SkTypeface::kBoldItalic;
+    }
+    return SkTypeface::kItalic;
+  }
+  if (aStyle->weight == NS_FONT_WEIGHT_BOLD) {
+    return SkTypeface::kBold;
+  }
+  return SkTypeface::kNormal;
+}
+
+ScaledFontSkia::ScaledFontSkia(gfxFont* aFont, Float aSize)
+  : mSize(aSize)
+{
+  NS_LossyConvertUTF16toASCII name(aFont->GetName());
+  mTypeface = SkTypeface::CreateFromName(name.get(), gfxFontStyleToSkia(aFont->GetStyle()));
+}
+
+ScaledFontSkia::ScaledFontSkia(Float aSize)
+  : mSize(aSize)
+{
+}
+
+ScaledFontSkia::~ScaledFontSkia()
+{
+  SkSafeUnref(mTypeface);
+}
+
+TemporaryRef<Path>
+ScaledFontSkia::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget)
+{
+  if (aTarget->GetType() != BACKEND_SKIA) {
+    return NULL;
+  }
+
+  SkPaint paint;
+  paint.setTypeface(mTypeface);
+  paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+  paint.setTextSize(SkFloatToScalar(mSize));
+  
+  std::vector<uint16_t> indices;
+  std::vector<SkPoint> offsets;
+  indices.resize(aBuffer.mNumGlyphs);
+  offsets.resize(aBuffer.mNumGlyphs);
+
+  for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) {
+    indices[i] = aBuffer.mGlyphs[i].mIndex;
+    offsets[i].fX = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.x);
+    offsets[i].fY = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.y);
+  }
+
+  SkPath path;
+  paint.getPosTextPath(&indices.front(), aBuffer.mNumGlyphs*2, &offsets.front(), &path);
+  return new PathSkia(path, FILL_WINDING);
+}
+
+}
+}
new file mode 100755
--- /dev/null
+++ b/gfx/2d/ScaledFontSkia.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Matt Woodrow <mwoodrow@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef MOZILLA_GFX_SCALEDFONTSKIA_H_
+#define MOZILLA_GFX_SCALEDFONTSKIA_H_
+
+#include "2D.h"
+#include "skia/SkTypeface.h"
+
+class gfxFont;
+
+namespace mozilla {
+namespace gfx {
+
+class ScaledFontSkia : public ScaledFont
+{
+public:
+  ScaledFontSkia(gfxFont* aFont, Float aSize);
+  ScaledFontSkia(Float aSize);
+  virtual ~ScaledFontSkia();
+
+  virtual FontType GetType() const { return FONT_SKIA; }
+
+  virtual TemporaryRef<Path> GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget);
+
+protected:
+  friend class DrawTargetSkia;
+
+  SkTypeface* mTypeface;
+  Float mSize;
+};
+
+}
+}
+
+#endif /* MOZILLA_GFX_SCALEDFONTSKIA_H_ */
new file mode 100644
--- /dev/null
+++ b/gfx/2d/SourceSurfaceSkia.cpp
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Matt Woodrow <mwoodrow@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "Logging.h"
+#include "SourceSurfaceSkia.h"
+#include "skia/SkBitmap.h"
+#include "skia/SkDevice.h"
+#include "HelpersSkia.h"
+
+namespace mozilla {
+namespace gfx {
+
+SourceSurfaceSkia::SourceSurfaceSkia()
+{
+}
+
+SourceSurfaceSkia::~SourceSurfaceSkia()
+{
+}
+
+IntSize
+SourceSurfaceSkia::GetSize() const
+{
+  return mSize;
+}
+
+SurfaceFormat
+SourceSurfaceSkia::GetFormat() const
+{
+  return mFormat;
+}
+
+bool 
+SourceSurfaceSkia::InitFromData(unsigned char* aData,
+                                const IntSize &aSize,
+                                int32_t aStride,
+                                SurfaceFormat aFormat)
+{
+  mBitmap.setConfig(GfxFormatToSkiaConfig(aFormat), aSize.width, aSize.height, aStride);
+  if (!mBitmap.allocPixels()) {
+    return false;
+  }
+  
+  if (!mBitmap.copyPixelsFrom(aData, mBitmap.getSafeSize(), aStride)) {
+    return false;
+  }
+  mSize = aSize;
+  mFormat = aFormat;
+  mStride = aStride;
+  return true;
+}
+
+bool
+SourceSurfaceSkia::InitWithBitmap(SkCanvas* aBitmap,
+                                  SurfaceFormat aFormat)
+{
+  if (aBitmap->readPixels(&mBitmap)) {
+    mStride = mBitmap.rowBytes();
+    mSize = IntSize(mBitmap.width(), mBitmap.height());
+    mFormat = aFormat;
+    return true;
+  }
+  return false;
+}
+
+unsigned char*
+SourceSurfaceSkia::GetData()
+{
+  mBitmap.lockPixels();
+  unsigned char *pixels = (unsigned char *)mBitmap.getPixels();
+  mBitmap.unlockPixels();
+  return pixels;
+
+}
+
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/2d/SourceSurfaceSkia.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Matt Woodrow <mwoodrow@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef MOZILLA_GFX_SOURCESURFACESKIA_H_
+#define MOZILLA_GFX_SOURCESURFACESKIA_H_
+
+#include "2D.h"
+#include <vector>
+#include "skia/SkCanvas.h"
+#include "skia/SkBitmap.h"
+
+namespace mozilla {
+namespace gfx {
+
+class SourceSurfaceSkia : public DataSourceSurface
+{
+public:
+  SourceSurfaceSkia();
+  ~SourceSurfaceSkia();
+
+  virtual SurfaceType GetType() const { return SURFACE_SKIA; }
+  virtual IntSize GetSize() const;
+  virtual SurfaceFormat GetFormat() const;
+
+  SkBitmap& GetBitmap() { return mBitmap; }
+
+  bool InitFromData(unsigned char* aData,
+                    const IntSize &aSize,
+                    int32_t aStride,
+                    SurfaceFormat aFormat);
+
+  bool InitWithBitmap(SkCanvas* aBitmap,
+                      SurfaceFormat aFormat);
+
+
+  virtual unsigned char *GetData();
+
+  virtual int32_t Stride() { return mStride; }
+
+private:
+  friend class DrawTargetSkia;
+
+  SkBitmap mBitmap;
+  SurfaceFormat mFormat;
+  IntSize mSize;
+  int32_t mStride;
+};
+
+}
+}
+
+#endif /* MOZILLA_GFX_SOURCESURFACESKIA_H_ */
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -63,46 +63,53 @@ namespace gfx {
 typedef float Float;
 
 enum SurfaceType
 {
   SURFACE_DATA, /* Data surface - bitmap in memory */
   SURFACE_D2D1_BITMAP, /* Surface wrapping a ID2D1Bitmap */
   SURFACE_D2D1_DRAWTARGET, /* Surface made from a D2D draw target */
   SURFACE_CAIRO, /* Surface wrapping a cairo surface */
-  SURFACE_COREGRAPHICS_IMAGE /* Surface wrapping a CoreGraphics Image */
+  SURFACE_COREGRAPHICS_IMAGE, /* Surface wrapping a CoreGraphics Image */
+  SURFACE_SKIA /* Surface wrapping a Skia bitmap */
 };
 
 enum SurfaceFormat
 {
   FORMAT_B8G8R8A8,
   FORMAT_B8G8R8X8,
+  FORMAT_R5G6B5,
   FORMAT_A8
 };
 
 enum BackendType
 {
   BACKEND_DIRECT2D,
   BACKEND_COREGRAPHICS,
-  BACKEND_CAIRO
+  BACKEND_CAIRO,
+  BACKEND_SKIA
 };
 
 enum FontType
 {
-  FONT_DWRITE
+  FONT_DWRITE,
+  FONT_MAC,
+  FONT_SKIA
 };
 
 enum NativeSurfaceType
 {
   NATIVE_SURFACE_D3D10_TEXTURE
 };
 
 enum NativeFontType
 {
-  NATIVE_FONT_DWRITE_FONT_FACE
+  NATIVE_FONT_DWRITE_FONT_FACE,
+  NATIVE_FONT_MAC_FONT_FACE,
+  NATIVE_FONT_SKIA_FONT_FACE
 };
 
 enum CompositionOp { OP_OVER, OP_ADD, OP_ATOP, OP_OUT, OP_IN, OP_SOURCE, OP_DEST_IN, OP_DEST_OUT, OP_DEST_OVER, OP_DEST_ATOP, OP_XOR, OP_COUNT };
 enum ExtendMode { EXTEND_CLAMP, EXTEND_WRAP, EXTEND_MIRROR };
 enum FillRule { FILL_WINDING, FILL_EVEN_ODD };
 enum AntialiasMode { AA_NONE, AA_GRAY, AA_SUBPIXEL };
 enum Snapping { SNAP_NONE, SNAP_ALIGNED };
 enum Filter { FILTER_LINEAR, FILTER_POINT };
@@ -134,16 +141,20 @@ public:
     return newColor;
   }
 
   Float r, g, b, a;
 };
 
 struct GradientStop
 {
+  bool operator<(const GradientStop& aOther) const {
+    return offset < aOther.offset;
+  }
+
   Float offset;
   Color color;
 };
 
 }
 }
 
 // Side constants for use in various places
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -32,24 +32,27 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "gfxAndroidPlatform.h"
+#include "mozilla/gfx/2D.h"
 
 #include "gfxFT2FontList.h"
 #include "gfxImageSurface.h"
 
 #include "cairo.h"
 
 #include "ft2build.h"
 #include FT_FREETYPE_H
+using namespace mozilla;
+using namespace mozilla::gfx;
 
 static FT_Library gPlatformFTLibrary = NULL;
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "GeckoFonts" , ## args)
 
 gfxAndroidPlatform::gfxAndroidPlatform()
 {
     FT_Init_FreeType(&gPlatformFTLibrary);
@@ -175,8 +178,20 @@ gfxFontEntry*
 gfxAndroidPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
                                      const PRUint8 *aFontData, PRUint32 aLength)
 {
     return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry,
                                                                      aFontData,
                                                                      aLength);
 }
 
+RefPtr<ScaledFont>
+gfxAndroidPlatform::GetScaledFontForFont(gfxFont *aFont)
+{
+    NativeFont nativeFont;
+    nativeFont.mType = NATIVE_FONT_SKIA_FONT_FACE;
+    nativeFont.mFont = aFont;
+    RefPtr<ScaledFont> scaledFont =
+      Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
+
+    return scaledFont;
+}
+
--- a/gfx/thebes/gfxAndroidPlatform.h
+++ b/gfx/thebes/gfxAndroidPlatform.h
@@ -62,16 +62,19 @@ public:
         return (gfxAndroidPlatform*) gfxPlatform::GetPlatform();
     }
 
     virtual already_AddRefed<gfxASurface>
     CreateOffscreenSurface(const gfxIntSize& size,
                            gfxASurface::gfxContentType contentType);
 
     virtual gfxImageFormat GetOffscreenFormat() { return gfxASurface::ImageFormatRGB16_565; }
+    
+    mozilla::RefPtr<mozilla::gfx::ScaledFont>
+      GetScaledFontForFont(gfxFont *aFont);
 
     // to support IPC font list (sharing between chrome and content)
     void GetFontList(InfallibleTArray<FontListEntry>* retValue);
 
     // platform implementations of font functions
     virtual bool IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags);
     virtual gfxPlatformFontList* CreatePlatformFontList();
     virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -474,16 +474,34 @@ gfxPlatform::GetSourceSurfaceForSurface(
     if (!imgSurface) {
       imgSurface = new gfxImageSurface(aSurface->GetSize(), gfxASurface::FormatFromContent(aSurface->GetContentType()));
       nsRefPtr<gfxContext> ctx = new gfxContext(imgSurface);
       ctx->SetSource(aSurface);
       ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
       ctx->Paint();
     }
 
+    gfxImageFormat cairoFormat = imgSurface->Format();
+    switch(cairoFormat) {
+      case gfxASurface::ImageFormatARGB32:
+        format = FORMAT_B8G8R8A8;
+        break;
+      case gfxASurface::ImageFormatRGB24:
+        format = FORMAT_B8G8R8X8;
+        break;
+      case gfxASurface::ImageFormatA8:
+        format = FORMAT_A8;
+        break;
+      case gfxASurface::ImageFormatRGB16_565:
+        format = FORMAT_R5G6B5;
+        break;
+      default:
+        NS_RUNTIMEABORT("Invalid surface format!");
+    }
+
     srcBuffer = aTarget->CreateSourceSurfaceFromData(imgSurface->Data(),
                                                      IntSize(imgSurface->GetSize().width, imgSurface->GetSize().height),
                                                      imgSurface->Stride(),
                                                      format);
   }
 
   srcBuffer->AddRef();
   aSurface->SetData(&kSourceSurface, srcBuffer, SourceBufferDestroy);
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -137,17 +137,17 @@ gfxPlatformMac::CreateOffscreenSurface(c
 
     NS_IF_ADDREF(newSurface);
     return newSurface;
 }
     
 RefPtr<DrawTarget>
 gfxPlatformMac::CreateOffscreenDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
 {
-  return NULL;
+  return Factory::CreateDrawTarget(BACKEND_SKIA, aSize, aFormat);
 }
 
 already_AddRefed<gfxASurface>
 gfxPlatformMac::OptimizeImage(gfxImageSurface *aSurface,
                               gfxASurface::gfxImageFormat format)
 {
     const gfxIntSize& surfaceSize = aSurface->GetSize();
     nsRefPtr<gfxImageSurface> isurf = aSurface;
@@ -160,16 +160,30 @@ gfxPlatformMac::OptimizeImage(gfxImageSu
             return aSurface;
         }
     }
 
     nsRefPtr<gfxASurface> ret = new gfxQuartzImageSurface(isurf);
     return ret.forget();
 }
 
+RefPtr<ScaledFont>
+gfxPlatformMac::GetScaledFontForFont(gfxFont *aFont)
+{
+    gfxMacFont *font = static_cast<gfxMacFont*>(aFont);
+
+    NativeFont nativeFont;
+    nativeFont.mType = NATIVE_FONT_MAC_FONT_FACE;
+    nativeFont.mFont = font->GetCGFontRef();
+    RefPtr<ScaledFont> scaledFont =
+      mozilla::gfx::Factory::CreateScaledFontForNativeFont(nativeFont, font->GetAdjustedSize());
+
+    return scaledFont;
+}
+
 nsresult
 gfxPlatformMac::ResolveFontName(const nsAString& aFontName,
                                 FontResolverCallback aCallback,
                                 void *aClosure, bool& aAborted)
 {
     nsAutoString resolvedName;
     if (!gfxPlatformFontList::PlatformFontList()->
              ResolveFontName(aFontName, resolvedName)) {
--- a/gfx/thebes/gfxPlatformMac.h
+++ b/gfx/thebes/gfxPlatformMac.h
@@ -62,16 +62,19 @@ public:
     already_AddRefed<gfxASurface> CreateOffscreenSurface(const gfxIntSize& size,
                                                          gfxASurface::gfxContentType contentType);
     
     virtual mozilla::RefPtr<mozilla::gfx::DrawTarget>
       CreateOffscreenDrawTarget(const mozilla::gfx::IntSize& aSize, mozilla::gfx::SurfaceFormat aFormat);
 
     already_AddRefed<gfxASurface> OptimizeImage(gfxImageSurface *aSurface,
                                                 gfxASurface::gfxImageFormat format);
+    
+    mozilla::RefPtr<mozilla::gfx::ScaledFont>
+      GetScaledFontForFont(gfxFont *aFont);
 
     nsresult ResolveFontName(const nsAString& aFontName,
                              FontResolverCallback aCallback,
                              void *aClosure, bool& aAborted);
 
     nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
 
     gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,