OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. | 2 * Copyright (C) Research In Motion Limited 2010-2012. 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 #include "core/layout/svg/SVGTextLayoutEngine.h" | 21 #include "core/layout/svg/SVGTextLayoutEngine.h" |
22 | 22 |
23 #include "core/layout/svg/LayoutSVGInlineText.h" | 23 #include "core/layout/svg/LayoutSVGInlineText.h" |
24 #include "core/layout/svg/LayoutSVGTextPath.h" | 24 #include "core/layout/svg/LayoutSVGTextPath.h" |
| 25 #include "core/layout/svg/SVGTextChunkBuilder.h" |
25 #include "core/layout/svg/SVGTextLayoutEngineBaseline.h" | 26 #include "core/layout/svg/SVGTextLayoutEngineBaseline.h" |
26 #include "core/layout/svg/SVGTextLayoutEngineSpacing.h" | 27 #include "core/layout/svg/SVGTextLayoutEngineSpacing.h" |
27 #include "core/layout/svg/line/SVGInlineTextBox.h" | 28 #include "core/layout/svg/line/SVGInlineTextBox.h" |
28 #include "core/svg/SVGElement.h" | 29 #include "core/svg/SVGElement.h" |
29 #include "core/svg/SVGLengthContext.h" | 30 #include "core/svg/SVGLengthContext.h" |
30 #include "core/svg/SVGTextContentElement.h" | 31 #include "core/svg/SVGTextContentElement.h" |
31 | 32 |
32 // Set to a value > 0 to dump the text fragments | |
33 #define DUMP_TEXT_FRAGMENTS 0 | |
34 | |
35 namespace blink { | 33 namespace blink { |
36 | 34 |
37 SVGTextLayoutEngine::SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes*>& layou
tAttributes) | 35 SVGTextLayoutEngine::SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes*>& layou
tAttributes) |
38 : m_layoutAttributes(layoutAttributes) | 36 : m_layoutAttributes(layoutAttributes) |
39 , m_layoutAttributesPosition(0) | 37 , m_layoutAttributesPosition(0) |
40 , m_logicalCharacterOffset(0) | 38 , m_logicalCharacterOffset(0) |
41 , m_logicalMetricsListOffset(0) | 39 , m_logicalMetricsListOffset(0) |
42 , m_visualCharacterOffset(0) | 40 , m_visualCharacterOffset(0) |
43 , m_visualMetricsListOffset(0) | 41 , m_visualMetricsListOffset(0) |
44 , m_x(0) | 42 , m_x(0) |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 return; | 173 return; |
176 m_textPathCalculator = new Path::PositionCalculator(path); | 174 m_textPathCalculator = new Path::PositionCalculator(path); |
177 m_textPathStartOffset = textPath->startOffset(); | 175 m_textPathStartOffset = textPath->startOffset(); |
178 m_textPathLength = path.length(); | 176 m_textPathLength = path.length(); |
179 if (m_textPathStartOffset > 0 && m_textPathStartOffset <= 1) | 177 if (m_textPathStartOffset > 0 && m_textPathStartOffset <= 1) |
180 m_textPathStartOffset *= m_textPathLength; | 178 m_textPathStartOffset *= m_textPathLength; |
181 | 179 |
182 float totalLength = 0; | 180 float totalLength = 0; |
183 unsigned totalCharacters = 0; | 181 unsigned totalCharacters = 0; |
184 | 182 |
185 lineLayout.m_chunkLayoutBuilder.buildTextChunks(lineLayout.m_lineLayoutBoxes
); | 183 SVGTextChunkBuilder textPathChunkLayoutBuilder; |
186 const Vector<SVGTextChunk>& textChunks = lineLayout.m_chunkLayoutBuilder.tex
tChunks(); | 184 textPathChunkLayoutBuilder.buildTextChunks(lineLayout.m_lineLayoutBoxes); |
| 185 const Vector<SVGTextChunk>& textChunks = textPathChunkLayoutBuilder.textChun
ks(); |
187 | 186 |
188 unsigned size = textChunks.size(); | 187 unsigned size = textChunks.size(); |
189 for (unsigned i = 0; i < size; ++i) { | 188 for (unsigned i = 0; i < size; ++i) { |
190 const SVGTextChunk& chunk = textChunks.at(i); | 189 const SVGTextChunk& chunk = textChunks.at(i); |
191 | 190 |
192 float length = 0; | 191 float length = 0; |
193 unsigned characters = 0; | 192 unsigned characters = 0; |
194 chunk.calculateLength(length, characters); | 193 chunk.calculateLength(length, characters); |
195 | 194 |
196 // Handle text-anchor as additional start offset for text paths. | 195 // Handle text-anchor as additional start offset for text paths. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 layoutTextOnLineOrPath(textBox, text, style); | 251 layoutTextOnLineOrPath(textBox, text, style); |
253 | 252 |
254 if (m_inPathLayout) { | 253 if (m_inPathLayout) { |
255 m_pathLayoutBoxes.append(textBox); | 254 m_pathLayoutBoxes.append(textBox); |
256 return; | 255 return; |
257 } | 256 } |
258 | 257 |
259 m_lineLayoutBoxes.append(textBox); | 258 m_lineLayoutBoxes.append(textBox); |
260 } | 259 } |
261 | 260 |
262 #if DUMP_TEXT_FRAGMENTS > 0 | |
263 static inline void dumpTextBoxes(Vector<SVGInlineTextBox*>& boxes) | |
264 { | |
265 unsigned boxCount = boxes.size(); | |
266 fprintf(stderr, "Dumping all text fragments in text sub tree, %i boxes\n", b
oxCount); | |
267 | |
268 for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) { | |
269 SVGInlineTextBox* textBox = boxes.at(boxPosition); | |
270 Vector<SVGTextFragment>& fragments = textBox->textFragments(); | |
271 fprintf(stderr, "-> Box %i: Dumping text fragments for SVGInlineTextBox,
textBox=%p, textLayoutObject=%p\n", boxPosition, textBox, textBox->textLayoutOb
ject()); | |
272 fprintf(stderr, " textBox properties, start=%i, len=%i, box direc
tion=%i\n", textBox->start(), textBox->len(), textBox->direction()); | |
273 fprintf(stderr, " textLayoutObject properties, textLength=%i\n", textB
ox->textLayoutObject()->textLength()); | |
274 | |
275 String characters = textBox->textLayoutObject()->text(); | |
276 | |
277 unsigned fragmentCount = fragments.size(); | |
278 for (unsigned i = 0; i < fragmentCount; ++i) { | |
279 SVGTextFragment& fragment = fragments.at(i); | |
280 String fragmentString = characters.substring(fragment.characterOffse
t, fragment.length); | |
281 fprintf(stderr, " -> Fragment %i, x=%lf, y=%lf, width=%lf, height
=%lf, characterOffset=%i, length=%i, characters='%s'\n", | |
282 i, fragment.x, fragment.y, fragment.width, fragment.height, frag
ment.characterOffset, fragment.length, fragmentString.utf8().data()); | |
283 } | |
284 } | |
285 } | |
286 #endif | |
287 | |
288 void SVGTextLayoutEngine::finalizeTransformMatrices(Vector<SVGInlineTextBox*>& b
oxes) | |
289 { | |
290 unsigned boxCount = boxes.size(); | |
291 if (!boxCount) | |
292 return; | |
293 | |
294 for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) { | |
295 SVGInlineTextBox* textBox = boxes.at(boxPosition); | |
296 AffineTransform textBoxTransformation = m_chunkLayoutBuilder.transformat
ionForTextBox(textBox); | |
297 if (textBoxTransformation.isIdentity()) | |
298 continue; | |
299 | |
300 Vector<SVGTextFragment>& fragments = textBox->textFragments(); | |
301 unsigned fragmentCount = fragments.size(); | |
302 for (unsigned i = 0; i < fragmentCount; ++i) { | |
303 ASSERT(fragments[i].lengthAdjustTransform.isIdentity()); | |
304 fragments[i].lengthAdjustTransform = textBoxTransformation; | |
305 } | |
306 } | |
307 | |
308 boxes.clear(); | |
309 } | |
310 | |
311 void SVGTextLayoutEngine::finishLayout() | 261 void SVGTextLayoutEngine::finishLayout() |
312 { | 262 { |
313 // After all text fragments are stored in their correpsonding SVGInlineTextB
oxes, we can layout individual text chunks. | 263 // After all text fragments are stored in their correpsonding SVGInlineTextB
oxes, we can layout individual text chunks. |
314 // Chunk layouting is only performed for line layout boxes, not for path lay
out, where it has already been done. | 264 // Chunk layouting is only performed for line layout boxes, not for path lay
out, where it has already been done. |
315 m_chunkLayoutBuilder.layoutTextChunks(m_lineLayoutBoxes); | 265 SVGTextChunkBuilder chunkLayoutBuilder; |
| 266 chunkLayoutBuilder.layoutTextChunks(m_lineLayoutBoxes); |
316 | 267 |
317 // Finalize transform matrices, after the chunk layout corrections have been
applied, and all fragment x/y positions are finalized. | 268 // Finalize transform matrices, after the chunk layout corrections have been
applied, and all fragment x/y positions are finalized. |
318 if (!m_lineLayoutBoxes.isEmpty()) { | 269 if (!m_lineLayoutBoxes.isEmpty()) { |
319 #if DUMP_TEXT_FRAGMENTS > 0 | 270 chunkLayoutBuilder.finalizeTransformMatrices(m_lineLayoutBoxes); |
320 fprintf(stderr, "Line layout: "); | 271 m_lineLayoutBoxes.clear(); |
321 dumpTextBoxes(m_lineLayoutBoxes); | |
322 #endif | |
323 | |
324 finalizeTransformMatrices(m_lineLayoutBoxes); | |
325 } | 272 } |
326 | 273 |
327 if (!m_pathLayoutBoxes.isEmpty()) { | 274 if (!m_pathLayoutBoxes.isEmpty()) { |
328 #if DUMP_TEXT_FRAGMENTS > 0 | 275 chunkLayoutBuilder.finalizeTransformMatrices(m_pathLayoutBoxes); |
329 fprintf(stderr, "Path layout: "); | 276 m_pathLayoutBoxes.clear(); |
330 dumpTextBoxes(m_pathLayoutBoxes); | |
331 #endif | |
332 | |
333 finalizeTransformMatrices(m_pathLayoutBoxes); | |
334 } | 277 } |
335 } | 278 } |
336 | 279 |
337 bool SVGTextLayoutEngine::currentLogicalCharacterAttributes(SVGTextLayoutAttribu
tes*& logicalAttributes) | 280 bool SVGTextLayoutEngine::currentLogicalCharacterAttributes(SVGTextLayoutAttribu
tes*& logicalAttributes) |
338 { | 281 { |
339 if (m_layoutAttributesPosition == m_layoutAttributes.size()) | 282 if (m_layoutAttributesPosition == m_layoutAttributes.size()) |
340 return false; | 283 return false; |
341 | 284 |
342 logicalAttributes = m_layoutAttributes[m_layoutAttributesPosition]; | 285 logicalAttributes = m_layoutAttributes[m_layoutAttributesPosition]; |
343 ASSERT(logicalAttributes); | 286 ASSERT(logicalAttributes); |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 } | 577 } |
635 | 578 |
636 if (!didStartTextFragment) | 579 if (!didStartTextFragment) |
637 return; | 580 return; |
638 | 581 |
639 // Close last open fragment, if needed. | 582 // Close last open fragment, if needed. |
640 recordTextFragment(textBox, visualMetricsValues); | 583 recordTextFragment(textBox, visualMetricsValues); |
641 } | 584 } |
642 | 585 |
643 } | 586 } |
OLD | NEW |