void SVGImage::drawForContainer(GraphicsContext* context, const FloatSize containerSize, float zoom, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace colorSpace, CompositeOperator compositeOp, BlendMode blendMode) { if (!m_page) return; ImageObserver* observer = imageObserver(); ASSERT(observer); // Temporarily reset image observer, we don't want to receive any changeInRect() calls due to this relayout. setImageObserver(0); IntSize roundedContainerSize = roundedIntSize(containerSize); setContainerSize(roundedContainerSize); FloatRect scaledSrc = srcRect; scaledSrc.scale(1 / zoom); // Compensate for the container size rounding by adjusting the source rect. FloatSize adjustedSrcSize = scaledSrc.size(); adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(), roundedContainerSize.height() / containerSize.height()); scaledSrc.setSize(adjustedSrcSize); draw(context, dstRect, scaledSrc, colorSpace, compositeOp, blendMode); setImageObserver(observer); }
void BitmapImage::drawPattern(GraphicsContext& ctxt, const FloatRect& tileRect, const AffineTransform& transform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, const FloatRect& destRect, BlendMode blendMode) { if (tileRect.isEmpty()) return; if (!ctxt.drawLuminanceMask()) { Image::drawPattern(ctxt, tileRect, transform, phase, spacing, op, destRect, blendMode); return; } if (!m_cachedImage) { auto buffer = ImageBuffer::createCompatibleBuffer(expandedIntSize(tileRect.size()), ctxt); if (!buffer) return; ImageObserver* observer = imageObserver(); ASSERT(observer); // Temporarily reset image observer, we don't want to receive any changeInRect() calls due to this relayout. setImageObserver(nullptr); draw(buffer->context(), tileRect, tileRect, op, blendMode, ImageOrientationDescription()); setImageObserver(observer); buffer->convertToLuminanceMask(); m_cachedImage = buffer->copyImage(DontCopyBackingStore, Unscaled); if (!m_cachedImage) return; } ctxt.setDrawLuminanceMask(false); m_cachedImage->drawPattern(ctxt, tileRect, transform, phase, spacing, op, destRect, blendMode); }
void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& transform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, BlendMode blendMode) { if (tileRect.isEmpty()) return; if (!ctxt->drawLuminanceMask()) { Image::drawPattern(ctxt, tileRect, transform, phase, styleColorSpace, op, destRect, blendMode); return; } if (!m_cachedImage) { OwnPtr<ImageBuffer> buffer = ImageBuffer::create(expandedIntSize(tileRect.size())); ASSERT(buffer.get()); ImageObserver* observer = imageObserver(); ASSERT(observer); // Temporarily reset image observer, we don't want to receive any changeInRect() calls due to this relayout. setImageObserver(0); draw(buffer->context(), tileRect, tileRect, styleColorSpace, op, blendMode); setImageObserver(observer); buffer->convertToLuminanceMask(); m_cachedImage = buffer->copyImage(DontCopyBackingStore, Unscaled); m_cachedImage->setSpaceSize(spaceSize()); setImageObserver(observer); } ctxt->setDrawLuminanceMask(false); m_cachedImage->drawPattern(ctxt, tileRect, transform, phase, styleColorSpace, op, destRect, blendMode); }
void SVGImage::drawSVGToImageBuffer(ImageBuffer* buffer, const IntSize& size, float zoom, ShouldClearBuffer shouldClear) { // FIXME: This doesn't work correctly with animations. If an image contains animations, that say run for 2 seconds, // and we currently have one <img> that displays us. If we open another document referencing the same SVGImage it // will display the document at a time where animations already ran - even though it has its own ImageBuffer. // We currently don't implement SVGSVGElement::setCurrentTime, and can NOT go back in time, once animations started. // There's no way to fix this besides avoiding style/attribute mutations from SVGAnimationElement. ASSERT(buffer); ASSERT(!size.isEmpty()); if (!m_page) return; Frame* frame = m_page->mainFrame(); SVGSVGElement* rootElement = static_cast<SVGDocument*>(frame->document())->rootElement(); if (!rootElement) return; RenderSVGRoot* renderer = toRenderSVGRoot(rootElement->renderer()); if (!renderer) return; // Draw image at requested size. ImageObserver* observer = imageObserver(); ASSERT(observer); // Temporarily reset image observer, we don't want to receive any changeInRect() calls due this relayout. setImageObserver(0); renderer->setContainerSize(size); frame->view()->resize(this->size()); if (zoom != 1) frame->setPageZoomFactor(zoom); // Eventually clear image buffer. IntRect rect(IntPoint(), size); if (shouldClear == ClearImageBuffer) buffer->context()->clearRect(rect); // Draw SVG on top of ImageBuffer. draw(buffer->context(), rect, rect, ColorSpaceDeviceRGB, CompositeSourceOver); // Reset container size & zoom to initial state. Otherwhise the size() of this // image would return whatever last size was set by drawSVGToImageBuffer(). if (zoom != 1) frame->setPageZoomFactor(1); renderer->setContainerSize(IntSize()); frame->view()->resize(this->size()); if (frame->view()->needsLayout()) frame->view()->layout(); setImageObserver(observer); }