Bug 1190210 - Part 2: Make sure the size of created ImageBitmap is the same as the intented cropping area. r=roc, a=sledru
authorKaku Kuo <tkuo@mozilla.com>
Thu, 06 Aug 2015 16:58:00 +0800
changeset 288938 9596a39c3e78e3a6e0185df8de285134d7c8a9d7
parent 288937 d7f7113240b378703f29ab65e2ae9ac095bc8af3
child 288939 2ba0588344a220b3f4f28583686b29e1c8ce2ca5
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, sledru
bugs1190210
milestone42.0a2
Bug 1190210 - Part 2: Make sure the size of created ImageBitmap is the same as the intented cropping area. r=roc, a=sledru
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.