Roll skia to 8cc209111876b7c78b5ec577c9221d8ed5e21024

Replaced all uses of skia::RefPtr<> with sk_sp<>.

Updated build scripts, largely borrowing changes from Flutter
with some modifications for running in a pure Mojo environment.
We could probably delete more of the support code for native
platforms but I'll leave that for later.

Added optimized convolution algorithms since they might be
useful for composition and they were already in the Flutter repo.

R=mikejurka@google.com

Review URL: https://codereview.chromium.org/2011713003 .
diff --git a/DEPS b/DEPS
index d7bf80a..58ffb77 100644
--- a/DEPS
+++ b/DEPS
@@ -19,7 +19,7 @@
 
 vars = {
   'chromium_git': 'https://chromium.googlesource.com',
-  'skia_revision': 'db284c52e62e8d16708e2065495a3b693b238771',
+  'skia_revision': '8cc209111876b7c78b5ec577c9221d8ed5e21024',
   'v8_revision': '3f036fc0ba4ca4483fe77822f8605c277d37ee24',
   'base_revision': '163fb42027bea947916ba4d2fa03aa0ed7c3f99e',
   'angle_revision': '46ccef1992a8ede16a596c3dd73cff13c047267d',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index abde026..7b8d174 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -87,7 +87,7 @@
       'SkRefPtr',
       (
         'The use of SkRefPtr is prohibited. ',
-        'Please use skia::RefPtr instead.'
+        'Please use sk_sp instead.'
       ),
       True,
       (),
@@ -96,7 +96,7 @@
       'SkAutoRef',
       (
         'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
-        'Please use skia::RefPtr instead.'
+        'Please use sk_sp instead.'
       ),
       True,
       (),
@@ -105,7 +105,7 @@
       'SkAutoTUnref',
       (
         'The use of SkAutoTUnref is dangerous because it implicitly ',
-        'converts to a raw pointer. Please use skia::RefPtr instead.'
+        'converts to a raw pointer. Please use sk_sp instead.'
       ),
       True,
       (),
@@ -115,7 +115,7 @@
       (
         'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
         'because it implicitly converts to a raw pointer. ',
-        'Please use skia::RefPtr instead.'
+        'Please use sk_sp instead.'
       ),
       True,
       (),
diff --git a/apps/moterm/moterm_view.cc b/apps/moterm/moterm_view.cc
index 43cb2fc..a31b6d7 100644
--- a/apps/moterm/moterm_view.cc
+++ b/apps/moterm/moterm_view.cc
@@ -65,13 +65,13 @@
     });
   }
 
-  regular_typeface_ = skia::AdoptRef(SkTypeface::CreateFromStream(
+  regular_typeface_ = SkTypeface::MakeFromStream(
       new SkMemoryStream(font_data::kDejaVuSansMonoRegular.data,
-                         font_data::kDejaVuSansMonoRegular.size)));
+                         font_data::kDejaVuSansMonoRegular.size));
 
   // TODO(vtl): This duplicates some code.
   SkPaint fg_paint;
-  fg_paint.setTypeface(regular_typeface_.get());
+  fg_paint.setTypeface(regular_typeface_);
   fg_paint.setTextSize(16);
   // Figure out appropriate metrics.
   SkPaint::FontMetrics fm = {};
@@ -275,7 +275,7 @@
   bg_paint.setStyle(SkPaint::kFill_Style);
 
   SkPaint fg_paint;
-  fg_paint.setTypeface(regular_typeface_.get());
+  fg_paint.setTypeface(regular_typeface_);
   fg_paint.setTextSize(16);
   fg_paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
 
diff --git a/apps/moterm/moterm_view.h b/apps/moterm/moterm_view.h
index a98f29d..8dce276 100644
--- a/apps/moterm/moterm_view.h
+++ b/apps/moterm/moterm_view.h
@@ -101,7 +101,7 @@
   // If we skip drawing despite being forced to, we should force the next draw.
   bool force_next_draw_;
 
-  skia::RefPtr<SkTypeface> regular_typeface_;
+  sk_sp<SkTypeface> regular_typeface_;
 
   int ascent_;
   int line_height_;
diff --git a/examples/ui/jank/jank.cc b/examples/ui/jank/jank.cc
index ae1a8c3..7825251 100644
--- a/examples/ui/jank/jank.cc
+++ b/examples/ui/jank/jank.cc
@@ -59,9 +59,9 @@
       : GaneshView(app_connector.Pass(), view_owner_request.Pass(), "Jank"),
         choreographer_(scene(), this),
         input_handler_(GetViewServiceProvider(), this),
-        typeface_(skia::AdoptRef(SkTypeface::CreateFromStream(
+        typeface_(SkTypeface::MakeFromStream(
             new SkMemoryStream(font_data::kDejaVuSansMonoRegular.data,
-                               font_data::kDejaVuSansMonoRegular.size)))) {}
+                               font_data::kDejaVuSansMonoRegular.size))) {}
 
   ~JankView() override {}
 
@@ -163,7 +163,7 @@
     textPaint.setColor(SK_ColorBLACK);
     textPaint.setTextSize(16);
     textPaint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
-    textPaint.setTypeface(typeface_.get());
+    textPaint.setTypeface(typeface_);
     textPaint.setAntiAlias(true);
     SkRect textBounds;
     textPaint.measureText(label, strlen(label), &textBounds);
@@ -195,7 +195,7 @@
 
   mojo::ui::Choreographer choreographer_;
   mojo::ui::InputHandler input_handler_;
-  skia::RefPtr<SkTypeface> typeface_;
+  sk_sp<SkTypeface> typeface_;
   int64_t stutter_end_time_ = 0u;
 
   DISALLOW_COPY_AND_ASSIGN(JankView);
diff --git a/examples/ui/noodles/frame.cc b/examples/ui/noodles/frame.cc
index ca4faec..937610a 100644
--- a/examples/ui/noodles/frame.cc
+++ b/examples/ui/noodles/frame.cc
@@ -12,7 +12,7 @@
 namespace examples {
 
 Frame::Frame(const mojo::Size& size,
-             skia::RefPtr<SkPicture> picture,
+             sk_sp<SkPicture> picture,
              mojo::gfx::composition::SceneMetadataPtr scene_metadata)
     : size_(size), picture_(picture), scene_metadata_(scene_metadata.Pass()) {
   DCHECK(picture_);
diff --git a/examples/ui/noodles/frame.h b/examples/ui/noodles/frame.h
index 6c3858d..77d8f31 100644
--- a/examples/ui/noodles/frame.h
+++ b/examples/ui/noodles/frame.h
@@ -8,7 +8,7 @@
 #include "base/macros.h"
 #include "mojo/services/geometry/interfaces/geometry.mojom.h"
 #include "mojo/services/gfx/composition/interfaces/scenes.mojom.h"
-#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 
 class SkCanvas;
 class SkPicture;
@@ -21,7 +21,7 @@
 class Frame {
  public:
   Frame(const mojo::Size& size,
-        skia::RefPtr<SkPicture> picture,
+        sk_sp<SkPicture> picture,
         mojo::gfx::composition::SceneMetadataPtr scene_metadata);
   ~Frame();
 
@@ -35,7 +35,7 @@
 
  private:
   mojo::Size size_;
-  skia::RefPtr<SkPicture> picture_;
+  sk_sp<SkPicture> picture_;
   mojo::gfx::composition::SceneMetadataPtr scene_metadata_;
 
   DISALLOW_COPY_AND_ASSIGN(Frame);
diff --git a/examples/ui/noodles/noodles_view.cc b/examples/ui/noodles/noodles_view.cc
index eec3045..07e8121 100644
--- a/examples/ui/noodles/noodles_view.cc
+++ b/examples/ui/noodles/noodles_view.cc
@@ -109,7 +109,7 @@
   }
 }
 
-skia::RefPtr<SkPicture> NoodlesView::CreatePicture() {
+sk_sp<SkPicture> NoodlesView::CreatePicture() {
   constexpr int count = 4;
   constexpr int padding = 1;
 
@@ -140,7 +140,7 @@
     canvas->drawPath(path, paint);
   }
 
-  return skia::AdoptRef(recorder.endRecordingAsPicture());
+  return recorder.finishRecordingAsPicture();
 }
 
 NoodlesView::FrameQueue::FrameQueue() {}
diff --git a/examples/ui/noodles/noodles_view.h b/examples/ui/noodles/noodles_view.h
index c7d1a25..2b64b2b 100644
--- a/examples/ui/noodles/noodles_view.h
+++ b/examples/ui/noodles/noodles_view.h
@@ -15,7 +15,7 @@
 #include "base/threading/thread.h"
 #include "mojo/ui/base_view.h"
 #include "mojo/ui/choreographer.h"
-#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 
 class SkPicture;
 
@@ -82,7 +82,7 @@
               const base::TimeDelta& time_delta) override;
 
   void UpdateFrame();
-  skia::RefPtr<SkPicture> CreatePicture();
+  sk_sp<SkPicture> CreatePicture();
 
   mojo::ui::Choreographer choreographer_;
 
diff --git a/examples/ui/pdf_viewer/pdf_viewer.cc b/examples/ui/pdf_viewer/pdf_viewer.cc
index d1e463d..f16be50 100644
--- a/examples/ui/pdf_viewer/pdf_viewer.cc
+++ b/examples/ui/pdf_viewer/pdf_viewer.cc
@@ -48,7 +48,7 @@
 
   uint32_t page_count() { return page_count_; }
 
-  skia::RefPtr<SkImage> DrawPage(int page_index, const mojo::Size& size) {
+  sk_sp<SkImage> DrawPage(int page_index, const mojo::Size& size) {
     FPDF_PAGE page = FPDF_LoadPage(doc_, page_index);
 
     double width_pts = FPDF_GetPageWidth(page);
@@ -64,8 +64,7 @@
     }
 
     int stride = width * 4;
-    skia::RefPtr<SkData> pixels =
-        skia::AdoptRef(SkData::NewUninitialized(stride * height));
+    sk_sp<SkData> pixels = SkData::MakeUninitialized(stride * height);
     DCHECK(pixels);
 
     FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(width, height, FPDFBitmap_BGRA,
@@ -78,7 +77,7 @@
 
     SkImageInfo info = SkImageInfo::Make(width, height, kBGRA_8888_SkColorType,
                                          kOpaque_SkAlphaType);
-    return skia::AdoptRef(SkImage::NewRasterData(info, pixels.get(), stride));
+    return SkImage::MakeRasterData(info, pixels, stride);
   }
 
  private:
@@ -244,13 +243,13 @@
   }
 
   void Redraw() {
-    cached_image_.clear();
+    cached_image_.reset();
     choreographer_.ScheduleDraw();
   }
 
   std::shared_ptr<PDFDocument> pdf_document_;
   uint32_t page_ = 0u;
-  skia::RefPtr<SkImage> cached_image_;
+  sk_sp<SkImage> cached_image_;
 
   mojo::ui::Choreographer choreographer_;
   mojo::ui::InputHandler input_handler_;
diff --git a/examples/ui/png_viewer/png_viewer.cc b/examples/ui/png_viewer/png_viewer.cc
index de10c25..6e89523 100644
--- a/examples/ui/png_viewer/png_viewer.cc
+++ b/examples/ui/png_viewer/png_viewer.cc
@@ -30,7 +30,7 @@
  public:
   PNGView(mojo::InterfaceHandle<mojo::ApplicationConnector> app_connector,
           mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
-          const skia::RefPtr<SkImage>& image)
+          const sk_sp<SkImage>& image)
       : GaneshView(app_connector.Pass(),
                    view_owner_request.Pass(),
                    "PNGViewer"),
@@ -104,14 +104,14 @@
         nullptr);
   }
 
-  skia::RefPtr<SkImage> image_;
+  sk_sp<SkImage> image_;
 
   DISALLOW_COPY_AND_ASSIGN(PNGView);
 };
 
 class PNGContentViewProviderApp : public mojo::ui::ViewProviderApp {
  public:
-  PNGContentViewProviderApp(skia::RefPtr<SkImage> image) : image_(image) {
+  PNGContentViewProviderApp(sk_sp<SkImage> image) : image_(image) {
     DCHECK(image_);
   }
 
@@ -126,7 +126,7 @@
   }
 
  private:
-  skia::RefPtr<SkImage> image_;
+  sk_sp<SkImage> image_;
 
   DISALLOW_COPY_AND_ASSIGN(PNGContentViewProviderApp);
 };
@@ -151,8 +151,7 @@
       return nullptr;
     }
 
-    return new PNGContentViewProviderApp(
-        skia::AdoptRef(SkImage::NewFromBitmap(bitmap)));
+    return new PNGContentViewProviderApp(SkImage::MakeFromBitmap(bitmap));
   }
 
  private:
diff --git a/mojo/skia/ganesh_context.cc b/mojo/skia/ganesh_context.cc
index 4446ba9..546a6cf 100644
--- a/mojo/skia/ganesh_context.cc
+++ b/mojo/skia/ganesh_context.cc
@@ -28,10 +28,9 @@
   gl_context_->AddObserver(this);
 
   GLContext::Scope gl_scope(gl_context_);
-  ::skia::RefPtr<GrGLInterface> interface =
-      ::skia::AdoptRef(CreateMojoSkiaGLBinding());
+  sk_sp<GrGLInterface> interface = CreateMojoSkiaGLBinding();
   DCHECK(interface);
-  gr_context_ = ::skia::AdoptRef(GrContext::Create(
+  gr_context_.reset(GrContext::Create(
       kOpenGL_GrBackend, reinterpret_cast<GrBackendContext>(interface.get())));
   DCHECK(gr_context_);
   gr_context_->setResourceCacheLimits(kMaxGaneshResourceCacheCount,
@@ -62,7 +61,7 @@
   gl_context_->RemoveObserver(this);
   if (!scope_entered_) {
     gr_context_->abandonContext();
-    gr_context_.clear();
+    gr_context_.reset();
   }
 }
 
@@ -94,7 +93,7 @@
   // flushing it above.
   if (ganesh_context_->is_lost()) {
     ganesh_context_->gr_context_->abandonContext();
-    ganesh_context_->gr_context_.clear();
+    ganesh_context_->gr_context_.reset();
   }
 
   // Do this last to avoid potential reentrance if the context is lost.
diff --git a/mojo/skia/ganesh_context.h b/mojo/skia/ganesh_context.h
index 0de655a..472c7fd 100644
--- a/mojo/skia/ganesh_context.h
+++ b/mojo/skia/ganesh_context.h
@@ -8,7 +8,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "mojo/gpu/gl_context.h"
-#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/gpu/GrContext.h"
 
 namespace mojo {
@@ -48,7 +48,7 @@
     }
 
     // Gets the underlying Ganesh rendering context, never null.
-    const ::skia::RefPtr<GrContext>& gr_context() const {
+    const sk_sp<GrContext>& gr_context() const {
       return ganesh_context_->gr_context_;
     }
 
@@ -84,7 +84,7 @@
   void OnContextLost() override;
 
   const scoped_refptr<GLContext> gl_context_;
-  ::skia::RefPtr<GrContext> gr_context_;
+  sk_sp<GrContext> gr_context_;
   bool scope_entered_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(GaneshContext);
diff --git a/mojo/skia/ganesh_framebuffer_surface.cc b/mojo/skia/ganesh_framebuffer_surface.cc
index 0f54b27..47ef539 100644
--- a/mojo/skia/ganesh_framebuffer_surface.cc
+++ b/mojo/skia/ganesh_framebuffer_surface.cc
@@ -33,8 +33,8 @@
   desc.fStencilBits = stencil_bits;
   desc.fRenderTargetHandle = framebuffer_binding;
 
-  surface_ = ::skia::AdoptRef(SkSurface::NewFromBackendRenderTarget(
-      scope.gr_context().get(), desc, nullptr));
+  surface_ = SkSurface::MakeFromBackendRenderTarget(scope.gr_context().get(),
+                                                    desc, nullptr);
   DCHECK(surface_);
 }
 
diff --git a/mojo/skia/ganesh_framebuffer_surface.h b/mojo/skia/ganesh_framebuffer_surface.h
index 99ab149..70036e0 100644
--- a/mojo/skia/ganesh_framebuffer_surface.h
+++ b/mojo/skia/ganesh_framebuffer_surface.h
@@ -7,7 +7,7 @@
 
 #include "base/macros.h"
 #include "mojo/skia/ganesh_context.h"
-#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/core/SkSurface.h"
 
 namespace mojo {
@@ -27,7 +27,7 @@
   SkCanvas* canvas() const { return surface_->getCanvas(); }
 
  private:
-  ::skia::RefPtr<SkSurface> surface_;
+  sk_sp<SkSurface> surface_;
 
   DISALLOW_COPY_AND_ASSIGN(GaneshFramebufferSurface);
 };
diff --git a/mojo/skia/ganesh_image_factory.cc b/mojo/skia/ganesh_image_factory.cc
index 95d3ef1..fc381f9 100644
--- a/mojo/skia/ganesh_image_factory.cc
+++ b/mojo/skia/ganesh_image_factory.cc
@@ -24,13 +24,12 @@
 }
 }  // namespace
 
-::skia::RefPtr<SkImage> CreateImageFromTexture(
-    const GaneshContext::Scope& scope,
-    uint32_t texture_id,
-    uint32_t width,
-    uint32_t height,
-    GrSurfaceOrigin origin,
-    const base::Closure& release_callback) {
+sk_sp<SkImage> CreateImageFromTexture(const GaneshContext::Scope& scope,
+                                      uint32_t texture_id,
+                                      uint32_t width,
+                                      uint32_t height,
+                                      GrSurfaceOrigin origin,
+                                      const base::Closure& release_callback) {
   DCHECK(texture_id);
   DCHECK(width);
   DCHECK(height);
@@ -47,9 +46,9 @@
   desc.fConfig = kSkia8888_GrPixelConfig;
   desc.fOrigin = origin;
   desc.fTextureHandle = reinterpret_cast<GrBackendObject>(&info);
-  return ::skia::AdoptRef(SkImage::NewFromTexture(
-      scope.gr_context().get(), desc, kPremul_SkAlphaType, &ReleaseThunk,
-      new base::Closure(release_callback)));
+  return SkImage::MakeFromTexture(scope.gr_context().get(), desc,
+                                  kPremul_SkAlphaType, &ReleaseThunk,
+                                  new base::Closure(release_callback));
 }
 
 MailboxTextureImageGenerator::MailboxTextureImageGenerator(
diff --git a/mojo/skia/ganesh_image_factory.h b/mojo/skia/ganesh_image_factory.h
index ddd3630..85709ef 100644
--- a/mojo/skia/ganesh_image_factory.h
+++ b/mojo/skia/ganesh_image_factory.h
@@ -10,8 +10,8 @@
 
 #include "base/callback.h"
 #include "mojo/skia/ganesh_context.h"
-#include "skia/ext/refptr.h"
 #include "third_party/skia/include/core/SkImageGenerator.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/gpu/GrTypes.h"
 
 class SkImage;
@@ -22,13 +22,12 @@
 // Creates an SkImage from a GL texture.
 // The underlying texture must be kept alive for as long as the SkImage exists.
 // Invokes |release_callback| when the SkImage is deleted.
-::skia::RefPtr<SkImage> CreateImageFromTexture(
-    const GaneshContext::Scope& scope,
-    uint32_t texture_id,
-    uint32_t width,
-    uint32_t height,
-    GrSurfaceOrigin origin,
-    const base::Closure& release_callback);
+sk_sp<SkImage> CreateImageFromTexture(const GaneshContext::Scope& scope,
+                                      uint32_t texture_id,
+                                      uint32_t width,
+                                      uint32_t height,
+                                      GrSurfaceOrigin origin,
+                                      const base::Closure& release_callback);
 
 // Generates backing content for SkImages from a texture mailbox.
 // If |sync_point| is non-zero, inserts a sync point into the command stream
diff --git a/mojo/skia/ganesh_texture_surface.cc b/mojo/skia/ganesh_texture_surface.cc
index c296020..5b03429 100644
--- a/mojo/skia/ganesh_texture_surface.cc
+++ b/mojo/skia/ganesh_texture_surface.cc
@@ -34,8 +34,8 @@
   desc.fSampleCnt = 0;
   desc.fTextureHandle = reinterpret_cast<GrBackendObject>(&info);
 
-  surface_ = ::skia::AdoptRef(SkSurface::NewFromBackendTexture(
-      scope.gr_context().get(), desc, nullptr));
+  surface_ = SkSurface::MakeFromBackendTexture(scope.gr_context().get(), desc,
+                                               nullptr);
   DCHECK(surface_);
 }
 
@@ -43,7 +43,7 @@
 
 std::unique_ptr<GLTexture> GaneshTextureSurface::TakeTexture() {
   surface_->getCanvas()->flush();
-  surface_.clear();
+  surface_.reset();
   return std::move(texture_);
 }
 
diff --git a/mojo/skia/ganesh_texture_surface.h b/mojo/skia/ganesh_texture_surface.h
index 3cf4c36..3cabe6e 100644
--- a/mojo/skia/ganesh_texture_surface.h
+++ b/mojo/skia/ganesh_texture_surface.h
@@ -9,7 +9,7 @@
 
 #include "base/macros.h"
 #include "mojo/skia/ganesh_context.h"
-#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/core/SkSurface.h"
 
 namespace mojo {
@@ -35,7 +35,7 @@
 
  private:
   std::unique_ptr<GLTexture> texture_;
-  ::skia::RefPtr<SkSurface> surface_;
+  sk_sp<SkSurface> surface_;
 
   DISALLOW_COPY_AND_ASSIGN(GaneshTextureSurface);
 };
diff --git a/mojo/skia/gl_bindings_skia.cc b/mojo/skia/gl_bindings_skia.cc
index 4ca10bd..89467f9 100644
--- a/mojo/skia/gl_bindings_skia.cc
+++ b/mojo/skia/gl_bindings_skia.cc
@@ -15,8 +15,8 @@
 namespace mojo {
 namespace skia {
 
-GrGLInterface* CreateMojoSkiaGLBinding() {
-  GrGLInterface* interface = new GrGLInterface;
+sk_sp<GrGLInterface> CreateMojoSkiaGLBinding() {
+  sk_sp<GrGLInterface> interface = sk_make_sp<GrGLInterface>();
   interface->fStandard = kGLES_GrGLStandard;
   interface->fExtensions.init(kGLES_GrGLStandard, glGetString, nullptr,
                               glGetIntegerv);
diff --git a/mojo/skia/gl_bindings_skia.h b/mojo/skia/gl_bindings_skia.h
index 3eba0f9..a39f8eb 100644
--- a/mojo/skia/gl_bindings_skia.h
+++ b/mojo/skia/gl_bindings_skia.h
@@ -5,6 +5,7 @@
 #ifndef MOJO_SKIA_GL_BINDINGS_SKIA_H_
 #define MOJO_SKIA_GL_BINDINGS_SKIA_H_
 
+#include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/core/SkTypes.h"
 
 struct GrGLInterface;
@@ -14,7 +15,7 @@
 
 // The GPU back-end for skia requires pointers to GL functions. This function
 // returns a binding for skia-gpu to the Mojo C GL entry points.
-GrGLInterface* CreateMojoSkiaGLBinding();
+sk_sp<GrGLInterface> CreateMojoSkiaGLBinding();
 
 }  // namespace skia
 }  // namespace mojo
diff --git a/mojo/skia/type_converters.h b/mojo/skia/type_converters.h
index e2972fe..dff4577 100644
--- a/mojo/skia/type_converters.h
+++ b/mojo/skia/type_converters.h
@@ -7,10 +7,10 @@
 
 #include "mojo/services/geometry/interfaces/geometry.mojom.h"
 #include "third_party/skia/include/core/SkMatrix.h"
+#include "third_party/skia/include/core/SkMatrix44.h"
 #include "third_party/skia/include/core/SkPoint.h"
 #include "third_party/skia/include/core/SkRRect.h"
 #include "third_party/skia/include/core/SkRect.h"
-#include "third_party/skia/include/utils/SkMatrix44.h"
 
 namespace mojo {
 
diff --git a/services/gfx/compositor/graph/nodes.cc b/services/gfx/compositor/graph/nodes.cc
index 1db819a..7104b2b 100644
--- a/services/gfx/compositor/graph/nodes.cc
+++ b/services/gfx/compositor/graph/nodes.cc
@@ -16,10 +16,10 @@
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkMatrix.h"
+#include "third_party/skia/include/core/SkMatrix44.h"
 #include "third_party/skia/include/core/SkPaint.h"
 #include "third_party/skia/include/core/SkPoint.h"
 #include "third_party/skia/include/core/SkRect.h"
-#include "third_party/skia/include/utils/SkMatrix44.h"
 
 namespace compositor {
 namespace {
diff --git a/services/gfx/compositor/graph/snapshot.cc b/services/gfx/compositor/graph/snapshot.cc
index b8051bd..876c13e 100644
--- a/services/gfx/compositor/graph/snapshot.cc
+++ b/services/gfx/compositor/graph/snapshot.cc
@@ -8,9 +8,9 @@
 #include "mojo/services/gfx/composition/cpp/formatting.h"
 #include "mojo/skia/type_converters.h"
 #include "services/gfx/compositor/graph/scene_content.h"
+#include "third_party/skia/include/core/SkMatrix44.h"
 #include "third_party/skia/include/core/SkPictureRecorder.h"
 #include "third_party/skia/include/core/SkRect.h"
-#include "third_party/skia/include/utils/SkMatrix44.h"
 
 namespace compositor {
 
@@ -35,7 +35,7 @@
   recorder.beginRecording(SkRect::Make(sk_viewport));
   root_scene_content_->Paint(this, recorder.getRecordingCanvas());
   return new RenderFrame(metadata, sk_viewport,
-                         skia::AdoptRef(recorder.endRecordingAsPicture()));
+                         recorder.finishRecordingAsPicture());
 }
 
 void Snapshot::HitTest(const mojo::PointF& point,
diff --git a/services/gfx/compositor/graph/transform_pair.h b/services/gfx/compositor/graph/transform_pair.h
index 5cdcb49..3ea6ddf 100644
--- a/services/gfx/compositor/graph/transform_pair.h
+++ b/services/gfx/compositor/graph/transform_pair.h
@@ -5,7 +5,7 @@
 #ifndef SERVICES_GFX_COMPOSITOR_GRAPH_TRANSFORM_PAIR_H_
 #define SERVICES_GFX_COMPOSITOR_GRAPH_TRANSFORM_PAIR_H_
 
-#include "third_party/skia/include/utils/SkMatrix44.h"
+#include "third_party/skia/include/core/SkMatrix44.h"
 
 namespace compositor {
 
diff --git a/services/gfx/compositor/render/render_frame.cc b/services/gfx/compositor/render/render_frame.cc
index d39753b..ce8bcef 100644
--- a/services/gfx/compositor/render/render_frame.cc
+++ b/services/gfx/compositor/render/render_frame.cc
@@ -6,9 +6,9 @@
 
 #include "base/logging.h"
 #include "base/trace_event/trace_event.h"
-#include "skia/ext/refptr.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkPicture.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 
 namespace compositor {
 
@@ -19,7 +19,7 @@
 
 RenderFrame::RenderFrame(const Metadata& metadata,
                          const SkIRect& viewport,
-                         const skia::RefPtr<SkPicture>& picture)
+                         const sk_sp<SkPicture>& picture)
     : metadata_(metadata), viewport_(viewport), picture_(picture) {
   DCHECK(!viewport_.isEmpty());
 }
diff --git a/services/gfx/compositor/render/render_frame.h b/services/gfx/compositor/render/render_frame.h
index f468fb9..77f7a6b 100644
--- a/services/gfx/compositor/render/render_frame.h
+++ b/services/gfx/compositor/render/render_frame.h
@@ -8,8 +8,8 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "mojo/services/gfx/composition/interfaces/scheduling.mojom.h"
-#include "skia/ext/refptr.h"
 #include "third_party/skia/include/core/SkRect.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 
 class SkCanvas;
 class SkPicture;
@@ -46,7 +46,7 @@
   // Creates render frame backed by a picture.
   RenderFrame(const Metadata& metadata,
               const SkIRect& viewport,
-              const skia::RefPtr<SkPicture>& picture);
+              const sk_sp<SkPicture>& picture);
 
   // Gets metadata about the frame.
   const Metadata& metadata() const { return metadata_; }
@@ -55,7 +55,7 @@
   const SkIRect& viewport() const { return viewport_; }
 
   // Gets the underlying picture to rasterize, or null if the frame is empty.
-  const skia::RefPtr<SkPicture>& picture() const { return picture_; }
+  const sk_sp<SkPicture>& picture() const { return picture_; }
 
   // Draws the contents of the frame to a canvas.
   void Draw(SkCanvas* canvas) const;
@@ -68,7 +68,7 @@
 
   Metadata metadata_;
   SkIRect viewport_;
-  skia::RefPtr<SkPicture> picture_;
+  sk_sp<SkPicture> picture_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderFrame);
 };
diff --git a/services/gfx/compositor/render/render_image.cc b/services/gfx/compositor/render/render_image.cc
index fd2572d..d4f64a6 100644
--- a/services/gfx/compositor/render/render_image.cc
+++ b/services/gfx/compositor/render/render_image.cc
@@ -55,7 +55,7 @@
   scoped_refptr<Releaser> releaser_;
 };
 
-RenderImage::RenderImage(const skia::RefPtr<SkImage>& image,
+RenderImage::RenderImage(const sk_sp<SkImage>& image,
                          const scoped_refptr<Releaser>& releaser)
     : image_(image), releaser_(releaser) {
   DCHECK(image_);
@@ -73,12 +73,12 @@
     const scoped_refptr<base::TaskRunner>& task_runner,
     const base::Closure& release_task) {
   scoped_refptr<Releaser> releaser = new Releaser(task_runner, release_task);
-  skia::RefPtr<SkImage> image = skia::AdoptRef(SkImage::NewFromGenerator(
+  sk_sp<SkImage> image = SkImage::MakeFromGenerator(
       new Generator(releaser, mailbox_name, sync_point, width, height,
                     origin == mojo::gfx::composition::MailboxTextureResource::
                                   Origin::BOTTOM_LEFT
                         ? kBottomLeft_GrSurfaceOrigin
-                        : kTopLeft_GrSurfaceOrigin)));
+                        : kTopLeft_GrSurfaceOrigin));
   if (!image)
     return nullptr;
 
diff --git a/services/gfx/compositor/render/render_image.h b/services/gfx/compositor/render/render_image.h
index d867f9e..4e75f7f 100644
--- a/services/gfx/compositor/render/render_image.h
+++ b/services/gfx/compositor/render/render_image.h
@@ -13,8 +13,8 @@
 #include "base/memory/ref_counted.h"
 #include "base/task_runner.h"
 #include "mojo/services/gfx/composition/interfaces/resources.mojom.h"
-#include "skia/ext/refptr.h"
 #include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 
 namespace compositor {
 
@@ -29,7 +29,7 @@
   class Generator;
 
  public:
-  RenderImage(const skia::RefPtr<SkImage>& image,
+  RenderImage(const sk_sp<SkImage>& image,
               const scoped_refptr<Releaser>& releaser);
 
   // Creates a new image backed by a mailbox texture.
@@ -51,14 +51,14 @@
   uint32_t height() const { return image_->height(); }
 
   // Gets the underlying image to rasterize, never null.
-  const skia::RefPtr<SkImage>& image() const { return image_; }
+  const sk_sp<SkImage>& image() const { return image_; }
 
  private:
   friend class base::RefCountedThreadSafe<RenderImage>;
 
   ~RenderImage();
 
-  skia::RefPtr<SkImage> image_;
+  sk_sp<SkImage> image_;
   scoped_refptr<Releaser> releaser_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderImage);
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index 3fc4a96..f53d9be 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -78,6 +78,17 @@
                 "scope",
                 [ "//third_party/skia/gyp/opts.gypi" ])
 
+# The list of Skia files is kept in skia_gn_files.gypi. Read it.
+gypi_values =
+    exec_script("//build/gypi_to_gn.py",
+                [
+                  rebase_path("skia_gn_files.gypi"),
+                  "--replace=<(skia_include_path)=//third_party/skia/include",
+                  "--replace=<(skia_src_path)=//third_party/skia/src",
+                ],
+                "scope",
+                [ "skia_gn_files.gypi" ])
+
 # External-facing config for dependent code.
 config("skia_config") {
   include_dirs = [
@@ -216,69 +227,18 @@
     "ext/SkDiscardableMemory_chrome.cc",
     "ext/SkDiscardableMemory_chrome.h",
     "ext/SkMemory_new_handler.cpp",
-    "ext/bitmap_platform_device.h",
+    "ext/convolver.cc",
+    "ext/convolver.h",
     "ext/event_tracer_impl.cc",
     "ext/event_tracer_impl.h",
     "ext/google_logging.cc",
-    "ext/opacity_draw_filter.cc",
-    "ext/opacity_draw_filter.h",
-    "ext/platform_canvas.cc",
-    "ext/platform_canvas.h",
-    "ext/platform_device.cc",
-    "ext/platform_device.h",
-    "ext/platform_device_linux.cc",
-    "ext/platform_device_mac.cc",
-    "ext/refptr.h",
-    "ext/skia_utils_base.cc",
-    "ext/skia_utils_base.h",
-    "ext/skia_utils_ios.h",
-    "ext/skia_utils_ios.mm",
-    "ext/skia_utils_mac.h",
-    "ext/skia_utils_mac.mm",
   ]
 
   # The skia gypi values are relative to the skia_dir, so we need to rebase.
   sources += gypi_skia_core.sources
   sources += gypi_skia_effects.sources
   sources += gypi_skia_utils.sources
-
-  sources += [
-    "//third_party/skia/include/images/SkMovie.h",
-    "//third_party/skia/include/images/SkPageFlipper.h",
-    "//third_party/skia/include/ports/SkTypeface_win.h",
-    "//third_party/skia/src/fonts/SkFontMgr_indirect.cpp",
-    "//third_party/skia/src/fonts/SkRemotableFontMgr.cpp",
-    "//third_party/skia/src/images/SkScaledBitmapSampler.cpp",
-    "//third_party/skia/src/images/SkScaledBitmapSampler.h",
-    "//third_party/skia/src/ports/SkFontHost_FreeType.cpp",
-    "//third_party/skia/src/ports/SkFontHost_FreeType_common.cpp",
-    "//third_party/skia/src/ports/SkFontHost_FreeType_common.h",
-    "//third_party/skia/src/ports/SkFontHost_mac.cpp",
-    "//third_party/skia/src/ports/SkFontHost_win.cpp",
-    "//third_party/skia/src/ports/SkFontMgr_android.cpp",
-    "//third_party/skia/src/ports/SkFontMgr_android_factory.cpp",
-    "//third_party/skia/src/ports/SkFontMgr_android_parser.cpp",
-    "//third_party/skia/src/ports/SkFontMgr_win_dw.cpp",
-    "//third_party/skia/src/ports/SkGlobalInitialization_chromium.cpp",
-    "//third_party/skia/src/ports/SkImageDecoder_empty.cpp",
-    "//third_party/skia/src/ports/SkImageGenerator_none.cpp",
-    "//third_party/skia/src/ports/SkOSFile_posix.cpp",
-    "//third_party/skia/src/ports/SkOSFile_stdio.cpp",
-    "//third_party/skia/src/ports/SkOSFile_win.cpp",
-    "//third_party/skia/src/ports/SkRemotableFontMgr_win_dw.cpp",
-    "//third_party/skia/src/ports/SkScalerContext_win_dw.cpp",
-    "//third_party/skia/src/ports/SkScalerContext_win_dw.h",
-    "//third_party/skia/src/ports/SkTLS_pthread.cpp",
-    "//third_party/skia/src/ports/SkTLS_win.cpp",
-    "//third_party/skia/src/ports/SkTime_Unix.cpp",
-    "//third_party/skia/src/ports/SkTypeface_win_dw.cpp",
-    "//third_party/skia/src/ports/SkTypeface_win_dw.h",
-    "//third_party/skia/src/sfnt/SkOTTable_name.cpp",
-    "//third_party/skia/src/sfnt/SkOTTable_name.h",
-    "//third_party/skia/src/sfnt/SkOTUtils.cpp",
-    "//third_party/skia/src/sfnt/SkOTUtils.h",
-    "//third_party/skia/src/utils/mac/SkStream_mac.cpp",
-  ]
+  sources += gypi_values.skia_library_sources
 
   # This and skia_opts are really the same conceptual target so share headers.
   allow_circular_includes_from = [ ":skia_opts" ]
@@ -295,44 +255,23 @@
   sources += gypi_skia_gpu.skgpu_sources
   sources += gypi_skia_gpu.skgpu_null_gl_sources
 
-  # Remove unused files from utils.
+  # Remove unused util files include in utils.gypi
   sources -= [
-    "//third_party/skia/include/utils/SkBoundaryPatch.h",
-    "//third_party/skia/include/utils/SkCamera.h",
-    "//third_party/skia/include/utils/SkCanvasStateUtils.h",
-    "//third_party/skia/include/utils/SkCubicInterval.h",
-    "//third_party/skia/include/utils/SkCullPoints.h",
-    "//third_party/skia/include/utils/SkDebugUtils.h",
-    "//third_party/skia/include/utils/SkDumpCanvas.h",
-    "//third_party/skia/include/utils/SkEventTracer.h",
-    "//third_party/skia/include/utils/SkFrontBufferedStream.h",
-    "//third_party/skia/include/utils/SkInterpolator.h",
-    "//third_party/skia/include/utils/SkLayer.h",
-    "//third_party/skia/include/utils/SkMeshUtils.h",
-    "//third_party/skia/include/utils/SkNinePatch.h",
-    "//third_party/skia/include/utils/SkParsePaint.h",
-    "//third_party/skia/include/utils/SkParsePath.h",
-    "//third_party/skia/include/utils/SkRandom.h",
-    "//third_party/skia/src/utils/SkBitmapHasher.cpp",
-    "//third_party/skia/src/utils/SkBitmapHasher.h",
     "//third_party/skia/src/utils/SkBoundaryPatch.cpp",
     "//third_party/skia/src/utils/SkCamera.cpp",
     "//third_party/skia/src/utils/SkCanvasStack.h",
-    "//third_party/skia/src/utils/SkCubicInterval.cpp",
-    "//third_party/skia/src/utils/SkCullPoints.cpp",
     "//third_party/skia/src/utils/SkDumpCanvas.cpp",
     "//third_party/skia/src/utils/SkFloatUtils.h",
     "//third_party/skia/src/utils/SkFrontBufferedStream.cpp",
     "//third_party/skia/src/utils/SkInterpolator.cpp",
     "//third_party/skia/src/utils/SkLayer.cpp",
-    "//third_party/skia/src/utils/SkMD5.cpp",
-    "//third_party/skia/src/utils/SkMD5.h",
     "//third_party/skia/src/utils/SkMeshUtils.cpp",
     "//third_party/skia/src/utils/SkNinePatch.cpp",
     "//third_party/skia/src/utils/SkParsePath.cpp",
-    "//third_party/skia/src/utils/SkSHA1.cpp",
-    "//third_party/skia/src/utils/SkSHA1.h",
-    "//third_party/skia/src/utils/SkTFitsIn.h",
+
+    #testing
+    "//third_party/skia/src/fonts/SkGScalerContext.cpp",
+    "//third_party/skia/src/fonts/SkGScalerContext.h",
   ]
 
   if (is_ios || is_mac || is_android) {
@@ -363,23 +302,7 @@
     set_sources_assignment_filter(sources_assignment_filter)
   }
 
-  if (is_android) {
-    sources -= [ "ext/skia_utils_base.cc" ]
-  }
-
   # Fixup skia library sources.
-  sources -= [
-    "//third_party/skia/src/ports/SkFontHost_win.cpp",
-    "//third_party/skia/src/ports/SkFontMgr_win_dw.cpp",
-    "//third_party/skia/src/ports/SkOSFile_win.cpp",
-    "//third_party/skia/src/ports/SkRemotableFontMgr_win_dw.cpp",
-    "//third_party/skia/src/ports/SkScalerContext_win_dw.cpp",
-    "//third_party/skia/src/ports/SkScalerContext_win_dw.h",
-    "//third_party/skia/src/ports/SkTLS_win.cpp",
-    "//third_party/skia/src/ports/SkTypeface_win_dw.cpp",
-    "//third_party/skia/src/ports/SkTypeface_win_dw.h",
-    "//third_party/skia/src/utils/SkThreadUtils_win.cpp",
-  ]
   if (!is_android) {
     sources -= [
       "//third_party/skia/src/ports/SkFontMgr_android.cpp",
@@ -407,19 +330,6 @@
     ]
   }
 
-  # Select the right BitmapPlatformDevice.
-  if (is_mac || is_ios) {
-    sources += [
-      "ext/bitmap_platform_device_mac.cc",
-      "ext/bitmap_platform_device_mac.h",
-    ]
-  } else {
-    sources += [
-      "ext/bitmap_platform_device_skia.cc",
-      "ext/bitmap_platform_device_skia.h",
-    ]
-  }
-
   if (is_clang) {
     # Skia won't compile with some of the more strict clang warnings.
     # e.g. it does:
@@ -450,7 +360,6 @@
 
   if (is_android) {
     set_sources_assignment_filter([])
-    sources += [ "ext/platform_device_linux.cc" ]
     set_sources_assignment_filter(sources_assignment_filter)
     deps += [
       "//third_party/android_tools:cpu_features",
@@ -471,12 +380,20 @@
   defines = []
 
   if (current_cpu == "x86" || current_cpu == "x64") {
-    sources = gypi_skia_opts.sse2_sources + gypi_skia_opts.ssse3_sources +
-              gypi_skia_opts.sse41_sources + gypi_skia_opts.avx_sources
-    if (is_linux || is_mac) {
+    if (!is_ios) {
+      sources = gypi_skia_opts.sse2_sources + gypi_skia_opts.ssse3_sources +
+                gypi_skia_opts.sse41_sources + gypi_skia_opts.avx_sources +
+                [
+                  # Chrome-specific.
+                  "ext/convolver_SSE2.cc",
+                  "ext/convolver_SSE2.h",
+                ]
+
       cflags += [ "-msse4.1" ]
+    } else {
+      sources = gypi_skia_opts.none_sources
     }
-  } else if (current_cpu == "arm" || current_cpu == "arm64") {
+  } else if (current_cpu == "arm") {
     # The assembly uses the frame pointer register (r7 in Thumb/r11 in
     # ARM), the compiler doesn't like that.
     cflags += [ "-fomit-frame-pointer" ]
@@ -501,9 +418,18 @@
   } else if (current_cpu == "mipsel") {
     cflags += [ "-fomit-frame-pointer" ]
 
-    sources = gypi_skia_opts.none_sources
-  } else if (current_cpu == "pnacl") {
-    sources = gypi_skia_opts.none_sources
+    if (mips_dsp_rev >= 1) {
+      sources = gypi_skia_opts.mips_dsp_sources
+      if (mips_dsp_rev >= 2) {
+        sources += [
+          # Chrome-specific.
+          "ext/convolver_mips_dspr2.cc",
+          "ext/convolver_mips_dspr2.h",
+        ]
+      }
+    } else {
+      sources = gypi_skia_opts.none_sources
+    }
   } else {
     assert(false, "Need to port cpu specific stuff from skia_library_opts.gyp")
   }
@@ -526,26 +452,3 @@
 
   visibility = [ ":skia" ]
 }
-
-test("skia_unittests") {
-  sources = [
-    "ext/bitmap_platform_device_mac_unittest.cc",
-    "ext/platform_canvas_unittest.cc",
-    "ext/refptr_unittest.cc",
-    "ext/skia_utils_ios_unittest.mm",
-    "ext/skia_utils_mac_unittest.mm",
-  ]
-
-  if (!is_mac) {
-    sources -= [ "ext/platform_canvas_unittest.cc" ]
-  }
-
-  deps = [
-    ":skia",
-    "//base",
-    "//base/test:run_all_unittests",
-    "//testing/gtest",
-    "//ui/gfx",
-    "//ui/gfx/geometry",
-  ]
-}
diff --git a/skia/ext/SkMemory_new_handler.cpp b/skia/ext/SkMemory_new_handler.cpp
index d4080a1..041ce34 100644
--- a/skia/ext/SkMemory_new_handler.cpp
+++ b/skia/ext/SkMemory_new_handler.cpp
@@ -23,9 +23,8 @@
     return p;
 }
 
-void sk_throw() {
-    SkASSERT(!"sk_throw");
-    abort();
+void sk_abort_no_print() {
+  abort();
 }
 
 void sk_out_of_memory(void) {
diff --git a/skia/ext/bitmap_platform_device.h b/skia/ext/bitmap_platform_device.h
deleted file mode 100644
index 60fa180..0000000
--- a/skia/ext/bitmap_platform_device.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SKIA_EXT_BITMAP_PLATFORM_DEVICE_H_
-#define SKIA_EXT_BITMAP_PLATFORM_DEVICE_H_
-
-// This file provides an easy way to include the appropriate
-// BitmapPlatformDevice header file for your platform.
-
-#if defined(WIN32)
-#include "skia/ext/bitmap_platform_device_win.h"
-#elif defined(__APPLE__)
-#include "skia/ext/bitmap_platform_device_mac.h"
-#else
-#include "skia/ext/bitmap_platform_device_skia.h"
-#endif
-
-namespace skia {
-    // Returns true if it is unsafe to attempt to allocate an offscreen buffer
-    // given these dimensions.
-    inline bool RasterDeviceTooBigToAllocate(int width, int height) {
-
-#ifndef SKIA_EXT_RASTER_DEVICE_ALLOCATION_MAX
-#define SKIA_EXT_RASTER_DEVICE_ALLOCATION_MAX    (2 * 256 * 1024 * 1024)
-#endif
-
-    int bytesPerPixel = 4;
-    int64_t bytes = (int64_t)width * height * bytesPerPixel;
-    return bytes > SKIA_EXT_RASTER_DEVICE_ALLOCATION_MAX;
-  }
-}
-
-#endif  // SKIA_EXT_BITMAP_PLATFORM_DEVICE_H_
diff --git a/skia/ext/bitmap_platform_device_mac.cc b/skia/ext/bitmap_platform_device_mac.cc
deleted file mode 100644
index 087cf39..0000000
--- a/skia/ext/bitmap_platform_device_mac.cc
+++ /dev/null
@@ -1,323 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/bitmap_platform_device_mac.h"
-
-#import <ApplicationServices/ApplicationServices.h>
-#include <time.h>
-
-#include "base/mac/mac_util.h"
-#include "base/memory/ref_counted.h"
-#include "skia/ext/bitmap_platform_device.h"
-#include "skia/ext/platform_canvas.h"
-#include "skia/ext/skia_utils_mac.h"
-#include "third_party/skia/include/core/SkMatrix.h"
-#include "third_party/skia/include/core/SkPath.h"
-#include "third_party/skia/include/core/SkRegion.h"
-#include "third_party/skia/include/core/SkTypes.h"
-#include "third_party/skia/include/core/SkUtils.h"
-
-namespace skia {
-
-namespace {
-
-static CGContextRef CGContextForData(void* data, int width, int height) {
-#define HAS_ARGB_SHIFTS(a, r, g, b) \
-            (SK_A32_SHIFT == (a) && SK_R32_SHIFT == (r) \
-             && SK_G32_SHIFT == (g) && SK_B32_SHIFT == (b))
-#if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0)
-  // Allocate a bitmap context with 4 components per pixel (BGRA).  Apple
-  // recommends these flags for improved CG performance.
-
-  // CGBitmapContextCreate returns NULL if width/height are 0. However, our
-  // callers expect to get a canvas back (which they later resize/reallocate)
-  // so we pin the dimensions here.
-  width = SkMax32(1, width);
-  height = SkMax32(1, height);
-  CGContextRef context =
-      CGBitmapContextCreate(data, width, height, 8, width * 4,
-                            base::mac::GetSystemColorSpace(),
-                            kCGImageAlphaPremultipliedFirst |
-                                kCGBitmapByteOrder32Host);
-#else
-#error We require that Skia's and CoreGraphics's recommended \
-       image memory layout match.
-#endif
-#undef HAS_ARGB_SHIFTS
-
-  if (!context)
-    return NULL;
-
-  // Change the coordinate system to match WebCore's
-  CGContextTranslateCTM(context, 0, height);
-  CGContextScaleCTM(context, 1.0, -1.0);
-
-  return context;
-}
-
-}  // namespace
-
-void BitmapPlatformDevice::ReleaseBitmapContext() {
-  SkASSERT(bitmap_context_);
-  CGContextRelease(bitmap_context_);
-  bitmap_context_ = NULL;
-}
-
-void BitmapPlatformDevice::SetMatrixClip(
-    const SkMatrix& transform,
-    const SkRegion& region) {
-  transform_ = transform;
-  clip_region_ = region;
-  config_dirty_ = true;
-}
-
-// Loads the specified Skia transform into the device context
-static void LoadTransformToCGContext(CGContextRef context,
-                                     const SkMatrix& matrix) {
-  // CoreGraphics can concatenate transforms, but not reset the current one.
-  // So in order to get the required behavior here, we need to first make
-  // the current transformation matrix identity and only then load the new one.
-
-  // Reset matrix to identity.
-  CGAffineTransform orig_cg_matrix = CGContextGetCTM(context);
-  CGAffineTransform orig_cg_matrix_inv =
-      CGAffineTransformInvert(orig_cg_matrix);
-  CGContextConcatCTM(context, orig_cg_matrix_inv);
-
-  // assert that we have indeed returned to the identity Matrix.
-  SkASSERT(CGAffineTransformIsIdentity(CGContextGetCTM(context)));
-
-  // Convert xform to CG-land.
-  // Our coordinate system is flipped to match WebKit's so we need to modify
-  // the xform to match that.
-  SkMatrix transformed_matrix = matrix;
-  SkScalar sy = -matrix.getScaleY();
-  transformed_matrix.setScaleY(sy);
-  size_t height = CGBitmapContextGetHeight(context);
-  SkScalar ty = -matrix.getTranslateY();  // y axis is flipped.
-  transformed_matrix.setTranslateY(ty + (SkScalar)height);
-
-  CGAffineTransform cg_matrix =
-      gfx::SkMatrixToCGAffineTransform(transformed_matrix);
-
-  // Load final transform into context.
-  CGContextConcatCTM(context, cg_matrix);
-}
-
-// Loads a SkRegion into the CG context.
-static void LoadClippingRegionToCGContext(CGContextRef context,
-                                          const SkRegion& region,
-                                          const SkMatrix& transformation) {
-  if (region.isEmpty()) {
-    // region can be empty, in which case everything will be clipped.
-    SkRect rect;
-    rect.setEmpty();
-    CGContextClipToRect(context, gfx::SkRectToCGRect(rect));
-  } else if (region.isRect()) {
-    // CoreGraphics applies the current transform to clip rects, which is
-    // unwanted. Inverse-transform the rect before sending it to CG. This only
-    // works for translations and scaling, but not for rotations (but the
-    // viewport is never rotated anyway).
-    SkMatrix t;
-    bool did_invert = transformation.invert(&t);
-    if (!did_invert)
-      t.reset();
-    // Do the transformation.
-    SkRect rect;
-    rect.set(region.getBounds());
-    t.mapRect(&rect);
-    SkIRect irect;
-    rect.round(&irect);
-    CGContextClipToRect(context, gfx::SkIRectToCGRect(irect));
-  } else {
-    // It is complex.
-    SkPath path;
-    region.getBoundaryPath(&path);
-    // Clip. Note that windows clipping regions are not affected by the
-    // transform so apply it manually.
-    path.transform(transformation);
-    // TODO(playmobil): Implement.
-    SkASSERT(false);
-    // LoadPathToDC(context, path);
-    // hrgn = PathToRegion(context);
-  }
-}
-
-void BitmapPlatformDevice::LoadConfig() {
-  if (!config_dirty_ || !bitmap_context_)
-    return;  // Nothing to do.
-  config_dirty_ = false;
-
-  // We must restore and then save the state of the graphics context since the
-  // calls to Load the clipping region to the context are strictly cummulative,
-  // i.e., you can't replace a clip rect, other than with a save/restore.
-  // But this implies that no other changes to the state are done elsewhere.
-  // If we ever get to need to change this, then we must replace the clip rect
-  // calls in LoadClippingRegionToCGContext() with an image mask instead.
-  CGContextRestoreGState(bitmap_context_);
-  CGContextSaveGState(bitmap_context_);
-  LoadTransformToCGContext(bitmap_context_, transform_);
-  LoadClippingRegionToCGContext(bitmap_context_, clip_region_, transform_);
-}
-
-
-// We use this static factory function instead of the regular constructor so
-// that we can create the pixel data before calling the constructor. This is
-// required so that we can call the base class' constructor with the pixel
-// data.
-BitmapPlatformDevice* BitmapPlatformDevice::Create(CGContextRef context,
-                                                   int width,
-                                                   int height,
-                                                   bool is_opaque,
-                                                   bool do_clear) {
-  if (RasterDeviceTooBigToAllocate(width, height))
-    return NULL;
-
-  SkBitmap bitmap;
-  // TODO: verify that the CG Context's pixels will have tight rowbytes or pass in the correct
-  // rowbytes for the case when context != NULL.
-  bitmap.setInfo(SkImageInfo::MakeN32(width, height, is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType));
-
-  void* data;
-  if (context) {
-    data = CGBitmapContextGetData(context);
-    bitmap.setPixels(data);
-  } else {
-    if (!bitmap.tryAllocPixels())
-      return NULL;
-    data = bitmap.getPixels();
-  }
-  if (do_clear)
-    memset(data, 0, bitmap.getSafeSize());
-
-  // If we were given data, then don't clobber it!
-#ifndef NDEBUG
-  if (!context && is_opaque) {
-    // To aid in finding bugs, we set the background color to something
-    // obviously wrong so it will be noticable when it is not cleared
-    bitmap.eraseARGB(255, 0, 255, 128);  // bright bluish green
-  }
-#endif
-
-  if (!context) {
-    context = CGContextForData(data, width, height);
-    if (!context)
-      return NULL;
-  } else
-    CGContextRetain(context);
-
-  BitmapPlatformDevice* rv = new BitmapPlatformDevice(context, bitmap);
-
-  // The device object took ownership of the graphics context with its own
-  // CGContextRetain call.
-  CGContextRelease(context);
-
-  return rv;
-}
-
-BitmapPlatformDevice* BitmapPlatformDevice::CreateWithData(uint8_t* data,
-                                                           int width,
-                                                           int height,
-                                                           bool is_opaque) {
-  CGContextRef context = NULL;
-  if (data)
-    context = CGContextForData(data, width, height);
-
-  BitmapPlatformDevice* rv = Create(context, width, height, is_opaque, false);
-
-  // The device object took ownership of the graphics context with its own
-  // CGContextRetain call.
-  if (context)
-    CGContextRelease(context);
-
-  return rv;
-}
-
-// The device will own the bitmap, which corresponds to also owning the pixel
-// data. Therefore, we do not transfer ownership to the SkBitmapDevice's bitmap.
-BitmapPlatformDevice::BitmapPlatformDevice(
-    CGContextRef context, const SkBitmap& bitmap)
-    : SkBitmapDevice(bitmap),
-      bitmap_context_(context),
-      config_dirty_(true),  // Want to load the config next time.
-      transform_(SkMatrix::I()) {
-  SetPlatformDevice(this, this);
-  SkASSERT(bitmap_context_);
-  // Initialize the clip region to the entire bitmap.
-
-  SkIRect rect;
-  rect.set(0, 0,
-           CGBitmapContextGetWidth(bitmap_context_),
-           CGBitmapContextGetHeight(bitmap_context_));
-  clip_region_ = SkRegion(rect);
-  CGContextRetain(bitmap_context_);
-  // We must save the state once so that we can use the restore/save trick
-  // in LoadConfig().
-  CGContextSaveGState(bitmap_context_);
-}
-
-BitmapPlatformDevice::~BitmapPlatformDevice() {
-  if (bitmap_context_)
-    CGContextRelease(bitmap_context_);
-}
-
-CGContextRef BitmapPlatformDevice::GetBitmapContext() {
-  LoadConfig();
-  return bitmap_context_;
-}
-
-void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform,
-                                         const SkRegion& region,
-                                         const SkClipStack&) {
-  SetMatrixClip(transform, region);
-}
-
-SkBaseDevice* BitmapPlatformDevice::onCreateDevice(const CreateInfo& cinfo,
-                                                   const SkPaint*) {
-  const SkImageInfo& info = cinfo.fInfo;
-  const bool do_clear = !info.isOpaque();
-  SkASSERT(info.colorType() == kN32_SkColorType);
-  return Create(NULL, info.width(), info.height(), info.isOpaque(), do_clear);
-}
-
-// PlatformCanvas impl
-
-SkCanvas* CreatePlatformCanvas(CGContextRef ctx, int width, int height,
-                               bool is_opaque, OnFailureType failureType) {
-  const bool do_clear = false;
-  skia::RefPtr<SkBaseDevice> dev = skia::AdoptRef(
-      BitmapPlatformDevice::Create(ctx, width, height, is_opaque, do_clear));
-  return CreateCanvas(dev, failureType);
-}
-
-SkCanvas* CreatePlatformCanvas(int width, int height, bool is_opaque,
-                               uint8_t* data, OnFailureType failureType) {
-  skia::RefPtr<SkBaseDevice> dev = skia::AdoptRef(
-      BitmapPlatformDevice::CreateWithData(data, width, height, is_opaque));
-  return CreateCanvas(dev, failureType);
-}
-
-// Port of PlatformBitmap to mac
-
-PlatformBitmap::~PlatformBitmap() {
-  if (surface_)
-    CGContextRelease(surface_);
-}
-
-bool PlatformBitmap::Allocate(int width, int height, bool is_opaque) {
-  if (RasterDeviceTooBigToAllocate(width, height))
-    return false;
-    
-  if (!bitmap_.tryAllocN32Pixels(width, height, is_opaque))
-    return false;
-
-  if (!is_opaque)
-    bitmap_.eraseColor(0);
-
-  surface_ = CGContextForData(bitmap_.getPixels(), bitmap_.width(),
-                              bitmap_.height());
-  return true;
-}
-
-}  // namespace skia
diff --git a/skia/ext/bitmap_platform_device_mac.h b/skia/ext/bitmap_platform_device_mac.h
deleted file mode 100644
index 566924b..0000000
--- a/skia/ext/bitmap_platform_device_mac.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SKIA_EXT_BITMAP_PLATFORM_DEVICE_MAC_H_
-#define SKIA_EXT_BITMAP_PLATFORM_DEVICE_MAC_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "skia/ext/platform_device.h"
-#include "skia/ext/refptr.h"
-
-namespace skia {
-
-// A device is basically a wrapper around SkBitmap that provides a surface for
-// SkCanvas to draw into. Our device provides a surface CoreGraphics can also
-// write to. BitmapPlatformDevice creates a bitmap using
-// CGCreateBitmapContext() in a format that Skia supports and can then use this
-// to draw text into, etc. This pixel data is provided to the bitmap that the
-// device contains so that it can be shared.
-//
-// The device owns the pixel data, when the device goes away, the pixel data
-// also becomes invalid. THIS IS DIFFERENT THAN NORMAL SKIA which uses
-// reference counting for the pixel data. In normal Skia, you could assign
-// another bitmap to this device's bitmap and everything will work properly.
-// For us, that other bitmap will become invalid as soon as the device becomes
-// invalid, which may lead to subtle bugs. Therefore, DO NOT ASSIGN THE
-// DEVICE'S PIXEL DATA TO ANOTHER BITMAP, make sure you copy instead.
-class SK_API BitmapPlatformDevice : public SkBitmapDevice, public PlatformDevice {
- public:
-  // Creates a BitmapPlatformDevice instance. |is_opaque| should be set if the
-  // caller knows the bitmap will be completely opaque and allows some
-  // optimizations.
-  // |context| may be NULL. If |context| is NULL, then the bitmap backing store
-  // is not initialized.
-  static BitmapPlatformDevice* Create(CGContextRef context,
-                                      int width, int height,
-                                      bool is_opaque, bool do_clear = false);
-
-  // Creates a context for |data| and calls Create.
-  // If |data| is NULL, then the bitmap backing store is not initialized.
-  static BitmapPlatformDevice* CreateWithData(uint8_t* data,
-                                              int width, int height,
-                                              bool is_opaque);
-
-  ~BitmapPlatformDevice() override;
-
-  // PlatformDevice overrides
-  CGContextRef GetBitmapContext() override;
-
-  // SkBaseDevice overrides
-  void setMatrixClip(const SkMatrix& transform,
-                     const SkRegion& region,
-                     const SkClipStack&) override;
-
- protected:
-  BitmapPlatformDevice(CGContextRef context,
-                       const SkBitmap& bitmap);
-
-  SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;
-
- private:
-  void ReleaseBitmapContext();
-
-  // Sets the transform and clip operations. This will not update the CGContext,
-  // but will mark the config as dirty. The next call of LoadConfig will
-  // pick up these changes.
-  void SetMatrixClip(const SkMatrix& transform, const SkRegion& region);
-
-  // Loads the current transform and clip into the context. Can be called even
-  // when |bitmap_context_| is NULL (will be a NOP).
-  void LoadConfig();
-
-  // Lazily-created graphics context used to draw into the bitmap.
-  CGContextRef bitmap_context_;
-
-  // True when there is a transform or clip that has not been set to the
-  // context.  The context is retrieved for every text operation, and the
-  // transform and clip do not change as much. We can save time by not loading
-  // the clip and transform for every one.
-  bool config_dirty_;
-
-  // Translation assigned to the context: we need to keep track of this
-  // separately so it can be updated even if the context isn't created yet.
-  SkMatrix transform_;
-
-  // The current clipping
-  SkRegion clip_region_;
-  DISALLOW_COPY_AND_ASSIGN(BitmapPlatformDevice);
-};
-
-}  // namespace skia
-
-#endif  // SKIA_EXT_BITMAP_PLATFORM_DEVICE_MAC_H_
diff --git a/skia/ext/bitmap_platform_device_mac_unittest.cc b/skia/ext/bitmap_platform_device_mac_unittest.cc
deleted file mode 100644
index 7265bc4..0000000
--- a/skia/ext/bitmap_platform_device_mac_unittest.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/bitmap_platform_device_mac.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "skia/ext/skia_utils_mac.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkMatrix.h"
-#include "third_party/skia/include/core/SkRegion.h"
-#include "third_party/skia/include/core/SkClipStack.h"
-
-namespace skia {
-
-const int kWidth = 400;
-const int kHeight = 300;
-
-class BitmapPlatformDeviceMacTest : public testing::Test {
- public:
-  BitmapPlatformDeviceMacTest() {
-    bitmap_.reset(BitmapPlatformDevice::Create(
-        NULL, kWidth, kHeight, /*is_opaque=*/true));
-  }
-
-  scoped_ptr<BitmapPlatformDevice> bitmap_;
-};
-
-TEST_F(BitmapPlatformDeviceMacTest, ClipRectTransformWithTranslate) {
-  SkMatrix transform;
-  transform.setTranslate(50, 140);
-
-  SkClipStack ignore;
-  SkRegion clip_region;
-  SkIRect rect;
-  rect.set(0, 0, kWidth, kHeight);
-  clip_region.setRect(rect);
-  bitmap_->setMatrixClip(transform, clip_region, ignore);
-
-  CGContextRef context = bitmap_->GetBitmapContext();
-  SkRect clip_rect = gfx::CGRectToSkRect(CGContextGetClipBoundingBox(context));
-  transform.mapRect(&clip_rect);
-  EXPECT_EQ(0, clip_rect.fLeft);
-  EXPECT_EQ(0, clip_rect.fTop);
-  EXPECT_EQ(kWidth, clip_rect.width());
-  EXPECT_EQ(kHeight, clip_rect.height());
-}
-
-TEST_F(BitmapPlatformDeviceMacTest, ClipRectTransformWithScale) {
-  SkMatrix transform;
-  transform.setScale(0.5, 0.5);
-
-  SkClipStack unused;
-  SkRegion clip_region;
-  SkIRect rect;
-  rect.set(0, 0, kWidth, kHeight);
-  clip_region.setRect(rect);
-  bitmap_->setMatrixClip(transform, clip_region, unused);
-
-  CGContextRef context = bitmap_->GetBitmapContext();
-  SkRect clip_rect = gfx::CGRectToSkRect(CGContextGetClipBoundingBox(context));
-  transform.mapRect(&clip_rect);
-  EXPECT_EQ(0, clip_rect.fLeft);
-  EXPECT_EQ(0, clip_rect.fTop);
-  EXPECT_EQ(kWidth, clip_rect.width());
-  EXPECT_EQ(kHeight, clip_rect.height());
-}
-
-}  // namespace skia
diff --git a/skia/ext/bitmap_platform_device_skia.cc b/skia/ext/bitmap_platform_device_skia.cc
deleted file mode 100644
index 04fc950..0000000
--- a/skia/ext/bitmap_platform_device_skia.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/bitmap_platform_device_skia.h"
-#include "skia/ext/platform_canvas.h"
-
-namespace skia {
-
-BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
-                                                   bool is_opaque) {
-  SkBitmap bitmap;
-  if (bitmap.tryAllocN32Pixels(width, height, is_opaque)) {
-    // Follow the logic in SkCanvas::createDevice(), initialize the bitmap if it
-    // is not opaque.
-    if (!is_opaque)
-      bitmap.eraseARGB(0, 0, 0, 0);
-    return new BitmapPlatformDevice(bitmap);
-  }
-  return NULL;
-}
-
-BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
-                                                   bool is_opaque,
-                                                   uint8_t* data) {
-  SkBitmap bitmap;
-  bitmap.setInfo(SkImageInfo::MakeN32(width, height,
-      is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType));
-  if (data)
-    bitmap.setPixels(data);
-  else if (!bitmap.tryAllocPixels())
-    return NULL;
-
-  return new BitmapPlatformDevice(bitmap);
-}
-
-BitmapPlatformDevice::BitmapPlatformDevice(const SkBitmap& bitmap)
-    : SkBitmapDevice(bitmap) {
-  SetPlatformDevice(this, this);
-}
-
-BitmapPlatformDevice::~BitmapPlatformDevice() {
-}
-
-SkBaseDevice* BitmapPlatformDevice::onCreateDevice(const CreateInfo& info,
-                                                   const SkPaint*) {
-  SkASSERT(info.fInfo.colorType() == kN32_SkColorType);
-  return BitmapPlatformDevice::Create(info.fInfo.width(), info.fInfo.height(),
-                                      info.fInfo.isOpaque());
-}
-
-PlatformSurface BitmapPlatformDevice::BeginPlatformPaint() {
-  // TODO(zhenghao): What should we return? The ptr to the address of the
-  // pixels? Maybe this won't be called at all.
-  return accessBitmap(true).getPixels();
-}
-
-// PlatformCanvas impl
-
-SkCanvas* CreatePlatformCanvas(int width, int height, bool is_opaque,
-                               uint8_t* data, OnFailureType failureType) {
-  skia::RefPtr<SkBaseDevice> dev = skia::AdoptRef(
-      BitmapPlatformDevice::Create(width, height, is_opaque, data));
-  return CreateCanvas(dev, failureType);
-}
-
-// Port of PlatformBitmap to android
-PlatformBitmap::~PlatformBitmap() {
-  // Nothing to do.
-}
-
-bool PlatformBitmap::Allocate(int width, int height, bool is_opaque) {
-  if (!bitmap_.tryAllocN32Pixels(width, height, is_opaque))
-    return false;
-
-  surface_ = bitmap_.getPixels();
-  return true;
-}
-
-}  // namespace skia
diff --git a/skia/ext/bitmap_platform_device_skia.h b/skia/ext/bitmap_platform_device_skia.h
deleted file mode 100644
index 0e21929..0000000
--- a/skia/ext/bitmap_platform_device_skia.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SKIA_EXT_BITMAP_PLATFORM_DEVICE_SKIA_H_
-#define SKIA_EXT_BITMAP_PLATFORM_DEVICE_SKIA_H_
-
-#include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
-#include "skia/ext/platform_device.h"
-
-namespace skia {
-
-// -----------------------------------------------------------------------------
-// For now we just use SkBitmap for SkBitmapDevice
-//
-// This is all quite ok for test_shell. In the future we will want to use
-// shared memory between the renderer and the main process at least. In this
-// case we'll probably create the buffer from a precreated region of memory.
-// -----------------------------------------------------------------------------
-class BitmapPlatformDevice : public SkBitmapDevice, public PlatformDevice {
- public:
-  // Construct a BitmapPlatformDevice. |is_opaque| should be set if the caller
-  // knows the bitmap will be completely opaque and allows some optimizations.
-  // The bitmap is not initialized.
-  static BitmapPlatformDevice* Create(int width, int height, bool is_opaque);
-
-  // This doesn't take ownership of |data|. If |data| is null, the bitmap
-  // is not initialized to 0.
-  static BitmapPlatformDevice* Create(int width, int height, bool is_opaque,
-                                      uint8_t* data);
-
-  // Create a BitmapPlatformDevice from an already constructed bitmap;
-  // you should probably be using Create(). This may become private later if
-  // we ever have to share state between some native drawing UI and Skia, like
-  // the Windows and Mac versions of this class do.
-  explicit BitmapPlatformDevice(const SkBitmap& other);
-  ~BitmapPlatformDevice() override;
-
-  PlatformSurface BeginPlatformPaint() override;
-
- protected:
-  SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(BitmapPlatformDevice);
-};
-
-}  // namespace skia
-
-#endif  // SKIA_EXT_BITMAP_PLATFORM_DEVICE_SKIA_H_
diff --git a/skia/ext/bitmap_platform_device_win.cc b/skia/ext/bitmap_platform_device_win.cc
deleted file mode 100644
index 6310820..0000000
--- a/skia/ext/bitmap_platform_device_win.cc
+++ /dev/null
@@ -1,328 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <windows.h>
-#include <psapi.h>
-
-#include "base/debug/gdi_debug_util_win.h"
-#include "base/logging.h"
-#include "skia/ext/bitmap_platform_device_win.h"
-#include "skia/ext/platform_canvas.h"
-#include "third_party/skia/include/core/SkMatrix.h"
-#include "third_party/skia/include/core/SkRefCnt.h"
-#include "third_party/skia/include/core/SkRegion.h"
-#include "third_party/skia/include/core/SkUtils.h"
-
-namespace {
-
-HBITMAP CreateHBitmap(int width, int height, bool is_opaque,
-                             HANDLE shared_section, void** data) {
-  // CreateDIBSection appears to get unhappy if we create an empty bitmap, so
-  // just create a minimal bitmap
-  if ((width == 0) || (height == 0)) {
-    width = 1;
-    height = 1;
-  }
-
-  BITMAPINFOHEADER hdr = {0};
-  hdr.biSize = sizeof(BITMAPINFOHEADER);
-  hdr.biWidth = width;
-  hdr.biHeight = -height;  // minus means top-down bitmap
-  hdr.biPlanes = 1;
-  hdr.biBitCount = 32;
-  hdr.biCompression = BI_RGB;  // no compression
-  hdr.biSizeImage = 0;
-  hdr.biXPelsPerMeter = 1;
-  hdr.biYPelsPerMeter = 1;
-  hdr.biClrUsed = 0;
-  hdr.biClrImportant = 0;
-
-  HBITMAP hbitmap = CreateDIBSection(NULL, reinterpret_cast<BITMAPINFO*>(&hdr),
-                                     0, data, shared_section, 0);
-
-#if !defined(_WIN64)
-  // If this call fails, we're gonna crash hard. Try to get some useful
-  // information out before we crash for post-mortem analysis.
-  if (!hbitmap)
-    base::debug::GDIBitmapAllocFailure(&hdr, shared_section);
-#endif
-
-  return hbitmap;
-}
-
-}  // namespace
-
-namespace skia {
-
-void DrawToNativeContext(SkCanvas* canvas, HDC hdc, int x, int y,
-                         const RECT* src_rect) {
-  PlatformDevice* platform_device = GetPlatformDevice(GetTopDevice(*canvas));
-  if (platform_device)
-    platform_device->DrawToHDC(hdc, x, y, src_rect);
-}
-
-void PlatformDevice::DrawToHDC(HDC, int x, int y, const RECT* src_rect) {}
-
-HDC BitmapPlatformDevice::GetBitmapDC() {
-  if (!hdc_) {
-    hdc_ = CreateCompatibleDC(NULL);
-    InitializeDC(hdc_);
-    old_hbitmap_ = static_cast<HBITMAP>(SelectObject(hdc_, hbitmap_));
-  }
-
-  LoadConfig();
-  return hdc_;
-}
-
-void BitmapPlatformDevice::ReleaseBitmapDC() {
-  SkASSERT(hdc_);
-  SelectObject(hdc_, old_hbitmap_);
-  DeleteDC(hdc_);
-  hdc_ = NULL;
-  old_hbitmap_ = NULL;
-}
-
-bool BitmapPlatformDevice::IsBitmapDCCreated()
-    const {
-  return hdc_ != NULL;
-}
-
-
-void BitmapPlatformDevice::SetMatrixClip(
-    const SkMatrix& transform,
-    const SkRegion& region) {
-  transform_ = transform;
-  clip_region_ = region;
-  config_dirty_ = true;
-}
-
-void BitmapPlatformDevice::LoadConfig() {
-  if (!config_dirty_ || !hdc_)
-    return;  // Nothing to do.
-  config_dirty_ = false;
-
-  // Transform.
-  LoadTransformToDC(hdc_, transform_);
-  LoadClippingRegionToDC(hdc_, clip_region_, transform_);
-}
-
-static void DeleteHBitmapCallback(void* addr, void* context) {
-  DeleteObject(static_cast<HBITMAP>(context));
-}
-
-static bool InstallHBitmapPixels(SkBitmap* bitmap, int width, int height,
-                                 bool is_opaque, void* data, HBITMAP hbitmap) {
-  const SkAlphaType at = is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
-  const SkImageInfo info = SkImageInfo::MakeN32(width, height, at);
-  const size_t rowBytes = info.minRowBytes();
-  SkColorTable* color_table = NULL;
-  return bitmap->installPixels(info, data, rowBytes, color_table,
-                               DeleteHBitmapCallback, hbitmap);
-}
-
-// We use this static factory function instead of the regular constructor so
-// that we can create the pixel data before calling the constructor. This is
-// required so that we can call the base class' constructor with the pixel
-// data.
-BitmapPlatformDevice* BitmapPlatformDevice::Create(
-    int width,
-    int height,
-    bool is_opaque,
-    HANDLE shared_section,
-    bool do_clear) {
-
-  void* data;
-  HBITMAP hbitmap = CreateHBitmap(width, height, is_opaque, shared_section,
-                                  &data);
-  if (!hbitmap)
-    return NULL;
-
-  SkBitmap bitmap;
-  if (!InstallHBitmapPixels(&bitmap, width, height, is_opaque, data, hbitmap))
-    return NULL;
-
-  if (do_clear)
-    bitmap.eraseColor(0);
-
-#ifndef NDEBUG
-  // If we were given data, then don't clobber it!
-  if (!shared_section && is_opaque)
-    // To aid in finding bugs, we set the background color to something
-    // obviously wrong so it will be noticable when it is not cleared
-    bitmap.eraseARGB(255, 0, 255, 128);  // bright bluish green
-#endif
-
-  // The device object will take ownership of the HBITMAP. The initial refcount
-  // of the data object will be 1, which is what the constructor expects.
-  return new BitmapPlatformDevice(hbitmap, bitmap);
-}
-
-// static
-BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
-                                                   bool is_opaque) {
-  const HANDLE shared_section = NULL;
-  const bool do_clear = false;
-  return Create(width, height, is_opaque, shared_section, do_clear);
-}
-
-// The device will own the HBITMAP, which corresponds to also owning the pixel
-// data. Therefore, we do not transfer ownership to the SkBitmapDevice's bitmap.
-BitmapPlatformDevice::BitmapPlatformDevice(
-    HBITMAP hbitmap,
-    const SkBitmap& bitmap)
-    : SkBitmapDevice(bitmap),
-      hbitmap_(hbitmap),
-      old_hbitmap_(NULL),
-      hdc_(NULL),
-      config_dirty_(true),  // Want to load the config next time.
-      transform_(SkMatrix::I()) {
-  // The data object is already ref'ed for us by create().
-  SkDEBUGCODE(begin_paint_count_ = 0);
-  SetPlatformDevice(this, this);
-  // Initialize the clip region to the entire bitmap.
-  BITMAP bitmap_data;
-  if (GetObject(hbitmap_, sizeof(BITMAP), &bitmap_data)) {
-    SkIRect rect;
-    rect.set(0, 0, bitmap_data.bmWidth, bitmap_data.bmHeight);
-    clip_region_ = SkRegion(rect);
-  }
-}
-
-BitmapPlatformDevice::~BitmapPlatformDevice() {
-  SkASSERT(begin_paint_count_ == 0);
-  if (hdc_)
-    ReleaseBitmapDC();
-}
-
-HDC BitmapPlatformDevice::BeginPlatformPaint() {
-  SkDEBUGCODE(begin_paint_count_++);
-  return GetBitmapDC();
-}
-
-void BitmapPlatformDevice::EndPlatformPaint() {
-  SkASSERT(begin_paint_count_--);
-  PlatformDevice::EndPlatformPaint();
-}
-
-void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform,
-                                         const SkRegion& region,
-                                         const SkClipStack&) {
-  SetMatrixClip(transform, region);
-}
-
-void BitmapPlatformDevice::DrawToHDC(HDC dc, int x, int y,
-                                     const RECT* src_rect) {
-  bool created_dc = !IsBitmapDCCreated();
-  HDC source_dc = BeginPlatformPaint();
-
-  RECT temp_rect;
-  if (!src_rect) {
-    temp_rect.left = 0;
-    temp_rect.right = width();
-    temp_rect.top = 0;
-    temp_rect.bottom = height();
-    src_rect = &temp_rect;
-  }
-
-  int copy_width = src_rect->right - src_rect->left;
-  int copy_height = src_rect->bottom - src_rect->top;
-
-  // We need to reset the translation for our bitmap or (0,0) won't be in the
-  // upper left anymore
-  SkMatrix identity;
-  identity.reset();
-
-  LoadTransformToDC(source_dc, identity);
-  if (isOpaque()) {
-    BitBlt(dc,
-           x,
-           y,
-           copy_width,
-           copy_height,
-           source_dc,
-           src_rect->left,
-           src_rect->top,
-           SRCCOPY);
-  } else {
-    SkASSERT(copy_width != 0 && copy_height != 0);
-    BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
-    GdiAlphaBlend(dc,
-                  x,
-                  y,
-                  copy_width,
-                  copy_height,
-                  source_dc,
-                  src_rect->left,
-                  src_rect->top,
-                  copy_width,
-                  copy_height,
-                  blend_function);
-  }
-  LoadTransformToDC(source_dc, transform_);
-
-  EndPlatformPaint();
-  if (created_dc)
-    ReleaseBitmapDC();
-}
-
-const SkBitmap& BitmapPlatformDevice::onAccessBitmap() {
-  // FIXME(brettw) OPTIMIZATION: We should only flush if we know a GDI
-  // operation has occurred on our DC.
-  if (IsBitmapDCCreated())
-    GdiFlush();
-  return SkBitmapDevice::onAccessBitmap();
-}
-
-SkBaseDevice* BitmapPlatformDevice::onCreateDevice(const CreateInfo& cinfo,
-                                                   const SkPaint*) {
-  const SkImageInfo& info = cinfo.fInfo;
-  const bool do_clear = !info.isOpaque();
-  SkASSERT(info.colorType() == kN32_SkColorType);
-  return Create(info.width(), info.height(), info.isOpaque(), NULL, do_clear);
-}
-
-// PlatformCanvas impl
-
-SkCanvas* CreatePlatformCanvas(int width,
-                               int height,
-                               bool is_opaque,
-                               HANDLE shared_section,
-                               OnFailureType failureType) {
-  skia::RefPtr<SkBaseDevice> dev = skia::AdoptRef(
-      BitmapPlatformDevice::Create(width, height, is_opaque, shared_section));
-  return CreateCanvas(dev, failureType);
-}
-
-// Port of PlatformBitmap to win
-
-PlatformBitmap::~PlatformBitmap() {
-  if (surface_) {
-    if (platform_extra_)
-      SelectObject(surface_, reinterpret_cast<HGDIOBJ>(platform_extra_));
-    DeleteDC(surface_);
-  }
-}
-
-bool PlatformBitmap::Allocate(int width, int height, bool is_opaque) {
-  void* data;
-  HBITMAP hbitmap = CreateHBitmap(width, height, is_opaque, 0, &data);
-  if (!hbitmap)
-    return false;
-
-  surface_ = CreateCompatibleDC(NULL);
-  InitializeDC(surface_);
-  // When the memory DC is created, its display surface is exactly one
-  // monochrome pixel wide and one monochrome pixel high. Save this object
-  // off, we'll restore it just before deleting the memory DC.
-  HGDIOBJ stock_bitmap = SelectObject(surface_, hbitmap);
-  platform_extra_ = reinterpret_cast<intptr_t>(stock_bitmap);
-
-  if (!InstallHBitmapPixels(&bitmap_, width, height, is_opaque, data, hbitmap))
-    return false;
-  bitmap_.lockPixels();
-
-  return true;
-}
-
-}  // namespace skia
diff --git a/skia/ext/bitmap_platform_device_win.h b/skia/ext/bitmap_platform_device_win.h
deleted file mode 100644
index 4a8ad8f..0000000
--- a/skia/ext/bitmap_platform_device_win.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SKIA_EXT_BITMAP_PLATFORM_DEVICE_WIN_H_
-#define SKIA_EXT_BITMAP_PLATFORM_DEVICE_WIN_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "skia/ext/platform_device.h"
-#include "skia/ext/refptr.h"
-
-namespace skia {
-
-// A device is basically a wrapper around SkBitmap that provides a surface for
-// SkCanvas to draw into. Our device provides a surface Windows can also write
-// to. BitmapPlatformDevice creates a bitmap using CreateDIBSection() in a
-// format that Skia supports and can then use this to draw ClearType into, etc.
-// This pixel data is provided to the bitmap that the device contains so that it
-// can be shared.
-//
-// The GDI bitmap created for drawing is actually owned by a
-// PlatformBitmapPixelRef, and stored in an SkBitmap via the normal skia
-// SkPixelRef refcounting mechanism. In this way, the GDI bitmap can outlive
-// the device created to draw into it. So it is safe to call accessBitmap() on
-// the device, and retain the returned SkBitmap.
-class SK_API BitmapPlatformDevice : public SkBitmapDevice, public PlatformDevice {
- public:
-  // Factory function. is_opaque should be set if the caller knows the bitmap
-  // will be completely opaque and allows some optimizations.
-  //
-  // The |shared_section| parameter is optional (pass NULL for default
-  // behavior). If |shared_section| is non-null, then it must be a handle to a
-  // file-mapping object returned by CreateFileMapping.  See CreateDIBSection
-  // for details. If |shared_section| is null, the bitmap backing store is not
-  // initialized.
-  static BitmapPlatformDevice* Create(int width, int height,
-                                      bool is_opaque, HANDLE shared_section,
-                                      bool do_clear = false);
-
-  // Create a BitmapPlatformDevice with no shared section. The bitmap is not
-  // initialized to 0.
-  static BitmapPlatformDevice* Create(int width, int height, bool is_opaque);
-
-  virtual ~BitmapPlatformDevice();
-
-  // PlatformDevice overrides
-  // Retrieves the bitmap DC, which is the memory DC for our bitmap data. The
-  // bitmap DC is lazy created.
-  virtual PlatformSurface BeginPlatformPaint() override;
-  virtual void EndPlatformPaint() override;
-
-  // Loads the given transform and clipping region into the HDC. This is
-  // overridden from SkBaseDevice.
-  virtual void setMatrixClip(const SkMatrix& transform, const SkRegion& region,
-                             const SkClipStack&) override;
-
-  void DrawToHDC(HDC dc, int x, int y, const RECT* src_rect) override;
-
- protected:
-  // Flushes the Windows device context so that the pixel data can be accessed
-  // directly by Skia. Overridden from SkBaseDevice, this is called when Skia
-  // starts accessing pixel data.
-  virtual const SkBitmap& onAccessBitmap() override;
-
-  SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;
-
- private:
-  // Private constructor.
-  BitmapPlatformDevice(HBITMAP hbitmap, const SkBitmap& bitmap);
-
-  // Bitmap into which the drawing will be done. This bitmap not owned by this
-  // class, but by the BitmapPlatformPixelRef inside the device's SkBitmap.
-  // It's only stored here in order to lazy-create the DC (below).
-  HBITMAP hbitmap_;
-
-  // Previous bitmap held by the DC. This will be selected back before the
-  // DC is destroyed.
-  HBITMAP old_hbitmap_;
-
-  // Lazily-created DC used to draw into the bitmap; see GetBitmapDC().
-  HDC hdc_;
-
-  // True when there is a transform or clip that has not been set to the
-  // context.  The context is retrieved for every text operation, and the
-  // transform and clip do not change as much. We can save time by not loading
-  // the clip and transform for every one.
-  bool config_dirty_;
-
-  // Translation assigned to the context: we need to keep track of this
-  // separately so it can be updated even if the context isn't created yet.
-  SkMatrix transform_;
-
-  // The current clipping region.
-  SkRegion clip_region_;
-
-  // Create/destroy hdc_, which is the memory DC for our bitmap data.
-  HDC GetBitmapDC();
-  void ReleaseBitmapDC();
-  bool IsBitmapDCCreated() const;
-
-  // Sets the transform and clip operations. This will not update the DC,
-  // but will mark the config as dirty. The next call of LoadConfig will
-  // pick up these changes.
-  void SetMatrixClip(const SkMatrix& transform, const SkRegion& region);
-
-  // Loads the current transform and clip into the context. Can be called even
-  // when |hbitmap_| is NULL (will be a NOP).
-  void LoadConfig();
-
-#ifdef SK_DEBUG
-  int begin_paint_count_;
-#endif
-
-  DISALLOW_COPY_AND_ASSIGN(BitmapPlatformDevice);
-};
-
-}  // namespace skia
-
-#endif  // SKIA_EXT_BITMAP_PLATFORM_DEVICE_WIN_H_
diff --git a/skia/ext/convolver.cc b/skia/ext/convolver.cc
new file mode 100644
index 0000000..9d07cff
--- /dev/null
+++ b/skia/ext/convolver.cc
@@ -0,0 +1,705 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "skia/ext/convolver.h"
+#include "skia/ext/convolver_SSE2.h"
+#include "skia/ext/convolver_mips_dspr2.h"
+#include "third_party/skia/include/core/SkSize.h"
+#include "third_party/skia/include/core/SkTypes.h"
+
+namespace skia {
+
+namespace {
+
+// Converts the argument to an 8-bit unsigned value by clamping to the range
+// 0-255.
+inline unsigned char ClampTo8(int a) {
+  if (static_cast<unsigned>(a) < 256)
+    return a;  // Avoid the extra check in the common case.
+  if (a < 0)
+    return 0;
+  return 255;
+}
+
+// Takes the value produced by accumulating element-wise product of image with
+// a kernel and brings it back into range.
+// All of the filter scaling factors are in fixed point with kShiftBits bits of
+// fractional part.
+inline unsigned char BringBackTo8(int a, bool take_absolute) {
+  a >>= ConvolutionFilter1D::kShiftBits;
+  if (take_absolute)
+    a = std::abs(a);
+  return ClampTo8(a);
+}
+
+// Stores a list of rows in a circular buffer. The usage is you write into it
+// by calling AdvanceRow. It will keep track of which row in the buffer it
+// should use next, and the total number of rows added.
+class CircularRowBuffer {
+ public:
+  // The number of pixels in each row is given in |source_row_pixel_width|.
+  // The maximum number of rows needed in the buffer is |max_y_filter_size|
+  // (we only need to store enough rows for the biggest filter).
+  //
+  // We use the |first_input_row| to compute the coordinates of all of the
+  // following rows returned by Advance().
+  CircularRowBuffer(int dest_row_pixel_width,
+                    int max_y_filter_size,
+                    int first_input_row)
+      : row_byte_width_(dest_row_pixel_width * 4),
+        num_rows_(max_y_filter_size),
+        next_row_(0),
+        next_row_coordinate_(first_input_row) {
+    buffer_.resize(row_byte_width_ * max_y_filter_size);
+    row_addresses_.resize(num_rows_);
+  }
+
+  // Moves to the next row in the buffer, returning a pointer to the beginning
+  // of it.
+  unsigned char* AdvanceRow() {
+    unsigned char* row = &buffer_[next_row_ * row_byte_width_];
+    next_row_coordinate_++;
+
+    // Set the pointer to the next row to use, wrapping around if necessary.
+    next_row_++;
+    if (next_row_ == num_rows_)
+      next_row_ = 0;
+    return row;
+  }
+
+  // Returns a pointer to an "unrolled" array of rows. These rows will start
+  // at the y coordinate placed into |*first_row_index| and will continue in
+  // order for the maximum number of rows in this circular buffer.
+  //
+  // The |first_row_index_| may be negative. This means the circular buffer
+  // starts before the top of the image (it hasn't been filled yet).
+  unsigned char* const* GetRowAddresses(int* first_row_index) {
+    // Example for a 4-element circular buffer holding coords 6-9.
+    //   Row 0   Coord 8
+    //   Row 1   Coord 9
+    //   Row 2   Coord 6  <- next_row_ = 2, next_row_coordinate_ = 10.
+    //   Row 3   Coord 7
+    //
+    // The "next" row is also the first (lowest) coordinate. This computation
+    // may yield a negative value, but that's OK, the math will work out
+    // since the user of this buffer will compute the offset relative
+    // to the first_row_index and the negative rows will never be used.
+    *first_row_index = next_row_coordinate_ - num_rows_;
+
+    int cur_row = next_row_;
+    for (int i = 0; i < num_rows_; i++) {
+      row_addresses_[i] = &buffer_[cur_row * row_byte_width_];
+
+      // Advance to the next row, wrapping if necessary.
+      cur_row++;
+      if (cur_row == num_rows_)
+        cur_row = 0;
+    }
+    return &row_addresses_[0];
+  }
+
+ private:
+  // The buffer storing the rows. They are packed, each one row_byte_width_.
+  std::vector<unsigned char> buffer_;
+
+  // Number of bytes per row in the |buffer_|.
+  int row_byte_width_;
+
+  // The number of rows available in the buffer.
+  int num_rows_;
+
+  // The next row index we should write into. This wraps around as the
+  // circular buffer is used.
+  int next_row_;
+
+  // The y coordinate of the |next_row_|. This is incremented each time a
+  // new row is appended and does not wrap.
+  int next_row_coordinate_;
+
+  // Buffer used by GetRowAddresses().
+  std::vector<unsigned char*> row_addresses_;
+};
+
+// Convolves horizontally along a single row. The row data is given in
+// |src_data| and continues for the num_values() of the filter.
+template <bool has_alpha>
+void ConvolveHorizontally(const unsigned char* src_data,
+                          const ConvolutionFilter1D& filter,
+                          unsigned char* out_row) {
+  // Loop over each pixel on this row in the output image.
+  int num_values = filter.num_values();
+  for (int out_x = 0; out_x < num_values; out_x++) {
+    // Get the filter that determines the current output pixel.
+    int filter_offset, filter_length;
+    const ConvolutionFilter1D::Fixed* filter_values =
+        filter.FilterForValue(out_x, &filter_offset, &filter_length);
+
+    // Compute the first pixel in this row that the filter affects. It will
+    // touch |filter_length| pixels (4 bytes each) after this.
+    const unsigned char* row_to_filter = &src_data[filter_offset * 4];
+
+    // Apply the filter to the row to get the destination pixel in |accum|.
+    int accum[4] = {0};
+    for (int filter_x = 0; filter_x < filter_length; filter_x++) {
+      ConvolutionFilter1D::Fixed cur_filter = filter_values[filter_x];
+      accum[0] += cur_filter * row_to_filter[filter_x * 4 + 0];
+      accum[1] += cur_filter * row_to_filter[filter_x * 4 + 1];
+      accum[2] += cur_filter * row_to_filter[filter_x * 4 + 2];
+      if (has_alpha)
+        accum[3] += cur_filter * row_to_filter[filter_x * 4 + 3];
+    }
+
+    // Bring this value back in range. All of the filter scaling factors
+    // are in fixed point with kShiftBits bits of fractional part.
+    accum[0] >>= ConvolutionFilter1D::kShiftBits;
+    accum[1] >>= ConvolutionFilter1D::kShiftBits;
+    accum[2] >>= ConvolutionFilter1D::kShiftBits;
+    if (has_alpha)
+      accum[3] >>= ConvolutionFilter1D::kShiftBits;
+
+    // Store the new pixel.
+    out_row[out_x * 4 + 0] = ClampTo8(accum[0]);
+    out_row[out_x * 4 + 1] = ClampTo8(accum[1]);
+    out_row[out_x * 4 + 2] = ClampTo8(accum[2]);
+    if (has_alpha)
+      out_row[out_x * 4 + 3] = ClampTo8(accum[3]);
+  }
+}
+
+// Does vertical convolution to produce one output row. The filter values and
+// length are given in the first two parameters. These are applied to each
+// of the rows pointed to in the |source_data_rows| array, with each row
+// being |pixel_width| wide.
+//
+// The output must have room for |pixel_width * 4| bytes.
+template <bool has_alpha>
+void ConvolveVertically(const ConvolutionFilter1D::Fixed* filter_values,
+                        int filter_length,
+                        unsigned char* const* source_data_rows,
+                        int pixel_width,
+                        unsigned char* out_row) {
+  // We go through each column in the output and do a vertical convolution,
+  // generating one output pixel each time.
+  for (int out_x = 0; out_x < pixel_width; out_x++) {
+    // Compute the number of bytes over in each row that the current column
+    // we're convolving starts at. The pixel will cover the next 4 bytes.
+    int byte_offset = out_x * 4;
+
+    // Apply the filter to one column of pixels.
+    int accum[4] = {0};
+    for (int filter_y = 0; filter_y < filter_length; filter_y++) {
+      ConvolutionFilter1D::Fixed cur_filter = filter_values[filter_y];
+      accum[0] += cur_filter * source_data_rows[filter_y][byte_offset + 0];
+      accum[1] += cur_filter * source_data_rows[filter_y][byte_offset + 1];
+      accum[2] += cur_filter * source_data_rows[filter_y][byte_offset + 2];
+      if (has_alpha)
+        accum[3] += cur_filter * source_data_rows[filter_y][byte_offset + 3];
+    }
+
+    // Bring this value back in range. All of the filter scaling factors
+    // are in fixed point with kShiftBits bits of precision.
+    accum[0] >>= ConvolutionFilter1D::kShiftBits;
+    accum[1] >>= ConvolutionFilter1D::kShiftBits;
+    accum[2] >>= ConvolutionFilter1D::kShiftBits;
+    if (has_alpha)
+      accum[3] >>= ConvolutionFilter1D::kShiftBits;
+
+    // Store the new pixel.
+    out_row[byte_offset + 0] = ClampTo8(accum[0]);
+    out_row[byte_offset + 1] = ClampTo8(accum[1]);
+    out_row[byte_offset + 2] = ClampTo8(accum[2]);
+    if (has_alpha) {
+      unsigned char alpha = ClampTo8(accum[3]);
+
+      // Make sure the alpha channel doesn't come out smaller than any of the
+      // color channels. We use premultipled alpha channels, so this should
+      // never happen, but rounding errors will cause this from time to time.
+      // These "impossible" colors will cause overflows (and hence random pixel
+      // values) when the resulting bitmap is drawn to the screen.
+      //
+      // We only need to do this when generating the final output row (here).
+      int max_color_channel = std::max(
+          out_row[byte_offset + 0],
+          std::max(out_row[byte_offset + 1], out_row[byte_offset + 2]));
+      if (alpha < max_color_channel)
+        out_row[byte_offset + 3] = max_color_channel;
+      else
+        out_row[byte_offset + 3] = alpha;
+    } else {
+      // No alpha channel, the image is opaque.
+      out_row[byte_offset + 3] = 0xff;
+    }
+  }
+}
+
+void ConvolveVertically(const ConvolutionFilter1D::Fixed* filter_values,
+                        int filter_length,
+                        unsigned char* const* source_data_rows,
+                        int pixel_width,
+                        unsigned char* out_row,
+                        bool source_has_alpha) {
+  if (source_has_alpha) {
+    ConvolveVertically<true>(filter_values, filter_length, source_data_rows,
+                             pixel_width, out_row);
+  } else {
+    ConvolveVertically<false>(filter_values, filter_length, source_data_rows,
+                              pixel_width, out_row);
+  }
+}
+
+}  // namespace
+
+// ConvolutionFilter1D ---------------------------------------------------------
+
+ConvolutionFilter1D::ConvolutionFilter1D() : max_filter_(0) {}
+
+ConvolutionFilter1D::~ConvolutionFilter1D() {}
+
+void ConvolutionFilter1D::AddFilter(int filter_offset,
+                                    const float* filter_values,
+                                    int filter_length) {
+  SkASSERT(filter_length > 0);
+
+  std::vector<Fixed> fixed_values;
+  fixed_values.reserve(filter_length);
+
+  for (int i = 0; i < filter_length; ++i)
+    fixed_values.push_back(FloatToFixed(filter_values[i]));
+
+  AddFilter(filter_offset, &fixed_values[0], filter_length);
+}
+
+void ConvolutionFilter1D::AddFilter(int filter_offset,
+                                    const Fixed* filter_values,
+                                    int filter_length) {
+  // It is common for leading/trailing filter values to be zeros. In such
+  // cases it is beneficial to only store the central factors.
+  // For a scaling to 1/4th in each dimension using a Lanczos-2 filter on
+  // a 1080p image this optimization gives a ~10% speed improvement.
+  int filter_size = filter_length;
+  int first_non_zero = 0;
+  while (first_non_zero < filter_length && filter_values[first_non_zero] == 0)
+    first_non_zero++;
+
+  if (first_non_zero < filter_length) {
+    // Here we have at least one non-zero factor.
+    int last_non_zero = filter_length - 1;
+    while (last_non_zero >= 0 && filter_values[last_non_zero] == 0)
+      last_non_zero--;
+
+    filter_offset += first_non_zero;
+    filter_length = last_non_zero + 1 - first_non_zero;
+    SkASSERT(filter_length > 0);
+
+    for (int i = first_non_zero; i <= last_non_zero; i++)
+      filter_values_.push_back(filter_values[i]);
+  } else {
+    // Here all the factors were zeroes.
+    filter_length = 0;
+  }
+
+  FilterInstance instance;
+
+  // We pushed filter_length elements onto filter_values_
+  instance.data_location =
+      (static_cast<int>(filter_values_.size()) - filter_length);
+  instance.offset = filter_offset;
+  instance.trimmed_length = filter_length;
+  instance.length = filter_size;
+  filters_.push_back(instance);
+
+  max_filter_ = std::max(max_filter_, filter_length);
+}
+
+const ConvolutionFilter1D::Fixed* ConvolutionFilter1D::GetSingleFilter(
+    int* specified_filter_length,
+    int* filter_offset,
+    int* filter_length) const {
+  const FilterInstance& filter = filters_[0];
+  *filter_offset = filter.offset;
+  *filter_length = filter.trimmed_length;
+  *specified_filter_length = filter.length;
+  if (filter.trimmed_length == 0)
+    return NULL;
+
+  return &filter_values_[filter.data_location];
+}
+
+typedef void (*ConvolveVertically_pointer)(
+    const ConvolutionFilter1D::Fixed* filter_values,
+    int filter_length,
+    unsigned char* const* source_data_rows,
+    int pixel_width,
+    unsigned char* out_row,
+    bool has_alpha);
+typedef void (*Convolve4RowsHorizontally_pointer)(
+    const unsigned char* src_data[4],
+    const ConvolutionFilter1D& filter,
+    unsigned char* out_row[4]);
+typedef void (*ConvolveHorizontally_pointer)(const unsigned char* src_data,
+                                             const ConvolutionFilter1D& filter,
+                                             unsigned char* out_row,
+                                             bool has_alpha);
+
+struct ConvolveProcs {
+  // This is how many extra pixels may be read by the
+  // conolve*horizontally functions.
+  int extra_horizontal_reads;
+  ConvolveVertically_pointer convolve_vertically;
+  Convolve4RowsHorizontally_pointer convolve_4rows_horizontally;
+  ConvolveHorizontally_pointer convolve_horizontally;
+};
+
+void SetupSIMD(ConvolveProcs* procs) {
+#ifdef SIMD_SSE2
+  procs->extra_horizontal_reads = 3;
+  procs->convolve_vertically = &ConvolveVertically_SSE2;
+  procs->convolve_4rows_horizontally = &Convolve4RowsHorizontally_SSE2;
+  procs->convolve_horizontally = &ConvolveHorizontally_SSE2;
+#elif defined SIMD_MIPS_DSPR2
+  procs->extra_horizontal_reads = 3;
+  procs->convolve_vertically = &ConvolveVertically_mips_dspr2;
+  procs->convolve_horizontally = &ConvolveHorizontally_mips_dspr2;
+#endif
+}
+
+void BGRAConvolve2D(const unsigned char* source_data,
+                    int source_byte_row_stride,
+                    bool source_has_alpha,
+                    const ConvolutionFilter1D& filter_x,
+                    const ConvolutionFilter1D& filter_y,
+                    int output_byte_row_stride,
+                    unsigned char* output,
+                    bool use_simd_if_possible) {
+  ConvolveProcs simd;
+  simd.extra_horizontal_reads = 0;
+  simd.convolve_vertically = NULL;
+  simd.convolve_4rows_horizontally = NULL;
+  simd.convolve_horizontally = NULL;
+  if (use_simd_if_possible) {
+    SetupSIMD(&simd);
+  }
+
+  int max_y_filter_size = filter_y.max_filter();
+
+  // The next row in the input that we will generate a horizontally
+  // convolved row for. If the filter doesn't start at the beginning of the
+  // image (this is the case when we are only resizing a subset), then we
+  // don't want to generate any output rows before that. Compute the starting
+  // row for convolution as the first pixel for the first vertical filter.
+  int filter_offset, filter_length;
+  const ConvolutionFilter1D::Fixed* filter_values =
+      filter_y.FilterForValue(0, &filter_offset, &filter_length);
+  int next_x_row = filter_offset;
+
+  // We loop over each row in the input doing a horizontal convolution. This
+  // will result in a horizontally convolved image. We write the results into
+  // a circular buffer of convolved rows and do vertical convolution as rows
+  // are available. This prevents us from having to store the entire
+  // intermediate image and helps cache coherency.
+  // We will need four extra rows to allow horizontal convolution could be done
+  // simultaneously. We also padding each row in row buffer to be aligned-up to
+  // 16 bytes.
+  // TODO(jiesun): We do not use aligned load from row buffer in vertical
+  // convolution pass yet. Somehow Windows does not like it.
+  int row_buffer_width = (filter_x.num_values() + 15) & ~0xF;
+  int row_buffer_height =
+      max_y_filter_size + (simd.convolve_4rows_horizontally ? 4 : 0);
+  CircularRowBuffer row_buffer(row_buffer_width, row_buffer_height,
+                               filter_offset);
+
+  // Loop over every possible output row, processing just enough horizontal
+  // convolutions to run each subsequent vertical convolution.
+  SkASSERT(output_byte_row_stride >= filter_x.num_values() * 4);
+  int num_output_rows = filter_y.num_values();
+
+  // We need to check which is the last line to convolve before we advance 4
+  // lines in one iteration.
+  int last_filter_offset, last_filter_length;
+
+  // SSE2 can access up to 3 extra pixels past the end of the
+  // buffer. At the bottom of the image, we have to be careful
+  // not to access data past the end of the buffer. Normally
+  // we fall back to the C++ implementation for the last row.
+  // If the last row is less than 3 pixels wide, we may have to fall
+  // back to the C++ version for more rows. Compute how many
+  // rows we need to avoid the SSE implementation for here.
+  filter_x.FilterForValue(filter_x.num_values() - 1, &last_filter_offset,
+                          &last_filter_length);
+  int avoid_simd_rows =
+      1 +
+      simd.extra_horizontal_reads / (last_filter_offset + last_filter_length);
+
+  filter_y.FilterForValue(num_output_rows - 1, &last_filter_offset,
+                          &last_filter_length);
+
+  for (int out_y = 0; out_y < num_output_rows; out_y++) {
+    filter_values =
+        filter_y.FilterForValue(out_y, &filter_offset, &filter_length);
+
+    // Generate output rows until we have enough to run the current filter.
+    while (next_x_row < filter_offset + filter_length) {
+      if (simd.convolve_4rows_horizontally &&
+          next_x_row + 3 <
+              last_filter_offset + last_filter_length - avoid_simd_rows) {
+        const unsigned char* src[4];
+        unsigned char* out_row[4];
+        for (int i = 0; i < 4; ++i) {
+          src[i] = &source_data[(next_x_row + i) * source_byte_row_stride];
+          out_row[i] = row_buffer.AdvanceRow();
+        }
+        simd.convolve_4rows_horizontally(src, filter_x, out_row);
+        next_x_row += 4;
+      } else {
+        // Check if we need to avoid SSE2 for this row.
+        if (simd.convolve_horizontally &&
+            next_x_row <
+                last_filter_offset + last_filter_length - avoid_simd_rows) {
+          simd.convolve_horizontally(
+              &source_data[next_x_row * source_byte_row_stride], filter_x,
+              row_buffer.AdvanceRow(), source_has_alpha);
+        } else {
+          if (source_has_alpha) {
+            ConvolveHorizontally<true>(
+                &source_data[next_x_row * source_byte_row_stride], filter_x,
+                row_buffer.AdvanceRow());
+          } else {
+            ConvolveHorizontally<false>(
+                &source_data[next_x_row * source_byte_row_stride], filter_x,
+                row_buffer.AdvanceRow());
+          }
+        }
+        next_x_row++;
+      }
+    }
+
+    // Compute where in the output image this row of final data will go.
+    unsigned char* cur_output_row = &output[out_y * output_byte_row_stride];
+
+    // Get the list of rows that the circular buffer has, in order.
+    int first_row_in_circular_buffer;
+    unsigned char* const* rows_to_convolve =
+        row_buffer.GetRowAddresses(&first_row_in_circular_buffer);
+
+    // Now compute the start of the subset of those rows that the filter
+    // needs.
+    unsigned char* const* first_row_for_filter =
+        &rows_to_convolve[filter_offset - first_row_in_circular_buffer];
+
+    if (simd.convolve_vertically) {
+      simd.convolve_vertically(filter_values, filter_length,
+                               first_row_for_filter, filter_x.num_values(),
+                               cur_output_row, source_has_alpha);
+    } else {
+      ConvolveVertically(filter_values, filter_length, first_row_for_filter,
+                         filter_x.num_values(), cur_output_row,
+                         source_has_alpha);
+    }
+  }
+}
+
+void SingleChannelConvolveX1D(const unsigned char* source_data,
+                              int source_byte_row_stride,
+                              int input_channel_index,
+                              int input_channel_count,
+                              const ConvolutionFilter1D& filter,
+                              const SkISize& image_size,
+                              unsigned char* output,
+                              int output_byte_row_stride,
+                              int output_channel_index,
+                              int output_channel_count,
+                              bool absolute_values) {
+  int filter_offset, filter_length, filter_size;
+  // Very much unlike BGRAConvolve2D, here we expect to have the same filter
+  // for all pixels.
+  const ConvolutionFilter1D::Fixed* filter_values =
+      filter.GetSingleFilter(&filter_size, &filter_offset, &filter_length);
+
+  if (filter_values == NULL || image_size.width() < filter_size) {
+    NOTREACHED();
+    return;
+  }
+
+  int centrepoint = filter_length / 2;
+  if (filter_size - filter_offset != 2 * filter_offset) {
+    // This means the original filter was not symmetrical AND
+    // got clipped from one side more than from the other.
+    centrepoint = filter_size / 2 - filter_offset;
+  }
+
+  const unsigned char* source_data_row = source_data;
+  unsigned char* output_row = output;
+
+  for (int r = 0; r < image_size.height(); ++r) {
+    unsigned char* target_byte = output_row + output_channel_index;
+    // Process the lead part, padding image to the left with the first pixel.
+    int c = 0;
+    for (; c < centrepoint; ++c, target_byte += output_channel_count) {
+      int accval = 0;
+      int i = 0;
+      int pixel_byte_index = input_channel_index;
+      for (; i < centrepoint - c; ++i)  // Padding part.
+        accval += filter_values[i] * source_data_row[pixel_byte_index];
+
+      for (; i < filter_length; ++i, pixel_byte_index += input_channel_count)
+        accval += filter_values[i] * source_data_row[pixel_byte_index];
+
+      *target_byte = BringBackTo8(accval, absolute_values);
+    }
+
+    // Now for the main event.
+    for (; c < image_size.width() - centrepoint;
+         ++c, target_byte += output_channel_count) {
+      int accval = 0;
+      int pixel_byte_index =
+          (c - centrepoint) * input_channel_count + input_channel_index;
+
+      for (int i = 0; i < filter_length;
+           ++i, pixel_byte_index += input_channel_count) {
+        accval += filter_values[i] * source_data_row[pixel_byte_index];
+      }
+
+      *target_byte = BringBackTo8(accval, absolute_values);
+    }
+
+    for (; c < image_size.width(); ++c, target_byte += output_channel_count) {
+      int accval = 0;
+      int overlap_taps = image_size.width() - c + centrepoint;
+      int pixel_byte_index =
+          (c - centrepoint) * input_channel_count + input_channel_index;
+      int i = 0;
+      for (; i < overlap_taps - 1; ++i, pixel_byte_index += input_channel_count)
+        accval += filter_values[i] * source_data_row[pixel_byte_index];
+
+      for (; i < filter_length; ++i)
+        accval += filter_values[i] * source_data_row[pixel_byte_index];
+
+      *target_byte = BringBackTo8(accval, absolute_values);
+    }
+
+    source_data_row += source_byte_row_stride;
+    output_row += output_byte_row_stride;
+  }
+}
+
+void SingleChannelConvolveY1D(const unsigned char* source_data,
+                              int source_byte_row_stride,
+                              int input_channel_index,
+                              int input_channel_count,
+                              const ConvolutionFilter1D& filter,
+                              const SkISize& image_size,
+                              unsigned char* output,
+                              int output_byte_row_stride,
+                              int output_channel_index,
+                              int output_channel_count,
+                              bool absolute_values) {
+  int filter_offset, filter_length, filter_size;
+  // Very much unlike BGRAConvolve2D, here we expect to have the same filter
+  // for all pixels.
+  const ConvolutionFilter1D::Fixed* filter_values =
+      filter.GetSingleFilter(&filter_size, &filter_offset, &filter_length);
+
+  if (filter_values == NULL || image_size.height() < filter_size) {
+    NOTREACHED();
+    return;
+  }
+
+  int centrepoint = filter_length / 2;
+  if (filter_size - filter_offset != 2 * filter_offset) {
+    // This means the original filter was not symmetrical AND
+    // got clipped from one side more than from the other.
+    centrepoint = filter_size / 2 - filter_offset;
+  }
+
+  for (int c = 0; c < image_size.width(); ++c) {
+    unsigned char* target_byte =
+        output + c * output_channel_count + output_channel_index;
+    int r = 0;
+
+    for (; r < centrepoint; ++r, target_byte += output_byte_row_stride) {
+      int accval = 0;
+      int i = 0;
+      int pixel_byte_index = c * input_channel_count + input_channel_index;
+
+      for (; i < centrepoint - r; ++i)  // Padding part.
+        accval += filter_values[i] * source_data[pixel_byte_index];
+
+      for (; i < filter_length; ++i, pixel_byte_index += source_byte_row_stride)
+        accval += filter_values[i] * source_data[pixel_byte_index];
+
+      *target_byte = BringBackTo8(accval, absolute_values);
+    }
+
+    for (; r < image_size.height() - centrepoint;
+         ++r, target_byte += output_byte_row_stride) {
+      int accval = 0;
+      int pixel_byte_index = (r - centrepoint) * source_byte_row_stride +
+                             c * input_channel_count + input_channel_index;
+      for (int i = 0; i < filter_length;
+           ++i, pixel_byte_index += source_byte_row_stride) {
+        accval += filter_values[i] * source_data[pixel_byte_index];
+      }
+
+      *target_byte = BringBackTo8(accval, absolute_values);
+    }
+
+    for (; r < image_size.height();
+         ++r, target_byte += output_byte_row_stride) {
+      int accval = 0;
+      int overlap_taps = image_size.height() - r + centrepoint;
+      int pixel_byte_index = (r - centrepoint) * source_byte_row_stride +
+                             c * input_channel_count + input_channel_index;
+      int i = 0;
+      for (; i < overlap_taps - 1;
+           ++i, pixel_byte_index += source_byte_row_stride) {
+        accval += filter_values[i] * source_data[pixel_byte_index];
+      }
+
+      for (; i < filter_length; ++i)
+        accval += filter_values[i] * source_data[pixel_byte_index];
+
+      *target_byte = BringBackTo8(accval, absolute_values);
+    }
+  }
+}
+
+void SetUpGaussianConvolutionKernel(ConvolutionFilter1D* filter,
+                                    float kernel_sigma,
+                                    bool derivative) {
+  DCHECK(filter != NULL);
+  DCHECK_GT(kernel_sigma, 0.0);
+  const int tail_length = static_cast<int>(4.0f * kernel_sigma + 0.5f);
+  const int kernel_size = tail_length * 2 + 1;
+  const float sigmasq = kernel_sigma * kernel_sigma;
+  std::vector<float> kernel_weights(kernel_size, 0.0);
+  float kernel_sum = 1.0f;
+
+  kernel_weights[tail_length] = 1.0f;
+
+  for (int ii = 1; ii <= tail_length; ++ii) {
+    float v = std::exp(-0.5f * ii * ii / sigmasq);
+    kernel_weights[tail_length + ii] = v;
+    kernel_weights[tail_length - ii] = v;
+    kernel_sum += 2.0f * v;
+  }
+
+  for (int i = 0; i < kernel_size; ++i)
+    kernel_weights[i] /= kernel_sum;
+
+  if (derivative) {
+    kernel_weights[tail_length] = 0.0;
+    for (int ii = 1; ii <= tail_length; ++ii) {
+      float v = sigmasq * kernel_weights[tail_length + ii] / ii;
+      kernel_weights[tail_length + ii] = v;
+      kernel_weights[tail_length - ii] = -v;
+    }
+  }
+
+  filter->AddFilter(0, &kernel_weights[0], kernel_weights.size());
+}
+
+}  // namespace skia
diff --git a/skia/ext/convolver.h b/skia/ext/convolver.h
new file mode 100644
index 0000000..37349ae
--- /dev/null
+++ b/skia/ext/convolver.h
@@ -0,0 +1,235 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SKIA_EXT_CONVOLVER_H_
+#define SKIA_EXT_CONVOLVER_H_
+
+#include <cmath>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "third_party/skia/include/core/SkSize.h"
+#include "third_party/skia/include/core/SkTypes.h"
+
+// We can build SSE2 optimized versions for all x86 CPUs
+// except when building for the IOS emulator.
+#if defined(ARCH_CPU_X86_FAMILY) && !defined(OS_IOS)
+#define SIMD_SSE2 1
+#define SIMD_PADDING 8  // 8 * int16
+#endif
+
+#if defined(ARCH_CPU_MIPS_FAMILY) && defined(__mips_dsp) && \
+    (__mips_dsp_rev >= 2)
+#define SIMD_MIPS_DSPR2 1
+#endif
+// avoid confusion with Mac OS X's math library (Carbon)
+#if defined(__APPLE__)
+#undef FloatToFixed
+#undef FixedToFloat
+#endif
+
+namespace skia {
+
+// Represents a filter in one dimension. Each output pixel has one entry in this
+// object for the filter values contributing to it. You build up the filter
+// list by calling AddFilter for each output pixel (in order).
+//
+// We do 2-dimensional convolution by first convolving each row by one
+// ConvolutionFilter1D, then convolving each column by another one.
+//
+// Entries are stored in fixed point, shifted left by kShiftBits.
+class ConvolutionFilter1D {
+ public:
+  typedef short Fixed;
+
+  // The number of bits that fixed point values are shifted by.
+  enum { kShiftBits = 14 };
+
+  SK_API ConvolutionFilter1D();
+  SK_API ~ConvolutionFilter1D();
+
+  // Convert between floating point and our fixed point representation.
+  static Fixed FloatToFixed(float f) {
+    return static_cast<Fixed>(f * (1 << kShiftBits));
+  }
+  static unsigned char FixedToChar(Fixed x) {
+    return static_cast<unsigned char>(x >> kShiftBits);
+  }
+  static float FixedToFloat(Fixed x) {
+    // The cast relies on Fixed being a short, implying that on
+    // the platforms we care about all (16) bits will fit into
+    // the mantissa of a (32-bit) float.
+    static_assert(sizeof(Fixed) == 2,
+                  "fixed type should fit in float mantissa");
+    float raw = static_cast<float>(x);
+    return ldexpf(raw, -kShiftBits);
+  }
+
+  // Returns the maximum pixel span of a filter.
+  int max_filter() const { return max_filter_; }
+
+  // Returns the number of filters in this filter. This is the dimension of the
+  // output image.
+  int num_values() const { return static_cast<int>(filters_.size()); }
+
+  // Appends the given list of scaling values for generating a given output
+  // pixel. |filter_offset| is the distance from the edge of the image to where
+  // the scaling factors start. The scaling factors apply to the source pixels
+  // starting from this position, and going for the next |filter_length| pixels.
+  //
+  // You will probably want to make sure your input is normalized (that is,
+  // all entries in |filter_values| sub to one) to prevent affecting the overall
+  // brighness of the image.
+  //
+  // The filter_length must be > 0.
+  //
+  // This version will automatically convert your input to fixed point.
+  SK_API void AddFilter(int filter_offset,
+                        const float* filter_values,
+                        int filter_length);
+
+  // Same as the above version, but the input is already fixed point.
+  void AddFilter(int filter_offset,
+                 const Fixed* filter_values,
+                 int filter_length);
+
+  // Retrieves a filter for the given |value_offset|, a position in the output
+  // image in the direction we're convolving. The offset and length of the
+  // filter values are put into the corresponding out arguments (see AddFilter
+  // above for what these mean), and a pointer to the first scaling factor is
+  // returned. There will be |filter_length| values in this array.
+  inline const Fixed* FilterForValue(int value_offset,
+                                     int* filter_offset,
+                                     int* filter_length) const {
+    const FilterInstance& filter = filters_[value_offset];
+    *filter_offset = filter.offset;
+    *filter_length = filter.trimmed_length;
+    if (filter.trimmed_length == 0) {
+      return NULL;
+    }
+    return &filter_values_[filter.data_location];
+  }
+
+  // Retrieves the filter for the offset 0, presumed to be the one and only.
+  // The offset and length of the filter values are put into the corresponding
+  // out arguments (see AddFilter). Note that |filter_legth| and
+  // |specified_filter_length| may be different if leading/trailing zeros of the
+  // original floating point form were clipped.
+  // There will be |filter_length| values in the return array.
+  // Returns NULL if the filter is 0-length (for instance when all floating
+  // point values passed to AddFilter were clipped to 0).
+  SK_API const Fixed* GetSingleFilter(int* specified_filter_length,
+                                      int* filter_offset,
+                                      int* filter_length) const;
+
+  inline void PaddingForSIMD() {
+// Padding |padding_count| of more dummy coefficients after the coefficients
+// of last filter to prevent SIMD instructions which load 8 or 16 bytes
+// together to access invalid memory areas. We are not trying to align the
+// coefficients right now due to the opaqueness of <vector> implementation.
+// This has to be done after all |AddFilter| calls.
+#ifdef SIMD_PADDING
+    for (int i = 0; i < SIMD_PADDING; ++i)
+      filter_values_.push_back(static_cast<Fixed>(0));
+#endif
+  }
+
+ private:
+  struct FilterInstance {
+    // Offset within filter_values for this instance of the filter.
+    int data_location;
+
+    // Distance from the left of the filter to the center. IN PIXELS
+    int offset;
+
+    // Number of values in this filter instance.
+    int trimmed_length;
+
+    // Filter length as specified. Note that this may be different from
+    // 'trimmed_length' if leading/trailing zeros of the original floating
+    // point form were clipped differently on each tail.
+    int length;
+  };
+
+  // Stores the information for each filter added to this class.
+  std::vector<FilterInstance> filters_;
+
+  // We store all the filter values in this flat list, indexed by
+  // |FilterInstance.data_location| to avoid the mallocs required for storing
+  // each one separately.
+  std::vector<Fixed> filter_values_;
+
+  // The maximum size of any filter we've added.
+  int max_filter_;
+};
+
+// Does a two-dimensional convolution on the given source image.
+//
+// It is assumed the source pixel offsets referenced in the input filters
+// reference only valid pixels, so the source image size is not required. Each
+// row of the source image starts |source_byte_row_stride| after the previous
+// one (this allows you to have rows with some padding at the end).
+//
+// The result will be put into the given output buffer. The destination image
+// size will be xfilter.num_values() * yfilter.num_values() pixels. It will be
+// in rows of exactly xfilter.num_values() * 4 bytes.
+//
+// |source_has_alpha| is a hint that allows us to avoid doing computations on
+// the alpha channel if the image is opaque. If you don't know, set this to
+// true and it will work properly, but setting this to false will be a few
+// percent faster if you know the image is opaque.
+//
+// The layout in memory is assumed to be 4-bytes per pixel in B-G-R-A order
+// (this is ARGB when loaded into 32-bit words on a little-endian machine).
+SK_API void BGRAConvolve2D(const unsigned char* source_data,
+                           int source_byte_row_stride,
+                           bool source_has_alpha,
+                           const ConvolutionFilter1D& xfilter,
+                           const ConvolutionFilter1D& yfilter,
+                           int output_byte_row_stride,
+                           unsigned char* output,
+                           bool use_simd_if_possible);
+
+// Does a 1D convolution of the given source image along the X dimension on
+// a single channel of the bitmap.
+//
+// The function uses the same convolution kernel for each pixel. That kernel
+// must be added to |filter| at offset 0. This is a most straightforward
+// implementation of convolution, intended chiefly for development purposes.
+SK_API void SingleChannelConvolveX1D(const unsigned char* source_data,
+                                     int source_byte_row_stride,
+                                     int input_channel_index,
+                                     int input_channel_count,
+                                     const ConvolutionFilter1D& filter,
+                                     const SkISize& image_size,
+                                     unsigned char* output,
+                                     int output_byte_row_stride,
+                                     int output_channel_index,
+                                     int output_channel_count,
+                                     bool absolute_values);
+
+// Does a 1D convolution of the given source image along the Y dimension on
+// a single channel of the bitmap.
+SK_API void SingleChannelConvolveY1D(const unsigned char* source_data,
+                                     int source_byte_row_stride,
+                                     int input_channel_index,
+                                     int input_channel_count,
+                                     const ConvolutionFilter1D& filter,
+                                     const SkISize& image_size,
+                                     unsigned char* output,
+                                     int output_byte_row_stride,
+                                     int output_channel_index,
+                                     int output_channel_count,
+                                     bool absolute_values);
+
+// Set up the |filter| instance with a gaussian kernel. |kernel_sigma| is the
+// parameter of gaussian. If |derivative| is true, the kernel will be that of
+// the first derivative. Intended for use with the two routines above.
+SK_API void SetUpGaussianConvolutionKernel(ConvolutionFilter1D* filter,
+                                           float kernel_sigma,
+                                           bool derivative);
+
+}  // namespace skia
+
+#endif  // SKIA_EXT_CONVOLVER_H_
diff --git a/skia/ext/convolver_SSE2.cc b/skia/ext/convolver_SSE2.cc
new file mode 100644
index 0000000..ae1bfb8
--- /dev/null
+++ b/skia/ext/convolver_SSE2.cc
@@ -0,0 +1,448 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+
+#include "skia/ext/convolver.h"
+#include "skia/ext/convolver_SSE2.h"
+#include "third_party/skia/include/core/SkTypes.h"
+
+#include <emmintrin.h>  // ARCH_CPU_X86_FAMILY was defined in build/config.h
+
+namespace skia {
+
+// Convolves horizontally along a single row. The row data is given in
+// |src_data| and continues for the num_values() of the filter.
+void ConvolveHorizontally_SSE2(const unsigned char* src_data,
+                               const ConvolutionFilter1D& filter,
+                               unsigned char* out_row,
+                               bool /*has_alpha*/) {
+  int num_values = filter.num_values();
+
+  int filter_offset, filter_length;
+  __m128i zero = _mm_setzero_si128();
+  __m128i mask[4];
+  // |mask| will be used to decimate all extra filter coefficients that are
+  // loaded by SIMD when |filter_length| is not divisible by 4.
+  // mask[0] is not used in following algorithm.
+  mask[1] = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, -1);
+  mask[2] = _mm_set_epi16(0, 0, 0, 0, 0, 0, -1, -1);
+  mask[3] = _mm_set_epi16(0, 0, 0, 0, 0, -1, -1, -1);
+
+  // Output one pixel each iteration, calculating all channels (RGBA) together.
+  for (int out_x = 0; out_x < num_values; out_x++) {
+    const ConvolutionFilter1D::Fixed* filter_values =
+        filter.FilterForValue(out_x, &filter_offset, &filter_length);
+
+    __m128i accum = _mm_setzero_si128();
+
+    // Compute the first pixel in this row that the filter affects. It will
+    // touch |filter_length| pixels (4 bytes each) after this.
+    const __m128i* row_to_filter =
+        reinterpret_cast<const __m128i*>(&src_data[filter_offset << 2]);
+
+    // We will load and accumulate with four coefficients per iteration.
+    for (int filter_x = 0; filter_x<filter_length>> 2; filter_x++) {
+      // Load 4 coefficients => duplicate 1st and 2nd of them for all channels.
+      __m128i coeff, coeff16;
+      // [16] xx xx xx xx c3 c2 c1 c0
+      coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
+      // [16] xx xx xx xx c1 c1 c0 c0
+      coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
+      // [16] c1 c1 c1 c1 c0 c0 c0 c0
+      coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
+
+      // Load four pixels => unpack the first two pixels to 16 bits =>
+      // multiply with coefficients => accumulate the convolution result.
+      // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
+      __m128i src8 = _mm_loadu_si128(row_to_filter);
+      // [16] a1 b1 g1 r1 a0 b0 g0 r0
+      __m128i src16 = _mm_unpacklo_epi8(src8, zero);
+      __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
+      __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
+      // [32]  a0*c0 b0*c0 g0*c0 r0*c0
+      __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+      accum = _mm_add_epi32(accum, t);
+      // [32]  a1*c1 b1*c1 g1*c1 r1*c1
+      t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+      accum = _mm_add_epi32(accum, t);
+
+      // Duplicate 3rd and 4th coefficients for all channels =>
+      // unpack the 3rd and 4th pixels to 16 bits => multiply with coefficients
+      // => accumulate the convolution results.
+      // [16] xx xx xx xx c3 c3 c2 c2
+      coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
+      // [16] c3 c3 c3 c3 c2 c2 c2 c2
+      coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
+      // [16] a3 g3 b3 r3 a2 g2 b2 r2
+      src16 = _mm_unpackhi_epi8(src8, zero);
+      mul_hi = _mm_mulhi_epi16(src16, coeff16);
+      mul_lo = _mm_mullo_epi16(src16, coeff16);
+      // [32]  a2*c2 b2*c2 g2*c2 r2*c2
+      t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+      accum = _mm_add_epi32(accum, t);
+      // [32]  a3*c3 b3*c3 g3*c3 r3*c3
+      t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+      accum = _mm_add_epi32(accum, t);
+
+      // Advance the pixel and coefficients pointers.
+      row_to_filter += 1;
+      filter_values += 4;
+    }
+
+    // When |filter_length| is not divisible by 4, we need to decimate some of
+    // the filter coefficient that was loaded incorrectly to zero; Other than
+    // that the algorithm is same with above, exceot that the 4th pixel will be
+    // always absent.
+    int r = filter_length & 3;
+    if (r) {
+      // Note: filter_values must be padded to align_up(filter_offset, 8).
+      __m128i coeff, coeff16;
+      coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
+      // Mask out extra filter taps.
+      coeff = _mm_and_si128(coeff, mask[r]);
+      coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
+      coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
+
+      // Note: line buffer must be padded to align_up(filter_offset, 16).
+      // We resolve this by use C-version for the last horizontal line.
+      __m128i src8 = _mm_loadu_si128(row_to_filter);
+      __m128i src16 = _mm_unpacklo_epi8(src8, zero);
+      __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
+      __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
+      __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+      accum = _mm_add_epi32(accum, t);
+      t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+      accum = _mm_add_epi32(accum, t);
+
+      src16 = _mm_unpackhi_epi8(src8, zero);
+      coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
+      coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
+      mul_hi = _mm_mulhi_epi16(src16, coeff16);
+      mul_lo = _mm_mullo_epi16(src16, coeff16);
+      t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+      accum = _mm_add_epi32(accum, t);
+    }
+
+    // Shift right for fixed point implementation.
+    accum = _mm_srai_epi32(accum, ConvolutionFilter1D::kShiftBits);
+
+    // Packing 32 bits |accum| to 16 bits per channel (signed saturation).
+    accum = _mm_packs_epi32(accum, zero);
+    // Packing 16 bits |accum| to 8 bits per channel (unsigned saturation).
+    accum = _mm_packus_epi16(accum, zero);
+
+    // Store the pixel value of 32 bits.
+    *(reinterpret_cast<int*>(out_row)) = _mm_cvtsi128_si32(accum);
+    out_row += 4;
+  }
+}
+
+// Convolves horizontally along four rows. The row data is given in
+// |src_data| and continues for the num_values() of the filter.
+// The algorithm is almost same as |ConvolveHorizontally_SSE2|. Please
+// refer to that function for detailed comments.
+void Convolve4RowsHorizontally_SSE2(const unsigned char* src_data[4],
+                                    const ConvolutionFilter1D& filter,
+                                    unsigned char* out_row[4]) {
+  int num_values = filter.num_values();
+
+  int filter_offset, filter_length;
+  __m128i zero = _mm_setzero_si128();
+  __m128i mask[4];
+  // |mask| will be used to decimate all extra filter coefficients that are
+  // loaded by SIMD when |filter_length| is not divisible by 4.
+  // mask[0] is not used in following algorithm.
+  mask[1] = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, -1);
+  mask[2] = _mm_set_epi16(0, 0, 0, 0, 0, 0, -1, -1);
+  mask[3] = _mm_set_epi16(0, 0, 0, 0, 0, -1, -1, -1);
+
+  // Output one pixel each iteration, calculating all channels (RGBA) together.
+  for (int out_x = 0; out_x < num_values; out_x++) {
+    const ConvolutionFilter1D::Fixed* filter_values =
+        filter.FilterForValue(out_x, &filter_offset, &filter_length);
+
+    // four pixels in a column per iteration.
+    __m128i accum0 = _mm_setzero_si128();
+    __m128i accum1 = _mm_setzero_si128();
+    __m128i accum2 = _mm_setzero_si128();
+    __m128i accum3 = _mm_setzero_si128();
+    int start = (filter_offset << 2);
+    // We will load and accumulate with four coefficients per iteration.
+    for (int filter_x = 0; filter_x < (filter_length >> 2); filter_x++) {
+      __m128i coeff, coeff16lo, coeff16hi;
+      // [16] xx xx xx xx c3 c2 c1 c0
+      coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
+      // [16] xx xx xx xx c1 c1 c0 c0
+      coeff16lo = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
+      // [16] c1 c1 c1 c1 c0 c0 c0 c0
+      coeff16lo = _mm_unpacklo_epi16(coeff16lo, coeff16lo);
+      // [16] xx xx xx xx c3 c3 c2 c2
+      coeff16hi = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
+      // [16] c3 c3 c3 c3 c2 c2 c2 c2
+      coeff16hi = _mm_unpacklo_epi16(coeff16hi, coeff16hi);
+
+      __m128i src8, src16, mul_hi, mul_lo, t;
+
+#define ITERATION(src, accum)                                    \
+  src8 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(src)); \
+  src16 = _mm_unpacklo_epi8(src8, zero);                         \
+  mul_hi = _mm_mulhi_epi16(src16, coeff16lo);                    \
+  mul_lo = _mm_mullo_epi16(src16, coeff16lo);                    \
+  t = _mm_unpacklo_epi16(mul_lo, mul_hi);                        \
+  accum = _mm_add_epi32(accum, t);                               \
+  t = _mm_unpackhi_epi16(mul_lo, mul_hi);                        \
+  accum = _mm_add_epi32(accum, t);                               \
+  src16 = _mm_unpackhi_epi8(src8, zero);                         \
+  mul_hi = _mm_mulhi_epi16(src16, coeff16hi);                    \
+  mul_lo = _mm_mullo_epi16(src16, coeff16hi);                    \
+  t = _mm_unpacklo_epi16(mul_lo, mul_hi);                        \
+  accum = _mm_add_epi32(accum, t);                               \
+  t = _mm_unpackhi_epi16(mul_lo, mul_hi);                        \
+  accum = _mm_add_epi32(accum, t)
+
+      ITERATION(src_data[0] + start, accum0);
+      ITERATION(src_data[1] + start, accum1);
+      ITERATION(src_data[2] + start, accum2);
+      ITERATION(src_data[3] + start, accum3);
+
+      start += 16;
+      filter_values += 4;
+    }
+
+    int r = filter_length & 3;
+    if (r) {
+      // Note: filter_values must be padded to align_up(filter_offset, 8);
+      __m128i coeff;
+      coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
+      // Mask out extra filter taps.
+      coeff = _mm_and_si128(coeff, mask[r]);
+
+      __m128i coeff16lo = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
+      /* c1 c1 c1 c1 c0 c0 c0 c0 */
+      coeff16lo = _mm_unpacklo_epi16(coeff16lo, coeff16lo);
+      __m128i coeff16hi = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
+      coeff16hi = _mm_unpacklo_epi16(coeff16hi, coeff16hi);
+
+      __m128i src8, src16, mul_hi, mul_lo, t;
+
+      ITERATION(src_data[0] + start, accum0);
+      ITERATION(src_data[1] + start, accum1);
+      ITERATION(src_data[2] + start, accum2);
+      ITERATION(src_data[3] + start, accum3);
+    }
+
+    accum0 = _mm_srai_epi32(accum0, ConvolutionFilter1D::kShiftBits);
+    accum0 = _mm_packs_epi32(accum0, zero);
+    accum0 = _mm_packus_epi16(accum0, zero);
+    accum1 = _mm_srai_epi32(accum1, ConvolutionFilter1D::kShiftBits);
+    accum1 = _mm_packs_epi32(accum1, zero);
+    accum1 = _mm_packus_epi16(accum1, zero);
+    accum2 = _mm_srai_epi32(accum2, ConvolutionFilter1D::kShiftBits);
+    accum2 = _mm_packs_epi32(accum2, zero);
+    accum2 = _mm_packus_epi16(accum2, zero);
+    accum3 = _mm_srai_epi32(accum3, ConvolutionFilter1D::kShiftBits);
+    accum3 = _mm_packs_epi32(accum3, zero);
+    accum3 = _mm_packus_epi16(accum3, zero);
+
+    *(reinterpret_cast<int*>(out_row[0])) = _mm_cvtsi128_si32(accum0);
+    *(reinterpret_cast<int*>(out_row[1])) = _mm_cvtsi128_si32(accum1);
+    *(reinterpret_cast<int*>(out_row[2])) = _mm_cvtsi128_si32(accum2);
+    *(reinterpret_cast<int*>(out_row[3])) = _mm_cvtsi128_si32(accum3);
+
+    out_row[0] += 4;
+    out_row[1] += 4;
+    out_row[2] += 4;
+    out_row[3] += 4;
+  }
+}
+
+// Does vertical convolution to produce one output row. The filter values and
+// length are given in the first two parameters. These are applied to each
+// of the rows pointed to in the |source_data_rows| array, with each row
+// being |pixel_width| wide.
+//
+// The output must have room for |pixel_width * 4| bytes.
+template <bool has_alpha>
+void ConvolveVertically_SSE2(const ConvolutionFilter1D::Fixed* filter_values,
+                             int filter_length,
+                             unsigned char* const* source_data_rows,
+                             int pixel_width,
+                             unsigned char* out_row) {
+  int width = pixel_width & ~3;
+
+  __m128i zero = _mm_setzero_si128();
+  __m128i accum0, accum1, accum2, accum3, coeff16;
+  const __m128i* src;
+  // Output four pixels per iteration (16 bytes).
+  for (int out_x = 0; out_x < width; out_x += 4) {
+    // Accumulated result for each pixel. 32 bits per RGBA channel.
+    accum0 = _mm_setzero_si128();
+    accum1 = _mm_setzero_si128();
+    accum2 = _mm_setzero_si128();
+    accum3 = _mm_setzero_si128();
+
+    // Convolve with one filter coefficient per iteration.
+    for (int filter_y = 0; filter_y < filter_length; filter_y++) {
+      // Duplicate the filter coefficient 8 times.
+      // [16] cj cj cj cj cj cj cj cj
+      coeff16 = _mm_set1_epi16(filter_values[filter_y]);
+
+      // Load four pixels (16 bytes) together.
+      // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
+      src = reinterpret_cast<const __m128i*>(
+          &source_data_rows[filter_y][out_x << 2]);
+      __m128i src8 = _mm_loadu_si128(src);
+
+      // Unpack 1st and 2nd pixels from 8 bits to 16 bits for each channels =>
+      // multiply with current coefficient => accumulate the result.
+      // [16] a1 b1 g1 r1 a0 b0 g0 r0
+      __m128i src16 = _mm_unpacklo_epi8(src8, zero);
+      __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
+      __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
+      // [32] a0 b0 g0 r0
+      __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+      accum0 = _mm_add_epi32(accum0, t);
+      // [32] a1 b1 g1 r1
+      t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+      accum1 = _mm_add_epi32(accum1, t);
+
+      // Unpack 3rd and 4th pixels from 8 bits to 16 bits for each channels =>
+      // multiply with current coefficient => accumulate the result.
+      // [16] a3 b3 g3 r3 a2 b2 g2 r2
+      src16 = _mm_unpackhi_epi8(src8, zero);
+      mul_hi = _mm_mulhi_epi16(src16, coeff16);
+      mul_lo = _mm_mullo_epi16(src16, coeff16);
+      // [32] a2 b2 g2 r2
+      t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+      accum2 = _mm_add_epi32(accum2, t);
+      // [32] a3 b3 g3 r3
+      t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+      accum3 = _mm_add_epi32(accum3, t);
+    }
+
+    // Shift right for fixed point implementation.
+    accum0 = _mm_srai_epi32(accum0, ConvolutionFilter1D::kShiftBits);
+    accum1 = _mm_srai_epi32(accum1, ConvolutionFilter1D::kShiftBits);
+    accum2 = _mm_srai_epi32(accum2, ConvolutionFilter1D::kShiftBits);
+    accum3 = _mm_srai_epi32(accum3, ConvolutionFilter1D::kShiftBits);
+
+    // Packing 32 bits |accum| to 16 bits per channel (signed saturation).
+    // [16] a1 b1 g1 r1 a0 b0 g0 r0
+    accum0 = _mm_packs_epi32(accum0, accum1);
+    // [16] a3 b3 g3 r3 a2 b2 g2 r2
+    accum2 = _mm_packs_epi32(accum2, accum3);
+
+    // Packing 16 bits |accum| to 8 bits per channel (unsigned saturation).
+    // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
+    accum0 = _mm_packus_epi16(accum0, accum2);
+
+    if (has_alpha) {
+      // Compute the max(ri, gi, bi) for each pixel.
+      // [8] xx a3 b3 g3 xx a2 b2 g2 xx a1 b1 g1 xx a0 b0 g0
+      __m128i a = _mm_srli_epi32(accum0, 8);
+      // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
+      __m128i b = _mm_max_epu8(a, accum0);  // Max of r and g.
+      // [8] xx xx a3 b3 xx xx a2 b2 xx xx a1 b1 xx xx a0 b0
+      a = _mm_srli_epi32(accum0, 16);
+      // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
+      b = _mm_max_epu8(a, b);  // Max of r and g and b.
+      // [8] max3 00 00 00 max2 00 00 00 max1 00 00 00 max0 00 00 00
+      b = _mm_slli_epi32(b, 24);
+
+      // Make sure the value of alpha channel is always larger than maximum
+      // value of color channels.
+      accum0 = _mm_max_epu8(b, accum0);
+    } else {
+      // Set value of alpha channels to 0xFF.
+      __m128i mask = _mm_set1_epi32(0xff000000);
+      accum0 = _mm_or_si128(accum0, mask);
+    }
+
+    // Store the convolution result (16 bytes) and advance the pixel pointers.
+    _mm_storeu_si128(reinterpret_cast<__m128i*>(out_row), accum0);
+    out_row += 16;
+  }
+
+  // When the width of the output is not divisible by 4, We need to save one
+  // pixel (4 bytes) each time. And also the fourth pixel is always absent.
+  if (pixel_width & 3) {
+    accum0 = _mm_setzero_si128();
+    accum1 = _mm_setzero_si128();
+    accum2 = _mm_setzero_si128();
+    for (int filter_y = 0; filter_y < filter_length; ++filter_y) {
+      coeff16 = _mm_set1_epi16(filter_values[filter_y]);
+      // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
+      src = reinterpret_cast<const __m128i*>(
+          &source_data_rows[filter_y][width << 2]);
+      __m128i src8 = _mm_loadu_si128(src);
+      // [16] a1 b1 g1 r1 a0 b0 g0 r0
+      __m128i src16 = _mm_unpacklo_epi8(src8, zero);
+      __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
+      __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
+      // [32] a0 b0 g0 r0
+      __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+      accum0 = _mm_add_epi32(accum0, t);
+      // [32] a1 b1 g1 r1
+      t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+      accum1 = _mm_add_epi32(accum1, t);
+      // [16] a3 b3 g3 r3 a2 b2 g2 r2
+      src16 = _mm_unpackhi_epi8(src8, zero);
+      mul_hi = _mm_mulhi_epi16(src16, coeff16);
+      mul_lo = _mm_mullo_epi16(src16, coeff16);
+      // [32] a2 b2 g2 r2
+      t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+      accum2 = _mm_add_epi32(accum2, t);
+    }
+
+    accum0 = _mm_srai_epi32(accum0, ConvolutionFilter1D::kShiftBits);
+    accum1 = _mm_srai_epi32(accum1, ConvolutionFilter1D::kShiftBits);
+    accum2 = _mm_srai_epi32(accum2, ConvolutionFilter1D::kShiftBits);
+    // [16] a1 b1 g1 r1 a0 b0 g0 r0
+    accum0 = _mm_packs_epi32(accum0, accum1);
+    // [16] a3 b3 g3 r3 a2 b2 g2 r2
+    accum2 = _mm_packs_epi32(accum2, zero);
+    // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
+    accum0 = _mm_packus_epi16(accum0, accum2);
+    if (has_alpha) {
+      // [8] xx a3 b3 g3 xx a2 b2 g2 xx a1 b1 g1 xx a0 b0 g0
+      __m128i a = _mm_srli_epi32(accum0, 8);
+      // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
+      __m128i b = _mm_max_epu8(a, accum0);  // Max of r and g.
+      // [8] xx xx a3 b3 xx xx a2 b2 xx xx a1 b1 xx xx a0 b0
+      a = _mm_srli_epi32(accum0, 16);
+      // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
+      b = _mm_max_epu8(a, b);  // Max of r and g and b.
+      // [8] max3 00 00 00 max2 00 00 00 max1 00 00 00 max0 00 00 00
+      b = _mm_slli_epi32(b, 24);
+      accum0 = _mm_max_epu8(b, accum0);
+    } else {
+      __m128i mask = _mm_set1_epi32(0xff000000);
+      accum0 = _mm_or_si128(accum0, mask);
+    }
+
+    for (int out_x = width; out_x < pixel_width; out_x++) {
+      *(reinterpret_cast<int*>(out_row)) = _mm_cvtsi128_si32(accum0);
+      accum0 = _mm_srli_si128(accum0, 4);
+      out_row += 4;
+    }
+  }
+}
+
+void ConvolveVertically_SSE2(const ConvolutionFilter1D::Fixed* filter_values,
+                             int filter_length,
+                             unsigned char* const* source_data_rows,
+                             int pixel_width,
+                             unsigned char* out_row,
+                             bool has_alpha) {
+  if (has_alpha) {
+    ConvolveVertically_SSE2<true>(filter_values, filter_length,
+                                  source_data_rows, pixel_width, out_row);
+  } else {
+    ConvolveVertically_SSE2<false>(filter_values, filter_length,
+                                   source_data_rows, pixel_width, out_row);
+  }
+}
+
+}  // namespace skia
diff --git a/skia/ext/convolver_SSE2.h b/skia/ext/convolver_SSE2.h
new file mode 100644
index 0000000..cf60406
--- /dev/null
+++ b/skia/ext/convolver_SSE2.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SKIA_EXT_CONVOLVER_SSE2_H_
+#define SKIA_EXT_CONVOLVER_SSE2_H_
+
+#include "skia/ext/convolver.h"
+
+namespace skia {
+
+void ConvolveVertically_SSE2(const ConvolutionFilter1D::Fixed* filter_values,
+                             int filter_length,
+                             unsigned char* const* source_data_rows,
+                             int pixel_width,
+                             unsigned char* out_row,
+                             bool has_alpha);
+void Convolve4RowsHorizontally_SSE2(const unsigned char* src_data[4],
+                                    const ConvolutionFilter1D& filter,
+                                    unsigned char* out_row[4]);
+void ConvolveHorizontally_SSE2(const unsigned char* src_data,
+                               const ConvolutionFilter1D& filter,
+                               unsigned char* out_row,
+                               bool has_alpha);
+}  // namespace skia
+
+#endif  // SKIA_EXT_CONVOLVER_SSE2_H_
diff --git a/skia/ext/convolver_mips_dspr2.cc b/skia/ext/convolver_mips_dspr2.cc
new file mode 100644
index 0000000..f1a9912
--- /dev/null
+++ b/skia/ext/convolver_mips_dspr2.cc
@@ -0,0 +1,516 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+#include "skia/ext/convolver.h"
+#include "skia/ext/convolver_mips_dspr2.h"
+#include "third_party/skia/include/core/SkTypes.h"
+
+namespace skia {
+// Convolves horizontally along a single row. The row data is given in
+// |src_data| and continues for the num_values() of the filter.
+void ConvolveHorizontally_mips_dspr2(const unsigned char* src_data,
+                                     const ConvolutionFilter1D& filter,
+                                     unsigned char* out_row,
+                                     bool has_alpha) {
+#if SIMD_MIPS_DSPR2
+  int row_to_filter = 0;
+  int num_values = filter.num_values();
+  if (has_alpha) {
+    for (int out_x = 0; out_x < num_values; out_x++) {
+      // Get the filter that determines the current output pixel.
+      int filter_offset, filter_length;
+      const ConvolutionFilter1D::Fixed* filter_values =
+          filter.FilterForValue(out_x, &filter_offset, &filter_length);
+      int filter_x = 0;
+
+      __asm__ __volatile__(
+          ".set push                                  \n"
+          ".set noreorder                             \n"
+
+          "beqz            %[filter_len], 3f          \n"
+          " sll            $t0, %[filter_offset], 2   \n"
+          "addu            %[rtf], %[src_data], $t0   \n"
+          "mtlo            $0, $ac0                   \n"
+          "mtlo            $0, $ac1                   \n"
+          "mtlo            $0, $ac2                   \n"
+          "mtlo            $0, $ac3                   \n"
+          "srl             $t7, %[filter_len], 2      \n"
+          "beqz            $t7, 2f                    \n"
+          " li             %[fx], 0                   \n"
+
+          "11:                                        \n"
+          "addu            $t4, %[filter_val], %[fx]  \n"
+          "sll             $t5, %[fx], 1              \n"
+          "ulw             $t6, 0($t4)                \n"  // t6 =
+                                                           // |cur[1]|cur[0]|
+          "ulw             $t8, 4($t4)                \n"  // t8 =
+                                                           // |cur[3]|cur[2]|
+          "addu            $t0, %[rtf], $t5           \n"
+          "lw              $t1, 0($t0)                \n"  // t1 = |a0|b0|g0|r0|
+          "lw              $t2, 4($t0)                \n"  // t2 = |a1|b1|g1|r1|
+          "lw              $t3, 8($t0)                \n"  // t3 = |a2|b2|g2|r2|
+          "lw              $t4, 12($t0)               \n"  // t4 = |a3|b3|g3|r3|
+          "precrq.qb.ph    $t0, $t2, $t1              \n"  // t0 = |a1|g1|a0|g0|
+          "precr.qb.ph     $t5, $t2, $t1              \n"  // t5 = |b1|r1|b0|r0|
+          "preceu.ph.qbla  $t1, $t0                   \n"  // t1 = |0|a1|0|a0|
+          "preceu.ph.qbra  $t2, $t0                   \n"  // t2 = |0|g1|0|g0|
+          "preceu.ph.qbla  $t0, $t5                   \n"  // t0 = |0|b1|0|b0|
+          "preceu.ph.qbra  $t5, $t5                   \n"  // t5 = |0|r1|0|r0|
+          "dpa.w.ph        $ac0, $t1, $t6             \n"  // ac0+(cur*a1)+(cur*a0)
+          "dpa.w.ph        $ac1, $t0, $t6             \n"  // ac1+(cur*b1)+(cur*b0)
+          "dpa.w.ph        $ac2, $t2, $t6             \n"  // ac2+(cur*g1)+(cur*g0)
+          "dpa.w.ph        $ac3, $t5, $t6             \n"  // ac3+(cur*r1)+(cur*r0)
+          "precrq.qb.ph    $t0, $t4, $t3              \n"  // t0 = |a3|g3|a2|g2|
+          "precr.qb.ph     $t5, $t4, $t3              \n"  // t5 = |b3|r3|b2|r2|
+          "preceu.ph.qbla  $t1, $t0                   \n"  // t1 = |0|a3|0|a2|
+          "preceu.ph.qbra  $t2, $t0                   \n"  // t2 = |0|g3|0|g2|
+          "preceu.ph.qbla  $t0, $t5                   \n"  // t0 = |0|b3|0|b2|
+          "preceu.ph.qbra  $t5, $t5                   \n"  // t5 = |0|r3|0|r2|
+          "dpa.w.ph        $ac0, $t1, $t8             \n"  // ac0+(cur*a3)+(cur*a2)
+          "dpa.w.ph        $ac1, $t0, $t8             \n"  // ac1+(cur*b3)+(cur*b2)
+          "dpa.w.ph        $ac2, $t2, $t8             \n"  // ac2+(cur*g3)+(cur*g2)
+          "dpa.w.ph        $ac3, $t5, $t8             \n"  // ac3+(cur*r3)+(cur*r2)
+          "addiu           $t7, $t7, -1               \n"
+          "bgtz            $t7, 11b                   \n"
+          " addiu          %[fx], %[fx], 8            \n"
+
+          "2:                                         \n"
+          "andi            $t7, %[filter_len], 0x3    \n"  // residual
+          "beqz            $t7, 3f                    \n"
+          " nop                                       \n"
+
+          "21:                                        \n"
+          "sll             $t1, %[fx], 1              \n"
+          "addu            $t2, %[filter_val], %[fx]  \n"
+          "addu            $t0, %[rtf], $t1           \n"
+          "lh              $t6, 0($t2)                \n"  // t6 =
+                                                           // filter_val[fx]
+          "lbu             $t1, 0($t0)                \n"  // t1 = row[fx * 4 +
+                                                           // 0]
+          "lbu             $t2, 1($t0)                \n"  // t2 = row[fx * 4 +
+                                                           // 1]
+          "lbu             $t3, 2($t0)                \n"  // t3 = row[fx * 4 +
+                                                           // 2]
+          "lbu             $t4, 3($t0)                \n"  // t4 = row[fx * 4 +
+                                                           // 2]
+          "maddu           $ac3, $t6, $t1             \n"
+          "maddu           $ac2, $t6, $t2             \n"
+          "maddu           $ac1, $t6, $t3             \n"
+          "maddu           $ac0, $t6, $t4             \n"
+          "addiu           $t7, $t7, -1               \n"
+          "bgtz            $t7, 21b                   \n"
+          " addiu          %[fx], %[fx], 2            \n"
+
+          "3:                                         \n"
+          "extrv.w         $t0, $ac0, %[kShiftBits]   \n"  // a >> kShiftBits
+          "extrv.w         $t1, $ac1, %[kShiftBits]   \n"  // b >> kShiftBits
+          "extrv.w         $t2, $ac2, %[kShiftBits]   \n"  // g >> kShiftBits
+          "extrv.w         $t3, $ac3, %[kShiftBits]   \n"  // r >> kShiftBits
+          "sll             $t5, %[out_x], 2           \n"
+          "repl.ph         $t6, 128                   \n"  // t6 = | 128 | 128 |
+          "addu            $t5, %[out_row], $t5       \n"
+          "append          $t2, $t3, 16               \n"
+          "append          $t0, $t1, 16               \n"
+          "subu.ph         $t1, $t0, $t6              \n"
+          "shll_s.ph       $t1, $t1, 8                \n"
+          "shra.ph         $t1, $t1, 8                \n"
+          "addu.ph         $t1, $t1, $t6              \n"
+          "subu.ph         $t3, $t2, $t6              \n"
+          "shll_s.ph       $t3, $t3, 8                \n"
+          "shra.ph         $t3, $t3, 8                \n"
+          "addu.ph         $t3, $t3, $t6              \n"
+          "precr.qb.ph     $t0, $t1, $t3              \n"
+          "usw             $t0, 0($t5)                \n"
+
+          ".set pop                                   \n"
+          : [fx] "+r"(filter_x), [out_x] "+r"(out_x), [out_row] "+r"(out_row),
+            [rtf] "+r"(row_to_filter)
+          : [filter_val] "r"(filter_values), [filter_len] "r"(filter_length),
+            [kShiftBits] "r"(ConvolutionFilter1D::kShiftBits),
+            [filter_offset] "r"(filter_offset), [src_data] "r"(src_data)
+          : "lo", "hi", "$ac1lo", "$ac1hi", "$ac2lo", "$ac2hi", "$ac3lo",
+            "$ac3hi", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8");
+    }
+  } else {
+    for (int out_x = 0; out_x < num_values; out_x++) {
+      // Get the filter that determines the current output pixel.
+      int filter_offset, filter_length;
+      const ConvolutionFilter1D::Fixed* filter_values =
+          filter.FilterForValue(out_x, &filter_offset, &filter_length);
+      int filter_x = 0;
+      __asm__ __volatile__(
+          ".set push                                  \n"
+          ".set noreorder                             \n"
+
+          "beqz            %[filter_len], 3f          \n"
+          " sll            $t0, %[filter_offset], 2   \n"
+          "addu            %[rtf], %[src_data], $t0   \n"
+          "mtlo            $0, $ac1                   \n"
+          "mtlo            $0, $ac2                   \n"
+          "mtlo            $0, $ac3                   \n"
+          "srl             $t7, %[filter_len], 2      \n"
+          "beqz            $t7, 2f                    \n"
+          " li             %[fx], 0                   \n"
+
+          "11:                                        \n"
+          "addu            $t4, %[filter_val], %[fx]  \n"
+          "sll             $t5, %[fx], 1              \n"
+          "ulw             $t6, 0($t4)                \n"  // t6 =
+                                                           // |cur[1]|cur[0]|
+          "ulw             $t8, 4($t4)                \n"  // t8 =
+                                                           // |cur[3]|cur[2]|
+          "addu            $t0, %[rtf], $t5           \n"
+          "lw              $t1, 0($t0)                \n"  // t1 = |a0|b0|g0|r0|
+          "lw              $t2, 4($t0)                \n"  // t2 = |a1|b1|g1|r1|
+          "lw              $t3, 8($t0)                \n"  // t3 = |a2|b2|g2|r2|
+          "lw              $t4, 12($t0)               \n"  // t4 = |a3|b3|g3|r3|
+          "precrq.qb.ph    $t0, $t2, $t1              \n"  // t0 = |a1|g1|a0|g0|
+          "precr.qb.ph     $t5, $t2, $t1              \n"  // t5 = |b1|r1|b0|r0|
+          "preceu.ph.qbra  $t2, $t0                   \n"  // t2 = |0|g1|0|g0|
+          "preceu.ph.qbla  $t0, $t5                   \n"  // t0 = |0|b1|0|b0|
+          "preceu.ph.qbra  $t5, $t5                   \n"  // t5 = |0|r1|0|r0|
+          "dpa.w.ph        $ac1, $t0, $t6             \n"  // ac1+(cur*b1)+(cur*b0)
+          "dpa.w.ph        $ac2, $t2, $t6             \n"  // ac2+(cur*g1)+(cur*g0)
+          "dpa.w.ph        $ac3, $t5, $t6             \n"  // ac3+(cur*r1)+(cur*r0)
+          "precrq.qb.ph    $t0, $t4, $t3              \n"  // t0 = |a3|g3|a2|g2|
+          "precr.qb.ph     $t5, $t4, $t3              \n"  // t5 = |b3|r3|b2|r2|
+          "preceu.ph.qbra  $t2, $t0                   \n"  // t2 = |0|g3|0|g2|
+          "preceu.ph.qbla  $t0, $t5                   \n"  // t0 = |0|b3|0|b2|
+          "preceu.ph.qbra  $t5, $t5                   \n"  // t5 = |0|r3|0|r2|
+          "dpa.w.ph        $ac1, $t0, $t8             \n"  // ac1+(cur*b3)+(cur*b2)
+          "dpa.w.ph        $ac2, $t2, $t8             \n"  // ac2+(cur*g3)+(cur*g2)
+          "dpa.w.ph        $ac3, $t5, $t8             \n"  // ac3+(cur*r3)+(cur*r2)
+          "addiu           $t7, $t7, -1               \n"
+          "bgtz            $t7, 11b                   \n"
+          " addiu          %[fx], %[fx], 8            \n"
+
+          "2:                                         \n"
+          "andi            $t7, %[filter_len], 0x3    \n"  // residual
+          "beqz            $t7, 3f                    \n"
+          " nop                                       \n"
+
+          "21:                                        \n"
+          "sll             $t1, %[fx], 1              \n"
+          "addu            $t2, %[filter_val], %[fx]  \n"
+          "addu            $t0, %[rtf], $t1           \n"
+          "lh              $t6, 0($t2)                \n"  // t6 =
+                                                           // filter_val[fx]
+          "lbu             $t1, 0($t0)                \n"  // t1 = row[fx * 4 +
+                                                           // 0]
+          "lbu             $t2, 1($t0)                \n"  // t2 = row[fx * 4 +
+                                                           // 1]
+          "lbu             $t3, 2($t0)                \n"  // t3 = row[fx * 4 +
+                                                           // 2]
+          "maddu           $ac3, $t6, $t1             \n"
+          "maddu           $ac2, $t6, $t2             \n"
+          "maddu           $ac1, $t6, $t3             \n"
+          "addiu           $t7, $t7, -1               \n"
+          "bgtz            $t7, 21b                   \n"
+          " addiu          %[fx], %[fx], 2            \n"
+
+          "3:                                         \n"
+          "extrv.w         $t1, $ac1, %[kShiftBits]   \n"  // b >> kShiftBits
+          "extrv.w         $t2, $ac2, %[kShiftBits]   \n"  // g >> kShiftBits
+          "extrv.w         $t3, $ac3, %[kShiftBits]   \n"  // r >> kShiftBits
+          "repl.ph         $t6, 128                   \n"  // t6 = | 128 | 128 |
+          "sll             $t8, %[out_x], 2           \n"
+          "addu            $t8, %[out_row], $t8       \n"
+          "append          $t2, $t3, 16               \n"
+          "andi            $t1, 0xFFFF                \n"
+          "subu.ph         $t5, $t1, $t6              \n"
+          "shll_s.ph       $t5, $t5, 8                \n"
+          "shra.ph         $t5, $t5, 8                \n"
+          "addu.ph         $t5, $t5, $t6              \n"
+          "subu.ph         $t4, $t2, $t6              \n"
+          "shll_s.ph       $t4, $t4, 8                \n"
+          "shra.ph         $t4, $t4, 8                \n"
+          "addu.ph         $t4, $t4, $t6              \n"
+          "precr.qb.ph     $t0, $t5, $t4              \n"
+          "usw             $t0, 0($t8)                \n"
+
+          ".set pop                                   \n"
+          : [fx] "+r"(filter_x), [out_x] "+r"(out_x), [out_row] "+r"(out_row),
+            [rtf] "+r"(row_to_filter)
+          : [filter_val] "r"(filter_values), [filter_len] "r"(filter_length),
+            [kShiftBits] "r"(ConvolutionFilter1D::kShiftBits),
+            [filter_offset] "r"(filter_offset), [src_data] "r"(src_data)
+          : "lo", "hi", "$ac1lo", "$ac1hi", "$ac2lo", "$ac2hi", "$ac3lo",
+            "$ac3hi", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8");
+    }
+  }
+#endif
+}
+void ConvolveVertically_mips_dspr2(const ConvolutionFilter1D::Fixed* filter_val,
+                                   int filter_length,
+                                   unsigned char* const* source_data_rows,
+                                   int pixel_width,
+                                   unsigned char* out_row,
+                                   bool has_alpha) {
+#if SIMD_MIPS_DSPR2
+  // We go through each column in the output and do a vertical convolution,
+  // generating one output pixel each time.
+  int byte_offset;
+  int cnt;
+  int filter_y;
+  if (has_alpha) {
+    for (int out_x = 0; out_x < pixel_width; out_x++) {
+      __asm__ __volatile__(
+          ".set push                                   \n"
+          ".set noreorder                              \n"
+
+          "beqz            %[filter_len], 3f           \n"
+          " sll            %[offset], %[out_x], 2      \n"
+          "mtlo            $0, $ac0                    \n"
+          "mtlo            $0, $ac1                    \n"
+          "mtlo            $0, $ac2                    \n"
+          "mtlo            $0, $ac3                    \n"
+          "srl             %[cnt], %[filter_len], 2    \n"
+          "beqz            %[cnt], 2f                  \n"
+          " li             %[fy], 0                    \n"
+
+          "11:                                         \n"
+          "sll             $t1, %[fy], 1               \n"
+          "addu            $t0, %[src_data_rows], $t1  \n"
+          "lw              $t1, 0($t0)                 \n"
+          "lw              $t2, 4($t0)                 \n"
+          "lw              $t3, 8($t0)                 \n"
+          "lw              $t4, 12($t0)                \n"
+          "addu            $t1, $t1, %[offset]         \n"
+          "addu            $t2, $t2, %[offset]         \n"
+          "addu            $t3, $t3, %[offset]         \n"
+          "addu            $t4, $t4, %[offset]         \n"
+          "lw              $t1, 0($t1)                 \n"  // t1 =
+                                                            // |a0|b0|g0|r0|
+          "lw              $t2, 0($t2)                 \n"  // t2 =
+                                                            // |a1|b1|g1|r1|
+          "lw              $t3, 0($t3)                 \n"  // t3 =
+                                                            // |a0|b0|g0|r0|
+          "lw              $t4, 0($t4)                 \n"  // t4 =
+                                                            // |a1|b1|g1|r1|
+          "precrq.qb.ph    $t5, $t2, $t1               \n"  // t5 =
+                                                            // |a1|g1|a0|g0|
+          "precr.qb.ph     $t6, $t2, $t1               \n"  // t6 =
+                                                            // |b1|r1|b0|r0|
+          "preceu.ph.qbla  $t0, $t5                    \n"  // t0 = |0|a1|0|a0|
+          "preceu.ph.qbra  $t1, $t5                    \n"  // t1 = |0|g1|0|g0|
+          "preceu.ph.qbla  $t2, $t6                    \n"  // t2 = |0|b1|0|b0|
+          "preceu.ph.qbra  $t5, $t6                    \n"  // t5 = |0|r1|0|r0|
+          "addu            $t6, %[filter_val], %[fy]   \n"
+          "ulw             $t7, 0($t6)                 \n"  // t7 =
+                                                            // |cur_1|cur_0|
+          "ulw             $t6, 4($t6)                 \n"  // t6 =
+                                                            // |cur_3|cur_2|
+          "dpa.w.ph        $ac0, $t5, $t7              \n"  // (cur*r1)+(cur*r0)
+          "dpa.w.ph        $ac1, $t1, $t7              \n"  // (cur*g1)+(cur*g0)
+          "dpa.w.ph        $ac2, $t2, $t7              \n"  // (cur*b1)+(cur*b0)
+          "dpa.w.ph        $ac3, $t0, $t7              \n"  // (cur*a1)+(cur*a0)
+          "precrq.qb.ph    $t5, $t4, $t3               \n"  // t5 =
+                                                            // |a3|g3|a2|g2|
+          "precr.qb.ph     $t7, $t4, $t3               \n"  // t7 =
+                                                            // |b3|r3|b2|r2|
+          "preceu.ph.qbla  $t0, $t5                    \n"  // t0 = |0|a3|0|a2|
+          "preceu.ph.qbra  $t1, $t5                    \n"  // t1 = |0|g3|0|g2|
+          "preceu.ph.qbla  $t2, $t7                    \n"  // t2 = |0|b3|0|b2|
+          "preceu.ph.qbra  $t5, $t7                    \n"  // t5 = |0|r3|0|r2|
+          "dpa.w.ph        $ac0, $t5, $t6              \n"  // (cur*r3)+(cur*r2)
+          "dpa.w.ph        $ac1, $t1, $t6              \n"  // (cur*g3)+(cur*g2)
+          "dpa.w.ph        $ac2, $t2, $t6              \n"  // (cur*b3)+(cur*b2)
+          "dpa.w.ph        $ac3, $t0, $t6              \n"  // (cur*a3)+(cur*a2)
+          "addiu           %[cnt], %[cnt], -1          \n"
+          "bgtz            %[cnt], 11b                 \n"
+          " addiu          %[fy], %[fy], 8             \n"
+
+          "2:                                          \n"
+          "andi            %[cnt], %[filter_len], 0x3  \n"  // residual
+          "beqz            %[cnt], 3f                  \n"
+          " nop                                        \n"
+
+          "21:                                         \n"
+          "addu            $t0, %[filter_val], %[fy]   \n"
+          "lh              $t4, 0($t0)                 \n"  // t4=filter_val[fx]
+          "sll             $t1, %[fy], 1               \n"
+          "addu            $t0, %[src_data_rows], $t1  \n"
+          "lw              $t1, 0($t0)                 \n"
+          "addu            $t0, $t1, %[offset]         \n"
+          "lbu             $t1, 0($t0)                 \n"  // t1 = row[fx*4 +
+                                                            // 0]
+          "lbu             $t2, 1($t0)                 \n"  // t2 = row[fx*4 +
+                                                            // 1]
+          "lbu             $t3, 2($t0)                 \n"  // t3 = row[fx*4 +
+                                                            // 2]
+          "lbu             $t0, 3($t0)                 \n"  // t4 = row[fx*4 +
+                                                            // 2]
+          "maddu           $ac0, $t4, $t1              \n"
+          "maddu           $ac1, $t4, $t2              \n"
+          "maddu           $ac2, $t4, $t3              \n"
+          "maddu           $ac3, $t4, $t0              \n"
+          "addiu           %[cnt], %[cnt], -1          \n"
+          "bgtz            %[cnt], 21b                 \n"
+          " addiu          %[fy], %[fy], 2             \n"
+
+          "3:                                          \n"
+          "extrv.w         $t3, $ac0, %[kShiftBits]    \n"  // a >> kShiftBits
+          "extrv.w         $t2, $ac1, %[kShiftBits]    \n"  // b >> kShiftBits
+          "extrv.w         $t1, $ac2, %[kShiftBits]    \n"  // g >> kShiftBits
+          "extrv.w         $t0, $ac3, %[kShiftBits]    \n"  // r >> kShiftBits
+          "repl.ph         $t4, 128                    \n"  // t4 = | 128 | 128
+                                                            // |
+          "addu            $t5, %[out_row], %[offset]  \n"
+          "append          $t2, $t3, 16                \n"  // t2 = |0|g|0|r|
+          "append          $t0, $t1, 16                \n"  // t0 = |0|a|0|b|
+          "subu.ph         $t1, $t0, $t4               \n"
+          "shll_s.ph       $t1, $t1, 8                 \n"
+          "shra.ph         $t1, $t1, 8                 \n"
+          "addu.ph         $t1, $t1, $t4               \n"  // Clamp(a)|Clamp(b)
+          "subu.ph         $t2, $t2, $t4               \n"
+          "shll_s.ph       $t2, $t2, 8                 \n"
+          "shra.ph         $t2, $t2, 8                 \n"
+          "addu.ph         $t2, $t2, $t4               \n"  // Clamp(g)|Clamp(r)
+          "andi            $t3, $t1, 0xFF              \n"  // t3 = ClampTo8(b)
+          "cmp.lt.ph       $t3, $t2                    \n"  // cmp b, g, r
+          "pick.ph         $t0, $t2, $t3               \n"
+          "andi            $t3, $t0, 0xFF              \n"
+          "srl             $t4, $t0, 16                \n"
+          "cmp.lt.ph       $t3, $t4                    \n"
+          "pick.ph         $t0, $t4, $t3               \n"  // t0 = max_color_ch
+          "srl             $t3, $t1, 16                \n"  // t1 = ClampTo8(a)
+          "cmp.lt.ph       $t3, $t0                    \n"
+          "pick.ph         $t0, $t0, $t3               \n"
+          "ins             $t1, $t0, 16, 8             \n"
+          "precr.qb.ph     $t0, $t1, $t2               \n"  // t0 = |a|b|g|r|
+          "usw             $t0, 0($t5)                 \n"
+
+          ".set pop                                    \n"
+          : [filter_val] "+r"(filter_val), [filter_len] "+r"(filter_length),
+            [offset] "+r"(byte_offset), [fy] "+r"(filter_y), [cnt] "+r"(cnt),
+            [out_x] "+r"(out_x), [pixel_width] "+r"(pixel_width)
+          : [src_data_rows] "r"(source_data_rows), [out_row] "r"(out_row),
+            [kShiftBits] "r"(ConvolutionFilter1D::kShiftBits)
+          : "lo", "hi", "$ac1lo", "$ac1hi", "$ac2lo", "$ac2hi", "$ac3lo",
+            "$ac3hi", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "memory");
+    }
+  } else {
+    for (int out_x = 0; out_x < pixel_width; out_x++) {
+      __asm__ __volatile__(
+          ".set push                                   \n"
+          ".set noreorder                              \n"
+
+          "beqz            %[filter_len], 3f           \n"
+          " sll            %[offset], %[out_x], 2      \n"
+          "mtlo            $0, $ac0                    \n"
+          "mtlo            $0, $ac1                    \n"
+          "mtlo            $0, $ac2                    \n"
+          "srl             %[cnt], %[filter_len], 2    \n"
+          "beqz            %[cnt], 2f                  \n"
+          " li             %[fy], 0                    \n"
+
+          "11:                                         \n"
+          "sll             $t1, %[fy], 1               \n"
+          "addu            $t0, %[src_data_rows], $t1  \n"
+          "lw              $t1, 0($t0)                 \n"
+          "lw              $t2, 4($t0)                 \n"
+          "lw              $t3, 8($t0)                 \n"
+          "lw              $t4, 12($t0)                \n"
+          "addu            $t1, $t1, %[offset]         \n"
+          "addu            $t2, $t2, %[offset]         \n"
+          "addu            $t3, $t3, %[offset]         \n"
+          "addu            $t4, $t4, %[offset]         \n"
+          "lw              $t1, 0($t1)                 \n"  // t1 =
+                                                            // |a0|b0|g0|r0|
+          "lw              $t2, 0($t2)                 \n"  // t2 =
+                                                            // |a1|b1|g1|r1|
+          "lw              $t3, 0($t3)                 \n"  // t3 =
+                                                            // |a0|b0|g0|r0|
+          "lw              $t4, 0($t4)                 \n"  // t4 =
+                                                            // |a1|b1|g1|r1|
+          "precrq.qb.ph    $t5, $t2, $t1               \n"  // t5 =
+                                                            // |a1|g1|a0|g0|
+          "precr.qb.ph     $t6, $t2, $t1               \n"  // t6 =
+                                                            // |b1|r1|b0|r0|
+          "preceu.ph.qbra  $t1, $t5                    \n"  // t1 = |0|g1|0|g0|
+          "preceu.ph.qbla  $t2, $t6                    \n"  // t2 = |0|b1|0|b0|
+          "preceu.ph.qbra  $t5, $t6                    \n"  // t5 = |0|r1|0|r0|
+          "addu            $t6, %[filter_val], %[fy]   \n"
+          "ulw             $t0, 0($t6)                 \n"  // t0 =
+                                                            // |cur_1|cur_0|
+          "ulw             $t6, 4($t6)                 \n"  // t6 =
+                                                            // |cur_1|cur_0|
+          "dpa.w.ph        $ac0, $t5, $t0              \n"  // (cur*r1)+(cur*r0)
+          "dpa.w.ph        $ac1, $t1, $t0              \n"  // (cur*g1)+(cur*g0)
+          "dpa.w.ph        $ac2, $t2, $t0              \n"  // (cur*b1)+(cur*b0)
+          "precrq.qb.ph    $t5, $t4, $t3               \n"  // t5 =
+                                                            // |a3|g3|a2|g2|
+          "precr.qb.ph     $t0, $t4, $t3               \n"  // t0 =
+                                                            // |b3|r3|b2|r2|
+          "preceu.ph.qbra  $t1, $t5                    \n"  // t1 = |0|g3|0|g2|
+          "preceu.ph.qbla  $t2, $t0                    \n"  // t2 = |0|b3|0|b2|
+          "preceu.ph.qbra  $t5, $t0                    \n"  // t5 = |0|r3|0|r2|
+          "dpa.w.ph        $ac0, $t5, $t6              \n"  // (cur*r1)+(cur*r0)
+          "dpa.w.ph        $ac1, $t1, $t6              \n"  // (cur*g1)+(cur*g0)
+          "dpa.w.ph        $ac2, $t2, $t6              \n"  // (cur*b1)+(cur*b0)
+          "addiu           %[cnt], %[cnt], -1          \n"
+          "bgtz            %[cnt], 11b                 \n"
+          " addiu          %[fy], %[fy], 8             \n"
+
+          "2:                                          \n"
+          "andi            %[cnt], %[filter_len], 0x3  \n"  // residual
+          "beqz            %[cnt], 3f                  \n"
+          " nop                                        \n"
+
+          "21:                                         \n"
+          "addu            $t0, %[filter_val], %[fy]   \n"
+          "lh              $t4, 0($t0)                 \n"  // filter_val[fx]
+          "sll             $t1, %[fy], 1               \n"
+          "addu            $t0, %[src_data_rows], $t1  \n"
+          "lw              $t1, 0($t0)                 \n"
+          "addu            $t0, $t1, %[offset]         \n"
+          "lbu             $t1, 0($t0)                 \n"  // t1 = row[fx*4 +
+                                                            // 0]
+          "lbu             $t2, 1($t0)                 \n"  // t2 = row[fx*4 +
+                                                            // 1]
+          "lbu             $t3, 2($t0)                 \n"  // t3 = row[fx*4 +
+                                                            // 2]
+          "maddu           $ac0, $t4, $t1              \n"
+          "maddu           $ac1, $t4, $t2              \n"
+          "maddu           $ac2, $t4, $t3              \n"
+          "addiu           %[cnt], %[cnt], -1          \n"
+          "bgtz            %[cnt], 21b                 \n"
+          " addiu          %[fy], %[fy], 2             \n"
+
+          "3:                                          \n"
+          "extrv.w         $t3, $ac0, %[kShiftBits]    \n"  // r >> kShiftBits
+          "extrv.w         $t2, $ac1, %[kShiftBits]    \n"  // g >> kShiftBits
+          "extrv.w         $t1, $ac2, %[kShiftBits]    \n"  // b >> kShiftBits
+          "repl.ph         $t6, 128                    \n"  // t6 = | 128 | 128
+                                                            // |
+          "addu            $t5, %[out_row], %[offset]  \n"
+          "append          $t2, $t3, 16                \n"  // t2 = |0|g|0|r|
+          "andi            $t1, $t1, 0xFFFF            \n"
+          "subu.ph         $t1, $t1, $t6               \n"
+          "shll_s.ph       $t1, $t1, 8                 \n"
+          "shra.ph         $t1, $t1, 8                 \n"
+          "addu.ph         $t1, $t1, $t6               \n"  // Clamp(a)|Clamp(b)
+          "subu.ph         $t2, $t2, $t6               \n"
+          "shll_s.ph       $t2, $t2, 8                 \n"
+          "shra.ph         $t2, $t2, 8                 \n"
+          "addu.ph         $t2, $t2, $t6               \n"  // Clamp(g)|Clamp(r)
+          "li              $t0, 0xFF                   \n"
+          "ins             $t1, $t0, 16, 8             \n"
+          "precr.qb.ph     $t0, $t1, $t2               \n"  // t0 = |a|b|g|r|
+          "usw             $t0, 0($t5)                 \n"
+
+          ".set pop                                    \n"
+          : [filter_val] "+r"(filter_val), [filter_len] "+r"(filter_length),
+            [offset] "+r"(byte_offset), [fy] "+r"(filter_y), [cnt] "+r"(cnt),
+            [out_x] "+r"(out_x), [pixel_width] "+r"(pixel_width)
+          : [src_data_rows] "r"(source_data_rows), [out_row] "r"(out_row),
+            [kShiftBits] "r"(ConvolutionFilter1D::kShiftBits)
+          : "lo", "hi", "$ac1lo", "$ac1hi", "$ac2lo", "$ac2hi", "$ac3lo",
+            "$ac3hi", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "memory");
+    }
+  }
+#endif
+}
+}  // namespace skia
diff --git a/skia/ext/convolver_mips_dspr2.h b/skia/ext/convolver_mips_dspr2.h
new file mode 100644
index 0000000..a5e59f9
--- /dev/null
+++ b/skia/ext/convolver_mips_dspr2.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SKIA_EXT_CONVOLVER_MIPS_DSPR2_H_
+#define SKIA_EXT_CONVOLVER_MIPS_DSPR2_H_
+
+#include "skia/ext/convolver.h"
+
+namespace skia {
+
+void ConvolveVertically_mips_dspr2(const ConvolutionFilter1D::Fixed* filter_val,
+                                   int filter_length,
+                                   unsigned char* const* source_data_rows,
+                                   int pixel_width,
+                                   unsigned char* out_row,
+                                   bool has_alpha);
+
+void ConvolveHorizontally_mips_dspr2(const unsigned char* src_data,
+                                     const ConvolutionFilter1D& filter,
+                                     unsigned char* out_row,
+                                     bool has_alpha);
+}  // namespace skia
+
+#endif  // SKIA_EXT_CONVOLVER_MIPS_DSPR2_H_
diff --git a/skia/ext/convolver_unittest.cc b/skia/ext/convolver_unittest.cc
new file mode 100644
index 0000000..5532f56
--- /dev/null
+++ b/skia/ext/convolver_unittest.cc
@@ -0,0 +1,530 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string.h>
+#include <time.h>
+#include <algorithm>
+#include <numeric>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/time/time.h"
+#include "skia/ext/convolver.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColorPriv.h"
+#include "third_party/skia/include/core/SkRect.h"
+#include "third_party/skia/include/core/SkTypes.h"
+
+namespace skia {
+
+namespace {
+
+// Fills the given filter with impulse functions for the range 0->num_entries.
+void FillImpulseFilter(int num_entries, ConvolutionFilter1D* filter) {
+  float one = 1.0f;
+  for (int i = 0; i < num_entries; i++)
+    filter->AddFilter(i, &one, 1);
+}
+
+// Filters the given input with the impulse function, and verifies that it
+// does not change.
+void TestImpulseConvolution(const unsigned char* data, int width, int height) {
+  int byte_count = width * height * 4;
+
+  ConvolutionFilter1D filter_x;
+  FillImpulseFilter(width, &filter_x);
+
+  ConvolutionFilter1D filter_y;
+  FillImpulseFilter(height, &filter_y);
+
+  std::vector<unsigned char> output;
+  output.resize(byte_count);
+  BGRAConvolve2D(data, width * 4, true, filter_x, filter_y,
+                 filter_x.num_values() * 4, &output[0], false);
+
+  // Output should exactly match input.
+  EXPECT_EQ(0, memcmp(data, &output[0], byte_count));
+}
+
+// Fills the destination filter with a box filter averaging every two pixels
+// to produce the output.
+void FillBoxFilter(int size, ConvolutionFilter1D* filter) {
+  const float box[2] = {0.5, 0.5};
+  for (int i = 0; i < size; i++)
+    filter->AddFilter(i * 2, box, 2);
+}
+
+}  // namespace
+
+// Tests that each pixel, when set and run through the impulse filter, does
+// not change.
+TEST(Convolver, Impulse) {
+  // We pick an "odd" size that is not likely to fit on any boundaries so that
+  // we can see if all the widths and paddings are handled properly.
+  int width = 15;
+  int height = 31;
+  int byte_count = width * height * 4;
+  std::vector<unsigned char> input;
+  input.resize(byte_count);
+
+  unsigned char* input_ptr = &input[0];
+  for (int y = 0; y < height; y++) {
+    for (int x = 0; x < width; x++) {
+      for (int channel = 0; channel < 3; channel++) {
+        memset(input_ptr, 0, byte_count);
+        input_ptr[(y * width + x) * 4 + channel] = 0xff;
+        // Always set the alpha channel or it will attempt to "fix" it for us.
+        input_ptr[(y * width + x) * 4 + 3] = 0xff;
+        TestImpulseConvolution(input_ptr, width, height);
+      }
+    }
+  }
+}
+
+// Tests that using a box filter to halve an image results in every square of 4
+// pixels in the original get averaged to a pixel in the output.
+TEST(Convolver, Halve) {
+  static const int kSize = 16;
+
+  int src_width = kSize;
+  int src_height = kSize;
+  int src_row_stride = src_width * 4;
+  int src_byte_count = src_row_stride * src_height;
+  std::vector<unsigned char> input;
+  input.resize(src_byte_count);
+
+  int dest_width = src_width / 2;
+  int dest_height = src_height / 2;
+  int dest_byte_count = dest_width * dest_height * 4;
+  std::vector<unsigned char> output;
+  output.resize(dest_byte_count);
+
+  // First fill the array with a bunch of random data.
+  srand(static_cast<unsigned>(time(NULL)));
+  for (int i = 0; i < src_byte_count; i++)
+    input[i] = rand() * 255 / RAND_MAX;
+
+  // Compute the filters.
+  ConvolutionFilter1D filter_x, filter_y;
+  FillBoxFilter(dest_width, &filter_x);
+  FillBoxFilter(dest_height, &filter_y);
+
+  // Do the convolution.
+  BGRAConvolve2D(&input[0], src_width, true, filter_x, filter_y,
+                 filter_x.num_values() * 4, &output[0], false);
+
+  // Compute the expected results and check, allowing for a small difference
+  // to account for rounding errors.
+  for (int y = 0; y < dest_height; y++) {
+    for (int x = 0; x < dest_width; x++) {
+      for (int channel = 0; channel < 4; channel++) {
+        int src_offset = (y * 2 * src_row_stride + x * 2 * 4) + channel;
+        int value = input[src_offset] +      // Top left source pixel.
+                    input[src_offset + 4] +  // Top right source pixel.
+                    input[src_offset + src_row_stride] +     // Lower left.
+                    input[src_offset + src_row_stride + 4];  // Lower right.
+        value /= 4;                                          // Average.
+        int difference = value - output[(y * dest_width + x) * 4 + channel];
+        EXPECT_TRUE(difference >= -1 || difference <= 1);
+      }
+    }
+  }
+}
+
+// Tests the optimization in Convolver1D::AddFilter that avoids storing
+// leading/trailing zeroes.
+TEST(Convolver, AddFilter) {
+  skia::ConvolutionFilter1D filter;
+
+  const skia::ConvolutionFilter1D::Fixed* values = NULL;
+  int filter_offset = 0;
+  int filter_length = 0;
+
+  // An all-zero filter is handled correctly, all factors ignored
+  static const float factors1[] = {0.0f, 0.0f, 0.0f};
+  filter.AddFilter(11, factors1, arraysize(factors1));
+  ASSERT_EQ(0, filter.max_filter());
+  ASSERT_EQ(1, filter.num_values());
+
+  values = filter.FilterForValue(0, &filter_offset, &filter_length);
+  ASSERT_TRUE(values == NULL);   // No values => NULL.
+  ASSERT_EQ(11, filter_offset);  // Same as input offset.
+  ASSERT_EQ(0, filter_length);   // But no factors since all are zeroes.
+
+  // Zeroes on the left are ignored
+  static const float factors2[] = {0.0f, 1.0f, 1.0f, 1.0f, 1.0f};
+  filter.AddFilter(22, factors2, arraysize(factors2));
+  ASSERT_EQ(4, filter.max_filter());
+  ASSERT_EQ(2, filter.num_values());
+
+  values = filter.FilterForValue(1, &filter_offset, &filter_length);
+  ASSERT_TRUE(values != NULL);
+  ASSERT_EQ(23, filter_offset);  // 22 plus 1 leading zero
+  ASSERT_EQ(4, filter_length);   // 5 - 1 leading zero
+
+  // Zeroes on the right are ignored
+  static const float factors3[] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f};
+  filter.AddFilter(33, factors3, arraysize(factors3));
+  ASSERT_EQ(5, filter.max_filter());
+  ASSERT_EQ(3, filter.num_values());
+
+  values = filter.FilterForValue(2, &filter_offset, &filter_length);
+  ASSERT_TRUE(values != NULL);
+  ASSERT_EQ(33, filter_offset);  // 33, same as input due to no leading zero
+  ASSERT_EQ(5, filter_length);   // 7 - 2 trailing zeroes
+
+  // Zeroes in leading & trailing positions
+  static const float factors4[] = {0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f};
+  filter.AddFilter(44, factors4, arraysize(factors4));
+  ASSERT_EQ(5, filter.max_filter());  // No change from existing value.
+  ASSERT_EQ(4, filter.num_values());
+
+  values = filter.FilterForValue(3, &filter_offset, &filter_length);
+  ASSERT_TRUE(values != NULL);
+  ASSERT_EQ(46, filter_offset);  // 44 plus 2 leading zeroes
+  ASSERT_EQ(3, filter_length);   // 7 - (2 leading + 2 trailing) zeroes
+
+  // Zeroes surrounded by non-zero values are ignored
+  static const float factors5[] = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+                                   0.0f, 0.0f, 1.0f, 0.0f};
+  filter.AddFilter(55, factors5, arraysize(factors5));
+  ASSERT_EQ(6, filter.max_filter());
+  ASSERT_EQ(5, filter.num_values());
+
+  values = filter.FilterForValue(4, &filter_offset, &filter_length);
+  ASSERT_TRUE(values != NULL);
+  ASSERT_EQ(57, filter_offset);  // 55 plus 2 leading zeroes
+  ASSERT_EQ(6, filter_length);   // 9 - (2 leading + 1 trailing) zeroes
+
+  // All-zero filters after the first one also work
+  static const float factors6[] = {0.0f};
+  filter.AddFilter(66, factors6, arraysize(factors6));
+  ASSERT_EQ(6, filter.max_filter());
+  ASSERT_EQ(6, filter.num_values());
+
+  values = filter.FilterForValue(5, &filter_offset, &filter_length);
+  ASSERT_TRUE(values == NULL);   // filter_length == 0 => values is NULL
+  ASSERT_EQ(66, filter_offset);  // value passed in
+  ASSERT_EQ(0, filter_length);
+}
+
+void VerifySIMD(unsigned int source_width,
+                unsigned int source_height,
+                unsigned int dest_width,
+                unsigned int dest_height) {
+  float filter[] = {0.05f, -0.15f, 0.6f, 0.6f, -0.15f, 0.05f};
+  // Preparing convolve coefficients.
+  ConvolutionFilter1D x_filter, y_filter;
+  for (unsigned int p = 0; p < dest_width; ++p) {
+    unsigned int offset = source_width * p / dest_width;
+    EXPECT_LT(offset, source_width);
+    x_filter.AddFilter(offset, filter,
+                       std::min<int>(arraysize(filter), source_width - offset));
+  }
+  x_filter.PaddingForSIMD();
+  for (unsigned int p = 0; p < dest_height; ++p) {
+    unsigned int offset = source_height * p / dest_height;
+    y_filter.AddFilter(offset, filter, std::min<int>(arraysize(filter),
+                                                     source_height - offset));
+  }
+  y_filter.PaddingForSIMD();
+
+  // Allocate input and output skia bitmap.
+  SkBitmap source, result_c, result_sse;
+  source.allocN32Pixels(source_width, source_height);
+  result_c.allocN32Pixels(dest_width, dest_height);
+  result_sse.allocN32Pixels(dest_width, dest_height);
+
+  // Randomize source bitmap for testing.
+  unsigned char* src_ptr = static_cast<unsigned char*>(source.getPixels());
+  for (int y = 0; y < source.height(); y++) {
+    for (unsigned int x = 0; x < source.rowBytes(); x++)
+      src_ptr[x] = rand() % 255;
+    src_ptr += source.rowBytes();
+  }
+
+  // Test both cases with different has_alpha.
+  for (int alpha = 0; alpha < 2; alpha++) {
+    // Convolve using C code.
+    base::TimeTicks resize_start;
+    base::TimeDelta delta_c, delta_sse;
+    unsigned char* r1 = static_cast<unsigned char*>(result_c.getPixels());
+    unsigned char* r2 = static_cast<unsigned char*>(result_sse.getPixels());
+
+    resize_start = base::TimeTicks::Now();
+    BGRAConvolve2D(static_cast<const uint8*>(source.getPixels()),
+                   static_cast<int>(source.rowBytes()), (alpha != 0), x_filter,
+                   y_filter, static_cast<int>(result_c.rowBytes()), r1, false);
+    delta_c = base::TimeTicks::Now() - resize_start;
+
+    resize_start = base::TimeTicks::Now();
+    // Convolve using SSE2 code
+    BGRAConvolve2D(static_cast<const uint8*>(source.getPixels()),
+                   static_cast<int>(source.rowBytes()), (alpha != 0), x_filter,
+                   y_filter, static_cast<int>(result_sse.rowBytes()), r2, true);
+    delta_sse = base::TimeTicks::Now() - resize_start;
+
+    // Unfortunately I could not enable the performance check now.
+    // Most bots use debug version, and there are great difference between
+    // the code generation for intrinsic, etc. In release version speed
+    // difference was 150%-200% depend on alpha channel presence;
+    // while in debug version speed difference was 96%-120%.
+    // TODO(jiesun): optimize further until we could enable this for
+    // debug version too.
+    // EXPECT_LE(delta_sse, delta_c);
+
+    int64 c_us = delta_c.InMicroseconds();
+    int64 sse_us = delta_sse.InMicroseconds();
+    VLOG(1) << "from:" << source_width << "x" << source_height
+            << " to:" << dest_width << "x" << dest_height
+            << (alpha ? " with alpha" : " w/o alpha");
+    VLOG(1) << "c:" << c_us << " sse:" << sse_us;
+    VLOG(1) << "ratio:" << static_cast<float>(c_us) / sse_us;
+
+    // Comparing result.
+    for (unsigned int i = 0; i < dest_height; i++) {
+      EXPECT_FALSE(memcmp(r1, r2, dest_width * 4));  // RGBA always
+      r1 += result_c.rowBytes();
+      r2 += result_sse.rowBytes();
+    }
+  }
+}
+
+TEST(Convolver, VerifySIMDEdgeCases) {
+  srand(static_cast<unsigned int>(time(0)));
+  // Loop over all possible (small) image sizes
+  for (unsigned int width = 1; width < 20; width++) {
+    for (unsigned int height = 1; height < 20; height++) {
+      VerifySIMD(width, height, 8, 8);
+      VerifySIMD(8, 8, width, height);
+    }
+  }
+}
+
+// Verify that lage upscales/downscales produce the same result
+// with and without SIMD.
+TEST(Convolver, VerifySIMDPrecision) {
+  int source_sizes[][2] = {{1920, 1080}, {1377, 523}, {325, 241}};
+  int dest_sizes[][2] = {{1280, 1024}, {177, 123}};
+
+  srand(static_cast<unsigned int>(time(0)));
+
+  // Loop over some specific source and destination dimensions.
+  for (unsigned int i = 0; i < arraysize(source_sizes); ++i) {
+    unsigned int source_width = source_sizes[i][0];
+    unsigned int source_height = source_sizes[i][1];
+    for (unsigned int j = 0; j < arraysize(dest_sizes); ++j) {
+      unsigned int dest_width = dest_sizes[j][0];
+      unsigned int dest_height = dest_sizes[j][1];
+      VerifySIMD(source_width, source_height, dest_width, dest_height);
+    }
+  }
+}
+
+TEST(Convolver, SeparableSingleConvolution) {
+  static const int kImgWidth = 1024;
+  static const int kImgHeight = 1024;
+  static const int kChannelCount = 3;
+  static const int kStrideSlack = 22;
+  ConvolutionFilter1D filter;
+  const float box[5] = {0.2f, 0.2f, 0.2f, 0.2f, 0.2f};
+  filter.AddFilter(0, box, 5);
+
+  // Allocate a source image and set to 0.
+  const int src_row_stride = kImgWidth * kChannelCount + kStrideSlack;
+  int src_byte_count = src_row_stride * kImgHeight;
+  std::vector<unsigned char> input;
+  const int signal_x = kImgWidth / 2;
+  const int signal_y = kImgHeight / 2;
+  input.resize(src_byte_count, 0);
+  // The image has a single impulse pixel in channel 1, smack in the middle.
+  const int non_zero_pixel_index =
+      signal_y * src_row_stride + signal_x * kChannelCount + 1;
+  input[non_zero_pixel_index] = 255;
+
+  // Destination will be a single channel image with stide matching width.
+  const int dest_row_stride = kImgWidth;
+  const int dest_byte_count = dest_row_stride * kImgHeight;
+  std::vector<unsigned char> output;
+  output.resize(dest_byte_count);
+
+  // Apply convolution in X.
+  SingleChannelConvolveX1D(&input[0], src_row_stride, 1, kChannelCount, filter,
+                           SkISize::Make(kImgWidth, kImgHeight), &output[0],
+                           dest_row_stride, 0, 1, false);
+  for (int x = signal_x - 2; x <= signal_x + 2; ++x)
+    EXPECT_GT(output[signal_y * dest_row_stride + x], 0);
+
+  EXPECT_EQ(output[signal_y * dest_row_stride + signal_x - 3], 0);
+  EXPECT_EQ(output[signal_y * dest_row_stride + signal_x + 3], 0);
+
+  // Apply convolution in Y.
+  SingleChannelConvolveY1D(&input[0], src_row_stride, 1, kChannelCount, filter,
+                           SkISize::Make(kImgWidth, kImgHeight), &output[0],
+                           dest_row_stride, 0, 1, false);
+  for (int y = signal_y - 2; y <= signal_y + 2; ++y)
+    EXPECT_GT(output[y * dest_row_stride + signal_x], 0);
+
+  EXPECT_EQ(output[(signal_y - 3) * dest_row_stride + signal_x], 0);
+  EXPECT_EQ(output[(signal_y + 3) * dest_row_stride + signal_x], 0);
+
+  EXPECT_EQ(output[signal_y * dest_row_stride + signal_x - 1], 0);
+  EXPECT_EQ(output[signal_y * dest_row_stride + signal_x + 1], 0);
+
+  // The main point of calling this is to invoke the routine on input without
+  // padding.
+  std::vector<unsigned char> output2;
+  output2.resize(dest_byte_count);
+  SingleChannelConvolveX1D(&output[0], dest_row_stride, 0, 1, filter,
+                           SkISize::Make(kImgWidth, kImgHeight), &output2[0],
+                           dest_row_stride, 0, 1, false);
+  // This should be a result of 2D convolution.
+  for (int x = signal_x - 2; x <= signal_x + 2; ++x) {
+    for (int y = signal_y - 2; y <= signal_y + 2; ++y)
+      EXPECT_GT(output2[y * dest_row_stride + x], 0);
+  }
+  EXPECT_EQ(output2[0], 0);
+  EXPECT_EQ(output2[dest_row_stride - 1], 0);
+  EXPECT_EQ(output2[dest_byte_count - 1], 0);
+}
+
+TEST(Convolver, SeparableSingleConvolutionEdges) {
+  // The purpose of this test is to check if the implementation treats correctly
+  // edges of the image.
+  static const int kImgWidth = 600;
+  static const int kImgHeight = 800;
+  static const int kChannelCount = 3;
+  static const int kStrideSlack = 22;
+  static const int kChannel = 1;
+  ConvolutionFilter1D filter;
+  const float box[5] = {0.2f, 0.2f, 0.2f, 0.2f, 0.2f};
+  filter.AddFilter(0, box, 5);
+
+  // Allocate a source image and set to 0.
+  int src_row_stride = kImgWidth * kChannelCount + kStrideSlack;
+  int src_byte_count = src_row_stride * kImgHeight;
+  std::vector<unsigned char> input(src_byte_count);
+
+  // Draw a frame around the image.
+  for (int i = 0; i < src_byte_count; ++i) {
+    int row = i / src_row_stride;
+    int col = i % src_row_stride / kChannelCount;
+    int channel = i % src_row_stride % kChannelCount;
+    if (channel != kChannel || col > kImgWidth) {
+      input[i] = 255;
+    } else if (row == 0 || col == 0 || col == kImgWidth - 1 ||
+               row == kImgHeight - 1) {
+      input[i] = 100;
+    } else if (row == 1 || col == 1 || col == kImgWidth - 2 ||
+               row == kImgHeight - 2) {
+      input[i] = 200;
+    } else {
+      input[i] = 0;
+    }
+  }
+
+  // Destination will be a single channel image with stide matching width.
+  int dest_row_stride = kImgWidth;
+  int dest_byte_count = dest_row_stride * kImgHeight;
+  std::vector<unsigned char> output;
+  output.resize(dest_byte_count);
+
+  // Apply convolution in X.
+  SingleChannelConvolveX1D(&input[0], src_row_stride, 1, kChannelCount, filter,
+                           SkISize::Make(kImgWidth, kImgHeight), &output[0],
+                           dest_row_stride, 0, 1, false);
+
+  // Sadly, comparison is not as simple as retaining all values.
+  int invalid_values = 0;
+  const unsigned char first_value = output[0];
+  EXPECT_NEAR(first_value, 100, 1);
+  for (int i = 0; i < dest_row_stride; ++i) {
+    if (output[i] != first_value)
+      ++invalid_values;
+  }
+  EXPECT_EQ(0, invalid_values);
+
+  int test_row = 22;
+  EXPECT_NEAR(output[test_row * dest_row_stride], 100, 1);
+  EXPECT_NEAR(output[test_row * dest_row_stride + 1], 80, 1);
+  EXPECT_NEAR(output[test_row * dest_row_stride + 2], 60, 1);
+  EXPECT_NEAR(output[test_row * dest_row_stride + 3], 40, 1);
+  EXPECT_NEAR(output[(test_row + 1) * dest_row_stride - 1], 100, 1);
+  EXPECT_NEAR(output[(test_row + 1) * dest_row_stride - 2], 80, 1);
+  EXPECT_NEAR(output[(test_row + 1) * dest_row_stride - 3], 60, 1);
+  EXPECT_NEAR(output[(test_row + 1) * dest_row_stride - 4], 40, 1);
+
+  SingleChannelConvolveY1D(&input[0], src_row_stride, 1, kChannelCount, filter,
+                           SkISize::Make(kImgWidth, kImgHeight), &output[0],
+                           dest_row_stride, 0, 1, false);
+
+  int test_column = 42;
+  EXPECT_NEAR(output[test_column], 100, 1);
+  EXPECT_NEAR(output[test_column + dest_row_stride], 80, 1);
+  EXPECT_NEAR(output[test_column + dest_row_stride * 2], 60, 1);
+  EXPECT_NEAR(output[test_column + dest_row_stride * 3], 40, 1);
+
+  EXPECT_NEAR(output[test_column + dest_row_stride * (kImgHeight - 1)], 100, 1);
+  EXPECT_NEAR(output[test_column + dest_row_stride * (kImgHeight - 2)], 80, 1);
+  EXPECT_NEAR(output[test_column + dest_row_stride * (kImgHeight - 3)], 60, 1);
+  EXPECT_NEAR(output[test_column + dest_row_stride * (kImgHeight - 4)], 40, 1);
+}
+
+TEST(Convolver, SetUpGaussianConvolutionFilter) {
+  ConvolutionFilter1D smoothing_filter;
+  ConvolutionFilter1D gradient_filter;
+  SetUpGaussianConvolutionKernel(&smoothing_filter, 4.5f, false);
+  SetUpGaussianConvolutionKernel(&gradient_filter, 3.0f, true);
+
+  int specified_filter_length;
+  int filter_offset;
+  int filter_length;
+
+  const ConvolutionFilter1D::Fixed* smoothing_kernel =
+      smoothing_filter.GetSingleFilter(&specified_filter_length, &filter_offset,
+                                       &filter_length);
+  EXPECT_TRUE(smoothing_kernel);
+  std::vector<float> fp_smoothing_kernel(filter_length);
+  std::transform(smoothing_kernel, smoothing_kernel + filter_length,
+                 fp_smoothing_kernel.begin(),
+                 ConvolutionFilter1D::FixedToFloat);
+  // Should sum-up to 1 (nearly), and all values whould be in ]0, 1[.
+  EXPECT_NEAR(std::accumulate(fp_smoothing_kernel.begin(),
+                              fp_smoothing_kernel.end(), 0.0f),
+              1.0f, 0.01f);
+  EXPECT_GT(
+      *std::min_element(fp_smoothing_kernel.begin(), fp_smoothing_kernel.end()),
+      0.0f);
+  EXPECT_LT(
+      *std::max_element(fp_smoothing_kernel.begin(), fp_smoothing_kernel.end()),
+      1.0f);
+
+  const ConvolutionFilter1D::Fixed* gradient_kernel =
+      gradient_filter.GetSingleFilter(&specified_filter_length, &filter_offset,
+                                      &filter_length);
+  EXPECT_TRUE(gradient_kernel);
+  std::vector<float> fp_gradient_kernel(filter_length);
+  std::transform(gradient_kernel, gradient_kernel + filter_length,
+                 fp_gradient_kernel.begin(), ConvolutionFilter1D::FixedToFloat);
+  // Should sum-up to 0, and all values whould be in ]-1.5, 1.5[.
+  EXPECT_NEAR(std::accumulate(fp_gradient_kernel.begin(),
+                              fp_gradient_kernel.end(), 0.0f),
+              0.0f, 0.01f);
+  EXPECT_GT(
+      *std::min_element(fp_gradient_kernel.begin(), fp_gradient_kernel.end()),
+      -1.5f);
+  EXPECT_LT(
+      *std::min_element(fp_gradient_kernel.begin(), fp_gradient_kernel.end()),
+      0.0f);
+  EXPECT_LT(
+      *std::max_element(fp_gradient_kernel.begin(), fp_gradient_kernel.end()),
+      1.5f);
+  EXPECT_GT(
+      *std::max_element(fp_gradient_kernel.begin(), fp_gradient_kernel.end()),
+      0.0f);
+}
+
+}  // namespace skia
diff --git a/skia/ext/opacity_draw_filter.cc b/skia/ext/opacity_draw_filter.cc
deleted file mode 100644
index 10ed9e8..0000000
--- a/skia/ext/opacity_draw_filter.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/opacity_draw_filter.h"
-#include "third_party/skia/include/core/SkPaint.h"
-
-namespace skia {
-
-OpacityDrawFilter::OpacityDrawFilter(float opacity,
-                                     bool disable_image_filtering)
-    : alpha_(SkScalarRoundToInt(opacity * 255)),
-      disable_image_filtering_(disable_image_filtering) {}
-
-OpacityDrawFilter::~OpacityDrawFilter() {}
-
-bool OpacityDrawFilter::filter(SkPaint* paint, Type type) {
-  if (alpha_ < 255)
-    paint->setAlpha(alpha_);
-  if (disable_image_filtering_)
-    paint->setFilterQuality(kNone_SkFilterQuality);
-  return true;
-}
-
-}  // namespace skia
-
-
diff --git a/skia/ext/opacity_draw_filter.h b/skia/ext/opacity_draw_filter.h
deleted file mode 100644
index 7d11d68..0000000
--- a/skia/ext/opacity_draw_filter.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SKIA_EXT_OPACITY_DRAW_FILTER_H
-#define SKIA_EXT_OPACITY_DRAW_FILTER_H
-
-#include "base/values.h"
-#include "third_party/skia/include/core/SkDrawFilter.h"
-
-class SkPaint;
-
-namespace skia {
-
-// This filter allows setting an opacity on every draw call to a canvas, and to
-// disable image filtering. Note that the opacity setting is only correct in
-// very limited conditions: when there is only zero or one opaque, nonlayer
-// draw for every pixel in the surface.
-class SK_API OpacityDrawFilter : public SkDrawFilter {
- public:
-  OpacityDrawFilter(float opacity, bool disable_image_filtering);
-  ~OpacityDrawFilter() override;
-  bool filter(SkPaint* paint, SkDrawFilter::Type type) override;
-
- private:
-  int alpha_;
-  bool disable_image_filtering_;
-};
-
-}  // namespace skia
-
-#endif  // SKIA_EXT_OPACITY_DRAW_FILTER_H
-
diff --git a/skia/ext/platform_canvas.cc b/skia/ext/platform_canvas.cc
deleted file mode 100644
index 9235967..0000000
--- a/skia/ext/platform_canvas.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/platform_canvas.h"
-
-#include "skia/ext/bitmap_platform_device.h"
-#include "third_party/skia/include/core/SkTypes.h"
-
-namespace skia {
-
-SkBaseDevice* GetTopDevice(const SkCanvas& canvas) {
-  return canvas.getTopDevice(true);
-}
-
-bool SupportsPlatformPaint(const SkCanvas* canvas) {
-  PlatformDevice* platform_device = GetPlatformDevice(GetTopDevice(*canvas));
-  return platform_device && platform_device->SupportsPlatformPaint();
-}
-
-PlatformSurface BeginPlatformPaint(SkCanvas* canvas) {
-  PlatformDevice* platform_device = GetPlatformDevice(GetTopDevice(*canvas));
-  if (platform_device)
-    return platform_device->BeginPlatformPaint();
-
-  return 0;
-}
-
-void EndPlatformPaint(SkCanvas* canvas) {
-  PlatformDevice* platform_device = GetPlatformDevice(GetTopDevice(*canvas));
-  if (platform_device)
-    platform_device->EndPlatformPaint();
-}
-
-void MakeOpaque(SkCanvas* canvas, int x, int y, int width, int height) {
-  if (width <= 0 || height <= 0)
-    return;
-
-  SkRect rect;
-  rect.setXYWH(SkIntToScalar(x), SkIntToScalar(y),
-               SkIntToScalar(width), SkIntToScalar(height));
-  SkPaint paint;
-  paint.setColor(SK_ColorBLACK);
-  paint.setXfermodeMode(SkXfermode::kDstATop_Mode);
-  canvas->drawRect(rect, paint);
-}
-
-size_t PlatformCanvasStrideForWidth(unsigned width) {
-  return 4 * width;
-}
-
-SkCanvas* CreateCanvas(const skia::RefPtr<SkBaseDevice>& device, OnFailureType failureType) {
-  if (!device) {
-    if (CRASH_ON_FAILURE == failureType)
-      SK_CRASH();
-    return NULL;
-  }
-  return new SkCanvas(device.get());
-}
-
-PlatformBitmap::PlatformBitmap() : surface_(0), platform_extra_(0) {}
-
-}  // namespace skia
diff --git a/skia/ext/platform_canvas.h b/skia/ext/platform_canvas.h
deleted file mode 100644
index 25560e7..0000000
--- a/skia/ext/platform_canvas.h
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SKIA_EXT_PLATFORM_CANVAS_H_
-#define SKIA_EXT_PLATFORM_CANVAS_H_
-
-// The platform-specific device will include the necessary platform headers
-// to get the surface type.
-#include "base/basictypes.h"
-#include "skia/ext/platform_device.h"
-#include "skia/ext/refptr.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkPixelRef.h"
-#include "third_party/skia/include/core/SkPreConfig.h"
-
-namespace skia {
-
-typedef SkCanvas PlatformCanvas;
-
-//
-//  Note about error handling.
-//
-//  Creating a canvas can fail at times, most often because we fail to allocate
-//  the backing-store (pixels). This can be from out-of-memory, or something
-//  more opaque, like GDI or cairo reported a failure.
-//
-//  To allow the caller to handle the failure, every Create... factory takes an
-//  enum as its last parameter. The default value is kCrashOnFailure. If the
-//  caller passes kReturnNullOnFailure, then the caller is responsible to check
-//  the return result.
-//
-enum OnFailureType {
-  CRASH_ON_FAILURE,
-  RETURN_NULL_ON_FAILURE
-};
-
-#if defined(SK_BUILD_FOR_WIN32)
-  // The shared_section parameter is passed to gfx::PlatformDevice::create.
-  // See it for details.
-  SK_API SkCanvas* CreatePlatformCanvas(int width,
-                                        int height,
-                                        bool is_opaque,
-                                        HANDLE shared_section,
-                                        OnFailureType failure_type);
-
-  // Draws the top layer of the canvas into the specified HDC. Only works
-  // with a PlatformCanvas with a BitmapPlatformDevice.
-  SK_API void DrawToNativeContext(SkCanvas* canvas,
-                                  HDC hdc,
-                                  int x,
-                                  int y,
-                                  const RECT* src_rect);
-#elif defined(SK_BUILD_FOR_MAC)
-  SK_API SkCanvas* CreatePlatformCanvas(CGContextRef context,
-                                        int width,
-                                        int height,
-                                        bool is_opaque,
-                                        OnFailureType failure_type);
-
-  SK_API SkCanvas* CreatePlatformCanvas(int width,
-                                        int height,
-                                        bool is_opaque,
-                                        uint8_t* context,
-                                        OnFailureType failure_type);
-#elif defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX)
-  // Linux ---------------------------------------------------------------------
-
-  // Construct a canvas from the given memory region. The memory is not cleared
-  // first. @data must be, at least, @height * StrideForWidth(@width) bytes.
-  SK_API SkCanvas* CreatePlatformCanvas(int width,
-                                        int height,
-                                        bool is_opaque,
-                                        uint8_t* data,
-                                        OnFailureType failure_type);
-#endif
-
-static inline SkCanvas* CreatePlatformCanvas(int width,
-                                             int height,
-                                             bool is_opaque) {
-  return CreatePlatformCanvas(width, height, is_opaque, 0, CRASH_ON_FAILURE);
-}
-
-SK_API SkCanvas* CreateCanvas(const skia::RefPtr<SkBaseDevice>& device,
-                              OnFailureType failure_type);
-
-static inline SkCanvas* CreateBitmapCanvas(int width,
-                                           int height,
-                                           bool is_opaque) {
-  return CreatePlatformCanvas(width, height, is_opaque, 0, CRASH_ON_FAILURE);
-}
-
-static inline SkCanvas* TryCreateBitmapCanvas(int width,
-                                              int height,
-                                              bool is_opaque) {
-  return CreatePlatformCanvas(width, height, is_opaque, 0,
-                              RETURN_NULL_ON_FAILURE);
-}
-
-// Return the stride (length of a line in bytes) for the given width. Because
-// we use 32-bits per pixel, this will be roughly 4*width. However, for
-// alignment reasons we may wish to increase that.
-SK_API size_t PlatformCanvasStrideForWidth(unsigned width);
-
-// Returns the SkBaseDevice pointer of the topmost rect with a non-empty
-// clip. In practice, this is usually either the top layer or nothing, since
-// we usually set the clip to new layers when we make them.
-//
-// This may return NULL, so callers need to check.
-//
-// This is different than SkCanvas' getDevice, because that returns the
-// bottommost device.
-//
-// Danger: the resulting device should not be saved. It will be invalidated
-// by the next call to save() or restore().
-SK_API SkBaseDevice* GetTopDevice(const SkCanvas& canvas);
-
-// Returns true if native platform routines can be used to draw on the
-// given canvas. If this function returns false, BeginPlatformPaint will
-// return NULL PlatformSurface.
-SK_API bool SupportsPlatformPaint(const SkCanvas* canvas);
-
-// Sets the opacity of each pixel in the specified region to be opaque.
-SK_API void MakeOpaque(SkCanvas* canvas, int x, int y, int width, int height);
-
-// These calls should surround calls to platform drawing routines, the
-// surface returned here can be used with the native platform routines.
-//
-// Call EndPlatformPaint when you are done and want to use skia operations
-// after calling the platform-specific BeginPlatformPaint; this will
-// synchronize the bitmap to OS if necessary.
-SK_API PlatformSurface BeginPlatformPaint(SkCanvas* canvas);
-SK_API void EndPlatformPaint(SkCanvas* canvas);
-
-// Helper class for pairing calls to BeginPlatformPaint and EndPlatformPaint.
-// Upon construction invokes BeginPlatformPaint, and upon destruction invokes
-// EndPlatformPaint.
-class SK_API ScopedPlatformPaint {
- public:
-  explicit ScopedPlatformPaint(SkCanvas* canvas) : canvas_(canvas) {
-    platform_surface_ = BeginPlatformPaint(canvas);
-  }
-  ~ScopedPlatformPaint() { EndPlatformPaint(canvas_); }
-
-  // Returns the PlatformSurface to use for native platform drawing calls.
-  PlatformSurface GetPlatformSurface() { return platform_surface_; }
- private:
-  SkCanvas* canvas_;
-  PlatformSurface platform_surface_;
-
-  // Disallow copy and assign
-  ScopedPlatformPaint(const ScopedPlatformPaint&);
-  ScopedPlatformPaint& operator=(const ScopedPlatformPaint&);
-};
-
-// PlatformBitmap holds a PlatformSurface that can also be used as an SkBitmap.
-class SK_API PlatformBitmap {
- public:
-  PlatformBitmap();
-  ~PlatformBitmap();
-
-  // Returns true if the bitmap was able to allocate its surface.
-  bool Allocate(int width, int height, bool is_opaque);
-
-  // Returns the platform surface, or 0 if Allocate() did not return true.
-  PlatformSurface GetSurface() { return surface_; }
-
-  // Return the skia bitmap, which will be empty if Allocate() did not
-  // return true.
-  //
-  // The resulting SkBitmap holds a refcount on the underlying platform surface,
-  // so the surface will remain allocated so long as the SkBitmap or its copies
-  // stay around.
-  const SkBitmap& GetBitmap() { return bitmap_; }
-
- private:
-  SkBitmap bitmap_;
-  PlatformSurface surface_;  // initialized to 0
-  intptr_t platform_extra_;  // platform specific, initialized to 0
-
-  DISALLOW_COPY_AND_ASSIGN(PlatformBitmap);
-};
-
-}  // namespace skia
-
-#endif  // SKIA_EXT_PLATFORM_CANVAS_H_
diff --git a/skia/ext/platform_canvas_unittest.cc b/skia/ext/platform_canvas_unittest.cc
deleted file mode 100644
index 560d47f..0000000
--- a/skia/ext/platform_canvas_unittest.cc
+++ /dev/null
@@ -1,453 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// TODO(awalker): clean up the const/non-const reference handling in this test
-
-#include "skia/ext/platform_canvas.h"
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "build/build_config.h"
-#include "skia/ext/platform_device.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/include/core/SkColorPriv.h"
-#include "third_party/skia/include/core/SkPixelRef.h"
-
-#if defined(OS_MACOSX)
-#import <ApplicationServices/ApplicationServices.h>
-#endif
-
-#if !defined(OS_WIN)
-#include <unistd.h>
-#endif
-
-namespace skia {
-
-namespace {
-
-bool IsOfColor(const SkBitmap& bitmap, int x, int y, uint32_t color) {
-  // For masking out the alpha values.
-  static uint32_t alpha_mask =
-      static_cast<uint32_t>(SK_A32_MASK) << SK_A32_SHIFT;
-  return (*bitmap.getAddr32(x, y) | alpha_mask) == (color | alpha_mask);
-}
-
-// Return true if the canvas is filled to canvas_color, and contains a single
-// rectangle filled to rect_color. This function ignores the alpha channel,
-// since Windows will sometimes clear the alpha channel when drawing, and we
-// will fix that up later in cases it's necessary.
-bool VerifyRect(const PlatformCanvas& canvas,
-                uint32_t canvas_color, uint32_t rect_color,
-                int x, int y, int w, int h) {
-  SkBaseDevice* device = skia::GetTopDevice(canvas);
-  const SkBitmap& bitmap = device->accessBitmap(false);
-  SkAutoLockPixels lock(bitmap);
-
-  for (int cur_y = 0; cur_y < bitmap.height(); cur_y++) {
-    for (int cur_x = 0; cur_x < bitmap.width(); cur_x++) {
-      if (cur_x >= x && cur_x < x + w &&
-          cur_y >= y && cur_y < y + h) {
-        // Inside the square should be rect_color
-        if (!IsOfColor(bitmap, cur_x, cur_y, rect_color))
-          return false;
-      } else {
-        // Outside the square should be canvas_color
-        if (!IsOfColor(bitmap, cur_x, cur_y, canvas_color))
-          return false;
-      }
-    }
-  }
-  return true;
-}
-
-#if !defined(OS_MACOSX)
-// Return true if canvas has something that passes for a rounded-corner
-// rectangle. Basically, we're just checking to make sure that the pixels in the
-// middle are of rect_color and pixels in the corners are of canvas_color.
-bool VerifyRoundedRect(const PlatformCanvas& canvas,
-                       uint32_t canvas_color,
-                       uint32_t rect_color,
-                       int x,
-                       int y,
-                       int w,
-                       int h) {
-  SkBaseDevice* device = skia::GetTopDevice(canvas);
-  const SkBitmap& bitmap = device->accessBitmap(false);
-  SkAutoLockPixels lock(bitmap);
-
-  // Check corner points first. They should be of canvas_color.
-  if (!IsOfColor(bitmap, x, y, canvas_color)) return false;
-  if (!IsOfColor(bitmap, x + w, y, canvas_color)) return false;
-  if (!IsOfColor(bitmap, x, y + h, canvas_color)) return false;
-  if (!IsOfColor(bitmap, x + w, y, canvas_color)) return false;
-
-  // Check middle points. They should be of rect_color.
-  if (!IsOfColor(bitmap, (x + w / 2), y, rect_color)) return false;
-  if (!IsOfColor(bitmap, x, (y + h / 2), rect_color)) return false;
-  if (!IsOfColor(bitmap, x + w, (y + h / 2), rect_color)) return false;
-  if (!IsOfColor(bitmap, (x + w / 2), y + h, rect_color)) return false;
-
-  return true;
-}
-#endif
-
-// Checks whether there is a white canvas with a black square at the given
-// location in pixels (not in the canvas coordinate system).
-bool VerifyBlackRect(const PlatformCanvas& canvas, int x, int y, int w, int h) {
-  return VerifyRect(canvas, SK_ColorWHITE, SK_ColorBLACK, x, y, w, h);
-}
-
-// Check that every pixel in the canvas is a single color.
-bool VerifyCanvasColor(const PlatformCanvas& canvas, uint32_t canvas_color) {
-  return VerifyRect(canvas, canvas_color, 0, 0, 0, 0, 0);
-}
-
-#if defined(OS_WIN)
-void DrawNativeRect(PlatformCanvas& canvas, int x, int y, int w, int h) {
-  skia::ScopedPlatformPaint scoped_platform_paint(&canvas);
-  HDC dc = scoped_platform_paint.GetPlatformSurface();
-
-  RECT inner_rc;
-  inner_rc.left = x;
-  inner_rc.top = y;
-  inner_rc.right = x + w;
-  inner_rc.bottom = y + h;
-  FillRect(dc, &inner_rc, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
-}
-#elif defined(OS_MACOSX)
-void DrawNativeRect(PlatformCanvas& canvas, int x, int y, int w, int h) {
-  skia::ScopedPlatformPaint scoped_platform_paint(&canvas);
-  CGContextRef context = scoped_platform_paint.GetPlatformSurface();
-
-  CGRect inner_rc = CGRectMake(x, y, w, h);
-  // RGBA opaque black
-  CGColorRef black = CGColorCreateGenericRGB(0.0, 0.0, 0.0, 1.0);
-  CGContextSetFillColorWithColor(context, black);
-  CGColorRelease(black);
-  CGContextFillRect(context, inner_rc);
-}
-#else
-void DrawNativeRect(PlatformCanvas& canvas, int x, int y, int w, int h) {
-  NOTIMPLEMENTED();
-}
-#endif
-
-// Clips the contents of the canvas to the given rectangle. This will be
-// intersected with any existing clip.
-void AddClip(PlatformCanvas& canvas, int x, int y, int w, int h) {
-  SkRect rect;
-  rect.set(SkIntToScalar(x), SkIntToScalar(y),
-           SkIntToScalar(x + w), SkIntToScalar(y + h));
-  canvas.clipRect(rect);
-}
-
-class LayerSaver {
- public:
-  LayerSaver(PlatformCanvas& canvas, int x, int y, int w, int h)
-      : canvas_(canvas),
-        x_(x),
-        y_(y),
-        w_(w),
-        h_(h) {
-    SkRect bounds;
-    bounds.set(SkIntToScalar(x_), SkIntToScalar(y_),
-               SkIntToScalar(right()), SkIntToScalar(bottom()));
-    canvas_.saveLayer(&bounds, NULL);
-    canvas.clear(SkColorSetARGB(0, 0, 0, 0));
-  }
-
-  ~LayerSaver() {
-    canvas_.restore();
-  }
-
-  int x() const { return x_; }
-  int y() const { return y_; }
-  int w() const { return w_; }
-  int h() const { return h_; }
-
-  // Returns the EXCLUSIVE far bounds of the layer.
-  int right() const { return x_ + w_; }
-  int bottom() const { return y_ + h_; }
-
- private:
-  PlatformCanvas& canvas_;
-  int x_, y_, w_, h_;
-};
-
-// Size used for making layers in many of the below tests.
-const int kLayerX = 2;
-const int kLayerY = 3;
-const int kLayerW = 9;
-const int kLayerH = 7;
-
-// Size used by some tests to draw a rectangle inside the layer.
-const int kInnerX = 4;
-const int kInnerY = 5;
-const int kInnerW = 2;
-const int kInnerH = 3;
-
-}
-
-// This just checks that our checking code is working properly, it just uses
-// regular skia primitives.
-TEST(PlatformCanvas, SkLayer) {
-  // Create the canvas initialized to opaque white.
-  RefPtr<SkCanvas> canvas = AdoptRef(CreatePlatformCanvas(16, 16, true));
-  canvas->drawColor(SK_ColorWHITE);
-
-  // Make a layer and fill it completely to make sure that the bounds are
-  // correct.
-  {
-    LayerSaver layer(*canvas, kLayerX, kLayerY, kLayerW, kLayerH);
-    canvas->drawColor(SK_ColorBLACK);
-  }
-  EXPECT_TRUE(VerifyBlackRect(*canvas, kLayerX, kLayerY, kLayerW, kLayerH));
-}
-
-// Test native clipping.
-TEST(PlatformCanvas, ClipRegion) {
-  // Initialize a white canvas
-  RefPtr<SkCanvas> canvas = AdoptRef(CreatePlatformCanvas(16, 16, true));
-  canvas->drawColor(SK_ColorWHITE);
-  EXPECT_TRUE(VerifyCanvasColor(*canvas, SK_ColorWHITE));
-
-  // Test that initially the canvas has no clip region, by filling it
-  // with a black rectangle.
-  // Note: Don't use LayerSaver, since internally it sets a clip region.
-  DrawNativeRect(*canvas, 0, 0, 16, 16);
-  EXPECT_TRUE(VerifyCanvasColor(*canvas, SK_ColorBLACK));
-
-  // Test that intersecting disjoint clip rectangles sets an empty clip region
-  canvas->drawColor(SK_ColorWHITE);
-  EXPECT_TRUE(VerifyCanvasColor(*canvas, SK_ColorWHITE));
-  {
-    LayerSaver layer(*canvas, 0, 0, 16, 16);
-    AddClip(*canvas, 2, 3, 4, 5);
-    AddClip(*canvas, 4, 9, 10, 10);
-    DrawNativeRect(*canvas, 0, 0, 16, 16);
-  }
-  EXPECT_TRUE(VerifyCanvasColor(*canvas, SK_ColorWHITE));
-}
-
-// Test the layers get filled properly by native rendering.
-TEST(PlatformCanvas, FillLayer) {
-  // Create the canvas initialized to opaque white.
-  RefPtr<SkCanvas> canvas = AdoptRef(CreatePlatformCanvas(16, 16, true));
-
-  // Make a layer and fill it completely to make sure that the bounds are
-  // correct.
-  canvas->drawColor(SK_ColorWHITE);
-  {
-    LayerSaver layer(*canvas, kLayerX, kLayerY, kLayerW, kLayerH);
-    DrawNativeRect(*canvas, 0, 0, 100, 100);
-#if defined(OS_WIN)
-    MakeOpaque(canvas.get(), 0, 0, 100, 100);
-#endif
-  }
-  EXPECT_TRUE(VerifyBlackRect(*canvas, kLayerX, kLayerY, kLayerW, kLayerH));
-
-  // Make a layer and fill it partially to make sure the translation is correct.
-  canvas->drawColor(SK_ColorWHITE);
-  {
-    LayerSaver layer(*canvas, kLayerX, kLayerY, kLayerW, kLayerH);
-    DrawNativeRect(*canvas, kInnerX, kInnerY, kInnerW, kInnerH);
-#if defined(OS_WIN)
-    MakeOpaque(canvas.get(), kInnerX, kInnerY, kInnerW, kInnerH);
-#endif
-  }
-  EXPECT_TRUE(VerifyBlackRect(*canvas, kInnerX, kInnerY, kInnerW, kInnerH));
-
-  // Add a clip on the layer and fill to make sure clip is correct.
-  canvas->drawColor(SK_ColorWHITE);
-  {
-    LayerSaver layer(*canvas, kLayerX, kLayerY, kLayerW, kLayerH);
-    canvas->save();
-    AddClip(*canvas, kInnerX, kInnerY, kInnerW, kInnerH);
-    DrawNativeRect(*canvas, 0, 0, 100, 100);
-#if defined(OS_WIN)
-    MakeOpaque(canvas.get(), kInnerX, kInnerY, kInnerW, kInnerH);
-#endif
-    canvas->restore();
-  }
-  EXPECT_TRUE(VerifyBlackRect(*canvas, kInnerX, kInnerY, kInnerW, kInnerH));
-
-  // Add a clip and then make the layer to make sure the clip is correct.
-  canvas->drawColor(SK_ColorWHITE);
-  canvas->save();
-  AddClip(*canvas, kInnerX, kInnerY, kInnerW, kInnerH);
-  {
-    LayerSaver layer(*canvas, kLayerX, kLayerY, kLayerW, kLayerH);
-    DrawNativeRect(*canvas, 0, 0, 100, 100);
-#if defined(OS_WIN)
-    MakeOpaque(canvas.get(), 0, 0, 100, 100);
-#endif
-  }
-  canvas->restore();
-  EXPECT_TRUE(VerifyBlackRect(*canvas, kInnerX, kInnerY, kInnerW, kInnerH));
-}
-
-// Test that translation + make layer works properly.
-TEST(PlatformCanvas, TranslateLayer) {
-  // Create the canvas initialized to opaque white.
-  RefPtr<SkCanvas> canvas = AdoptRef(CreatePlatformCanvas(16, 16, true));
-
-  // Make a layer and fill it completely to make sure that the bounds are
-  // correct.
-  canvas->drawColor(SK_ColorWHITE);
-  canvas->save();
-  canvas->translate(1, 1);
-  {
-    LayerSaver layer(*canvas, kLayerX, kLayerY, kLayerW, kLayerH);
-    DrawNativeRect(*canvas, 0, 0, 100, 100);
-#if defined(OS_WIN)
-    MakeOpaque(canvas.get(), 0, 0, 100, 100);
-#endif
-  }
-  canvas->restore();
-  EXPECT_TRUE(VerifyBlackRect(*canvas, kLayerX + 1, kLayerY + 1,
-                              kLayerW, kLayerH));
-
-  // Translate then make the layer.
-  canvas->drawColor(SK_ColorWHITE);
-  canvas->save();
-  canvas->translate(1, 1);
-  {
-    LayerSaver layer(*canvas, kLayerX, kLayerY, kLayerW, kLayerH);
-    DrawNativeRect(*canvas, kInnerX, kInnerY, kInnerW, kInnerH);
-#if defined(OS_WIN)
-    MakeOpaque(canvas.get(), kInnerX, kInnerY, kInnerW, kInnerH);
-#endif
-  }
-  canvas->restore();
-  EXPECT_TRUE(VerifyBlackRect(*canvas, kInnerX + 1, kInnerY + 1,
-                              kInnerW, kInnerH));
-
-  // Make the layer then translate.
-  canvas->drawColor(SK_ColorWHITE);
-  canvas->save();
-  {
-    LayerSaver layer(*canvas, kLayerX, kLayerY, kLayerW, kLayerH);
-    canvas->translate(1, 1);
-    DrawNativeRect(*canvas, kInnerX, kInnerY, kInnerW, kInnerH);
-#if defined(OS_WIN)
-    MakeOpaque(canvas.get(), kInnerX, kInnerY, kInnerW, kInnerH);
-#endif
-  }
-  canvas->restore();
-  EXPECT_TRUE(VerifyBlackRect(*canvas, kInnerX + 1, kInnerY + 1,
-                              kInnerW, kInnerH));
-
-  // Translate both before and after, and have a clip.
-  canvas->drawColor(SK_ColorWHITE);
-  canvas->save();
-  canvas->translate(1, 1);
-  {
-    LayerSaver layer(*canvas, kLayerX, kLayerY, kLayerW, kLayerH);
-    canvas->drawColor(SK_ColorWHITE);
-    canvas->translate(1, 1);
-    AddClip(*canvas, kInnerX + 1, kInnerY + 1, kInnerW - 1, kInnerH - 1);
-    DrawNativeRect(*canvas, 0, 0, 100, 100);
-#if defined(OS_WIN)
-    MakeOpaque(canvas.get(), kLayerX, kLayerY, kLayerW, kLayerH);
-#endif
-  }
-  canvas->restore();
-  EXPECT_TRUE(VerifyBlackRect(*canvas, kInnerX + 3, kInnerY + 3,
-                              kInnerW - 1, kInnerH - 1));
-
-// TODO(dglazkov): Figure out why this fails on Mac (antialiased clipping?),
-// modify test and remove this guard.
-#if !defined(OS_MACOSX)
-  // Translate both before and after, and have a path clip.
-  canvas->drawColor(SK_ColorWHITE);
-  canvas->save();
-  canvas->translate(1, 1);
-  {
-    LayerSaver layer(*canvas, kLayerX, kLayerY, kLayerW, kLayerH);
-    canvas->drawColor(SK_ColorWHITE);
-    canvas->translate(1, 1);
-
-    SkPath path;
-    SkRect rect;
-    rect.iset(kInnerX - 1, kInnerY - 1,
-              kInnerX + kInnerW, kInnerY + kInnerH);
-    const SkScalar kRadius = 2.0;
-    path.addRoundRect(rect, kRadius, kRadius);
-    canvas->clipPath(path);
-
-    DrawNativeRect(*canvas, 0, 0, 100, 100);
-#if defined(OS_WIN)
-    MakeOpaque(canvas.get(), kLayerX, kLayerY, kLayerW, kLayerH);
-#endif
-  }
-  canvas->restore();
-  EXPECT_TRUE(VerifyRoundedRect(*canvas, SK_ColorWHITE, SK_ColorBLACK,
-                                kInnerX + 1, kInnerY + 1, kInnerW, kInnerH));
-#endif
-}
-
-TEST(PlatformBitmapTest, PlatformBitmap) {
-  const int kWidth = 400;
-  const int kHeight = 300;
-  scoped_ptr<PlatformBitmap> platform_bitmap(new PlatformBitmap);
-
-  EXPECT_TRUE(0 == platform_bitmap->GetSurface());
-  EXPECT_TRUE(platform_bitmap->GetBitmap().empty());
-  EXPECT_TRUE(platform_bitmap->GetBitmap().isNull());
-
-  EXPECT_TRUE(platform_bitmap->Allocate(kWidth, kHeight, /*is_opaque=*/false));
-
-  EXPECT_TRUE(0 != platform_bitmap->GetSurface());
-  EXPECT_FALSE(platform_bitmap->GetBitmap().empty());
-  EXPECT_FALSE(platform_bitmap->GetBitmap().isNull());
-  EXPECT_EQ(kWidth, platform_bitmap->GetBitmap().width());
-  EXPECT_EQ(kHeight, platform_bitmap->GetBitmap().height());
-  EXPECT_LE(static_cast<size_t>(platform_bitmap->GetBitmap().width()*4),
-            platform_bitmap->GetBitmap().rowBytes());
-  EXPECT_EQ(kN32_SkColorType,  // Same for all platforms.
-            platform_bitmap->GetBitmap().colorType());
-  EXPECT_TRUE(platform_bitmap->GetBitmap().lockPixelsAreWritable());
-#if defined(SK_DEBUG)
-  EXPECT_TRUE(platform_bitmap->GetBitmap().pixelRef()->isLocked());
-#endif
-  EXPECT_TRUE(platform_bitmap->GetBitmap().pixelRef()->unique());
-
-  *(platform_bitmap->GetBitmap().getAddr32(10, 20)) = 0xDEED1020;
-  *(platform_bitmap->GetBitmap().getAddr32(20, 30)) = 0xDEED2030;
-
-  SkBitmap sk_bitmap = platform_bitmap->GetBitmap();
-  sk_bitmap.lockPixels();
-
-  EXPECT_FALSE(platform_bitmap->GetBitmap().pixelRef()->unique());
-  EXPECT_FALSE(sk_bitmap.pixelRef()->unique());
-
-  EXPECT_EQ(0xDEED1020, *sk_bitmap.getAddr32(10, 20));
-  EXPECT_EQ(0xDEED2030, *sk_bitmap.getAddr32(20, 30));
-
-  *(platform_bitmap->GetBitmap().getAddr32(30, 40)) = 0xDEED3040;
-
-  // The SkBitmaps derived from a PlatformBitmap must be capable of outliving
-  // the PlatformBitmap.
-  platform_bitmap.reset();
-
-  EXPECT_TRUE(sk_bitmap.pixelRef()->unique());
-
-  EXPECT_EQ(0xDEED1020, *sk_bitmap.getAddr32(10, 20));
-  EXPECT_EQ(0xDEED2030, *sk_bitmap.getAddr32(20, 30));
-  EXPECT_EQ(0xDEED3040, *sk_bitmap.getAddr32(30, 40));
-  sk_bitmap.unlockPixels();
-
-  EXPECT_EQ(NULL, sk_bitmap.getPixels());
-
-  sk_bitmap.lockPixels();
-  EXPECT_EQ(0xDEED1020, *sk_bitmap.getAddr32(10, 20));
-  EXPECT_EQ(0xDEED2030, *sk_bitmap.getAddr32(20, 30));
-  EXPECT_EQ(0xDEED3040, *sk_bitmap.getAddr32(30, 40));
-  sk_bitmap.unlockPixels();
-}
-
-
-}  // namespace skia
diff --git a/skia/ext/platform_device.cc b/skia/ext/platform_device.cc
deleted file mode 100644
index 1a76bc4..0000000
--- a/skia/ext/platform_device.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/logging.h"
-#include "skia/ext/platform_device.h"
-
-#include "third_party/skia/include/core/SkMetaData.h"
-
-namespace skia {
-
-namespace {
-
-const char* kDevicePlatformBehaviour = "CrDevicePlatformBehaviour";
-const char* kDraftModeKey = "CrDraftMode";
-
-#if defined(OS_MACOSX) || defined(OS_WIN)
-const char* kIsPreviewMetafileKey = "CrIsPreviewMetafile";
-#endif
-
-void SetBoolMetaData(const SkCanvas& canvas, const char* key,  bool value) {
-  SkMetaData& meta = skia::getMetaData(canvas);
-  meta.setBool(key, value);
-}
-
-bool GetBoolMetaData(const SkCanvas& canvas, const char* key) {
-  bool value;
-  SkMetaData& meta = skia::getMetaData(canvas);
-  if (!meta.findBool(key, &value))
-    value = false;
-  return value;
-}
-
-}  // namespace
-
-void SetPlatformDevice(SkBaseDevice* device, PlatformDevice* platform_behaviour) {
-  SkMetaData& meta_data = device->getMetaData();
-  meta_data.setPtr(kDevicePlatformBehaviour, platform_behaviour);
-}
-
-PlatformDevice* GetPlatformDevice(SkBaseDevice* device) {
-  if (device) {
-    SkMetaData& meta_data = device->getMetaData();
-    PlatformDevice* device_behaviour = NULL;
-    if (meta_data.findPtr(kDevicePlatformBehaviour,
-                          reinterpret_cast<void**>(&device_behaviour)))
-      return device_behaviour;
-  }
-  return NULL;
-}
-
-SkMetaData& getMetaData(const SkCanvas& canvas) {
-  SkBaseDevice* device = canvas.getDevice();
-  DCHECK(device != NULL);
-  return device->getMetaData();
-}
-
-void SetIsDraftMode(const SkCanvas& canvas, bool draft_mode) {
-  SetBoolMetaData(canvas, kDraftModeKey, draft_mode);
-}
-
-bool IsDraftMode(const SkCanvas& canvas) {
-  return GetBoolMetaData(canvas, kDraftModeKey);
-}
-
-#if defined(OS_MACOSX) || defined(OS_WIN)
-void SetIsPreviewMetafile(const SkCanvas& canvas, bool is_preview) {
-  SetBoolMetaData(canvas, kIsPreviewMetafileKey, is_preview);
-}
-
-bool IsPreviewMetafile(const SkCanvas& canvas) {
-  return GetBoolMetaData(canvas, kIsPreviewMetafileKey);
-}
-#endif
-
-// For platforms without "platform_device_*" specific files,
-// include default behaviors for necessary methods to compile.
-#if defined(OS_NACL)
-PlatformSurface PlatformDevice::BeginPlatformPaint() {
-  return NULL;
-}
-
-void PlatformDevice::EndPlatformPaint() {
-  // By default, do nothing here.
-}
-#endif
-
-bool PlatformDevice::SupportsPlatformPaint() {
-  return true;
-}
-
-}  // namespace skia
diff --git a/skia/ext/platform_device.h b/skia/ext/platform_device.h
deleted file mode 100644
index 464652d..0000000
--- a/skia/ext/platform_device.h
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SKIA_EXT_PLATFORM_DEVICE_H_
-#define SKIA_EXT_PLATFORM_DEVICE_H_
-
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#include <vector>
-#endif
-
-#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/include/core/SkBitmapDevice.h"
-#include "third_party/skia/include/core/SkPreConfig.h"
-
-class SkMatrix;
-class SkMetaData;
-class SkPath;
-class SkRegion;
-
-#if defined(OS_MACOSX)
-typedef struct CGContext* CGContextRef;
-typedef struct CGRect CGRect;
-#endif
-
-namespace skia {
-
-class PlatformDevice;
-
-#if defined(OS_WIN)
-typedef HDC PlatformSurface;
-typedef RECT PlatformRect;
-#elif defined(OS_MACOSX)
-typedef CGContextRef PlatformSurface;
-typedef CGRect PlatformRect;
-#else
-typedef void* PlatformSurface;
-typedef SkIRect* PlatformRect;
-#endif
-
-// The following routines provide accessor points for the functionality
-// exported by the various PlatformDevice ports.  
-// All calls to PlatformDevice::* should be routed through these 
-// helper functions.
-
-// Bind a PlatformDevice instance, |platform_device| to |device|.  Subsequent
-// calls to the functions exported below will forward the request to the
-// corresponding method on the bound PlatformDevice instance.    If no
-// PlatformDevice has been bound to the SkBaseDevice passed, then the 
-// routines are NOPS.
-SK_API void SetPlatformDevice(SkBaseDevice* device,
-                              PlatformDevice* platform_device);
-SK_API PlatformDevice* GetPlatformDevice(SkBaseDevice* device);
-
-
-#if defined(OS_WIN)
-// Initializes the default settings and colors in a device context.
-SK_API void InitializeDC(HDC context);
-#elif defined(OS_MACOSX)
-// Returns the CGContext that backing the SkBaseDevice.  Forwards to the bound
-// PlatformDevice.  Returns NULL if no PlatformDevice is bound.
-SK_API CGContextRef GetBitmapContext(SkBaseDevice* device);
-#endif
-
-// Following routines are used in print preview workflow to mark the draft mode
-// metafile and preview metafile.
-SK_API SkMetaData& getMetaData(const SkCanvas& canvas);
-SK_API void SetIsDraftMode(const SkCanvas& canvas, bool draft_mode);
-SK_API bool IsDraftMode(const SkCanvas& canvas);
-
-#if defined(OS_MACOSX) || defined(OS_WIN)
-SK_API void SetIsPreviewMetafile(const SkCanvas& canvas, bool is_preview);
-SK_API bool IsPreviewMetafile(const SkCanvas& canvas);
-#endif
-
-// A SkBitmapDevice is basically a wrapper around SkBitmap that provides a 
-// surface for SkCanvas to draw into. PlatformDevice provides a surface 
-// Windows can also write to. It also provides functionality to play well 
-// with GDI drawing functions. This class is abstract and must be subclassed. 
-// It provides the basic interface to implement it either with or without 
-// a bitmap backend.
-//
-// PlatformDevice provides an interface which sub-classes of SkBaseDevice can 
-// also provide to allow for drawing by the native platform into the device.
-// TODO(robertphillips): Once the bitmap-specific entry points are removed
-// from SkBaseDevice it might make sense for PlatformDevice to be derived
-// from it.
-class SK_API PlatformDevice {
- public:
-  virtual ~PlatformDevice() {}
-
-#if defined(OS_MACOSX)
-  // The CGContext that corresponds to the bitmap, used for CoreGraphics
-  // operations drawing into the bitmap. This is possibly heavyweight, so it
-  // should exist only during one pass of rendering.
-  virtual CGContextRef GetBitmapContext() = 0;
-#endif
-
-  // The DC that corresponds to the bitmap, used for GDI operations drawing
-  // into the bitmap. This is possibly heavyweight, so it should be existant
-  // only during one pass of rendering.
-  virtual PlatformSurface BeginPlatformPaint();
-
-  // Finish a previous call to beginPlatformPaint.
-  virtual void EndPlatformPaint();
-
-  // Returns true if GDI operations can be used for drawing into the bitmap.
-  virtual bool SupportsPlatformPaint();
-
-#if defined(OS_WIN)
-  // Loads a SkPath into the GDI context. The path can there after be used for
-  // clipping or as a stroke. Returns false if the path failed to be loaded.
-  static bool LoadPathToDC(HDC context, const SkPath& path);
-
-  // Loads a SkRegion into the GDI context.
-  static void LoadClippingRegionToDC(HDC context, const SkRegion& region,
-                                     const SkMatrix& transformation);
-
-  // Draws to the given screen DC, if the bitmap DC doesn't exist, this will
-  // temporarily create it. However, if you have created the bitmap DC, it will
-  // be more efficient if you don't free it until after this call so it doesn't
-  // have to be created twice.  If src_rect is null, then the entirety of the
-  // source device will be copied.
-  virtual void DrawToHDC(HDC, int x, int y, const RECT* src_rect);
-#endif
-
- protected:
-#if defined(OS_WIN)
-  // Arrays must be inside structures.
-  struct CubicPoints {
-    SkPoint p[4];
-  };
-  typedef std::vector<CubicPoints> CubicPath;
-  typedef std::vector<CubicPath> CubicPaths;
-
-  // Loads the specified Skia transform into the device context, excluding
-  // perspective (which GDI doesn't support).
-  static void LoadTransformToDC(HDC dc, const SkMatrix& matrix);
-
-  // Transforms SkPath's paths into a series of cubic path.
-  static bool SkPathToCubicPaths(CubicPaths* paths, const SkPath& skpath);
-#endif
-};
-
-}  // namespace skia
-
-#endif  // SKIA_EXT_PLATFORM_DEVICE_H_
diff --git a/skia/ext/platform_device_linux.cc b/skia/ext/platform_device_linux.cc
deleted file mode 100644
index f72e614..0000000
--- a/skia/ext/platform_device_linux.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/platform_device.h"
-
-namespace skia {
-
-PlatformSurface PlatformDevice::BeginPlatformPaint() {
-  return NULL;
-}
-
-void PlatformDevice::EndPlatformPaint() {
-  // We don't need to do anything on Linux here.
-}
-
-}  // namespace skia
diff --git a/skia/ext/platform_device_mac.cc b/skia/ext/platform_device_mac.cc
deleted file mode 100644
index 065b767..0000000
--- a/skia/ext/platform_device_mac.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/platform_device.h"
-#include "skia/ext/bitmap_platform_device.h"
-
-#import <ApplicationServices/ApplicationServices.h>
-#include "skia/ext/skia_utils_mac.h"
-#include "third_party/skia/include/core/SkMatrix.h"
-#include "third_party/skia/include/core/SkPath.h"
-#include "third_party/skia/include/core/SkTypes.h"
-#include "third_party/skia/include/core/SkUtils.h"
-
-namespace skia {
-
-CGContextRef GetBitmapContext(SkBaseDevice* device) {
-  PlatformDevice* platform_device = GetPlatformDevice(device);
-  if (platform_device)
-    return platform_device->GetBitmapContext();
-
-  return NULL;
-}
-
-CGContextRef PlatformDevice::BeginPlatformPaint() {
-  return GetBitmapContext();
-}
-
-void PlatformDevice::EndPlatformPaint() {
-  // Flushing will be done in onAccessBitmap.
-}
-
-}  // namespace skia
diff --git a/skia/ext/platform_device_win.cc b/skia/ext/platform_device_win.cc
deleted file mode 100644
index ef48fbd..0000000
--- a/skia/ext/platform_device_win.cc
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/platform_device.h"
-
-#include "skia/ext/skia_utils_win.h"
-#include "third_party/skia/include/core/SkMatrix.h"
-#include "third_party/skia/include/core/SkPath.h"
-#include "third_party/skia/include/core/SkRegion.h"
-#include "third_party/skia/include/core/SkUtils.h"
-
-namespace skia {
-
-void InitializeDC(HDC context) {
-  // Enables world transformation.
-  // If the GM_ADVANCED graphics mode is set, GDI always draws arcs in the
-  // counterclockwise direction in logical space. This is equivalent to the
-  // statement that, in the GM_ADVANCED graphics mode, both arc control points
-  // and arcs themselves fully respect the device context's world-to-device
-  // transformation.
-  BOOL res = SetGraphicsMode(context, GM_ADVANCED);
-  SkASSERT(res != 0);
-
-  // Enables dithering.
-  res = SetStretchBltMode(context, HALFTONE);
-  SkASSERT(res != 0);
-  // As per SetStretchBltMode() documentation, SetBrushOrgEx() must be called
-  // right after.
-  res = SetBrushOrgEx(context, 0, 0, NULL);
-  SkASSERT(res != 0);
-
-  // Sets up default orientation.
-  res = SetArcDirection(context, AD_CLOCKWISE);
-  SkASSERT(res != 0);
-
-  // Sets up default colors.
-  res = SetBkColor(context, RGB(255, 255, 255));
-  SkASSERT(res != CLR_INVALID);
-  res = SetTextColor(context, RGB(0, 0, 0));
-  SkASSERT(res != CLR_INVALID);
-  res = SetDCBrushColor(context, RGB(255, 255, 255));
-  SkASSERT(res != CLR_INVALID);
-  res = SetDCPenColor(context, RGB(0, 0, 0));
-  SkASSERT(res != CLR_INVALID);
-
-  // Sets up default transparency.
-  res = SetBkMode(context, OPAQUE);
-  SkASSERT(res != 0);
-  res = SetROP2(context, R2_COPYPEN);
-  SkASSERT(res != 0);
-}
-
-PlatformSurface PlatformDevice::BeginPlatformPaint() {
-  return 0;
-}
-
-void PlatformDevice::EndPlatformPaint() {
-  // We don't clear the DC here since it will be likely to be used again.
-  // Flushing will be done in onAccessBitmap.
-}
-
-// static
-bool PlatformDevice::LoadPathToDC(HDC context, const SkPath& path) {
-  switch (path.getFillType()) {
-    case SkPath::kWinding_FillType: {
-      int res = SetPolyFillMode(context, WINDING);
-      SkASSERT(res != 0);
-      break;
-    }
-    case SkPath::kEvenOdd_FillType: {
-      int res = SetPolyFillMode(context, ALTERNATE);
-      SkASSERT(res != 0);
-      break;
-    }
-    default: {
-      SkASSERT(false);
-      break;
-    }
-  }
-  BOOL res = BeginPath(context);
-  if (!res) {
-      return false;
-  }
-
-  CubicPaths paths;
-  if (!SkPathToCubicPaths(&paths, path))
-    return false;
-
-  std::vector<POINT> points;
-  for (CubicPaths::const_iterator path(paths.begin()); path != paths.end();
-       ++path) {
-    if (!path->size())
-      continue;
-    points.resize(0);
-    points.reserve(path->size() * 3 / 4 + 1);
-    points.push_back(SkPointToPOINT(path->front().p[0]));
-    for (CubicPath::const_iterator point(path->begin()); point != path->end();
-       ++point) {
-      // Never add point->p[0]
-      points.push_back(SkPointToPOINT(point->p[1]));
-      points.push_back(SkPointToPOINT(point->p[2]));
-      points.push_back(SkPointToPOINT(point->p[3]));
-    }
-    SkASSERT((points.size() - 1) % 3 == 0);
-    // This is slightly inefficient since all straight line and quadratic lines
-    // are "upgraded" to a cubic line.
-    // TODO(maruel):  http://b/1147346 We should use
-    // PolyDraw/PolyBezier/Polyline whenever possible.
-    res = PolyBezier(context, &points.front(),
-                     static_cast<DWORD>(points.size()));
-    SkASSERT(res != 0);
-    if (res == 0)
-      break;
-  }
-  if (res == 0) {
-    // Make sure the path is discarded.
-    AbortPath(context);
-  } else {
-    res = EndPath(context);
-    SkASSERT(res != 0);
-  }
-  return true;
-}
-
-// static
-void PlatformDevice::LoadTransformToDC(HDC dc, const SkMatrix& matrix) {
-  XFORM xf;
-  xf.eM11 = matrix[SkMatrix::kMScaleX];
-  xf.eM21 = matrix[SkMatrix::kMSkewX];
-  xf.eDx = matrix[SkMatrix::kMTransX];
-  xf.eM12 = matrix[SkMatrix::kMSkewY];
-  xf.eM22 = matrix[SkMatrix::kMScaleY];
-  xf.eDy = matrix[SkMatrix::kMTransY];
-  SetWorldTransform(dc, &xf);
-}
-
-// static
-bool PlatformDevice::SkPathToCubicPaths(CubicPaths* paths,
-                                        const SkPath& skpath) {
-  paths->clear();
-  CubicPath* current_path = NULL;
-  SkPoint current_points[4];
-  CubicPoints points_to_add;
-  SkPath::Iter iter(skpath, false);
-  for (SkPath::Verb verb = iter.next(current_points);
-       verb != SkPath::kDone_Verb;
-       verb = iter.next(current_points)) {
-    switch (verb) {
-      case SkPath::kMove_Verb: {  // iter.next returns 1 point
-        // Ignores it since the point is copied in the next operation. See
-        // SkPath::Iter::next() for reference.
-        paths->push_back(CubicPath());
-        current_path = &paths->back();
-        // Skip point addition.
-        continue;
-      }
-      case SkPath::kLine_Verb: {  // iter.next returns 2 points
-        points_to_add.p[0] = current_points[0];
-        points_to_add.p[1] = current_points[0];
-        points_to_add.p[2] = current_points[1];
-        points_to_add.p[3] = current_points[1];
-        break;
-      }
-      case SkPath::kQuad_Verb: {  // iter.next returns 3 points
-        points_to_add.p[0] = current_points[0];
-        points_to_add.p[1] = current_points[1];
-        points_to_add.p[2] = current_points[2];
-        points_to_add.p[3] = current_points[2];
-        break;
-      }
-      case SkPath::kCubic_Verb: {  // iter.next returns 4 points
-        points_to_add.p[0] = current_points[0];
-        points_to_add.p[1] = current_points[1];
-        points_to_add.p[2] = current_points[2];
-        points_to_add.p[3] = current_points[3];
-        break;
-      }
-      case SkPath::kClose_Verb: {  // iter.next returns 1 point (the last point)
-        paths->push_back(CubicPath());
-        current_path = &paths->back();
-        continue;
-      }
-      default: {
-        current_path = NULL;
-        // Will return false.
-        break;
-      }
-    }
-    SkASSERT(current_path);
-    if (!current_path) {
-      paths->clear();
-      return false;
-    }
-    current_path->push_back(points_to_add);
-  }
-  return true;
-}
-
-// static
-void PlatformDevice::LoadClippingRegionToDC(HDC context,
-                                            const SkRegion& region,
-                                            const SkMatrix& transformation) {
-  HRGN hrgn;
-  if (region.isEmpty()) {
-    // region can be empty, in which case everything will be clipped.
-    hrgn = CreateRectRgn(0, 0, 0, 0);
-  } else if (region.isRect()) {
-    // We don't apply transformation, because the translation is already applied
-    // to the region.
-    hrgn = CreateRectRgnIndirect(&SkIRectToRECT(region.getBounds()));
-  } else {
-    // It is complex.
-    SkPath path;
-    region.getBoundaryPath(&path);
-    // Clip. Note that windows clipping regions are not affected by the
-    // transform so apply it manually.
-    // Since the transform is given as the original translation of canvas, we
-    // should apply it in reverse.
-    SkMatrix t(transformation);
-    t.setTranslateX(-t.getTranslateX());
-    t.setTranslateY(-t.getTranslateY());
-    path.transform(t);
-    LoadPathToDC(context, path);
-    hrgn = PathToRegion(context);
-  }
-  int result = SelectClipRgn(context, hrgn);
-  SkASSERT(result != ERROR);
-  result = DeleteObject(hrgn);
-  SkASSERT(result != 0);
-}
-
-}  // namespace skia
diff --git a/skia/ext/refptr.h b/skia/ext/refptr.h
deleted file mode 100644
index a3900f6..0000000
--- a/skia/ext/refptr.h
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SKIA_EXT_REFPTR_H_
-#define SKIA_EXT_REFPTR_H_
-
-#include "third_party/skia/include/core/SkRefCnt.h"
-
-namespace skia {
-
-// When creating/receiving a ref-counted pointer from Skia, wrap that pointer in
-// this class to avoid dealing with the ref-counting and prevent leaks/crashes
-// due to ref-counting bugs.
-//
-// Example of creating a new SkShader* and setting it on a SkPaint:
-//   skia::RefPtr<SkShader> shader = skia::AdoptRef(SkGradientShader::Create());
-//   paint.setShader(shader.get());
-//
-// When passing around a ref-counted pointer to methods outside of Skia, always
-// pass around the skia::RefPtr instead of the raw pointer. An example method
-// that takes a SkShader* parameter and saves the SkShader* in the class.
-//   void AMethodThatSavesAShader(const skia::RefPtr<SkShader>& shader) {
-//     member_refptr_ = shader;
-//   }
-//   skia::RefPtr<SkShader> member_refptr_;
-//
-// When returning a ref-counted pointer, also return the skia::RefPtr instead.
-// An example method that creates an SkShader* and returns it:
-//   skia::RefPtr<SkShader> MakeAShader() {
-//     return skia::AdoptRef(SkGradientShader::Create());
-//   }
-//
-// To take a scoped reference to an object whose references are all owned
-// by other objects (i.e. does not have one that needs to be adopted) use the
-// skia::SharePtr helper:
-//
-//   skia::RefPtr<SkShader> shader = skia::SharePtr(paint.getShader());
-//
-// Never call ref() or unref() on the underlying ref-counted pointer. If you
-// AdoptRef() the raw pointer immediately into a skia::RefPtr and always work
-// with skia::RefPtr instances instead, the ref-counting will be taken care of
-// for you.
-template<typename T>
-class RefPtr {
- public:
-  RefPtr() : ptr_(NULL) {}
-
-  RefPtr(const RefPtr& other)
-      : ptr_(other.get()) {
-    SkSafeRef(ptr_);
-  }
-
-  template<typename U>
-  RefPtr(const RefPtr<U>& other)
-      : ptr_(other.get()) {
-    SkSafeRef(ptr_);
-  }
-
-  ~RefPtr() {
-    clear();
-  }
-
-  RefPtr& operator=(const RefPtr& other) {
-    SkRefCnt_SafeAssign(ptr_, other.get());
-    return *this;
-  }
-
-  template<typename U>
-  RefPtr& operator=(const RefPtr<U>& other) {
-    SkRefCnt_SafeAssign(ptr_, other.get());
-    return *this;
-  }
-
-  void clear() {
-    T* to_unref = ptr_;
-    ptr_ = NULL;
-    SkSafeUnref(to_unref);
-  }
-
-  T* get() const { return ptr_; }
-  T& operator*() const { return *ptr_; }
-  T* operator->() const { return ptr_; }
-
-  typedef T* RefPtr::*unspecified_bool_type;
-  operator unspecified_bool_type() const {
-    return ptr_ ? &RefPtr::ptr_ : NULL;
-  }
-
- private:
-  T* ptr_;
-
-  // This function cannot be public because Skia starts its ref-counted
-  // objects at refcnt=1.  This makes it impossible to differentiate
-  // between a newly created object (that doesn't need to be ref'd) or an
-  // already existing object with one owner (that does need to be ref'd so that
-  // this RefPtr can also manage its lifetime).
-  explicit RefPtr(T* ptr) : ptr_(ptr) {}
-
-  template<typename U>
-  friend RefPtr<U> AdoptRef(U* ptr);
-
-  template<typename U>
-  friend RefPtr<U> SharePtr(U* ptr);
-};
-
-// For objects that have an unowned reference (such as newly created objects).
-template<typename T>
-RefPtr<T> AdoptRef(T* ptr) { return RefPtr<T>(ptr); }
-
-// For objects that are already owned. This doesn't take ownership of existing
-// references and adds a new one.
-template<typename T>
-RefPtr<T> SharePtr(T* ptr) { return RefPtr<T>(SkSafeRef(ptr)); }
-
-}  // namespace skia
-
-#endif  // SKIA_EXT_REFPTR_H_
diff --git a/skia/ext/refptr_unittest.cc b/skia/ext/refptr_unittest.cc
deleted file mode 100644
index bf54b03..0000000
--- a/skia/ext/refptr_unittest.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/refptr.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace skia {
-namespace {
-
-TEST(RefPtrTest, ReferenceCounting) {
-  SkRefCnt* ref = new SkRefCnt();
-  EXPECT_TRUE(ref->unique());
-
-  {
-    // Adopt the reference from the caller on creation.
-    RefPtr<SkRefCnt> refptr1 = AdoptRef(ref);
-    EXPECT_TRUE(ref->unique());
-    EXPECT_TRUE(refptr1->unique());
-
-    EXPECT_EQ(ref, &*refptr1);
-    EXPECT_EQ(ref, refptr1.get());
-
-    {
-      // Take a second reference for the second instance.
-      RefPtr<SkRefCnt> refptr2(refptr1);
-      EXPECT_FALSE(ref->unique());
-
-      RefPtr<SkRefCnt> refptr3;
-      EXPECT_FALSE(refptr3);
-
-      // Take a third reference for the third instance.
-      refptr3 = refptr1;
-      EXPECT_FALSE(ref->unique());
-
-      // Same object, so should have the same refcount.
-      refptr2 = refptr3;
-      EXPECT_FALSE(ref->unique());
-
-      // Drop the object from refptr2, so it should lose its reference.
-      EXPECT_TRUE(refptr2);
-      refptr2.clear();
-      EXPECT_FALSE(ref->unique());
-
-      EXPECT_FALSE(refptr2);
-      EXPECT_EQ(NULL, refptr2.get());
-
-      EXPECT_TRUE(refptr3);
-      EXPECT_FALSE(refptr3->unique());
-      EXPECT_EQ(ref, &*refptr3);
-      EXPECT_EQ(ref, refptr3.get());
-    }
-
-    // Drop a reference when the third object is destroyed.
-    EXPECT_TRUE(ref->unique());
-  }
-}
-
-TEST(RefPtrTest, Construct) {
-  SkRefCnt* ref = new SkRefCnt();
-  EXPECT_TRUE(ref->unique());
-
-  // Adopt the reference from the caller on creation.
-  RefPtr<SkRefCnt> refptr1(AdoptRef(ref));
-  EXPECT_TRUE(ref->unique());
-  EXPECT_TRUE(refptr1->unique());
-
-  EXPECT_EQ(ref, &*refptr1);
-  EXPECT_EQ(ref, refptr1.get());
-
-  RefPtr<SkRefCnt> refptr2(refptr1);
-  EXPECT_FALSE(ref->unique());
-}
-
-TEST(RefPtrTest, DeclareAndAssign) {
-  SkRefCnt* ref = new SkRefCnt();
-  EXPECT_TRUE(ref->unique());
-
-  // Adopt the reference from the caller on creation.
-  RefPtr<SkRefCnt> refptr1 = AdoptRef(ref);
-  EXPECT_TRUE(ref->unique());
-  EXPECT_TRUE(refptr1->unique());
-
-  EXPECT_EQ(ref, &*refptr1);
-  EXPECT_EQ(ref, refptr1.get());
-
-  RefPtr<SkRefCnt> refptr2 = refptr1;
-  EXPECT_FALSE(ref->unique());
-}
-
-TEST(RefPtrTest, Assign) {
-  SkRefCnt* ref = new SkRefCnt();
-  EXPECT_TRUE(ref->unique());
-
-  // Adopt the reference from the caller on creation.
-  RefPtr<SkRefCnt> refptr1;
-  refptr1 = AdoptRef(ref);
-  EXPECT_TRUE(ref->unique());
-  EXPECT_TRUE(refptr1->unique());
-
-  EXPECT_EQ(ref, &*refptr1);
-  EXPECT_EQ(ref, refptr1.get());
-
-  RefPtr<SkRefCnt> refptr2;
-  refptr2 = refptr1;
-  EXPECT_FALSE(ref->unique());
-}
-
-class Subclass : public SkRefCnt {};
-
-TEST(RefPtrTest, Upcast) {
-  RefPtr<Subclass> child = AdoptRef(new Subclass());
-  EXPECT_TRUE(child->unique());
-
-  RefPtr<SkRefCnt> parent = child;
-  EXPECT_TRUE(child);
-  EXPECT_TRUE(parent);
-
-  EXPECT_FALSE(child->unique());
-  EXPECT_FALSE(parent->unique());
-}
-
-}  // namespace
-}  // namespace skia
diff --git a/skia/ext/skia_utils_base.cc b/skia/ext/skia_utils_base.cc
deleted file mode 100644
index 6643b49..0000000
--- a/skia/ext/skia_utils_base.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/skia_utils_base.h"
-
-namespace skia {
-
-bool ReadSkString(base::PickleIterator* iter, SkString* str) {
-  int reply_length;
-  const char* reply_text;
-
-  if (!iter->ReadData(&reply_text, &reply_length))
-    return false;
-
-  if (str)
-    str->set(reply_text, reply_length);
-  return true;
-}
-
-bool ReadSkFontIdentity(base::PickleIterator* iter,
-                        SkFontConfigInterface::FontIdentity* identity) {
-  uint32_t reply_id;
-  uint32_t reply_ttcIndex;
-  int reply_length;
-  const char* reply_text;
-
-  if (!iter->ReadUInt32(&reply_id) ||
-      !iter->ReadUInt32(&reply_ttcIndex) ||
-      !iter->ReadData(&reply_text, &reply_length))
-    return false;
-
-  if (identity) {
-    identity->fID = reply_id;
-    identity->fTTCIndex = reply_ttcIndex;
-    identity->fString.set(reply_text, reply_length);
-  }
-  return true;
-}
-
-bool WriteSkString(base::Pickle* pickle, const SkString& str) {
-  return pickle->WriteData(str.c_str(), str.size());
-}
-
-bool WriteSkFontIdentity(base::Pickle* pickle,
-                         const SkFontConfigInterface::FontIdentity& identity) {
-  return pickle->WriteUInt32(identity.fID) &&
-         pickle->WriteUInt32(identity.fTTCIndex) &&
-         WriteSkString(pickle, identity.fString);
-}
-
-}  // namespace skia
-
diff --git a/skia/ext/skia_utils_base.h b/skia/ext/skia_utils_base.h
deleted file mode 100644
index f37fbf2..0000000
--- a/skia/ext/skia_utils_base.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SKIA_EXT_SKIA_UTILS_BASE_H_
-#define SKIA_EXT_SKIA_UTILS_BASE_H_
-
-#include "base/pickle.h"
-#include "third_party/skia/include/ports/SkFontConfigInterface.h"
-
-namespace skia {
-
-// Return true if the pickle/iterator contains a string. If so, and if str
-// is not null, copy that string into str.
-SK_API bool ReadSkString(base::PickleIterator* iter, SkString* str);
-
-// Return true if the pickle/iterator contains a FontIdentity. If so, and if
-// identity is not null, copy it into identity.
-SK_API bool ReadSkFontIdentity(base::PickleIterator* iter,
-                               SkFontConfigInterface::FontIdentity* identity);
-
-// Return true if str can be written into the request pickle.
-SK_API bool WriteSkString(base::Pickle* pickle, const SkString& str);
-
-// Return true if identity can be written into the request pickle.
-SK_API bool WriteSkFontIdentity(
-    base::Pickle* pickle,
-    const SkFontConfigInterface::FontIdentity& identity);
-
-}  // namespace skia
-
-#endif  // SKIA_EXT_SKIA_UTILS_BASE_H_
-
diff --git a/skia/ext/skia_utils_ios.h b/skia/ext/skia_utils_ios.h
deleted file mode 100644
index 6a854ce..0000000
--- a/skia/ext/skia_utils_ios.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SKIA_EXT_SKIA_UTILS_IOS_H_
-#define SKIA_EXT_SKIA_UTILS_IOS_H_
-
-#include <CoreGraphics/CoreGraphics.h>
-#include <vector>
-
-#include "third_party/skia/include/core/SkBitmap.h"
-
-#ifdef __OBJC__
-@class UIImage;
-@class NSData;
-#else
-class UIImage;
-class NSData;
-#endif
-
-namespace gfx {
-
-// Draws a CGImage into an SkBitmap of the given size.
-SK_API SkBitmap CGImageToSkBitmap(CGImageRef image,
-                                  CGSize size,
-                                  bool is_opaque);
-
-// Given an SkBitmap and a color space, return an autoreleased UIImage.
-SK_API UIImage* SkBitmapToUIImageWithColorSpace(const SkBitmap& skia_bitmap,
-                                                CGFloat scale,
-                                                CGColorSpaceRef color_space);
-
-// Decodes all image representations inside the data into a vector of SkBitmaps.
-// Returns a vector of all the successfully decoded representations or an empty
-// vector if none can be decoded.
-SK_API std::vector<SkBitmap> ImageDataToSkBitmaps(NSData* image_data);
-
-}  // namespace gfx
-
-#endif  // SKIA_EXT_SKIA_UTILS_IOS_H_
diff --git a/skia/ext/skia_utils_ios.mm b/skia/ext/skia_utils_ios.mm
deleted file mode 100644
index 5655d22..0000000
--- a/skia/ext/skia_utils_ios.mm
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/skia_utils_ios.h"
-
-#import <ImageIO/ImageIO.h>
-#import <UIKit/UIKit.h>
-
-#include "base/ios/ios_util.h"
-#include "base/logging.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/macros.h"
-#include "third_party/skia/include/utils/mac/SkCGUtils.h"
-
-namespace {
-
-const uint8 kICOHeaderMagic[4] = {0x00, 0x00, 0x01, 0x00};
-
-// Returns whether the data encodes an ico image.
-bool EncodesIcoImage(NSData* image_data) {
-  if (image_data.length < arraysize(kICOHeaderMagic))
-    return false;
-  return memcmp(kICOHeaderMagic, image_data.bytes,
-                arraysize(kICOHeaderMagic)) == 0;
-}
-
-}  // namespace
-
-namespace gfx {
-
-SkBitmap CGImageToSkBitmap(CGImageRef image, CGSize size, bool is_opaque) {
-  SkBitmap bitmap;
-  if (!image)
-    return bitmap;
-
-  if (!bitmap.tryAllocN32Pixels(size.width, size.height, is_opaque))
-    return bitmap;
-
-  void* data = bitmap.getPixels();
-
-  // Allocate a bitmap context with 4 components per pixel (BGRA). Apple
-  // recommends these flags for improved CG performance.
-#define HAS_ARGB_SHIFTS(a, r, g, b) \
-            (SK_A32_SHIFT == (a) && SK_R32_SHIFT == (r) \
-             && SK_G32_SHIFT == (g) && SK_B32_SHIFT == (b))
-#if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0)
-  base::ScopedCFTypeRef<CGColorSpaceRef> color_space(
-      CGColorSpaceCreateDeviceRGB());
-  base::ScopedCFTypeRef<CGContextRef> context(CGBitmapContextCreate(
-      data,
-      size.width,
-      size.height,
-      8,
-      size.width * 4,
-      color_space,
-      kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
-#else
-#error We require that Skia's and CoreGraphics's recommended \
-       image memory layout match.
-#endif
-#undef HAS_ARGB_SHIFTS
-
-  DCHECK(context);
-  if (!context)
-    return bitmap;
-
-  CGRect imageRect = CGRectMake(0.0, 0.0, size.width, size.height);
-  CGContextSetBlendMode(context, kCGBlendModeCopy);
-  CGContextDrawImage(context, imageRect, image);
-
-  return bitmap;
-}
-
-UIImage* SkBitmapToUIImageWithColorSpace(const SkBitmap& skia_bitmap,
-                                         CGFloat scale,
-                                         CGColorSpaceRef color_space) {
-  if (skia_bitmap.isNull())
-    return nil;
-
-  // First convert SkBitmap to CGImageRef.
-  base::ScopedCFTypeRef<CGImageRef> cg_image(
-      SkCreateCGImageRefWithColorspace(skia_bitmap, color_space));
-
-  // Now convert to UIImage.
-  return [UIImage imageWithCGImage:cg_image.get()
-                             scale:scale
-                       orientation:UIImageOrientationUp];
-}
-
-std::vector<SkBitmap> ImageDataToSkBitmaps(NSData* image_data) {
-  DCHECK(image_data);
-
-  // On iOS 8.1.1 |CGContextDrawImage| crashes when processing images included
-  // in .ico files that are 88x88 pixels or larger (http://crbug.com/435068).
-  bool skip_images_88x88_or_larger =
-      base::ios::IsRunningOnOrLater(8, 1, 1) && EncodesIcoImage(image_data);
-
-  base::ScopedCFTypeRef<CFDictionaryRef> empty_dictionary(
-      CFDictionaryCreate(NULL, NULL, NULL, 0, NULL, NULL));
-  std::vector<SkBitmap> frames;
-
-  base::ScopedCFTypeRef<CGImageSourceRef> source(
-      CGImageSourceCreateWithData((CFDataRef)image_data, empty_dictionary));
-
-  size_t count = CGImageSourceGetCount(source);
-  for (size_t index = 0; index < count; ++index) {
-    base::ScopedCFTypeRef<CGImageRef> cg_image(
-        CGImageSourceCreateImageAtIndex(source, index, empty_dictionary));
-
-    CGSize size = CGSizeMake(CGImageGetWidth(cg_image),
-                             CGImageGetHeight(cg_image));
-    if (size.width >= 88 && size.height >= 88 && skip_images_88x88_or_larger)
-      continue;
-
-    const SkBitmap bitmap = CGImageToSkBitmap(cg_image, size, false);
-    if (!bitmap.empty())
-      frames.push_back(bitmap);
-  }
-
-  DLOG_IF(WARNING, frames.size() != count) << "Only decoded " << frames.size()
-      << " frames for " << count << " expected.";
-  return frames;
-}
-
-}  // namespace gfx
diff --git a/skia/ext/skia_utils_ios_unittest.mm b/skia/ext/skia_utils_ios_unittest.mm
deleted file mode 100644
index 71f46a4..0000000
--- a/skia/ext/skia_utils_ios_unittest.mm
+++ /dev/null
@@ -1,753 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/skia_utils_ios.h"
-
-#import <ImageIO/ImageIO.h>
-#import <UIKit/UIKit.h>
-
-#include "base/base64.h"
-#include "base/ios/ios_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-typedef testing::Test SkiaUtilsIosTest;
-
-// This is a base64 encoded version of google.com ico file. generated by
-// curl http://www.google.com/favicon.ico | base64 -b 76
-const char kIcoEncodedData[] =
-  "AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAA"
-  "AAAEAAASCwAAEgsAAAAAAAAAAAAA9IVCSvSFQuf0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQv/0hUL/9IVC//SFQv/0hULk9IVCSvSFQub0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0"
-  "hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQuf0hUL/9IVC//SFQv/0hUL/9Y1O//rI"
-  "q//+7+f//eXX//vUvf/7z7X/96Fu//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC"
-  "//vYwv/97OH/9ZRZ//SFQv/0hUL/9IhG//zbx//3om7/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQv/97uX/+buW//SFQv/0hUL/9IVC//SFQv/5upT/+9O6//SFQv/0hUL/9IVC//SFQv/0"
-  "hUL/9IVC//SFQv/0hUL/+b6b//zezP/0iEf/9IVC//SFQv/1klf//ezh//vPtP/0hUL/9IVC//SF"
-  "Qv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/3qXr/+siq//m8lv/5wqD//vTu//3t4//1klb/9IVC"
-  "//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0h0b//vbx//zi0//1j1H/"
-  "9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/2nmn/+bmS/////v/4"
-  "sIX/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/5uJH///v5//eo"
-  "ef/1jU//+82y//afav/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL//vXw"
-  "//vOs//0hUL/9IVC//ekcf/96+D/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//728v/4sIX/9IVC//SFQv/4s4n///v4//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0"
-  "hUL/9IVC//SFQv/6yKn/+byX//SFQv/0hkT//eTV//vWv//0hUL/9IVC//SFQv/0hUL/9IVC//SF"
-  "Qv/0hUL/9IVC//SFQv/0hUL/9IZE//m6lP/5u5b//OHQ///+/f/6y6//96d3//SFQv/0hUL/9IVC"
-  "//SFQv/0hULm9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQv/0hULm9IVCSfSFQub0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0"
-  "hUL/9IVC//SFQv/0hULm9IVCSQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAASCwAAEgsA"
-  "AAAAAAAAAAAA9IVCAPSFQif0hUKt9IVC8vSFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0"
-  "hUL/9IVC//SFQvL0hUKt9IVCJ/SFQgD0hUIo9IVC7/SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SF"
-  "Qv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC"
-  "//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hULv9IVCKPSFQq30hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0"
-  "hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUKt9IVC8fSF"
-  "Qv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC"
-  "//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQvP0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9YtL//i2jv/8"
-  "28f//vLr///7+P///Pv//vTu//3n2v/6zbH/96Nw//SFQ//0hUL/9IVC//SFQv/0hUL/9IVC//SF"
-  "Qv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC"
-  "//ekcv/+8+z////////////+9fD/+9K5//m9mf/4to7/+buV//vSuf/++PT//OPT//aYYP/0hUL/"
-  "9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0"
-  "hUL/9IVC//SFQv/2l13///r3/////////fv/+b2Z//SIRv/0hUL/9IVC//SFQv/0hUL/9IVC//WN"
-  "T//84M///vXv//aZYf/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC"
-  "//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//vPtP////////////i0i//0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQv/0hUL/9IVC//WQUv///Pr//OPU//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0"
-  "hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL//eTV///////+9O7/9IVD//SF"
-  "Qv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//3m2P//////9ppi//SFQv/0hUL/9IVC"
-  "//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/718H/"
-  "//////3s4f/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL//vDn///////4"
-  "soj/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SF"
-  "Qv/0hUL/9IVC//erff////////38//WTWP/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC"
-  "//iziv////////////iwhf/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//rMsP///////eXW//WSVv/0hUL/9IVC//SFQv/0"
-  "hUL/9IVC//SFQv/4sYb///z7/////////Pv/9ZFV//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SF"
-  "Qv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//ixhv/+8Of//vn1"
-  "//rMsP/4rH//9plh//WQUv/1j1L/+s2x//////////////////m9mf/0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0"
-  "hUL/9IVC//SGQ//2nmn/+buW//vNsv/82sb//e3j/////////////////////v/5wZ//9IVC//SF"
-  "Qv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC"
-  "//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/83Mj////////////++fb/"
-  "+K+C//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0"
-  "hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9ZRZ////"
-  "/////////vTt//aaYv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC"
-  "//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQv/1lFr////////////6xqf/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0"
-  "hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SF"
-  "Qv/0hUL/9IVC//ehbf/70bj//end//3o2////v3///////3l1//0iEb/9IVC//SFQv/0hUL/9IVC"
-  "//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQv/0hUL/9IVC//SFQv/5wqD////////////96t7/96Z2//WOUP/2nWf//NvH//zcyP/1"
-  "i0z/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SF"
-  "Qv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/96l6/////////////vLr//WPUf/0hUL/9IVC"
-  "//SFQv/0h0b//end//3k1f/0iUn/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/8387////////////4"
-  "sYf/9IVC//SFQv/0hUL/9IVC//SFQv/6w6L///////nBn//0hUL/9IVC//SFQv/0hUL/9IVC//SF"
-  "Qv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC"
-  "///69////////vj1//SIR//0hUL/9IVC//SFQv/0hUL/9IVC//m+mv///////e3j//SFQv/0hUL/"
-  "9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0"
-  "hUL/9IVC//SFQv/0hUL///r3///////8387/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/+syw////"
-  "///++fb/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC"
-  "//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/95NX///////vUvP/0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQv/97OH///////7y6//0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0"
-  "hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//i2jv///////N/O//SF"
-  "Qv/0hUL/9IVC//SFQv/0hUL/96Nx////////////+s2x//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC"
-  "//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/"
-  "9IdF//zh0P//+/j/9ZJW//SFQv/0hUL/9IVC//SKSv/96t7///////738v/1k1f/9IVC//SFQv/0"
-  "hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SF"
-  "Qv/0hUL/9IVC//SFQv/0hUL/9YxN//vUvf/96+D/96Z0//WNT//3om///ebY/////////Pv/+LKI"
-  "//WVW//0h0X/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//agbP/7zbL//enc//749P//"
-  "//////////////////////////3r4P/3p3f/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SF"
-  "Qv/0hULx9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC"
-  "//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQv/0hUL/9IVC8/SFQq30hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0"
-  "hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SF"
-  "Qv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUKt9IVCJ/SFQu/0hUL/9IVC//SFQv/0hUL/9IVC"
-  "//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/"
-  "9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC7/SFQif0hUIA9IVCJfSFQq30"
-  "hULx9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SF"
-  "Qv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC8fSFQq30hUIl9IVC"
-  "AIAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-  "AAAAAAAAAAAAAACAAAAB";
-
-NSData* StringToNSData(const char* base64encodedData) {
-  std::string output;
-  EXPECT_TRUE(base::Base64Decode(base64encodedData, &output));
-  return [NSData dataWithBytes:output.data() length:output.length()];
-}
-
-NSData* InvalidData(NSUInteger length) {
-  NSMutableData* data=[NSMutableData dataWithLength:length];
-  memset([data mutableBytes], 0xFF, length);
-  return data;
-}
-
-TEST_F(SkiaUtilsIosTest, ImageDataToSkBitmaps) {
-  std::vector<SkBitmap> bitmaps(
-      gfx::ImageDataToSkBitmaps(StringToNSData(kIcoEncodedData)));
-
-  EXPECT_EQ(2UL, bitmaps.size());
-  EXPECT_EQ(32, bitmaps[0].width());
-  EXPECT_EQ(32, bitmaps[0].height());
-  EXPECT_EQ(16, bitmaps[1].width());
-  EXPECT_EQ(16, bitmaps[1].height());
-}
-
-TEST_F(SkiaUtilsIosTest, InvalidDataFailure) {
-  std::vector<SkBitmap> bitmaps1(gfx::ImageDataToSkBitmaps(InvalidData(1)));
-  EXPECT_EQ(0UL, bitmaps1.size());
-  std::vector<SkBitmap> bitmaps2(gfx::ImageDataToSkBitmaps(InvalidData(10)));
-  EXPECT_EQ(0UL, bitmaps2.size());
-  std::vector<SkBitmap> bitmaps3(gfx::ImageDataToSkBitmaps(InvalidData(100)));
-  EXPECT_EQ(0UL, bitmaps3.size());
-  std::vector<SkBitmap> bitmaps4(gfx::ImageDataToSkBitmaps(InvalidData(1000)));
-  EXPECT_EQ(0UL, bitmaps4.size());
-  std::vector<SkBitmap> bitmaps5(gfx::ImageDataToSkBitmaps(InvalidData(5000)));
-  EXPECT_EQ(0UL, bitmaps5.size());
-}
-
-TEST_F(SkiaUtilsIosTest, EmptyDataFailure) {
-  std::vector<SkBitmap> bitmaps(gfx::ImageDataToSkBitmaps([NSData data]));
-
-  EXPECT_EQ(0UL, bitmaps.size());
-}
-
-// This is a base64 encoded version of ico file containing a 88x88 image.
-// generated by: convert -size 88x88 xc:white test.ico; base64 -b -i test.ico
-const char kIco88x88EncodedData[] =
-    "AAABAAEAWFgAAAEAIABIfQAAFgAAACgAAABYAAAAsAAAAAEAIAAAAAAAAHkAAAAAAAAAAAAAAA"
-    "AAAAAAAAD/AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8A"
-    "AP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w"
-    "AA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//"
-    "AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//"
-    "8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD/"
-    "/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP"
-    "//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA"
-    "//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AA"
-    "D//wAA//8AAP//AAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-    "AAAAAAAAAAAAAAAAAAAA";
-
-TEST_F(SkiaUtilsIosTest, Image88x88OrLarger) {
-  std::vector<SkBitmap> bitmaps(
-      gfx::ImageDataToSkBitmaps(StringToNSData(kIco88x88EncodedData)));
-  if (base::ios::IsRunningOnOrLater(8, 1, 1))
-    EXPECT_EQ(0UL, bitmaps.size());
-  else
-    EXPECT_EQ(1UL, bitmaps.size());
-}
-
-}  // namespace
-
diff --git a/skia/ext/skia_utils_mac.h b/skia/ext/skia_utils_mac.h
deleted file mode 100644
index b60f9e8..0000000
--- a/skia/ext/skia_utils_mac.h
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SKIA_EXT_SKIA_UTILS_MAC_H_
-#define SKIA_EXT_SKIA_UTILS_MAC_H_
-
-#include <ApplicationServices/ApplicationServices.h>
-#include <vector>
-
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkColor.h"
-
-struct SkIRect;
-struct SkPoint;
-struct SkRect;
-class SkCanvas;
-class SkMatrix;
-#ifdef __LP64__
-typedef CGSize NSSize;
-#else
-typedef struct _NSSize NSSize;
-#endif
-
-#ifdef __OBJC__
-@class NSBitmapImageRep;
-@class NSImage;
-@class NSImageRep;
-@class NSColor;
-#else
-class NSBitmapImageRep;
-class NSImage;
-class NSImageRep;
-class NSColor;
-#endif
-
-namespace gfx {
-
-// Converts a Skia point to a CoreGraphics CGPoint.
-// Both use same in-memory format.
-inline const CGPoint& SkPointToCGPoint(const SkPoint& point) {
-  return reinterpret_cast<const CGPoint&>(point);
-}
-
-// Converts a CoreGraphics point to a Skia CGPoint.
-// Both use same in-memory format.
-inline const SkPoint& CGPointToSkPoint(const CGPoint& point) {
-  return reinterpret_cast<const SkPoint&>(point);
-}
-
-// Matrix converters.
-SK_API CGAffineTransform SkMatrixToCGAffineTransform(const SkMatrix& matrix);
-
-// Rectangle converters.
-SK_API SkRect CGRectToSkRect(const CGRect& rect);
-
-// Converts a Skia rect to a CoreGraphics CGRect.
-CGRect SkIRectToCGRect(const SkIRect& rect);
-CGRect SkRectToCGRect(const SkRect& rect);
-
-// Converts CGColorRef to the ARGB layout Skia expects.
-SK_API SkColor CGColorRefToSkColor(CGColorRef color);
-
-// Converts ARGB to CGColorRef.
-SK_API CGColorRef CGColorCreateFromSkColor(SkColor color);
-
-// Converts NSColor to ARGB. Returns raw rgb values and does no colorspace
-// conversion. Only valid for colors in calibrated and device color spaces.
-SK_API SkColor NSDeviceColorToSkColor(NSColor* color);
-
-// Converts ARGB in the specified color space to NSColor.
-// Prefer sRGB over calibrated colors.
-SK_API NSColor* SkColorToCalibratedNSColor(SkColor color);
-SK_API NSColor* SkColorToDeviceNSColor(SkColor color);
-SK_API NSColor* SkColorToSRGBNSColor(SkColor color);
-
-// Converts a CGImage to a SkBitmap.
-SK_API SkBitmap CGImageToSkBitmap(CGImageRef image);
-
-// Draws an NSImage with a given size into a SkBitmap.
-SK_API SkBitmap NSImageToSkBitmapWithColorSpace(NSImage* image,
-                                                bool is_opaque,
-                                                CGColorSpaceRef color_space);
-
-// Draws an NSImageRep with a given size into a SkBitmap.
-SK_API SkBitmap NSImageRepToSkBitmapWithColorSpace(NSImageRep* image,
-                                                   NSSize size,
-                                                   bool is_opaque,
-                                                   CGColorSpaceRef colorspace);
-
-// Given an SkBitmap, return an autoreleased NSBitmapImageRep in the generic
-// color space.
-SK_API NSBitmapImageRep* SkBitmapToNSBitmapImageRep(const SkBitmap& image);
-
-SK_API NSBitmapImageRep* SkBitmapToNSBitmapImageRepWithColorSpace(
-    const SkBitmap& skiaBitmap,
-    CGColorSpaceRef colorSpace);
-
-// Given an SkBitmap and a color space, return an autoreleased NSImage.
-SK_API NSImage* SkBitmapToNSImageWithColorSpace(const SkBitmap& icon,
-                                                CGColorSpaceRef colorSpace);
-
-// Given an SkBitmap, return an autoreleased NSImage in the generic color space.
-// DEPRECATED, use SkBitmapToNSImageWithColorSpace() instead.
-// TODO(thakis): Remove this -- http://crbug.com/69432
-SK_API NSImage* SkBitmapToNSImage(const SkBitmap& icon);
-
-// Converts a SkCanvas temporarily to a CGContext
-class SK_API SkiaBitLocker {
- public:
-  // TODO(ccameron): delete this constructor
-  explicit SkiaBitLocker(SkCanvas* canvas);
-  SkiaBitLocker(SkCanvas* canvas,
-                const SkIRect& userClipRect,
-                SkScalar bitmapScaleFactor = 1);
-  ~SkiaBitLocker();
-  CGContextRef cgContext();
-  bool hasEmptyClipRegion() const;
-
- private:
-  void releaseIfNeeded();
-  SkIRect computeDirtyRect();
-
-  SkCanvas* canvas_;
-
-  // If the user specified a clip rect it would draw into then the locker may
-  // skip the step of searching for a rect bounding the pixels that the user
-  // has drawn into.
-  bool userClipRectSpecified_;
-
-  CGContextRef cgContext_;
-  SkBitmap bitmap_;
-  SkIPoint bitmapOffset_;
-  SkScalar bitmapScaleFactor_;
-
-  // True if we are drawing to |canvas_|'s SkBaseDevice's bits directly through
-  // |bitmap_|. Otherwise, the bits in |bitmap_| are our allocation and need to
-  // be copied over to |canvas_|.
-  bool useDeviceBits_;
-
-  // True if |bitmap_| is a dummy 1x1 bitmap allocated for the sake of creating
-  // a non-NULL CGContext (it is invalid to use a NULL CGContext), and will not
-  // be copied to |canvas_|. This will happen if |canvas_|'s clip region is
-  // empty.
-  bool bitmapIsDummy_;
-};
-
-
-}  // namespace gfx
-
-#endif  // SKIA_EXT_SKIA_UTILS_MAC_H_
diff --git a/skia/ext/skia_utils_mac.mm b/skia/ext/skia_utils_mac.mm
deleted file mode 100644
index 9e552eb..0000000
--- a/skia/ext/skia_utils_mac.mm
+++ /dev/null
@@ -1,462 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/skia_utils_mac.h"
-
-#import <AppKit/AppKit.h>
-
-#include "base/logging.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/mac/scoped_nsobject.h"
-#include "base/memory/scoped_ptr.h"
-#include "skia/ext/bitmap_platform_device_mac.h"
-#include "third_party/skia/include/core/SkRegion.h"
-#include "third_party/skia/include/utils/mac/SkCGUtils.h"
-
-namespace {
-
-// Draws an NSImage or an NSImageRep with a given size into a SkBitmap.
-SkBitmap NSImageOrNSImageRepToSkBitmapWithColorSpace(
-    NSImage* image,
-    NSImageRep* image_rep,
-    NSSize size,
-    bool is_opaque,
-    CGColorSpaceRef color_space) {
-  // Only image or image_rep should be provided, not both.
-  DCHECK((image != 0) ^ (image_rep != 0));
-
-  SkBitmap bitmap;
-  if (!bitmap.tryAllocN32Pixels(size.width, size.height, is_opaque))
-    return bitmap;  // Return |bitmap| which should respond true to isNull().
-
-
-  void* data = bitmap.getPixels();
-
-  // Allocate a bitmap context with 4 components per pixel (BGRA). Apple
-  // recommends these flags for improved CG performance.
-#define HAS_ARGB_SHIFTS(a, r, g, b) \
-            (SK_A32_SHIFT == (a) && SK_R32_SHIFT == (r) \
-             && SK_G32_SHIFT == (g) && SK_B32_SHIFT == (b))
-#if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0)
-  base::ScopedCFTypeRef<CGContextRef> context(CGBitmapContextCreate(
-      data,
-      size.width,
-      size.height,
-      8,
-      size.width * 4,
-      color_space,
-      kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
-#else
-#error We require that Skia's and CoreGraphics's recommended \
-       image memory layout match.
-#endif
-#undef HAS_ARGB_SHIFTS
-
-  // Something went really wrong. Best guess is that the bitmap data is invalid.
-  DCHECK(context);
-
-  [NSGraphicsContext saveGraphicsState];
-
-  NSGraphicsContext* context_cocoa =
-      [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO];
-  [NSGraphicsContext setCurrentContext:context_cocoa];
-
-  NSRect drawRect = NSMakeRect(0, 0, size.width, size.height);
-  if (image) {
-    [image drawInRect:drawRect
-             fromRect:NSZeroRect
-            operation:NSCompositeCopy
-             fraction:1.0];
-  } else {
-    [image_rep drawInRect:drawRect
-                 fromRect:NSZeroRect
-                operation:NSCompositeCopy
-                 fraction:1.0
-           respectFlipped:NO
-                    hints:nil];
-  }
-
-  [NSGraphicsContext restoreGraphicsState];
-
-  return bitmap;
-}
-
-} // namespace
-
-namespace gfx {
-
-CGAffineTransform SkMatrixToCGAffineTransform(const SkMatrix& matrix) {
-  // CGAffineTransforms don't support perspective transforms, so make sure
-  // we don't get those.
-  DCHECK(matrix[SkMatrix::kMPersp0] == 0.0f);
-  DCHECK(matrix[SkMatrix::kMPersp1] == 0.0f);
-  DCHECK(matrix[SkMatrix::kMPersp2] == 1.0f);
-
-  return CGAffineTransformMake(matrix[SkMatrix::kMScaleX],
-                               matrix[SkMatrix::kMSkewY],
-                               matrix[SkMatrix::kMSkewX],
-                               matrix[SkMatrix::kMScaleY],
-                               matrix[SkMatrix::kMTransX],
-                               matrix[SkMatrix::kMTransY]);
-}
-
-SkRect CGRectToSkRect(const CGRect& rect) {
-  SkRect sk_rect = {
-    rect.origin.x, rect.origin.y, CGRectGetMaxX(rect), CGRectGetMaxY(rect)
-  };
-  return sk_rect;
-}
-
-CGRect SkIRectToCGRect(const SkIRect& rect) {
-  CGRect cg_rect = {
-    { rect.fLeft, rect.fTop },
-    { rect.fRight - rect.fLeft, rect.fBottom - rect.fTop }
-  };
-  return cg_rect;
-}
-
-CGRect SkRectToCGRect(const SkRect& rect) {
-  CGRect cg_rect = {
-    { rect.fLeft, rect.fTop },
-    { rect.fRight - rect.fLeft, rect.fBottom - rect.fTop }
-  };
-  return cg_rect;
-}
-
-// Converts CGColorRef to the ARGB layout Skia expects.
-SkColor CGColorRefToSkColor(CGColorRef color) {
-  DCHECK(CGColorGetNumberOfComponents(color) == 4);
-  const CGFloat* components = CGColorGetComponents(color);
-  return SkColorSetARGB(SkScalarRoundToInt(255.0 * components[3]), // alpha
-                        SkScalarRoundToInt(255.0 * components[0]), // red
-                        SkScalarRoundToInt(255.0 * components[1]), // green
-                        SkScalarRoundToInt(255.0 * components[2])); // blue
-}
-
-// Converts ARGB to CGColorRef.
-CGColorRef CGColorCreateFromSkColor(SkColor color) {
-  return CGColorCreateGenericRGB(SkColorGetR(color) / 255.0,
-                                 SkColorGetG(color) / 255.0,
-                                 SkColorGetB(color) / 255.0,
-                                 SkColorGetA(color) / 255.0);
-}
-
-// Converts NSColor to ARGB
-SkColor NSDeviceColorToSkColor(NSColor* color) {
-  DCHECK([color colorSpace] == [NSColorSpace genericRGBColorSpace] ||
-         [color colorSpace] == [NSColorSpace deviceRGBColorSpace]);
-  CGFloat red, green, blue, alpha;
-  color = [color colorUsingColorSpace:[NSColorSpace deviceRGBColorSpace]];
-  [color getRed:&red green:&green blue:&blue alpha:&alpha];
-  return SkColorSetARGB(SkScalarRoundToInt(255.0 * alpha),
-                        SkScalarRoundToInt(255.0 * red),
-                        SkScalarRoundToInt(255.0 * green),
-                        SkScalarRoundToInt(255.0 * blue));
-}
-
-// Converts ARGB to NSColor.
-NSColor* SkColorToCalibratedNSColor(SkColor color) {
-  return [NSColor colorWithCalibratedRed:SkColorGetR(color) / 255.0
-                                   green:SkColorGetG(color) / 255.0
-                                    blue:SkColorGetB(color) / 255.0
-                                   alpha:SkColorGetA(color) / 255.0];
-}
-
-NSColor* SkColorToDeviceNSColor(SkColor color) {
-  return [NSColor colorWithDeviceRed:SkColorGetR(color) / 255.0
-                               green:SkColorGetG(color) / 255.0
-                                blue:SkColorGetB(color) / 255.0
-                               alpha:SkColorGetA(color) / 255.0];
-}
-
-NSColor* SkColorToSRGBNSColor(SkColor color) {
-  const CGFloat components[] = {
-    SkColorGetR(color) / 255.0,
-    SkColorGetG(color) / 255.0,
-    SkColorGetB(color) / 255.0,
-    SkColorGetA(color) / 255.0
-  };
-  return [NSColor colorWithColorSpace:[NSColorSpace sRGBColorSpace]
-                           components:components
-                                count:4];
-}
-
-SkBitmap CGImageToSkBitmap(CGImageRef image) {
-  if (!image)
-    return SkBitmap();
-
-  int width = CGImageGetWidth(image);
-  int height = CGImageGetHeight(image);
-
-  scoped_ptr<SkBaseDevice> device(
-      skia::BitmapPlatformDevice::Create(NULL, width, height, false));
-
-  CGContextRef context = skia::GetBitmapContext(device.get());
-
-  // We need to invert the y-axis of the canvas so that Core Graphics drawing
-  // happens right-side up. Skia has an upper-left origin and CG has a lower-
-  // left one.
-  CGContextScaleCTM(context, 1.0, -1.0);
-  CGContextTranslateCTM(context, 0, -height);
-
-  // We want to copy transparent pixels from |image|, instead of blending it
-  // onto uninitialized pixels.
-  CGContextSetBlendMode(context, kCGBlendModeCopy);
-
-  CGRect rect = CGRectMake(0, 0, width, height);
-  CGContextDrawImage(context, rect, image);
-
-  // Because |device| will be cleaned up and will take its pixels with it, we
-  // copy it to the stack and return it.
-  SkBitmap bitmap = device->accessBitmap(false);
-
-  return bitmap;
-}
-
-SkBitmap NSImageToSkBitmapWithColorSpace(
-    NSImage* image, bool is_opaque, CGColorSpaceRef color_space) {
-  return NSImageOrNSImageRepToSkBitmapWithColorSpace(
-      image, nil, [image size], is_opaque, color_space);
-}
-
-SkBitmap NSImageRepToSkBitmapWithColorSpace(NSImageRep* image_rep,
-                                            NSSize size,
-                                            bool is_opaque,
-                                            CGColorSpaceRef color_space) {
-  return NSImageOrNSImageRepToSkBitmapWithColorSpace(
-      nil, image_rep, size, is_opaque, color_space);
-}
-
-NSBitmapImageRep* SkBitmapToNSBitmapImageRep(const SkBitmap& skiaBitmap) {
-  base::ScopedCFTypeRef<CGColorSpaceRef> color_space(
-      CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB));
-  return SkBitmapToNSBitmapImageRepWithColorSpace(skiaBitmap, color_space);
-}
-
-NSBitmapImageRep* SkBitmapToNSBitmapImageRepWithColorSpace(
-    const SkBitmap& skiaBitmap,
-    CGColorSpaceRef colorSpace) {
-  // First convert SkBitmap to CGImageRef.
-  base::ScopedCFTypeRef<CGImageRef> cgimage(
-      SkCreateCGImageRefWithColorspace(skiaBitmap, colorSpace));
-
-  // Now convert to NSBitmapImageRep.
-  base::scoped_nsobject<NSBitmapImageRep> bitmap(
-      [[NSBitmapImageRep alloc] initWithCGImage:cgimage]);
-  return [bitmap.release() autorelease];
-}
-
-NSImage* SkBitmapToNSImageWithColorSpace(const SkBitmap& skiaBitmap,
-                                         CGColorSpaceRef colorSpace) {
-  if (skiaBitmap.isNull())
-    return nil;
-
-  base::scoped_nsobject<NSImage> image([[NSImage alloc] init]);
-  [image addRepresentation:
-      SkBitmapToNSBitmapImageRepWithColorSpace(skiaBitmap, colorSpace)];
-  [image setSize:NSMakeSize(skiaBitmap.width(), skiaBitmap.height())];
-  return [image.release() autorelease];
-}
-
-NSImage* SkBitmapToNSImage(const SkBitmap& skiaBitmap) {
-  base::ScopedCFTypeRef<CGColorSpaceRef> colorSpace(
-      CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB));
-  return SkBitmapToNSImageWithColorSpace(skiaBitmap, colorSpace.get());
-}
-
-SkiaBitLocker::SkiaBitLocker(SkCanvas* canvas)
-    : canvas_(canvas),
-      userClipRectSpecified_(false),
-      cgContext_(0),
-      bitmapScaleFactor_(1),
-      useDeviceBits_(false),
-      bitmapIsDummy_(false) {
-}
-
-SkiaBitLocker::SkiaBitLocker(SkCanvas* canvas,
-                             const SkIRect& userClipRect,
-                             SkScalar bitmapScaleFactor)
-    : canvas_(canvas),
-      userClipRectSpecified_(true),
-      cgContext_(0),
-      bitmapScaleFactor_(bitmapScaleFactor),
-      useDeviceBits_(false),
-      bitmapIsDummy_(false) {
-  canvas_->save();
-  canvas_->clipRect(SkRect::MakeFromIRect(userClipRect));
-}
-
-SkiaBitLocker::~SkiaBitLocker() {
-  releaseIfNeeded();
-  if (userClipRectSpecified_)
-    canvas_->restore();
-}
-
-SkIRect SkiaBitLocker::computeDirtyRect() {
-  // If the user specified a clip region, assume that it was tight and that the
-  // dirty rect is approximately the whole bitmap.
-  if (userClipRectSpecified_)
-    return SkIRect::MakeWH(bitmap_.width(), bitmap_.height());
-
-  // Find the bits that were drawn to.
-  SkAutoLockPixels lockedPixels(bitmap_);
-  const uint32_t* pixelBase
-      = reinterpret_cast<uint32_t*>(bitmap_.getPixels());
-  int rowPixels = bitmap_.rowBytesAsPixels();
-  int width = bitmap_.width();
-  int height = bitmap_.height();
-  SkIRect bounds;
-  bounds.fTop = 0;
-  int x;
-  int y = -1;
-  const uint32_t* pixels = pixelBase;
-  while (++y < height) {
-    for (x = 0; x < width; ++x) {
-      if (pixels[x]) {
-        bounds.fTop = y;
-        goto foundTop;
-      }
-    }
-    pixels += rowPixels;
-  }
-foundTop:
-  bounds.fBottom = height;
-  y = height;
-  pixels = pixelBase + rowPixels * (y - 1);
-  while (--y > bounds.fTop) {
-    for (x = 0; x < width; ++x) {
-      if (pixels[x]) {
-        bounds.fBottom = y + 1;
-        goto foundBottom;
-      }
-    }
-    pixels -= rowPixels;
-  }
-foundBottom:
-  bounds.fLeft = 0;
-  x = -1;
-  while (++x < width) {
-    pixels = pixelBase + rowPixels * bounds.fTop;
-    for (y = bounds.fTop; y < bounds.fBottom; ++y) {
-      if (pixels[x]) {
-        bounds.fLeft = x;
-        goto foundLeft;
-      }
-      pixels += rowPixels;
-    }
-  }
-foundLeft:
-  bounds.fRight = width;
-  x = width;
-  while (--x > bounds.fLeft) {
-    pixels = pixelBase + rowPixels * bounds.fTop;
-    for (y = bounds.fTop; y < bounds.fBottom; ++y) {
-      if (pixels[x]) {
-        bounds.fRight = x + 1;
-        goto foundRight;
-      }
-      pixels += rowPixels;
-    }
-  }
-foundRight:
-  return bounds;
-}
-
-// This must be called to balance calls to cgContext
-void SkiaBitLocker::releaseIfNeeded() {
-  if (!cgContext_)
-    return;
-  if (useDeviceBits_) {
-    bitmap_.unlockPixels();
-  } else if (!bitmapIsDummy_) {
-    // Find the bits that were drawn to.
-    SkIRect bounds = computeDirtyRect();
-    SkBitmap subset;
-    if (!bitmap_.extractSubset(&subset, bounds)) {
-        return;
-    }
-    subset.setImmutable();  // Prevents a defensive copy inside Skia.
-    canvas_->save();
-    canvas_->setMatrix(SkMatrix::I());  // Reset back to device space.
-    canvas_->translate(bounds.x() + bitmapOffset_.x(),
-                       bounds.y() + bitmapOffset_.y());
-    canvas_->scale(1.f / bitmapScaleFactor_, 1.f / bitmapScaleFactor_);
-    canvas_->drawBitmap(subset, 0, 0);
-    canvas_->restore();
-  }
-  CGContextRelease(cgContext_);
-  cgContext_ = 0;
-  useDeviceBits_ = false;
-  bitmapIsDummy_ = false;
-}
-
-CGContextRef SkiaBitLocker::cgContext() {
-  SkIRect clip_bounds;
-  if (!canvas_->getClipDeviceBounds(&clip_bounds)) {
-    // If the clip is empty, then there is nothing to draw. The caller may
-    // attempt to draw (to-be-clipped) results, so ensure there is a dummy
-    // non-NULL CGContext to use.
-    bitmapIsDummy_ = true;
-    clip_bounds = SkIRect::MakeXYWH(0, 0, 1, 1);
-  }
-
-  SkBaseDevice* device = canvas_->getTopDevice();
-  DCHECK(device);
-  if (!device)
-    return 0;
-
-  releaseIfNeeded(); // This flushes any prior bitmap use
-
-  // remember the top/left, in case we need to compose this later
-  bitmapOffset_.set(clip_bounds.x(), clip_bounds.y());
-
-  // Now make clip_bounds be relative to the current layer/device
-  clip_bounds.offset(-device->getOrigin());
-
-  const SkBitmap& deviceBits = device->accessBitmap(true);
-
-  // Only draw directly if we have pixels, and we're only rect-clipped.
-  // If not, we allocate an offscreen and draw into that, relying on the
-  // compositing step to apply skia's clip.
-  useDeviceBits_ = deviceBits.getPixels() &&
-                   canvas_->isClipRect() &&
-                   !bitmapIsDummy_;
-  if (useDeviceBits_) {
-    bool result = deviceBits.extractSubset(&bitmap_, clip_bounds);
-    DCHECK(result);
-    if (!result)
-      return 0;
-    bitmap_.lockPixels();
-  } else {
-    bool result = bitmap_.tryAllocN32Pixels(
-        SkScalarCeilToInt(bitmapScaleFactor_ * clip_bounds.width()),
-        SkScalarCeilToInt(bitmapScaleFactor_ * clip_bounds.height()));
-    DCHECK(result);
-    if (!result)
-      return 0;
-    bitmap_.eraseColor(0);
-  }
-  base::ScopedCFTypeRef<CGColorSpaceRef> colorSpace(
-      CGColorSpaceCreateDeviceRGB());
-  cgContext_ = CGBitmapContextCreate(bitmap_.getPixels(), bitmap_.width(),
-    bitmap_.height(), 8, bitmap_.rowBytes(), colorSpace, 
-    kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst);
-  DCHECK(cgContext_);
-
-  SkMatrix matrix = canvas_->getTotalMatrix();
-  matrix.postTranslate(-SkIntToScalar(bitmapOffset_.x()),
-                       -SkIntToScalar(bitmapOffset_.y()));
-  matrix.postScale(bitmapScaleFactor_, -bitmapScaleFactor_);
-  matrix.postTranslate(0, SkIntToScalar(bitmap_.height()));
-
-  CGContextConcatCTM(cgContext_, SkMatrixToCGAffineTransform(matrix));
-  
-  return cgContext_;
-}
-
-bool SkiaBitLocker::hasEmptyClipRegion() const {
-  return canvas_->isClipEmpty();
-}
-
-}  // namespace gfx
diff --git a/skia/ext/skia_utils_mac_unittest.mm b/skia/ext/skia_utils_mac_unittest.mm
deleted file mode 100644
index 27c862b..0000000
--- a/skia/ext/skia_utils_mac_unittest.mm
+++ /dev/null
@@ -1,247 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/skia_utils_mac.h"
-
-#import <AppKit/AppKit.h>
-
-#include "base/mac/scoped_nsobject.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-
-namespace {
-
-class SkiaUtilsMacTest : public testing::Test {
- public:
-  // Creates a red or blue bitmap.
-  SkBitmap CreateSkBitmap(int width, int height, bool isred, bool tfbit);
-
-  // Creates a red or blue image.
-  NSImage* CreateNSImage(int width, int height, bool isred);
-
-  // Checks that the given bitmap rep is actually red or blue.
-  void TestImageRep(NSBitmapImageRep* imageRep, bool isred);
-
-  // Checks that the given bitmap is actually red or blue.
-  void TestSkBitmap(const SkBitmap& bitmap, bool isred);
-
-  enum BitLockerTest {
-    TestIdentity = 0,
-    TestTranslate = 1,
-    TestClip = 2,
-    TestXClip = TestTranslate | TestClip,
-    TestNoBits = 4,
-    TestTranslateNoBits = TestTranslate | TestNoBits,
-    TestClipNoBits = TestClip | TestNoBits,
-    TestXClipNoBits = TestXClip | TestNoBits,
-  };
-  void RunBitLockerTest(BitLockerTest test);
-
-  // If not red, is blue.
-  // If not tfbit (twenty-four-bit), is 444.
-  void ShapeHelper(int width, int height, bool isred, bool tfbit);
-};
-
-SkBitmap SkiaUtilsMacTest::CreateSkBitmap(int width, int height,
-                                          bool isred, bool tfbit) {
-  SkColorType ct = tfbit ? kN32_SkColorType : kARGB_4444_SkColorType;
-  SkImageInfo info = SkImageInfo::Make(width, height, ct, kPremul_SkAlphaType);
-
-  SkBitmap bitmap;
-  bitmap.allocPixels(info);
-
-  if (isred)
-    bitmap.eraseARGB(0xff, 0xff, 0, 0);
-  else
-    bitmap.eraseARGB(0xff, 0, 0, 0xff);
-
-  return bitmap;
-}
-
-NSImage* SkiaUtilsMacTest::CreateNSImage(int width, int height, bool isred) {
-  base::scoped_nsobject<NSImage> image(
-      [[NSImage alloc] initWithSize:NSMakeSize(width, height)]);
-  [image lockFocus];
-  if (isred)
-    [[NSColor colorWithDeviceRed:1.0 green:0.0 blue:0.0 alpha:1.0] set];
-  else
-    [[NSColor colorWithDeviceRed:0.0 green:0.0 blue:1.0 alpha:1.0] set];
-  NSRectFill(NSMakeRect(0, 0, width, height));
-  [image unlockFocus];
-  return [image.release() autorelease];
-}
-
-void SkiaUtilsMacTest::TestImageRep(NSBitmapImageRep* imageRep, bool isred) {
-  // Get the color of a pixel and make sure it looks fine
-  int x = [imageRep size].width > 17 ? 17 : 0;
-  int y = [imageRep size].height > 17 ? 17 : 0;
-  NSColor* color = [imageRep colorAtX:x y:y];
-  CGFloat red = 0, green = 0, blue = 0, alpha = 0;
-
-  // SkBitmapToNSImage returns a bitmap in the calibrated color space (sRGB),
-  // while NSReadPixel returns a color in the device color space. Convert back
-  // to the calibrated color space before testing.
-  color = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
-
-  [color getRed:&red green:&green blue:&blue alpha:&alpha];
-
-  // Be tolerant of floating point rounding and lossy color space conversions.
-  if (isred) {
-    EXPECT_GT(red, 0.95);
-    EXPECT_LT(blue, 0.05);
-  } else {
-    EXPECT_LT(red, 0.05);
-    EXPECT_GT(blue, 0.95);
-  }
-  EXPECT_LT(green, 0.05);
-  EXPECT_GT(alpha, 0.95);
-}
-
-void SkiaUtilsMacTest::TestSkBitmap(const SkBitmap& bitmap, bool isred) {
-  int x = bitmap.width() > 17 ? 17 : 0;
-  int y = bitmap.height() > 17 ? 17 : 0;
-  SkColor color = bitmap.getColor(x, y);
-
-  if (isred) {
-    EXPECT_EQ(255u, SkColorGetR(color));
-    EXPECT_EQ(0u, SkColorGetB(color));
-  } else {
-    EXPECT_EQ(0u, SkColorGetR(color));
-    EXPECT_EQ(255u, SkColorGetB(color));
-  }
-  EXPECT_EQ(0u, SkColorGetG(color));
-  EXPECT_EQ(255u, SkColorGetA(color));
-}
-
-// setBitmapDevice has been deprecated/removed. Is this test still useful?
-void SkiaUtilsMacTest::RunBitLockerTest(BitLockerTest test) {
-  const unsigned width = 2;
-  const unsigned height = 2;
-  const unsigned storageSize = width * height;
-  const unsigned original[] = {0xFF333333, 0xFF666666, 0xFF999999, 0xFFCCCCCC};
-  EXPECT_EQ(storageSize, sizeof(original) / sizeof(original[0]));
-  unsigned bits[storageSize];
-  memcpy(bits, original, sizeof(original));
-  SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
-  SkBitmap bitmap;
-  bitmap.installPixels(info, bits, info.minRowBytes());
-
-  SkCanvas canvas(bitmap);
-  if (test & TestTranslate)
-    canvas.translate(width / 2, 0);
-  if (test & TestClip) {
-    SkRect clipRect = {0, height / 2, width, height};
-    canvas.clipRect(clipRect);
-  }
-  {
-    gfx::SkiaBitLocker bitLocker(&canvas);
-    CGContextRef cgContext = bitLocker.cgContext();
-    CGColorRef testColor = CGColorGetConstantColor(kCGColorWhite);
-    CGContextSetFillColorWithColor(cgContext, testColor);
-    CGRect cgRect = {{0, 0}, {width, height}};
-    CGContextFillRect(cgContext, cgRect);
-    if (test & TestNoBits) {
-      if (test & TestClip) {
-        SkRect clipRect = {0, height / 2, width, height};
-        canvas.clipRect(clipRect);
-      }
-    }
-  }
-  const unsigned results[][storageSize] = {
-    {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, // identity
-    {0xFF333333, 0xFFFFFFFF, 0xFF999999, 0xFFFFFFFF}, // translate
-    {0xFF333333, 0xFF666666, 0xFFFFFFFF, 0xFFFFFFFF}, // clip
-    {0xFF333333, 0xFF666666, 0xFF999999, 0xFFFFFFFF}  // translate | clip
-  };
-  for (unsigned index = 0; index < storageSize; index++)
-    EXPECT_EQ(results[test & ~TestNoBits][index], bits[index]);
-}
-
-void SkiaUtilsMacTest::ShapeHelper(int width, int height,
-                                   bool isred, bool tfbit) {
-  SkBitmap thing(CreateSkBitmap(width, height, isred, tfbit));
-
-  // Confirm size
-  NSImage* image = gfx::SkBitmapToNSImage(thing);
-  EXPECT_DOUBLE_EQ([image size].width, (double)width);
-  EXPECT_DOUBLE_EQ([image size].height, (double)height);
-
-  EXPECT_TRUE([[image representations] count] == 1);
-  EXPECT_TRUE([[[image representations] lastObject]
-      isKindOfClass:[NSBitmapImageRep class]]);
-  TestImageRep([[image representations] lastObject], isred);
-}
-
-TEST_F(SkiaUtilsMacTest, BitmapToNSImage_RedSquare64x64) {
-  ShapeHelper(64, 64, true, true);
-}
-
-TEST_F(SkiaUtilsMacTest, BitmapToNSImage_BlueRectangle199x19) {
-  ShapeHelper(199, 19, false, true);
-}
-
-TEST_F(SkiaUtilsMacTest, BitmapToNSImage_BlueRectangle444) {
-  ShapeHelper(200, 200, false, false);
-}
-
-TEST_F(SkiaUtilsMacTest, BitmapToNSBitmapImageRep_BlueRectangle20x30) {
-  int width = 20;
-  int height = 30;
-
-  SkBitmap bitmap(CreateSkBitmap(width, height, false, true));
-  NSBitmapImageRep* imageRep = gfx::SkBitmapToNSBitmapImageRep(bitmap);
-
-  EXPECT_DOUBLE_EQ(width, [imageRep size].width);
-  EXPECT_DOUBLE_EQ(height, [imageRep size].height);
-  TestImageRep(imageRep, false);
-}
-
-TEST_F(SkiaUtilsMacTest, NSImageRepToSkBitmap) {
-  int width = 10;
-  int height = 15;
-  bool isred = true;
-
-  NSImage* image = CreateNSImage(width, height, isred);
-  EXPECT_EQ(1u, [[image representations] count]);
-  NSBitmapImageRep* imageRep = [[image representations] lastObject];
-  NSColorSpace* colorSpace = [NSColorSpace deviceRGBColorSpace];
-  SkBitmap bitmap(gfx::NSImageRepToSkBitmapWithColorSpace(
-      imageRep, [image size], false, [colorSpace CGColorSpace]));
-  TestSkBitmap(bitmap, isred);
-}
-
-TEST_F(SkiaUtilsMacTest, BitLocker_Identity) {
-  RunBitLockerTest(SkiaUtilsMacTest::TestIdentity);
-}
-
-TEST_F(SkiaUtilsMacTest, BitLocker_Translate) {
-  RunBitLockerTest(SkiaUtilsMacTest::TestTranslate);
-}
-
-TEST_F(SkiaUtilsMacTest, BitLocker_Clip) {
-  RunBitLockerTest(SkiaUtilsMacTest::TestClip);
-}
-
-TEST_F(SkiaUtilsMacTest, BitLocker_XClip) {
-  RunBitLockerTest(SkiaUtilsMacTest::TestXClip);
-}
-
-TEST_F(SkiaUtilsMacTest, BitLocker_NoBits) {
-  RunBitLockerTest(SkiaUtilsMacTest::TestNoBits);
-}
-
-TEST_F(SkiaUtilsMacTest, BitLocker_TranslateNoBits) {
-  RunBitLockerTest(SkiaUtilsMacTest::TestTranslateNoBits);
-}
-
-TEST_F(SkiaUtilsMacTest, BitLocker_ClipNoBits) {
-  RunBitLockerTest(SkiaUtilsMacTest::TestClipNoBits);
-}
-
-TEST_F(SkiaUtilsMacTest, BitLocker_XClipNoBits) {
-  RunBitLockerTest(SkiaUtilsMacTest::TestXClipNoBits);
-}
-
-}  // namespace
-
diff --git a/skia/ext/skia_utils_win.cc b/skia/ext/skia_utils_win.cc
deleted file mode 100644
index e065b1e..0000000
--- a/skia/ext/skia_utils_win.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/skia_utils_win.h"
-
-#include <stddef.h>
-#include <windows.h>
-
-#include "third_party/skia/include/core/SkRect.h"
-#include "third_party/skia/include/core/SkTypes.h"
-#include "third_party/skia/include/effects/SkGradientShader.h"
-
-namespace {
-
-SK_COMPILE_ASSERT(offsetof(RECT, left) == offsetof(SkIRect, fLeft), o1);
-SK_COMPILE_ASSERT(offsetof(RECT, top) == offsetof(SkIRect, fTop), o2);
-SK_COMPILE_ASSERT(offsetof(RECT, right) == offsetof(SkIRect, fRight), o3);
-SK_COMPILE_ASSERT(offsetof(RECT, bottom) == offsetof(SkIRect, fBottom), o4);
-SK_COMPILE_ASSERT(sizeof(RECT().left) == sizeof(SkIRect().fLeft), o5);
-SK_COMPILE_ASSERT(sizeof(RECT().top) == sizeof(SkIRect().fTop), o6);
-SK_COMPILE_ASSERT(sizeof(RECT().right) == sizeof(SkIRect().fRight), o7);
-SK_COMPILE_ASSERT(sizeof(RECT().bottom) == sizeof(SkIRect().fBottom), o8);
-SK_COMPILE_ASSERT(sizeof(RECT) == sizeof(SkIRect), o9);
-
-}  // namespace
-
-namespace skia {
-
-POINT SkPointToPOINT(const SkPoint& point) {
-  POINT win_point = {
-      SkScalarRoundToInt(point.fX), SkScalarRoundToInt(point.fY)
-  };
-  return win_point;
-}
-
-SkRect RECTToSkRect(const RECT& rect) {
-  SkRect sk_rect = { SkIntToScalar(rect.left), SkIntToScalar(rect.top),
-                     SkIntToScalar(rect.right), SkIntToScalar(rect.bottom) };
-  return sk_rect;
-}
-
-SkColor COLORREFToSkColor(COLORREF color) {
-#ifndef _MSC_VER
-  return SkColorSetRGB(GetRValue(color), GetGValue(color), GetBValue(color));
-#else
-  // ARGB = 0xFF000000 | ((0BGR -> RGB0) >> 8)
-  return 0xFF000000u | (_byteswap_ulong(color) >> 8);
-#endif
-}
-
-COLORREF SkColorToCOLORREF(SkColor color) {
-#ifndef _MSC_VER
-  return RGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
-#else
-  // 0BGR = ((ARGB -> BGRA) >> 8)
-  return (_byteswap_ulong(color) >> 8);
-#endif
-}
-
-}  // namespace skia
-
diff --git a/skia/ext/skia_utils_win.h b/skia/ext/skia_utils_win.h
deleted file mode 100644
index 6ac5234..0000000
--- a/skia/ext/skia_utils_win.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SKIA_EXT_SKIA_UTILS_WIN_H_
-#define SKIA_EXT_SKIA_UTILS_WIN_H_
-
-#include "third_party/skia/include/core/SkColor.h"
-
-struct SkIRect;
-struct SkPoint;
-struct SkRect;
-typedef unsigned long DWORD;
-typedef DWORD COLORREF;
-typedef struct tagPOINT POINT;
-typedef struct tagRECT RECT;
-
-namespace skia {
-
-// Converts a Skia point to a Windows POINT.
-POINT SkPointToPOINT(const SkPoint& point);
-
-// Converts a Windows RECT to a Skia rect.
-SkRect RECTToSkRect(const RECT& rect);
-
-// Converts a Windows RECT to a Skia rect.
-// Both use same in-memory format. Verified by SK_COMPILE_ASSERT() in
-// skia_utils_win.cc.
-inline const SkIRect& RECTToSkIRect(const RECT& rect) {
-  return reinterpret_cast<const SkIRect&>(rect);
-}
-
-// Converts a Skia rect to a Windows RECT.
-// Both use same in-memory format. Verified by SK_COMPILE_ASSERT() in
-// skia_utils_win.cc.
-inline const RECT& SkIRectToRECT(const SkIRect& rect) {
-  return reinterpret_cast<const RECT&>(rect);
-}
-
-// Converts COLORREFs (0BGR) to the ARGB layout Skia expects.
-SK_API SkColor COLORREFToSkColor(COLORREF color);
-
-// Converts ARGB to COLORREFs (0BGR).
-SK_API COLORREF SkColorToCOLORREF(SkColor color);
-
-}  // namespace skia
-
-#endif  // SKIA_EXT_SKIA_UTILS_WIN_H_
-
diff --git a/skia/skia_gn_files.gypi b/skia/skia_gn_files.gypi
new file mode 100644
index 0000000..11f37ff
--- /dev/null
+++ b/skia/skia_gn_files.gypi
@@ -0,0 +1,37 @@
+# This file is read into the GN build.
+
+# Files are relative to third_party/skia.
+{
+  'skia_library_sources': [
+    '<(skia_src_path)/ports/SkImageGenerator_none.cpp',
+
+    '<(skia_include_path)/images/SkMovie.h',
+    '<(skia_src_path)/fonts/SkFontMgr_indirect.cpp',
+    '<(skia_src_path)/fonts/SkRemotableFontMgr.cpp',
+    '<(skia_src_path)/ports/SkFontHost_FreeType_common.cpp',
+    '<(skia_src_path)/ports/SkFontHost_FreeType_common.h',
+    '<(skia_src_path)/ports/SkFontHost_FreeType.cpp',
+    '<(skia_src_path)/ports/SkFontHost_mac.cpp',
+    '<(skia_src_path)/ports/SkFontMgr_android.cpp',
+    '<(skia_src_path)/ports/SkFontMgr_android_factory.cpp',
+    '<(skia_src_path)/ports/SkFontMgr_android_parser.cpp',
+    '<(skia_src_path)/ports/SkGlobalInitialization_default.cpp',
+    '<(skia_src_path)/ports/SkImageEncoder_none.cpp',
+    '<(skia_src_path)/ports/SkOSFile_posix.cpp',
+    '<(skia_src_path)/ports/SkOSFile_stdio.cpp',
+    '<(skia_src_path)/ports/SkTLS_pthread.cpp',
+    '<(skia_src_path)/sfnt/SkOTTable_name.cpp',
+    '<(skia_src_path)/sfnt/SkOTTable_name.h',
+    '<(skia_src_path)/sfnt/SkOTUtils.cpp',
+    '<(skia_src_path)/sfnt/SkOTUtils.h',
+
+    #mac
+    '<(skia_src_path)/utils/mac/SkStream_mac.cpp',
+
+    #windows
+
+    #testing
+    '<(skia_src_path)/fonts/SkGScalerContext.cpp',
+    '<(skia_src_path)/fonts/SkGScalerContext.h',
+  ],
+}
diff --git a/ui/gfx/hud_font.cc b/ui/gfx/hud_font.cc
index 8151778..881d17d 100644
--- a/ui/gfx/hud_font.cc
+++ b/ui/gfx/hud_font.cc
@@ -10,14 +10,14 @@
 namespace gfx {
 
 namespace {
-base::LazyInstance<skia::RefPtr<SkTypeface>> g_hud_typeface;
+base::LazyInstance<sk_sp<SkTypeface>> g_hud_typeface;
 }  // namespace
 
-void SetHudTypeface(skia::RefPtr<SkTypeface> typeface) {
+void SetHudTypeface(sk_sp<SkTypeface> typeface) {
   g_hud_typeface.Get() = typeface;
 }
 
-skia::RefPtr<SkTypeface> GetHudTypeface() {
+sk_sp<SkTypeface> GetHudTypeface() {
   // nullptr is fine; caller will create its own in that case.
   return g_hud_typeface.Get();
 }
diff --git a/ui/gfx/hud_font.h b/ui/gfx/hud_font.h
index f72a050..748f542 100644
--- a/ui/gfx/hud_font.h
+++ b/ui/gfx/hud_font.h
@@ -5,15 +5,15 @@
 #ifndef UI_GFX_HUD_FONT_H_
 #define UI_GFX_HUD_FONT_H_
 
-#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 #include "ui/gfx/gfx_export.h"
 
 class SkTypeface;
 
 namespace gfx {
 
-GFX_EXPORT void SetHudTypeface(skia::RefPtr<SkTypeface> typeface);
-GFX_EXPORT skia::RefPtr<SkTypeface> GetHudTypeface();
+GFX_EXPORT void SetHudTypeface(sk_sp<SkTypeface> typeface);
+GFX_EXPORT sk_sp<SkTypeface> GetHudTypeface();
 
 }  // namespace gfx
 
diff --git a/ui/gfx/skia_util.cc b/ui/gfx/skia_util.cc
index 1b4e219..511b0a5 100644
--- a/ui/gfx/skia_util.cc
+++ b/ui/gfx/skia_util.cc
@@ -71,17 +71,17 @@
   flattened->set(8, SkMScalarToScalar(transform.matrix().get(3, 3)));
 }
 
-skia::RefPtr<SkShader> CreateGradientShader(int start_point,
-                                            int end_point,
-                                            SkColor start_color,
-                                            SkColor end_color) {
+sk_sp<SkShader> CreateGradientShader(int start_point,
+                                     int end_point,
+                                     SkColor start_color,
+                                     SkColor end_color) {
   SkColor grad_colors[2] = { start_color, end_color};
   SkPoint grad_points[2];
   grad_points[0].iset(0, start_point);
   grad_points[1].iset(0, end_point);
 
-  return skia::AdoptRef(SkGradientShader::CreateLinear(
-      grad_points, grad_colors, NULL, 2, SkShader::kRepeat_TileMode));
+  return SkGradientShader::MakeLinear(grad_points, grad_colors, NULL, 2,
+                                      SkShader::kRepeat_TileMode);
 }
 
 static SkScalar RadiusToSigma(double radius) {
@@ -90,10 +90,10 @@
   return radius > 0 ? SkDoubleToScalar(0.57735f * radius + 0.5) : 0;
 }
 
-skia::RefPtr<SkDrawLooper> CreateShadowDrawLooper(
+sk_sp<SkDrawLooper> CreateShadowDrawLooper(
     const std::vector<ShadowValue>& shadows) {
   if (shadows.empty())
-    return skia::RefPtr<SkDrawLooper>();
+    return sk_sp<SkDrawLooper>();
 
   SkLayerDrawLooper::Builder looper_builder;
 
@@ -112,20 +112,18 @@
 
     // SkBlurMaskFilter's blur radius defines the range to extend the blur from
     // original mask, which is half of blur amount as defined in ShadowValue.
-    skia::RefPtr<SkMaskFilter> blur_mask =
-        skia::AdoptRef(SkBlurMaskFilter::Create(
-            kNormal_SkBlurStyle, RadiusToSigma(shadow.blur() / 2),
-            SkBlurMaskFilter::kHighQuality_BlurFlag));
-    skia::RefPtr<SkColorFilter> color_filter =
-        skia::AdoptRef(SkColorFilter::CreateModeFilter(
-            shadow.color(), SkXfermode::kSrcIn_Mode));
+    sk_sp<SkMaskFilter> blur_mask = SkBlurMaskFilter::Make(
+        kNormal_SkBlurStyle, RadiusToSigma(shadow.blur() / 2),
+        SkBlurMaskFilter::kHighQuality_BlurFlag);
+    sk_sp<SkColorFilter> color_filter =
+        SkColorFilter::MakeModeFilter(shadow.color(), SkXfermode::kSrcIn_Mode);
 
     SkPaint* paint = looper_builder.addLayer(layer_info);
-    paint->setMaskFilter(blur_mask.get());
-    paint->setColorFilter(color_filter.get());
+    paint->setMaskFilter(blur_mask);
+    paint->setColorFilter(color_filter);
   }
 
-  return skia::AdoptRef<SkDrawLooper>(looper_builder.detachLooper());
+  return looper_builder.detach();
 }
 
 bool BitmapsAreEqual(const SkBitmap& bitmap1, const SkBitmap& bitmap2) {
diff --git a/ui/gfx/skia_util.h b/ui/gfx/skia_util.h
index 44c9a09..d6be1b2 100644
--- a/ui/gfx/skia_util.h
+++ b/ui/gfx/skia_util.h
@@ -8,9 +8,9 @@
 #include <string>
 #include <vector>
 
-#include "skia/ext/refptr.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkRect.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/core/SkShader.h"
 #include "ui/gfx/geometry/quad_f.h"
 #include "ui/gfx/geometry/size.h"
@@ -48,13 +48,13 @@
 // TODO(pkotwicz): Allow shader's local matrix to be changed after the shader
 // is created.
 //
-GFX_EXPORT skia::RefPtr<SkShader> CreateImageRepShader(
+GFX_EXPORT sk_sp<SkShader> CreateImageRepShader(
     const gfx::ImageSkiaRep& image_rep,
     SkShader::TileMode tile_mode,
     const SkMatrix& local_matrix);
 
 // Creates a bitmap shader for the image rep with the passed in scale factor.
-GFX_EXPORT skia::RefPtr<SkShader> CreateImageRepShaderForScale(
+GFX_EXPORT sk_sp<SkShader> CreateImageRepShaderForScale(
     const gfx::ImageSkiaRep& image_rep,
     SkShader::TileMode tile_mode,
     const SkMatrix& local_matrix,
@@ -62,15 +62,15 @@
 
 // Creates a vertical gradient shader. The caller owns the shader.
 // Example usage to avoid leaks:
-GFX_EXPORT skia::RefPtr<SkShader> CreateGradientShader(int start_point,
-                                                       int end_point,
-                                                       SkColor start_color,
-                                                       SkColor end_color);
+GFX_EXPORT sk_sp<SkShader> CreateGradientShader(int start_point,
+                                                int end_point,
+                                                SkColor start_color,
+                                                SkColor end_color);
 
 // Creates a draw looper to generate |shadows|. The caller owns the draw looper.
 // NULL is returned if |shadows| is empty since no draw looper is needed in
 // this case.
-GFX_EXPORT skia::RefPtr<SkDrawLooper> CreateShadowDrawLooper(
+GFX_EXPORT sk_sp<SkDrawLooper> CreateShadowDrawLooper(
     const std::vector<ShadowValue>& shadows);
 
 // Returns true if the two bitmaps contain the same pixels.
diff --git a/ui/gfx/transform.h b/ui/gfx/transform.h
index 7f2c599..2752efd 100644
--- a/ui/gfx/transform.h
+++ b/ui/gfx/transform.h
@@ -9,7 +9,7 @@
 #include <string>
 
 #include "base/compiler_specific.h"
-#include "third_party/skia/include/utils/SkMatrix44.h"
+#include "third_party/skia/include/core/SkMatrix44.h"
 #include "ui/gfx/gfx_export.h"
 #include "ui/gfx/vector2d_f.h"
 
@@ -25,10 +25,7 @@
 // copy/assign.
 class GFX_EXPORT Transform {
  public:
-
-  enum SkipInitialization {
-    kSkipInitialization
-  };
+  enum SkipInitialization { kSkipInitialization };
 
   Transform() : matrix_(SkMatrix44::kIdentity_Constructor) {}
 
@@ -261,11 +258,9 @@
   std::string ToString() const;
 
  private:
-  void TransformPointInternal(const SkMatrix44& xform,
-                              Point* point) const;
+  void TransformPointInternal(const SkMatrix44& xform, Point* point) const;
 
-  void TransformPointInternal(const SkMatrix44& xform,
-                              Point3F* point) const;
+  void TransformPointInternal(const SkMatrix44& xform, Point3F* point) const;
 
   SkMatrix44 matrix_;
 
diff --git a/ui/ozone/demo/software_renderer.cc b/ui/ozone/demo/software_renderer.cc
index 162d5e0..bfb412a 100644
--- a/ui/ozone/demo/software_renderer.cc
+++ b/ui/ozone/demo/software_renderer.cc
@@ -46,7 +46,7 @@
 void SoftwareRenderer::RenderFrame() {
   float fraction = NextFraction();
 
-  skia::RefPtr<SkSurface> surface = software_surface_->GetSurface();
+  sk_sp<SkSurface> surface = software_surface_->GetSurface();
 
   SkColor color =
       SkColorSetARGB(0xff, 0, 0xff * fraction, 0xff * (1 - fraction));
diff --git a/ui/ozone/platform/drm/gpu/drm_buffer.cc b/ui/ozone/platform/drm/gpu/drm_buffer.cc
index 0ab1f61..5c05185 100644
--- a/ui/ozone/platform/drm/gpu/drm_buffer.cc
+++ b/ui/ozone/platform/drm/gpu/drm_buffer.cc
@@ -72,8 +72,7 @@
     return false;
   }
 
-  surface_ =
-      skia::AdoptRef(SkSurface::NewRasterDirect(info, mmap_base_, stride_));
+  surface_ = SkSurface::MakeRasterDirect(info, mmap_base_, stride_);
   if (!surface_) {
     LOG(ERROR) << "DrmBuffer: Failed to create SkSurface: handle " << handle_;
     return false;
diff --git a/ui/ozone/platform/drm/gpu/drm_buffer.h b/ui/ozone/platform/drm/gpu/drm_buffer.h
index 84556ad..8396149 100644
--- a/ui/ozone/platform/drm/gpu/drm_buffer.h
+++ b/ui/ozone/platform/drm/gpu/drm_buffer.h
@@ -6,7 +6,7 @@
 #define UI_OZONE_PLATFORM_DRM_GPU_DRM_BUFFER_H_
 
 #include "base/macros.h"
-#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/core/SkSurface.h"
 #include "ui/ozone/ozone_export.h"
 #include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
@@ -57,7 +57,7 @@
   uint32_t framebuffer_ = 0;
 
   // Wrapper around the native pixel memory.
-  skia::RefPtr<SkSurface> surface_;
+  sk_sp<SkSurface> surface_;
 
   DISALLOW_COPY_AND_ASSIGN(DrmBuffer);
 };
diff --git a/ui/ozone/platform/drm/gpu/drm_console_buffer.cc b/ui/ozone/platform/drm/gpu/drm_console_buffer.cc
index 464c380..0fe4399 100644
--- a/ui/ozone/platform/drm/gpu/drm_console_buffer.cc
+++ b/ui/ozone/platform/drm/gpu/drm_console_buffer.cc
@@ -44,8 +44,7 @@
     return false;
   }
 
-  surface_ =
-      skia::AdoptRef(SkSurface::NewRasterDirect(info, mmap_base_, stride_));
+  surface_ = SkSurface::MakeRasterDirect(info, mmap_base_, stride_);
   if (!surface_)
     return false;
 
diff --git a/ui/ozone/platform/drm/gpu/drm_console_buffer.h b/ui/ozone/platform/drm/gpu/drm_console_buffer.h
index 27dc038..ed46fff 100644
--- a/ui/ozone/platform/drm/gpu/drm_console_buffer.h
+++ b/ui/ozone/platform/drm/gpu/drm_console_buffer.h
@@ -7,7 +7,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/core/SkSurface.h"
 
 class SkCanvas;
@@ -26,9 +26,7 @@
   ~DrmConsoleBuffer();
 
   SkCanvas* canvas() { return surface_->getCanvas(); }
-  skia::RefPtr<SkImage> image() {
-    return skia::AdoptRef(surface_->newImageSnapshot());
-  }
+  sk_sp<SkImage> image() { return surface_->makeImageSnapshot(); }
 
   // Memory map the backing pixels and wrap them in |surface_|.
   bool Initialize();
@@ -37,7 +35,7 @@
   scoped_refptr<DrmDevice> drm_;
 
   // Wrapper around the native pixel memory.
-  skia::RefPtr<SkSurface> surface_;
+  sk_sp<SkSurface> surface_;
 
   // Length of a row of pixels.
   uint32_t stride_ = 0;
diff --git a/ui/ozone/platform/drm/gpu/drm_surface.cc b/ui/ozone/platform/drm/gpu/drm_surface.cc
index 074ac5e..907747f 100644
--- a/ui/ozone/platform/drm/gpu/drm_surface.cc
+++ b/ui/ozone/platform/drm/gpu/drm_surface.cc
@@ -43,14 +43,14 @@
 DrmSurface::~DrmSurface() {
 }
 
-skia::RefPtr<SkSurface> DrmSurface::GetSurface() {
+sk_sp<SkSurface> DrmSurface::GetSurface() {
   return surface_;
 }
 
 void DrmSurface::ResizeCanvas(const gfx::Size& viewport_size) {
   SkImageInfo info = SkImageInfo::MakeN32(
       viewport_size.width(), viewport_size.height(), kOpaque_SkAlphaType);
-  surface_ = skia::AdoptRef(SkSurface::NewRaster(info));
+  surface_ = SkSurface::MakeRaster(info);
 
   HardwareDisplayController* controller = window_delegate_->GetController();
   if (!controller)
@@ -70,7 +70,7 @@
   // Create a snapshot of the requested drawing. If we get here again before
   // presenting, just add the additional damage.
   pending_image_damage_.Union(damage);
-  pending_image_ = skia::AdoptRef(surface_->newImageSnapshot());
+  pending_image_ = surface_->makeImageSnapshot();
 
   if (!pending_pageflip_)
     SchedulePageFlip();
diff --git a/ui/ozone/platform/drm/gpu/drm_surface.h b/ui/ozone/platform/drm/gpu/drm_surface.h
index 65fe969..1768eba 100644
--- a/ui/ozone/platform/drm/gpu/drm_surface.h
+++ b/ui/ozone/platform/drm/gpu/drm_surface.h
@@ -29,7 +29,7 @@
   ~DrmSurface() override;
 
   // SurfaceOzoneCanvas:
-  skia::RefPtr<SkSurface> GetSurface() override;
+  sk_sp<SkSurface> GetSurface() override;
   void ResizeCanvas(const gfx::Size& viewport_size) override;
   void PresentCanvas(const gfx::Rect& damage) override;
   scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() override;
@@ -47,13 +47,13 @@
   scoped_refptr<DrmBuffer> front_buffer_;
   scoped_refptr<DrmBuffer> back_buffer_;
 
-  skia::RefPtr<SkSurface> surface_;
+  sk_sp<SkSurface> surface_;
   gfx::Rect last_damage_;
 
   // Keep track of the requested image and damage for the last presentation.
   // This will be used to update the scanout buffers once the previous page flip
   // events completes.
-  skia::RefPtr<SkImage> pending_image_;
+  sk_sp<SkImage> pending_image_;
   gfx::Rect pending_image_damage_;
   bool pending_pageflip_ = false;
 
diff --git a/ui/ozone/platform/drm/gpu/drm_surface_unittest.cc b/ui/ozone/platform/drm/gpu/drm_surface_unittest.cc
index 4498f1f..156124b 100644
--- a/ui/ozone/platform/drm/gpu/drm_surface_unittest.cc
+++ b/ui/ozone/platform/drm/gpu/drm_surface_unittest.cc
@@ -105,7 +105,7 @@
   drm_->RunCallbacks();
 
   SkBitmap image;
-  std::vector<skia::RefPtr<SkSurface>> framebuffers;
+  std::vector<sk_sp<SkSurface>> framebuffers;
   for (const auto& buffer : drm_->buffers()) {
     // Skip cursor buffers.
     if (buffer->width() == kDefaultCursorSize &&
@@ -157,7 +157,7 @@
   drm_->RunCallbacks();
 
   SkBitmap image;
-  std::vector<skia::RefPtr<SkSurface>> framebuffers;
+  std::vector<sk_sp<SkSurface>> framebuffers;
   for (const auto& buffer : drm_->buffers()) {
     // Skip cursor buffers.
     if (buffer->width() == kDefaultCursorSize &&
diff --git a/ui/ozone/platform/drm/gpu/drm_window_unittest.cc b/ui/ozone/platform/drm/gpu/drm_window_unittest.cc
index abb3129..edd737b 100644
--- a/ui/ozone/platform/drm/gpu/drm_window_unittest.cc
+++ b/ui/ozone/platform/drm/gpu/drm_window_unittest.cc
@@ -32,10 +32,10 @@
 const uint32_t kDefaultConnector = 2;
 const int kDefaultCursorSize = 64;
 
-std::vector<skia::RefPtr<SkSurface>> GetCursorBuffers(
+std::vector<sk_sp<SkSurface>> GetCursorBuffers(
     const scoped_refptr<ui::MockDrmDevice> drm) {
-  std::vector<skia::RefPtr<SkSurface>> cursor_buffers;
-  for (const skia::RefPtr<SkSurface>& cursor_buffer : drm->buffers()) {
+  std::vector<sk_sp<SkSurface>> cursor_buffers;
+  for (const sk_sp<SkSurface>& cursor_buffer : drm->buffers()) {
     if (cursor_buffer->width() == kDefaultCursorSize &&
         cursor_buffer->height() == kDefaultCursorSize) {
       cursor_buffers.push_back(cursor_buffer);
@@ -107,7 +107,7 @@
                   gfx::Point(4, 2), 0);
 
   SkBitmap cursor;
-  std::vector<skia::RefPtr<SkSurface>> cursor_buffers = GetCursorBuffers(drm_);
+  std::vector<sk_sp<SkSurface>> cursor_buffers = GetCursorBuffers(drm_);
   EXPECT_EQ(2u, cursor_buffers.size());
 
   // Buffers 1 is the cursor backbuffer we just drew in.
diff --git a/ui/ozone/platform/drm/gpu/screen_manager.cc b/ui/ozone/platform/drm/gpu/screen_manager.cc
index 4b4d3f1..5797eb1 100644
--- a/ui/ozone/platform/drm/gpu/screen_manager.cc
+++ b/ui/ozone/platform/drm/gpu/screen_manager.cc
@@ -58,7 +58,7 @@
     return;
   }
 
-  skia::RefPtr<SkImage> image = saved_buffer.image();
+  sk_sp<SkImage> image = saved_buffer.image();
   SkPaint paint;
   // Copy the source buffer. Do not perform any blending.
   paint.setXfermodeMode(SkXfermode::kSrc_Mode);
diff --git a/ui/ozone/platform/drm/test/mock_drm_device.cc b/ui/ozone/platform/drm/test/mock_drm_device.cc
index 8999297..525f28e 100644
--- a/ui/ozone/platform/drm/test/mock_drm_device.cc
+++ b/ui/ozone/platform/drm/test/mock_drm_device.cc
@@ -203,8 +203,7 @@
   *handle = allocate_buffer_count_++;
   *stride = info.minRowBytes();
   void* pixels = new char[info.getSafeSize(*stride)];
-  buffers_.push_back(
-      skia::AdoptRef(SkSurface::NewRasterDirect(info, pixels, *stride)));
+  buffers_.push_back(SkSurface::MakeRasterDirect(info, pixels, *stride));
   buffers_[*handle]->getCanvas()->clear(SK_ColorBLACK);
 
   return true;
diff --git a/ui/ozone/platform/drm/test/mock_drm_device.h b/ui/ozone/platform/drm/test/mock_drm_device.h
index a25bad9..eed66a1 100644
--- a/ui/ozone/platform/drm/test/mock_drm_device.h
+++ b/ui/ozone/platform/drm/test/mock_drm_device.h
@@ -9,7 +9,7 @@
 #include <queue>
 #include <vector>
 
-#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/core/SkSurface.h"
 #include "ui/ozone/platform/drm/gpu/drm_device.h"
 
@@ -49,9 +49,7 @@
 
   uint32_t current_framebuffer() const { return current_framebuffer_; }
 
-  const std::vector<skia::RefPtr<SkSurface>> buffers() const {
-    return buffers_;
-  }
+  const std::vector<sk_sp<SkSurface>> buffers() const { return buffers_; }
 
   uint32_t get_cursor_handle_for_crtc(uint32_t crtc) const {
     const auto it = crtc_cursor_map_.find(crtc);
@@ -137,7 +135,7 @@
 
   uint32_t current_framebuffer_;
 
-  std::vector<skia::RefPtr<SkSurface>> buffers_;
+  std::vector<sk_sp<SkSurface>> buffers_;
 
   std::map<uint32_t, uint32_t> crtc_cursor_map_;
 
diff --git a/ui/ozone/platform/test/test_window_manager.cc b/ui/ozone/platform/test/test_window_manager.cc
index cd48bf3..ab57de8 100644
--- a/ui/ozone/platform/test/test_window_manager.cc
+++ b/ui/ozone/platform/test/test_window_manager.cc
@@ -36,10 +36,10 @@
 
   // SurfaceOzoneCanvas overrides:
   void ResizeCanvas(const gfx::Size& viewport_size) override {
-    surface_ = skia::AdoptRef(SkSurface::NewRaster(SkImageInfo::MakeN32Premul(
-        viewport_size.width(), viewport_size.height())));
+    surface_ = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(
+        viewport_size.width(), viewport_size.height()));
   }
-  skia::RefPtr<SkSurface> GetSurface() override { return surface_; }
+  sk_sp<SkSurface> GetSurface() override { return surface_; }
   void PresentCanvas(const gfx::Rect& damage) override {
     if (location_.empty())
       return;
@@ -59,7 +59,7 @@
 
  private:
   base::FilePath location_;
-  skia::RefPtr<SkSurface> surface_;
+  sk_sp<SkSurface> surface_;
 };
 
 }  // namespace
diff --git a/ui/ozone/public/surface_ozone_canvas.h b/ui/ozone/public/surface_ozone_canvas.h
index 42347c3..8a7c4d1 100644
--- a/ui/ozone/public/surface_ozone_canvas.h
+++ b/ui/ozone/public/surface_ozone_canvas.h
@@ -7,7 +7,7 @@
 
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
-#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 #include "ui/ozone/ozone_base_export.h"
 
 class SkSurface;
@@ -28,7 +28,7 @@
   virtual ~SurfaceOzoneCanvas() {}
 
   // Returns an SkSurface for drawing on the window.
-  virtual skia::RefPtr<SkSurface> GetSurface() = 0;
+  virtual sk_sp<SkSurface> GetSurface() = 0;
 
   // Attempts to resize the canvas to match the viewport size. After
   // resizing, the compositor must call GetCanvas() to get the next