OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) |
3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ight reserved. | 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ight reserved. |
4 * Copyright (C) 2010 Google Inc. All rights reserved. | 4 * Copyright (C) 2010 Google Inc. All rights reserved. |
5 * | 5 * |
6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
9 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
10 * | 10 * |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 if (!runWithNextObject->m_lineLayoutItem.isOutOfFlowPositioned() && !run
WithNextObject->m_box->isLineBreak()) { | 420 if (!runWithNextObject->m_lineLayoutItem.isOutOfFlowPositioned() && !run
WithNextObject->m_box->isLineBreak()) { |
421 nextObject = runWithNextObject->m_lineLayoutItem.layoutObject(); | 421 nextObject = runWithNextObject->m_lineLayoutItem.layoutObject(); |
422 break; | 422 break; |
423 } | 423 } |
424 } | 424 } |
425 layoutRubyRun->getOverhang(lineInfo.isFirstLine(), layoutRubyRun->style()->i
sLeftToRightDirection() ? previousObject : nextObject, layoutRubyRun->style()->i
sLeftToRightDirection() ? nextObject : previousObject, startOverhang, endOverhan
g); | 425 layoutRubyRun->getOverhang(lineInfo.isFirstLine(), layoutRubyRun->style()->i
sLeftToRightDirection() ? previousObject : nextObject, layoutRubyRun->style()->i
sLeftToRightDirection() ? nextObject : previousObject, startOverhang, endOverhan
g); |
426 setMarginStartForChild(*layoutRubyRun, LayoutUnit(-startOverhang)); | 426 setMarginStartForChild(*layoutRubyRun, LayoutUnit(-startOverhang)); |
427 setMarginEndForChild(*layoutRubyRun, LayoutUnit(-endOverhang)); | 427 setMarginEndForChild(*layoutRubyRun, LayoutUnit(-endOverhang)); |
428 } | 428 } |
429 | 429 |
| 430 static inline size_t findWordMeasurement(LineLayoutText layoutText, int offset, |
| 431 WordMeasurements& wordMeasurements, size_t lastIndex) |
| 432 { |
| 433 // In LTR, lastIndex should match since the order of BidiRun (visual) and |
| 434 // WordMeasurement (logical) are the same. |
| 435 size_t size = wordMeasurements.size(); |
| 436 if (lastIndex < size) { |
| 437 const WordMeasurement& wordMeasurement = wordMeasurements[lastIndex]; |
| 438 if (wordMeasurement.layoutText == layoutText && wordMeasurement.startOff
set == offset) |
| 439 return lastIndex; |
| 440 } |
| 441 |
| 442 // In RTL, scan the whole array because they are not the same. |
| 443 for (size_t i = 0; i < size; ++i) { |
| 444 const WordMeasurement& wordMeasurement = wordMeasurements[i]; |
| 445 if (wordMeasurement.layoutText != layoutText) |
| 446 continue; |
| 447 if (wordMeasurement.startOffset == offset) |
| 448 return i; |
| 449 if (wordMeasurement.startOffset > offset) |
| 450 break; |
| 451 } |
| 452 |
| 453 // In RTL with space collpasing or in LTR/RTL mixed lines, there can be no |
| 454 // matches because spaces are handled differently in BidiRun and |
| 455 // WordMeasurement. This can cause slight performance hit and slight |
| 456 // differences in glyph positions since we re-measure the whole run. |
| 457 return size; |
| 458 } |
| 459 |
430 static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* ru
n, LineLayoutText layoutText, LayoutUnit xPos, const LineInfo& lineInfo, | 460 static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* ru
n, LineLayoutText layoutText, LayoutUnit xPos, const LineInfo& lineInfo, |
431 GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& ver
ticalPositionCache, WordMeasurements& wordMeasurements) | 461 GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& ver
ticalPositionCache, WordMeasurements& wordMeasurements, |
| 462 size_t& wordMeasurementsIndex) |
432 { | 463 { |
433 HashSet<const SimpleFontData*> fallbackFonts; | 464 HashSet<const SimpleFontData*> fallbackFonts; |
434 GlyphOverflow glyphOverflow; | 465 GlyphOverflow glyphOverflow; |
435 | 466 |
436 const Font& font = layoutText.style(lineInfo.isFirstLine())->font(); | 467 const Font& font = layoutText.style(lineInfo.isFirstLine())->font(); |
437 | 468 |
438 LayoutUnit hyphenWidth; | 469 LayoutUnit hyphenWidth; |
439 if (toInlineTextBox(run->m_box)->hasHyphen()) | 470 if (toInlineTextBox(run->m_box)->hasHyphen()) |
440 hyphenWidth = LayoutUnit(layoutText.hyphenWidth(font, run->direction()))
; | 471 hyphenWidth = LayoutUnit(layoutText.hyphenWidth(font, run->direction()))
; |
441 | 472 |
442 float measuredWidth = 0; | 473 float measuredWidth = 0; |
443 FloatRect glyphBounds; | 474 FloatRect glyphBounds; |
444 | 475 |
445 bool kerningIsEnabled = font.getFontDescription().getTypesettingFeatures() &
Kerning; | 476 bool kerningIsEnabled = font.getFontDescription().getTypesettingFeatures() &
Kerning; |
446 | 477 |
447 #if OS(MACOSX) | 478 #if OS(MACOSX) |
448 // FIXME: Having any font feature settings enabled can lead to selection gap
s on | 479 // FIXME: Having any font feature settings enabled can lead to selection gap
s on |
449 // Chromium-mac. https://bugs.webkit.org/show_bug.cgi?id=113418 | 480 // Chromium-mac. https://bugs.webkit.org/show_bug.cgi?id=113418 |
450 bool canUseCachedWordMeasurements = font.canShapeWordByWord() && !font.getFo
ntDescription().featureSettings(); | 481 bool canUseCachedWordMeasurements = font.canShapeWordByWord() && !font.getFo
ntDescription().featureSettings(); |
451 #else | 482 #else |
452 bool canUseCachedWordMeasurements = font.canShapeWordByWord(); | 483 bool canUseCachedWordMeasurements = font.canShapeWordByWord(); |
453 #endif | 484 #endif |
454 | 485 |
455 if (canUseCachedWordMeasurements) { | 486 if (canUseCachedWordMeasurements) { |
456 int lastEndOffset = run->m_start; | 487 int lastEndOffset = run->m_start; |
457 for (size_t i = 0, size = wordMeasurements.size(); i < size && lastEndOf
fset < run->m_stop; ++i) { | 488 size_t i = findWordMeasurement(layoutText, lastEndOffset, wordMeasuremen
ts, wordMeasurementsIndex); |
| 489 for (size_t size = wordMeasurements.size(); i < size && lastEndOffset <
run->m_stop; ++i) { |
458 const WordMeasurement& wordMeasurement = wordMeasurements[i]; | 490 const WordMeasurement& wordMeasurement = wordMeasurements[i]; |
459 if (wordMeasurement.startOffset == wordMeasurement.endOffset) | 491 if (wordMeasurement.startOffset == wordMeasurement.endOffset) |
460 continue; | 492 continue; |
461 if (wordMeasurement.layoutText != layoutText || wordMeasurement.star
tOffset != lastEndOffset || wordMeasurement.endOffset > run->m_stop) | 493 if (wordMeasurement.layoutText != layoutText || wordMeasurement.star
tOffset != lastEndOffset || wordMeasurement.endOffset > run->m_stop) |
462 continue; | 494 break; |
463 | 495 |
464 lastEndOffset = wordMeasurement.endOffset; | 496 lastEndOffset = wordMeasurement.endOffset; |
465 if (kerningIsEnabled && lastEndOffset == run->m_stop) { | 497 if (kerningIsEnabled && lastEndOffset == run->m_stop) { |
466 int wordLength = lastEndOffset - wordMeasurement.startOffset; | 498 int wordLength = lastEndOffset - wordMeasurement.startOffset; |
467 measuredWidth += layoutText.width(wordMeasurement.startOffset, w
ordLength, xPos, run->direction(), lineInfo.isFirstLine()); | 499 measuredWidth += layoutText.width(wordMeasurement.startOffset, w
ordLength, xPos, run->direction(), lineInfo.isFirstLine()); |
468 if (i > 0 && wordLength == 1 && layoutText.characterAt(wordMeasu
rement.startOffset) == ' ') | 500 if (i > 0 && wordLength == 1 && layoutText.characterAt(wordMeasu
rement.startOffset) == ' ') |
469 measuredWidth += layoutText.style()->wordSpacing(); | 501 measuredWidth += layoutText.style()->wordSpacing(); |
470 } else { | 502 } else { |
471 FloatRect wordGlyphBounds = wordMeasurement.glyphBounds; | 503 FloatRect wordGlyphBounds = wordMeasurement.glyphBounds; |
472 wordGlyphBounds.move(measuredWidth, 0); | 504 wordGlyphBounds.move(measuredWidth, 0); |
473 glyphBounds.unite(wordGlyphBounds); | 505 glyphBounds.unite(wordGlyphBounds); |
474 measuredWidth += wordMeasurement.width; | 506 measuredWidth += wordMeasurement.width; |
475 } | 507 } |
476 if (!wordMeasurement.fallbackFonts.isEmpty()) { | 508 if (!wordMeasurement.fallbackFonts.isEmpty()) { |
477 HashSet<const SimpleFontData*>::const_iterator end = wordMeasure
ment.fallbackFonts.end(); | 509 HashSet<const SimpleFontData*>::const_iterator end = wordMeasure
ment.fallbackFonts.end(); |
478 for (HashSet<const SimpleFontData*>::const_iterator it = wordMea
surement.fallbackFonts.begin(); it != end; ++it) | 510 for (HashSet<const SimpleFontData*>::const_iterator it = wordMea
surement.fallbackFonts.begin(); it != end; ++it) |
479 fallbackFonts.add(*it); | 511 fallbackFonts.add(*it); |
480 } | 512 } |
481 } | 513 } |
| 514 wordMeasurementsIndex = i; |
482 if (lastEndOffset != run->m_stop) { | 515 if (lastEndOffset != run->m_stop) { |
483 // If we don't have enough cached data, we'll measure the run again. | 516 // If we don't have enough cached data, we'll measure the run again. |
484 canUseCachedWordMeasurements = false; | 517 canUseCachedWordMeasurements = false; |
485 fallbackFonts.clear(); | 518 fallbackFonts.clear(); |
486 } | 519 } |
487 } | 520 } |
488 | 521 |
489 // Don't put this into 'else' part of the above 'if' because canUseCachedWor
dMeasurements may be modified in the 'if' block. | 522 // Don't put this into 'else' part of the above 'if' because canUseCachedWor
dMeasurements may be modified in the 'if' block. |
490 if (!canUseCachedWordMeasurements) | 523 if (!canUseCachedWordMeasurements) |
491 measuredWidth = layoutText.width(run->m_start, run->m_stop - run->m_star
t, xPos, run->direction(), lineInfo.isFirstLine(), &fallbackFonts, &glyphBounds)
; | 524 measuredWidth = layoutText.width(run->m_start, run->m_stop - run->m_star
t, xPos, run->direction(), lineInfo.isFirstLine(), &fallbackFonts, &glyphBounds)
; |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 WordMeasurements& wordMeasurements) | 646 WordMeasurements& wordMeasurements) |
614 { | 647 { |
615 bool needsWordSpacing = true; | 648 bool needsWordSpacing = true; |
616 LayoutUnit totalLogicalWidth = lineBox->getFlowSpacingLogicalWidth(); | 649 LayoutUnit totalLogicalWidth = lineBox->getFlowSpacingLogicalWidth(); |
617 bool isAfterExpansion = true; | 650 bool isAfterExpansion = true; |
618 ExpansionOpportunities expansions; | 651 ExpansionOpportunities expansions; |
619 LayoutObject* previousObject = nullptr; | 652 LayoutObject* previousObject = nullptr; |
620 TextJustify textJustify = style()->getTextJustify(); | 653 TextJustify textJustify = style()->getTextJustify(); |
621 | 654 |
622 BidiRun* r = firstRun; | 655 BidiRun* r = firstRun; |
| 656 size_t wordMeasurementsIndex = 0; |
623 for (; r; r = r->next()) { | 657 for (; r; r = r->next()) { |
624 if (!r->m_box || r->m_lineLayoutItem.isOutOfFlowPositioned() || r->m_box
->isLineBreak()) { | 658 if (!r->m_box || r->m_lineLayoutItem.isOutOfFlowPositioned() || r->m_box
->isLineBreak()) { |
625 continue; // Positioned objects are only participating to figure out
their | 659 continue; // Positioned objects are only participating to figure out
their |
626 // correct static x position. They have no effect on the width. | 660 // correct static x position. They have no effect on the width. |
627 // Similarly, line break boxes have no effect on the width. | 661 // Similarly, line break boxes have no effect on the width. |
628 } | 662 } |
629 if (r->m_lineLayoutItem.isText()) { | 663 if (r->m_lineLayoutItem.isText()) { |
630 LineLayoutText rt(r->m_lineLayoutItem); | 664 LineLayoutText rt(r->m_lineLayoutItem); |
631 if (textAlign == JUSTIFY && r != trailingSpaceRun && textJustify !=
TextJustifyNone) { | 665 if (textAlign == JUSTIFY && r != trailingSpaceRun && textJustify !=
TextJustifyNone) { |
632 if (!isAfterExpansion) | 666 if (!isAfterExpansion) |
633 toInlineTextBox(r->m_box)->setCanHaveLeadingExpansion(true); | 667 toInlineTextBox(r->m_box)->setCanHaveLeadingExpansion(true); |
634 expansions.addRunWithExpansions(*r, isAfterExpansion, textJustif
y); | 668 expansions.addRunWithExpansions(*r, isAfterExpansion, textJustif
y); |
635 } | 669 } |
636 | 670 |
637 if (rt.textLength()) { | 671 if (rt.textLength()) { |
638 if (!r->m_start && needsWordSpacing && isSpaceOrNewline(rt.chara
cterAt(r->m_start))) | 672 if (!r->m_start && needsWordSpacing && isSpaceOrNewline(rt.chara
cterAt(r->m_start))) |
639 totalLogicalWidth += rt.style(lineInfo.isFirstLine())->font(
).getFontDescription().wordSpacing(); | 673 totalLogicalWidth += rt.style(lineInfo.isFirstLine())->font(
).getFontDescription().wordSpacing(); |
640 needsWordSpacing = !isSpaceOrNewline(rt.characterAt(r->m_stop -
1)); | 674 needsWordSpacing = !isSpaceOrNewline(rt.characterAt(r->m_stop -
1)); |
641 } | 675 } |
642 | 676 |
643 setLogicalWidthForTextRun(lineBox, r, rt, totalLogicalWidth, lineInf
o, textBoxDataMap, verticalPositionCache, wordMeasurements); | 677 setLogicalWidthForTextRun(lineBox, r, rt, totalLogicalWidth, lineInf
o, textBoxDataMap, verticalPositionCache, wordMeasurements, wordMeasurementsInde
x); |
644 } else { | 678 } else { |
645 isAfterExpansion = false; | 679 isAfterExpansion = false; |
646 if (!r->m_lineLayoutItem.isLayoutInline()) { | 680 if (!r->m_lineLayoutItem.isLayoutInline()) { |
647 LayoutBox* layoutBox = toLayoutBox(r->m_lineLayoutItem.layoutObj
ect()); | 681 LayoutBox* layoutBox = toLayoutBox(r->m_lineLayoutItem.layoutObj
ect()); |
648 if (layoutBox->isRubyRun()) | 682 if (layoutBox->isRubyRun()) |
649 setMarginsForRubyRun(r, toLayoutRubyRun(layoutBox), previous
Object, lineInfo); | 683 setMarginsForRubyRun(r, toLayoutRubyRun(layoutBox), previous
Object, lineInfo); |
650 r->m_box->setLogicalWidth(logicalWidthForChild(*layoutBox)); | 684 r->m_box->setLogicalWidth(logicalWidthForChild(*layoutBox)); |
651 totalLogicalWidth += marginStartForChild(*layoutBox) + marginEnd
ForChild(*layoutBox); | 685 totalLogicalWidth += marginStartForChild(*layoutBox) + marginEnd
ForChild(*layoutBox); |
652 needsWordSpacing = true; | 686 needsWordSpacing = true; |
653 } | 687 } |
(...skipping 1427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2081 bool LayoutBlockFlow::paintedOutputOfObjectHasNoEffectRegardlessOfSize() const | 2115 bool LayoutBlockFlow::paintedOutputOfObjectHasNoEffectRegardlessOfSize() const |
2082 { | 2116 { |
2083 // LayoutBlockFlow is in charge of paint invalidation of the first line. | 2117 // LayoutBlockFlow is in charge of paint invalidation of the first line. |
2084 if (firstLineBox()) | 2118 if (firstLineBox()) |
2085 return false; | 2119 return false; |
2086 | 2120 |
2087 return LayoutBlock::paintedOutputOfObjectHasNoEffectRegardlessOfSize(); | 2121 return LayoutBlock::paintedOutputOfObjectHasNoEffectRegardlessOfSize(); |
2088 } | 2122 } |
2089 | 2123 |
2090 } // namespace blink | 2124 } // namespace blink |
OLD | NEW |