Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 #include "core/paint/InlineTextBoxPainter.h" | 6 #include "core/paint/InlineTextBoxPainter.h" |
| 7 | 7 |
| 8 #include "core/editing/CompositionUnderline.h" | 8 #include "core/editing/CompositionUnderline.h" |
| 9 #include "core/editing/Editor.h" | 9 #include "core/editing/Editor.h" |
| 10 #include "core/editing/markers/DocumentMarkerController.h" | 10 #include "core/editing/markers/DocumentMarkerController.h" |
| 11 #include "core/editing/markers/RenderedDocumentMarker.h" | 11 #include "core/editing/markers/RenderedDocumentMarker.h" |
| 12 #include "core/frame/LocalFrame.h" | 12 #include "core/frame/LocalFrame.h" |
| 13 #include "core/layout/LayoutBlock.h" | 13 #include "core/layout/LayoutBlock.h" |
| 14 #include "core/layout/LayoutTextCombine.h" | 14 #include "core/layout/LayoutTextCombine.h" |
| 15 #include "core/layout/LayoutTheme.h" | 15 #include "core/layout/LayoutTheme.h" |
| 16 #include "core/layout/api/LineLayoutBox.h" | 16 #include "core/layout/api/LineLayoutBox.h" |
| 17 #include "core/layout/api/LineLayoutText.h" | 17 #include "core/layout/api/LineLayoutText.h" |
| 18 #include "core/layout/line/InlineTextBox.h" | 18 #include "core/layout/line/InlineTextBox.h" |
| 19 #include "core/paint/BoxPainter.h" | 19 #include "core/paint/BoxPainter.h" |
| 20 #include "core/paint/PaintInfo.h" | 20 #include "core/paint/PaintInfo.h" |
| 21 #include "core/paint/TextPainter.h" | 21 #include "core/paint/TextPainter.h" |
| 22 #include "core/style/AppliedTextDecoration.h" | |
| 22 #include "platform/graphics/GraphicsContextStateSaver.h" | 23 #include "platform/graphics/GraphicsContextStateSaver.h" |
| 23 #include "platform/graphics/paint/DrawingRecorder.h" | 24 #include "platform/graphics/paint/DrawingRecorder.h" |
| 24 #include "wtf/Optional.h" | 25 #include "wtf/Optional.h" |
| 25 | 26 |
| 26 namespace blink { | 27 namespace blink { |
| 27 | 28 |
| 28 typedef WTF::HashMap<const InlineTextBox*, TextBlobPtr> InlineTextBoxBlobCacheMa p; | 29 typedef WTF::HashMap<const InlineTextBox*, TextBlobPtr> InlineTextBoxBlobCacheMa p; |
| 29 static InlineTextBoxBlobCacheMap* gTextBlobCache; | 30 static InlineTextBoxBlobCacheMap* gTextBlobCache; |
| 30 | 31 |
| 31 static const int misspellingLineThickness = 3; | 32 static const int misspellingLineThickness = 3; |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 226 textPainter.paint(selectionStart, selectionEnd, length, selectionStyle, cachedTextBlob); | 227 textPainter.paint(selectionStart, selectionEnd, length, selectionStyle, cachedTextBlob); |
| 227 } | 228 } |
| 228 | 229 |
| 229 // Paint decorations | 230 // Paint decorations |
| 230 TextDecoration textDecorations = styleToUse.textDecorationsInEffect(); | 231 TextDecoration textDecorations = styleToUse.textDecorationsInEffect(); |
| 231 if (textDecorations != TextDecorationNone && !paintSelectedTextOnly) { | 232 if (textDecorations != TextDecorationNone && !paintSelectedTextOnly) { |
| 232 GraphicsContextStateSaver stateSaver(*context, false); | 233 GraphicsContextStateSaver stateSaver(*context, false); |
| 233 TextPainter::updateGraphicsContext(context, textStyle, m_inlineTextBox.i sHorizontal(), stateSaver); | 234 TextPainter::updateGraphicsContext(context, textStyle, m_inlineTextBox.i sHorizontal(), stateSaver); |
| 234 if (combinedText) | 235 if (combinedText) |
| 235 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Clock wise)); | 236 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Clock wise)); |
| 236 paintDecoration(paintInfo, boxOrigin, textDecorations); | 237 paintDecorations(paintInfo, boxOrigin, styleToUse.appliedTextDecorations ()); |
| 237 if (combinedText) | 238 if (combinedText) |
| 238 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Count erclockwise)); | 239 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Count erclockwise)); |
| 239 } | 240 } |
| 240 | 241 |
| 241 if (paintInfo.phase == PaintPhaseForeground) | 242 if (paintInfo.phase == PaintPhaseForeground) |
| 242 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); | 243 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); |
| 243 | 244 |
| 244 if (shouldRotate) | 245 if (shouldRotate) |
| 245 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Countercl ockwise)); | 246 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Countercl ockwise)); |
| 246 } | 247 } |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 533 | 534 |
| 534 ASSERT_NOT_REACHED(); | 535 ASSERT_NOT_REACHED(); |
| 535 return fontMetrics.ascent() + gap; | 536 return fontMetrics.ascent() + gap; |
| 536 } | 537 } |
| 537 | 538 |
| 538 static bool shouldSetDecorationAntialias(TextDecorationStyle decorationStyle) | 539 static bool shouldSetDecorationAntialias(TextDecorationStyle decorationStyle) |
| 539 { | 540 { |
| 540 return decorationStyle == TextDecorationStyleDotted || decorationStyle == Te xtDecorationStyleDashed; | 541 return decorationStyle == TextDecorationStyleDotted || decorationStyle == Te xtDecorationStyleDashed; |
| 541 } | 542 } |
| 542 | 543 |
| 543 static bool shouldSetDecorationAntialias(TextDecorationStyle underline, TextDeco rationStyle overline, TextDecorationStyle linethrough) | |
| 544 { | |
| 545 return shouldSetDecorationAntialias(underline) || shouldSetDecorationAntiali as(overline) || shouldSetDecorationAntialias(linethrough); | |
| 546 } | |
| 547 | |
| 548 static StrokeStyle textDecorationStyleToStrokeStyle(TextDecorationStyle decorati onStyle) | 544 static StrokeStyle textDecorationStyleToStrokeStyle(TextDecorationStyle decorati onStyle) |
| 549 { | 545 { |
| 550 StrokeStyle strokeStyle = SolidStroke; | 546 StrokeStyle strokeStyle = SolidStroke; |
| 551 switch (decorationStyle) { | 547 switch (decorationStyle) { |
| 552 case TextDecorationStyleSolid: | 548 case TextDecorationStyleSolid: |
| 553 strokeStyle = SolidStroke; | 549 strokeStyle = SolidStroke; |
| 554 break; | 550 break; |
| 555 case TextDecorationStyleDouble: | 551 case TextDecorationStyleDouble: |
| 556 strokeStyle = DoubleStroke; | 552 strokeStyle = DoubleStroke; |
| 557 break; | 553 break; |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 685 x += 2 * step; | 681 x += 2 * step; |
| 686 path.addBezierCurveTo(controlPoint1, controlPoint2, FloatPoint(x, yA xis)); | 682 path.addBezierCurveTo(controlPoint1, controlPoint2, FloatPoint(x, yA xis)); |
| 687 } | 683 } |
| 688 } | 684 } |
| 689 | 685 |
| 690 context->setShouldAntialias(true); | 686 context->setShouldAntialias(true); |
| 691 context->strokePath(path); | 687 context->strokePath(path); |
| 692 } | 688 } |
| 693 | 689 |
| 694 static void paintAppliedDecoration(GraphicsContext* context, FloatPoint start, f loat width, float doubleOffset, int wavyOffsetFactor, | 690 static void paintAppliedDecoration(GraphicsContext* context, FloatPoint start, f loat width, float doubleOffset, int wavyOffsetFactor, |
| 695 LayoutObject::AppliedTextDecoration decoration, float thickness, bool antial iasDecoration, bool isPrinting) | 691 AppliedTextDecoration decoration, float thickness, bool antialiasDecoration, bool isPrinting) |
| 696 { | 692 { |
| 697 context->setStrokeStyle(textDecorationStyleToStrokeStyle(decoration.style)); | 693 context->setStrokeStyle(textDecorationStyleToStrokeStyle(decoration.style()) ); |
| 698 context->setStrokeColor(decoration.color); | 694 context->setStrokeColor(decoration.color()); |
| 699 | 695 |
| 700 switch (decoration.style) { | 696 switch (decoration.style()) { |
| 701 case TextDecorationStyleWavy: | 697 case TextDecorationStyleWavy: |
| 702 strokeWavyTextDecoration(context, start + FloatPoint(0, doubleOffset * w avyOffsetFactor), start + FloatPoint(width, doubleOffset * wavyOffsetFactor), th ickness); | 698 strokeWavyTextDecoration(context, start + FloatPoint(0, doubleOffset * w avyOffsetFactor), start + FloatPoint(width, doubleOffset * wavyOffsetFactor), th ickness); |
| 703 break; | 699 break; |
| 704 case TextDecorationStyleDotted: | 700 case TextDecorationStyleDotted: |
| 705 case TextDecorationStyleDashed: | 701 case TextDecorationStyleDashed: |
| 706 context->setShouldAntialias(antialiasDecoration); | 702 context->setShouldAntialias(antialiasDecoration); |
| 707 // Fall through | 703 // Fall through |
| 708 default: | 704 default: |
| 709 context->drawLineForText(FloatPoint(start), width, isPrinting); | 705 context->drawLineForText(FloatPoint(start), width, isPrinting); |
| 710 | 706 |
| 711 if (decoration.style == TextDecorationStyleDouble) | 707 if (decoration.style() == TextDecorationStyleDouble) |
| 712 context->drawLineForText(start + FloatPoint(0, doubleOffset), width, isPrinting); | 708 context->drawLineForText(start + FloatPoint(0, doubleOffset), width, isPrinting); |
| 713 } | 709 } |
| 714 } | 710 } |
| 715 | 711 |
| 716 void InlineTextBoxPainter::paintDecoration(const PaintInfo& paintInfo, const Lay outPoint& boxOrigin, TextDecoration deco) | 712 void InlineTextBoxPainter::paintDecorations(const PaintInfo& paintInfo, const La youtPoint& boxOrigin, const Vector<AppliedTextDecoration>& decorations) |
| 717 { | 713 { |
| 718 if (m_inlineTextBox.truncation() == cFullTruncation) | 714 if (m_inlineTextBox.truncation() == cFullTruncation) |
| 719 return; | 715 return; |
| 720 | 716 |
| 721 GraphicsContext* context = paintInfo.context; | 717 GraphicsContext* context = paintInfo.context; |
| 722 GraphicsContextStateSaver stateSaver(*context); | 718 GraphicsContextStateSaver stateSaver(*context); |
| 723 | 719 |
| 724 LayoutPoint localOrigin(boxOrigin); | 720 LayoutPoint localOrigin(boxOrigin); |
| 725 | 721 |
| 726 LayoutUnit width = m_inlineTextBox.logicalWidth(); | 722 LayoutUnit width = m_inlineTextBox.logicalWidth(); |
| 727 if (m_inlineTextBox.truncation() != cNoTruncation) { | 723 if (m_inlineTextBox.truncation() != cNoTruncation) { |
| 728 width = m_inlineTextBox.lineLayoutItem().width(m_inlineTextBox.start(), m_inlineTextBox.truncation(), m_inlineTextBox.textPos(), m_inlineTextBox.isLeftT oRightDirection() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle()); | 724 width = m_inlineTextBox.lineLayoutItem().width(m_inlineTextBox.start(), m_inlineTextBox.truncation(), m_inlineTextBox.textPos(), m_inlineTextBox.isLeftT oRightDirection() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle()); |
| 729 if (!m_inlineTextBox.isLeftToRightDirection()) | 725 if (!m_inlineTextBox.isLeftToRightDirection()) |
| 730 localOrigin.move(m_inlineTextBox.logicalWidth() - width, 0); | 726 localOrigin.move(m_inlineTextBox.logicalWidth() - width, 0); |
| 731 } | 727 } |
| 732 | 728 |
| 733 // Get the text decoration colors. | |
| 734 LayoutObject::AppliedTextDecoration underline, overline, linethrough; | |
| 735 m_inlineTextBox.layoutObject().getTextDecorations(deco, underline, overline, linethrough, true); | |
| 736 if (m_inlineTextBox.isFirstLineStyle()) | |
| 737 m_inlineTextBox.layoutObject().getTextDecorations(deco, underline, overl ine, linethrough, true, true); | |
| 738 | |
| 739 // Use a special function for underlines to get the positioning exactly righ t. | 729 // Use a special function for underlines to get the positioning exactly righ t. |
| 740 bool isPrinting = paintInfo.isPrinting(); | 730 bool isPrinting = paintInfo.isPrinting(); |
| 741 | 731 |
| 742 const ComputedStyle& styleToUse = m_inlineTextBox.lineLayoutItem().styleRef( m_inlineTextBox.isFirstLineStyle()); | 732 const ComputedStyle& styleToUse = m_inlineTextBox.lineLayoutItem().styleRef( m_inlineTextBox.isFirstLineStyle()); |
| 743 float baseline = styleToUse.fontMetrics().ascent(); | 733 float baseline = styleToUse.fontMetrics().ascent(); |
| 744 | 734 |
| 745 // Set the thick of the line to be 10% (or something else ?)of the computed font size and not less than 1px. | 735 // Set the thick of the line to be 10% (or something else ?)of the computed font size and not less than 1px. |
| 746 // Using computedFontSize should take care of zoom as well. | 736 // Using computedFontSize should take care of zoom as well. |
| 747 | 737 |
| 748 // Update Underline thickness, in case we have Faulty Font Metrics calculati ng underline thickness by old method. | 738 // Update Underline thickness, in case we have Faulty Font Metrics calculati ng underline thickness by old method. |
| 749 float textDecorationThickness = styleToUse.fontMetrics().underlineThickness( ); | 739 float textDecorationThickness = styleToUse.fontMetrics().underlineThickness( ); |
| 750 int fontHeightInt = (int)(styleToUse.fontMetrics().floatHeight() + 0.5); | 740 int fontHeightInt = (int)(styleToUse.fontMetrics().floatHeight() + 0.5); |
| 751 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei ghtInt >> 1))) | 741 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei ghtInt >> 1))) |
| 752 textDecorationThickness = std::max(1.f, styleToUse.computedFontSize() / 10.f); | 742 textDecorationThickness = std::max(1.f, styleToUse.computedFontSize() / 10.f); |
| 753 | 743 |
| 754 context->setStrokeThickness(textDecorationThickness); | 744 context->setStrokeThickness(textDecorationThickness); |
| 755 | 745 |
| 756 bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, unde rline.style, linethrough.style); | 746 bool antialiasDecoration = false; |
| 747 for (const auto& decoration : decorations) | |
| 748 antialiasDecoration |= shouldSetDecorationAntialias(decoration.style()); | |
| 757 | 749 |
| 758 // Offset between lines - always non-zero, so lines never cross each other. | 750 // Offset between lines - always non-zero, so lines never cross each other. |
| 759 float doubleOffset = textDecorationThickness + 1.f; | 751 float doubleOffset = textDecorationThickness + 1.f; |
| 760 | 752 |
| 761 if (deco & TextDecorationUnderline) { | 753 for (const auto& decoration : decorations) { |
|
Timothy Loh
2015/10/01 01:51:43
let's write out the type here and everywhere else
sashab
2015/10/02 02:45:41
Done.
| |
| 762 const int underlineOffset = computeUnderlineOffset(styleToUse.textUnderl inePosition(), styleToUse.fontMetrics(), &m_inlineTextBox, textDecorationThickne ss); | 754 if (decoration.lines() & TextDecorationUnderline) { |
| 763 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint(0, underlineOffset), width.toFloat(), doubleOffset, 1, underline, textDecorationThi ckness, antialiasDecoration, isPrinting); | 755 const int underlineOffset = computeUnderlineOffset(styleToUse.textUn derlinePosition(), styleToUse.fontMetrics(), &m_inlineTextBox, textDecorationThi ckness); |
| 764 } | 756 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint (0, underlineOffset), width.toFloat(), doubleOffset, 1, decoration, textDecorati onThickness, antialiasDecoration, isPrinting); |
| 765 if (deco & TextDecorationOverline) { | 757 } |
| 766 paintAppliedDecoration(context, FloatPoint(localOrigin), width.toFloat() , -doubleOffset, 1, overline, textDecorationThickness, antialiasDecoration, isPr inting); | 758 if (decoration.lines() & TextDecorationOverline) { |
| 767 } | 759 paintAppliedDecoration(context, FloatPoint(localOrigin), width.toFlo at(), -doubleOffset, 1, decoration, textDecorationThickness, antialiasDecoration , isPrinting); |
| 768 if (deco & TextDecorationLineThrough) { | 760 } |
| 769 const float lineThroughOffset = 2 * baseline / 3; | 761 if (decoration.lines() & TextDecorationLineThrough) { |
| 770 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint(0, lineThroughOffset), width.toFloat(), doubleOffset, 0, linethrough, textDecoratio nThickness, antialiasDecoration, isPrinting); | 762 const float lineThroughOffset = 2 * baseline / 3; |
| 763 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint (0, lineThroughOffset), width.toFloat(), doubleOffset, 0, decoration, textDecora tionThickness, antialiasDecoration, isPrinting); | |
| 764 } | |
| 771 } | 765 } |
| 772 } | 766 } |
| 773 | 767 |
| 774 void InlineTextBoxPainter::paintCompositionUnderline(GraphicsContext* ctx, const LayoutPoint& boxOrigin, const CompositionUnderline& underline) | 768 void InlineTextBoxPainter::paintCompositionUnderline(GraphicsContext* ctx, const LayoutPoint& boxOrigin, const CompositionUnderline& underline) |
| 775 { | 769 { |
| 776 if (underline.color == Color::transparent) | 770 if (underline.color == Color::transparent) |
| 777 return; | 771 return; |
| 778 | 772 |
| 779 if (m_inlineTextBox.truncation() == cFullTruncation) | 773 if (m_inlineTextBox.truncation() == cFullTruncation) |
| 780 return; | 774 return; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 840 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetri cs().ascent()); | 834 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetri cs().ascent()); |
| 841 TextPainter textPainter(pt, font, run, textOrigin, boxRect, m_inline TextBox.isHorizontal()); | 835 TextPainter textPainter(pt, font, run, textOrigin, boxRect, m_inline TextBox.isHorizontal()); |
| 842 | 836 |
| 843 textPainter.paint(sPos, ePos, length, textStyle, 0); | 837 textPainter.paint(sPos, ePos, length, textStyle, 0); |
| 844 } | 838 } |
| 845 } | 839 } |
| 846 } | 840 } |
| 847 | 841 |
| 848 | 842 |
| 849 } // namespace blink | 843 } // namespace blink |
| OLD | NEW |