Chromium Code Reviews| Index: Source/platform/graphics/Image.cpp |
| diff --git a/Source/platform/graphics/Image.cpp b/Source/platform/graphics/Image.cpp |
| index 368a0373f78afd8d3b3ae495b415c2ef9a31c55d..f3dcdb26f86218abc454c9ec1519fea92cc5ef5e 100644 |
| --- a/Source/platform/graphics/Image.cpp |
| +++ b/Source/platform/graphics/Image.cpp |
| @@ -29,16 +29,20 @@ |
| #include "platform/Length.h" |
| #include "platform/MIMETypeRegistry.h" |
| +#include "platform/PlatformInstrumentation.h" |
| +#include "platform/RuntimeEnabledFeatures.h" |
| #include "platform/SharedBuffer.h" |
| #include "platform/TraceEvent.h" |
| #include "platform/geometry/FloatPoint.h" |
| #include "platform/geometry/FloatRect.h" |
| #include "platform/geometry/FloatSize.h" |
| #include "platform/graphics/BitmapImage.h" |
| +#include "platform/graphics/DeferredImageDecoder.h" |
| #include "platform/graphics/GraphicsContext.h" |
| #include "platform/graphics/GraphicsContextStateSaver.h" |
| #include "public/platform/Platform.h" |
| #include "public/platform/WebData.h" |
| +#include "third_party/skia/include/core/SkCanvas.h" |
| #include "third_party/skia/include/core/SkImage.h" |
| #include "wtf/MainThread.h" |
| #include "wtf/StdLibExtras.h" |
| @@ -222,8 +226,111 @@ void Image::drawPattern(GraphicsContext* context, const FloatRect& floatSrcRect, |
| const FloatPoint& phase, SkXfermode::Mode op, const FloatRect& destRect, const IntSize& repeatSpacing) |
| { |
| TRACE_EVENT0("skia", "Image::drawPattern"); |
| - if (RefPtr<NativeImageSkia> bitmap = nativeImageForCurrentFrame()) |
| - bitmap->drawPattern(context, adjustForNegativeSize(floatSrcRect), scale, phase, op, destRect, repeatSpacing); |
| + SkBitmap bitmap = bitmapForCurrentFrame(); |
| + if (!bitmap.isNull()) { |
| + drawBitmapPattern(context, bitmap, adjustForNegativeSize(floatSrcRect), scale, phase, op, destRect, repeatSpacing); |
|
f(malita)
2015/03/15 00:32:45
I think we could inline drawBitmapPattern here - I
Stephen White
2015/03/15 16:49:31
Done. Also inlined drawBitmap() into BitmapImage,
|
| + } |
| +} |
| + |
| +void Image::drawBitmap( |
| + GraphicsContext* context, |
| + const SkBitmap& bitmap, |
| + const SkRect& srcRect, |
| + const SkRect& destRect, |
| + SkXfermode::Mode op) |
| +{ |
| + TRACE_EVENT0("skia", "Image::drawBitmap"); |
| + |
| + bool isLazyDecoded = DeferredImageDecoder::isLazyDecoded(bitmap); |
| + bool isOpaque = bitmap.isOpaque(); |
| + |
| + { |
| + SkPaint paint; |
| + int initialSaveCount = context->preparePaintForDrawRectToRect(&paint, srcRect, destRect, op, !isOpaque, isLazyDecoded, bitmap.isImmutable()); |
| + // 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 |
| + // don't send extra pixels. |
| + context->drawBitmapRect(bitmap, &srcRect, destRect, &paint); |
| + context->canvas()->restoreToCount(initialSaveCount); |
| + } |
| + |
| + if (isLazyDecoded) |
| + PlatformInstrumentation::didDrawLazyPixelRef(bitmap.getGenerationID()); |
| +} |
| + |
| +static SkBitmap createBitmapWithSpace(const SkBitmap& bitmap, int spaceWidth, int spaceHeight) |
| +{ |
| + SkImageInfo info = bitmap.info(); |
| + info = SkImageInfo::Make(info.width() + spaceWidth, info.height() + spaceHeight, info.colorType(), kPremul_SkAlphaType); |
| + |
| + SkBitmap result; |
| + result.allocPixels(info); |
| + result.eraseColor(SK_ColorTRANSPARENT); |
| + bitmap.copyPixelsTo(reinterpret_cast<uint8_t*>(result.getPixels()), result.rowBytes() * result.height(), result.rowBytes()); |
| + |
| + return result; |
| +} |
| + |
| +void Image::drawBitmapPattern( |
| + GraphicsContext* context, |
| + const SkBitmap& bitmap, |
| + const FloatRect& floatSrcRect, |
| + const FloatSize& scale, |
| + const FloatPoint& phase, |
| + SkXfermode::Mode compositeOp, |
| + const FloatRect& destRect, |
| + const IntSize& repeatSpacing) |
| +{ |
| + FloatRect normSrcRect = floatSrcRect; |
| + normSrcRect.intersect(FloatRect(0, 0, bitmap.width(), bitmap.height())); |
| + if (destRect.isEmpty() || normSrcRect.isEmpty()) |
| + return; // nothing to draw |
| + |
| + SkMatrix localMatrix; |
| + // We also need to translate it such that the origin of the pattern is the |
| + // origin of the destination rect, which is what WebKit expects. Skia uses |
| + // the coordinate system origin as the base for the pattern. If WebKit wants |
| + // a shifted image, it will shift it from there using the localMatrix. |
| + const float adjustedX = phase.x() + normSrcRect.x() * scale.width(); |
| + const float adjustedY = phase.y() + normSrcRect.y() * scale.height(); |
| + localMatrix.setTranslate(SkFloatToScalar(adjustedX), SkFloatToScalar(adjustedY)); |
| + |
| + // Because no resizing occurred, the shader transform should be |
| + // set to the pattern's transform, which just includes scale. |
| + localMatrix.preScale(scale.width(), scale.height()); |
| + |
| + SkBitmap bitmapToPaint; |
| + bitmap.extractSubset(&bitmapToPaint, enclosingIntRect(normSrcRect)); |
| + if (!repeatSpacing.isZero()) { |
| + SkScalar ctmScaleX = 1.0; |
| + SkScalar ctmScaleY = 1.0; |
| + |
| + if (!RuntimeEnabledFeatures::slimmingPaintEnabled()) { |
| + AffineTransform ctm = context->getCTM(); |
| + ctmScaleX = ctm.xScale(); |
| + ctmScaleY = ctm.yScale(); |
| + } |
| + |
| + bitmapToPaint = createBitmapWithSpace( |
| + bitmapToPaint, |
| + repeatSpacing.width() * ctmScaleX / scale.width(), |
| + repeatSpacing.height() * ctmScaleY / scale.height()); |
| + } |
| + RefPtr<SkShader> shader = adoptRef(SkShader::CreateBitmapShader(bitmapToPaint, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix)); |
| + |
| + bool isLazyDecoded = DeferredImageDecoder::isLazyDecoded(bitmap); |
| + { |
| + SkPaint paint; |
| + int initialSaveCount = context->preparePaintForDrawRectToRect(&paint, floatSrcRect, |
| + destRect, compositeOp, !bitmap.isOpaque(), isLazyDecoded, bitmap.isImmutable()); |
| + paint.setShader(shader.get()); |
| + context->drawRect(destRect, paint); |
| + context->canvas()->restoreToCount(initialSaveCount); |
| + } |
| + |
| + if (isLazyDecoded) |
| + PlatformInstrumentation::didDrawLazyPixelRef(bitmap.getGenerationID()); |
| } |
| void Image::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio) |