PassRefPtr<DisplayList> RenderSVGResourcePattern::asDisplayList(const FloatRect& tileBounds, const AffineTransform& tileTransform) const { ASSERT(!m_shouldCollectPatternAttributes); AffineTransform contentTransform; if (m_attributes.patternContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) contentTransform = tileTransform; // Draw the content into a DisplayList. GraphicsContext recordingContext(nullptr); recordingContext.beginRecording(FloatRect(FloatPoint(), tileBounds.size())); recordingContext.concatCTM(tileTransform); ASSERT(m_attributes.patternContentElement()); RenderSVGResourceContainer* patternRenderer = toRenderSVGResourceContainer(m_attributes.patternContentElement()->renderer()); ASSERT(patternRenderer); ASSERT(!patternRenderer->needsLayout()); SubtreeContentTransformScope contentTransformScope(contentTransform); for (RenderObject* child = patternRenderer->firstChild(); child; child = child->nextSibling()) SVGRenderingContext::renderSubtree(&recordingContext, child); return recordingContext.endRecording(); }
void SVGFilterElement::setFilterRes(unsigned filterResX, unsigned filterResY) { setFilterResXBaseValue(filterResX); setFilterResYBaseValue(filterResY); RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer()); if (renderer) renderer->invalidateCacheAndMarkForLayout(); }
void SVGClipPathElement::svgAttributeChanged(const QualifiedName& attrName) { if (!isSupportedAttribute(attrName)) { SVGGraphicsElement::svgAttributeChanged(attrName); return; } SVGElement::InvalidationGuard invalidationGuard(this); RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer()); if (renderer) renderer->invalidateCacheAndMarkForLayout(); }
void SVGRadialGradientElement::svgAttributeChanged(const QualifiedName& attrName) { if (!isSupportedAttribute(attrName)) { SVGGradientElement::svgAttributeChanged(attrName); return; } SVGElement::InvalidationGuard invalidationGuard(this); updateRelativeLengthsInformation(); RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer()); if (renderer) renderer->invalidateCacheAndMarkForLayout(); }
static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document& document, const SVGPaintType& paintType, const String& paintUri, AtomicString& id, bool& hasPendingResource) { if (paintType != SVG_PAINTTYPE_URI && paintType != SVG_PAINTTYPE_URI_RGBCOLOR && paintType != SVG_PAINTTYPE_URI_CURRENTCOLOR) return 0; id = SVGURIReference::fragmentIdentifierFromIRIString(paintUri, document); RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(document, id); if (!container) { hasPendingResource = true; return 0; } RenderSVGResourceType resourceType = container->resourceType(); if (resourceType != PatternResourceType && resourceType != LinearGradientResourceType && resourceType != RadialGradientResourceType) return 0; return container; }
void RenderSVGGradientStop::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderObject::styleDidChange(diff, oldStyle); if (!diff.hasDifference()) return; // <stop> elements should only be allowed to make renderers under gradient elements // but I can imagine a few cases we might not be catching, so let's not crash if our parent isn't a gradient. SVGGradientElement* gradient = gradientElement(); if (!gradient) return; RenderObject* renderer = gradient->renderer(); if (!renderer) return; RenderSVGResourceContainer* container = toRenderSVGResourceContainer(renderer); container->removeAllClientsFromCache(); }
void SVGMaskElement::svgAttributeChanged(const QualifiedName& attrName) { if (!isSupportedAttribute(attrName)) { SVGElement::svgAttributeChanged(attrName); return; } SVGElement::InvalidationGuard invalidationGuard(this); if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr || attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr) updateRelativeLengthsInformation(); RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer()); if (renderer) renderer->invalidateCacheAndMarkForLayout(); }
static void writeSVGPaintingResource(TextStream& ts, RenderSVGResource* resource) { if (resource->resourceType() == SolidColorResourceType) { ts << "[type=SOLID] [color=" << static_cast<RenderSVGResourceSolidColor*>(resource)->color() << "]"; return; } // All other resources derive from RenderSVGResourceContainer RenderSVGResourceContainer* container = static_cast<RenderSVGResourceContainer*>(resource); SVGElement& element = container->element(); if (resource->resourceType() == PatternResourceType) ts << "[type=PATTERN]"; else if (resource->resourceType() == LinearGradientResourceType) ts << "[type=LINEAR-GRADIENT]"; else if (resource->resourceType() == RadialGradientResourceType) ts << "[type=RADIAL-GRADIENT]"; ts << " [id=\"" << element.getIdAttribute() << "\"]"; }
void SVGResourcesCycleSolver::breakCycle(RenderSVGResourceContainer& resourceLeadingToCycle) { if (&resourceLeadingToCycle == m_resources.linkedResource()) { m_resources.resetLinkedResource(); return; } switch (resourceLeadingToCycle.resourceType()) { case MaskerResourceType: ASSERT(&resourceLeadingToCycle == m_resources.masker()); m_resources.resetMasker(); break; case MarkerResourceType: ASSERT(&resourceLeadingToCycle == m_resources.markerStart() || &resourceLeadingToCycle == m_resources.markerMid() || &resourceLeadingToCycle == m_resources.markerEnd()); if (m_resources.markerStart() == &resourceLeadingToCycle) m_resources.resetMarkerStart(); if (m_resources.markerMid() == &resourceLeadingToCycle) m_resources.resetMarkerMid(); if (m_resources.markerEnd() == &resourceLeadingToCycle) m_resources.resetMarkerEnd(); break; case PatternResourceType: case LinearGradientResourceType: case RadialGradientResourceType: ASSERT(&resourceLeadingToCycle == m_resources.fill() || &resourceLeadingToCycle == m_resources.stroke()); if (m_resources.fill() == &resourceLeadingToCycle) m_resources.resetFill(); if (m_resources.stroke() == &resourceLeadingToCycle) m_resources.resetStroke(); break; case FilterResourceType: #if ENABLE(FILTERS) ASSERT(&resourceLeadingToCycle == m_resources.filter()); m_resources.resetFilter(); #endif break; case ClipperResourceType: ASSERT(&resourceLeadingToCycle == m_resources.clipper()); m_resources.resetClipper(); break; case SolidColorResourceType: ASSERT_NOT_REACHED(); break; } }
void SVGResourcesCache::resourceDestroyed(RenderSVGResourceContainer& resource) { SVGResourcesCache* cache = resourcesCacheFromRenderObject(resource); // The resource itself may have clients, that need to be notified. cache->removeResourcesFromRenderer(resource); for (auto it = cache->m_cache.begin(), end = cache->m_cache.end(); it != end; ++it) { it->value->resourceDestroyed(resource); // Mark users of destroyed resources as pending resolution based on the id of the old resource. Element& resourceElement = resource.element(); Element* clientElement = toElement(it->key->node()); SVGDocumentExtensions* extensions = clientElement->document().accessSVGExtensions(); extensions->addPendingResource(resourceElement.getIdAttribute(), clientElement); } }
void SVGResources::resourceDestroyed(RenderSVGResourceContainer& resource) { if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource) return; if (m_linkedResource == &resource) { ASSERT(!m_clipperFilterMaskerData); ASSERT(!m_markerData); ASSERT(!m_fillStrokeData); m_linkedResource->removeAllClientsFromCache(); m_linkedResource = 0; return; } switch (resource.resourceType()) { case MaskerResourceType: if (!m_clipperFilterMaskerData) break; if (m_clipperFilterMaskerData->masker == &resource) { m_clipperFilterMaskerData->masker->removeAllClientsFromCache(); m_clipperFilterMaskerData->masker = 0; } break; case MarkerResourceType: if (!m_markerData) break; if (m_markerData->markerStart == &resource) { m_markerData->markerStart->removeAllClientsFromCache(); m_markerData->markerStart = 0; } if (m_markerData->markerMid == &resource) { m_markerData->markerMid->removeAllClientsFromCache(); m_markerData->markerMid = 0; } if (m_markerData->markerEnd == &resource) { m_markerData->markerEnd->removeAllClientsFromCache(); m_markerData->markerEnd = 0; } break; case PatternResourceType: case LinearGradientResourceType: case RadialGradientResourceType: if (!m_fillStrokeData) break; if (m_fillStrokeData->fill == &resource) { m_fillStrokeData->fill->removeAllClientsFromCache(); m_fillStrokeData->fill = 0; } if (m_fillStrokeData->stroke == &resource) { m_fillStrokeData->stroke->removeAllClientsFromCache(); m_fillStrokeData->stroke = 0; } break; case FilterResourceType: if (!m_clipperFilterMaskerData) break; if (m_clipperFilterMaskerData->filter == &resource) { m_clipperFilterMaskerData->filter->removeAllClientsFromCache(); m_clipperFilterMaskerData->filter = 0; } break; case ClipperResourceType: if (!m_clipperFilterMaskerData) break; if (m_clipperFilterMaskerData->clipper == &resource) { m_clipperFilterMaskerData->clipper->removeAllClientsFromCache(); m_clipperFilterMaskerData->clipper = 0; } break; case SolidColorResourceType: ASSERT_NOT_REACHED(); } }
void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int indent) { writeStandardPrefix(ts, object, indent); Element* element = toElement(object.node()); const AtomicString& id = element->getIdAttribute(); writeNameAndQuotedValue(ts, "id", id); RenderSVGResourceContainer* resource = const_cast<RenderObject&>(object).toRenderSVGResourceContainer(); ASSERT(resource); if (resource->resourceType() == MaskerResourceType) { RenderSVGResourceMasker* masker = toRenderSVGResourceMasker(resource); writeNameValuePair(ts, "maskUnits", masker->maskUnits()); writeNameValuePair(ts, "maskContentUnits", masker->maskContentUnits()); ts << "\n"; } else if (resource->resourceType() == FilterResourceType) { RenderSVGResourceFilter* filter = toRenderSVGResourceFilter(resource); writeNameValuePair(ts, "filterUnits", filter->filterUnits()); writeNameValuePair(ts, "primitiveUnits", filter->primitiveUnits()); ts << "\n"; // Creating a placeholder filter which is passed to the builder. FloatRect dummyRect; RefPtr<SVGFilter> dummyFilter = SVGFilter::create(AffineTransform(), dummyRect, dummyRect, dummyRect, true); if (RefPtr<SVGFilterBuilder> builder = filter->buildPrimitives(dummyFilter.get())) { if (FilterEffect* lastEffect = builder->lastEffect()) lastEffect->externalRepresentation(ts, indent + 1); } } else if (resource->resourceType() == ClipperResourceType) { writeNameValuePair(ts, "clipPathUnits", toRenderSVGResourceClipper(resource)->clipPathUnits()); ts << "\n"; } else if (resource->resourceType() == MarkerResourceType) { RenderSVGResourceMarker* marker = toRenderSVGResourceMarker(resource); writeNameValuePair(ts, "markerUnits", marker->markerUnits()); ts << " [ref at " << marker->referencePoint() << "]"; ts << " [angle="; if (marker->angle() == -1) ts << "auto" << "]\n"; else ts << marker->angle() << "]\n"; } else if (resource->resourceType() == PatternResourceType) { RenderSVGResourcePattern* pattern = static_cast<RenderSVGResourcePattern*>(resource); // Dump final results that are used for rendering. No use in asking SVGPatternElement for its patternUnits(), as it may // link to other patterns using xlink:href, we need to build the full inheritance chain, aka. collectPatternProperties() PatternAttributes attributes; toSVGPatternElement(pattern->element())->collectPatternAttributes(attributes); writeNameValuePair(ts, "patternUnits", attributes.patternUnits()); writeNameValuePair(ts, "patternContentUnits", attributes.patternContentUnits()); AffineTransform transform = attributes.patternTransform(); if (!transform.isIdentity()) ts << " [patternTransform=" << transform << "]"; ts << "\n"; } else if (resource->resourceType() == LinearGradientResourceType) { RenderSVGResourceLinearGradient* gradient = static_cast<RenderSVGResourceLinearGradient*>(resource); // Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may // link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties() LinearGradientAttributes attributes; toSVGLinearGradientElement(gradient->element())->collectGradientAttributes(attributes); writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.gradientUnits()); ts << " [start=" << gradient->startPoint(attributes) << "] [end=" << gradient->endPoint(attributes) << "]\n"; } else if (resource->resourceType() == RadialGradientResourceType) { RenderSVGResourceRadialGradient* gradient = toRenderSVGResourceRadialGradient(resource); // Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may // link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties() RadialGradientAttributes attributes; toSVGRadialGradientElement(gradient->element())->collectGradientAttributes(attributes); writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.gradientUnits()); FloatPoint focalPoint = gradient->focalPoint(attributes); FloatPoint centerPoint = gradient->centerPoint(attributes); float radius = gradient->radius(attributes); float focalRadius = gradient->focalRadius(attributes); ts << " [center=" << centerPoint << "] [focal=" << focalPoint << "] [radius=" << radius << "] [focalRadius=" << focalRadius << "]\n"; } else ts << "\n"; writeChildren(ts, object, indent); }
void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int indent) { writeStandardPrefix(ts, object, indent); Element* element = static_cast<Element*>(object.node()); const AtomicString& id = element->getIdAttribute(); writeNameAndQuotedValue(ts, "id", id); RenderSVGResourceContainer* resource = const_cast<RenderObject&>(object).toRenderSVGResourceContainer(); ASSERT(resource); if (resource->resourceType() == MaskerResourceType) { RenderSVGResourceMasker* masker = static_cast<RenderSVGResourceMasker*>(resource); writeNameValuePair(ts, "maskUnits", masker->maskUnits()); writeNameValuePair(ts, "maskContentUnits", masker->maskContentUnits()); ts << "\n"; #if ENABLE(FILTERS) } else if (resource->resourceType() == FilterResourceType) { RenderSVGResourceFilter* filter = static_cast<RenderSVGResourceFilter*>(resource); writeNameValuePair(ts, "filterUnits", filter->filterUnits()); writeNameValuePair(ts, "primitiveUnits", filter->primitiveUnits()); ts << "\n"; if (RefPtr<SVGFilterBuilder> builder = filter->buildPrimitives()) { if (FilterEffect* lastEffect = builder->lastEffect()) lastEffect->externalRepresentation(ts, indent + 1); } #endif } else if (resource->resourceType() == ClipperResourceType) { RenderSVGResourceClipper* clipper = static_cast<RenderSVGResourceClipper*>(resource); writeNameValuePair(ts, "clipPathUnits", clipper->clipPathUnits()); ts << "\n"; } else if (resource->resourceType() == MarkerResourceType) { RenderSVGResourceMarker* marker = static_cast<RenderSVGResourceMarker*>(resource); writeNameValuePair(ts, "markerUnits", marker->markerUnits()); ts << " [ref at " << marker->referencePoint() << "]"; ts << " [angle="; if (marker->angle() == -1) ts << "auto" << "]\n"; else ts << marker->angle() << "]\n"; } else if (resource->resourceType() == PatternResourceType) { RenderSVGResourcePattern* pattern = static_cast<RenderSVGResourcePattern*>(resource); // Dump final results that are used for rendering. No use in asking SVGPatternElement for its patternUnits(), as it may // link to other patterns using xlink:href, we need to build the full inheritance chain, aka. collectPatternProperties() PatternAttributes attributes = static_cast<SVGPatternElement*>(pattern->node())->collectPatternProperties(); writeNameValuePair(ts, "patternUnits", boundingBoxModeString(attributes.boundingBoxMode())); writeNameValuePair(ts, "patternContentUnits", boundingBoxModeString(attributes.boundingBoxModeContent())); AffineTransform transform = attributes.patternTransform(); if (!transform.isIdentity()) ts << " [patternTransform=" << transform << "]"; ts << "\n"; } else if (resource->resourceType() == LinearGradientResourceType) { RenderSVGResourceLinearGradient* gradient = static_cast<RenderSVGResourceLinearGradient*>(resource); // Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may // link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties() SVGLinearGradientElement* linearGradientElement = static_cast<SVGLinearGradientElement*>(gradient->node()); LinearGradientAttributes attributes = linearGradientElement->collectGradientProperties(); writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.boundingBoxMode()); FloatPoint startPoint; FloatPoint endPoint; linearGradientElement->calculateStartEndPoints(attributes, startPoint, endPoint); ts << " [start=" << startPoint << "] [end=" << endPoint << "]\n"; } else if (resource->resourceType() == RadialGradientResourceType) { RenderSVGResourceRadialGradient* gradient = static_cast<RenderSVGResourceRadialGradient*>(resource); // Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may // link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties() SVGRadialGradientElement* radialGradientElement = static_cast<SVGRadialGradientElement*>(gradient->node()); RadialGradientAttributes attributes = radialGradientElement->collectGradientProperties(); writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.boundingBoxMode()); FloatPoint focalPoint; FloatPoint centerPoint; float radius; radialGradientElement->calculateFocalCenterPointsAndRadius(attributes, focalPoint, centerPoint, radius); ts << " [center=" << centerPoint << "] [focal=" << focalPoint << "] [radius=" << radius << "]\n"; } else ts << "\n"; writeChildren(ts, object, indent); }