bool SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& repaintRect, RenderSVGResourceFilter*& filter, RenderSVGResourceFilter* rootFilter) { #if !ENABLE(FILTERS) UNUSED_PARAM(filter); UNUSED_PARAM(rootFilter); #endif ASSERT(object); SVGElement* svgElement = static_cast<SVGElement*>(object->node()); ASSERT(svgElement && svgElement->document() && svgElement->isStyled()); SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); RenderStyle* style = object->style(); ASSERT(style); const SVGRenderStyle* svgStyle = style->svgStyle(); ASSERT(svgStyle); // Setup transparency layers before setting up filters! float opacity = style->opacity(); if (opacity < 1.0f) { paintInfo.context->clip(repaintRect); paintInfo.context->beginTransparencyLayer(opacity); } if (const ShadowData* shadow = svgStyle->shadow()) { paintInfo.context->clip(repaintRect); paintInfo.context->setShadow(IntSize(shadow->x(), shadow->y()), shadow->blur(), shadow->color(), style->colorSpace()); paintInfo.context->beginTransparencyLayer(1.0f); } #if ENABLE(FILTERS) AtomicString filterId(svgStyle->filterResource()); #endif AtomicString clipperId(svgStyle->clipperResource()); AtomicString maskerId(svgStyle->maskerResource()); Document* document = object->document(); #if ENABLE(FILTERS) RenderSVGResourceFilter* newFilter = getRenderSVGResourceById<RenderSVGResourceFilter>(document, filterId); if (newFilter == rootFilter) { // Catch <text filter="url(#foo)">Test<tspan filter="url(#foo)">123</tspan></text>. // The filter is NOT meant to be applied twice in that case! filter = 0; filterId = String(); } else filter = newFilter; #endif if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(document, maskerId)) { if (!masker->applyResource(object, style, paintInfo.context, ApplyToDefaultMode)) return false; } else if (!maskerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(document, clipperId)) clipper->applyResource(object, style, paintInfo.context, ApplyToDefaultMode); else if (!clipperId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement); #if ENABLE(FILTERS) if (filter) { if (!filter->applyResource(object, style, paintInfo.context, ApplyToDefaultMode)) return false; } else if (!filterId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement); #endif return true; }
void SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& boundingBox, SVGResourceFilter*& filter, SVGResourceFilter* rootFilter) { #if !ENABLE(FILTERS) UNUSED_PARAM(filter); UNUSED_PARAM(rootFilter); #endif ASSERT(object); SVGElement* svgElement = static_cast<SVGElement*>(object->node()); ASSERT(svgElement && svgElement->document() && svgElement->isStyled()); SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); const RenderStyle* style = object->style(); ASSERT(style); const SVGRenderStyle* svgStyle = style->svgStyle(); ASSERT(svgStyle); // Setup transparency layers before setting up filters! float opacity = style->opacity(); if (opacity < 1.0f) { paintInfo.context->clip(enclosingIntRect(boundingBox)); paintInfo.context->beginTransparencyLayer(opacity); } #if ENABLE(FILTERS) AtomicString filterId(svgStyle->filter()); #endif AtomicString clipperId(svgStyle->clipPath()); AtomicString maskerId(svgStyle->maskElement()); Document* document = object->document(); #if ENABLE(FILTERS) SVGResourceFilter* newFilter = getFilterById(document, filterId); if (newFilter == rootFilter) { // Catch <text filter="url(#foo)">Test<tspan filter="url(#foo)">123</tspan></text>. // The filter is NOT meant to be applied twice in that case! filter = 0; filterId = String(); } else filter = newFilter; #endif SVGResourceClipper* clipper = getClipperById(document, clipperId); SVGResourceMasker* masker = getMaskerById(document, maskerId); #if ENABLE(FILTERS) if (filter) { filter->addClient(styledElement); filter->prepareFilter(paintInfo.context, object); } else if (!filterId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement); #endif if (clipper) { clipper->addClient(styledElement); clipper->applyClip(paintInfo.context, boundingBox); } else if (!clipperId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement); if (masker) { masker->addClient(styledElement); masker->applyMask(paintInfo.context, boundingBox); } else if (!maskerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); }
void RenderSVGContainer::paint(PaintInfo& paintInfo, int parentX, int parentY) { if (paintInfo.context->paintingDisabled()) return; // This should only exist for <svg> renderers if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)) paintBoxDecorations(paintInfo, m_x + parentX, m_y + parentY); if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE) paintOutline(paintInfo.context, parentX, parentY, width(), height(), style()); if (paintInfo.phase != PaintPhaseForeground || !drawsContents()) return; const SVGRenderStyle* svgStyle = style()->svgStyle(); AtomicString filterId(SVGURIReference::getTarget(svgStyle->filter())); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) SVGResourceFilter* filter = getFilterById(document(), filterId); #endif if (!firstChild() #if ENABLE(SVG_EXPERIMENTAL_FEATURES) && !filter #endif ) return; // Spec: groups w/o children still may render filter content. paintInfo.context->save(); if (!parent()->isSVGContainer()) { // Translate from parent offsets (html renderers) to a relative transform (svg renderers) IntPoint origin; origin.move(parentX, parentY); origin.move(m_x, m_y); origin.move(borderLeft(), borderTop()); origin.move(paddingLeft(), paddingTop()); if (origin.x() || origin.y()) { paintInfo.context->concatCTM(AffineTransform().translate(origin.x(), origin.y())); paintInfo.rect.move(-origin.x(), -origin.y()); } parentX = parentY = 0; SVGSVGElement* svg = static_cast<SVGSVGElement*>(element()); paintInfo.context->concatCTM(AffineTransform().scale(svg->currentScale())); } else { // Only the root <svg> element should need any translations using the HTML/CSS system // parentX, parentY are also non-zero for first-level kids of these // CSS-transformed <svg> root-elements (due to RenderBox::paint) for any other element // they should be 0. m_x, m_y should always be 0 for non-root svg containers ASSERT(m_x == 0); ASSERT(m_y == 0); } if (!viewport().isEmpty()) { if (style()->overflowX() != OVISIBLE) paintInfo.context->clip(enclosingIntRect(viewport())); // FIXME: Eventually we'll want float-precision clipping paintInfo.context->concatCTM(AffineTransform().translate(viewport().x(), viewport().y())); } if (!localTransform().isIdentity()) paintInfo.context->concatCTM(localTransform()); if (!parent()->isSVGContainer()) { SVGSVGElement* svg = static_cast<SVGSVGElement*>(element()); paintInfo.context->concatCTM(AffineTransform().translate(svg->currentTranslate().x(), svg->currentTranslate().y())); } FloatRect strokeBBox = relativeBBox(true); SVGElement* svgElement = static_cast<SVGElement*>(element()); ASSERT(svgElement && svgElement->document() && svgElement->isStyled()); SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); AtomicString clipperId(SVGURIReference::getTarget(svgStyle->clipPath())); AtomicString maskerId(SVGURIReference::getTarget(svgStyle->maskElement())); SVGResourceClipper* clipper = getClipperById(document(), clipperId); SVGResourceMasker* masker = getMaskerById(document(), maskerId); if (clipper) { clipper->addClient(styledElement); clipper->applyClip(paintInfo.context, strokeBBox); } else if (!clipperId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement); if (masker) { masker->addClient(styledElement); masker->applyMask(paintInfo.context, strokeBBox); } else if (!maskerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); float opacity = style()->opacity(); if (opacity < 1.0f) { paintInfo.context->clip(enclosingIntRect(strokeBBox)); paintInfo.context->beginTransparencyLayer(opacity); } #if ENABLE(SVG_EXPERIMENTAL_FEATURES) if (filter) filter->prepareFilter(paintInfo.context, strokeBBox); else if (!filterId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement); #endif if (!viewBox().isEmpty()) paintInfo.context->concatCTM(viewportTransform()); RenderContainer::paint(paintInfo, 0, 0); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) if (filter) filter->applyFilter(paintInfo.context, strokeBBox); #endif if (opacity < 1.0f) paintInfo.context->endTransparencyLayer(); paintInfo.context->restore(); }
void RenderPath::paint(PaintInfo& paintInfo, int, int) { if (paintInfo.context->paintingDisabled() || (paintInfo.phase != PaintPhaseForeground) || style()->visibility() == HIDDEN || m_path.isEmpty()) return; paintInfo.context->save(); paintInfo.context->concatCTM(localTransform()); FloatRect strokeBBox = relativeBBox(true); SVGElement* svgElement = static_cast<SVGElement*>(element()); ASSERT(svgElement && svgElement->document() && svgElement->isStyled()); SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); const SVGRenderStyle* svgStyle = style()->svgStyle(); AtomicString filterId(SVGURIReference::getTarget(svgStyle->filter())); AtomicString clipperId(SVGURIReference::getTarget(svgStyle->clipPath())); AtomicString maskerId(SVGURIReference::getTarget(svgStyle->maskElement())); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) SVGResourceFilter* filter = getFilterById(document(), filterId); #endif SVGResourceClipper* clipper = getClipperById(document(), clipperId); SVGResourceMasker* masker = getMaskerById(document(), maskerId); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) if (filter) filter->prepareFilter(paintInfo.context, strokeBBox); else if (!filterId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement); #endif if (clipper) { clipper->addClient(styledElement); clipper->applyClip(paintInfo.context, strokeBBox); } else if (!clipperId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement); if (masker) { masker->addClient(styledElement); masker->applyMask(paintInfo.context, strokeBBox); } else if (!maskerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); paintInfo.context->beginPath(); SVGPaintServer* fillPaintServer = KSVGPainterFactory::fillPaintServer(style(), this); if (fillPaintServer) { paintInfo.context->addPath(m_path); fillPaintServer->draw(paintInfo.context, this, ApplyToFillTargetType); } SVGPaintServer* strokePaintServer = KSVGPainterFactory::strokePaintServer(style(), this); if (strokePaintServer) { paintInfo.context->addPath(m_path); // path is cleared when filled. strokePaintServer->draw(paintInfo.context, this, ApplyToStrokeTargetType); } if (styledElement->supportsMarkers()) m_markerBounds = drawMarkersIfNeeded(paintInfo.context, paintInfo.rect, m_path); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) // actually apply the filter if (filter) filter->applyFilter(paintInfo.context, strokeBBox); #endif paintInfo.context->restore(); }
void RenderSVGImage::paint(PaintInfo& paintInfo, int parentX, int parentY) { if (paintInfo.context->paintingDisabled() || (paintInfo.phase != PaintPhaseForeground) || style()->visibility() == HIDDEN) return; paintInfo.context->save(); paintInfo.context->concatCTM(AffineTransform().translate(parentX, parentY)); paintInfo.context->concatCTM(localTransform()); paintInfo.context->concatCTM(translationForAttributes()); FloatRect boundingBox = FloatRect(0, 0, width(), height()); SVGElement* svgElement = static_cast<SVGElement*>(element()); ASSERT(svgElement && svgElement->document() && svgElement->isStyled()); SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); const SVGRenderStyle* svgStyle = style()->svgStyle(); AtomicString filterId(SVGURIReference::getTarget(svgStyle->filter())); AtomicString clipperId(SVGURIReference::getTarget(svgStyle->clipPath())); AtomicString maskerId(SVGURIReference::getTarget(svgStyle->maskElement())); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) SVGResourceFilter* filter = getFilterById(document(), filterId); #endif SVGResourceClipper* clipper = getClipperById(document(), clipperId); SVGResourceMasker* masker = getMaskerById(document(), maskerId); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) if (filter) filter->prepareFilter(paintInfo.context, boundingBox); else if (!filterId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement); #endif if (clipper) { clipper->addClient(styledElement); clipper->applyClip(paintInfo.context, boundingBox); } else if (!clipperId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement); if (masker) { masker->addClient(styledElement); masker->applyMask(paintInfo.context, boundingBox); } else if (!maskerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); float opacity = style()->opacity(); if (opacity < 1.0f) { paintInfo.context->clip(enclosingIntRect(boundingBox)); paintInfo.context->beginTransparencyLayer(opacity); } PaintInfo pi(paintInfo); pi.rect = absoluteTransform().inverse().mapRect(pi.rect); SVGImageElement* imageElt = static_cast<SVGImageElement*>(node()); FloatRect destRect(m_x, m_y, contentWidth(), contentHeight()); FloatRect srcRect(0, 0, image()->width(), image()->height()); if (imageElt->preserveAspectRatio()->align() != SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE) adjustRectsForAspectRatio(destRect, srcRect, imageElt->preserveAspectRatio()); paintInfo.context->drawImage(image(), destRect, srcRect); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) if (filter) filter->applyFilter(paintInfo.context, boundingBox); #endif if (opacity < 1.0f) paintInfo.context->endTransparencyLayer(); paintInfo.context->restore(); }