| 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 |