void SVGPathElement::svgAttributeChanged(const QualifiedName& attrName) { if (!isSupportedAttribute(attrName)) { SVGGraphicsElement::svgAttributeChanged(attrName); return; } SVGElementInstance::InvalidationGuard invalidationGuard(this); RenderSVGPath* renderer = toRenderSVGPath(this->renderer()); if (attrName == SVGNames::dAttr) { if (m_pathSegList.shouldSynchronize && !SVGAnimatedProperty::lookupWrapper<SVGPathElement, SVGAnimatedPathSegListPropertyTearOff>(this, dPropertyInfo())->isAnimating()) { SVGPathSegList newList(PathSegUnalteredRole); buildSVGPathSegListFromByteStream(m_pathByteStream.get(), this, newList, UnalteredParsing); m_pathSegList.value = newList; } if (renderer) renderer->setNeedsShapeUpdate(); invalidateMPathDependencies(); } if (renderer) RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer); }
void SVGPathElement::pathSegListChanged(SVGPathSegRole role, ListModification listModification) { switch (role) { case PathSegNormalizedRole: // FIXME: https://bugs.webkit.org/show_bug.cgi?id=15412 - Implement normalized path segment lists! break; case PathSegUnalteredRole: if (listModification == ListModificationAppend) { ASSERT(!m_pathSegList.value.isEmpty()); appendSVGPathByteStreamFromSVGPathSeg(m_pathSegList.value.last(), m_pathByteStream.get(), UnalteredParsing); } else buildSVGPathByteStreamFromSVGPathSegList(m_pathSegList.value, m_pathByteStream.get(), UnalteredParsing); break; case PathSegUndefinedRole: return; } invalidateSVGAttributes(); RenderSVGPath* renderer = toRenderSVGPath(this->renderer()); if (!renderer) return; renderer->setNeedsShapeUpdate(); RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer); }
FloatRect SVGPathElement::getBBox(StyleUpdateStrategy styleUpdateStrategy) { if (styleUpdateStrategy == AllowStyleUpdate) document().updateLayoutIgnorePendingStylesheets(); RenderSVGPath* renderer = toRenderSVGPath(this->renderer()); // FIXME: Eventually we should support getBBox for detached elements. if (!renderer) return FloatRect(); return renderer->path().boundingRect(); }
void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout) { bool layoutSizeChanged = findTreeRootObject(start)->isLayoutSizeChanged(); HashSet<RenderObject*> notlayoutedObjects; for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) { bool needsLayout = selfNeedsLayout; if (layoutSizeChanged) { // When selfNeedsLayout is false and the layout size changed, we have to check whether this child uses relative lengths if (SVGElement* element = child->node()->isSVGElement() ? static_cast<SVGElement*>(child->node()) : 0) { if (element->isStyled() && static_cast<SVGStyledElement*>(element)->hasRelativeLengths()) { // When the layout size changed and when using relative values tell the RenderSVGPath to update its Path object if (child->isSVGPath()) toRenderSVGPath(child)->setNeedsPathUpdate(); needsLayout = true; } } } if (needsLayout) { child->setNeedsLayout(true, false); child->layout(); } else { if (child->needsLayout()) child->layout(); else if (layoutSizeChanged) notlayoutedObjects.add(child); } ASSERT(!child->needsLayout()); } if (!layoutSizeChanged) { ASSERT(notlayoutedObjects.isEmpty()); return; } // If the layout size changed, invalidate all resources of all children that didn't go through the layout() code path. HashSet<RenderObject*>::iterator end = notlayoutedObjects.end(); for (HashSet<RenderObject*>::iterator it = notlayoutedObjects.begin(); it != end; ++it) invalidateResourcesOfChildren(*it); }
void write(TextStream& ts, const RenderObject& o, int indent, RenderAsTextBehavior behavior) { #if ENABLE(SVG) if (o.isSVGPath()) { write(ts, *toRenderSVGPath(&o), indent); return; } if (o.isSVGGradientStop()) { writeSVGGradientStop(ts, *toRenderSVGGradientStop(&o), indent); return; } if (o.isSVGResourceContainer()) { writeSVGResourceContainer(ts, o, indent); return; } if (o.isSVGContainer()) { writeSVGContainer(ts, o, indent); return; } if (o.isSVGRoot()) { write(ts, *toRenderSVGRoot(&o), indent); return; } if (o.isSVGText()) { writeSVGText(ts, *toRenderBlock(&o), indent); return; } if (o.isSVGInlineText()) { writeSVGInlineText(ts, *toRenderText(&o), indent); return; } if (o.isSVGImage()) { writeSVGImage(ts, *toRenderSVGImage(&o), indent); return; } #endif writeIndent(ts, indent); RenderTreeAsText::writeRenderObject(ts, o, behavior); ts << "\n"; if (o.isText() && !o.isBR()) { const RenderText& text = *toRenderText(&o); for (InlineTextBox* box = text.firstTextBox(); box; box = box->nextTextBox()) { writeIndent(ts, indent + 1); writeTextRun(ts, text, *box); } } for (RenderObject* child = o.firstChild(); child; child = child->nextSibling()) { if (child->hasLayer()) continue; write(ts, *child, indent + 1, behavior); } if (o.isWidget()) { Widget* widget = toRenderWidget(&o)->widget(); if (widget && widget->isFrameView()) { FrameView* view = static_cast<FrameView*>(widget); RenderView* root = view->frame()->contentRenderer(); if (root) { view->layout(); RenderLayer* l = root->layer(); if (l) writeLayers(ts, l, l, IntRect(l->x(), l->y(), l->width(), l->height()), indent + 1, behavior); } } } }