Chromium Code Reviews| Index: Source/platform/graphics/GraphicsContext.cpp |
| diff --git a/Source/platform/graphics/GraphicsContext.cpp b/Source/platform/graphics/GraphicsContext.cpp |
| index 6a237098cdcb61b57229a281df6ce90c46aad1ad..fb1d974483acbfb6b5bc01007b337a6883c78e7c 100644 |
| --- a/Source/platform/graphics/GraphicsContext.cpp |
| +++ b/Source/platform/graphics/GraphicsContext.cpp |
| @@ -1125,6 +1125,15 @@ void GraphicsContext::drawImageBuffer(ImageBuffer* image, const FloatRect& dest, |
| image->draw(this, dest, src, op, blendMode); |
| } |
| +static inline bool pictureScaleIsApproximatelyOne(float x) |
| +{ |
| + // Function used to validate canvas scale factor. |
| + // Numerical error should not reach 6th decimal except for highly degenerate cases, |
| + // and effect of 6th decimal on scale is negligible over max span of a skia canvas |
| + // which is 32k pixels. |
| + return x > 0.999999 && x < 1.000001; |
|
Stephen White
2014/10/16 17:38:00
Could you put this in a constant at the start of t
|
| +} |
| + |
| void GraphicsContext::drawPicture(PassRefPtr<SkPicture> picture, const FloatRect& dest, const FloatRect& src, CompositeOperator op, WebBlendMode blendMode) |
| { |
| ASSERT(m_canvas); |
| @@ -1134,22 +1143,35 @@ void GraphicsContext::drawPicture(PassRefPtr<SkPicture> picture, const FloatRect |
| SkMatrix ctm = m_canvas->getTotalMatrix(); |
| SkRect deviceDest; |
| ctm.mapRect(&deviceDest, dest); |
| - SkRect sourceBounds = WebCoreFloatRectToSKRect(src); |
| + float scaleX = deviceDest.width() / src.width(); |
| + float scaleY = deviceDest.height() / src.height(); |
| - RefPtr<SkPictureImageFilter> pictureFilter = adoptRef(SkPictureImageFilter::Create(picture.get(), sourceBounds)); |
| - SkMatrix layerScale; |
| - layerScale.setScale(deviceDest.width() / src.width(), deviceDest.height() / src.height()); |
| - RefPtr<SkMatrixImageFilter> matrixFilter = adoptRef(SkMatrixImageFilter::Create(layerScale, SkPaint::kLow_FilterLevel, pictureFilter.get())); |
| SkPaint picturePaint; |
| picturePaint.setXfermodeMode(WebCoreCompositeToSkiaComposite(op, blendMode)); |
| - picturePaint.setImageFilter(matrixFilter.get()); |
| - SkRect layerBounds = SkRect::MakeWH(std::max(deviceDest.width(), sourceBounds.width()), std::max(deviceDest.height(), sourceBounds.height())); |
| - m_canvas->save(); |
| - m_canvas->resetMatrix(); |
| - m_canvas->translate(deviceDest.x(), deviceDest.y()); |
| - m_canvas->saveLayer(&layerBounds, &picturePaint); |
| - m_canvas->restore(); |
| - m_canvas->restore(); |
| + SkRect sourceBounds = WebCoreFloatRectToSKRect(src); |
| + if (pictureScaleIsApproximatelyOne(scaleX * m_deviceScaleFactor) && pictureScaleIsApproximatelyOne(scaleY * m_deviceScaleFactor)) { |
|
Stephen White
2014/10/16 17:38:00
I'm not certain, but I think that using the device
|
| + // Fast path for canvases that are rasterized at screen resolution |
| + SkRect skBounds = WebCoreFloatRectToSKRect(dest); |
| + m_canvas->saveLayer(&skBounds, &picturePaint); |
| + SkMatrix pictureTransform; |
| + pictureTransform.setRectToRect(sourceBounds, skBounds, SkMatrix::kFill_ScaleToFit); |
| + m_canvas->concat(pictureTransform); |
| + m_canvas->drawPicture(picture.get()); |
| + m_canvas->restore(); |
| + } else { |
| + RefPtr<SkPictureImageFilter> pictureFilter = adoptRef(SkPictureImageFilter::Create(picture.get(), sourceBounds)); |
| + SkMatrix layerScale; |
| + layerScale.setScale(scaleX, scaleY); |
| + RefPtr<SkMatrixImageFilter> matrixFilter = adoptRef(SkMatrixImageFilter::Create(layerScale, SkPaint::kLow_FilterLevel, pictureFilter.get())); |
| + picturePaint.setImageFilter(matrixFilter.get()); |
| + SkRect layerBounds = SkRect::MakeWH(std::max(deviceDest.width(), sourceBounds.width()), std::max(deviceDest.height(), sourceBounds.height())); |
| + m_canvas->save(); |
| + m_canvas->resetMatrix(); |
| + m_canvas->translate(deviceDest.x(), deviceDest.y()); |
| + m_canvas->saveLayer(&layerBounds, &picturePaint); |
| + m_canvas->restore(); |
| + m_canvas->restore(); |
| + } |
| } |
| void GraphicsContext::writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y) |