PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternAttributes& attributes, const FloatRect& tileBoundaries, const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform) const { FloatRect clampedAbsoluteTileBoundaries = SVGRenderingContext::clampedAbsoluteTargetRect(absoluteTileBoundaries); IntSize imageSize(roundedIntSize(clampedAbsoluteTileBoundaries.size())); if (imageSize.isEmpty()) return nullptr; OwnPtr<ImageBuffer> tileImage = ImageBuffer::create(imageSize); if (!tileImage) return nullptr; GraphicsContext* tileImageContext = tileImage->context(); ASSERT(tileImageContext); IntSize unclampedImageSize(roundedIntSize(absoluteTileBoundaries.size())); tileImageContext->scale(unclampedImageSize.width() / absoluteTileBoundaries.width(), unclampedImageSize.height() / absoluteTileBoundaries.height()); // The image buffer represents the final rendered size, so the content has to be scaled (to avoid pixelation). tileImageContext->scale( clampedAbsoluteTileBoundaries.width() / tileBoundaries.width(), clampedAbsoluteTileBoundaries.height() / tileBoundaries.height()); // Apply tile image transformations. if (!tileImageTransform.isIdentity()) tileImageContext->concatCTM(tileImageTransform); AffineTransform contentTransformation; if (attributes.patternContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) contentTransformation = tileImageTransform; // Draw the content into the ImageBuffer. for (Element* element = ElementTraversal::firstWithin(*attributes.patternContentElement()); element; element = ElementTraversal::nextSibling(*element)) { if (!element->isSVGElement() || !element->renderer()) continue; if (element->renderer()->needsLayout()) return nullptr; SVGRenderingContext::renderSubtree(tileImage->context(), element->renderer(), contentTransformation); } return tileImage.release(); }
bool SVGImageBufferTools::createImageBuffer(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, OwnPtr<ImageBuffer>& imageBuffer, ColorSpace colorSpace, RenderingMode renderingMode) { IntSize imageSize(roundedImageBufferSize(clampedAbsoluteTargetRect.size())); IntSize unclampedImageSize(SVGImageBufferTools::roundedImageBufferSize(absoluteTargetRect.size())); // Don't create empty ImageBuffers. if (imageSize.isEmpty()) return false; OwnPtr<ImageBuffer> image = ImageBuffer::create(imageSize, colorSpace, renderingMode); if (!image) return false; GraphicsContext* imageContext = image->context(); ASSERT(imageContext); // Compensate rounding effects, as the absolute target rect is using floating-point numbers and the image buffer size is integer. imageContext->scale(FloatSize(unclampedImageSize.width() / absoluteTargetRect.width(), unclampedImageSize.height() / absoluteTargetRect.height())); imageBuffer = image.release(); return true; }