OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved. | 2 * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved. |
3 * | 3 * |
4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public |
6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either |
7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. |
8 * | 8 * |
9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 * Library General Public License for more details. | 12 * Library General Public License for more details. |
13 * | 13 * |
14 * You should have received a copy of the GNU Library General Public License | 14 * You should have received a copy of the GNU Library General Public License |
15 * along with this library; see the file COPYING.LIB. If not, write to | 15 * along with this library; see the file COPYING.LIB. If not, write to |
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 * Boston, MA 02110-1301, USA. | 17 * Boston, MA 02110-1301, USA. |
18 */ | 18 */ |
19 | 19 |
20 #include "config.h" | 20 #include "config.h" |
21 | 21 |
22 #if ENABLE(SVG) | 22 #if ENABLE(SVG) |
23 #include "SVGTextLayoutAttributesBuilder.h" | 23 #include "SVGTextLayoutAttributesBuilder.h" |
24 | 24 |
25 #include "RenderSVGInlineText.h" | 25 #include "RenderSVGInlineText.h" |
26 #include "RenderSVGText.h" | 26 #include "RenderSVGText.h" |
27 #include "SVGTextPositioningElement.h" | 27 #include "SVGTextPositioningElement.h" |
28 | 28 |
29 // Set to a value > 0 to dump the text layout attributes | |
30 #define DUMP_TEXT_LAYOUT_ATTRIBUTES 0 | |
31 | |
32 namespace WebCore { | 29 namespace WebCore { |
33 | 30 |
34 SVGTextLayoutAttributesBuilder::SVGTextLayoutAttributesBuilder() | 31 SVGTextLayoutAttributesBuilder::SVGTextLayoutAttributesBuilder() |
35 : m_textLength(0) | 32 : m_textLength(0) |
36 { | 33 { |
37 } | 34 } |
38 | 35 |
39 void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextRenderer(Render
SVGInlineText* text) | 36 void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextRenderer(Render
SVGInlineText* text) |
40 { | 37 { |
41 ASSERT(text); | 38 ASSERT(text); |
42 | 39 |
43 RenderSVGText* textRoot = RenderSVGText::locateRenderSVGTextAncestor(text); | 40 RenderSVGText* textRoot = RenderSVGText::locateRenderSVGTextAncestor(text); |
44 if (!textRoot) | 41 if (!textRoot) |
45 return; | 42 return; |
46 | 43 |
47 if (!buildLayoutAttributesIfNeeded(textRoot)) | 44 if (m_textPositions.isEmpty()) { |
48 return; | 45 m_characterDataMap.clear(); |
| 46 |
| 47 m_textLength = 0; |
| 48 const UChar* lastCharacter = 0; |
| 49 collectTextPositioningElements(textRoot, lastCharacter); |
| 50 |
| 51 if (!m_textLength) |
| 52 return; |
| 53 |
| 54 buildCharacterDataMap(textRoot); |
| 55 } |
49 | 56 |
50 m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, text, m_character
DataMap); | 57 m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, text, m_character
DataMap); |
51 } | 58 } |
52 | 59 |
53 void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForWholeTree(RenderSVG
Text* textRoot) | 60 bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesForForSubtree(RenderSV
GText* textRoot) |
54 { | 61 { |
55 ASSERT(textRoot); | 62 ASSERT(textRoot); |
56 | 63 |
57 if (!buildLayoutAttributesIfNeeded(textRoot)) | 64 m_characterDataMap.clear(); |
58 return; | |
59 | 65 |
| 66 if (m_textPositions.isEmpty()) { |
| 67 m_textLength = 0; |
| 68 const UChar* lastCharacter = 0; |
| 69 collectTextPositioningElements(textRoot, lastCharacter); |
| 70 } |
| 71 |
| 72 if (!m_textLength) |
| 73 return false; |
| 74 |
| 75 buildCharacterDataMap(textRoot); |
60 m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, 0, m_characterDat
aMap); | 76 m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, 0, m_characterDat
aMap); |
| 77 return true; |
61 } | 78 } |
62 | 79 |
63 void SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer(RenderSVGInli
neText* text) | 80 void SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer(RenderSVGInli
neText* text) |
64 { | 81 { |
65 ASSERT(text); | 82 ASSERT(text); |
66 m_metricsBuilder.measureTextRenderer(text); | 83 m_metricsBuilder.measureTextRenderer(text); |
67 } | 84 } |
68 | 85 |
69 void SVGTextLayoutAttributesBuilder::rebuildMetricsForWholeTree(RenderSVGText* t
extRoot) | |
70 { | |
71 ASSERT(textRoot); | |
72 Vector<SVGTextLayoutAttributes*>& layoutAttributes = textRoot->layoutAttribu
tes(); | |
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 | |
83 if (m_textPositions.isEmpty()) { | |
84 m_textLength = 0; | |
85 const UChar* lastCharacter = 0; | |
86 collectTextPositioningElements(textRoot, lastCharacter); | |
87 } | |
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, unsigne
d& atCharacter, const UChar*& lastCharacter) | 86 static inline void processRenderSVGInlineText(RenderSVGInlineText* text, unsigne
d& atCharacter, const UChar*& lastCharacter) |
98 { | 87 { |
99 if (text->style()->whiteSpace() == PRE) { | 88 if (text->style()->whiteSpace() == PRE) { |
100 atCharacter += text->textLength(); | 89 atCharacter += text->textLength(); |
101 return; | 90 return; |
102 } | 91 } |
103 | 92 |
104 const UChar* characters = text->characters(); | 93 const UChar* characters = text->characters(); |
105 unsigned textLength = text->textLength(); | 94 unsigned textLength = text->textLength(); |
106 for (unsigned textPosition = 0; textPosition < textLength; ++textPosition) { | 95 for (unsigned textPosition = 0; textPosition < textLength; ++textPosition) { |
(...skipping 29 matching lines...) Expand all Loading... |
136 if (!element) | 125 if (!element) |
137 continue; | 126 continue; |
138 | 127 |
139 // Update text position, after we're back from recursion. | 128 // Update text position, after we're back from recursion. |
140 TextPosition& position = m_textPositions[atPosition]; | 129 TextPosition& position = m_textPositions[atPosition]; |
141 ASSERT(!position.length); | 130 ASSERT(!position.length); |
142 position.length = m_textLength - position.start; | 131 position.length = m_textLength - position.start; |
143 } | 132 } |
144 } | 133 } |
145 | 134 |
146 void SVGTextLayoutAttributesBuilder::buildLayoutAttributes(RenderSVGText* textRo
ot) | 135 void SVGTextLayoutAttributesBuilder::buildCharacterDataMap(RenderSVGText* textRo
ot) |
147 { | 136 { |
148 ASSERT(m_textLength); | |
149 | |
150 SVGTextPositioningElement* outermostTextElement = SVGTextPositioningElement:
:elementFromRenderer(textRoot); | 137 SVGTextPositioningElement* outermostTextElement = SVGTextPositioningElement:
:elementFromRenderer(textRoot); |
151 ASSERT(outermostTextElement); | 138 ASSERT(outermostTextElement); |
152 | 139 |
153 // Grab outermost <text> element value lists and insert them in the characte
r data map. | 140 // Grab outermost <text> element value lists and insert them in the characte
r data map. |
154 TextPosition wholeTextPosition(outermostTextElement, 0, m_textLength); | 141 TextPosition wholeTextPosition(outermostTextElement, 0, m_textLength); |
155 fillCharacterDataMap(wholeTextPosition); | 142 fillCharacterDataMap(wholeTextPosition); |
156 | 143 |
157 // Handle x/y default attributes. | 144 // Handle x/y default attributes. |
158 SVGCharacterDataMap::iterator it = m_characterDataMap.find(1); | 145 SVGCharacterDataMap::iterator it = m_characterDataMap.find(1); |
159 if (it == m_characterDataMap.end()) { | 146 if (it == m_characterDataMap.end()) { |
160 SVGCharacterData data; | 147 SVGCharacterData data; |
161 data.x = 0; | 148 data.x = 0; |
162 data.y = 0; | 149 data.y = 0; |
163 m_characterDataMap.set(1, data); | 150 m_characterDataMap.set(1, data); |
164 } else { | 151 } else { |
165 SVGCharacterData& data = it->second; | 152 SVGCharacterData& data = it->second; |
166 if (data.x == SVGTextLayoutAttributes::emptyValue()) | 153 if (data.x == SVGTextLayoutAttributes::emptyValue()) |
167 data.x = 0; | 154 data.x = 0; |
168 if (data.y == SVGTextLayoutAttributes::emptyValue()) | 155 if (data.y == SVGTextLayoutAttributes::emptyValue()) |
169 data.y = 0; | 156 data.y = 0; |
170 } | 157 } |
171 | 158 |
172 // Fill character data map using child text positioning elements in top-down
order. | 159 // Fill character data map using child text positioning elements in top-down
order. |
173 unsigned size = m_textPositions.size(); | 160 unsigned size = m_textPositions.size(); |
174 for (unsigned i = 0; i < size; ++i) | 161 for (unsigned i = 0; i < size; ++i) |
175 fillCharacterDataMap(m_textPositions[i]); | 162 fillCharacterDataMap(m_textPositions[i]); |
176 | |
177 #if DUMP_TEXT_LAYOUT_ATTRIBUTES > 0 | |
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(); | |
180 #endif | |
181 } | 163 } |
182 | 164 |
183 static inline void updateCharacterData(unsigned i, float& lastRotation, SVGChara
cterData& data, const SVGLengthContext& lengthContext, const SVGLengthList* xLis
t, const SVGLengthList* yList, const SVGLengthList* dxList, const SVGLengthList*
dyList, const SVGNumberList* rotateList) | 165 static inline void updateCharacterData(unsigned i, float& lastRotation, SVGChara
cterData& data, const SVGLengthContext& lengthContext, const SVGLengthList* xLis
t, const SVGLengthList* yList, const SVGLengthList* dxList, const SVGLengthList*
dyList, const SVGNumberList* rotateList) |
184 { | 166 { |
185 if (xList) | 167 if (xList) |
186 data.x = xList->at(i).value(lengthContext); | 168 data.x = xList->at(i).value(lengthContext); |
187 if (yList) | 169 if (yList) |
188 data.y = yList->at(i).value(lengthContext); | 170 data.y = yList->at(i).value(lengthContext); |
189 if (dxList) | 171 if (dxList) |
190 data.dx = dxList->at(i).value(lengthContext); | 172 data.dx = dxList->at(i).value(lengthContext); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 continue; | 229 continue; |
248 } | 230 } |
249 | 231 |
250 it->second.rotate = lastRotation; | 232 it->second.rotate = lastRotation; |
251 } | 233 } |
252 } | 234 } |
253 | 235 |
254 } | 236 } |
255 | 237 |
256 #endif // ENABLE(SVG) | 238 #endif // ENABLE(SVG) |
OLD | NEW |