void SVGImage::drawPatternForContainer(GraphicsContext* context, const FloatSize containerSize, float zoom, const FloatRect& srcRect, const FloatSize& scale, const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& dstRect, blink::WebBlendMode blendMode, const IntSize& repeatSpacing) { FloatRect zoomedContainerRect = FloatRect(FloatPoint(), containerSize); zoomedContainerRect.scale(zoom); // The ImageBuffer size needs to be scaled to match the final resolution. // FIXME: No need to get the full CTM here, we just need the scale. AffineTransform transform = context->getCTM(); FloatSize imageBufferScale = FloatSize(transform.xScale(), transform.yScale()); ASSERT(imageBufferScale.width()); ASSERT(imageBufferScale.height()); FloatSize scaleWithoutCTM(scale.width() / imageBufferScale.width(), scale.height() / imageBufferScale.height()); FloatRect imageBufferSize = zoomedContainerRect; imageBufferSize.scale(imageBufferScale.width(), imageBufferScale.height()); OwnPtr<ImageBuffer> buffer = ImageBuffer::create(expandedIntSize(imageBufferSize.size())); if (!buffer) // Failed to allocate buffer. return; drawForContainer(buffer->context(), containerSize, zoom, imageBufferSize, zoomedContainerRect, CompositeSourceOver, blink::WebBlendModeNormal); RefPtr<Image> image = buffer->copyImage(DontCopyBackingStore, Unscaled); // Adjust the source rect and transform due to the image buffer's scaling. FloatRect scaledSrcRect = srcRect; scaledSrcRect.scale(imageBufferScale.width(), imageBufferScale.height()); image->drawPattern(context, scaledSrcRect, scaleWithoutCTM, phase, compositeOp, dstRect, blendMode, repeatSpacing); }
void GeneratorGeneratedImage::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const FloatSize& scale, const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& destRect, BlendMode) { // Allow the generator to provide visually-equivalent tiling parameters for better performance. IntSize adjustedSize = m_size; FloatRect adjustedSrcRect = srcRect; m_gradient->adjustParametersForTiledDrawing(adjustedSize, adjustedSrcRect); // Factor in the destination context's scale to generate at the best resolution. // FIXME: No need to get the full CTM here, we just need the scale. AffineTransform destContextCTM = destContext->getCTM(GraphicsContext::DefinitelyIncludeDeviceScale); float xScale = fabs(destContextCTM.xScale()); float yScale = fabs(destContextCTM.yScale()); FloatSize scaleWithoutCTM(scale.width() / xScale, scale.height() / yScale); adjustedSrcRect.scale(xScale, yScale); unsigned generatorHash = m_gradient->hash(); if (!m_cachedImageBuffer || m_cachedGeneratorHash != generatorHash || m_cachedAdjustedSize != adjustedSize || !destContext->isCompatibleWithBuffer(m_cachedImageBuffer.get())) { m_cachedImageBuffer = destContext->createCompatibleBuffer(adjustedSize, m_gradient->hasAlpha()); if (!m_cachedImageBuffer) return; // Fill with the generated image. m_cachedImageBuffer->context()->setFillGradient(m_gradient); m_cachedImageBuffer->context()->fillRect(FloatRect(FloatPoint(), adjustedSize)); m_cachedGeneratorHash = generatorHash; m_cachedAdjustedSize = adjustedSize; } // Tile the image buffer into the context. m_cachedImageBuffer->drawPattern(destContext, adjustedSrcRect, scaleWithoutCTM, phase, compositeOp, destRect); m_cacheTimer.restart(); }