OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006 Apple Computer, Inc. | 2 * Copyright (C) 2006 Apple Computer, Inc. |
3 * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org> | 3 * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org> |
4 * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz> | 4 * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz> |
5 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> | 5 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> |
6 * Copyright (C) 2008 Rob Buis <buis@kde.org> | 6 * Copyright (C) 2008 Rob Buis <buis@kde.org> |
7 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> | 7 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> |
8 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. | 8 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. |
9 * Copyright (C) 2012 Google Inc. | 9 * Copyright (C) 2012 Google Inc. |
10 * | 10 * |
(...skipping 13 matching lines...) Expand all Loading... |
24 * Boston, MA 02110-1301, USA. | 24 * Boston, MA 02110-1301, USA. |
25 */ | 25 */ |
26 | 26 |
27 #include "core/layout/svg/LayoutSVGText.h" | 27 #include "core/layout/svg/LayoutSVGText.h" |
28 | 28 |
29 #include "core/editing/PositionWithAffinity.h" | 29 #include "core/editing/PositionWithAffinity.h" |
30 #include "core/layout/HitTestRequest.h" | 30 #include "core/layout/HitTestRequest.h" |
31 #include "core/layout/HitTestResult.h" | 31 #include "core/layout/HitTestResult.h" |
32 #include "core/layout/LayoutAnalyzer.h" | 32 #include "core/layout/LayoutAnalyzer.h" |
33 #include "core/layout/LayoutState.h" | 33 #include "core/layout/LayoutState.h" |
34 #include "core/layout/LayoutView.h" | |
35 #include "core/layout/PointerEventsHitRules.h" | 34 #include "core/layout/PointerEventsHitRules.h" |
36 #include "core/layout/api/LineLayoutItem.h" | 35 #include "core/layout/api/LineLayoutItem.h" |
37 #include "core/layout/svg/LayoutSVGInline.h" | 36 #include "core/layout/svg/LayoutSVGInline.h" |
38 #include "core/layout/svg/LayoutSVGInlineText.h" | 37 #include "core/layout/svg/LayoutSVGInlineText.h" |
39 #include "core/layout/svg/LayoutSVGRoot.h" | 38 #include "core/layout/svg/LayoutSVGRoot.h" |
40 #include "core/layout/svg/SVGLayoutSupport.h" | 39 #include "core/layout/svg/SVGLayoutSupport.h" |
41 #include "core/layout/svg/SVGResourcesCache.h" | 40 #include "core/layout/svg/SVGResourcesCache.h" |
42 #include "core/layout/svg/SVGTextLayoutAttributesBuilder.h" | 41 #include "core/layout/svg/SVGTextLayoutAttributesBuilder.h" |
43 #include "core/layout/svg/line/SVGRootInlineBox.h" | 42 #include "core/layout/svg/line/SVGRootInlineBox.h" |
44 #include "core/paint/SVGTextPainter.h" | 43 #include "core/paint/SVGTextPainter.h" |
45 #include "core/style/ShadowList.h" | 44 #include "core/style/ShadowList.h" |
46 #include "core/svg/SVGLengthList.h" | |
47 #include "core/svg/SVGTextElement.h" | 45 #include "core/svg/SVGTextElement.h" |
48 #include "core/svg/SVGTransformList.h" | |
49 #include "core/svg/SVGURIReference.h" | |
50 #include "platform/FloatConversion.h" | 46 #include "platform/FloatConversion.h" |
51 #include "platform/geometry/FloatQuad.h" | 47 #include "platform/geometry/FloatQuad.h" |
52 | 48 |
53 namespace blink { | 49 namespace blink { |
54 | 50 |
55 namespace { | 51 namespace { |
56 | 52 |
57 const LayoutSVGText* findTextRoot(const LayoutObject* start) | 53 const LayoutSVGText* findTextRoot(const LayoutObject* start) |
58 { | 54 { |
59 ASSERT(start); | 55 ASSERT(start); |
(...skipping 10 matching lines...) Expand all Loading... |
70 : LayoutSVGBlock(node) | 66 : LayoutSVGBlock(node) |
71 , m_needsReordering(false) | 67 , m_needsReordering(false) |
72 , m_needsPositioningValuesUpdate(false) | 68 , m_needsPositioningValuesUpdate(false) |
73 , m_needsTransformUpdate(true) | 69 , m_needsTransformUpdate(true) |
74 , m_needsTextMetricsUpdate(false) | 70 , m_needsTextMetricsUpdate(false) |
75 { | 71 { |
76 } | 72 } |
77 | 73 |
78 LayoutSVGText::~LayoutSVGText() | 74 LayoutSVGText::~LayoutSVGText() |
79 { | 75 { |
80 ASSERT(m_layoutAttributes.isEmpty()); | 76 ASSERT(m_descendantTextNodes.isEmpty()); |
81 } | 77 } |
82 | 78 |
83 void LayoutSVGText::willBeDestroyed() | 79 void LayoutSVGText::willBeDestroyed() |
84 { | 80 { |
85 m_layoutAttributes.clear(); | 81 m_descendantTextNodes.clear(); |
86 | 82 |
87 LayoutSVGBlock::willBeDestroyed(); | 83 LayoutSVGBlock::willBeDestroyed(); |
88 } | 84 } |
89 | 85 |
90 bool LayoutSVGText::isChildAllowed(LayoutObject* child, const ComputedStyle&) co
nst | 86 bool LayoutSVGText::isChildAllowed(LayoutObject* child, const ComputedStyle&) co
nst |
91 { | 87 { |
92 return child->isSVGInline() || (child->isText() && SVGLayoutSupport::isLayou
tableTextNode(child)); | 88 return child->isSVGInline() || (child->isText() && SVGLayoutSupport::isLayou
tableTextNode(child)); |
93 } | 89 } |
94 | 90 |
95 LayoutSVGText* LayoutSVGText::locateLayoutSVGTextAncestor(LayoutObject* start) | 91 LayoutSVGText* LayoutSVGText::locateLayoutSVGTextAncestor(LayoutObject* start) |
96 { | 92 { |
97 return const_cast<LayoutSVGText*>(findTextRoot(start)); | 93 return const_cast<LayoutSVGText*>(findTextRoot(start)); |
98 } | 94 } |
99 | 95 |
100 const LayoutSVGText* LayoutSVGText::locateLayoutSVGTextAncestor(const LayoutObje
ct* start) | 96 const LayoutSVGText* LayoutSVGText::locateLayoutSVGTextAncestor(const LayoutObje
ct* start) |
101 { | 97 { |
102 return findTextRoot(start); | 98 return findTextRoot(start); |
103 } | 99 } |
104 | 100 |
105 static inline void collectLayoutAttributes(LayoutObject* text, Vector<SVGTextLay
outAttributes*>& attributes) | 101 static inline void collectDescendantTextNodes(LayoutSVGText& textRoot, Vector<La
youtSVGInlineText*>& descendantTextNodes) |
106 { | 102 { |
107 for (LayoutObject* descendant = text; descendant; descendant = descendant->n
extInPreOrder(text)) { | 103 for (LayoutObject* descendant = textRoot.firstChild(); descendant; descendan
t = descendant->nextInPreOrder(&textRoot)) { |
108 if (descendant->isSVGInlineText()) | 104 if (descendant->isSVGInlineText()) |
109 attributes.append(toLayoutSVGInlineText(descendant)->layoutAttribute
s()); | 105 descendantTextNodes.append(toLayoutSVGInlineText(descendant)); |
110 } | 106 } |
111 } | 107 } |
112 | 108 |
113 void LayoutSVGText::invalidatePositioningValues(LayoutInvalidationReasonForTraci
ng reason) | 109 void LayoutSVGText::invalidatePositioningValues(LayoutInvalidationReasonForTraci
ng reason) |
114 { | 110 { |
115 m_layoutAttributes.clear(); | 111 m_descendantTextNodes.clear(); |
116 setNeedsPositioningValuesUpdate(); | 112 setNeedsPositioningValuesUpdate(); |
117 setNeedsLayoutAndFullPaintInvalidation(reason); | 113 setNeedsLayoutAndFullPaintInvalidation(reason); |
118 } | 114 } |
119 | 115 |
120 void LayoutSVGText::subtreeChildWasAdded() | 116 void LayoutSVGText::subtreeChildWasAdded() |
121 { | 117 { |
122 if (beingDestroyed() || !everHadLayout()) { | 118 if (beingDestroyed() || !everHadLayout()) { |
123 ASSERT(m_layoutAttributes.isEmpty()); | 119 ASSERT(m_descendantTextNodes.isEmpty()); |
124 return; | 120 return; |
125 } | 121 } |
126 if (documentBeingDestroyed()) | 122 if (documentBeingDestroyed()) |
127 return; | 123 return; |
128 | 124 |
129 // The positioning elements cache depends on the size of each text layoutObj
ect in the | 125 // The positioning elements cache depends on the size of each text layoutObj
ect in the |
130 // subtree. If this changes, clear the cache. It will be rebuilt on the next
layout. | 126 // subtree. If this changes, clear the cache. It will be rebuilt on the next
layout. |
131 invalidatePositioningValues(LayoutInvalidationReason::ChildChanged); | 127 invalidatePositioningValues(LayoutInvalidationReason::ChildChanged); |
132 setNeedsTextMetricsUpdate(); | 128 setNeedsTextMetricsUpdate(); |
133 } | 129 } |
134 | 130 |
135 void LayoutSVGText::subtreeChildWillBeRemoved() | 131 void LayoutSVGText::subtreeChildWillBeRemoved() |
136 { | 132 { |
137 if (beingDestroyed() || !everHadLayout()) { | 133 if (beingDestroyed() || !everHadLayout()) { |
138 ASSERT(m_layoutAttributes.isEmpty()); | 134 ASSERT(m_descendantTextNodes.isEmpty()); |
139 return; | 135 return; |
140 } | 136 } |
141 | 137 |
142 // The positioning elements cache depends on the size of each text layoutObj
ect in the | 138 // The positioning elements cache depends on the size of each text layoutObj
ect in the |
143 // subtree. If this changes, clear the cache. It will be rebuilt on the next
layout. | 139 // subtree. If this changes, clear the cache. It will be rebuilt on the next
layout. |
144 invalidatePositioningValues(LayoutInvalidationReason::ChildChanged); | 140 invalidatePositioningValues(LayoutInvalidationReason::ChildChanged); |
145 setNeedsTextMetricsUpdate(); | 141 setNeedsTextMetricsUpdate(); |
146 } | 142 } |
147 | 143 |
148 void LayoutSVGText::subtreeTextDidChange() | 144 void LayoutSVGText::subtreeTextDidChange() |
149 { | 145 { |
150 ASSERT(!beingDestroyed()); | 146 ASSERT(!beingDestroyed()); |
151 if (!everHadLayout()) { | 147 if (!everHadLayout()) { |
152 ASSERT(m_layoutAttributes.isEmpty()); | 148 ASSERT(m_descendantTextNodes.isEmpty()); |
153 return; | 149 return; |
154 } | 150 } |
155 | 151 |
156 // The positioning elements cache depends on the size of each text object in | 152 // The positioning elements cache depends on the size of each text object in |
157 // the subtree. If this changes, clear the cache and mark it for rebuilding | 153 // the subtree. If this changes, clear the cache and mark it for rebuilding |
158 // in the next layout. | 154 // in the next layout. |
159 invalidatePositioningValues(LayoutInvalidationReason::TextChanged); | 155 invalidatePositioningValues(LayoutInvalidationReason::TextChanged); |
160 setNeedsTextMetricsUpdate(); | 156 setNeedsTextMetricsUpdate(); |
161 } | 157 } |
162 | 158 |
163 static inline void updateFontAndMetrics(LayoutSVGText& textRoot) | 159 static inline void updateFontAndMetrics(LayoutSVGText& textRoot) |
164 { | 160 { |
165 bool lastCharacterWasWhiteSpace = true; | 161 bool lastCharacterWasWhiteSpace = true; |
166 for (LayoutObject* descendant = textRoot.firstChild(); descendant; descendan
t = descendant->nextInPreOrder(&textRoot)) { | 162 for (LayoutObject* descendant = textRoot.firstChild(); descendant; descendan
t = descendant->nextInPreOrder(&textRoot)) { |
167 if (!descendant->isSVGInlineText()) | 163 if (!descendant->isSVGInlineText()) |
168 continue; | 164 continue; |
169 LayoutSVGInlineText& text = toLayoutSVGInlineText(*descendant); | 165 LayoutSVGInlineText& text = toLayoutSVGInlineText(*descendant); |
170 text.updateScaledFont(); | 166 text.updateScaledFont(); |
171 text.updateMetricsList(lastCharacterWasWhiteSpace); | 167 text.updateMetricsList(lastCharacterWasWhiteSpace); |
172 } | 168 } |
173 } | 169 } |
174 | 170 |
175 static inline void checkLayoutAttributesConsistency(LayoutSVGText* text, Vector<
SVGTextLayoutAttributes*>& expectedLayoutAttributes) | 171 static inline void checkDescendantTextNodeConsistency(LayoutSVGText& text, Vecto
r<LayoutSVGInlineText*>& expectedDescendantTextNodes) |
176 { | 172 { |
177 #if ENABLE(ASSERT) | 173 #if ENABLE(ASSERT) |
178 Vector<SVGTextLayoutAttributes*> newLayoutAttributes; | 174 Vector<LayoutSVGInlineText*> newDescendantTextNodes; |
179 collectLayoutAttributes(text, newLayoutAttributes); | 175 collectDescendantTextNodes(text, newDescendantTextNodes); |
180 ASSERT(newLayoutAttributes == expectedLayoutAttributes); | 176 ASSERT(newDescendantTextNodes == expectedDescendantTextNodes); |
181 #endif | 177 #endif |
182 } | 178 } |
183 | 179 |
184 void LayoutSVGText::layout() | 180 void LayoutSVGText::layout() |
185 { | 181 { |
186 ASSERT(needsLayout()); | 182 ASSERT(needsLayout()); |
187 // This flag is set and reset as needed only within this function. | 183 // This flag is set and reset as needed only within this function. |
188 ASSERT(!m_needsReordering); | 184 ASSERT(!m_needsReordering); |
189 LayoutAnalyzer::Scope analyzer(*this); | 185 LayoutAnalyzer::Scope analyzer(*this); |
190 | 186 |
(...skipping 18 matching lines...) Expand all Loading... |
209 // update them before updating the layout attributes. | 205 // update them before updating the layout attributes. |
210 if (m_needsTextMetricsUpdate || SVGLayoutSupport::findTreeRootObject(this)->
isLayoutSizeChanged()) { | 206 if (m_needsTextMetricsUpdate || SVGLayoutSupport::findTreeRootObject(this)->
isLayoutSizeChanged()) { |
211 updateFontAndMetrics(*this); | 207 updateFontAndMetrics(*this); |
212 m_needsTextMetricsUpdate = false; | 208 m_needsTextMetricsUpdate = false; |
213 updateParentBoundaries = true; | 209 updateParentBoundaries = true; |
214 } | 210 } |
215 | 211 |
216 // When the x/y/dx/dy/rotate lists change, we need to recompute the layout | 212 // When the x/y/dx/dy/rotate lists change, we need to recompute the layout |
217 // attributes. | 213 // attributes. |
218 if (m_needsPositioningValuesUpdate) { | 214 if (m_needsPositioningValuesUpdate) { |
219 m_layoutAttributes.clear(); | 215 m_descendantTextNodes.clear(); |
220 collectLayoutAttributes(this, m_layoutAttributes); | 216 collectDescendantTextNodes(*this, m_descendantTextNodes); |
221 | 217 |
222 SVGTextLayoutAttributesBuilder(*this).buildLayoutAttributes(); | 218 SVGTextLayoutAttributesBuilder(*this).buildLayoutAttributes(); |
223 | 219 |
224 m_needsPositioningValuesUpdate = false; | 220 m_needsPositioningValuesUpdate = false; |
225 m_needsReordering = true; | 221 m_needsReordering = true; |
226 updateParentBoundaries = true; | 222 updateParentBoundaries = true; |
227 } | 223 } |
228 | 224 |
229 checkLayoutAttributesConsistency(this, m_layoutAttributes); | 225 checkDescendantTextNodeConsistency(*this, m_descendantTextNodes); |
230 | 226 |
231 // Reduced version of LayoutBlock::layoutBlock(), which only takes care of S
VG text. | 227 // Reduced version of LayoutBlock::layoutBlock(), which only takes care of S
VG text. |
232 // All if branches that could cause early exit in LayoutBlocks layoutBlock()
method are turned into assertions. | 228 // All if branches that could cause early exit in LayoutBlocks layoutBlock()
method are turned into assertions. |
233 ASSERT(!isInline()); | 229 ASSERT(!isInline()); |
234 ASSERT(!simplifiedLayout()); | 230 ASSERT(!simplifiedLayout()); |
235 ASSERT(!scrollsOverflow()); | 231 ASSERT(!scrollsOverflow()); |
236 ASSERT(!hasControlClip()); | 232 ASSERT(!hasControlClip()); |
237 ASSERT(!positionedObjects()); | 233 ASSERT(!positionedObjects()); |
238 ASSERT(!isAnonymousBlock()); | 234 ASSERT(!isAnonymousBlock()); |
239 | 235 |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 paintInvalidationState.pushDelayedPaintInvalidationTarget(*this); | 409 paintInvalidationState.pushDelayedPaintInvalidationTarget(*this); |
414 | 410 |
415 if (reason == PaintInvalidationSVGResourceChange) | 411 if (reason == PaintInvalidationSVGResourceChange) |
416 newPaintInvalidationState.setForceSubtreeInvalidationWithinContainer(); | 412 newPaintInvalidationState.setForceSubtreeInvalidationWithinContainer(); |
417 | 413 |
418 newPaintInvalidationState.updateForChildren(); | 414 newPaintInvalidationState.updateForChildren(); |
419 invalidatePaintOfSubtreesIfNeeded(newPaintInvalidationState); | 415 invalidatePaintOfSubtreesIfNeeded(newPaintInvalidationState); |
420 } | 416 } |
421 | 417 |
422 } // namespace blink | 418 } // namespace blink |
OLD | NEW |