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