Bug 1190210 - Part 2: Make sure the size of created ImageBitmap is the same as the intented cropping area. r=roc
authorKaku Kuo <tkuo@mozilla.com>
Thu, 06 Aug 2015 16:58:00 +0800
changeset 258158 d25a897f1e9d5981d291b1e316ae2978066f0068
parent 258157 9a8c950d08effc16b9caf23e1fa39b4c1e1d077e
child 258159 dfa165b74218afa2957a6a2918fe3225b5696fb9
push id63841
push userryanvm@gmail.com
push dateTue, 18 Aug 2015 14:08:57 +0000
treeherdermozilla-inbound@230bde30c650 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs1190210
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1190210 - Part 2: Make sure the size of created ImageBitmap is the same as the intented cropping area. r=roc
dom/canvas/ImageBitmap.cpp
--- a/dom/canvas/ImageBitmap.cpp
+++ b/dom/canvas/ImageBitmap.cpp
@@ -448,45 +448,61 @@ ImageBitmap::PrepareForDrawTarget(gfx::D
       mSurface = nullptr;
       RefPtr<gfx::SourceSurface> surface(mSurface);
       return surface.forget();
     }
 
     IntPoint dest(std::max(0, surfPortion.X() - mPictureRect.X()),
                   std::max(0, surfPortion.Y() - mPictureRect.Y()));
 
-    // Do not initialize this target with mPictureRect.Size().
-    // In the Windows8 D2D1 backend, it might trigger "partial upload" from a
-    // non-SourceSurfaceD2D1 surface to a D2D1Image in the following
-    // CopySurface() step. However, the "partial upload" only supports uploading
-    // a rectangle starts from the upper-left point, which means it cannot
-    // upload an arbitrary part of the source surface and this causes problems
-    // if the mPictureRect is not starts from the upper-left point.
-    target = target->CreateSimilarDrawTarget(mSurface->GetSize(),
+    // We must initialize this target with mPictureRect.Size() because the
+    // specification states that if the cropping area is given, then return an
+    // ImageBitmap with the size equals to the cropping area.
+    target = target->CreateSimilarDrawTarget(mPictureRect.Size(),
                                              target->GetFormat());
 
     if (!target) {
       mSurface = nullptr;
       RefPtr<gfx::SourceSurface> surface(mSurface);
       return surface.forget();
     }
 
+    // We need to fall back to generic copying and cropping for the Windows8.1,
+    // D2D1 backend.
+    // In the Windows8.1 D2D1 backend, it might trigger "partial upload" from a
+    // non-SourceSurfaceD2D1 surface to a D2D1Image in the following
+    // CopySurface() step. However, the "partial upload" only supports uploading
+    // a rectangle starts from the upper-left point, which means it cannot
+    // upload an arbitrary part of the source surface and this causes problems
+    // if the mPictureRect is not starts from the upper-left point.
+    if (target->GetBackendType() == BackendType::DIRECT2D1_1 &&
+        mSurface->GetType() != SurfaceType::D2D1_1_IMAGE) {
+      RefPtr<DataSourceSurface> dataSurface = mSurface->GetDataSurface();
+      if (NS_WARN_IF(!dataSurface)) {
+        mSurface = nullptr;
+        RefPtr<gfx::SourceSurface> surface(mSurface);
+        return surface.forget();
+      }
+
+      mSurface = CropAndCopyDataSourceSurface(dataSurface, mPictureRect);
+    } else {
+      target->CopySurface(mSurface, surfPortion, dest);
+      mSurface = target->Snapshot();
+    }
+
     // Make mCropRect match new surface we've cropped to
     mPictureRect.MoveTo(0, 0);
-    target->CopySurface(mSurface, surfPortion, dest);
-    mSurface = target->Snapshot();
   }
 
   // Replace our surface with one optimized for the target we're about to draw
   // to, under the assumption it'll likely be drawn again to that target.
   // This call should be a no-op for already-optimized surfaces
   mSurface = target->OptimizeSourceSurface(mSurface);
 
   RefPtr<gfx::SourceSurface> surface(mSurface);
-
   return surface.forget();
 }
 
 /* static */ already_AddRefed<ImageBitmap>
 ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLImageElement& aImageEl,
                             const Maybe<IntRect>& aCropRect, ErrorResult& aRv)
 {
   // Check if the image element is completely available or not.