OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde
.org> | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde
.org> |
3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> | 3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> |
4 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. | 4 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
5 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved. | 5 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved. |
6 * Copyright (C) 2012 University of Szeged | 6 * Copyright (C) 2012 University of Szeged |
7 * Copyright (C) 2012 Renata Hodovan <reni@webkit.org> | 7 * Copyright (C) 2012 Renata Hodovan <reni@webkit.org> |
8 * | 8 * |
9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 return sharedLoadEventSender; | 52 return sharedLoadEventSender; |
53 } | 53 } |
54 | 54 |
55 inline SVGUseElement::SVGUseElement(Document& document) | 55 inline SVGUseElement::SVGUseElement(Document& document) |
56 : SVGGraphicsElement(SVGNames::useTag, document) | 56 : SVGGraphicsElement(SVGNames::useTag, document) |
57 , SVGURIReference(this) | 57 , SVGURIReference(this) |
58 , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(SVG
LengthMode::Width))) | 58 , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(SVG
LengthMode::Width))) |
59 , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(SVG
LengthMode::Height))) | 59 , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(SVG
LengthMode::Height))) |
60 , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::cr
eate(SVGLengthMode::Width))) | 60 , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::cr
eate(SVGLengthMode::Width))) |
61 , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::
create(SVGLengthMode::Height))) | 61 , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::
create(SVGLengthMode::Height))) |
| 62 , m_elementIdentifierIsLocal(true) |
62 , m_haveFiredLoadEvent(false) | 63 , m_haveFiredLoadEvent(false) |
63 , m_needsShadowTreeRecreation(false) | 64 , m_needsShadowTreeRecreation(false) |
64 { | 65 { |
65 ASSERT(hasCustomStyleCallbacks()); | 66 ASSERT(hasCustomStyleCallbacks()); |
66 ThreadState::current()->registerPreFinalizer(this); | 67 ThreadState::current()->registerPreFinalizer(this); |
67 | 68 |
68 addToPropertyMap(m_x); | 69 addToPropertyMap(m_x); |
69 addToPropertyMap(m_y); | 70 addToPropertyMap(m_y); |
70 addToPropertyMap(m_width); | 71 addToPropertyMap(m_width); |
71 addToPropertyMap(m_height); | 72 addToPropertyMap(m_height); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 | 125 |
125 void SVGUseElement::removedFrom(ContainerNode* rootParent) | 126 void SVGUseElement::removedFrom(ContainerNode* rootParent) |
126 { | 127 { |
127 SVGGraphicsElement::removedFrom(rootParent); | 128 SVGGraphicsElement::removedFrom(rootParent); |
128 if (rootParent->isConnected()) { | 129 if (rootParent->isConnected()) { |
129 clearShadowTree(); | 130 clearShadowTree(); |
130 cancelShadowTreeRecreation(); | 131 cancelShadowTreeRecreation(); |
131 } | 132 } |
132 } | 133 } |
133 | 134 |
134 Document* SVGUseElement::externalDocument() const | |
135 { | |
136 // Gracefully handle error condition. | |
137 if (!resourceIsValid()) | |
138 return nullptr; | |
139 ASSERT(m_resource->document()); | |
140 return m_resource->document(); | |
141 } | |
142 | |
143 static void transferUseWidthAndHeightIfNeeded(const SVGUseElement& use, SVGEleme
nt& shadowElement, const SVGElement& originalElement) | 135 static void transferUseWidthAndHeightIfNeeded(const SVGUseElement& use, SVGEleme
nt& shadowElement, const SVGElement& originalElement) |
144 { | 136 { |
145 DEFINE_STATIC_LOCAL(const AtomicString, hundredPercentString, ("100%")); | 137 DEFINE_STATIC_LOCAL(const AtomicString, hundredPercentString, ("100%")); |
146 // Use |originalElement| for checking the element type, because we will | 138 // Use |originalElement| for checking the element type, because we will |
147 // have replaced a <symbol> with an <svg> in the instance tree. | 139 // have replaced a <symbol> with an <svg> in the instance tree. |
148 if (isSVGSymbolElement(originalElement)) { | 140 if (isSVGSymbolElement(originalElement)) { |
149 // Spec (<use> on <symbol>): This generated 'svg' will always have | 141 // Spec (<use> on <symbol>): This generated 'svg' will always have |
150 // explicit values for attributes width and height. If attributes | 142 // explicit values for attributes width and height. If attributes |
151 // width and/or height are provided on the 'use' element, then these | 143 // width and/or height are provided on the 'use' element, then these |
152 // attributes will be transferred to the generated 'svg'. If attributes | 144 // attributes will be transferred to the generated 'svg'. If attributes |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 { | 177 { |
186 SVGAnimatedPropertyBase* property = propertyFromAttribute(name); | 178 SVGAnimatedPropertyBase* property = propertyFromAttribute(name); |
187 if (property == m_x) | 179 if (property == m_x) |
188 addPropertyToPresentationAttributeStyle(style, CSSPropertyX, m_x->curren
tValue()->asCSSPrimitiveValue()); | 180 addPropertyToPresentationAttributeStyle(style, CSSPropertyX, m_x->curren
tValue()->asCSSPrimitiveValue()); |
189 else if (property == m_y) | 181 else if (property == m_y) |
190 addPropertyToPresentationAttributeStyle(style, CSSPropertyY, m_y->curren
tValue()->asCSSPrimitiveValue()); | 182 addPropertyToPresentationAttributeStyle(style, CSSPropertyY, m_y->curren
tValue()->asCSSPrimitiveValue()); |
191 else | 183 else |
192 SVGGraphicsElement::collectStyleForPresentationAttribute(name, value, st
yle); | 184 SVGGraphicsElement::collectStyleForPresentationAttribute(name, value, st
yle); |
193 } | 185 } |
194 | 186 |
| 187 void SVGUseElement::updateTargetReference() |
| 188 { |
| 189 KURL resolvedUrl = document().completeURL(hrefString()); |
| 190 m_elementIdentifier = AtomicString(resolvedUrl.fragmentIdentifier()); |
| 191 m_elementIdentifierIsLocal = resolvedUrl.isNull() |
| 192 || equalIgnoringFragmentIdentifier(resolvedUrl, document().url()); |
| 193 if (m_elementIdentifierIsLocal) { |
| 194 setDocumentResource(nullptr); |
| 195 return; |
| 196 } |
| 197 if (m_elementIdentifier.isEmpty() |
| 198 || (m_resource && equalIgnoringFragmentIdentifier(resolvedUrl, m_resourc
e->url()))) |
| 199 return; |
| 200 FetchRequest request(ResourceRequest(resolvedUrl), localName()); |
| 201 setDocumentResource(DocumentResource::fetchSVGDocument(request, document().f
etcher())); |
| 202 } |
| 203 |
195 void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName) | 204 void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName) |
196 { | 205 { |
197 if (attrName == SVGNames::xAttr | 206 if (attrName == SVGNames::xAttr |
198 || attrName == SVGNames::yAttr | 207 || attrName == SVGNames::yAttr |
199 || attrName == SVGNames::widthAttr | 208 || attrName == SVGNames::widthAttr |
200 || attrName == SVGNames::heightAttr) { | 209 || attrName == SVGNames::heightAttr) { |
201 SVGElement::InvalidationGuard invalidationGuard(this); | 210 SVGElement::InvalidationGuard invalidationGuard(this); |
202 | 211 |
203 if (attrName == SVGNames::xAttr | 212 if (attrName == SVGNames::xAttr |
204 || attrName == SVGNames::yAttr) { | 213 || attrName == SVGNames::yAttr) { |
205 invalidateSVGPresentationAttributeStyle(); | 214 invalidateSVGPresentationAttributeStyle(); |
206 setNeedsStyleRecalc(LocalStyleChange, | 215 setNeedsStyleRecalc(LocalStyleChange, |
207 StyleChangeReasonForTracing::fromAttribute(attrName)); | 216 StyleChangeReasonForTracing::fromAttribute(attrName)); |
208 } | 217 } |
209 | 218 |
210 updateRelativeLengthsInformation(); | 219 updateRelativeLengthsInformation(); |
211 if (m_targetElementInstance) { | 220 if (m_targetElementInstance) { |
212 ASSERT(m_targetElementInstance->correspondingElement()); | 221 ASSERT(m_targetElementInstance->correspondingElement()); |
213 transferUseWidthAndHeightIfNeeded(*this, *m_targetElementInstance, *
m_targetElementInstance->correspondingElement()); | 222 transferUseWidthAndHeightIfNeeded(*this, *m_targetElementInstance, *
m_targetElementInstance->correspondingElement()); |
214 } | 223 } |
215 | 224 |
216 LayoutObject* object = this->layoutObject(); | 225 LayoutObject* object = this->layoutObject(); |
217 if (object) | 226 if (object) |
218 markForLayoutAndParentResourceInvalidation(object); | 227 markForLayoutAndParentResourceInvalidation(object); |
219 return; | 228 return; |
220 } | 229 } |
221 | 230 |
222 if (SVGURIReference::isKnownAttribute(attrName)) { | 231 if (SVGURIReference::isKnownAttribute(attrName)) { |
223 SVGElement::InvalidationGuard invalidationGuard(this); | 232 SVGElement::InvalidationGuard invalidationGuard(this); |
224 if (isStructurallyExternal()) { | 233 updateTargetReference(); |
225 KURL url = document().completeURL(hrefString()); | |
226 const KURL& existingURL = m_resource ? m_resource->url() : KURL(); | |
227 if (url.hasFragmentIdentifier() && !equalIgnoringFragmentIdentifier(
url, existingURL)) { | |
228 FetchRequest request(ResourceRequest(url), localName()); | |
229 setDocumentResource(DocumentResource::fetchSVGDocument(request,
document().fetcher())); | |
230 } | |
231 } else { | |
232 setDocumentResource(nullptr); | |
233 } | |
234 | |
235 invalidateShadowTree(); | 234 invalidateShadowTree(); |
236 | |
237 return; | 235 return; |
238 } | 236 } |
239 | 237 |
240 SVGGraphicsElement::svgAttributeChanged(attrName); | 238 SVGGraphicsElement::svgAttributeChanged(attrName); |
241 } | 239 } |
242 | 240 |
243 static bool isDisallowedElement(const Element& element) | 241 static bool isDisallowedElement(const Element& element) |
244 { | 242 { |
245 // Spec: "Any 'svg', 'symbol', 'g', graphics element or other 'use' is poten
tially a template object that can be re-used | 243 // Spec: "Any 'svg', 'symbol', 'g', graphics element or other 'use' is poten
tially a template object that can be re-used |
246 // (i.e., "instanced") in the SVG document via a 'use' element." | 244 // (i.e., "instanced") in the SVG document via a 'use' element." |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 { | 296 { |
299 clearInstanceRoot(); | 297 clearInstanceRoot(); |
300 | 298 |
301 // FIXME: We should try to optimize this, to at least allow partial reclones
. | 299 // FIXME: We should try to optimize this, to at least allow partial reclones
. |
302 if (ShadowRoot* shadowTreeRootElement = userAgentShadowRoot()) | 300 if (ShadowRoot* shadowTreeRootElement = userAgentShadowRoot()) |
303 shadowTreeRootElement->removeChildren(OmitSubtreeModifiedEvent); | 301 shadowTreeRootElement->removeChildren(OmitSubtreeModifiedEvent); |
304 | 302 |
305 removeAllOutgoingReferences(); | 303 removeAllOutgoingReferences(); |
306 } | 304 } |
307 | 305 |
| 306 Element* SVGUseElement::resolveTargetElement() |
| 307 { |
| 308 if (m_elementIdentifier.isEmpty()) |
| 309 return nullptr; |
| 310 const TreeScope* lookupScope = nullptr; |
| 311 if (m_elementIdentifierIsLocal) |
| 312 lookupScope = &treeScope(); |
| 313 else if (resourceIsValid()) |
| 314 lookupScope = m_resource->document(); |
| 315 else |
| 316 return nullptr; |
| 317 Element* target = lookupScope->getElementById(m_elementIdentifier); |
| 318 // TODO(fs): Why would the Element not be "connected" at this point? |
| 319 if (target && target->isConnected()) |
| 320 return target; |
| 321 // Don't record any pending references for external resources. |
| 322 if (!m_resource) { |
| 323 document().accessSVGExtensions().addPendingResource(m_elementIdentifier,
this); |
| 324 DCHECK(hasPendingResources()); |
| 325 } |
| 326 return nullptr; |
| 327 } |
| 328 |
308 void SVGUseElement::buildPendingResource() | 329 void SVGUseElement::buildPendingResource() |
309 { | 330 { |
310 if (inUseShadowTree()) | 331 if (inUseShadowTree()) |
311 return; | 332 return; |
312 clearShadowTree(); | 333 clearShadowTree(); |
313 cancelShadowTreeRecreation(); | 334 cancelShadowTreeRecreation(); |
314 if (!isConnected()) | 335 if (!isConnected()) |
315 return; | 336 return; |
316 Document* externalDocument = this->externalDocument(); | 337 Element* target = resolveTargetElement(); |
317 if (isStructurallyExternal() && !externalDocument) | 338 if (target && target->isSVGElement()) { |
318 return; | |
319 | |
320 AtomicString id; | |
321 Element* target = targetElementFromIRIString(hrefString(), treeScope(), &id,
externalDocument); | |
322 if (!target || !target->isConnected()) { | |
323 // If we can't find the target of an external element, just give up. | |
324 // We can't observe if the target somewhen enters the external document,
nor should we do it. | |
325 if (externalDocument) | |
326 return; | |
327 if (id.isEmpty()) | |
328 return; | |
329 | |
330 document().accessSVGExtensions().addPendingResource(id, this); | |
331 ASSERT(hasPendingResources()); | |
332 return; | |
333 } | |
334 | |
335 if (target->isSVGElement()) { | |
336 buildShadowAndInstanceTree(toSVGElement(*target)); | 339 buildShadowAndInstanceTree(toSVGElement(*target)); |
337 invalidateDependentShadowTrees(); | 340 invalidateDependentShadowTrees(); |
338 } | 341 } |
339 | 342 |
340 ASSERT(!m_needsShadowTreeRecreation); | 343 ASSERT(!m_needsShadowTreeRecreation); |
341 } | 344 } |
342 | 345 |
343 static void associateCorrespondingElements(SVGElement& targetRoot, SVGElement& i
nstanceRoot) | 346 static void associateCorrespondingElements(SVGElement& targetRoot, SVGElement& i
nstanceRoot) |
344 { | 347 { |
345 auto targetRange = Traversal<SVGElement>::inclusiveDescendantsOf(targetRoot)
; | 348 auto targetRange = Traversal<SVGElement>::inclusiveDescendantsOf(targetRoot)
; |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 | 751 |
749 if (m_resource) | 752 if (m_resource) |
750 m_resource->removeClient(this); | 753 m_resource->removeClient(this); |
751 | 754 |
752 m_resource = resource; | 755 m_resource = resource; |
753 if (m_resource) | 756 if (m_resource) |
754 m_resource->addClient(this); | 757 m_resource->addClient(this); |
755 } | 758 } |
756 | 759 |
757 } // namespace blink | 760 } // namespace blink |
OLD | NEW |