Changeset 105057 in webkit
- Timestamp:
- Jan 16, 2012 5:08:29 AM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r105056 r105057 1 2012-01-16 Nikolas Zimmermann <nzimmermann@rim.com> 2 3 Large SVG text layout performance regression in r81168 4 https://bugs.webkit.org/show_bug.cgi?id=65711 5 6 Reviewed by Zoltan Herczeg. 7 8 Change the way we store x/y/dx/dy/rotate values for a <text> element and its ancestors. 9 10 SVGTextLayoutAttributesBuilder used to hold a Vector<float> for x/y/dx/dy/rotate, each as big 11 as the whole text subtree length. For each character, that has an absolute position, or rotation 12 the value was stored in this list. For all other characters a special empty value marker was stored. 13 14 This is highly inefficient, and is now replaced with a HashMap<unsigned, SVGCharacterData> where 15 SVGCharacterData is a struct, holding float x/y/dx/dy/rotate. The code is now optimized for the 16 common case, where only a few characters actually specify such values, eg: 17 <text x="50" y="90">looooong text<tspan x="50" y="30">abc</tspan></text>. 18 19 NOTE: There are still some inefficiencies in this patch (especially the copying of SVGTextLayoutAttributes). 20 To keep the patch size smaller, I decided to fix this in another patch, and only fix the memory issue with this patch. 21 22 This reduces the memory consumption from 35MB to 10MB on the attached testcase in bug 65711. 23 24 Doesn't affect any test, yet. A follow-up commit will enable the usage of the simple code path, using WidthIterator, 25 in SVGTextMetricsBuilder, which will result in several layout test changes, because of geometry changes. 26 27 * rendering/svg/RenderSVGInlineText.cpp: 28 (WebCore::RenderSVGInlineText::RenderSVGInlineText): 29 (WebCore::RenderSVGInlineText::characterStartsNewTextChunk): 30 * rendering/svg/RenderSVGInlineText.h: 31 (WebCore::RenderSVGInlineText::layoutAttributes): 32 * rendering/svg/RenderSVGText.cpp: 33 (WebCore::RenderSVGText::layout): 34 (WebCore::recursiveCollectLayoutAttributes): 35 (WebCore::RenderSVGText::rebuildLayoutAttributes): 36 * rendering/svg/RenderSVGText.h: 37 * rendering/svg/SVGRootInlineBox.cpp: 38 (WebCore::SVGRootInlineBox::computePerCharacterLayoutInformation): 39 (WebCore::SVGRootInlineBox::layoutCharactersInTextBoxes): 40 (WebCore::SVGRootInlineBox::closestLeafChildForPosition): 41 (WebCore::swapItemsInLayoutAttributes): 42 (WebCore::findFirstAndLastAttributesInVector): 43 (WebCore::reverseInlineBoxRangeAndValueListsIfNeeded): 44 * rendering/svg/SVGTextLayoutAttributes.cpp: 45 (WebCore::SVGTextLayoutAttributes::clear): 46 (WebCore::dumpSVGCharacterDataMapValue): 47 (WebCore::SVGTextLayoutAttributes::dump): 48 * rendering/svg/SVGTextLayoutAttributes.h: 49 (WebCore::SVGTextLayoutAttributes::characterDataMap): 50 * rendering/svg/SVGTextLayoutAttributesBuilder.cpp: 51 (WebCore::SVGTextLayoutAttributesBuilder::SVGTextLayoutAttributesBuilder): 52 (WebCore::SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextRenderer): 53 (WebCore::SVGTextLayoutAttributesBuilder::buildLayoutAttributesForWholeTree): 54 (WebCore::SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer): 55 (WebCore::SVGTextLayoutAttributesBuilder::rebuildMetricsForWholeTree): 56 (WebCore::SVGTextLayoutAttributesBuilder::buildLayoutAttributesIfNeeded): 57 (WebCore::processRenderSVGInlineText): 58 (WebCore::SVGTextLayoutAttributesBuilder::collectTextPositioningElements): 59 (WebCore::SVGTextLayoutAttributesBuilder::buildLayoutAttributes): 60 (WebCore::updateCharacterData): 61 (WebCore::SVGTextLayoutAttributesBuilder::fillCharacterDataMap): 62 * rendering/svg/SVGTextLayoutAttributesBuilder.h: 63 (WebCore::SVGTextLayoutAttributesBuilder::clearTextPositioningElements): 64 * rendering/svg/SVGTextLayoutEngine.cpp: 65 (WebCore::SVGTextLayoutEngine::updateRelativePositionAdjustmentsIfNeeded): 66 (WebCore::SVGTextLayoutEngine::currentLogicalCharacterAttributes): 67 (WebCore::SVGTextLayoutEngine::layoutTextOnLineOrPath): 68 * rendering/svg/SVGTextLayoutEngine.h: 69 (WebCore::SVGTextLayoutEngine::layoutAttributes): 70 * rendering/svg/SVGTextMetricsBuilder.cpp: 71 (WebCore::SVGTextMetricsBuilder::advance): 72 (WebCore::SVGTextMetricsBuilder::advanceComplexText): 73 (WebCore::SVGTextMetricsBuilder::measureTextRenderer): 74 * rendering/svg/SVGTextQuery.cpp: 75 (WebCore::SVGTextQuery::modifyStartEndPositionsRespectingLigatures): 76 1 77 2012-01-15 Andreas Kling <awesomekling@apple.com> 2 78 -
trunk/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp
r101342 r105057 69 69 : RenderText(n, applySVGWhitespaceRules(string, false)) 70 70 , m_scalingFactor(1) 71 , m_layoutAttributes(this) 71 72 { 72 73 } … … 141 142 bool RenderSVGInlineText::characterStartsNewTextChunk(int position) const 142 143 { 143 ASSERT(m_attributes.xValues().size() == textLength());144 ASSERT(m_attributes.yValues().size() == textLength());145 144 ASSERT(position >= 0); 146 145 ASSERT(position < static_cast<int>(textLength())); … … 150 149 return true; 151 150 152 int currentPosition = 0; 153 unsigned size = m_attributes.textMetricsValues().size(); 154 for (unsigned i = 0; i < size; ++i) { 155 const SVGTextMetrics& metrics = m_attributes.textMetricsValues().at(i); 156 157 // We found the desired character. 158 if (currentPosition == position) { 159 return m_attributes.xValues().at(position) != SVGTextLayoutAttributes::emptyValue() 160 || m_attributes.yValues().at(position) != SVGTextLayoutAttributes::emptyValue(); 161 } 162 163 currentPosition += metrics.length(); 164 if (currentPosition > position) 165 break; 166 } 167 168 // The desired position is available in the x/y list, but not in the character data values list. 169 // That means the previous character data described a single glyph, consisting of multiple unicode characters. 170 // The consequence is that the desired character does not define a new absolute x/y position, even if present in the x/y test. 171 // This code is tested by svg/W3C-SVG-1.1/text-text-06-t.svg (and described in detail, why this influences chunk detection). 172 return false; 151 const SVGCharacterDataMap::const_iterator it = m_layoutAttributes.characterDataMap().find(static_cast<unsigned>(position + 1)); 152 if (it == m_layoutAttributes.characterDataMap().end()) 153 return false; 154 155 return it->second.x != SVGTextLayoutAttributes::emptyValue() || it->second.y != SVGTextLayoutAttributes::emptyValue(); 173 156 } 174 157 -
trunk/Source/WebCore/rendering/svg/RenderSVGInlineText.h
r101342 r105057 36 36 37 37 bool characterStartsNewTextChunk(int position) const; 38 39 SVGTextLayoutAttributes& layoutAttributes() { return m_attributes; } 40 const SVGTextLayoutAttributes& layoutAttributes() const { return m_attributes; } 41 void storeLayoutAttributes(const SVGTextLayoutAttributes& attributes) { m_attributes = attributes; } 38 SVGTextLayoutAttributes& layoutAttributes() { return m_layoutAttributes; } 42 39 43 40 float scalingFactor() const { return m_scalingFactor; } … … 69 66 float m_scalingFactor; 70 67 Font m_scaledFont; 71 SVGTextLayoutAttributes m_ attributes;68 SVGTextLayoutAttributes m_layoutAttributes; 72 69 }; 73 70 -
trunk/Source/WebCore/rendering/svg/RenderSVGText.cpp
r104683 r105057 142 142 if (m_needsPositioningValuesUpdate) { 143 143 // Perform SVG text layout phase one (see SVGTextLayoutAttributesBuilder for details). 144 SVGTextLayoutAttributesBuilder layoutAttributesBuilder; 145 layoutAttributesBuilder.buildLayoutAttributesForTextSubtree(this); 144 m_layoutAttributesBuilder.buildLayoutAttributesForWholeTree(this); 146 145 m_needsReordering = true; 147 146 m_needsPositioningValuesUpdate = false; … … 294 293 } 295 294 295 static inline void recursiveCollectLayoutAttributes(RenderObject* start, Vector<SVGTextLayoutAttributes>& attributes) 296 { 297 for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) { 298 if (child->isSVGInlineText()) { 299 attributes.append(toRenderSVGInlineText(child)->layoutAttributes()); 300 continue; 301 } 302 303 recursiveCollectLayoutAttributes(child, attributes); 304 } 305 } 306 307 void RenderSVGText::rebuildLayoutAttributes(bool performFullRebuild) 308 { 309 // FIXME: For now we always rebuild the whole tree, as it used to be. 310 performFullRebuild = true; 311 if (performFullRebuild) 312 m_layoutAttributes.clear(); 313 314 if (m_layoutAttributes.isEmpty()) { 315 recursiveCollectLayoutAttributes(this, m_layoutAttributes); 316 if (m_layoutAttributes.isEmpty() || !performFullRebuild) 317 return; 318 319 m_layoutAttributesBuilder.rebuildMetricsForWholeTree(this); 320 return; 321 } 322 323 /* FIXME: Enable this once we rebuild subtrees, instead of the full tree 324 Vector<SVGTextLayoutAttributes*> affectedAttributes; 325 rebuildLayoutAttributes(affectedAttributes); 326 */ 327 } 328 296 329 } 297 330 -
trunk/Source/WebCore/rendering/svg/RenderSVGText.h
r104683 r105057 27 27 #include "AffineTransform.h" 28 28 #include "RenderSVGBlock.h" 29 #include "SVGTextLayoutAttributes .h"29 #include "SVGTextLayoutAttributesBuilder.h" 30 30 31 31 namespace WebCore { … … 49 49 Vector<SVGTextLayoutAttributes>& layoutAttributes() { return m_layoutAttributes; } 50 50 bool needsReordering() const { return m_needsReordering; } 51 52 void rebuildLayoutAttributes(bool performFullRebuild = false); 51 53 52 54 private: … … 84 86 bool m_needsTransformUpdate : 1; 85 87 AffineTransform m_localTransform; 88 SVGTextLayoutAttributesBuilder m_layoutAttributesBuilder; 86 89 Vector<SVGTextLayoutAttributes> m_layoutAttributes; 87 90 }; -
trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp
r101342 r105057 74 74 void SVGRootInlineBox::computePerCharacterLayoutInformation() 75 75 { 76 RenderSVGText* parentBlock = toRenderSVGText(block()); 77 ASSERT(parentBlock); 78 79 Vector<SVGTextLayoutAttributes>& attributes = parentBlock->layoutAttributes(); 80 if (attributes.isEmpty()) 76 RenderSVGText* textRoot = toRenderSVGText(block()); 77 ASSERT(textRoot); 78 79 textRoot->rebuildLayoutAttributes(); 80 Vector<SVGTextLayoutAttributes>& layoutAttributes = textRoot->layoutAttributes(); 81 if (layoutAttributes.isEmpty()) 81 82 return; 82 83 83 if ( parentBlock->needsReordering())84 reorderValueLists( attributes);84 if (textRoot->needsReordering()) 85 reorderValueLists(layoutAttributes); 85 86 86 87 // Perform SVG text layout phase two (see SVGTextLayoutEngine for details). 87 SVGTextLayoutEngine characterLayout( attributes);88 SVGTextLayoutEngine characterLayout(layoutAttributes); 88 89 layoutCharactersInTextBoxes(this, characterLayout); 89 90 … … 120 121 // Build text chunks for all <textPath> children, using the line layout algorithm. 121 122 // This is needeed as text-anchor is just an additional startOffset for text paths. 122 RenderSVGText* parentBlock = toRenderSVGText(block()); 123 ASSERT(parentBlock); 124 125 SVGTextLayoutEngine lineLayout(parentBlock->layoutAttributes()); 123 SVGTextLayoutEngine lineLayout(characterLayout.layoutAttributes()); 126 124 layoutCharactersInTextBoxes(flowBox, lineLayout); 127 125 … … 222 220 return closestLeaf ? closestLeaf : lastLeaf; 223 221 } 224 225 static inline void swapItemsInVector(Vector<float>& firstVector, Vector<float>& lastVector, unsigned first, unsigned last) 226 { 227 float temp = firstVector.at(first); 228 firstVector.at(first) = lastVector.at(last); 229 lastVector.at(last) = temp; 230 } 231 232 static inline void swapItemsInLayoutAttributes(SVGTextLayoutAttributes& firstAttributes, SVGTextLayoutAttributes& lastAttributes, unsigned firstPosition, unsigned lastPosition) 233 { 234 swapItemsInVector(firstAttributes.xValues(), lastAttributes.xValues(), firstPosition, lastPosition); 235 swapItemsInVector(firstAttributes.yValues(), lastAttributes.yValues(), firstPosition, lastPosition); 236 swapItemsInVector(firstAttributes.dxValues(), lastAttributes.dxValues(), firstPosition, lastPosition); 237 swapItemsInVector(firstAttributes.dyValues(), lastAttributes.dyValues(), firstPosition, lastPosition); 238 swapItemsInVector(firstAttributes.rotateValues(), lastAttributes.rotateValues(), firstPosition, lastPosition); 222 223 static inline void swapItemsInLayoutAttributes(SVGTextLayoutAttributes* firstAttributes, SVGTextLayoutAttributes* lastAttributes, unsigned firstPosition, unsigned lastPosition) 224 { 225 SVGCharacterDataMap::iterator itFirst = firstAttributes->characterDataMap().find(firstPosition + 1); 226 SVGCharacterDataMap::iterator itLast = lastAttributes->characterDataMap().find(lastPosition + 1); 227 bool firstPresent = itFirst != firstAttributes->characterDataMap().end(); 228 bool lastPresent = itLast != lastAttributes->characterDataMap().end(); 229 if (!firstPresent && !lastPresent) 230 return; 231 232 if (firstPresent && lastPresent) { 233 std::swap(itFirst->second, itLast->second); 234 return; 235 } 236 237 if (firstPresent && !lastPresent) { 238 lastAttributes->characterDataMap().set(lastPosition + 1, itFirst->second); 239 return; 240 } 241 242 // !firstPresent && lastPresent 243 firstAttributes->characterDataMap().set(firstPosition + 1, itLast->second); 239 244 } 240 245 … … 247 252 unsigned attributesSize = attributes.size(); 248 253 for (unsigned i = 0; i < attributesSize; ++i) { 249 SVGTextLayoutAttributes& current = attributes .at(i);254 SVGTextLayoutAttributes& current = attributes[i]; 250 255 if (!first && firstContext == current.context()) 251 256 first = ¤t; … … 265 270 Vector<SVGTextLayoutAttributes>& attributes = *reinterpret_cast<Vector<SVGTextLayoutAttributes>*>(userData); 266 271 267 // This is a copy of std::reverse(first, last). It additionally assure that the value lists withinthe InlineBoxes are reordered as well.272 // This is a copy of std::reverse(first, last). It additionally assures that the metrics map within the renderers belonging to the InlineBoxes are reordered as well. 268 273 while (true) { 269 274 if (first == last || first == --last) … … 289 294 SVGTextLayoutAttributes* lastAttributes = 0; 290 295 findFirstAndLastAttributesInVector(attributes, firstContext, lastContext, firstAttributes, lastAttributes); 291 292 unsigned firstBoxPosition = firstTextBox->start(); 293 unsigned firstBoxEnd = firstTextBox->end(); 294 295 unsigned lastBoxPosition = lastTextBox->start(); 296 unsigned lastBoxEnd = lastTextBox->end(); 297 for (; firstBoxPosition <= firstBoxEnd && lastBoxPosition <= lastBoxEnd; ++lastBoxPosition, ++firstBoxPosition) 298 swapItemsInLayoutAttributes(*firstAttributes, *lastAttributes, firstBoxPosition, lastBoxPosition); 296 swapItemsInLayoutAttributes(firstAttributes, lastAttributes, firstTextBox->start(), lastTextBox->start()); 299 297 } 300 298 -
trunk/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp
r95901 r105057 1 1 /* 2 * Copyright (C) Research In Motion Limited 2010 . All rights reserved.2 * Copyright (C) Research In Motion Limited 2010-11. All rights reserved. 3 3 * 4 4 * This library is free software; you can redistribute it and/or … … 33 33 } 34 34 35 void SVGTextLayoutAttributes:: reserveCapacity(unsigned length)35 void SVGTextLayoutAttributes::clear() 36 36 { 37 m_positioningLists.xValues.reserveCapacity(length); 38 m_positioningLists.yValues.reserveCapacity(length); 39 m_positioningLists.dxValues.reserveCapacity(length); 40 m_positioningLists.dyValues.reserveCapacity(length); 41 m_positioningLists.rotateValues.reserveCapacity(length); 42 m_textMetricsValues.reserveCapacity(length); 43 } 44 45 void SVGTextLayoutAttributes::PositioningLists::fillWithEmptyValues(unsigned length) 46 { 47 xValues.fill(SVGTextLayoutAttributes::emptyValue(), length); 48 yValues.fill(SVGTextLayoutAttributes::emptyValue(), length); 49 dxValues.fill(SVGTextLayoutAttributes::emptyValue(), length); 50 dyValues.fill(SVGTextLayoutAttributes::emptyValue(), length); 51 rotateValues.fill(SVGTextLayoutAttributes::emptyValue(), length); 52 } 53 54 void SVGTextLayoutAttributes::PositioningLists::appendEmptyValues() 55 { 56 xValues.append(SVGTextLayoutAttributes::emptyValue()); 57 yValues.append(SVGTextLayoutAttributes::emptyValue()); 58 dxValues.append(SVGTextLayoutAttributes::emptyValue()); 59 dyValues.append(SVGTextLayoutAttributes::emptyValue()); 60 rotateValues.append(SVGTextLayoutAttributes::emptyValue()); 61 } 62 63 static inline float safeValueAtPosition(const Vector<float>& values, unsigned position) 64 { 65 return position < values.size() ? values[position] : SVGTextLayoutAttributes::emptyValue(); 66 } 67 68 void SVGTextLayoutAttributes::PositioningLists::appendValuesFromPosition(const PositioningLists& source, unsigned position) 69 { 70 xValues.append(safeValueAtPosition(source.xValues, position)); 71 yValues.append(safeValueAtPosition(source.yValues, position)); 72 dxValues.append(safeValueAtPosition(source.dxValues, position)); 73 dyValues.append(safeValueAtPosition(source.dyValues, position)); 74 rotateValues.append(safeValueAtPosition(source.rotateValues, position)); 37 m_characterDataMap.clear(); 38 m_textMetricsValues.clear(); 75 39 } 76 40 … … 81 45 } 82 46 83 static inline void dump LayoutVector(const Vector<float>& values)47 static inline void dumpSVGCharacterDataMapValue(const char* identifier, float value, bool appendSpace = true) 84 48 { 85 if (values.isEmpty()) { 86 fprintf(stderr, "empty"); 49 if (value == SVGTextLayoutAttributes::emptyValue()) { 50 fprintf(stderr, "%s=x", identifier); 51 if (appendSpace) 52 fprintf(stderr, " "); 87 53 return; 88 54 } 89 90 unsigned size = values.size(); 91 for (unsigned i = 0; i < size; ++i) { 92 float value = values.at(i); 93 if (value == SVGTextLayoutAttributes::emptyValue()) 94 fprintf(stderr, "x "); 95 else 96 fprintf(stderr, "%lf ", value); 97 } 55 fprintf(stderr, "%s=%lf", identifier, value); 56 if (appendSpace) 57 fprintf(stderr, " "); 98 58 } 99 59 … … 101 61 { 102 62 fprintf(stderr, "context: %p\n", m_context); 103 104 fprintf(stderr, "x values: "); 105 dumpLayoutVector(m_positioningLists.xValues); 106 fprintf(stderr, "\n"); 107 108 fprintf(stderr, "y values: "); 109 dumpLayoutVector(m_positioningLists.yValues); 110 fprintf(stderr, "\n"); 111 112 fprintf(stderr, "dx values: "); 113 dumpLayoutVector(m_positioningLists.dxValues); 114 fprintf(stderr, "\n"); 115 116 fprintf(stderr, "dy values: "); 117 dumpLayoutVector(m_positioningLists.dyValues); 118 fprintf(stderr, "\n"); 119 120 fprintf(stderr, "rotate values: "); 121 dumpLayoutVector(m_positioningLists.rotateValues); 122 fprintf(stderr, "\n"); 123 124 fprintf(stderr, "character data values:\n"); 125 unsigned textMetricsSize = m_textMetricsValues.size(); 126 for (unsigned i = 0; i < textMetricsSize; ++i) { 127 const SVGTextMetrics& metrics = m_textMetricsValues.at(i); 128 fprintf(stderr, "| {length=%i, glyphName='%s', unicodeString='%s', width=%lf, height=%lf}\n", 129 metrics.length(), metrics.glyph().name.utf8().data(), metrics.glyph().unicodeString.utf8().data(), metrics.width(), metrics.height()); 63 const SVGCharacterDataMap::const_iterator end = m_characterDataMap.end(); 64 for (SVGCharacterDataMap::const_iterator it = m_characterDataMap.begin(); it != end; ++it) { 65 const SVGCharacterData& data = it->second; 66 fprintf(stderr, " ---> pos=%i, data={", it->first); 67 dumpSVGCharacterDataMapValue("x", data.x); 68 dumpSVGCharacterDataMapValue("y", data.y); 69 dumpSVGCharacterDataMapValue("dx", data.dx); 70 dumpSVGCharacterDataMapValue("dy", data.dy); 71 dumpSVGCharacterDataMapValue("rotate", data.rotate, false); 72 fprintf(stderr, "}\n"); 130 73 } 131 fprintf(stderr, "\n");132 74 } 133 75 -
trunk/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h
r104926 r105057 1 1 /* 2 * Copyright (C) Research In Motion Limited 2010 . All rights reserved.2 * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved. 3 3 * 4 4 * This library is free software; you can redistribute it and/or … … 44 44 class SVGTextLayoutAttributes { 45 45 public: 46 // FIXME: This struct will be replaced by SVGCharacterData in a follow up patch. 47 struct PositioningLists { 48 void fillWithEmptyValues(unsigned length); 49 void appendEmptyValues(); 50 void appendValuesFromPosition(const PositioningLists&, unsigned position); 46 SVGTextLayoutAttributes(RenderSVGInlineText*); 51 47 52 Vector<float> xValues; 53 Vector<float> yValues; 54 Vector<float> dxValues; 55 Vector<float> dyValues; 56 Vector<float> rotateValues; 57 }; 58 59 SVGTextLayoutAttributes(RenderSVGInlineText* context = 0); 60 61 // FIXME: Still a no-op, we'll need this once we switch to SVGCharacterDataMap. 62 void clear() { } 63 void reserveCapacity(unsigned length); 48 void clear(); 64 49 void dump() const; 65 66 50 static float emptyValue(); 67 51 68 52 RenderSVGInlineText* context() const { return m_context; } 69 70 PositioningLists& positioningLists() { return m_positioningLists; } 71 const PositioningLists& positioningLists() const { return m_positioningLists; } 72 73 Vector<float>& xValues() { return m_positioningLists.xValues; } 74 const Vector<float>& xValues() const { return m_positioningLists.xValues; } 75 76 Vector<float>& yValues() { return m_positioningLists.yValues; } 77 const Vector<float>& yValues() const { return m_positioningLists.yValues; } 78 79 Vector<float>& dxValues() { return m_positioningLists.dxValues; } 80 const Vector<float>& dxValues() const { return m_positioningLists.dxValues; } 81 82 Vector<float>& dyValues() { return m_positioningLists.dyValues; } 83 const Vector<float>& dyValues() const { return m_positioningLists.dyValues; } 84 85 Vector<float>& rotateValues() { return m_positioningLists.rotateValues; } 86 const Vector<float>& rotateValues() const { return m_positioningLists.rotateValues; } 53 54 SVGCharacterDataMap& characterDataMap() { return m_characterDataMap; } 55 const SVGCharacterDataMap& characterDataMap() const { return m_characterDataMap; } 87 56 88 57 Vector<SVGTextMetrics>& textMetricsValues() { return m_textMetricsValues; } 89 const Vector<SVGTextMetrics>& textMetricsValues() const { return m_textMetricsValues; }90 58 91 59 private: 92 60 RenderSVGInlineText* m_context; 93 PositioningLists m_positioningLists;61 SVGCharacterDataMap m_characterDataMap; 94 62 Vector<SVGTextMetrics> m_textMetricsValues; 95 63 }; -
trunk/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
r104683 r105057 33 33 34 34 SVGTextLayoutAttributesBuilder::SVGTextLayoutAttributesBuilder() 35 { 36 } 37 38 void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextSubtree(RenderSVGText* textRoot) 35 : m_textLength(0) 36 { 37 } 38 39 void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextRenderer(RenderSVGInlineText* text) 40 { 41 ASSERT(text); 42 43 RenderSVGText* textRoot = RenderSVGText::locateRenderSVGTextAncestor(text); 44 if (!textRoot) 45 return; 46 47 if (!buildLayoutAttributesIfNeeded(textRoot)) 48 return; 49 50 m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, text, m_characterDataMap); 51 } 52 53 void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForWholeTree(RenderSVGText* textRoot) 39 54 { 40 55 ASSERT(textRoot); 41 56 42 // We always clear our current attribute as we don't want to keep any stale ones that could survive DOM modification. 43 Vector<SVGTextLayoutAttributes>& allAttributes = textRoot->layoutAttributes(); 44 allAttributes.clear(); 45 46 // Build list of x/y/dx/dy/rotate values for each subtree element that may define these values (tspan/textPath etc). 47 unsigned atCharacter = 0; 48 UChar lastCharacter = '\0'; 49 collectTextPositioningElements(textRoot, atCharacter, lastCharacter); 50 51 if (!atCharacter) 52 return; 53 54 // Collect x/y/dx/dy/rotate values for each character, stored in the m_positioningLists.xValues()/etc. lists. 55 buildLayoutAttributesForAllCharacters(textRoot, atCharacter); 56 57 // Propagate layout attributes to each RenderSVGInlineText object, and the whole list to the RenderSVGText root. 58 atCharacter = 0; 59 lastCharacter = '\0'; 60 propagateLayoutAttributes(textRoot, allAttributes, atCharacter, lastCharacter); 61 } 62 63 static inline void extractFloatValuesFromSVGLengthList(SVGElement* contextElement, const SVGLengthList& list, Vector<float>& floatValues, unsigned textContentLength) 64 { 65 ASSERT(contextElement); 66 67 unsigned length = list.size(); 68 if (length > textContentLength) 69 length = textContentLength; 70 floatValues.reserveCapacity(length); 71 72 SVGLengthContext lengthContext(contextElement); 73 for (unsigned i = 0; i < length; ++i) { 74 const SVGLength& length = list.at(i); 75 floatValues.append(length.value(lengthContext)); 76 } 77 } 78 79 static inline void extractFloatValuesFromSVGNumberList(const SVGNumberList& list, Vector<float>& floatValues, unsigned textContentLength) 80 { 81 unsigned length = list.size(); 82 if (length > textContentLength) 83 length = textContentLength; 84 floatValues.reserveCapacity(length); 85 86 for (unsigned i = 0; i < length; ++i) 87 floatValues.append(list.at(i)); 88 } 89 90 91 static inline bool characterIsSpace(const UChar& character) 92 { 93 return character == ' '; 94 } 95 96 static inline bool characterIsSpaceOrNull(const UChar& character) 97 { 98 return character == ' ' || character == '\0'; 99 } 100 101 static inline bool shouldPreserveAllWhiteSpace(RenderStyle* style) 102 { 103 ASSERT(style); 104 return style->whiteSpace() == PRE; 105 } 106 107 static inline void processRenderSVGInlineText(RenderSVGInlineText* text, unsigned& atCharacter, UChar& lastCharacter) 108 { 109 if (shouldPreserveAllWhiteSpace(text->style())) { 57 if (!buildLayoutAttributesIfNeeded(textRoot)) 58 return; 59 60 m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, 0, m_characterDataMap); 61 } 62 63 void SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer(RenderSVGInlineText* text) 64 { 65 ASSERT(text); 66 m_metricsBuilder.measureTextRenderer(text); 67 } 68 69 void SVGTextLayoutAttributesBuilder::rebuildMetricsForWholeTree(RenderSVGText* textRoot) 70 { 71 ASSERT(textRoot); 72 Vector<SVGTextLayoutAttributes>& layoutAttributes = textRoot->layoutAttributes(); 73 74 size_t layoutAttributesSize = layoutAttributes.size(); 75 for (size_t i = 0; i < layoutAttributesSize; ++i) 76 m_metricsBuilder.measureTextRenderer(layoutAttributes[i].context()); 77 } 78 79 bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesIfNeeded(RenderSVGText* textRoot) 80 { 81 ASSERT(textRoot); 82 if (!m_textPositions.isEmpty()) 83 return m_textLength; 84 85 m_textLength = 0; 86 const UChar* lastCharacter = 0; 87 collectTextPositioningElements(textRoot, lastCharacter); 88 89 m_characterDataMap.clear(); 90 if (!m_textLength) 91 return false; 92 93 buildLayoutAttributes(textRoot); 94 return true; 95 } 96 97 static inline void processRenderSVGInlineText(RenderSVGInlineText* text, unsigned& atCharacter, const UChar*& lastCharacter) 98 { 99 if (text->style()->whiteSpace() == PRE) { 110 100 atCharacter += text->textLength(); 111 101 return; … … 115 105 unsigned textLength = text->textLength(); 116 106 for (unsigned textPosition = 0; textPosition < textLength; ++textPosition) { 117 const UChar & currentCharacter = characters[textPosition];118 if ( characterIsSpace(currentCharacter) && characterIsSpaceOrNull(lastCharacter))107 const UChar* currentCharacter = characters + textPosition; 108 if (*currentCharacter == ' ' && (!lastCharacter || *lastCharacter == ' ')) 119 109 continue; 120 110 … … 124 114 } 125 115 126 void SVGTextLayoutAttributesBuilder::collectTextPositioningElements(RenderObject* start, unsigned& atCharacter, UChar& lastCharacter)116 void SVGTextLayoutAttributesBuilder::collectTextPositioningElements(RenderObject* start, const UChar*& lastCharacter) 127 117 { 128 118 ASSERT(!start->isSVGText() || m_textPositions.isEmpty()); … … 130 120 for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) { 131 121 if (child->isSVGInlineText()) { 132 processRenderSVGInlineText(toRenderSVGInlineText(child), atCharacter, lastCharacter);122 processRenderSVGInlineText(toRenderSVGInlineText(child), m_textLength, lastCharacter); 133 123 continue; 134 124 } … … 140 130 unsigned atPosition = m_textPositions.size(); 141 131 if (element) 142 m_textPositions.append(TextPosition(element, atCharacter));143 144 collectTextPositioningElements(child, atCharacter,lastCharacter);132 m_textPositions.append(TextPosition(element, m_textLength)); 133 134 collectTextPositioningElements(child, lastCharacter); 145 135 146 136 if (!element) … … 150 140 TextPosition& position = m_textPositions[atPosition]; 151 141 ASSERT(!position.length); 152 position.length = atCharacter- position.start;153 } 154 } 155 156 void SVGTextLayoutAttributesBuilder::buildLayoutAttributes ForAllCharacters(RenderSVGText* textRoot, unsigned textLength)157 { 158 ASSERT( textLength);142 position.length = m_textLength - position.start; 143 } 144 } 145 146 void SVGTextLayoutAttributesBuilder::buildLayoutAttributes(RenderSVGText* textRoot) 147 { 148 ASSERT(m_textLength); 159 149 160 150 SVGTextPositioningElement* outermostTextElement = SVGTextPositioningElement::elementFromRenderer(textRoot); 161 151 ASSERT(outermostTextElement); 162 152 163 // Fill the lists with the special emptyValue marker. 164 m_positioningLists.fillWithEmptyValues(textLength); 165 166 // Grab outermost <text> element value lists and insert them in the m_positioningLists. 167 TextPosition wholeTextPosition(outermostTextElement, 0, textLength); 168 fillAttributesAtPosition(wholeTextPosition); 153 // Grab outermost <text> element value lists and insert them in the character data map. 154 TextPosition wholeTextPosition(outermostTextElement, 0, m_textLength); 155 fillCharacterDataMap(wholeTextPosition); 169 156 170 157 // Handle x/y default attributes. 171 float& xFirst = m_positioningLists.xValues.first(); 172 if (xFirst == SVGTextLayoutAttributes::emptyValue()) 173 xFirst = 0; 174 175 float& yFirst = m_positioningLists.yValues.first(); 176 if (yFirst == SVGTextLayoutAttributes::emptyValue()) 177 yFirst = 0; 178 179 // Fill m_positioningLists using child text positioning elements in top-down order. 158 SVGCharacterDataMap::iterator it = m_characterDataMap.find(1); 159 if (it == m_characterDataMap.end()) { 160 SVGCharacterData data; 161 data.x = 0; 162 data.y = 0; 163 m_characterDataMap.set(1, data); 164 } else { 165 SVGCharacterData& data = it->second; 166 if (data.x == SVGTextLayoutAttributes::emptyValue()) 167 data.x = 0; 168 if (data.y == SVGTextLayoutAttributes::emptyValue()) 169 data.y = 0; 170 } 171 172 // Fill character data map using child text positioning elements in top-down order. 180 173 unsigned size = m_textPositions.size(); 181 174 for (unsigned i = 0; i < size; ++i) 182 fillAttributesAtPosition(m_textPositions[i]); 183 184 // Now m_positioningLists.contains a x/y/dx/dy/rotate value for each character in the <text> subtree. 185 } 186 187 void SVGTextLayoutAttributesBuilder::propagateLayoutAttributes(RenderObject* start, Vector<SVGTextLayoutAttributes>& allAttributes, unsigned& atCharacter, UChar& lastCharacter) const 188 { 189 for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) { 190 if (child->isSVGInlineText()) { 191 RenderSVGInlineText* text = toRenderSVGInlineText(child); 192 const UChar* characters = text->characters(); 193 unsigned textLength = text->textLength(); 194 bool preserveWhiteSpace = shouldPreserveAllWhiteSpace(text->style()); 195 196 SVGTextLayoutAttributes attributes(text); 197 attributes.reserveCapacity(textLength); 198 199 unsigned valueListPosition = atCharacter; 200 unsigned metricsLength = 1; 201 SVGTextMetrics lastMetrics(SVGTextMetrics::SkippedSpaceMetrics); 202 203 for (unsigned textPosition = 0; textPosition < textLength; textPosition += metricsLength) { 204 const UChar& currentCharacter = characters[textPosition]; 205 206 SVGTextMetrics startToCurrentMetrics; 207 SVGTextMetrics currentMetrics; 208 unsigned valueListAdvance = 0; 209 210 if (U16_IS_LEAD(currentCharacter) && (textPosition + 1) < textLength && U16_IS_TRAIL(characters[textPosition + 1])) { 211 // Handle surrogate pairs. 212 startToCurrentMetrics = SVGTextMetrics::measureCharacterRange(text, 0, textPosition + 2); 213 currentMetrics = SVGTextMetrics::measureCharacterRange(text, textPosition, 2); 214 metricsLength = currentMetrics.length(); 215 valueListAdvance = 1; 216 } else { 217 // Handle BMP characters. 218 startToCurrentMetrics = SVGTextMetrics::measureCharacterRange(text, 0, textPosition + 1); 219 currentMetrics = SVGTextMetrics::measureCharacterRange(text, textPosition, 1); 220 metricsLength = currentMetrics.length(); 221 valueListAdvance = metricsLength; 222 } 223 224 if (!metricsLength) 225 break; 226 227 // Frequent case for Arabic text: when measuring a single character the arabic isolated form is taken 228 // when rendering the glyph "in context" (with it's surrounding characters) it changes due to shaping. 229 // So whenever runWidthAdvance != currentMetrics.width(), we are processing a text run whose length is 230 // not equal to the sum of the individual lengths of the glyphs, when measuring them isolated. 231 float runWidthAdvance = startToCurrentMetrics.width() - lastMetrics.width(); 232 if (runWidthAdvance != currentMetrics.width()) 233 currentMetrics.setWidth(runWidthAdvance); 234 235 lastMetrics = startToCurrentMetrics; 236 237 if (!preserveWhiteSpace && characterIsSpace(currentCharacter) && characterIsSpaceOrNull(lastCharacter)) { 238 attributes.positioningLists().appendEmptyValues(); 239 attributes.textMetricsValues().append(SVGTextMetrics(SVGTextMetrics::SkippedSpaceMetrics)); 240 continue; 241 } 242 243 SVGTextLayoutAttributes::PositioningLists& positioningLists = attributes.positioningLists(); 244 positioningLists.appendValuesFromPosition(m_positioningLists, valueListPosition); 245 attributes.textMetricsValues().append(currentMetrics); 246 247 // Pad x/y/dx/dy/rotate value lists with empty values, if the metrics span more than one character. 248 if (metricsLength > 1) { 249 for (unsigned i = 0; i < metricsLength - 1; ++i) 250 positioningLists.appendEmptyValues(); 251 } 252 253 lastCharacter = currentCharacter; 254 valueListPosition += valueListAdvance; 255 } 175 fillCharacterDataMap(m_textPositions[i]); 256 176 257 177 #if DUMP_TEXT_LAYOUT_ATTRIBUTES > 0 258 fprintf(stderr, "\nDumping layout attributes for RenderSVGInlineText, renderer=%p, node=%p (atCharacter: %i)\n", text, text->node(), atCharacter); 259 fprintf(stderr, "BiDi properties: unicode-bidi=%i, block direction=%i\n", text->style()->unicodeBidi(), text->style()->direction()); 260 attributes.dump(); 178 fprintf(stderr, "\nDumping ALL layout attributes for RenderSVGText, renderer=%p, node=%p (m_textLength: %i)\n", textRoot, textRoot->node(), m_textLength); 179 m_characterDataMap.dump(); 261 180 #endif 262 263 text->storeLayoutAttributes(attributes); 264 allAttributes.append(attributes); 265 atCharacter = valueListPosition; 181 } 182 183 static inline void updateCharacterData(unsigned i, float& lastRotation, SVGCharacterData& data, const SVGLengthContext& lengthContext, const SVGLengthList* xList, const SVGLengthList* yList, const SVGLengthList* dxList, const SVGLengthList* dyList, const SVGNumberList* rotateList) 184 { 185 if (xList) 186 data.x = xList->at(i).value(lengthContext); 187 if (yList) 188 data.y = yList->at(i).value(lengthContext); 189 if (dxList) 190 data.dx = dxList->at(i).value(lengthContext); 191 if (dyList) 192 data.dy = dyList->at(i).value(lengthContext); 193 if (rotateList) { 194 data.rotate = rotateList->at(i); 195 lastRotation = data.rotate; 196 } 197 } 198 199 void SVGTextLayoutAttributesBuilder::fillCharacterDataMap(const TextPosition& position) 200 { 201 const SVGLengthList& xList = position.element->x(); 202 const SVGLengthList& yList = position.element->y(); 203 const SVGLengthList& dxList = position.element->dx(); 204 const SVGLengthList& dyList = position.element->dy(); 205 const SVGNumberList& rotateList = position.element->rotate(); 206 207 unsigned xListSize = xList.size(); 208 unsigned yListSize = yList.size(); 209 unsigned dxListSize = dxList.size(); 210 unsigned dyListSize = dyList.size(); 211 unsigned rotateListSize = rotateList.size(); 212 if (!xListSize && !yListSize && !dxListSize && !dyListSize && !rotateListSize) 213 return; 214 215 float lastRotation = SVGTextLayoutAttributes::emptyValue(); 216 SVGLengthContext lengthContext(position.element); 217 for (unsigned i = 0; i < position.length; ++i) { 218 const SVGLengthList* xListPtr = i < xListSize ? &xList : 0; 219 const SVGLengthList* yListPtr = i < yListSize ? &yList : 0; 220 const SVGLengthList* dxListPtr = i < dxListSize ? &dxList : 0; 221 const SVGLengthList* dyListPtr = i < dyListSize ? &dyList : 0; 222 const SVGNumberList* rotateListPtr = i < rotateListSize ? &rotateList : 0; 223 if (!xListPtr && !yListPtr && !dxListPtr && !dyListPtr && !rotateListPtr) 224 break; 225 226 SVGCharacterDataMap::iterator it = m_characterDataMap.find(position.start + i + 1); 227 if (it == m_characterDataMap.end()) { 228 SVGCharacterData data; 229 updateCharacterData(i, lastRotation, data, lengthContext, xListPtr, yListPtr, dxListPtr, dyListPtr, rotateListPtr); 230 m_characterDataMap.set(position.start + i + 1, data); 266 231 continue; 267 232 } 268 233 269 if (!child->isSVGInline()) 270 continue; 271 272 propagateLayoutAttributes(child, allAttributes, atCharacter, lastCharacter); 273 } 274 } 275 276 static inline void fillListAtPosition(Vector<float>& allValues, Vector<float>& values, unsigned start) 277 { 278 unsigned valuesSize = values.size(); 279 for (unsigned i = 0; i < valuesSize; ++i) 280 allValues[start + i] = values[i]; 281 } 282 283 void SVGTextLayoutAttributesBuilder::fillAttributesAtPosition(const TextPosition& position) 284 { 285 Vector<float> values; 286 extractFloatValuesFromSVGLengthList(position.element, position.element->x(), values, position.length); 287 fillListAtPosition(m_positioningLists.xValues, values, position.start); 288 289 values.clear(); 290 extractFloatValuesFromSVGLengthList(position.element, position.element->y(), values, position.length); 291 fillListAtPosition(m_positioningLists.yValues, values, position.start); 292 293 values.clear(); 294 extractFloatValuesFromSVGLengthList(position.element, position.element->dx(), values, position.length); 295 fillListAtPosition(m_positioningLists.dxValues, values, position.start); 296 297 values.clear(); 298 extractFloatValuesFromSVGLengthList(position.element, position.element->dy(), values, position.length); 299 fillListAtPosition(m_positioningLists.dyValues, values, position.start); 300 301 values.clear(); 302 extractFloatValuesFromSVGNumberList(position.element->rotate(), values, position.length); 303 fillListAtPosition(m_positioningLists.rotateValues, values, position.start); 234 updateCharacterData(i, lastRotation, it->second, lengthContext, xListPtr, yListPtr, dxListPtr, dyListPtr, rotateListPtr); 235 } 304 236 305 237 // The last rotation value always spans the whole scope. 306 if (values.isEmpty()) 307 return; 308 309 float lastValue = values.last(); 310 for (unsigned i = values.size(); i < position.length; ++i) 311 m_positioningLists.rotateValues[position.start + i] = lastValue; 238 if (lastRotation == SVGTextLayoutAttributes::emptyValue()) 239 return; 240 241 for (unsigned i = rotateList.size(); i < position.length; ++i) { 242 SVGCharacterDataMap::iterator it = m_characterDataMap.find(position.start + i + 1); 243 if (it == m_characterDataMap.end()) { 244 SVGCharacterData data; 245 data.rotate = lastRotation; 246 m_characterDataMap.set(position.start + i + 1, data); 247 continue; 248 } 249 250 it->second.rotate = lastRotation; 251 } 312 252 } 313 253 -
trunk/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h
r95901 r105057 1 1 /* 2 * Copyright (C) Research In Motion Limited 2010-201 1. All rights reserved.2 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. 3 3 * 4 4 * This library is free software; you can redistribute it and/or … … 22 22 23 23 #if ENABLE(SVG) 24 #include "SVGText LayoutAttributes.h"24 #include "SVGTextMetricsBuilder.h" 25 25 #include <wtf/Vector.h> 26 26 … … 28 28 29 29 class RenderObject; 30 class RenderSVGInlineText; 30 31 class RenderSVGText; 31 32 class SVGTextPositioningElement; … … 33 34 // SVGTextLayoutAttributesBuilder performs the first layout phase for SVG text. 34 35 // 35 // It extracts the x/y/dx/dy/rotate values from the SVGTextPositioningElements in the DOM, 36 // measures all characters in the RenderSVGText subtree and extracts kerning/ligature information. 36 // It extracts the x/y/dx/dy/rotate values from the SVGTextPositioningElements in the DOM. 37 37 // These values are propagated to the corresponding RenderSVGInlineText renderers. 38 38 // The first layout phase only extracts the relevant information needed in RenderBlockLineLayout … … 44 44 public: 45 45 SVGTextLayoutAttributesBuilder(); 46 void buildLayoutAttributesForTextSubtree(RenderSVGText*); 46 void buildLayoutAttributesForWholeTree(RenderSVGText*); 47 void buildLayoutAttributesForTextRenderer(RenderSVGInlineText*); 48 49 void rebuildMetricsForWholeTree(RenderSVGText*); 50 void rebuildMetricsForTextRenderer(RenderSVGInlineText*); 51 52 // Invoked whenever the underlying DOM tree changes, so that m_textPositions is rebuild. 53 void clearTextPositioningElements() { m_textPositions.clear(); } 47 54 48 55 private: … … 60 67 }; 61 68 62 void collectTextPositioningElements(RenderObject*, unsigned& atCharacter, UChar& lastCharacter);63 void buildLayoutAttributesForAllCharacters(RenderSVGText*, unsigned textLength);64 void propagateLayoutAttributes(RenderObject*, Vector<SVGTextLayoutAttributes>& allAttributes, unsigned& atCharacter, UChar& lastCharacter) const;65 void fill AttributesAtPosition(const TextPosition&);69 bool buildLayoutAttributesIfNeeded(RenderSVGText*); 70 void collectTextPositioningElements(RenderObject*, const UChar*& lastCharacter); 71 void buildLayoutAttributes(RenderSVGText*); 72 void fillCharacterDataMap(const TextPosition&); 66 73 67 74 private: 75 unsigned m_textLength; 68 76 Vector<TextPosition> m_textPositions; 69 SVGTextLayoutAttributes::PositioningLists m_positioningLists; 77 SVGCharacterDataMap m_characterDataMap; 78 SVGTextMetricsBuilder m_metricsBuilder; 70 79 }; 71 80 -
trunk/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp
r104683 r105057 1 1 /* 2 * Copyright (C) Research In Motion Limited 2010 . All rights reserved.2 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. 3 3 * 4 4 * This library is free software; you can redistribute it and/or … … 85 85 } 86 86 87 void SVGTextLayoutEngine::updateRelativePositionAdjustmentsIfNeeded( Vector<float>& dxValues, Vector<float>& dyValues)87 void SVGTextLayoutEngine::updateRelativePositionAdjustmentsIfNeeded(float dx, float dy) 88 88 { 89 89 // Update relative positioning information. 90 if (dx Values.isEmpty() && dyValues.isEmpty())90 if (dx == SVGTextLayoutAttributes::emptyValue() && dy == SVGTextLayoutAttributes::emptyValue()) 91 91 return; 92 92 93 float dx = 0; 94 if (!dxValues.isEmpty()) { 95 float& dxCurrent = dxValues.at(m_logicalCharacterOffset); 96 if (dxCurrent != SVGTextLayoutAttributes::emptyValue()) 97 dx = dxCurrent; 98 } 99 100 float dy = 0; 101 if (!dyValues.isEmpty()) { 102 float& dyCurrent = dyValues.at(m_logicalCharacterOffset); 103 if (dyCurrent != SVGTextLayoutAttributes::emptyValue()) 104 dy = dyCurrent; 105 } 93 if (dx == SVGTextLayoutAttributes::emptyValue()) 94 dx = 0; 95 if (dy == SVGTextLayoutAttributes::emptyValue()) 96 dy = 0; 106 97 107 98 if (m_inPathLayout) { … … 345 336 346 337 logicalAttributes = m_layoutAttributes.first(); 347 if (m_logicalCharacterOffset != logicalAttributes. xValues().size())338 if (m_logicalCharacterOffset != logicalAttributes.context()->textLength()) 348 339 return true; 349 340 … … 473 464 } 474 465 475 SVGTextLayoutAttributes logicalAttributes ;466 SVGTextLayoutAttributes logicalAttributes(0); 476 467 if (!currentLogicalCharacterAttributes(logicalAttributes)) 477 468 break; … … 481 472 break; 482 473 483 Vector<float>& xValues = logicalAttributes.xValues();484 Vector<float>& yValues = logicalAttributes.yValues();485 Vector<float>& dxValues = logicalAttributes.dxValues();486 Vector<float>& dyValues = logicalAttributes.dyValues();487 Vector<float>& rotateValues = logicalAttributes.rotateValues();488 489 float x = xValues.at(m_logicalCharacterOffset);490 float y = yValues.at(m_logicalCharacterOffset);474 SVGCharacterDataMap& characterDataMap = logicalAttributes.characterDataMap(); 475 SVGCharacterData data; 476 SVGCharacterDataMap::iterator it = characterDataMap.find(m_logicalCharacterOffset + 1); 477 if (it != characterDataMap.end()) 478 data = it->second; 479 480 float x = data.x; 481 float y = data.y; 491 482 492 483 // When we've advanced to the box start offset, determine using the original x/y values, … … 495 486 textBox->setStartsNewTextChunk(logicalAttributes.context()->characterStartsNewTextChunk(m_logicalCharacterOffset)); 496 487 497 float angle = 0; 498 if (!rotateValues.isEmpty()) { 499 float newAngle = rotateValues.at(m_logicalCharacterOffset); 500 if (newAngle != SVGTextLayoutAttributes::emptyValue()) 501 angle = newAngle; 502 } 488 float angle = data.rotate == SVGTextLayoutAttributes::emptyValue() ? 0 : data.rotate; 503 489 504 490 // Calculate glyph orientation angle. … … 515 501 516 502 // Apply dx/dy value adjustments to current text position, if needed. 517 updateRelativePositionAdjustmentsIfNeeded(d xValues, dyValues);503 updateRelativePositionAdjustmentsIfNeeded(data.dx, data.dy); 518 504 519 505 // Calculate SVG Fonts kerning, if needed. -
trunk/Source/WebCore/rendering/svg/SVGTextLayoutEngine.h
r95901 r105057 1 1 /* 2 * Copyright (C) Research In Motion Limited 2010 . All rights reserved.2 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. 3 3 * 4 4 * This library is free software; you can redistribute it and/or … … 58 58 void finishLayout(); 59 59 60 Vector<SVGTextLayoutAttributes>& layoutAttributes() { return m_layoutAttributes; } 61 60 62 private: 61 63 void updateCharacerPositionIfNeeded(float& x, float& y); 62 64 void updateCurrentTextPosition(float x, float y, float glyphAdvance); 63 void updateRelativePositionAdjustmentsIfNeeded( Vector<float>& dxValues, Vector<float>& dyValues);65 void updateRelativePositionAdjustmentsIfNeeded(float dx, float dy); 64 66 65 67 void recordTextFragment(SVGInlineTextBox*, Vector<SVGTextMetrics>& textMetricValues); -
trunk/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp
r104926 r105057 26 26 #include "RenderSVGText.h" 27 27 #include "SVGTextRunRenderingContext.h" 28 #include "WidthIterator.h"29 28 30 29 namespace WebCore { … … 53 52 advanceComplexText(); 54 53 #else 54 // FIXME: Enabling the simple code path, affects some layout test results, so this will be landed seperated. 55 m_isComplexText = true; 55 56 if (m_isComplexText) 56 57 advanceComplexText(); … … 92 93 m_currentMetrics = SVGTextMetrics::measureCharacterRange(m_text, m_textPosition, metricsLength); 93 94 m_complexStartToCurrentMetrics = SVGTextMetrics::measureCharacterRange(m_text, 0, m_textPosition + metricsLength); 94 ASSERT(m_currentMetrics.length() == metricsLength); 95 96 // FIXME: Re-enable this assertion, once SVG Fonts stop using this code path. 97 // ASSERT(m_currentMetrics.length() == metricsLength); 95 98 96 99 // Frequent case for Arabic text: when measuring a single character the arabic isolated form is taken … … 171 174 if (data->allCharactersMap) { 172 175 const SVGCharacterDataMap::const_iterator it = data->allCharactersMap->find(data->valueListPosition + m_textPosition - data->skippedCharacters + 1); 173 if (it != data->allCharactersMap->end()) { 174 // FIXME: Yes this is nonsense for now. This will use attributes->characterDataMap(), as soon as its available, in a follow-up commit. 175 SVGCharacterDataMap map; 176 map.set(m_textPosition + 1, it->second); 177 } 176 if (it != data->allCharactersMap->end()) 177 attributes->characterDataMap().set(m_textPosition + 1, it->second); 178 178 } 179 179 textMetricsValues->append(m_currentMetrics); -
trunk/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.h
r104926 r105057 25 25 #include "SVGTextMetrics.h" 26 26 #include "TextRun.h" 27 #include "WidthIterator.h" 27 28 #include <wtf/Vector.h> 28 29 … … 33 34 class RenderSVGText; 34 35 struct MeasureTextData; 35 struct WidthIterator;36 36 37 37 class SVGTextMetricsBuilder { -
trunk/Source/WebCore/rendering/svg/SVGTextQuery.cpp
r95901 r105057 1 1 /* 2 * Copyright (C) Research In Motion Limited 2010 . All rights reserved.2 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. 3 3 * 4 4 * This library is free software; you can redistribute it and/or … … 159 159 void SVGTextQuery::modifyStartEndPositionsRespectingLigatures(Data* queryData, int& startPosition, int& endPosition) const 160 160 { 161 const SVGTextLayoutAttributes& layoutAttributes = queryData->textRenderer->layoutAttributes(); 162 const Vector<float>& xValues = layoutAttributes.xValues(); 163 const Vector<SVGTextMetrics>& textMetricsValues = layoutAttributes.textMetricsValues(); 164 161 SVGTextLayoutAttributes& layoutAttributes = queryData->textRenderer->layoutAttributes(); 162 Vector<SVGTextMetrics>& textMetricsValues = layoutAttributes.textMetricsValues(); 165 163 unsigned boxStart = queryData->textBox->start(); 166 164 unsigned boxLength = queryData->textBox->len(); … … 170 168 171 169 unsigned positionOffset = 0; 172 unsigned positionSize = xValues.size();170 unsigned positionSize = layoutAttributes.context()->textLength(); 173 171 174 172 bool alterStartPosition = true; … … 177 175 int lastPositionOffset = -1; 178 176 for (; textMetricsOffset < textMetricsSize && positionOffset < positionSize; ++textMetricsOffset) { 179 const SVGTextMetrics& metrics = textMetricsValues.at(textMetricsOffset);177 SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset]; 180 178 181 179 // Advance to text box start location.
Note: See TracChangeset
for help on using the changeset viewer.