void writeRenderResources(TextStream& ts, Node* parent) { ASSERT(parent); Node* node = parent; do { if (!node->isSVGElement()) continue; SVGElement* svgElement = static_cast<SVGElement*>(node); if (!svgElement->isStyled()) continue; SVGStyledElement* styled = static_cast<SVGStyledElement*>(svgElement); RefPtr<SVGResource> resource(styled->canvasResource()); if (!resource) continue; String elementId = svgElement->getAttribute(svgElement->idAttributeName()); // FIXME: These names are lies! if (resource->isPaintServer()) { RefPtr<SVGPaintServer> paintServer = WTF::static_pointer_cast<SVGPaintServer>(resource); ts << "KRenderingPaintServer {id=\"" << elementId << "\" " << *paintServer << "}" << "\n"; } else ts << "KCanvasResource {id=\"" << elementId << "\" " << *resource << "}" << "\n"; } while ((node = node->traverseNextNode(parent))); }
FloatRect RenderSVGPath::calculateMarkerBoundsIfNeeded() { SVGElement* svgElement = static_cast<SVGElement*>(node()); ASSERT(svgElement && svgElement->document()); if (!svgElement->isStyled()) return FloatRect(); SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); if (!styledElement->supportsMarkers()) return FloatRect(); const SVGRenderStyle* svgStyle = style()->svgStyle(); ASSERT(svgStyle->hasMarkers()); SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this); if (!resources) return FloatRect(); RenderSVGResourceMarker* markerStart = resources->markerStart(); RenderSVGResourceMarker* markerMid = resources->markerMid(); RenderSVGResourceMarker* markerEnd = resources->markerEnd(); if (!markerStart && !markerMid && !markerEnd) return FloatRect(); return m_markerLayoutInfo.calculateBoundaries(markerStart, markerMid, markerEnd, svgStyle->strokeWidth().value(svgElement), m_path); }
static DeprecatedString getTagName(void *node) { SVGStyledElement *elem = static_cast<SVGStyledElement *>(node); if (elem) return String(elem->nodeName()).deprecatedString(); return DeprecatedString(); }
KCanvasClipper *SVGClipPathElement::canvasResource() { if (!view()) return 0; if (!m_clipper) m_clipper = static_cast<KCanvasClipper *>(renderingDevice()->createResource(RS_CLIPPER)); else m_clipper->resetClipData(); bool bbox = clipPathUnits()->baseVal() == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; RenderStyle *clipPathStyle = styleForRenderer(parent()->renderer()); // FIXME: Manual style resolution is a hack for (Node *n = firstChild(); n != 0; n = n->nextSibling()) { SVGElement *e = svg_dynamic_cast(n); if (e && e->isStyled()) { SVGStyledElement *styled = static_cast<SVGStyledElement *>(e); RenderStyle *pathStyle = document()->styleSelector()->styleForElement(styled, clipPathStyle); if (KCanvasPath* pathData = styled->toPathData()) m_clipper->addClipData(pathData, (KCWindRule) pathStyle->svgStyle()->clipRule(), bbox); pathStyle->deref(view()->renderArena()); } } clipPathStyle->deref(view()->renderArena()); return m_clipper; }
void SVGResource::invalidate() { HashSet<SVGStyledElement*>::const_iterator it = m_clients.begin(); const HashSet<SVGStyledElement*>::const_iterator end = m_clients.end(); for (; it != end; ++it) { SVGStyledElement* cur = *it; if (cur->renderer()) cur->renderer()->setNeedsLayout(true); cur->invalidateResourcesInAncestorChain(); } }
float SVGRenderStyle::cssPrimitiveToLength(const RenderObject* item, CSSValue* value, float defaultValue) { CSSPrimitiveValue* primitive = static_cast<CSSPrimitiveValue*>(value); unsigned short cssType = (primitive ? primitive->primitiveType() : (unsigned short) CSSPrimitiveValue::CSS_UNKNOWN); if (!(cssType > CSSPrimitiveValue::CSS_UNKNOWN && cssType <= CSSPrimitiveValue::CSS_PC)) return defaultValue; if (cssType == CSSPrimitiveValue::CSS_PERCENTAGE) { SVGStyledElement* element = static_cast<SVGStyledElement*>(item->node()); SVGElement* viewportElement = (element ? element->viewportElement() : 0); if (viewportElement) { float result = primitive->getFloatValue() / 100.0f; return SVGLength::PercentageOfViewport(result, element, LengthModeOther); } } return primitive->computeLengthFloat(const_cast<RenderStyle*>(item->style()), item->document()->documentElement()->renderStyle()); }
void RenderPath::calculateMarkerBoundsIfNeeded() const { Document* doc = document(); SVGElement* svgElement = static_cast<SVGElement*>(node()); ASSERT(svgElement && svgElement->document()); if (!svgElement->isStyled()) return; SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); if (!styledElement->supportsMarkers()) return; const SVGRenderStyle* svgStyle = style()->svgStyle(); AtomicString startMarkerId(svgStyle->startMarker()); AtomicString midMarkerId(svgStyle->midMarker()); AtomicString endMarkerId(svgStyle->endMarker()); SVGResourceMarker* startMarker = getMarkerById(doc, startMarkerId, this); SVGResourceMarker* midMarker = getMarkerById(doc, midMarkerId, this); SVGResourceMarker* endMarker = getMarkerById(doc, endMarkerId, this); if (!startMarker && !startMarkerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(startMarkerId, styledElement); else if (startMarker) startMarker->addClient(styledElement); if (!midMarker && !midMarkerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(midMarkerId, styledElement); else if (midMarker) midMarker->addClient(styledElement); if (!endMarker && !endMarkerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(endMarkerId, styledElement); else if (endMarker) endMarker->addClient(styledElement); if (!startMarker && !midMarker && !endMarker) return; float strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, svgStyle->strokeWidth(), 1.0f); m_cachedLocalMarkerBBox = m_markerLayoutInfo.calculateBoundaries(startMarker, midMarker, endMarker, strokeWidth, m_path); }
void SVGGradientElement::notifyAttributeChange() const { if(ownerDocument()->parsing() || !attached()) return; // Update clients of this gradient resource... buildGradient(m_resource); m_resource->invalidate(); // should this be added to build gradient? const KCanvasItemList &clients = m_resource->clients(); for(KCanvasItemList::ConstIterator it = clients.begin(); it != clients.end(); ++it) { const RenderPath *current = (*it); SVGStyledElement *styled = (current ? static_cast<SVGStyledElement *>(current->element()) : 0); if(styled) styled->setChanged(true); } }
void SVGResourcesCache::resourceDestroyed(RenderSVGResourceContainer* resource) { ASSERT(resource); SVGResourcesCache* cache = resourcesCacheFromRenderObject(resource); // The resource itself may have clients, that need to be notified. cache->removeResourcesFromRenderObject(resource); HashMap<RenderObject*, SVGResources*>::iterator end = cache->m_cache.end(); for (HashMap<RenderObject*, SVGResources*>::iterator it = cache->m_cache.begin(); it != end; ++it) { it->second->resourceDestroyed(resource); // Mark users of destroyed resources as pending resolution based on the id of the old resource. Element* resourceElement = toElement(resource->node()); SVGStyledElement* clientElement = toSVGStyledElement(it->first->node()); SVGDocumentExtensions* extensions = clientElement->document()->accessSVGExtensions(); extensions->addPendingResource(resourceElement->fastGetAttribute(HTMLNames::idAttr), clientElement); } }
void SVGPatternElement::notifyClientsToRepaint() const { const KCanvasItemList &clients = m_paintServer->clients(); KCanvasItemList::ConstIterator it = clients.begin(); KCanvasItemList::ConstIterator end = clients.end(); for(; it != end; ++it) { const RenderPath *current = (*it); SVGStyledElement* styled = (current ? static_cast<SVGStyledElement* >(current->element()) : 0); if (styled) { styled->setChanged(true); if (styled->renderer()) styled->renderer()->repaint(); } } }
void writeRenderResources(TextStream &ts, Node *parent) { ASSERT(parent); Node *node = parent; do { if (!node->isSVGElement()) continue; SVGElement *svgElement = static_cast<SVGElement *>(node); if (!svgElement->isStyled()) continue; SVGStyledElement *styled = static_cast<SVGStyledElement *>(svgElement); KCanvasResource *resource = styled->canvasResource(); if (!resource) continue; DeprecatedString elementId = svgElement->getAttribute(HTMLNames::idAttr).deprecatedString(); if (resource->isPaintServer()) ts << "KRenderingPaintServer {id=\"" << elementId << "\" " << *static_cast<KRenderingPaintServer *>(resource) << "}" << endl; else ts << "KCanvasResource {id=\"" << elementId << "\" " << *resource << "}" << endl; } while ((node = node->traverseNextNode(parent))); }
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(); }
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(); }
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(); }
void SVGPatternElement::drawPatternContentIntoTile(const SVGPatternElement* target, const IntSize& newSize, KCanvasMatrix patternTransformMatrix) const { KRenderingDevice* device = renderingDevice(); SVGStyledElement* activeElement = static_cast<SVGStyledElement*>(m_paintServer->activeClient()->element()); bool bbox = (patternUnits()->baseVal() == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX); const SVGStyledElement* savedContext = 0; if (bbox) { if (width()->baseVal()->unitType() != SVGLength::SVG_LENGTHTYPE_PERCENTAGE) width()->baseVal()->newValueSpecifiedUnits(SVGLength::SVG_LENGTHTYPE_PERCENTAGE, width()->baseVal()->value() * 100.); if (height()->baseVal()->unitType() != SVGLength::SVG_LENGTHTYPE_PERCENTAGE) height()->baseVal()->newValueSpecifiedUnits(SVGLength::SVG_LENGTHTYPE_PERCENTAGE, height()->baseVal()->value() * 100.); if (activeElement) savedContext = const_cast<SVGPatternElement* >(this)->pushAttributeContext(activeElement); } delete m_tile; m_tile = static_cast<KCanvasImage*>(device->createResource(RS_IMAGE)); m_tile->init(newSize); KRenderingDeviceContext* patternContext = device->contextForImage(m_tile); device->pushContext(patternContext); FloatRect rect(x()->baseVal()->value(), y()->baseVal()->value(), width()->baseVal()->value(), height()->baseVal()->value()); m_paintServer->setBbox(rect); m_paintServer->setPatternTransform(patternTransformMatrix); m_paintServer->setTile(m_tile); OwnPtr<GraphicsContext> context(patternContext->createGraphicsContext()); for(Node *n = target->firstChild(); n != 0; n = n->nextSibling()) { SVGElement* elem = svg_dynamic_cast(n); if (!elem || !elem->isStyled()) continue; SVGStyledElement* e = static_cast<SVGStyledElement* >(elem); RenderObject *item = e->renderer(); if (!item) continue; #if 0 // FIXME: None of this code seems to be necessary // to pass the w3c tests (and infact breaks them) // However, I'm leaving it #if 0'd for now until // I can quiz WildFox on the subject -- ecs 11/24/05 // It's possible that W3C-SVG-1.1/coords-units-01-b // is failing due to lack of this code. KCanvasMatrix savedMatrix = item->localTransform(); const SVGStyledElement* savedContext = 0; if (patternContentUnits()->baseVal() == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { if (activeElement) savedContext = e->pushAttributeContext(activeElement); } // Take into account viewportElement's viewBox, if existant... if (viewportElement() && viewportElement()->hasTagName(SVGNames::svgTag)) { SVGSVGElement* svgElement = static_cast<SVGSVGElement* >(viewportElement()); RefPtr<SVGMatrix> svgCTM = svgElement->getCTM(); RefPtr<SVGMatrix> ctm = getCTM(); KCanvasMatrix newMatrix(svgCTM->matrix()); newMatrix.multiply(savedMatrix); newMatrix.scale(1.0 / ctm->a(), 1.0 / ctm->d()); item->setLocalTransform(newMatrix.matrix()); } #endif RenderObject::PaintInfo info(context.get(), IntRect(), PaintPhaseForeground, 0, 0, 0); item->paint(info, 0, 0); #if 0 if (savedContext) e->pushAttributeContext(savedContext); item->setLocalTransform(savedMatrix.matrix()); #endif } if (savedContext) const_cast<SVGPatternElement* >(this)->pushAttributeContext(savedContext); device->popContext(); delete patternContext; }