Changeset 82411 in webkit
- Timestamp:
- Mar 30, 2011 1:36:42 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r82410 r82411 1 2011-03-29 Nikolas Zimmermann <nzimmermann@rim.com> 2 3 Reviewed by Eric Seidel. 4 5 REGRESSION (r68976): Incorrect bidi rendering in SVG text 6 https://bugs.webkit.org/show_bug.cgi?id=53980 7 8 Add testcase from bug 53980, assuring that BiDi works as well, when using the Unicode directional formatting characters. 9 10 * platform/mac/svg/text/bidi-embedded-direction-expected.checksum: Added. 11 * platform/mac/svg/text/bidi-embedded-direction-expected.png: Added. 12 * platform/mac/svg/text/bidi-embedded-direction-expected.txt: Added. 13 * platform/mac/svg/text/bidi-reorder-value-lists-expected.checksum: 14 * platform/mac/svg/text/bidi-reorder-value-lists-expected.png: 15 * platform/mac/svg/text/bidi-reorder-value-lists-expected.txt: 16 * platform/mac/svg/text/font-size-below-point-five-expected.txt: Update result, as text runs aren't created anymore for empty text. 17 * svg/text/bidi-embedded-direction.svg: Added. 18 * svg/text/bidi-reorder-value-lists.svg: Extend testcase, to cover more reordering cases. 19 1 20 2011-03-30 Yuta Kitamura <yutak@chromium.org> 2 21 -
trunk/LayoutTests/platform/mac/svg/text/bidi-reorder-value-lists-expected.checksum
r81168 r82411 1 b5700b4960426f2c6994d4d54f163f7f 1 dcef2f4c8ed6fdd9483bd4070cf5864b -
trunk/LayoutTests/platform/mac/svg/text/bidi-reorder-value-lists-expected.txt
r81168 r82411 2 2 RenderView at (0,0) size 800x600 3 3 layer at (0,0) size 400x400 4 RenderSVGRoot {svg} at ( 40,60) size 360x1965 RenderSVGContainer {g} at ( 40,60) size 360x196 [transform={m=((4.00,0.00)(0.00,4.00)) t=(0.00,0.00)}]6 RenderSVGText {text} at (10, 15) size 90x19 contains 1 chunk(s)4 RenderSVGRoot {svg} at (30,15) size 270x237 5 RenderSVGContainer {g} at (30,15) size 270x237 [transform={m=((3.00,0.00)(0.00,3.00)) t=(0.00,0.00)}] 6 RenderSVGText {text} at (10,5) size 90x19 contains 1 chunk(s) 7 7 RenderSVGInlineText {#text} at (0,0) size 90x19 8 chunk 1 text run 1 at (10.00,30.00) startOffset 0 endOffset 1 width 9.75: "T" 9 chunk 1 text run 1 at (20.00,30.00) startOffset 0 endOffset 1 width 7.00: "e" 10 chunk 1 text run 1 at (30.00,30.00) startOffset 0 endOffset 1 width 6.25: "s" 11 chunk 1 text run 1 at (40.00,30.00) startOffset 0 endOffset 1 width 4.50: "t" 12 chunk 1 text run 1 at (50.00,30.00) startOffset 0 endOffset 1 width 4.00: " " 13 chunk 1 text run 1 at (54.00,30.00) startOffset 0 endOffset 5 width 45.57 RTL: "\x{5D0}\x{5D1}\x{5D2}\x{5D3}\x{5D4}" 8 chunk 1 text run 1 at (10.00,20.00) startOffset 0 endOffset 1 width 9.67: "T" 9 chunk 1 text run 1 at (20.00,20.00) startOffset 0 endOffset 1 width 7.00: "e" 10 chunk 1 text run 1 at (30.00,20.00) startOffset 0 endOffset 1 width 6.33: "s" 11 chunk 1 text run 1 at (40.00,20.00) startOffset 0 endOffset 1 width 4.33: "t" 12 chunk 1 text run 1 at (50.00,20.00) startOffset 0 endOffset 1 width 4.00: " " 13 chunk 1 text run 1 at (54.00,20.00) startOffset 0 endOffset 5 width 45.57 RTL: "\x{5D0}\x{5D1}\x{5D2}\x{5D3}\x{5D4}" 14 RenderSVGText {text} at (10,25) size 89x19 contains 1 chunk(s) 15 RenderSVGTSpan {tspan} at (0,0) size 89x19 16 RenderSVGInlineText {#text} at (0,0) size 89x19 17 chunk 1 text run 1 at (10.00,40.00) startOffset 0 endOffset 1 width 9.67: "T" 18 chunk 1 text run 1 at (20.00,40.00) startOffset 0 endOffset 1 width 7.00: "e" 19 chunk 1 text run 1 at (30.00,40.00) startOffset 0 endOffset 1 width 6.33: "s" 20 chunk 1 text run 1 at (40.00,40.00) startOffset 0 endOffset 1 width 4.33: "t" 21 chunk 1 text run 1 at (50.00,40.00) startOffset 0 endOffset 1 width 4.00: " " 22 chunk 1 text run 1 at (55.00,40.00) startOffset 0 endOffset 1 width 11.39 RTL: "\x{5D4}" 23 chunk 1 text run 1 at (64.00,40.00) startOffset 0 endOffset 1 width 8.02 RTL: "\x{5D3}" 24 chunk 1 text run 1 at (72.00,40.00) startOffset 0 endOffset 1 width 6.84 RTL: "\x{5D2}" 25 chunk 1 text run 1 at (79.00,40.00) startOffset 0 endOffset 1 width 9.01 RTL: "\x{5D1}" 26 chunk 1 text run 1 at (88.00,40.00) startOffset 0 endOffset 1 width 10.32 RTL: "\x{5D0}" 14 27 RenderSVGText {text} at (10,45) size 89x19 contains 1 chunk(s) 28 RenderSVGInlineText {#text} at (0,0) size 44x19 29 chunk 1 text run 1 at (10.00,60.00) startOffset 0 endOffset 1 width 9.67: "T" 30 chunk 1 text run 1 at (20.00,60.00) startOffset 0 endOffset 1 width 7.00: "e" 31 chunk 1 text run 1 at (30.00,60.00) startOffset 0 endOffset 1 width 6.33: "s" 32 chunk 1 text run 1 at (40.00,60.00) startOffset 0 endOffset 1 width 4.33: "t" 33 chunk 1 text run 1 at (50.00,60.00) startOffset 0 endOffset 1 width 4.00: " " 34 RenderSVGTSpan {tspan} at (0,0) size 44x19 35 RenderSVGInlineText {#text} at (45,0) size 44x19 36 chunk 1 text run 1 at (55.00,60.00) startOffset 0 endOffset 1 width 11.39 RTL: "\x{5D4}" 37 chunk 1 text run 1 at (64.00,60.00) startOffset 0 endOffset 1 width 8.02 RTL: "\x{5D3}" 38 chunk 1 text run 1 at (72.00,60.00) startOffset 0 endOffset 1 width 6.84 RTL: "\x{5D2}" 39 chunk 1 text run 1 at (79.00,60.00) startOffset 0 endOffset 1 width 9.01 RTL: "\x{5D1}" 40 chunk 1 text run 1 at (88.00,60.00) startOffset 0 endOffset 1 width 10.32 RTL: "\x{5D0}" 41 RenderSVGText {text} at (10,65) size 89x19 contains 1 chunk(s) 15 42 RenderSVGInlineText {#text} at (0,0) size 89x19 16 chunk 1 text run 1 at (10.00, 60.00) startOffset 0 endOffset 1 width 9.75: "T"17 chunk 1 text run 1 at (20.00, 60.00) startOffset 0 endOffset 1 width 7.00: "e"18 chunk 1 text run 1 at (30.00, 60.00) startOffset 0 endOffset 1 width 6.25: "s"19 chunk 1 text run 1 at (40.00, 60.00) startOffset 0 endOffset 1 width 4.50: "t"20 chunk 1 text run 1 at (50.00, 60.00) startOffset 0 endOffset 1 width 4.00: " "21 chunk 1 text run 1 at (55.00, 60.00) startOffset 0 endOffset 1 width 11.39 RTL: "\x{5D4}"22 chunk 1 text run 1 at (64.00, 60.00) startOffset 0 endOffset 1 width 8.02 RTL: "\x{5D3}"23 chunk 1 text run 1 at (72.00, 60.00) startOffset 0 endOffset 1 width 6.84 RTL: "\x{5D2}"24 chunk 1 text run 1 at (79.00, 60.00) startOffset 0 endOffset 1 width 9.01 RTL: "\x{5D1}"25 chunk 1 text run 1 at (88.00, 60.00) startOffset 0 endOffset 1 width 10.32 RTL: "\x{5D0}"43 chunk 1 text run 1 at (10.00,80.00) startOffset 0 endOffset 1 width 9.67: "T" 44 chunk 1 text run 1 at (20.00,80.00) startOffset 0 endOffset 1 width 7.00: "e" 45 chunk 1 text run 1 at (30.00,80.00) startOffset 0 endOffset 1 width 6.33: "s" 46 chunk 1 text run 1 at (40.00,80.00) startOffset 0 endOffset 1 width 4.33: "t" 47 chunk 1 text run 1 at (50.00,80.00) startOffset 0 endOffset 1 width 4.00: " " 48 chunk 1 text run 1 at (55.00,80.00) startOffset 0 endOffset 1 width 11.39 RTL: "\x{5D4}" 49 chunk 1 text run 1 at (64.00,80.00) startOffset 0 endOffset 1 width 8.02 RTL: "\x{5D3}" 50 chunk 1 text run 1 at (72.00,80.00) startOffset 0 endOffset 1 width 6.84 RTL: "\x{5D2}" 51 chunk 1 text run 1 at (79.00,80.00) startOffset 0 endOffset 1 width 9.01 RTL: "\x{5D1}" 52 chunk 1 text run 1 at (88.00,80.00) startOffset 0 endOffset 1 width 10.32 RTL: "\x{5D0}" -
trunk/LayoutTests/platform/mac/svg/text/font-size-below-point-five-expected.txt
r77554 r82411 31 31 RenderSVGTSpan {tspan} at (0,0) size 0x0 32 32 RenderSVGInlineText {#text} at (-10,5) size 0x0 33 chunk 1 text run 1 at (39.53,10.00) startOffset 0 endOffset 1 width 0.00: "6"34 33 RenderSVGInlineText {#text} at (0,0) size 0x0 35 34 RenderSVGText {text} at (63,42) size 124x11 contains 1 chunk(s) -
trunk/LayoutTests/svg/text/bidi-reorder-value-lists.svg
r81168 r82411 1 1 <svg width="400" height="400" xmlns="http://www.w3.org/2000/svg"> 2 <g font-size="16" transform="scale( 4,4)">2 <g font-size="16" transform="scale(3,3)"> 3 3 <!-- The order of all characters in both lines should be the same, the spacing is different due the absolute positioning in the second line --> 4 <text x="10 20 30 40 50" y="30">Test אבגדה</text>4 <text y="20" x="10 20 30 40 50">Test אבגדה</text> 5 5 6 6 <!-- … … 22 22 The Hebrew string is reordered, and the x/y/dx/dy/rotate lists as well to maintain correspondence. 23 23 --> 24 <text x="10 20 30 40 50 88 79 72 64 55" y="60">Test אבגדה</text> 24 <text y="40"><tspan x="10 20 30 40 50 88 79 72 64 55">Test אבגדה</tspan></text> 25 26 <text y="60" x="10 20 30 40 50">Test <tspan x="88 79 72 64 55">אבגדה</tspan></text> 27 28 <text y="80" x="10 20 30 40 50 88 79 72 64 55">Test אבגדה</text> 25 29 </g> 26 30 </svg> -
trunk/Source/WebCore/ChangeLog
r82403 r82411 1 2011-03-29 Nikolas Zimmermann <nzimmermann@rim.com> 2 3 Reviewed by Eric Seidel. 4 5 REGRESSION (r68976): Incorrect bidi rendering in SVG text 6 https://bugs.webkit.org/show_bug.cgi?id=53980 7 8 Deconvolute SVGTextLayoutEngine code, which was confusing due to the simultaneous processing of the rendered text 9 in visual and logical order. Added several helper methods to make the code more readable. 10 11 Fix Unicode directional formatting characters support, now works as expected. 12 13 Test: svg/text/bidi-embedded-direction.svg 14 15 * editing/visible_units.cpp: Refactor getLeafBoxesInLogicalOrder(), move to InlineFlowBox. 16 (WebCore::getLogicalStartBoxAndNode): Use new collectLeafBoxesInLogicalOrder() method in InlineFlowBox. 17 (WebCore::getLogicalEndBoxAndNode): Ditto. 18 * rendering/InlineFlowBox.cpp: Add new helper function, that returns a list of all leaf boxes in logical order. 19 (WebCore::InlineFlowBox::collectLeafBoxesInLogicalOrder): 20 * rendering/InlineFlowBox.h: 21 * rendering/svg/RenderSVGText.cpp: Actually trigger reordering the x/y/dx/dy/rotate value lists, if needed. 22 (WebCore::RenderSVGText::RenderSVGText): 23 (WebCore::RenderSVGText::layout): 24 * rendering/svg/RenderSVGText.h: Ditto. 25 (WebCore::RenderSVGText::layoutAttributes): 26 (WebCore::RenderSVGText::needsReordering): 27 * rendering/svg/SVGRootInlineBox.cpp: Use new InlineFlowBox::collectLeafBoxesINLogicalOrder(), with a custom "inline box reverse" implementation, 28 which not only reverses the order of InlineBoxes, but also the order of the x/y/dx/dy/rotate value lists, if needed. 29 (WebCore::SVGRootInlineBox::computePerCharacterLayoutInformation): 30 (WebCore::SVGRootInlineBox::layoutCharactersInTextBoxes): 31 (WebCore::swapItems): 32 (WebCore::reverseInlineBoxRangeAndValueListsIfNeeded): 33 (WebCore::SVGRootInlineBox::reorderValueLists): 34 * rendering/svg/SVGRootInlineBox.h: 35 * rendering/svg/SVGTextLayoutAttributes.cpp: Store RenderSVGInlineText* pointer, where we belong to. 36 (WebCore::SVGTextLayoutAttributes::SVGTextLayoutAttributes): 37 (WebCore::SVGTextLayoutAttributes::dump): 38 * rendering/svg/SVGTextLayoutAttributes.h: 39 (WebCore::SVGTextLayoutAttributes::context): 40 * rendering/svg/SVGTextLayoutAttributesBuilder.cpp: Pass RenderSVGInlineText* object when creating SVGTextLayoutAttributes. 41 (WebCore::SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextSubtree): 42 (WebCore::SVGTextLayoutAttributesBuilder::propagateLayoutAttributes): 43 * rendering/svg/SVGTextLayoutAttributesBuilder.h: 44 * rendering/svg/SVGTextLayoutEngine.cpp: Rewrite & cleanup the main layout algorithm, to be less confusing. 45 (WebCore::SVGTextLayoutEngine::SVGTextLayoutEngine): 46 (WebCore::SVGTextLayoutEngine::updateRelativePositionAdjustmentsIfNeeded): 47 (WebCore::SVGTextLayoutEngine::recordTextFragment): 48 (WebCore::SVGTextLayoutEngine::currentLogicalCharacterAttributes): 49 (WebCore::SVGTextLayoutEngine::currentLogicalCharacterMetrics): 50 (WebCore::SVGTextLayoutEngine::currentVisualCharacterMetrics): 51 (WebCore::SVGTextLayoutEngine::advanceToNextLogicalCharacter): 52 (WebCore::SVGTextLayoutEngine::advanceToNextVisualCharacter): 53 (WebCore::SVGTextLayoutEngine::layoutTextOnLineOrPath): 54 * rendering/svg/SVGTextLayoutEngine.h: 55 1 56 2011-03-30 Ilya Tikhonovsky <loislo@chromium.org> 2 57 -
trunk/Source/WebCore/editing/visible_units.cpp
r81965 r82411 1042 1042 } 1043 1043 1044 static void getLeafBoxesInLogicalOrder(RootInlineBox* rootBox, Vector<InlineBox*>& leafBoxesInLogicalOrder)1045 {1046 unsigned char minLevel = 128;1047 unsigned char maxLevel = 0;1048 unsigned count = 0;1049 InlineBox* r = rootBox->firstLeafChild();1050 // First find highest and lowest levels,1051 // and initialize leafBoxesInLogicalOrder with the leaf boxes in visual order.1052 while (r) {1053 if (r->bidiLevel() > maxLevel)1054 maxLevel = r->bidiLevel();1055 if (r->bidiLevel() < minLevel)1056 minLevel = r->bidiLevel();1057 leafBoxesInLogicalOrder.append(r);1058 r = r->nextLeafChild();1059 ++count;1060 }1061 1062 if (rootBox->renderer()->style()->visuallyOrdered())1063 return;1064 // Reverse of reordering of the line (L2 according to Bidi spec):1065 // L2. From the highest level found in the text to the lowest odd level on each line,1066 // reverse any contiguous sequence of characters that are at that level or higher.1067 1068 // Reversing the reordering of the line is only done up to the lowest odd level.1069 if (!(minLevel % 2))1070 minLevel++;1071 1072 InlineBox** end = leafBoxesInLogicalOrder.end();1073 while (minLevel <= maxLevel) {1074 InlineBox** iter = leafBoxesInLogicalOrder.begin();1075 while (iter != end) {1076 while (iter != end) {1077 if ((*iter)->bidiLevel() >= minLevel)1078 break;1079 ++iter;1080 }1081 InlineBox** first = iter;1082 while (iter != end) {1083 if ((*iter)->bidiLevel() < minLevel)1084 break;1085 ++iter;1086 }1087 InlineBox** last = iter;1088 std::reverse(first, last);1089 }1090 ++minLevel;1091 }1092 }1093 1094 1044 static void getLogicalStartBoxAndNode(RootInlineBox* rootBox, InlineBox*& startBox, Node*& startNode) 1095 1045 { 1096 1046 Vector<InlineBox*> leafBoxesInLogicalOrder; 1097 getLeafBoxesInLogicalOrder(rootBox,leafBoxesInLogicalOrder);1047 rootBox->collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder); 1098 1048 startBox = 0; 1099 1049 startNode = 0; … … 1109 1059 { 1110 1060 Vector<InlineBox*> leafBoxesInLogicalOrder; 1111 getLeafBoxesInLogicalOrder(rootBox,leafBoxesInLogicalOrder);1061 rootBox->collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder); 1112 1062 endBox = 0; 1113 1063 endNode = 0; -
trunk/Source/WebCore/rendering/InlineFlowBox.cpp
r82280 r82411 1335 1335 } 1336 1336 1337 void InlineFlowBox::collectLeafBoxesInLogicalOrder(Vector<InlineBox*>& leafBoxesInLogicalOrder, CustomInlineBoxRangeReverse customReverseImplementation, void* userData) const 1338 { 1339 InlineBox* leaf = firstLeafChild(); 1340 1341 // FIXME: The reordering code is a copy of parts from BidiResolver::createBidiRunsForLine, operating directly on InlineBoxes, instead of BidiRuns. 1342 // Investigate on how this code could possibly be shared. 1343 unsigned char minLevel = 128; 1344 unsigned char maxLevel = 0; 1345 1346 // First find highest and lowest levels, and initialize leafBoxesInLogicalOrder with the leaf boxes in visual order. 1347 for (; leaf; leaf = leaf->nextLeafChild()) { 1348 minLevel = min(minLevel, leaf->bidiLevel()); 1349 maxLevel = max(maxLevel, leaf->bidiLevel()); 1350 leafBoxesInLogicalOrder.append(leaf); 1351 } 1352 1353 if (renderer()->style()->visuallyOrdered()) 1354 return; 1355 1356 // Reverse of reordering of the line (L2 according to Bidi spec): 1357 // L2. From the highest level found in the text to the lowest odd level on each line, 1358 // reverse any contiguous sequence of characters that are at that level or higher. 1359 1360 // Reversing the reordering of the line is only done up to the lowest odd level. 1361 if (!(minLevel % 2)) 1362 ++minLevel; 1363 1364 Vector<InlineBox*>::iterator end = leafBoxesInLogicalOrder.end(); 1365 while (minLevel <= maxLevel) { 1366 Vector<InlineBox*>::iterator it = leafBoxesInLogicalOrder.begin(); 1367 while (it != end) { 1368 while (it != end) { 1369 if ((*it)->bidiLevel() >= minLevel) 1370 break; 1371 ++it; 1372 } 1373 Vector<InlineBox*>::iterator first = it; 1374 while (it != end) { 1375 if ((*it)->bidiLevel() < minLevel) 1376 break; 1377 ++it; 1378 } 1379 Vector<InlineBox*>::iterator last = it; 1380 if (customReverseImplementation) { 1381 ASSERT(userData); 1382 (*customReverseImplementation)(userData, first, last); 1383 } else 1384 std::reverse(first, last); 1385 } 1386 ++minLevel; 1387 } 1388 } 1389 1337 1390 #ifndef NDEBUG 1338 1391 -
trunk/Source/WebCore/rendering/InlineFlowBox.h
r82280 r82411 76 76 InlineBox* firstLeafChild() const; 77 77 InlineBox* lastLeafChild() const; 78 79 typedef void (*CustomInlineBoxRangeReverse)(void* userData, Vector<InlineBox*>::iterator first, Vector<InlineBox*>::iterator last); 80 void collectLeafBoxesInLogicalOrder(Vector<InlineBox*>&, CustomInlineBoxRangeReverse customReverseImplementation = 0, void* userData = 0) const; 78 81 79 82 virtual void setConstructed() -
trunk/Source/WebCore/rendering/svg/RenderSVGText.cpp
r81992 r82411 52 52 RenderSVGText::RenderSVGText(SVGTextElement* node) 53 53 : RenderSVGBlock(node) 54 , m_needsReordering(false) 54 55 , m_needsPositioningValuesUpdate(true) 55 56 , m_needsTransformUpdate(true) … … 128 129 SVGTextLayoutAttributesBuilder layoutAttributesBuilder; 129 130 layoutAttributesBuilder.buildLayoutAttributesForTextSubtree(this); 131 m_needsReordering = true; 130 132 m_needsPositioningValuesUpdate = false; 131 133 updateCachedBoundariesInParents = true; … … 151 153 forceLayoutInlineChildren(); 152 154 155 if (m_needsReordering) 156 m_needsReordering = false; 157 153 158 if (!updateCachedBoundariesInParents) 154 159 updateCachedBoundariesInParents = oldBoundaries != objectBoundingBox(); -
trunk/Source/WebCore/rendering/svg/RenderSVGText.h
r75325 r82411 27 27 #include "AffineTransform.h" 28 28 #include "RenderSVGBlock.h" 29 #include "SVGTextLayoutAttributes.h" 29 30 30 31 namespace WebCore { … … 34 35 class RenderSVGText : public RenderSVGBlock { 35 36 public: 36 RenderSVGText(SVGTextElement* node);37 RenderSVGText(SVGTextElement*); 37 38 38 39 void setNeedsPositioningValuesUpdate() { m_needsPositioningValuesUpdate = true; } … … 42 43 static RenderSVGText* locateRenderSVGTextAncestor(RenderObject*); 43 44 static const RenderSVGText* locateRenderSVGTextAncestor(const RenderObject*); 45 46 Vector<SVGTextLayoutAttributes>& layoutAttributes() { return m_layoutAttributes; } 47 bool needsReordering() const { return m_needsReordering; } 44 48 45 49 private: … … 72 76 virtual void updateFirstLetter(); 73 77 78 bool m_needsReordering : 1; 74 79 bool m_needsPositioningValuesUpdate : 1; 75 80 bool m_needsTransformUpdate : 1; 76 81 AffineTransform m_localTransform; 82 Vector<SVGTextLayoutAttributes> m_layoutAttributes; 77 83 }; 78 84 -
trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp
r81168 r82411 26 26 #if ENABLE(SVG) 27 27 #include "GraphicsContext.h" 28 #include "RenderBlock.h"29 28 #include "RenderSVGInlineText.h" 29 #include "RenderSVGText.h" 30 30 #include "SVGInlineFlowBox.h" 31 31 #include "SVGInlineTextBox.h" … … 74 74 void SVGRootInlineBox::computePerCharacterLayoutInformation() 75 75 { 76 Render Block* parentBlock = block();76 RenderSVGText* parentBlock = toRenderSVGText(block()); 77 77 ASSERT(parentBlock); 78 78 79 // Build list of all text boxes which belong to our root renderer, in logical order, 80 // aka. the order of the characters as they appear in the original document. 81 // This is needed to maintain correspondence between the x/y/dx/dy/rotate value 82 // lists and the potentially reordered characters in the inline box tree. 83 Vector<SVGInlineTextBox*> boxesInLogicalOrder; 84 buildTextBoxListInLogicalOrder(parentBlock, boxesInLogicalOrder); 79 Vector<SVGTextLayoutAttributes>& attributes = parentBlock->layoutAttributes(); 80 if (parentBlock->needsReordering()) 81 reorderValueLists(attributes); 85 82 86 83 // Perform SVG text layout phase two (see SVGTextLayoutEngine for details). 87 SVGTextLayoutEngine characterLayout( boxesInLogicalOrder);84 SVGTextLayoutEngine characterLayout(attributes); 88 85 layoutCharactersInTextBoxes(this, characterLayout); 89 86 … … 95 92 layoutChildBoxes(this); 96 93 layoutRootBox(); 97 }98 99 void SVGRootInlineBox::buildTextBoxListInLogicalOrder(RenderObject* start, Vector<SVGInlineTextBox*>& boxes)100 {101 bool ltr = start->style()->isLeftToRightDirection();102 for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {103 if (child->isSVGInline()) {104 buildTextBoxListInLogicalOrder(child, boxes);105 continue;106 }107 108 if (!child->isSVGInlineText())109 continue;110 111 RenderSVGInlineText* text = toRenderSVGInlineText(child);112 for (InlineTextBox* textBox = ltr ? text->firstTextBox() : text->lastTextBox(); textBox; textBox = ltr ? textBox->nextTextBox() : textBox->prevTextBox()) {113 if (!textBox->isSVGInlineTextBox())114 continue;115 boxes.append(static_cast<SVGInlineTextBox*>(textBox));116 }117 }118 94 } 119 95 … … 140 116 // Build text chunks for all <textPath> children, using the line layout algorithm. 141 117 // This is needeed as text-anchor is just an additional startOffset for text paths. 142 Vector<SVGInlineTextBox*> boxesInLogicalOrder;143 buildTextBoxListInLogicalOrder(flowBox->renderer(), boxesInLogicalOrder);144 145 SVGTextLayoutEngine lineLayout( boxesInLogicalOrder);118 RenderSVGText* parentBlock = toRenderSVGText(block()); 119 ASSERT(parentBlock); 120 121 SVGTextLayoutEngine lineLayout(parentBlock->layoutAttributes()); 146 122 layoutCharactersInTextBoxes(flowBox, lineLayout); 147 123 … … 251 227 return closestLeaf ? closestLeaf : lastLeaf; 252 228 } 229 230 static inline void swapItemsInVector(Vector<float>& firstVector, Vector<float>& lastVector, unsigned first, unsigned last) 231 { 232 float temp = firstVector.at(first); 233 firstVector.at(first) = lastVector.at(last); 234 lastVector.at(last) = temp; 235 } 236 237 static inline void swapItemsInLayoutAttributes(SVGTextLayoutAttributes& firstAttributes, SVGTextLayoutAttributes& lastAttributes, unsigned firstPosition, unsigned lastPosition) 238 { 239 swapItemsInVector(firstAttributes.xValues(), lastAttributes.xValues(), firstPosition, lastPosition); 240 swapItemsInVector(firstAttributes.yValues(), lastAttributes.yValues(), firstPosition, lastPosition); 241 swapItemsInVector(firstAttributes.dxValues(), lastAttributes.dxValues(), firstPosition, lastPosition); 242 swapItemsInVector(firstAttributes.dyValues(), lastAttributes.dyValues(), firstPosition, lastPosition); 243 swapItemsInVector(firstAttributes.rotateValues(), lastAttributes.rotateValues(), firstPosition, lastPosition); 244 } 245 246 static inline void findFirstAndLastAttributesInVector(Vector<SVGTextLayoutAttributes>& attributes, RenderSVGInlineText* firstContext, RenderSVGInlineText* lastContext, 247 SVGTextLayoutAttributes*& first, SVGTextLayoutAttributes*& last) 248 { 249 first = 0; 250 last = 0; 251 252 unsigned attributesSize = attributes.size(); 253 for (unsigned i = 0; i < attributesSize; ++i) { 254 SVGTextLayoutAttributes& current = attributes.at(i); 255 if (!first && firstContext == current.context()) 256 first = ¤t; 257 if (!last && lastContext == current.context()) 258 last = ¤t; 259 if (first && last) 260 break; 261 } 262 263 ASSERT(first); 264 ASSERT(last); 265 } 266 267 static inline void reverseInlineBoxRangeAndValueListsIfNeeded(void* userData, Vector<InlineBox*>::iterator first, Vector<InlineBox*>::iterator last) 268 { 269 ASSERT(userData); 270 Vector<SVGTextLayoutAttributes>& attributes = *reinterpret_cast<Vector<SVGTextLayoutAttributes>*>(userData); 271 272 // This is a copy of std::reverse(first, last). It additionally assure that the value lists within the InlineBoxes are reordered as well. 273 while (true) { 274 if (first == last || first == --last) 275 return; 276 277 ASSERT((*first)->isSVGInlineTextBox()); 278 ASSERT((*last)->isSVGInlineTextBox()); 279 280 SVGInlineTextBox* firstTextBox = static_cast<SVGInlineTextBox*>(*first); 281 SVGInlineTextBox* lastTextBox = static_cast<SVGInlineTextBox*>(*last); 282 283 // Reordering is only necessary for BiDi text that is _absolutely_ positioned. 284 if (firstTextBox->len() == 1 && firstTextBox->len() == lastTextBox->len()) { 285 RenderSVGInlineText* firstContext = toRenderSVGInlineText(firstTextBox->textRenderer()); 286 RenderSVGInlineText* lastContext = toRenderSVGInlineText(lastTextBox->textRenderer()); 287 288 SVGTextLayoutAttributes* firstAttributes = 0; 289 SVGTextLayoutAttributes* lastAttributes = 0; 290 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); 299 } 300 301 InlineBox* temp = *first; 302 *first = *last; 303 *last = temp; 304 305 ++first; 306 } 307 } 308 309 void SVGRootInlineBox::reorderValueLists(Vector<SVGTextLayoutAttributes>& attributes) 310 { 311 Vector<InlineBox*> leafBoxesInLogicalOrder; 312 collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder, reverseInlineBoxRangeAndValueListsIfNeeded, &attributes); 313 } 253 314 254 315 } // namespace WebCore -
trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.h
r81168 r82411 56 56 57 57 private: 58 void buildTextBoxListInLogicalOrder(RenderObject*, Vector<SVGInlineTextBox*>&);58 void reorderValueLists(Vector<SVGTextLayoutAttributes>&); 59 59 void layoutCharactersInTextBoxes(InlineFlowBox*, SVGTextLayoutEngine&); 60 60 void layoutChildBoxes(InlineFlowBox*); -
trunk/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp
r68976 r82411 28 28 namespace WebCore { 29 29 30 SVGTextLayoutAttributes::SVGTextLayoutAttributes() 30 SVGTextLayoutAttributes::SVGTextLayoutAttributes(RenderSVGInlineText* context) 31 : m_context(context) 31 32 { 32 33 } … … 66 67 void SVGTextLayoutAttributes::dump() const 67 68 { 69 fprintf(stderr, "context: %p\n", m_context); 70 68 71 fprintf(stderr, "x values: "); 69 72 dumpLayoutVector(m_xValues); -
trunk/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h
r68976 r82411 28 28 namespace WebCore { 29 29 30 class RenderSVGInlineText; 31 30 32 class SVGTextLayoutAttributes { 31 33 public: 32 SVGTextLayoutAttributes( );34 SVGTextLayoutAttributes(RenderSVGInlineText* context = 0); 33 35 34 36 void reserveCapacity(unsigned length); … … 36 38 37 39 static float emptyValue(); 40 41 RenderSVGInlineText* context() const { return m_context; } 38 42 39 43 Vector<float>& xValues() { return m_xValues; } … … 56 60 57 61 private: 62 RenderSVGInlineText* m_context; 58 63 Vector<float> m_xValues; 59 64 Vector<float> m_yValues; -
trunk/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
r81168 r82411 53 53 54 54 // Propagate layout attributes to each RenderSVGInlineText object. 55 Vector<SVGTextLayoutAttributes>& allAttributes = textRoot->layoutAttributes(); 56 allAttributes.clear(); 55 57 atCharacter = 0; 56 58 lastCharacter = '\0'; 57 propagateLayoutAttributes(textRoot, a tCharacter, lastCharacter);59 propagateLayoutAttributes(textRoot, allAttributes, atCharacter, lastCharacter); 58 60 } 59 61 … … 187 189 } 188 190 189 void SVGTextLayoutAttributesBuilder::propagateLayoutAttributes(RenderObject* start, unsigned& atCharacter, UChar& lastCharacter) const191 void SVGTextLayoutAttributesBuilder::propagateLayoutAttributes(RenderObject* start, Vector<SVGTextLayoutAttributes>& allAttributes, unsigned& atCharacter, UChar& lastCharacter) const 190 192 { 191 193 for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) { … … 196 198 bool preserveWhiteSpace = shouldPreserveAllWhiteSpace(text->style()); 197 199 198 SVGTextLayoutAttributes attributes ;200 SVGTextLayoutAttributes attributes(text); 199 201 attributes.reserveCapacity(textLength); 200 202 … … 244 246 245 247 text->storeLayoutAttributes(attributes); 248 allAttributes.append(attributes); 246 249 atCharacter = valueListPosition; 247 250 continue; … … 251 254 continue; 252 255 253 propagateLayoutAttributes(child, a tCharacter, lastCharacter);256 propagateLayoutAttributes(child, allAttributes, atCharacter, lastCharacter); 254 257 } 255 258 } -
trunk/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h
r76248 r82411 61 61 void buildLayoutScopes(RenderObject*, unsigned& atCharacter, UChar& lastCharacter); 62 62 void buildOutermostLayoutScope(RenderSVGText*, unsigned textLength); 63 void propagateLayoutAttributes(RenderObject*, unsigned& atCharacter, UChar& lastCharacter) const;63 void propagateLayoutAttributes(RenderObject*, Vector<SVGTextLayoutAttributes>& allAttributes, unsigned& atCharacter, UChar& lastCharacter) const; 64 64 65 65 enum LayoutValueType { -
trunk/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp
r81168 r82411 35 35 namespace WebCore { 36 36 37 SVGTextLayoutEngine::SVGTextLayoutEngine(Vector<SVGInlineTextBox*>& boxesInLogicalOrder) 38 : m_x(0) 37 SVGTextLayoutEngine::SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes>& layoutAttributes) 38 : m_layoutAttributes(layoutAttributes) 39 , m_logicalCharacterOffset(0) 40 , m_logicalMetricsListOffset(0) 41 , m_visualCharacterOffset(0) 42 , m_visualMetricsListOffset(0) 43 , m_x(0) 39 44 , m_y(0) 40 45 , m_dx(0) … … 47 52 , m_textPathScaling(1) 48 53 { 49 unsigned size = boxesInLogicalOrder.size(); 50 for (unsigned i = 0; i < size; ++i) { 51 SVGInlineTextBox* textBox = boxesInLogicalOrder.at(i); 52 m_ranges.append(CharacterRange(textBox->start(), textBox->end(), textBox)); 53 } 54 55 ASSERT(!m_ranges.isEmpty()); 54 ASSERT(!m_layoutAttributes.isEmpty()); 56 55 } 57 56 … … 85 84 } 86 85 87 void SVGTextLayoutEngine::updateRelativePositionAdjustmentsIfNeeded(Vector<float>& dxValues, Vector<float>& dyValues , unsigned positionListOffset)86 void SVGTextLayoutEngine::updateRelativePositionAdjustmentsIfNeeded(Vector<float>& dxValues, Vector<float>& dyValues) 88 87 { 89 88 // Update relative positioning information. … … 93 92 float dx = 0; 94 93 if (!dxValues.isEmpty()) { 95 float& dxCurrent = dxValues.at( positionListOffset);94 float& dxCurrent = dxValues.at(m_logicalCharacterOffset); 96 95 if (dxCurrent != SVGTextLayoutAttributes::emptyValue()) 97 96 dx = dxCurrent; … … 100 99 float dy = 0; 101 100 if (!dyValues.isEmpty()) { 102 float& dyCurrent = dyValues.at( positionListOffset);101 float& dyCurrent = dyValues.at(m_logicalCharacterOffset); 103 102 if (dyCurrent != SVGTextLayoutAttributes::emptyValue()) 104 103 dy = dyCurrent; … … 121 120 } 122 121 123 void SVGTextLayoutEngine::recordTextFragment(SVGInlineTextBox* textBox, Vector<SVGTextMetrics>& textMetricsValues , unsigned characterOffset, unsigned metricsListOffset)122 void SVGTextLayoutEngine::recordTextFragment(SVGInlineTextBox* textBox, Vector<SVGTextMetrics>& textMetricsValues) 124 123 { 125 124 ASSERT(!m_currentTextFragment.length); 126 ASSERT(m etricsListOffset > 0);125 ASSERT(m_visualMetricsListOffset > 0); 127 126 128 127 // Figure out length of fragment. 129 m_currentTextFragment.length = characterOffset - m_currentTextFragment.characterOffset;128 m_currentTextFragment.length = m_visualCharacterOffset - m_currentTextFragment.characterOffset; 130 129 131 130 // Figure out fragment metrics. 132 SVGTextMetrics& lastCharacterMetrics = textMetricsValues.at(m etricsListOffset - 1);131 SVGTextMetrics& lastCharacterMetrics = textMetricsValues.at(m_visualMetricsListOffset - 1); 133 132 m_currentTextFragment.width = lastCharacterMetrics.width(); 134 133 m_currentTextFragment.height = lastCharacterMetrics.height(); … … 138 137 float length = 0; 139 138 if (m_isVerticalText) { 140 for (unsigned i = m_currentTextFragment.metricsListOffset; i < m etricsListOffset; ++i)139 for (unsigned i = m_currentTextFragment.metricsListOffset; i < m_visualMetricsListOffset; ++i) 141 140 length += textMetricsValues.at(i).height(); 142 141 m_currentTextFragment.height = length; 143 142 } else { 144 for (unsigned i = m_currentTextFragment.metricsListOffset; i < m etricsListOffset; ++i)143 for (unsigned i = m_currentTextFragment.metricsListOffset; i < m_visualMetricsListOffset; ++i) 145 144 length += textMetricsValues.at(i).width(); 146 145 m_currentTextFragment.width = length; … … 344 343 } 345 344 346 void SVGTextLayoutEngine::nextLogicalBoxAndOffset(unsigned consumeCharacters, unsigned& positionListOffset, SVGInlineTextBox*& box) 347 { 348 ASSERT(!m_ranges.isEmpty()); 349 350 unsigned consumed = 0; 351 do { 352 CharacterRange& firstRange = m_ranges.first(); 353 if (!consumed) { 354 positionListOffset = firstRange.start; 355 box = firstRange.box; 356 } else 357 ASSERT(firstRange.box == box); 358 359 ++consumed; 360 if (firstRange.start == firstRange.end) { 361 m_ranges.remove(0); 345 bool SVGTextLayoutEngine::currentLogicalCharacterAttributes(SVGTextLayoutAttributes& logicalAttributes) 346 { 347 logicalAttributes = m_layoutAttributes.first(); 348 if (m_logicalCharacterOffset != logicalAttributes.xValues().size()) 349 return true; 350 351 m_layoutAttributes.remove(0); 352 if (m_layoutAttributes.isEmpty()) 353 return false; 354 355 logicalAttributes = m_layoutAttributes.first(); 356 m_logicalMetricsListOffset = 0; 357 m_logicalCharacterOffset = 0; 358 return true; 359 } 360 361 bool SVGTextLayoutEngine::currentLogicalCharacterMetrics(SVGTextLayoutAttributes& logicalAttributes, SVGTextMetrics& logicalMetrics) 362 { 363 logicalMetrics = SVGTextMetrics::emptyMetrics(); 364 365 Vector<SVGTextMetrics>& textMetricsValues = logicalAttributes.textMetricsValues(); 366 unsigned textMetricsSize = textMetricsValues.size(); 367 while (true) { 368 if (m_logicalMetricsListOffset == textMetricsSize) { 369 if (!currentLogicalCharacterAttributes(logicalAttributes)) 370 return false; 371 372 textMetricsValues = logicalAttributes.textMetricsValues(); 373 textMetricsSize = textMetricsValues.size(); 362 374 continue; 363 375 } 364 376 365 ++firstRange.start; 366 } while (consumed < consumeCharacters); 377 logicalMetrics = textMetricsValues.at(m_logicalMetricsListOffset); 378 if (logicalMetrics == SVGTextMetrics::emptyMetrics() || (!logicalMetrics.width() && !logicalMetrics.height())) { 379 advanceToNextLogicalCharacter(logicalMetrics); 380 continue; 381 } 382 383 // Stop if we found the next valid logical text metrics object. 384 return true; 385 } 386 387 ASSERT_NOT_REACHED(); 388 return true; 389 } 390 391 bool SVGTextLayoutEngine::currentVisualCharacterMetrics(SVGInlineTextBox* textBox, RenderSVGInlineText* text, SVGTextMetrics& metrics) 392 { 393 SVGTextLayoutAttributes& attributes = text->layoutAttributes(); 394 Vector<SVGTextMetrics>& textMetricsValues = attributes.textMetricsValues(); 395 ASSERT(!textMetricsValues.isEmpty()); 396 397 unsigned textMetricsSize = textMetricsValues.size(); 398 unsigned boxStart = textBox->start(); 399 unsigned boxLength = textBox->len(); 400 401 if (m_visualMetricsListOffset == textMetricsSize) 402 return false; 403 404 while (m_visualMetricsListOffset < textMetricsSize) { 405 SVGTextMetrics& visualMetrics = textMetricsValues.at(m_visualMetricsListOffset); 406 407 // Advance to text box start location. 408 if (m_visualCharacterOffset < boxStart) { 409 advanceToNextVisualCharacter(visualMetrics); 410 continue; 411 } 412 413 // Stop if we've finished processing this text box. 414 if (m_visualCharacterOffset >= boxStart + boxLength) 415 return false; 416 417 metrics = visualMetrics; 418 return true; 419 } 420 421 return false; 422 } 423 424 void SVGTextLayoutEngine::advanceToNextLogicalCharacter(const SVGTextMetrics& logicalMetrics) 425 { 426 ++m_logicalMetricsListOffset; 427 m_logicalCharacterOffset += logicalMetrics.length(); 428 } 429 430 void SVGTextLayoutEngine::advanceToNextVisualCharacter(const SVGTextMetrics& visualMetrics) 431 { 432 ++m_visualMetricsListOffset; 433 m_visualCharacterOffset += visualMetrics.length(); 367 434 } 368 435 … … 377 444 ASSERT(svgStyle); 378 445 379 SVGTextLayoutAttributes& attributes = text->layoutAttributes(); 380 Vector<SVGTextMetrics>& textMetricsValues = attributes.textMetricsValues(); 381 382 unsigned boxStart = textBox->start(); 383 unsigned boxLength = textBox->len(); 384 unsigned textMetricsSize = textMetricsValues.size(); 385 386 unsigned positionListOffset = 0; 387 unsigned metricsListOffset = 0; 388 unsigned characterOffset = 0; 446 m_visualMetricsListOffset = 0; 447 m_visualCharacterOffset = 0; 448 449 Vector<SVGTextMetrics>& textMetricsValues = text->layoutAttributes().textMetricsValues(); 389 450 const UChar* characters = text->characters(); 390 451 … … 401 462 402 463 // Main layout algorithm. 403 // Find the start of the current text box in this list, respecting ligatures. 404 for (; metricsListOffset < textMetricsSize; ++metricsListOffset) { 405 SVGTextMetrics& metrics = textMetricsValues.at(metricsListOffset); 406 407 // Advance to text box start location. 408 if (characterOffset < boxStart) { 409 characterOffset += metrics.length(); 464 while (true) { 465 // Find the start of the current text box in this list, respecting ligatures. 466 SVGTextMetrics visualMetrics = SVGTextMetrics::emptyMetrics(); 467 if (!currentVisualCharacterMetrics(textBox, text, visualMetrics)) 468 break; 469 470 if (visualMetrics == SVGTextMetrics::emptyMetrics()) { 471 advanceToNextVisualCharacter(visualMetrics); 410 472 continue; 411 473 } 412 413 // Stop if we've finished processing this text box.414 if ( characterOffset >= boxStart + boxLength)474 475 SVGTextLayoutAttributes logicalAttributes; 476 if (!currentLogicalCharacterAttributes(logicalAttributes)) 415 477 break; 416 417 SVGInlineTextBox* ownerBox = 0; 418 nextLogicalBoxAndOffset(metrics.length(), positionListOffset, ownerBox); 419 420 SVGTextLayoutAttributes& currentBoxAttributes = toRenderSVGInlineText(ownerBox->textRenderer())->layoutAttributes(); 421 Vector<float>& xValues = currentBoxAttributes.xValues(); 422 Vector<float>& yValues = currentBoxAttributes.yValues(); 423 424 float x = xValues.at(positionListOffset); 425 float y = yValues.at(positionListOffset); 478 479 SVGTextMetrics logicalMetrics = SVGTextMetrics::emptyMetrics(); 480 if (!currentLogicalCharacterMetrics(logicalAttributes, logicalMetrics)) 481 break; 482 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); 426 491 427 492 // When we've advanced to the box start offset, determine using the original x/y values, 428 493 // whether this character starts a new text chunk, before doing any further processing. 429 if (characterOffset == boxStart) 430 textBox->setStartsNewTextChunk(toRenderSVGInlineText(ownerBox->textRenderer())->characterStartsNewTextChunk(positionListOffset)); 431 432 if (metrics == SVGTextMetrics::emptyMetrics()) { 433 characterOffset += metrics.length(); 434 continue; 435 } 436 437 const UChar* currentCharacter = characters + characterOffset; 494 if (m_visualCharacterOffset == textBox->start()) 495 textBox->setStartsNewTextChunk(logicalAttributes.context()->characterStartsNewTextChunk(m_logicalCharacterOffset)); 496 438 497 float angle = 0; 439 Vector<float>& rotateValues = currentBoxAttributes.rotateValues();440 498 if (!rotateValues.isEmpty()) { 441 float newAngle = rotateValues.at( positionListOffset);499 float newAngle = rotateValues.at(m_logicalCharacterOffset); 442 500 if (newAngle != SVGTextLayoutAttributes::emptyValue()) 443 501 angle = newAngle; … … 445 503 446 504 // Calculate glyph orientation angle. 505 const UChar* currentCharacter = characters + m_visualCharacterOffset; 447 506 float orientationAngle = baselineLayout.calculateGlyphOrientationAngle(m_isVerticalText, svgStyle, *currentCharacter); 448 507 … … 450 509 float xOrientationShift = 0; 451 510 float yOrientationShift = 0; 452 float glyphAdvance = baselineLayout.calculateGlyphAdvanceAndOrientation(m_isVerticalText, metrics, orientationAngle, xOrientationShift, yOrientationShift);511 float glyphAdvance = baselineLayout.calculateGlyphAdvanceAndOrientation(m_isVerticalText, visualMetrics, orientationAngle, xOrientationShift, yOrientationShift); 453 512 454 513 // Assign current text position to x/y values, if needed. … … 456 515 457 516 // Apply dx/dy value adjustments to current text position, if needed. 458 updateRelativePositionAdjustmentsIfNeeded( currentBoxAttributes.dxValues(), currentBoxAttributes.dyValues(), positionListOffset);517 updateRelativePositionAdjustmentsIfNeeded(dxValues, dyValues); 459 518 460 519 // Calculate SVG Fonts kerning, if needed. 461 float kerning = spacingLayout.calculateSVGKerning(m_isVerticalText, metrics.glyph());520 float kerning = spacingLayout.calculateSVGKerning(m_isVerticalText, visualMetrics.glyph()); 462 521 463 522 // Calculate CSS 'kerning', 'letter-spacing' and 'word-spacing' for next character, if needed. … … 499 558 // Skip character, if we're before the path. 500 559 if (textPathOffset < 0) { 501 characterOffset += metrics.length(); 560 advanceToNextLogicalCharacter(logicalMetrics); 561 advanceToNextVisualCharacter(visualMetrics); 502 562 continue; 503 563 } … … 551 611 if (didStartTextFragment && shouldStartNewFragment) { 552 612 applySpacingToNextCharacter = false; 553 recordTextFragment(textBox, textMetricsValues , characterOffset, metricsListOffset);613 recordTextFragment(textBox, textMetricsValues); 554 614 } 555 615 … … 560 620 561 621 didStartTextFragment = true; 562 m_currentTextFragment.characterOffset = characterOffset;563 m_currentTextFragment.metricsListOffset = m etricsListOffset;622 m_currentTextFragment.characterOffset = m_visualCharacterOffset; 623 m_currentTextFragment.metricsListOffset = m_visualMetricsListOffset; 564 624 m_currentTextFragment.x = x; 565 625 m_currentTextFragment.y = y; … … 602 662 } 603 663 604 characterOffset += metrics.length(); 664 advanceToNextLogicalCharacter(logicalMetrics); 665 advanceToNextVisualCharacter(visualMetrics); 605 666 lastAngle = angle; 606 667 } … … 610 671 611 672 // Close last open fragment, if needed. 612 recordTextFragment(textBox, textMetricsValues , characterOffset, metricsListOffset);673 recordTextFragment(textBox, textMetricsValues); 613 674 } 614 675 -
trunk/Source/WebCore/rendering/svg/SVGTextLayoutEngine.h
r81168 r82411 25 25 #include "SVGTextChunkBuilder.h" 26 26 #include "SVGTextFragment.h" 27 #include "SVGTextLayoutAttributes.h" 27 28 #include "SVGTextMetrics.h" 28 29 #include <wtf/Vector.h> … … 48 49 WTF_MAKE_NONCOPYABLE(SVGTextLayoutEngine); 49 50 public: 50 SVGTextLayoutEngine(Vector<SVG InlineTextBox*>& boxesInLogicalOrder);51 SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes>&); 51 52 SVGTextChunkBuilder& chunkLayoutBuilder() { return m_chunkLayoutBuilder; } 52 53 … … 58 59 59 60 private: 60 struct CharacterRange {61 CharacterRange(unsigned newStart = 0, unsigned newEnd = 0, SVGInlineTextBox* newBox = 0)62 : start(newStart)63 , end(newEnd)64 , box(newBox)65 {66 }67 68 unsigned start;69 unsigned end;70 SVGInlineTextBox* box;71 };72 73 typedef Vector<CharacterRange> CharacterRanges;74 75 61 void updateCharacerPositionIfNeeded(float& x, float& y); 76 62 void updateCurrentTextPosition(float x, float y, float glyphAdvance); 77 void updateRelativePositionAdjustmentsIfNeeded(Vector<float>& dxValues, Vector<float>& dyValues , unsigned valueListPosition);63 void updateRelativePositionAdjustmentsIfNeeded(Vector<float>& dxValues, Vector<float>& dyValues); 78 64 79 void recordTextFragment(SVGInlineTextBox*, Vector<SVGTextMetrics>& textMetricValues , unsigned characterOffset, unsigned metricsListOffset);65 void recordTextFragment(SVGInlineTextBox*, Vector<SVGTextMetrics>& textMetricValues); 80 66 bool parentDefinesTextLength(RenderObject*) const; 81 67 … … 83 69 void finalizeTransformMatrices(Vector<SVGInlineTextBox*>&); 84 70 85 void nextLogicalBoxAndOffset(unsigned consumeCharacters, unsigned& positionListOffset, SVGInlineTextBox*&); 71 bool currentLogicalCharacterAttributes(SVGTextLayoutAttributes&); 72 bool currentLogicalCharacterMetrics(SVGTextLayoutAttributes&, SVGTextMetrics&); 73 bool currentVisualCharacterMetrics(SVGInlineTextBox*, RenderSVGInlineText*, SVGTextMetrics&); 74 75 void advanceToNextLogicalCharacter(const SVGTextMetrics&); 76 void advanceToNextVisualCharacter(const SVGTextMetrics&); 86 77 87 78 private: 88 CharacterRanges m_ranges;79 Vector<SVGTextLayoutAttributes> m_layoutAttributes; 89 80 Vector<SVGInlineTextBox*> m_lineLayoutBoxes; 90 81 Vector<SVGInlineTextBox*> m_pathLayoutBoxes; … … 92 83 93 84 SVGTextFragment m_currentTextFragment; 85 unsigned m_logicalCharacterOffset; 86 unsigned m_logicalMetricsListOffset; 87 unsigned m_visualCharacterOffset; 88 unsigned m_visualMetricsListOffset; 94 89 float m_x; 95 90 float m_y;
Note: See TracChangeset
for help on using the changeset viewer.