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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 #include "core/paint/SVGTextPainter.h" | 43 #include "core/paint/SVGTextPainter.h" |
44 #include "core/style/ShadowList.h" | 44 #include "core/style/ShadowList.h" |
45 #include "core/svg/SVGTextElement.h" | 45 #include "core/svg/SVGTextElement.h" |
46 #include "platform/geometry/FloatQuad.h" | 46 #include "platform/geometry/FloatQuad.h" |
47 | 47 |
48 namespace blink { | 48 namespace blink { |
49 | 49 |
50 namespace { | 50 namespace { |
51 | 51 |
52 const LayoutSVGText* findTextRoot(const LayoutObject* start) { | 52 const LayoutSVGText* findTextRoot(const LayoutObject* start) { |
53 ASSERT(start); | 53 DCHECK(start); |
54 for (; start; start = start->parent()) { | 54 for (; start; start = start->parent()) { |
55 if (start->isSVGText()) | 55 if (start->isSVGText()) |
56 return toLayoutSVGText(start); | 56 return toLayoutSVGText(start); |
57 } | 57 } |
58 return nullptr; | 58 return nullptr; |
59 } | 59 } |
60 | 60 |
61 } // namespace | 61 } // namespace |
62 | 62 |
63 LayoutSVGText::LayoutSVGText(SVGTextElement* node) | 63 LayoutSVGText::LayoutSVGText(SVGTextElement* node) |
64 : LayoutSVGBlock(node), | 64 : LayoutSVGBlock(node), |
65 m_needsReordering(false), | 65 m_needsReordering(false), |
66 m_needsPositioningValuesUpdate(false), | 66 m_needsPositioningValuesUpdate(false), |
67 m_needsTransformUpdate(true), | 67 m_needsTransformUpdate(true), |
68 m_needsTextMetricsUpdate(false) {} | 68 m_needsTextMetricsUpdate(false) {} |
69 | 69 |
70 LayoutSVGText::~LayoutSVGText() { | 70 LayoutSVGText::~LayoutSVGText() { |
71 ASSERT(m_descendantTextNodes.isEmpty()); | 71 DCHECK(m_descendantTextNodes.isEmpty()); |
72 } | 72 } |
73 | 73 |
74 void LayoutSVGText::willBeDestroyed() { | 74 void LayoutSVGText::willBeDestroyed() { |
75 m_descendantTextNodes.clear(); | 75 m_descendantTextNodes.clear(); |
76 | 76 |
77 LayoutSVGBlock::willBeDestroyed(); | 77 LayoutSVGBlock::willBeDestroyed(); |
78 } | 78 } |
79 | 79 |
80 bool LayoutSVGText::isChildAllowed(LayoutObject* child, | 80 bool LayoutSVGText::isChildAllowed(LayoutObject* child, |
81 const ComputedStyle&) const { | 81 const ComputedStyle&) const { |
(...skipping 22 matching lines...) Expand all Loading... |
104 | 104 |
105 void LayoutSVGText::invalidatePositioningValues( | 105 void LayoutSVGText::invalidatePositioningValues( |
106 LayoutInvalidationReasonForTracing reason) { | 106 LayoutInvalidationReasonForTracing reason) { |
107 m_descendantTextNodes.clear(); | 107 m_descendantTextNodes.clear(); |
108 setNeedsPositioningValuesUpdate(); | 108 setNeedsPositioningValuesUpdate(); |
109 setNeedsLayoutAndFullPaintInvalidation(reason); | 109 setNeedsLayoutAndFullPaintInvalidation(reason); |
110 } | 110 } |
111 | 111 |
112 void LayoutSVGText::subtreeChildWasAdded() { | 112 void LayoutSVGText::subtreeChildWasAdded() { |
113 if (beingDestroyed() || !everHadLayout()) { | 113 if (beingDestroyed() || !everHadLayout()) { |
114 ASSERT(m_descendantTextNodes.isEmpty()); | 114 DCHECK(m_descendantTextNodes.isEmpty()); |
115 return; | 115 return; |
116 } | 116 } |
117 if (documentBeingDestroyed()) | 117 if (documentBeingDestroyed()) |
118 return; | 118 return; |
119 | 119 |
120 // The positioning elements cache depends on the size of each text | 120 // The positioning elements cache depends on the size of each text |
121 // layoutObject in the subtree. If this changes, clear the cache. It will be | 121 // layoutObject in the subtree. If this changes, clear the cache. It will be |
122 // rebuilt on the next layout. | 122 // rebuilt on the next layout. |
123 invalidatePositioningValues(LayoutInvalidationReason::ChildChanged); | 123 invalidatePositioningValues(LayoutInvalidationReason::ChildChanged); |
124 setNeedsTextMetricsUpdate(); | 124 setNeedsTextMetricsUpdate(); |
125 } | 125 } |
126 | 126 |
127 void LayoutSVGText::subtreeChildWillBeRemoved() { | 127 void LayoutSVGText::subtreeChildWillBeRemoved() { |
128 if (beingDestroyed() || !everHadLayout()) { | 128 if (beingDestroyed() || !everHadLayout()) { |
129 ASSERT(m_descendantTextNodes.isEmpty()); | 129 DCHECK(m_descendantTextNodes.isEmpty()); |
130 return; | 130 return; |
131 } | 131 } |
132 | 132 |
133 // The positioning elements cache depends on the size of each text | 133 // The positioning elements cache depends on the size of each text |
134 // layoutObject in the subtree. If this changes, clear the cache. It will be | 134 // layoutObject in the subtree. If this changes, clear the cache. It will be |
135 // rebuilt on the next layout. | 135 // rebuilt on the next layout. |
136 invalidatePositioningValues(LayoutInvalidationReason::ChildChanged); | 136 invalidatePositioningValues(LayoutInvalidationReason::ChildChanged); |
137 setNeedsTextMetricsUpdate(); | 137 setNeedsTextMetricsUpdate(); |
138 } | 138 } |
139 | 139 |
140 void LayoutSVGText::subtreeTextDidChange() { | 140 void LayoutSVGText::subtreeTextDidChange() { |
141 ASSERT(!beingDestroyed()); | 141 DCHECK(!beingDestroyed()); |
142 if (!everHadLayout()) { | 142 if (!everHadLayout()) { |
143 ASSERT(m_descendantTextNodes.isEmpty()); | 143 DCHECK(m_descendantTextNodes.isEmpty()); |
144 return; | 144 return; |
145 } | 145 } |
146 | 146 |
147 // The positioning elements cache depends on the size of each text object in | 147 // The positioning elements cache depends on the size of each text object in |
148 // the subtree. If this changes, clear the cache and mark it for rebuilding | 148 // the subtree. If this changes, clear the cache and mark it for rebuilding |
149 // in the next layout. | 149 // in the next layout. |
150 invalidatePositioningValues(LayoutInvalidationReason::TextChanged); | 150 invalidatePositioningValues(LayoutInvalidationReason::TextChanged); |
151 setNeedsTextMetricsUpdate(); | 151 setNeedsTextMetricsUpdate(); |
152 } | 152 } |
153 | 153 |
154 static inline void updateFontAndMetrics(LayoutSVGText& textRoot) { | 154 static inline void updateFontAndMetrics(LayoutSVGText& textRoot) { |
155 bool lastCharacterWasWhiteSpace = true; | 155 bool lastCharacterWasWhiteSpace = true; |
156 for (LayoutObject* descendant = textRoot.firstChild(); descendant; | 156 for (LayoutObject* descendant = textRoot.firstChild(); descendant; |
157 descendant = descendant->nextInPreOrder(&textRoot)) { | 157 descendant = descendant->nextInPreOrder(&textRoot)) { |
158 if (!descendant->isSVGInlineText()) | 158 if (!descendant->isSVGInlineText()) |
159 continue; | 159 continue; |
160 LayoutSVGInlineText& text = toLayoutSVGInlineText(*descendant); | 160 LayoutSVGInlineText& text = toLayoutSVGInlineText(*descendant); |
161 text.updateScaledFont(); | 161 text.updateScaledFont(); |
162 text.updateMetricsList(lastCharacterWasWhiteSpace); | 162 text.updateMetricsList(lastCharacterWasWhiteSpace); |
163 } | 163 } |
164 } | 164 } |
165 | 165 |
166 static inline void checkDescendantTextNodeConsistency( | 166 static inline void checkDescendantTextNodeConsistency( |
167 LayoutSVGText& text, | 167 LayoutSVGText& text, |
168 Vector<LayoutSVGInlineText*>& expectedDescendantTextNodes) { | 168 Vector<LayoutSVGInlineText*>& expectedDescendantTextNodes) { |
169 #if DCHECK_IS_ON() | 169 #if DCHECK_IS_ON() |
170 Vector<LayoutSVGInlineText*> newDescendantTextNodes; | 170 Vector<LayoutSVGInlineText*> newDescendantTextNodes; |
171 collectDescendantTextNodes(text, newDescendantTextNodes); | 171 collectDescendantTextNodes(text, newDescendantTextNodes); |
172 ASSERT(newDescendantTextNodes == expectedDescendantTextNodes); | 172 DCHECK(newDescendantTextNodes == expectedDescendantTextNodes); |
173 #endif | 173 #endif |
174 } | 174 } |
175 | 175 |
176 void LayoutSVGText::layout() { | 176 void LayoutSVGText::layout() { |
177 ASSERT(needsLayout()); | 177 DCHECK(needsLayout()); |
178 // This flag is set and reset as needed only within this function. | 178 // This flag is set and reset as needed only within this function. |
179 ASSERT(!m_needsReordering); | 179 DCHECK(!m_needsReordering); |
180 LayoutAnalyzer::Scope analyzer(*this); | 180 LayoutAnalyzer::Scope analyzer(*this); |
181 | 181 |
182 bool updateParentBoundaries = false; | 182 bool updateParentBoundaries = false; |
183 if (m_needsTransformUpdate) { | 183 if (m_needsTransformUpdate) { |
184 m_localTransform = toSVGTextElement(node())->calculateTransform( | 184 m_localTransform = toSVGTextElement(node())->calculateTransform( |
185 SVGElement::IncludeMotionTransform); | 185 SVGElement::IncludeMotionTransform); |
186 m_needsTransformUpdate = false; | 186 m_needsTransformUpdate = false; |
187 updateParentBoundaries = true; | 187 updateParentBoundaries = true; |
188 } | 188 } |
189 | 189 |
(...skipping 26 matching lines...) Expand all Loading... |
216 m_needsPositioningValuesUpdate = false; | 216 m_needsPositioningValuesUpdate = false; |
217 m_needsReordering = true; | 217 m_needsReordering = true; |
218 updateParentBoundaries = true; | 218 updateParentBoundaries = true; |
219 } | 219 } |
220 | 220 |
221 checkDescendantTextNodeConsistency(*this, m_descendantTextNodes); | 221 checkDescendantTextNodeConsistency(*this, m_descendantTextNodes); |
222 | 222 |
223 // Reduced version of LayoutBlock::layoutBlock(), which only takes care of SVG | 223 // Reduced version of LayoutBlock::layoutBlock(), which only takes care of SVG |
224 // text. All if branches that could cause early exit in LayoutBlocks | 224 // text. All if branches that could cause early exit in LayoutBlocks |
225 // layoutBlock() method are turned into assertions. | 225 // layoutBlock() method are turned into assertions. |
226 ASSERT(!isInline()); | 226 DCHECK(!isInline()); |
227 ASSERT(!simplifiedLayout()); | 227 DCHECK(!simplifiedLayout()); |
228 ASSERT(!scrollsOverflow()); | 228 DCHECK(!scrollsOverflow()); |
229 ASSERT(!hasControlClip()); | 229 DCHECK(!hasControlClip()); |
230 ASSERT(!positionedObjects()); | 230 DCHECK(!positionedObjects()); |
231 ASSERT(!isAnonymousBlock()); | 231 DCHECK(!isAnonymousBlock()); |
232 | 232 |
233 if (!firstChild()) | 233 if (!firstChild()) |
234 setChildrenInline(true); | 234 setChildrenInline(true); |
235 | 235 |
236 // FIXME: We need to find a way to only layout the child boxes, if needed. | 236 // FIXME: We need to find a way to only layout the child boxes, if needed. |
237 FloatRect oldBoundaries = objectBoundingBox(); | 237 FloatRect oldBoundaries = objectBoundingBox(); |
238 ASSERT(childrenInline()); | 238 DCHECK(childrenInline()); |
239 | 239 |
240 rebuildFloatsFromIntruding(); | 240 rebuildFloatsFromIntruding(); |
241 | 241 |
242 LayoutUnit beforeEdge = borderBefore() + paddingBefore(); | 242 LayoutUnit beforeEdge = borderBefore() + paddingBefore(); |
243 LayoutUnit afterEdge = | 243 LayoutUnit afterEdge = |
244 borderAfter() + paddingAfter() + scrollbarLogicalHeight(); | 244 borderAfter() + paddingAfter() + scrollbarLogicalHeight(); |
245 setLogicalHeight(beforeEdge); | 245 setLogicalHeight(beforeEdge); |
246 | 246 |
247 LayoutState state(*this); | 247 LayoutState state(*this); |
248 layoutInlineChildren(true, afterEdge); | 248 layoutInlineChildren(true, afterEdge); |
249 | 249 |
250 m_needsReordering = false; | 250 m_needsReordering = false; |
251 | 251 |
252 FloatRect newBoundaries = objectBoundingBox(); | 252 FloatRect newBoundaries = objectBoundingBox(); |
253 if (!updateParentBoundaries) | 253 if (!updateParentBoundaries) |
254 updateParentBoundaries = oldBoundaries != newBoundaries; | 254 updateParentBoundaries = oldBoundaries != newBoundaries; |
255 | 255 |
256 m_overflow.reset(); | 256 m_overflow.reset(); |
257 addSelfVisualOverflow(LayoutRect(newBoundaries)); | 257 addSelfVisualOverflow(LayoutRect(newBoundaries)); |
258 addVisualEffectOverflow(); | 258 addVisualEffectOverflow(); |
259 | 259 |
260 // Invalidate all resources of this client if our layout changed. | 260 // Invalidate all resources of this client if our layout changed. |
261 if (everHadLayout() && selfNeedsLayout()) | 261 if (everHadLayout() && selfNeedsLayout()) |
262 SVGResourcesCache::clientLayoutChanged(this); | 262 SVGResourcesCache::clientLayoutChanged(this); |
263 | 263 |
264 // If our bounds changed, notify the parents. | 264 // If our bounds changed, notify the parents. |
265 if (updateParentBoundaries) | 265 if (updateParentBoundaries) |
266 LayoutSVGBlock::setNeedsBoundariesUpdate(); | 266 LayoutSVGBlock::setNeedsBoundariesUpdate(); |
267 | 267 |
268 ASSERT(!m_needsReordering); | 268 DCHECK(!m_needsReordering); |
269 ASSERT(!m_needsTransformUpdate); | 269 DCHECK(!m_needsTransformUpdate); |
270 ASSERT(!m_needsTextMetricsUpdate); | 270 DCHECK(!m_needsTextMetricsUpdate); |
271 ASSERT(!m_needsPositioningValuesUpdate); | 271 DCHECK(!m_needsPositioningValuesUpdate); |
272 clearNeedsLayout(); | 272 clearNeedsLayout(); |
273 } | 273 } |
274 | 274 |
275 RootInlineBox* LayoutSVGText::createRootInlineBox() { | 275 RootInlineBox* LayoutSVGText::createRootInlineBox() { |
276 RootInlineBox* box = new SVGRootInlineBox(LineLayoutItem(this)); | 276 RootInlineBox* box = new SVGRootInlineBox(LineLayoutItem(this)); |
277 box->setHasVirtualLogicalHeight(); | 277 box->setHasVirtualLogicalHeight(); |
278 return box; | 278 return box; |
279 } | 279 } |
280 | 280 |
281 bool LayoutSVGText::nodeAtFloatPoint(HitTestResult& result, | 281 bool LayoutSVGText::nodeAtFloatPoint(HitTestResult& result, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 const LayoutPoint& pointInContents) { | 324 const LayoutPoint& pointInContents) { |
325 RootInlineBox* rootBox = firstRootBox(); | 325 RootInlineBox* rootBox = firstRootBox(); |
326 if (!rootBox) | 326 if (!rootBox) |
327 return createPositionWithAffinity(0); | 327 return createPositionWithAffinity(0); |
328 | 328 |
329 LayoutPoint clippedPointInContents(pointInContents); | 329 LayoutPoint clippedPointInContents(pointInContents); |
330 clippedPointInContents.moveBy(-rootBox->location()); | 330 clippedPointInContents.moveBy(-rootBox->location()); |
331 clippedPointInContents.clampNegativeToZero(); | 331 clippedPointInContents.clampNegativeToZero(); |
332 clippedPointInContents.moveBy(rootBox->location()); | 332 clippedPointInContents.moveBy(rootBox->location()); |
333 | 333 |
334 ASSERT(!rootBox->nextRootBox()); | 334 DCHECK(!rootBox->nextRootBox()); |
335 ASSERT(childrenInline()); | 335 DCHECK(childrenInline()); |
336 | 336 |
337 InlineBox* closestBox = | 337 InlineBox* closestBox = |
338 toSVGRootInlineBox(rootBox)->closestLeafChildForPosition( | 338 toSVGRootInlineBox(rootBox)->closestLeafChildForPosition( |
339 clippedPointInContents); | 339 clippedPointInContents); |
340 if (!closestBox) | 340 if (!closestBox) |
341 return createPositionWithAffinity(0); | 341 return createPositionWithAffinity(0); |
342 | 342 |
343 return closestBox->getLineLayoutItem().positionForPoint( | 343 return closestBox->getLineLayoutItem().positionForPoint( |
344 LayoutPoint(clippedPointInContents.x(), closestBox->y())); | 344 LayoutPoint(clippedPointInContents.x(), closestBox->y())); |
345 } | 345 } |
(...skipping 13 matching lines...) Expand all Loading... |
359 return FloatRect(box->frameRect()); | 359 return FloatRect(box->frameRect()); |
360 return FloatRect(); | 360 return FloatRect(); |
361 } | 361 } |
362 | 362 |
363 FloatRect LayoutSVGText::strokeBoundingBox() const { | 363 FloatRect LayoutSVGText::strokeBoundingBox() const { |
364 FloatRect strokeBoundaries = objectBoundingBox(); | 364 FloatRect strokeBoundaries = objectBoundingBox(); |
365 const SVGComputedStyle& svgStyle = style()->svgStyle(); | 365 const SVGComputedStyle& svgStyle = style()->svgStyle(); |
366 if (!svgStyle.hasStroke()) | 366 if (!svgStyle.hasStroke()) |
367 return strokeBoundaries; | 367 return strokeBoundaries; |
368 | 368 |
369 ASSERT(node()); | 369 DCHECK(node()); |
370 ASSERT(node()->isSVGElement()); | 370 DCHECK(node()->isSVGElement()); |
371 SVGLengthContext lengthContext(toSVGElement(node())); | 371 SVGLengthContext lengthContext(toSVGElement(node())); |
372 strokeBoundaries.inflate( | 372 strokeBoundaries.inflate( |
373 lengthContext.valueForLength(svgStyle.strokeWidth())); | 373 lengthContext.valueForLength(svgStyle.strokeWidth())); |
374 return strokeBoundaries; | 374 return strokeBoundaries; |
375 } | 375 } |
376 | 376 |
377 FloatRect LayoutSVGText::visualRectInLocalSVGCoordinates() const { | 377 FloatRect LayoutSVGText::visualRectInLocalSVGCoordinates() const { |
378 FloatRect visualRect = strokeBoundingBox(); | 378 FloatRect visualRect = strokeBoundingBox(); |
379 SVGLayoutSupport::adjustVisualRectWithResources(this, visualRect); | 379 SVGLayoutSupport::adjustVisualRectWithResources(this, visualRect); |
380 | 380 |
(...skipping 30 matching lines...) Expand all Loading... |
411 | 411 |
412 void LayoutSVGText::invalidateTreeIfNeeded( | 412 void LayoutSVGText::invalidateTreeIfNeeded( |
413 const PaintInvalidationState& paintInvalidationState) { | 413 const PaintInvalidationState& paintInvalidationState) { |
414 // TODO(wangxianzhu): Verify if the inherited | 414 // TODO(wangxianzhu): Verify if the inherited |
415 // LayoutBoxModelObject::invalidateTreeIfNeeded() | 415 // LayoutBoxModelObject::invalidateTreeIfNeeded() |
416 // is applicable here. If yes, remove this overriding method. | 416 // is applicable here. If yes, remove this overriding method. |
417 LayoutObject::invalidateTreeIfNeeded(paintInvalidationState); | 417 LayoutObject::invalidateTreeIfNeeded(paintInvalidationState); |
418 } | 418 } |
419 | 419 |
420 } // namespace blink | 420 } // namespace blink |
OLD | NEW |