Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / graphics / skia / SkiaUtils.cpp
index ac2a0b3..94d3a29 100644 (file)
@@ -37,7 +37,7 @@
 #include "platform/graphics/GraphicsContext.h"
 #include "platform/graphics/ImageBuffer.h"
 
-namespace WebCore {
+namespace blink {
 
 static const struct CompositOpToXfermodeMode {
     uint8_t mCompositOp;
@@ -58,31 +58,31 @@ static const struct CompositOpToXfermodeMode {
     { CompositePlusLighter,     SkXfermode::kPlus_Mode }
 };
 
-// keep this array in sync with blink::WebBlendMode enum in public/platform/WebBlendMode.h
+// keep this array in sync with WebBlendMode enum in public/platform/WebBlendMode.h
 static const uint8_t gMapBlendOpsToXfermodeModes[] = {
-    SkXfermode::kClear_Mode, // blink::WebBlendModeNormal
-    SkXfermode::kMultiply_Mode, // blink::WebBlendModeMultiply
-    SkXfermode::kScreen_Mode, // blink::WebBlendModeScreen
-    SkXfermode::kOverlay_Mode, // blink::WebBlendModeOverlay
-    SkXfermode::kDarken_Mode, // blink::WebBlendModeDarken
-    SkXfermode::kLighten_Mode, // blink::WebBlendModeLighten
-    SkXfermode::kColorDodge_Mode, // blink::WebBlendModeColorDodge
-    SkXfermode::kColorBurn_Mode, // blink::WebBlendModeColorBurn
-    SkXfermode::kHardLight_Mode, // blink::WebBlendModeHardLight
-    SkXfermode::kSoftLight_Mode, // blink::WebBlendModeSoftLight
-    SkXfermode::kDifference_Mode, // blink::WebBlendModeDifference
-    SkXfermode::kExclusion_Mode, // blink::WebBlendModeExclusion
-    SkXfermode::kHue_Mode, // blink::WebBlendModeHue
-    SkXfermode::kSaturation_Mode, // blink::WebBlendModeSaturation
-    SkXfermode::kColor_Mode, // blink::WebBlendModeColor
-    SkXfermode::kLuminosity_Mode // blink::WebBlendModeLuminosity
+    SkXfermode::kClear_Mode, // WebBlendModeNormal
+    SkXfermode::kMultiply_Mode, // WebBlendModeMultiply
+    SkXfermode::kScreen_Mode, // WebBlendModeScreen
+    SkXfermode::kOverlay_Mode, // WebBlendModeOverlay
+    SkXfermode::kDarken_Mode, // WebBlendModeDarken
+    SkXfermode::kLighten_Mode, // WebBlendModeLighten
+    SkXfermode::kColorDodge_Mode, // WebBlendModeColorDodge
+    SkXfermode::kColorBurn_Mode, // WebBlendModeColorBurn
+    SkXfermode::kHardLight_Mode, // WebBlendModeHardLight
+    SkXfermode::kSoftLight_Mode, // WebBlendModeSoftLight
+    SkXfermode::kDifference_Mode, // WebBlendModeDifference
+    SkXfermode::kExclusion_Mode, // WebBlendModeExclusion
+    SkXfermode::kHue_Mode, // WebBlendModeHue
+    SkXfermode::kSaturation_Mode, // WebBlendModeSaturation
+    SkXfermode::kColor_Mode, // WebBlendModeColor
+    SkXfermode::kLuminosity_Mode // WebBlendModeLuminosity
 };
 
-PassRefPtr<SkXfermode> WebCoreCompositeToSkiaComposite(CompositeOperator op, blink::WebBlendMode blendMode)
+PassRefPtr<SkXfermode> WebCoreCompositeToSkiaComposite(CompositeOperator op, WebBlendMode blendMode)
 {
-    if (blendMode != blink::WebBlendModeNormal) {
+    if (blendMode != WebBlendModeNormal) {
         if ((uint8_t)blendMode >= SK_ARRAY_COUNT(gMapBlendOpsToXfermodeModes)) {
-            SkDEBUGF(("GraphicsContext::setPlatformCompositeOperation unknown blink::WebBlendMode %d\n", blendMode));
+            SkDEBUGF(("GraphicsContext::setPlatformCompositeOperation unknown WebBlendMode %d\n", blendMode));
             return adoptRef(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
         }
         SkXfermode::Mode mode = (SkXfermode::Mode)gMapBlendOpsToXfermodeModes[(uint8_t)blendMode];
@@ -189,4 +189,132 @@ SkMatrix affineTransformToSkMatrix(const AffineTransform& source)
     return result;
 }
 
-}  // namespace WebCore
+bool nearlyIntegral(float value)
+{
+    return fabs(value - floorf(value)) < std::numeric_limits<float>::epsilon();
+}
+
+InterpolationQuality limitInterpolationQuality(const GraphicsContext* context, InterpolationQuality resampling)
+{
+    return std::min(resampling, context->imageInterpolationQuality());
+}
+
+InterpolationQuality computeInterpolationQuality(
+    const SkMatrix& matrix,
+    float srcWidth,
+    float srcHeight,
+    float destWidth,
+    float destHeight,
+    bool isDataComplete)
+{
+    // 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;
+}
+
+
+bool shouldDrawAntiAliased(const 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;
+}
+
+}  // namespace blink