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 |