Bug 987292 - drawImage does not resample outside source rect r=jmuizelaar
authorRik Cabanier <cabanier@adobe.com>
Mon, 24 Mar 2014 14:10:00 +0100
changeset 195056 cafd9175112f6bff12705dc822c7f5f7d37914a9
parent 195055 6d2ffe8dc04699778a59491472d1532d59d5de9a
child 195057 d44bebf793fdf79907db60f4a1363fe49f683c78
push idunknown
push userunknown
push dateunknown
reviewersjmuizelaar
bugs987292
milestone31.0a1
Bug 987292 - drawImage does not resample outside source rect r=jmuizelaar
gfx/2d/DrawTargetCG.cpp
--- a/gfx/2d/DrawTargetCG.cpp
+++ b/gfx/2d/DrawTargetCG.cpp
@@ -297,38 +297,53 @@ DrawTargetCG::DrawSurface(SourceSurface 
 
   CGContextSetBlendMode(mCg, ToBlendMode(aDrawOptions.mCompositionOp));
   UnboundnessFixer fixer;
   CGContextRef cg = fixer.Check(mCg, aDrawOptions.mCompositionOp);
   CGContextSetAlpha(cg, aDrawOptions.mAlpha);
   CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AntialiasMode::NONE);
 
   CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform));
-  CGImageRef image = GetRetainedImageFromSourceSurface(aSurface);
-
-  /* we have two options here:
-   *  - create a subimage -- this is slower
-   *  - fancy things with clip and different dest rects */
-  CGImageRef subimage = CGImageCreateWithImageInRect(image, RectToCGRect(aSource));
-  CGImageRelease(image);
-
-  CGContextScaleCTM(cg, 1, -1);
-
-  CGRect flippedRect = CGRectMake(aDest.x, -(aDest.y + aDest.height),
-                                  aDest.width, aDest.height);
 
   CGContextSetInterpolationQuality(cg, InterpolationQualityFromFilter(aSurfOptions.mFilter));
 
-  CGContextDrawImage(cg, flippedRect, subimage);
+  CGImageRef image = GetRetainedImageFromSourceSurface(aSurface);
+
+  if (aSurfOptions.mFilter == Filter::POINT) {
+    CGImageRef subimage = CGImageCreateWithImageInRect(image, RectToCGRect(aSource));
+    CGImageRelease(image);
+
+    CGContextScaleCTM(cg, 1, -1);
+
+    CGRect flippedRect = CGRectMake(aDest.x, -(aDest.y + aDest.height),
+                                    aDest.width, aDest.height);
+
+    CGContextDrawImage(cg, flippedRect, subimage);
+    CGImageRelease(subimage);
+  } else {
+    CGRect destRect = CGRectMake(aDest.x, aDest.y, aDest.width, aDest.height);
+    CGContextClipToRect(cg, destRect);
+
+    float xScale = aSource.width / aDest.width;
+    float yScale = aSource.height / aDest.height;
+    CGContextTranslateCTM(cg, aDest.x - aSource.x / xScale, aDest.y - aSource.y / yScale);
+
+    CGRect adjustedDestRect = CGRectMake(0, 0, CGImageGetWidth(image) / xScale,
+                                         CGImageGetHeight(image) / yScale);
+
+    CGContextTranslateCTM(cg, 0, CGRectGetHeight(adjustedDestRect));
+    CGContextScaleCTM(cg, 1, -1);
+
+    CGContextDrawImage(cg, adjustedDestRect, image);
+    CGImageRelease(image);
+  }
 
   fixer.Fix(mCg);
 
   CGContextRestoreGState(mCg);
-
-  CGImageRelease(subimage);
 }
 
 TemporaryRef<FilterNode>
 DrawTargetCG::CreateFilter(FilterType aType)
 {
   return FilterNodeSoftware::Create(aType);
 }