Chromium Code Reviews| 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 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 32 // Set to a value > 0 to dump the text fragments | 32 // Set to a value > 0 to dump the text fragments |
| 33 #define DUMP_TEXT_FRAGMENTS 0 | 33 #define DUMP_TEXT_FRAGMENTS 0 |
| 34 | 34 |
| 35 namespace blink { | 35 namespace blink { |
| 36 | 36 |
| 37 SVGTextLayoutEngine::SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes*>& layou tAttributes) | 37 SVGTextLayoutEngine::SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes*>& layou tAttributes) |
| 38 : m_layoutAttributes(layoutAttributes) | 38 : m_layoutAttributes(layoutAttributes) |
| 39 , m_layoutAttributesPosition(0) | 39 , m_layoutAttributesPosition(0) |
| 40 , m_logicalCharacterOffset(0) | 40 , m_logicalCharacterOffset(0) |
| 41 , m_logicalMetricsListOffset(0) | 41 , m_logicalMetricsListOffset(0) |
| 42 , m_visualCharacterOffset(0) | |
| 43 , m_visualMetricsListOffset(0) | |
| 44 , m_x(0) | 42 , m_x(0) |
| 45 , m_y(0) | 43 , m_y(0) |
| 46 , m_dx(0) | 44 , m_dx(0) |
| 47 , m_dy(0) | 45 , m_dy(0) |
| 48 , m_isVerticalText(false) | 46 , m_isVerticalText(false) |
| 49 , m_inPathLayout(false) | 47 , m_inPathLayout(false) |
| 50 , m_textPathCalculator(0) | 48 , m_textPathCalculator(0) |
| 51 , m_textPathLength(0) | 49 , m_textPathLength(0) |
| 52 , m_textPathCurrentOffset(0) | 50 , m_textPathCurrentOffset(0) |
| 53 , m_textPathSpacing(0) | 51 , m_textPathSpacing(0) |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 m_dy += dy; | 103 m_dy += dy; |
| 106 } | 104 } |
| 107 | 105 |
| 108 return; | 106 return; |
| 109 } | 107 } |
| 110 | 108 |
| 111 m_dx = dx; | 109 m_dx = dx; |
| 112 m_dy = dy; | 110 m_dy = dy; |
| 113 } | 111 } |
| 114 | 112 |
| 115 void SVGTextLayoutEngine::recordTextFragment(SVGInlineTextBox* textBox, const Ve ctor<SVGTextMetrics>& textMetricsValues) | 113 void SVGTextLayoutEngine::recordTextFragment(SVGInlineTextBox* textBox) |
| 116 { | 114 { |
| 117 ASSERT(!m_currentTextFragment.length); | 115 ASSERT(!m_currentTextFragment.length); |
| 118 ASSERT(m_visualMetricsListOffset > 0); | |
| 119 | 116 |
| 120 // Figure out length of fragment. | 117 // Figure out length of fragment. |
| 121 m_currentTextFragment.length = m_visualCharacterOffset - m_currentTextFragme nt.characterOffset; | 118 m_currentTextFragment.length = m_visualMetricsIterator.characterOffset() - m _currentTextFragment.characterOffset; |
| 122 | 119 |
| 123 // Figure out fragment metrics. | 120 // Figure out fragment metrics. |
| 124 const SVGTextMetrics& lastCharacterMetrics = textMetricsValues.at(m_visualMe tricsListOffset - 1); | 121 const unsigned visualMetricsListOffset = m_visualMetricsIterator.metricsList Offset(); |
| 122 const Vector<SVGTextMetrics>& textMetricsValues = m_visualMetricsIterator.me tricsList(); | |
| 123 const SVGTextMetrics& lastCharacterMetrics = textMetricsValues.at(visualMetr icsListOffset - 1); | |
| 125 m_currentTextFragment.width = lastCharacterMetrics.width(); | 124 m_currentTextFragment.width = lastCharacterMetrics.width(); |
| 126 m_currentTextFragment.height = lastCharacterMetrics.height(); | 125 m_currentTextFragment.height = lastCharacterMetrics.height(); |
| 127 | 126 |
| 128 if (m_currentTextFragment.length > 1) { | 127 if (m_currentTextFragment.length > 1) { |
| 129 // SVGTextLayoutAttributesBuilder assures that the length of the range i s equal to the sum of the individual lengths of the glyphs. | 128 // SVGTextLayoutAttributesBuilder assures that the length of the range i s equal to the sum of the individual lengths of the glyphs. |
| 130 float length = 0; | 129 float length = 0; |
| 131 if (m_isVerticalText) { | 130 if (m_isVerticalText) { |
| 132 for (unsigned i = m_currentTextFragment.metricsListOffset; i < m_vis ualMetricsListOffset; ++i) | 131 for (unsigned i = m_currentTextFragment.metricsListOffset; i < visua lMetricsListOffset; ++i) |
| 133 length += textMetricsValues.at(i).height(); | 132 length += textMetricsValues.at(i).height(); |
| 134 m_currentTextFragment.height = length; | 133 m_currentTextFragment.height = length; |
| 135 } else { | 134 } else { |
| 136 for (unsigned i = m_currentTextFragment.metricsListOffset; i < m_vis ualMetricsListOffset; ++i) | 135 for (unsigned i = m_currentTextFragment.metricsListOffset; i < visua lMetricsListOffset; ++i) |
| 137 length += textMetricsValues.at(i).width(); | 136 length += textMetricsValues.at(i).width(); |
| 138 m_currentTextFragment.width = length; | 137 m_currentTextFragment.width = length; |
| 139 } | 138 } |
| 140 } | 139 } |
| 141 | 140 |
| 142 textBox->textFragments().append(m_currentTextFragment); | 141 textBox->textFragments().append(m_currentTextFragment); |
| 143 m_currentTextFragment = SVGTextFragment(); | 142 m_currentTextFragment = SVGTextFragment(); |
| 144 } | 143 } |
| 145 | 144 |
| 146 bool SVGTextLayoutEngine::parentDefinesTextLength(LayoutObject* parent) const | 145 bool SVGTextLayoutEngine::parentDefinesTextLength(LayoutObject* parent) const |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 unsigned fragmentCount = fragments.size(); | 300 unsigned fragmentCount = fragments.size(); |
| 302 for (unsigned i = 0; i < fragmentCount; ++i) { | 301 for (unsigned i = 0; i < fragmentCount; ++i) { |
| 303 ASSERT(fragments[i].lengthAdjustTransform.isIdentity()); | 302 ASSERT(fragments[i].lengthAdjustTransform.isIdentity()); |
| 304 fragments[i].lengthAdjustTransform = textBoxTransformation; | 303 fragments[i].lengthAdjustTransform = textBoxTransformation; |
| 305 } | 304 } |
| 306 } | 305 } |
| 307 | 306 |
| 308 boxes.clear(); | 307 boxes.clear(); |
| 309 } | 308 } |
| 310 | 309 |
| 311 void SVGTextLayoutEngine::finishLayout() | 310 void SVGTextLayoutEngine::finishLayout() |
|
pdr.
2015/05/27 03:11:18
m_metricsList feels like a use after free waiting
fs
2015/05/27 12:53:13
I'm not too worried about life-times myself - if t
| |
| 312 { | 311 { |
| 313 // After all text fragments are stored in their correpsonding SVGInlineTextB oxes, we can layout individual text chunks. | 312 // 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. | 313 // 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); | 314 m_chunkLayoutBuilder.layoutTextChunks(m_lineLayoutBoxes); |
| 316 | 315 |
| 317 // Finalize transform matrices, after the chunk layout corrections have been applied, and all fragment x/y positions are finalized. | 316 // Finalize transform matrices, after the chunk layout corrections have been applied, and all fragment x/y positions are finalized. |
| 318 if (!m_lineLayoutBoxes.isEmpty()) { | 317 if (!m_lineLayoutBoxes.isEmpty()) { |
| 319 #if DUMP_TEXT_FRAGMENTS > 0 | 318 #if DUMP_TEXT_FRAGMENTS > 0 |
| 320 fprintf(stderr, "Line layout: "); | 319 fprintf(stderr, "Line layout: "); |
| 321 dumpTextBoxes(m_lineLayoutBoxes); | 320 dumpTextBoxes(m_lineLayoutBoxes); |
| 322 #endif | 321 #endif |
| 323 | 322 |
| 324 finalizeTransformMatrices(m_lineLayoutBoxes); | 323 finalizeTransformMatrices(m_lineLayoutBoxes); |
| 325 } | 324 } |
| 326 | 325 |
| 327 if (!m_pathLayoutBoxes.isEmpty()) { | 326 if (!m_pathLayoutBoxes.isEmpty()) { |
| 328 #if DUMP_TEXT_FRAGMENTS > 0 | 327 #if DUMP_TEXT_FRAGMENTS > 0 |
| 329 fprintf(stderr, "Path layout: "); | 328 fprintf(stderr, "Path layout: "); |
| 330 dumpTextBoxes(m_pathLayoutBoxes); | 329 dumpTextBoxes(m_pathLayoutBoxes); |
| 331 #endif | 330 #endif |
| 332 | 331 |
| 333 finalizeTransformMatrices(m_pathLayoutBoxes); | 332 finalizeTransformMatrices(m_pathLayoutBoxes); |
| 334 } | 333 } |
| 335 } | 334 } |
| 336 | 335 |
| 336 void SVGTextLayoutEngine::updateMetricsIterator(const LayoutSVGInlineText& textL ayoutObject, unsigned startCharacterOffset) | |
| 337 { | |
| 338 const Vector<SVGTextMetrics>* metricsList = &textLayoutObject.layoutAttribut es()->textMetricsValues(); | |
|
f(malita)
2015/05/27 01:53:49
Let's keep the prev ASSERT(!metricsList->isEmpty()
fs
2015/05/27 12:53:13
Added.
| |
| 339 if (&m_visualMetricsIterator.metricsList() != metricsList) | |
|
pdr.
2015/05/27 03:11:18
Instead of relying on the metrics list address, ca
fs
2015/05/27 12:53:13
Done, except I left the "Visual" part out (it's co
| |
| 340 m_visualMetricsIterator.reset(metricsList); | |
| 341 | |
| 342 if (m_visualMetricsIterator.characterOffset() == startCharacterOffset) | |
| 343 return; | |
| 344 | |
| 345 // TODO(fs): We could walk backwards through the metrics list in these cases . | |
| 346 if (m_visualMetricsIterator.characterOffset() > startCharacterOffset) | |
| 347 m_visualMetricsIterator.reset(metricsList); | |
| 348 | |
| 349 while (m_visualMetricsIterator.characterOffset() < startCharacterOffset) | |
| 350 m_visualMetricsIterator.next(); | |
| 351 } | |
| 352 | |
| 337 bool SVGTextLayoutEngine::currentLogicalCharacterAttributes(SVGTextLayoutAttribu tes*& logicalAttributes) | 353 bool SVGTextLayoutEngine::currentLogicalCharacterAttributes(SVGTextLayoutAttribu tes*& logicalAttributes) |
| 338 { | 354 { |
| 339 if (m_layoutAttributesPosition == m_layoutAttributes.size()) | 355 if (m_layoutAttributesPosition == m_layoutAttributes.size()) |
| 340 return false; | 356 return false; |
| 341 | 357 |
| 342 logicalAttributes = m_layoutAttributes[m_layoutAttributesPosition]; | 358 logicalAttributes = m_layoutAttributes[m_layoutAttributesPosition]; |
| 343 ASSERT(logicalAttributes); | 359 ASSERT(logicalAttributes); |
| 344 | 360 |
| 345 if (m_logicalCharacterOffset != logicalAttributes->context()->textLength()) | 361 if (m_logicalCharacterOffset != logicalAttributes->context()->textLength()) |
| 346 return true; | 362 return true; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 378 } | 394 } |
| 379 | 395 |
| 380 // Stop if we found the next valid logical text metrics object. | 396 // Stop if we found the next valid logical text metrics object. |
| 381 return true; | 397 return true; |
| 382 } | 398 } |
| 383 | 399 |
| 384 ASSERT_NOT_REACHED(); | 400 ASSERT_NOT_REACHED(); |
| 385 return true; | 401 return true; |
| 386 } | 402 } |
| 387 | 403 |
| 388 bool SVGTextLayoutEngine::currentVisualCharacterMetrics(SVGInlineTextBox* textBo x, const Vector<SVGTextMetrics>& visualMetricsValues, SVGTextMetrics& visualMetr ics) | |
| 389 { | |
| 390 ASSERT(!visualMetricsValues.isEmpty()); | |
| 391 unsigned textMetricsSize = visualMetricsValues.size(); | |
| 392 unsigned boxStart = textBox->start(); | |
| 393 unsigned boxLength = textBox->len(); | |
| 394 | |
| 395 while (m_visualMetricsListOffset < textMetricsSize) { | |
| 396 // Advance to text box start location. | |
| 397 if (m_visualCharacterOffset < boxStart) { | |
| 398 advanceToNextVisualCharacter(visualMetricsValues[m_visualMetricsList Offset]); | |
| 399 continue; | |
| 400 } | |
| 401 | |
| 402 // Stop if we've finished processing this text box. | |
| 403 if (m_visualCharacterOffset >= boxStart + boxLength) | |
| 404 return false; | |
| 405 | |
| 406 visualMetrics = visualMetricsValues[m_visualMetricsListOffset]; | |
| 407 return true; | |
| 408 } | |
| 409 | |
| 410 return false; | |
| 411 } | |
| 412 | |
| 413 void SVGTextLayoutEngine::advanceToNextLogicalCharacter(const SVGTextMetrics& lo gicalMetrics) | 404 void SVGTextLayoutEngine::advanceToNextLogicalCharacter(const SVGTextMetrics& lo gicalMetrics) |
| 414 { | 405 { |
| 415 ++m_logicalMetricsListOffset; | 406 ++m_logicalMetricsListOffset; |
| 416 m_logicalCharacterOffset += logicalMetrics.length(); | 407 m_logicalCharacterOffset += logicalMetrics.length(); |
| 417 } | 408 } |
| 418 | 409 |
| 419 void SVGTextLayoutEngine::advanceToNextVisualCharacter(const SVGTextMetrics& vis ualMetrics) | |
| 420 { | |
| 421 ++m_visualMetricsListOffset; | |
| 422 m_visualCharacterOffset += visualMetrics.length(); | |
| 423 } | |
| 424 | |
| 425 void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, cons t LayoutSVGInlineText& text, const ComputedStyle& style) | 410 void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, cons t LayoutSVGInlineText& text, const ComputedStyle& style) |
| 426 { | 411 { |
| 427 if (m_inPathLayout && !m_textPathCalculator) | 412 if (m_inPathLayout && !m_textPathCalculator) |
| 428 return; | 413 return; |
| 429 | 414 |
| 430 LayoutObject* textParent = text.parent(); | 415 LayoutObject* textParent = text.parent(); |
| 431 bool definesTextLength = textParent ? parentDefinesTextLength(textParent) : false; | 416 bool definesTextLength = textParent ? parentDefinesTextLength(textParent) : false; |
| 432 | 417 |
| 433 const SVGComputedStyle& svgStyle = style.svgStyle(); | 418 const SVGComputedStyle& svgStyle = style.svgStyle(); |
| 434 | 419 |
| 435 m_visualMetricsListOffset = 0; | 420 // Find the start of the current text box in the metrics list. |
| 436 m_visualCharacterOffset = 0; | 421 updateMetricsIterator(text, textBox->start()); |
|
pdr.
2015/05/27 03:11:18
Do you think something like m_visualMetricsIterato
fs
2015/05/27 12:53:13
Done.
| |
| 437 | |
| 438 const Vector<SVGTextMetrics>& visualMetricsValues = text.layoutAttributes()- >textMetricsValues(); | |
| 439 ASSERT(!visualMetricsValues.isEmpty()); | |
| 440 | 422 |
| 441 const Font& font = style.font(); | 423 const Font& font = style.font(); |
| 442 | 424 |
| 443 SVGTextLayoutEngineSpacing spacingLayout(font, style.effectiveZoom()); | 425 SVGTextLayoutEngineSpacing spacingLayout(font, style.effectiveZoom()); |
| 444 SVGTextLayoutEngineBaseline baselineLayout(font, style.effectiveZoom()); | 426 SVGTextLayoutEngineBaseline baselineLayout(font, style.effectiveZoom()); |
| 445 | 427 |
| 446 bool didStartTextFragment = false; | 428 bool didStartTextFragment = false; |
| 447 bool applySpacingToNextCharacter = false; | 429 bool applySpacingToNextCharacter = false; |
| 448 | 430 |
| 449 float lastAngle = 0; | 431 float lastAngle = 0; |
| 450 float baselineShift = baselineLayout.calculateBaselineShift(style); | 432 float baselineShift = baselineLayout.calculateBaselineShift(style); |
| 451 baselineShift -= baselineLayout.calculateAlignmentBaselineShift(m_isVertical Text, &text); | 433 baselineShift -= baselineLayout.calculateAlignmentBaselineShift(m_isVertical Text, &text); |
| 452 | 434 |
| 453 // Main layout algorithm. | 435 // Main layout algorithm. |
| 454 while (true) { | 436 const unsigned boxEndOffset = textBox->start() + textBox->len(); |
| 455 // Find the start of the current text box in this list, respecting ligat ures. | 437 while (m_visualMetricsIterator.characterOffset() < boxEndOffset) { |
| 456 SVGTextMetrics visualMetrics(SVGTextMetrics::SkippedSpaceMetrics); | 438 const SVGTextMetrics& visualMetrics = m_visualMetricsIterator.metrics(); |
| 457 if (!currentVisualCharacterMetrics(textBox, visualMetricsValues, visualM etrics)) | |
| 458 break; | |
| 459 | |
| 460 if (visualMetrics.isEmpty()) { | 439 if (visualMetrics.isEmpty()) { |
| 461 advanceToNextVisualCharacter(visualMetrics); | 440 m_visualMetricsIterator.next(); |
| 462 continue; | 441 continue; |
| 463 } | 442 } |
| 464 | 443 |
| 465 SVGTextLayoutAttributes* logicalAttributes = 0; | 444 SVGTextLayoutAttributes* logicalAttributes = 0; |
| 466 if (!currentLogicalCharacterAttributes(logicalAttributes)) | 445 if (!currentLogicalCharacterAttributes(logicalAttributes)) |
| 467 break; | 446 break; |
| 468 | 447 |
| 469 ASSERT(logicalAttributes); | 448 ASSERT(logicalAttributes); |
| 470 SVGTextMetrics logicalMetrics(SVGTextMetrics::SkippedSpaceMetrics); | 449 SVGTextMetrics logicalMetrics(SVGTextMetrics::SkippedSpaceMetrics); |
| 471 if (!currentLogicalCharacterMetrics(logicalAttributes, logicalMetrics)) | 450 if (!currentLogicalCharacterMetrics(logicalAttributes, logicalMetrics)) |
| 472 break; | 451 break; |
| 473 | 452 |
| 474 SVGCharacterDataMap& characterDataMap = logicalAttributes->characterData Map(); | 453 SVGCharacterDataMap& characterDataMap = logicalAttributes->characterData Map(); |
| 475 SVGCharacterData data; | 454 SVGCharacterData data; |
| 476 SVGCharacterDataMap::iterator it = characterDataMap.find(m_logicalCharac terOffset + 1); | 455 SVGCharacterDataMap::iterator it = characterDataMap.find(m_logicalCharac terOffset + 1); |
| 477 if (it != characterDataMap.end()) | 456 if (it != characterDataMap.end()) |
| 478 data = it->value; | 457 data = it->value; |
| 479 | 458 |
| 480 float x = data.x; | 459 float x = data.x; |
| 481 float y = data.y; | 460 float y = data.y; |
| 482 | 461 |
| 483 // When we've advanced to the box start offset, determine using the orig inal x/y values, | 462 // When we've advanced to the box start offset, determine using the orig inal x/y values, |
| 484 // whether this character starts a new text chunk, before doing any furt her processing. | 463 // whether this character starts a new text chunk, before doing any furt her processing. |
| 485 if (m_visualCharacterOffset == textBox->start()) | 464 if (m_visualMetricsIterator.characterOffset() == textBox->start()) |
| 486 textBox->setStartsNewTextChunk(logicalAttributes->context()->charact erStartsNewTextChunk(m_logicalCharacterOffset)); | 465 textBox->setStartsNewTextChunk(logicalAttributes->context()->charact erStartsNewTextChunk(m_logicalCharacterOffset)); |
| 487 | 466 |
| 488 float angle = SVGTextLayoutAttributes::isEmptyValue(data.rotate) ? 0 : d ata.rotate; | 467 float angle = SVGTextLayoutAttributes::isEmptyValue(data.rotate) ? 0 : d ata.rotate; |
| 489 | 468 |
| 490 // Calculate glyph orientation angle. | 469 // Calculate glyph orientation angle. |
| 491 UChar currentCharacter = text.characterAt(m_visualCharacterOffset); | 470 UChar currentCharacter = text.characterAt(m_visualMetricsIterator.charac terOffset()); |
| 492 float orientationAngle = baselineLayout.calculateGlyphOrientationAngle(m _isVerticalText, svgStyle, currentCharacter); | 471 float orientationAngle = baselineLayout.calculateGlyphOrientationAngle(m _isVerticalText, svgStyle, currentCharacter); |
| 493 | 472 |
| 494 // Calculate glyph advance & x/y orientation shifts. | 473 // Calculate glyph advance & x/y orientation shifts. |
| 495 float xOrientationShift = 0; | 474 float xOrientationShift = 0; |
| 496 float yOrientationShift = 0; | 475 float yOrientationShift = 0; |
| 497 float glyphAdvance = baselineLayout.calculateGlyphAdvanceAndOrientation( m_isVerticalText, visualMetrics, orientationAngle, xOrientationShift, yOrientati onShift); | 476 float glyphAdvance = baselineLayout.calculateGlyphAdvanceAndOrientation( m_isVerticalText, visualMetrics, orientationAngle, xOrientationShift, yOrientati onShift); |
| 498 | 477 |
| 499 // Assign current text position to x/y values, if needed. | 478 // Assign current text position to x/y values, if needed. |
| 500 updateCharacterPositionIfNeeded(x, y); | 479 updateCharacterPositionIfNeeded(x, y); |
| 501 | 480 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 534 | 513 |
| 535 // Calculate current offset along path. | 514 // Calculate current offset along path. |
| 536 textPathOffset = m_textPathCurrentOffset + scaledGlyphAdvance / 2; | 515 textPathOffset = m_textPathCurrentOffset + scaledGlyphAdvance / 2; |
| 537 | 516 |
| 538 // Move to next character. | 517 // Move to next character. |
| 539 m_textPathCurrentOffset += scaledGlyphAdvance + m_textPathSpacing + spacing * m_textPathScaling; | 518 m_textPathCurrentOffset += scaledGlyphAdvance + m_textPathSpacing + spacing * m_textPathScaling; |
| 540 | 519 |
| 541 // Skip character, if we're before the path. | 520 // Skip character, if we're before the path. |
| 542 if (textPathOffset < 0) { | 521 if (textPathOffset < 0) { |
| 543 advanceToNextLogicalCharacter(logicalMetrics); | 522 advanceToNextLogicalCharacter(logicalMetrics); |
| 544 advanceToNextVisualCharacter(visualMetrics); | 523 m_visualMetricsIterator.next(); |
| 545 continue; | 524 continue; |
| 546 } | 525 } |
| 547 | 526 |
| 548 // Stop processing, if the next character lies behind the path. | 527 // Stop processing, if the next character lies behind the path. |
| 549 if (textPathOffset > m_textPathLength) | 528 if (textPathOffset > m_textPathLength) |
| 550 break; | 529 break; |
| 551 | 530 |
| 552 FloatPoint point; | 531 FloatPoint point; |
| 553 bool ok = m_textPathCalculator->pointAndNormalAtLength(textPathOffse t, point, angle); | 532 bool ok = m_textPathCalculator->pointAndNormalAtLength(textPathOffse t, point, angle); |
| 554 ASSERT_UNUSED(ok, ok); | 533 ASSERT_UNUSED(ok, ok); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 569 y += m_dy; | 548 y += m_dy; |
| 570 } | 549 } |
| 571 | 550 |
| 572 // Determine whether we have to start a new fragment. | 551 // Determine whether we have to start a new fragment. |
| 573 bool shouldStartNewFragment = m_dx || m_dy || m_isVerticalText || m_inPa thLayout || angle || angle != lastAngle | 552 bool shouldStartNewFragment = m_dx || m_dy || m_isVerticalText || m_inPa thLayout || angle || angle != lastAngle |
| 574 || orientationAngle || applySpacingToNextCharacter || definesTextLen gth; | 553 || orientationAngle || applySpacingToNextCharacter || definesTextLen gth; |
| 575 | 554 |
| 576 // If we already started a fragment, close it now. | 555 // If we already started a fragment, close it now. |
| 577 if (didStartTextFragment && shouldStartNewFragment) { | 556 if (didStartTextFragment && shouldStartNewFragment) { |
| 578 applySpacingToNextCharacter = false; | 557 applySpacingToNextCharacter = false; |
| 579 recordTextFragment(textBox, visualMetricsValues); | 558 recordTextFragment(textBox); |
| 580 } | 559 } |
| 581 | 560 |
| 582 // Eventually start a new fragment, if not yet done. | 561 // Eventually start a new fragment, if not yet done. |
| 583 if (!didStartTextFragment || shouldStartNewFragment) { | 562 if (!didStartTextFragment || shouldStartNewFragment) { |
| 584 ASSERT(!m_currentTextFragment.characterOffset); | 563 ASSERT(!m_currentTextFragment.characterOffset); |
| 585 ASSERT(!m_currentTextFragment.length); | 564 ASSERT(!m_currentTextFragment.length); |
| 586 | 565 |
| 587 didStartTextFragment = true; | 566 didStartTextFragment = true; |
| 588 m_currentTextFragment.characterOffset = m_visualCharacterOffset; | 567 m_currentTextFragment.characterOffset = m_visualMetricsIterator.char acterOffset(); |
| 589 m_currentTextFragment.metricsListOffset = m_visualMetricsListOffset; | 568 m_currentTextFragment.metricsListOffset = m_visualMetricsIterator.me tricsListOffset(); |
| 590 m_currentTextFragment.x = x; | 569 m_currentTextFragment.x = x; |
| 591 m_currentTextFragment.y = y; | 570 m_currentTextFragment.y = y; |
| 592 | 571 |
| 593 // Build fragment transformation. | 572 // Build fragment transformation. |
| 594 if (angle) | 573 if (angle) |
| 595 m_currentTextFragment.transform.rotate(angle); | 574 m_currentTextFragment.transform.rotate(angle); |
| 596 | 575 |
| 597 if (xOrientationShift || yOrientationShift) | 576 if (xOrientationShift || yOrientationShift) |
| 598 m_currentTextFragment.transform.translate(xOrientationShift, yOr ientationShift); | 577 m_currentTextFragment.transform.translate(xOrientationShift, yOr ientationShift); |
| 599 | 578 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 622 | 601 |
| 623 if (m_isVerticalText) | 602 if (m_isVerticalText) |
| 624 xNew -= baselineShift; | 603 xNew -= baselineShift; |
| 625 else | 604 else |
| 626 yNew += baselineShift; | 605 yNew += baselineShift; |
| 627 | 606 |
| 628 updateCurrentTextPosition(xNew, yNew, glyphAdvance + spacing); | 607 updateCurrentTextPosition(xNew, yNew, glyphAdvance + spacing); |
| 629 } | 608 } |
| 630 | 609 |
| 631 advanceToNextLogicalCharacter(logicalMetrics); | 610 advanceToNextLogicalCharacter(logicalMetrics); |
| 632 advanceToNextVisualCharacter(visualMetrics); | 611 m_visualMetricsIterator.next(); |
| 633 lastAngle = angle; | 612 lastAngle = angle; |
| 634 } | 613 } |
| 635 | 614 |
| 636 if (!didStartTextFragment) | 615 if (!didStartTextFragment) |
| 637 return; | 616 return; |
| 638 | 617 |
| 639 // Close last open fragment, if needed. | 618 // Close last open fragment, if needed. |
| 640 recordTextFragment(textBox, visualMetricsValues); | 619 recordTextFragment(textBox); |
| 641 } | 620 } |
| 642 | 621 |
| 643 } | 622 } |
| OLD | NEW |