Index: Source/platform/graphics/skia/NativeImageSkia.cpp |
diff --git a/Source/platform/graphics/skia/NativeImageSkia.cpp b/Source/platform/graphics/skia/NativeImageSkia.cpp |
index 50a31c7fc4718573c223235b55f25161dffc4344..618669d9e6dfbd78fbadf9fe6febb6389bd18238 100644 |
--- a/Source/platform/graphics/skia/NativeImageSkia.cpp |
+++ b/Source/platform/graphics/skia/NativeImageSkia.cpp |
@@ -46,118 +46,10 @@ |
#include "third_party/skia/include/core/SkScalar.h" |
#include "third_party/skia/include/core/SkShader.h" |
-#include <algorithm> |
#include <math.h> |
-#include <limits> |
namespace blink { |
-static bool nearlyIntegral(float value) |
-{ |
- return fabs(value - floorf(value)) < std::numeric_limits<float>::epsilon(); |
-} |
- |
-InterpolationQuality NativeImageSkia::computeInterpolationQuality(const SkMatrix& matrix, float srcWidth, float srcHeight, float destWidth, float destHeight) const |
-{ |
- // The percent change below which we will not resample. This usually means |
- // an off-by-one error on the web page, and just doing nearest neighbor |
- // sampling is usually good enough. |
- const float kFractionalChangeThreshold = 0.025f; |
- |
- // Images smaller than this in either direction are considered "small" and |
- // are not resampled ever (see below). |
- const int kSmallImageSizeThreshold = 8; |
- |
- // The amount an image can be stretched in a single direction before we |
- // say that it is being stretched so much that it must be a line or |
- // background that doesn't need resampling. |
- const float kLargeStretch = 3.0f; |
- |
- // Figure out if we should resample this image. We try to prune out some |
- // common cases where resampling won't give us anything, since it is much |
- // slower than drawing stretched. |
- float diffWidth = fabs(destWidth - srcWidth); |
- float diffHeight = fabs(destHeight - srcHeight); |
- bool widthNearlyEqual = diffWidth < std::numeric_limits<float>::epsilon(); |
- bool heightNearlyEqual = diffHeight < std::numeric_limits<float>::epsilon(); |
- // We don't need to resample if the source and destination are the same. |
- if (widthNearlyEqual && heightNearlyEqual) |
- return InterpolationNone; |
- |
- if (srcWidth <= kSmallImageSizeThreshold |
- || srcHeight <= kSmallImageSizeThreshold |
- || destWidth <= kSmallImageSizeThreshold |
- || destHeight <= kSmallImageSizeThreshold) { |
- // Small image detected. |
- |
- // Resample in the case where the new size would be non-integral. |
- // This can cause noticeable breaks in repeating patterns, except |
- // when the source image is only one pixel wide in that dimension. |
- if ((!nearlyIntegral(destWidth) && srcWidth > 1 + std::numeric_limits<float>::epsilon()) |
- || (!nearlyIntegral(destHeight) && srcHeight > 1 + std::numeric_limits<float>::epsilon())) |
- return InterpolationLow; |
- |
- // Otherwise, don't resample small images. These are often used for |
- // borders and rules (think 1x1 images used to make lines). |
- return InterpolationNone; |
- } |
- |
- if (srcHeight * kLargeStretch <= destHeight || srcWidth * kLargeStretch <= destWidth) { |
- // Large image detected. |
- |
- // Don't resample if it is being stretched a lot in only one direction. |
- // This is trying to catch cases where somebody has created a border |
- // (which might be large) and then is stretching it to fill some part |
- // of the page. |
- if (widthNearlyEqual || heightNearlyEqual) |
- return InterpolationNone; |
- |
- // The image is growing a lot and in more than one direction. Resampling |
- // is slow and doesn't give us very much when growing a lot. |
- return InterpolationLow; |
- } |
- |
- if ((diffWidth / srcWidth < kFractionalChangeThreshold) |
- && (diffHeight / srcHeight < kFractionalChangeThreshold)) { |
- // It is disappointingly common on the web for image sizes to be off by |
- // one or two pixels. We don't bother resampling if the size difference |
- // is a small fraction of the original size. |
- return InterpolationNone; |
- } |
- |
- // When the image is not yet done loading, use linear. We don't cache the |
- // partially resampled images, and as they come in incrementally, it causes |
- // us to have to resample the whole thing every time. |
- if (!isDataComplete()) |
- return InterpolationLow; |
- |
- // Everything else gets resampled. |
- // High quality interpolation only enabled for scaling and translation. |
- if (!(matrix.getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask))) |
- return InterpolationHigh; |
- |
- return InterpolationLow; |
-} |
- |
-static InterpolationQuality limitInterpolationQuality(GraphicsContext* context, InterpolationQuality resampling) |
-{ |
- return std::min(resampling, context->imageInterpolationQuality()); |
-} |
- |
-static SkPaint::FilterLevel convertToSkiaFilterLevel(bool useBicubicFilter, InterpolationQuality resampling) |
-{ |
- // FIXME: If we get rid of this special case, this function can go away entirely. |
- if (useBicubicFilter) |
- return SkPaint::kHigh_FilterLevel; |
- |
- // InterpolationHigh if useBicubicFilter is false means that we do |
- // a manual high quality resampling before drawing to Skia. |
- if (resampling == InterpolationHigh) |
- return SkPaint::kNone_FilterLevel; |
- |
- return static_cast<SkPaint::FilterLevel>(resampling); |
-} |
- |
// This function is used to scale an image and extract a scaled fragment. |
// |
// ALGORITHM |
@@ -275,77 +167,19 @@ SkBitmap NativeImageSkia::resizedBitmap(const SkISize& scaledImageSize, const Sk |
return resizedSubset; |
} |
-static bool shouldDrawAntiAliased(GraphicsContext* context, const SkRect& destRect) |
-{ |
- if (!context->shouldAntialias()) |
- return false; |
- const SkMatrix totalMatrix = context->getTotalMatrix(); |
- // Don't disable anti-aliasing if we're rotated or skewed. |
- if (!totalMatrix.rectStaysRect()) |
- return true; |
- // Disable anti-aliasing for scales or n*90 degree rotations. |
- // Allow to opt out of the optimization though for "hairline" geometry |
- // images - using the shouldAntialiasHairlineImages() GraphicsContext flag. |
- if (!context->shouldAntialiasHairlineImages()) |
- return false; |
- // Check if the dimensions of the destination are "small" (less than one |
- // device pixel). To prevent sudden drop-outs. Since we know that |
- // kRectStaysRect_Mask is set, the matrix either has scale and no skew or |
- // vice versa. We can query the kAffine_Mask flag to determine which case |
- // it is. |
- // FIXME: This queries the CTM while drawing, which is generally |
- // discouraged. Always drawing with AA can negatively impact performance |
- // though - that's why it's not always on. |
- SkScalar widthExpansion, heightExpansion; |
- if (totalMatrix.getType() & SkMatrix::kAffine_Mask) |
- widthExpansion = totalMatrix[SkMatrix::kMSkewY], heightExpansion = totalMatrix[SkMatrix::kMSkewX]; |
- else |
- widthExpansion = totalMatrix[SkMatrix::kMScaleX], heightExpansion = totalMatrix[SkMatrix::kMScaleY]; |
- return destRect.width() * fabs(widthExpansion) < 1 || destRect.height() * fabs(heightExpansion) < 1; |
-} |
- |
-void NativeImageSkia::draw(GraphicsContext* context, const SkRect& srcRect, const SkRect& destRect, PassRefPtr<SkXfermode> compOp) const |
+void NativeImageSkia::draw( |
+ GraphicsContext* context, |
+ const SkRect& srcRect, |
+ const SkRect& destRect, |
+ CompositeOperator compositeOp, |
+ blink::WebBlendMode blendMode) const |
{ |
TRACE_EVENT0("skia", "NativeImageSkia::draw"); |
- SkPaint paint; |
- paint.setXfermode(compOp.get()); |
- paint.setColorFilter(context->colorFilter()); |
- paint.setAlpha(context->getNormalizedAlpha()); |
- paint.setLooper(context->drawLooper()); |
- paint.setAntiAlias(shouldDrawAntiAliased(context, destRect)); |
bool isLazyDecoded = DeferredImageDecoder::isLazyDecoded(bitmap()); |
- InterpolationQuality resampling; |
- if (context->isAccelerated()) { |
- resampling = InterpolationLow; |
- } else if (context->printing()) { |
- resampling = InterpolationNone; |
- } else if (isLazyDecoded) { |
- resampling = InterpolationHigh; |
- } else { |
- // Take into account scale applied to the canvas when computing sampling mode (e.g. CSS scale or page scale). |
- SkRect destRectTarget = destRect; |
- SkMatrix totalMatrix = context->getTotalMatrix(); |
- if (!(totalMatrix.getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask))) |
- totalMatrix.mapRect(&destRectTarget, destRect); |
- |
- resampling = computeInterpolationQuality(totalMatrix, |
- SkScalarToFloat(srcRect.width()), SkScalarToFloat(srcRect.height()), |
- SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTarget.height())); |
- } |
- |
- if (resampling == InterpolationNone) { |
- // FIXME: This is to not break tests (it results in the filter bitmap flag |
- // being set to true). We need to decide if we respect InterpolationNone |
- // being returned from computeInterpolationQuality. |
- resampling = InterpolationLow; |
- } |
- resampling = limitInterpolationQuality(context, resampling); |
- |
- bool useBicubicFilter = resampling == InterpolationHigh; |
- paint.setFilterLevel(convertToSkiaFilterLevel(useBicubicFilter, resampling)); |
- |
+ SkPaint paint; |
+ context->preparePaintForDrawRectToRect(&paint, srcRect, destRect, compositeOp, blendMode, isLazyDecoded, isDataComplete()); |
// We want to filter it if we decided to do interpolation above, or if |
// there is something interesting going on with the matrix (like a rotation). |
// Note: for serialization, we will want to subset the bitmap first so we |
@@ -411,7 +245,7 @@ void NativeImageSkia::drawPattern( |
else if (isLazyDecoded) |
resampling = InterpolationHigh; |
else |
- resampling = computeInterpolationQuality(totalMatrix, normSrcRect.width(), normSrcRect.height(), destBitmapWidth, destBitmapHeight); |
+ resampling = computeInterpolationQuality(totalMatrix, normSrcRect.width(), normSrcRect.height(), destBitmapWidth, destBitmapHeight, isDataComplete()); |
resampling = limitInterpolationQuality(context, resampling); |
SkMatrix localMatrix; |