PassOwnPtr<ImageBuffer> SVGMaskElement::drawMaskerContent(const FloatRect& targetRect, FloatRect& maskDestRect) const { // Determine specified mask size float xValue; float yValue; float widthValue; float heightValue; if (maskUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { xValue = x().valueAsPercentage() * targetRect.width(); yValue = y().valueAsPercentage() * targetRect.height(); widthValue = width().valueAsPercentage() * targetRect.width(); heightValue = height().valueAsPercentage() * targetRect.height(); } else { xValue = x().value(this); yValue = y().value(this); widthValue = width().value(this); heightValue = height().value(this); } IntSize imageSize(lroundf(widthValue), lroundf(heightValue)); clampImageBufferSizeToViewport(document()->view(), imageSize); if (imageSize.width() < static_cast<int>(widthValue)) widthValue = imageSize.width(); if (imageSize.height() < static_cast<int>(heightValue)) heightValue = imageSize.height(); OwnPtr<ImageBuffer> maskImage = ImageBuffer::create(imageSize, false); if (!maskImage) return 0; maskDestRect = FloatRect(xValue, yValue, widthValue, heightValue); if (maskUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) maskDestRect.move(targetRect.x(), targetRect.y()); GraphicsContext* maskImageContext = maskImage->context(); ASSERT(maskImageContext); maskImageContext->save(); maskImageContext->translate(-xValue, -yValue); if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { maskImageContext->save(); maskImageContext->scale(FloatSize(targetRect.width(), targetRect.height())); } // Render subtree into ImageBuffer for (Node* n = firstChild(); n; n = n->nextSibling()) { SVGElement* elem = 0; if (n->isSVGElement()) elem = static_cast<SVGElement*>(n); if (!elem || !elem->isStyled()) continue; SVGStyledElement* e = static_cast<SVGStyledElement*>(elem); RenderObject* item = e->renderer(); if (!item) continue; renderSubtreeToImage(maskImage.get(), item); } if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) maskImageContext->restore(); maskImageContext->restore(); return maskImage.release(); }
PassOwnPtr<ImageBuffer> SVGMaskElement::drawMaskerContent(const FloatRect& targetRect, FloatRect& maskDestRect) const { // Determine specified mask size if (maskUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) maskDestRect = FloatRect(x().valueAsPercentage() * targetRect.width(), y().valueAsPercentage() * targetRect.height(), width().valueAsPercentage() * targetRect.width(), height().valueAsPercentage() * targetRect.height()); else maskDestRect = FloatRect(x().value(this), y().value(this), width().value(this), height().value(this)); IntSize imageSize(lroundf(maskDestRect.width()), lroundf(maskDestRect.height())); clampImageBufferSizeToViewport(document()->view(), imageSize); if (imageSize.width() < static_cast<int>(maskDestRect.width())) maskDestRect.setWidth(imageSize.width()); if (imageSize.height() < static_cast<int>(maskDestRect.height())) maskDestRect.setHeight(imageSize.height()); // FIXME: This changes color space to linearRGB, the default color space // for masking operations in SVG. We need a switch for the other color-space // attribute values sRGB, inherit and auto. OwnPtr<ImageBuffer> maskImage = ImageBuffer::create(imageSize, LinearRGB); if (!maskImage) return 0; FloatPoint maskContextLocation = maskDestRect.location(); if (maskUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) maskDestRect.move(targetRect.x(), targetRect.y()); if (maskContentUnits() != SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) maskContextLocation.move(targetRect.x(), targetRect.y()); GraphicsContext* maskImageContext = maskImage->context(); ASSERT(maskImageContext); maskImageContext->save(); maskImageContext->translate(-maskContextLocation.x(), -maskContextLocation.y()); if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { maskImageContext->save(); maskImageContext->scale(FloatSize(targetRect.width(), targetRect.height())); } // Render subtree into ImageBuffer for (Node* n = firstChild(); n; n = n->nextSibling()) { SVGElement* elem = 0; if (n->isSVGElement()) elem = static_cast<SVGElement*>(n); if (!elem || !elem->isStyled()) continue; SVGStyledElement* e = static_cast<SVGStyledElement*>(elem); RenderObject* item = e->renderer(); if (!item) continue; renderSubtreeToImage(maskImage.get(), item); } if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) maskImageContext->restore(); maskImageContext->restore(); return maskImage.release(); }