Commit b958999a authored by Fredrik Söderqvist's avatar Fredrik Söderqvist Committed by Chromium LUCI CQ

Rework inheritance for SVG <pattern>

Switch SVGPatternElement to use an observer scheme similar to that used
by SVGGradientElement - i.e using an IdTargetObserver. Implement an
override of FindCycleFromSelf() on LayoutSVGResourcePattern to handle
the cycle-checking for the inheritance link.
LayoutSVGResourcePattern is refactored a little in the process to allow
reusing the attribute collection phase.
This drops the only remaining user of SVGResources::LinkedResource(), so
it and its associated code can be removed as well.

Bug: 1028063
Change-Id: I228f80fb707921ccab695ee8a573d17c0498fcbe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2584307Reviewed-by: default avatarStephen Chenney <schenney@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#836111}
parent 345c368a
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h" #include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
#include "third_party/blink/renderer/core/layout/svg/svg_resources.h" #include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
#include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h"
#include "third_party/blink/renderer/core/paint/svg_object_painter.h" #include "third_party/blink/renderer/core/paint/svg_object_painter.h"
#include "third_party/blink/renderer/core/svg/svg_fit_to_view_box.h" #include "third_party/blink/renderer/core/svg/svg_fit_to_view_box.h"
#include "third_party/blink/renderer/core/svg/svg_pattern_element.h" #include "third_party/blink/renderer/core/svg/svg_pattern_element.h"
...@@ -57,6 +56,7 @@ void LayoutSVGResourcePattern::RemoveAllClientsFromCache() { ...@@ -57,6 +56,7 @@ void LayoutSVGResourcePattern::RemoveAllClientsFromCache() {
NOT_DESTROYED(); NOT_DESTROYED();
pattern_map_->clear(); pattern_map_->clear();
should_collect_pattern_attributes_ = true; should_collect_pattern_attributes_ = true;
To<SVGPatternElement>(*GetElement()).InvalidateDependentPatterns();
MarkAllClientsForInvalidation(SVGResourceClient::kPaintInvalidation); MarkAllClientsForInvalidation(SVGResourceClient::kPaintInvalidation);
} }
...@@ -70,11 +70,7 @@ bool LayoutSVGResourcePattern::RemoveClientFromCache( ...@@ -70,11 +70,7 @@ bool LayoutSVGResourcePattern::RemoveClientFromCache(
return true; return true;
} }
std::unique_ptr<PatternData> LayoutSVGResourcePattern::BuildPatternData( const PatternAttributes& LayoutSVGResourcePattern::EnsureAttributes() const {
const FloatRect& object_bounding_box) {
NOT_DESTROYED();
auto pattern_data = std::make_unique<PatternData>();
DCHECK(GetElement()); DCHECK(GetElement());
// Validate pattern DOM state before building the actual pattern. This should // Validate pattern DOM state before building the actual pattern. This should
// avoid tearing down the pattern we're currently working on. Preferably the // avoid tearing down the pattern we're currently working on. Preferably the
...@@ -82,11 +78,34 @@ std::unique_ptr<PatternData> LayoutSVGResourcePattern::BuildPatternData( ...@@ -82,11 +78,34 @@ std::unique_ptr<PatternData> LayoutSVGResourcePattern::BuildPatternData(
if (should_collect_pattern_attributes_) { if (should_collect_pattern_attributes_) {
attributes_wrapper_->Set(PatternAttributes()); attributes_wrapper_->Set(PatternAttributes());
auto* pattern_element = To<SVGPatternElement>(GetElement()); auto* pattern_element = To<SVGPatternElement>(GetElement());
pattern_element->CollectPatternAttributes(MutableAttributes()); pattern_element->CollectPatternAttributes(
attributes_wrapper_->Attributes());
should_collect_pattern_attributes_ = false; should_collect_pattern_attributes_ = false;
} }
return Attributes();
}
bool LayoutSVGResourcePattern::FindCycleFromSelf(
SVGResourcesCycleSolver& solver) const {
NOT_DESTROYED();
const PatternAttributes& attributes = EnsureAttributes();
const SVGPatternElement* content_element = attributes.PatternContentElement();
if (!content_element)
return false;
const LayoutObject* content_object = content_element->GetLayoutObject();
DCHECK(content_object);
return FindCycleInDescendants(solver, *content_object);
}
std::unique_ptr<PatternData> LayoutSVGResourcePattern::BuildPatternData(
const FloatRect& object_bounding_box) {
NOT_DESTROYED();
auto pattern_data = std::make_unique<PatternData>();
const PatternAttributes& attributes = Attributes(); const PatternAttributes& attributes = EnsureAttributes();
// If there's no content disable rendering of the pattern.
if (!attributes.PatternContentElement())
return pattern_data;
// Spec: When the geometry of the applicable element has no width or height // Spec: When the geometry of the applicable element has no width or height
// and objectBoundingBox is specified, then the given effect (e.g. a gradient // and objectBoundingBox is specified, then the given effect (e.g. a gradient
...@@ -96,10 +115,6 @@ std::unique_ptr<PatternData> LayoutSVGResourcePattern::BuildPatternData( ...@@ -96,10 +115,6 @@ std::unique_ptr<PatternData> LayoutSVGResourcePattern::BuildPatternData(
object_bounding_box.IsEmpty()) object_bounding_box.IsEmpty())
return pattern_data; return pattern_data;
// If there's no content disable rendering of the pattern.
if (!attributes.PatternContentElement())
return pattern_data;
// Compute tile metrics. // Compute tile metrics.
FloatRect tile_bounds = SVGLengthContext::ResolveRectangle( FloatRect tile_bounds = SVGLengthContext::ResolveRectangle(
GetElement(), attributes.PatternUnits(), object_bounding_box, GetElement(), attributes.PatternUnits(), object_bounding_box,
...@@ -161,34 +176,6 @@ bool LayoutSVGResourcePattern::ApplyShader( ...@@ -161,34 +176,6 @@ bool LayoutSVGResourcePattern::ApplyShader(
return true; return true;
} }
const LayoutSVGResourceContainer*
LayoutSVGResourcePattern::ResolveContentElement() const {
NOT_DESTROYED();
DCHECK(Attributes().PatternContentElement());
auto* expected_layout_object = To<LayoutSVGResourceContainer>(
Attributes().PatternContentElement()->GetLayoutObject());
// No content inheritance - avoid walking the inheritance chain.
if (this == expected_layout_object)
return this;
// Walk the inheritance chain on the LayoutObject-side. If we reach the
// expected LayoutObject, all is fine. If we don't, there's a cycle that
// the cycle resolver did break, and the resource will be content-less.
const LayoutSVGResourceContainer* content_layout_object = this;
while (SVGResources* resources =
SVGResourcesCache::CachedResourcesForLayoutObject(
*content_layout_object)) {
LayoutSVGResourceContainer* linked_resource = resources->LinkedResource();
if (!linked_resource)
break;
if (linked_resource == expected_layout_object)
return expected_layout_object;
content_layout_object = linked_resource;
}
// There was a cycle, just use this resource as the "content resource" even
// though it will be empty (have no children).
return this;
}
sk_sp<PaintRecord> LayoutSVGResourcePattern::AsPaintRecord( sk_sp<PaintRecord> LayoutSVGResourcePattern::AsPaintRecord(
const FloatSize& size, const FloatSize& size,
const AffineTransform& tile_transform) const { const AffineTransform& tile_transform) const {
...@@ -201,8 +188,8 @@ sk_sp<PaintRecord> LayoutSVGResourcePattern::AsPaintRecord( ...@@ -201,8 +188,8 @@ sk_sp<PaintRecord> LayoutSVGResourcePattern::AsPaintRecord(
content_transform = tile_transform; content_transform = tile_transform;
FloatRect bounds(FloatPoint(), size); FloatRect bounds(FloatPoint(), size);
const LayoutSVGResourceContainer* pattern_layout_object = const auto* pattern_layout_object = To<LayoutSVGResourceContainer>(
ResolveContentElement(); Attributes().PatternContentElement()->GetLayoutObject());
DCHECK(pattern_layout_object); DCHECK(pattern_layout_object);
DCHECK(!pattern_layout_object->NeedsLayout()); DCHECK(!pattern_layout_object->NeedsLayout());
......
...@@ -59,24 +59,20 @@ class LayoutSVGResourcePattern final : public LayoutSVGResourcePaintServer { ...@@ -59,24 +59,20 @@ class LayoutSVGResourcePattern final : public LayoutSVGResourcePaintServer {
} }
private: private:
bool FindCycleFromSelf(SVGResourcesCycleSolver&) const override;
std::unique_ptr<PatternData> BuildPatternData( std::unique_ptr<PatternData> BuildPatternData(
const FloatRect& object_bounding_box); const FloatRect& object_bounding_box);
sk_sp<PaintRecord> AsPaintRecord(const FloatSize&, sk_sp<PaintRecord> AsPaintRecord(const FloatSize&,
const AffineTransform&) const; const AffineTransform&) const;
const LayoutSVGResourceContainer* ResolveContentElement() const; mutable bool should_collect_pattern_attributes_ : 1;
bool should_collect_pattern_attributes_ : 1;
Persistent<PatternAttributesWrapper> attributes_wrapper_; Persistent<PatternAttributesWrapper> attributes_wrapper_;
PatternAttributes& MutableAttributes() {
NOT_DESTROYED();
return attributes_wrapper_->Attributes();
}
const PatternAttributes& Attributes() const { const PatternAttributes& Attributes() const {
NOT_DESTROYED(); NOT_DESTROYED();
return attributes_wrapper_->Attributes(); return attributes_wrapper_->Attributes();
} }
const PatternAttributes& EnsureAttributes() const;
// FIXME: we can almost do away with this per-object map, but not quite: the // FIXME: we can almost do away with this per-object map, but not quite: the
// tile size can be relative to the client bounding box, and it gets captured // tile size can be relative to the client bounding box, and it gets captured
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include "third_party/blink/renderer/core/style/style_svg_resource.h" #include "third_party/blink/renderer/core/style/style_svg_resource.h"
#include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h" #include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h"
#include "third_party/blink/renderer/core/svg/svg_filter_primitive_standard_attributes.h" #include "third_party/blink/renderer/core/svg/svg_filter_primitive_standard_attributes.h"
#include "third_party/blink/renderer/core/svg/svg_pattern_element.h"
#include "third_party/blink/renderer/core/svg/svg_resource.h" #include "third_party/blink/renderer/core/svg/svg_resource.h"
#include "third_party/blink/renderer/core/svg/svg_tree_scope_resources.h" #include "third_party/blink/renderer/core/svg/svg_tree_scope_resources.h"
#include "third_party/blink/renderer/core/svg/svg_uri_reference.h" #include "third_party/blink/renderer/core/svg/svg_uri_reference.h"
...@@ -52,7 +51,7 @@ ...@@ -52,7 +51,7 @@
namespace blink { namespace blink {
SVGResources::SVGResources() : linked_resource_(nullptr) {} SVGResources::SVGResources() = default;
SVGElementResourceClient* SVGResources::GetClient(const LayoutObject& object) { SVGElementResourceClient* SVGResources::GetClient(const LayoutObject& object) {
return To<SVGElement>(object.GetNode())->GetSVGResourceClient(); return To<SVGElement>(object.GetNode())->GetSVGResourceClient();
...@@ -146,8 +145,7 @@ static HashSet<AtomicString>& FillAndStrokeTags() { ...@@ -146,8 +145,7 @@ static HashSet<AtomicString>& FillAndStrokeTags() {
} }
bool SVGResources::HasResourceData() const { bool SVGResources::HasResourceData() const {
return clipper_filter_masker_data_ || marker_data_ || fill_stroke_data_ || return clipper_filter_masker_data_ || marker_data_ || fill_stroke_data_;
linked_resource_;
} }
static inline SVGResources& EnsureResources( static inline SVGResources& EnsureResources(
...@@ -223,16 +221,6 @@ std::unique_ptr<SVGResources> SVGResources::BuildResources( ...@@ -223,16 +221,6 @@ std::unique_ptr<SVGResources> SVGResources::BuildResources(
} }
} }
if (auto* pattern = DynamicTo<SVGPatternElement>(element)) {
const SVGPatternElement* directly_referenced_pattern =
pattern->ReferencedElement();
if (directly_referenced_pattern) {
EnsureResources(resources).SetLinkedResource(
DynamicTo<LayoutSVGResourceContainer>(
directly_referenced_pattern->GetLayoutObject()));
}
}
return (!resources || !resources->HasResourceData()) ? nullptr return (!resources || !resources->HasResourceData()) ? nullptr
: std::move(resources); : std::move(resources);
} }
...@@ -242,15 +230,6 @@ void SVGResources::ResourceDestroyed(LayoutSVGResourceContainer* resource) { ...@@ -242,15 +230,6 @@ void SVGResources::ResourceDestroyed(LayoutSVGResourceContainer* resource) {
if (!HasResourceData()) if (!HasResourceData())
return; return;
if (linked_resource_ == resource) {
DCHECK(!clipper_filter_masker_data_);
DCHECK(!marker_data_);
DCHECK(!fill_stroke_data_);
linked_resource_->RemoveAllClientsFromCache();
linked_resource_ = nullptr;
return;
}
switch (resource->ResourceType()) { switch (resource->ResourceType()) {
case kMaskerResourceType: case kMaskerResourceType:
if (!clipper_filter_masker_data_) if (!clipper_filter_masker_data_)
...@@ -297,14 +276,6 @@ void SVGResources::ResourceDestroyed(LayoutSVGResourceContainer* resource) { ...@@ -297,14 +276,6 @@ void SVGResources::ResourceDestroyed(LayoutSVGResourceContainer* resource) {
void SVGResources::ClearReferencesTo(LayoutSVGResourceContainer* resource) { void SVGResources::ClearReferencesTo(LayoutSVGResourceContainer* resource) {
DCHECK(resource); DCHECK(resource);
if (linked_resource_ == resource) {
DCHECK(!clipper_filter_masker_data_);
DCHECK(!marker_data_);
DCHECK(!fill_stroke_data_);
linked_resource_ = nullptr;
return;
}
switch (resource->ResourceType()) { switch (resource->ResourceType()) {
case kMaskerResourceType: case kMaskerResourceType:
DCHECK(clipper_filter_masker_data_); DCHECK(clipper_filter_masker_data_);
...@@ -352,14 +323,6 @@ void SVGResources::BuildSetOfResources( ...@@ -352,14 +323,6 @@ void SVGResources::BuildSetOfResources(
if (!HasResourceData()) if (!HasResourceData())
return; return;
if (linked_resource_) {
DCHECK(!clipper_filter_masker_data_);
DCHECK(!marker_data_);
DCHECK(!fill_stroke_data_);
set.insert(linked_resource_);
return;
}
if (clipper_filter_masker_data_) { if (clipper_filter_masker_data_) {
if (clipper_filter_masker_data_->clipper) if (clipper_filter_masker_data_->clipper)
set.insert(clipper_filter_masker_data_->clipper); set.insert(clipper_filter_masker_data_->clipper);
...@@ -464,14 +427,6 @@ void SVGResources::SetStroke(LayoutSVGResourcePaintServer* stroke) { ...@@ -464,14 +427,6 @@ void SVGResources::SetStroke(LayoutSVGResourcePaintServer* stroke) {
fill_stroke_data_->stroke = stroke; fill_stroke_data_->stroke = stroke;
} }
void SVGResources::SetLinkedResource(
LayoutSVGResourceContainer* linked_resource) {
if (!linked_resource)
return;
linked_resource_ = linked_resource;
}
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
void SVGResources::Dump(const LayoutObject* object) { void SVGResources::Dump(const LayoutObject* object) {
DCHECK(object); DCHECK(object);
...@@ -517,10 +472,6 @@ void SVGResources::Dump(const LayoutObject* object) { ...@@ -517,10 +472,6 @@ void SVGResources::Dump(const LayoutObject* object) {
fprintf(stderr, " |-> Stroke : %p (node=%p)\n", stroke, fprintf(stderr, " |-> Stroke : %p (node=%p)\n", stroke,
stroke->GetElement()); stroke->GetElement());
} }
if (linked_resource_)
fprintf(stderr, " |-> xlink:href : %p (node=%p)\n", linked_resource_,
linked_resource_->GetElement());
} }
#endif #endif
......
...@@ -107,11 +107,6 @@ class SVGResources { ...@@ -107,11 +107,6 @@ class SVGResources {
return fill_stroke_data_ ? fill_stroke_data_->stroke : nullptr; return fill_stroke_data_ ? fill_stroke_data_->stroke : nullptr;
} }
// Chainable resources - linked through xlink:href
LayoutSVGResourceContainer* LinkedResource() const {
return linked_resource_;
}
void BuildSetOfResources(HashSet<LayoutSVGResourceContainer*>&); void BuildSetOfResources(HashSet<LayoutSVGResourceContainer*>&);
// Methods operating on all cached resources // Methods operating on all cached resources
...@@ -133,7 +128,6 @@ class SVGResources { ...@@ -133,7 +128,6 @@ class SVGResources {
void SetMasker(LayoutSVGResourceMasker*); void SetMasker(LayoutSVGResourceMasker*);
void SetFill(LayoutSVGResourcePaintServer*); void SetFill(LayoutSVGResourcePaintServer*);
void SetStroke(LayoutSVGResourcePaintServer*); void SetStroke(LayoutSVGResourcePaintServer*);
void SetLinkedResource(LayoutSVGResourceContainer*);
// From SVG 1.1 2nd Edition // From SVG 1.1 2nd Edition
// clipper: 'container elements' and 'graphics elements' // clipper: 'container elements' and 'graphics elements'
...@@ -186,7 +180,6 @@ class SVGResources { ...@@ -186,7 +180,6 @@ class SVGResources {
std::unique_ptr<ClipperFilterMaskerData> clipper_filter_masker_data_; std::unique_ptr<ClipperFilterMaskerData> clipper_filter_masker_data_;
std::unique_ptr<MarkerData> marker_data_; std::unique_ptr<MarkerData> marker_data_;
std::unique_ptr<FillStrokeData> fill_stroke_data_; std::unique_ptr<FillStrokeData> fill_stroke_data_;
LayoutSVGResourceContainer* linked_resource_;
}; };
class SVGElementResourceClient final class SVGElementResourceClient final
......
...@@ -24,16 +24,13 @@ ...@@ -24,16 +24,13 @@
#include "third_party/blink/renderer/core/css/style_change_reason.h" #include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/id_target_observer.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.h"
#include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
#include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h"
#include "third_party/blink/renderer/core/svg/pattern_attributes.h" #include "third_party/blink/renderer/core/svg/pattern_attributes.h"
#include "third_party/blink/renderer/core/svg/svg_animated_length.h" #include "third_party/blink/renderer/core/svg/svg_animated_length.h"
#include "third_party/blink/renderer/core/svg/svg_animated_preserve_aspect_ratio.h" #include "third_party/blink/renderer/core/svg/svg_animated_preserve_aspect_ratio.h"
#include "third_party/blink/renderer/core/svg/svg_animated_rect.h" #include "third_party/blink/renderer/core/svg/svg_animated_rect.h"
#include "third_party/blink/renderer/core/svg/svg_animated_transform_list.h" #include "third_party/blink/renderer/core/svg/svg_animated_transform_list.h"
#include "third_party/blink/renderer/core/svg/svg_resource.h"
#include "third_party/blink/renderer/core/svg/svg_tree_scope_resources.h"
#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/transforms/affine_transform.h" #include "third_party/blink/renderer/platform/transforms/affine_transform.h"
...@@ -95,7 +92,7 @@ void SVGPatternElement::Trace(Visitor* visitor) const { ...@@ -95,7 +92,7 @@ void SVGPatternElement::Trace(Visitor* visitor) const {
visitor->Trace(pattern_transform_); visitor->Trace(pattern_transform_);
visitor->Trace(pattern_units_); visitor->Trace(pattern_units_);
visitor->Trace(pattern_content_units_); visitor->Trace(pattern_content_units_);
visitor->Trace(resource_); visitor->Trace(target_id_observer_);
SVGElement::Trace(visitor); SVGElement::Trace(visitor);
SVGURIReference::Trace(visitor); SVGURIReference::Trace(visitor);
SVGTests::Trace(visitor); SVGTests::Trace(visitor);
...@@ -106,28 +103,16 @@ void SVGPatternElement::BuildPendingResource() { ...@@ -106,28 +103,16 @@ void SVGPatternElement::BuildPendingResource() {
ClearResourceReferences(); ClearResourceReferences();
if (!isConnected()) if (!isConnected())
return; return;
TreeScope& tree_scope = GetTreeScope(); Element* target = ObserveTarget(target_id_observer_, *this);
SVGTreeScopeResources& tree_scope_resources = if (auto* pattern = DynamicTo<SVGPatternElement>(target))
tree_scope.EnsureSVGTreeScopedResources(); AddReferenceTo(pattern);
resource_ = tree_scope_resources.ResourceForId(
FragmentIdentifierFromIRIString(HrefString(), tree_scope));
if (resource_)
resource_->AddClient(EnsureSVGResourceClient());
InvalidatePattern(layout_invalidation_reason::kSvgResourceInvalidated); InvalidatePattern(layout_invalidation_reason::kSvgResourceInvalidated);
if (auto* layout_object = GetLayoutObject()) {
if (!layout_object->Parent())
return;
SVGResourcesCache::UpdateResources(*layout_object);
InvalidateDependentPatterns();
}
} }
void SVGPatternElement::ClearResourceReferences() { void SVGPatternElement::ClearResourceReferences() {
if (!resource_) UnobserveTarget(target_id_observer_);
return; RemoveAllOutgoingReferences();
resource_->RemoveClient(*GetSVGResourceClient());
resource_ = nullptr;
} }
void SVGPatternElement::CollectStyleForPresentationAttribute( void SVGPatternElement::CollectStyleForPresentationAttribute(
...@@ -265,8 +250,8 @@ static void SetPatternAttributes(const SVGPatternElement& element, ...@@ -265,8 +250,8 @@ static void SetPatternAttributes(const SVGPatternElement& element,
} }
const SVGPatternElement* SVGPatternElement::ReferencedElement() const { const SVGPatternElement* SVGPatternElement::ReferencedElement() const {
return DynamicTo<SVGPatternElement>(resource_ ? resource_->Target() return DynamicTo<SVGPatternElement>(
: nullptr); TargetElementFromIRIString(HrefString(), GetTreeScope()));
} }
void SVGPatternElement::CollectPatternAttributes( void SVGPatternElement::CollectPatternAttributes(
......
...@@ -35,7 +35,6 @@ namespace blink { ...@@ -35,7 +35,6 @@ namespace blink {
class PatternAttributes; class PatternAttributes;
class SVGAnimatedLength; class SVGAnimatedLength;
class SVGAnimatedTransformList; class SVGAnimatedTransformList;
class SVGResource;
class SVGPatternElement final : public SVGElement, class SVGPatternElement final : public SVGElement,
public SVGURIReference, public SVGURIReference,
...@@ -110,7 +109,7 @@ class SVGPatternElement final : public SVGElement, ...@@ -110,7 +109,7 @@ class SVGPatternElement final : public SVGElement,
Member<SVGAnimatedEnumeration<SVGUnitTypes::SVGUnitType>> pattern_units_; Member<SVGAnimatedEnumeration<SVGUnitTypes::SVGUnitType>> pattern_units_;
Member<SVGAnimatedEnumeration<SVGUnitTypes::SVGUnitType>> Member<SVGAnimatedEnumeration<SVGUnitTypes::SVGUnitType>>
pattern_content_units_; pattern_content_units_;
Member<SVGResource> resource_; Member<IdTargetObserver> target_id_observer_;
}; };
} // namespace blink } // namespace blink
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment