| OLD | NEW |
| 1 /* | 1 /* |
| 2 * (C) 1999 Lars Knoll (knoll@kde.org) | 2 * (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 2000 Dirk Mueller (mueller@kde.org) | 3 * (C) 2000 Dirk Mueller (mueller@kde.org) |
| 4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ights reserved. | 4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ights 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 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 // subpixel boundaries on the x-axis and thus there is no reason to | 494 // subpixel boundaries on the x-axis and thus there is no reason to |
| 495 // snap the x value. We still round the y-axis to ensure consistent | 495 // snap the x value. We still round the y-axis to ensure consistent |
| 496 // line heights. | 496 // line heights. |
| 497 LayoutPoint adjustedPaintOffset = RuntimeEnabledFeatures::subpixelFontScalin
gEnabled() | 497 LayoutPoint adjustedPaintOffset = RuntimeEnabledFeatures::subpixelFontScalin
gEnabled() |
| 498 ? LayoutPoint(paintOffset.x(), paintOffset.y().round()) | 498 ? LayoutPoint(paintOffset.x(), paintOffset.y().round()) |
| 499 : roundedIntPoint(paintOffset); | 499 : roundedIntPoint(paintOffset); |
| 500 | 500 |
| 501 if (logicalStart >= paintEnd || logicalStart + logicalExtent <= paintStart) | 501 if (logicalStart >= paintEnd || logicalStart + logicalExtent <= paintStart) |
| 502 return; | 502 return; |
| 503 | 503 |
| 504 // Determine whether or not we're selected. | |
| 505 bool haveSelection = selectionState() != RenderObject::SelectionNone; | |
| 506 if (!haveSelection && paintInfo.phase == PaintPhaseSelection) | |
| 507 // When only painting the selection, don't bother to paint if there is n
one. | |
| 508 return; | |
| 509 | |
| 510 if (m_truncation != cNoTruncation) { | 504 if (m_truncation != cNoTruncation) { |
| 511 if (renderer().containingBlock()->style()->isLeftToRightDirection() != i
sLeftToRightDirection()) { | 505 if (renderer().containingBlock()->style()->isLeftToRightDirection() != i
sLeftToRightDirection()) { |
| 512 // Make the visible fragment of text hug the edge closest to the res
t of the run by moving the origin | 506 // Make the visible fragment of text hug the edge closest to the res
t of the run by moving the origin |
| 513 // at which we start drawing text. | 507 // at which we start drawing text. |
| 514 // e.g. In the case of LTR text truncated in an RTL Context, the cor
rect behavior is: | 508 // e.g. In the case of LTR text truncated in an RTL Context, the cor
rect behavior is: |
| 515 // |Hello|CBA| -> |...He|CBA| | 509 // |Hello|CBA| -> |...He|CBA| |
| 516 // In order to draw the fragment "He" aligned to the right edge of i
t's box, we need to start drawing | 510 // In order to draw the fragment "He" aligned to the right edge of i
t's box, we need to start drawing |
| 517 // farther to the right. | 511 // farther to the right. |
| 518 // NOTE: WebKit's behavior differs from that of IE which appears to
just overlay the ellipsis on top of the | 512 // NOTE: WebKit's behavior differs from that of IE which appears to
just overlay the ellipsis on top of the |
| 519 // truncated string i.e. |Hello|CBA| -> |...lo|CBA| | 513 // truncated string i.e. |Hello|CBA| -> |...lo|CBA| |
| 520 LayoutUnit widthOfVisibleText = renderer().width(m_start, m_truncati
on, textPos(), isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle()); | 514 LayoutUnit widthOfVisibleText = renderer().width(m_start, m_truncati
on, textPos(), isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle()); |
| 521 LayoutUnit widthOfHiddenText = m_logicalWidth - widthOfVisibleText; | 515 LayoutUnit widthOfHiddenText = m_logicalWidth - widthOfVisibleText; |
| 522 // FIXME: The hit testing logic also needs to take this translation
into account. | 516 // FIXME: The hit testing logic also needs to take this translation
into account. |
| 523 LayoutSize truncationOffset(isLeftToRightDirection() ? widthOfHidden
Text : -widthOfHiddenText, 0); | 517 LayoutSize truncationOffset(isLeftToRightDirection() ? widthOfHidden
Text : -widthOfHiddenText, 0); |
| 524 adjustedPaintOffset.move(truncationOffset); | 518 adjustedPaintOffset.move(truncationOffset); |
| 525 } | 519 } |
| 526 } | 520 } |
| 527 | 521 |
| 528 GraphicsContext* context = paintInfo.context; | 522 GraphicsContext* context = paintInfo.context; |
| 529 RenderStyle* styleToUse = renderer().style(isFirstLineStyle()); | 523 RenderStyle* styleToUse = renderer().style(isFirstLineStyle()); |
| 530 | 524 |
| 531 FloatPoint boxOrigin = locationIncludingFlipping(); | 525 FloatPoint boxOrigin = locationIncludingFlipping(); |
| 532 boxOrigin.move(adjustedPaintOffset.x().toFloat(), adjustedPaintOffset.y().to
Float()); | 526 boxOrigin.move(adjustedPaintOffset.x().toFloat(), adjustedPaintOffset.y().to
Float()); |
| 533 FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), logicalHeight())); | 527 FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), logicalHeight())); |
| 534 | 528 |
| 535 // Determine whether or not we have composition underlines to draw. | 529 // Determine whether or not we have composition underlines to draw. |
| 536 bool containsComposition = renderer().node() && renderer().frame()->inputMet
hodController().compositionNode() == renderer().node(); | 530 bool containsComposition = renderer().node() && renderer().frame()->inputMet
hodController().compositionNode() == renderer().node(); |
| 537 bool useCustomUnderlines = containsComposition && renderer().frame()->inputM
ethodController().compositionUsesCustomUnderlines(); | 531 bool useCustomUnderlines = containsComposition && renderer().frame()->inputM
ethodController().compositionUsesCustomUnderlines(); |
| 538 | 532 |
| 533 bool haveSelection = selectionState() != RenderObject::SelectionNone; |
| 534 |
| 539 // Determine text colors. | 535 // Determine text colors. |
| 540 TextPaintingStyle textStyle = textPaintingStyle(renderer(), styleToUse); | 536 TextPaintingStyle textStyle = textPaintingStyle(renderer(), styleToUse); |
| 541 TextPaintingStyle selectionStyle = selectionPaintingStyle(renderer(), haveSe
lection, textStyle); | 537 TextPaintingStyle selectionStyle = selectionPaintingStyle(renderer(), haveSe
lection, textStyle); |
| 542 bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection); | 538 bool paintSelectedTextSeparately = textStyle != selectionStyle; |
| 543 bool paintSelectedTextSeparately = !paintSelectedTextOnly && textStyle != se
lectionStyle; | |
| 544 | 539 |
| 545 // Set our font. | 540 // Set our font. |
| 546 const Font& font = styleToUse->font(); | 541 const Font& font = styleToUse->font(); |
| 547 | 542 |
| 548 FloatPoint textOrigin = FloatPoint(boxOrigin.x(), boxOrigin.y() + font.fontM
etrics().ascent()); | 543 FloatPoint textOrigin = FloatPoint(boxOrigin.x(), boxOrigin.y() + font.fontM
etrics().ascent()); |
| 549 | 544 |
| 550 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
include selection | 545 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
include selection |
| 551 // and composition highlights. | 546 // and composition highlights. |
| 552 if (paintInfo.phase != PaintPhaseSelection) { | 547 if (containsComposition) { |
| 553 if (containsComposition) { | 548 paintCompositionBackgrounds(context, boxOrigin, styleToUse, font, useCus
tomUnderlines); |
| 554 paintCompositionBackgrounds(context, boxOrigin, styleToUse, font, us
eCustomUnderlines); | 549 } |
| 555 } | |
| 556 | 550 |
| 557 paintDocumentMarkers(context, boxOrigin, styleToUse, font, true); | 551 paintDocumentMarkers(context, boxOrigin, styleToUse, font, true); |
| 558 | 552 |
| 559 if (haveSelection && !useCustomUnderlines) | 553 if (haveSelection && !useCustomUnderlines) |
| 560 paintSelection(context, boxOrigin, styleToUse, font, selectionStyle.
fillColor); | 554 paintSelection(context, boxOrigin, styleToUse, font, selectionStyle.fill
Color); |
| 561 } | |
| 562 | 555 |
| 563 // 2. Now paint the foreground, including text and decorations like underlin
e/overline (in quirks mode only). | 556 // 2. Now paint the foreground, including text and decorations like underlin
e/overline (in quirks mode only). |
| 564 int length = m_len; | 557 int length = m_len; |
| 565 int maximumLength; | 558 int maximumLength; |
| 566 StringView string = renderer().text().createView(); | 559 StringView string = renderer().text().createView(); |
| 567 if (static_cast<unsigned>(length) != string.length() || m_start) | 560 if (static_cast<unsigned>(length) != string.length() || m_start) |
| 568 string.narrow(m_start, length); | 561 string.narrow(m_start, length); |
| 569 maximumLength = renderer().textLength() - m_start; | 562 maximumLength = renderer().textLength() - m_start; |
| 570 | 563 |
| 571 StringBuilder charactersWithHyphen; | 564 StringBuilder charactersWithHyphen; |
| 572 TextRun textRun = constructTextRun(styleToUse, font, string, maximumLength,
hasHyphen() ? &charactersWithHyphen : 0); | 565 TextRun textRun = constructTextRun(styleToUse, font, string, maximumLength,
hasHyphen() ? &charactersWithHyphen : 0); |
| 573 if (hasHyphen()) | 566 if (hasHyphen()) |
| 574 length = textRun.length(); | 567 length = textRun.length(); |
| 575 | 568 |
| 576 int sPos = 0; | 569 int sPos = 0; |
| 577 int ePos = 0; | 570 int ePos = 0; |
| 578 if (paintSelectedTextOnly || paintSelectedTextSeparately) | 571 if (paintSelectedTextSeparately) |
| 579 selectionStartEnd(sPos, ePos); | 572 selectionStartEnd(sPos, ePos); |
| 580 | 573 |
| 581 bool respectHyphen = ePos == m_len && hasHyphen(); | 574 bool respectHyphen = ePos == m_len && hasHyphen(); |
| 582 if (respectHyphen) | 575 if (respectHyphen) |
| 583 ePos = textRun.length(); | 576 ePos = textRun.length(); |
| 584 | 577 |
| 585 if (m_truncation != cNoTruncation) { | 578 if (m_truncation != cNoTruncation) { |
| 586 sPos = std::min<int>(sPos, m_truncation); | 579 sPos = std::min<int>(sPos, m_truncation); |
| 587 ePos = std::min<int>(ePos, m_truncation); | 580 ePos = std::min<int>(ePos, m_truncation); |
| 588 length = m_truncation; | 581 length = m_truncation; |
| 589 } | 582 } |
| 590 | 583 |
| 591 int emphasisMarkOffset = 0; | 584 int emphasisMarkOffset = 0; |
| 592 TextEmphasisPosition emphasisMarkPosition; | 585 TextEmphasisPosition emphasisMarkPosition; |
| 593 bool hasTextEmphasis = getEmphasisMarkPosition(styleToUse, emphasisMarkPosit
ion); | 586 bool hasTextEmphasis = getEmphasisMarkPosition(styleToUse, emphasisMarkPosit
ion); |
| 594 const AtomicString& emphasisMark = hasTextEmphasis ? styleToUse->textEmphasi
sMarkString() : nullAtom; | 587 const AtomicString& emphasisMark = hasTextEmphasis ? styleToUse->textEmphasi
sMarkString() : nullAtom; |
| 595 if (!emphasisMark.isEmpty()) | 588 if (!emphasisMark.isEmpty()) |
| 596 emphasisMarkOffset = emphasisMarkPosition == TextEmphasisPositionOver ?
-font.fontMetrics().ascent() - font.emphasisMarkDescent(emphasisMark) : font.fon
tMetrics().descent() + font.emphasisMarkAscent(emphasisMark); | 589 emphasisMarkOffset = emphasisMarkPosition == TextEmphasisPositionOver ?
-font.fontMetrics().ascent() - font.emphasisMarkDescent(emphasisMark) : font.fon
tMetrics().descent() + font.emphasisMarkAscent(emphasisMark); |
| 597 | 590 |
| 598 if (!paintSelectedTextOnly) { | 591 // FIXME: Truncate right-to-left text correctly. |
| 599 // FIXME: Truncate right-to-left text correctly. | 592 int startOffset = 0; |
| 600 int startOffset = 0; | 593 int endOffset = length; |
| 601 int endOffset = length; | 594 if (paintSelectedTextSeparately && ePos > sPos) { |
| 602 if (paintSelectedTextSeparately && ePos > sPos) { | 595 startOffset = ePos; |
| 603 startOffset = ePos; | 596 endOffset = sPos; |
| 604 endOffset = sPos; | |
| 605 } | |
| 606 // FIXME: This cache should probably ultimately be held somewhere else. | |
| 607 // A hashmap is convenient to avoid a memory hit when the | |
| 608 // RuntimeEnabledFeature is off. | |
| 609 bool textBlobIsCacheable = RuntimeEnabledFeatures::textBlobEnabled() &&
startOffset == 0 && endOffset == length; | |
| 610 TextBlobPtr* cachedTextBlob = textBlobIsCacheable ? &m_cachedTextBlob :
nullptr; | |
| 611 paintTextWithEmphasisMark(context, font, textStyle, textRun, emphasisMar
k, emphasisMarkOffset, startOffset, endOffset, length, textOrigin, boxRect, cach
edTextBlob); | |
| 612 } | 597 } |
| 598 // FIXME: This cache should probably ultimately be held somewhere else. |
| 599 // A hashmap is convenient to avoid a memory hit when the |
| 600 // RuntimeEnabledFeature is off. |
| 601 bool textBlobIsCacheable = RuntimeEnabledFeatures::textBlobEnabled() && star
tOffset == 0 && endOffset == length; |
| 602 TextBlobPtr* cachedTextBlob = textBlobIsCacheable ? &m_cachedTextBlob : null
ptr; |
| 603 paintTextWithEmphasisMark(context, font, textStyle, textRun, emphasisMark, e
mphasisMarkOffset, startOffset, endOffset, length, textOrigin, boxRect, cachedTe
xtBlob); |
| 613 | 604 |
| 614 if ((paintSelectedTextOnly || paintSelectedTextSeparately) && sPos < ePos) { | 605 if (paintSelectedTextSeparately && sPos < ePos) { |
| 615 // paint only the text that is selected | 606 // paint only the text that is selected |
| 616 bool textBlobIsCacheable = RuntimeEnabledFeatures::textBlobEnabled() &&
sPos == 0 && ePos == length; | 607 bool textBlobIsCacheable = RuntimeEnabledFeatures::textBlobEnabled() &&
sPos == 0 && ePos == length; |
| 617 TextBlobPtr* cachedTextBlob = textBlobIsCacheable ? &m_cachedTextBlob :
nullptr; | 608 TextBlobPtr* cachedTextBlob = textBlobIsCacheable ? &m_cachedTextBlob :
nullptr; |
| 618 paintTextWithEmphasisMark(context, font, selectionStyle, textRun, emphas
isMark, emphasisMarkOffset, sPos, ePos, length, textOrigin, boxRect, cachedTextB
lob); | 609 paintTextWithEmphasisMark(context, font, selectionStyle, textRun, emphas
isMark, emphasisMarkOffset, sPos, ePos, length, textOrigin, boxRect, cachedTextB
lob); |
| 619 } | 610 } |
| 620 | 611 |
| 621 // Paint decorations | 612 // Paint decorations |
| 622 TextDecoration textDecorations = styleToUse->textDecorationsInEffect(); | 613 TextDecoration textDecorations = styleToUse->textDecorationsInEffect(); |
| 623 if (textDecorations != TextDecorationNone && !paintSelectedTextOnly) { | 614 if (textDecorations != TextDecorationNone) { |
| 624 GraphicsContextStateSaver stateSaver(*context, false); | 615 GraphicsContextStateSaver stateSaver(*context, false); |
| 625 updateGraphicsContext(context, textStyle, stateSaver); | 616 updateGraphicsContext(context, textStyle, stateSaver); |
| 626 paintDecoration(context, boxOrigin, textDecorations); | 617 paintDecoration(context, boxOrigin, textDecorations); |
| 627 } | 618 } |
| 628 | 619 |
| 629 if (paintInfo.phase == PaintPhaseForeground) { | 620 if (paintInfo.phase == PaintPhaseForeground) { |
| 630 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); | 621 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); |
| 631 | 622 |
| 632 // Paint custom underlines for compositions. | 623 // Paint custom underlines for compositions. |
| 633 if (useCustomUnderlines) { | 624 if (useCustomUnderlines) { |
| (...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1346 printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj); | 1337 printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj); |
| 1347 const int rendererCharacterOffset = 24; | 1338 const int rendererCharacterOffset = 24; |
| 1348 for (; printedCharacters < rendererCharacterOffset; printedCharacters++) | 1339 for (; printedCharacters < rendererCharacterOffset; printedCharacters++) |
| 1349 fputc(' ', stderr); | 1340 fputc(' ', stderr); |
| 1350 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d
ata()); | 1341 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d
ata()); |
| 1351 } | 1342 } |
| 1352 | 1343 |
| 1353 #endif | 1344 #endif |
| 1354 | 1345 |
| 1355 } // namespace blink | 1346 } // namespace blink |
| OLD | NEW |