Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(228)

Side by Side Diff: third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp

Issue 1328283005: Add support for multiple text decorations with same line positioning (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/LineLayoutPaintShim.h" 20 #include "core/paint/LineLayoutPaintShim.h"
21 #include "core/paint/PaintInfo.h" 21 #include "core/paint/PaintInfo.h"
22 #include "core/paint/TextPainter.h" 22 #include "core/paint/TextPainter.h"
23 #include "core/style/AppliedTextDecoration.h"
23 #include "platform/graphics/GraphicsContextStateSaver.h" 24 #include "platform/graphics/GraphicsContextStateSaver.h"
24 #include "platform/graphics/paint/DrawingRecorder.h" 25 #include "platform/graphics/paint/DrawingRecorder.h"
25 #include "wtf/Optional.h" 26 #include "wtf/Optional.h"
26 27
27 namespace blink { 28 namespace blink {
28 29
29 typedef WTF::HashMap<const InlineTextBox*, TextBlobPtr> InlineTextBoxBlobCacheMa p; 30 typedef WTF::HashMap<const InlineTextBox*, TextBlobPtr> InlineTextBoxBlobCacheMa p;
30 static InlineTextBoxBlobCacheMap* gTextBlobCache; 31 static InlineTextBoxBlobCacheMap* gTextBlobCache;
31 32
32 static const int misspellingLineThickness = 3; 33 static const int misspellingLineThickness = 3;
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 textPainter.paint(selectionStart, selectionEnd, length, selectionStyle, cachedTextBlob); 231 textPainter.paint(selectionStart, selectionEnd, length, selectionStyle, cachedTextBlob);
231 } 232 }
232 233
233 // Paint decorations 234 // Paint decorations
234 TextDecoration textDecorations = styleToUse.textDecorationsInEffect(); 235 TextDecoration textDecorations = styleToUse.textDecorationsInEffect();
235 if (textDecorations != TextDecorationNone && !paintSelectedTextOnly) { 236 if (textDecorations != TextDecorationNone && !paintSelectedTextOnly) {
236 GraphicsContextStateSaver stateSaver(*context, false); 237 GraphicsContextStateSaver stateSaver(*context, false);
237 TextPainter::updateGraphicsContext(context, textStyle, m_inlineTextBox.i sHorizontal(), stateSaver); 238 TextPainter::updateGraphicsContext(context, textStyle, m_inlineTextBox.i sHorizontal(), stateSaver);
238 if (combinedText) 239 if (combinedText)
239 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Clock wise)); 240 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Clock wise));
240 paintDecoration(paintInfo, boxOrigin, textDecorations); 241 paintDecorations(paintInfo, boxOrigin, styleToUse.appliedTextDecorations ());
241 if (combinedText) 242 if (combinedText)
242 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Count erclockwise)); 243 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Count erclockwise));
243 } 244 }
244 245
245 if (paintInfo.phase == PaintPhaseForeground) 246 if (paintInfo.phase == PaintPhaseForeground)
246 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); 247 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false);
247 248
248 if (shouldRotate) 249 if (shouldRotate)
249 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Countercl ockwise)); 250 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Countercl ockwise));
250 } 251 }
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 549
549 ASSERT_NOT_REACHED(); 550 ASSERT_NOT_REACHED();
550 return fontMetrics.ascent() + gap; 551 return fontMetrics.ascent() + gap;
551 } 552 }
552 553
553 static bool shouldSetDecorationAntialias(TextDecorationStyle decorationStyle) 554 static bool shouldSetDecorationAntialias(TextDecorationStyle decorationStyle)
554 { 555 {
555 return decorationStyle == TextDecorationStyleDotted || decorationStyle == Te xtDecorationStyleDashed; 556 return decorationStyle == TextDecorationStyleDotted || decorationStyle == Te xtDecorationStyleDashed;
556 } 557 }
557 558
558 static bool shouldSetDecorationAntialias(TextDecorationStyle underline, TextDeco rationStyle overline, TextDecorationStyle linethrough)
559 {
560 return shouldSetDecorationAntialias(underline) || shouldSetDecorationAntiali as(overline) || shouldSetDecorationAntialias(linethrough);
561 }
562
563 static StrokeStyle textDecorationStyleToStrokeStyle(TextDecorationStyle decorati onStyle) 559 static StrokeStyle textDecorationStyleToStrokeStyle(TextDecorationStyle decorati onStyle)
564 { 560 {
565 StrokeStyle strokeStyle = SolidStroke; 561 StrokeStyle strokeStyle = SolidStroke;
566 switch (decorationStyle) { 562 switch (decorationStyle) {
567 case TextDecorationStyleSolid: 563 case TextDecorationStyleSolid:
568 strokeStyle = SolidStroke; 564 strokeStyle = SolidStroke;
569 break; 565 break;
570 case TextDecorationStyleDouble: 566 case TextDecorationStyleDouble:
571 strokeStyle = DoubleStroke; 567 strokeStyle = DoubleStroke;
572 break; 568 break;
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 x += 2 * step; 696 x += 2 * step;
701 path.addBezierCurveTo(controlPoint1, controlPoint2, FloatPoint(x, yA xis)); 697 path.addBezierCurveTo(controlPoint1, controlPoint2, FloatPoint(x, yA xis));
702 } 698 }
703 } 699 }
704 700
705 context->setShouldAntialias(true); 701 context->setShouldAntialias(true);
706 context->strokePath(path); 702 context->strokePath(path);
707 } 703 }
708 704
709 static void paintAppliedDecoration(GraphicsContext* context, FloatPoint start, f loat width, float doubleOffset, int wavyOffsetFactor, 705 static void paintAppliedDecoration(GraphicsContext* context, FloatPoint start, f loat width, float doubleOffset, int wavyOffsetFactor,
710 LayoutObject::AppliedTextDecoration decoration, float thickness, bool antial iasDecoration, bool isPrinting) 706 AppliedTextDecoration decoration, float thickness, bool antialiasDecoration, bool isPrinting)
711 { 707 {
712 context->setStrokeStyle(textDecorationStyleToStrokeStyle(decoration.style)); 708 context->setStrokeStyle(textDecorationStyleToStrokeStyle(decoration.style()) );
713 context->setStrokeColor(decoration.color); 709 context->setStrokeColor(decoration.color());
714 710
715 switch (decoration.style) { 711 switch (decoration.style()) {
716 case TextDecorationStyleWavy: 712 case TextDecorationStyleWavy:
717 strokeWavyTextDecoration(context, start + FloatPoint(0, doubleOffset * w avyOffsetFactor), start + FloatPoint(width, doubleOffset * wavyOffsetFactor), th ickness); 713 strokeWavyTextDecoration(context, start + FloatPoint(0, doubleOffset * w avyOffsetFactor), start + FloatPoint(width, doubleOffset * wavyOffsetFactor), th ickness);
718 break; 714 break;
719 case TextDecorationStyleDotted: 715 case TextDecorationStyleDotted:
720 case TextDecorationStyleDashed: 716 case TextDecorationStyleDashed:
721 context->setShouldAntialias(antialiasDecoration); 717 context->setShouldAntialias(antialiasDecoration);
722 // Fall through 718 // Fall through
723 default: 719 default:
724 context->drawLineForText(FloatPoint(start), width, isPrinting); 720 context->drawLineForText(FloatPoint(start), width, isPrinting);
725 721
726 if (decoration.style == TextDecorationStyleDouble) 722 if (decoration.style() == TextDecorationStyleDouble)
727 context->drawLineForText(start + FloatPoint(0, doubleOffset), width, isPrinting); 723 context->drawLineForText(start + FloatPoint(0, doubleOffset), width, isPrinting);
728 } 724 }
729 } 725 }
730 726
731 void InlineTextBoxPainter::paintDecoration(const PaintInfo& paintInfo, const Lay outPoint& boxOrigin, TextDecoration deco) 727 void InlineTextBoxPainter::paintDecorations(const PaintInfo& paintInfo, const La youtPoint& boxOrigin, const Vector<AppliedTextDecoration>& decorations)
732 { 728 {
733 if (m_inlineTextBox.truncation() == cFullTruncation) 729 if (m_inlineTextBox.truncation() == cFullTruncation)
734 return; 730 return;
735 731
736 GraphicsContext* context = paintInfo.context; 732 GraphicsContext* context = paintInfo.context;
737 GraphicsContextStateSaver stateSaver(*context); 733 GraphicsContextStateSaver stateSaver(*context);
738 734
739 LayoutPoint localOrigin(boxOrigin); 735 LayoutPoint localOrigin(boxOrigin);
740 736
741 LayoutUnit width = m_inlineTextBox.logicalWidth(); 737 LayoutUnit width = m_inlineTextBox.logicalWidth();
742 if (m_inlineTextBox.truncation() != cNoTruncation) { 738 if (m_inlineTextBox.truncation() != cNoTruncation) {
743 width = m_inlineTextBox.lineLayoutItem().width(m_inlineTextBox.start(), m_inlineTextBox.truncation(), m_inlineTextBox.textPos(), m_inlineTextBox.isLeftT oRightDirection() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle()); 739 width = m_inlineTextBox.lineLayoutItem().width(m_inlineTextBox.start(), m_inlineTextBox.truncation(), m_inlineTextBox.textPos(), m_inlineTextBox.isLeftT oRightDirection() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle());
744 if (!m_inlineTextBox.isLeftToRightDirection()) 740 if (!m_inlineTextBox.isLeftToRightDirection())
745 localOrigin.move(m_inlineTextBox.logicalWidth() - width, 0); 741 localOrigin.move(m_inlineTextBox.logicalWidth() - width, 0);
746 } 742 }
747 743
748 // Get the text decoration colors.
749 LayoutObject::AppliedTextDecoration underline, overline, linethrough;
750 LayoutObject& textBoxLayoutObject = *LineLayoutPaintShim::layoutObjectFrom(m _inlineTextBox.lineLayoutItem());
751 textBoxLayoutObject.getTextDecorations(deco, underline, overline, linethroug h, true);
752 if (m_inlineTextBox.isFirstLineStyle())
753 textBoxLayoutObject.getTextDecorations(deco, underline, overline, lineth rough, true, true);
754
755 // Use a special function for underlines to get the positioning exactly righ t. 744 // Use a special function for underlines to get the positioning exactly righ t.
756 bool isPrinting = paintInfo.isPrinting(); 745 bool isPrinting = paintInfo.isPrinting();
757 746
747 LayoutObject& textBoxLayoutObject = *LineLayoutPaintShim::layoutObjectFrom(m _inlineTextBox.lineLayoutItem());
758 const ComputedStyle& styleToUse = textBoxLayoutObject.styleRef(m_inlineTextB ox.isFirstLineStyle()); 748 const ComputedStyle& styleToUse = textBoxLayoutObject.styleRef(m_inlineTextB ox.isFirstLineStyle());
759 float baseline = styleToUse.fontMetrics().ascent(); 749 float baseline = styleToUse.fontMetrics().ascent();
760 750
761 // Set the thick of the line to be 10% (or something else ?)of the computed font size and not less than 1px. 751 // Set the thick of the line to be 10% (or something else ?)of the computed font size and not less than 1px.
762 // Using computedFontSize should take care of zoom as well. 752 // Using computedFontSize should take care of zoom as well.
763 753
764 // Update Underline thickness, in case we have Faulty Font Metrics calculati ng underline thickness by old method. 754 // Update Underline thickness, in case we have Faulty Font Metrics calculati ng underline thickness by old method.
765 float textDecorationThickness = styleToUse.fontMetrics().underlineThickness( ); 755 float textDecorationThickness = styleToUse.fontMetrics().underlineThickness( );
766 int fontHeightInt = (int)(styleToUse.fontMetrics().floatHeight() + 0.5); 756 int fontHeightInt = (int)(styleToUse.fontMetrics().floatHeight() + 0.5);
767 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei ghtInt >> 1))) 757 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei ghtInt >> 1)))
768 textDecorationThickness = std::max(1.f, styleToUse.computedFontSize() / 10.f); 758 textDecorationThickness = std::max(1.f, styleToUse.computedFontSize() / 10.f);
769 759
770 context->setStrokeThickness(textDecorationThickness); 760 context->setStrokeThickness(textDecorationThickness);
771 761
772 bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, unde rline.style, linethrough.style); 762 bool antialiasDecoration = false;
763 for (const AppliedTextDecoration& decoration : decorations)
764 antialiasDecoration |= shouldSetDecorationAntialias(decoration.style());
773 765
774 // Offset between lines - always non-zero, so lines never cross each other. 766 // Offset between lines - always non-zero, so lines never cross each other.
775 float doubleOffset = textDecorationThickness + 1.f; 767 float doubleOffset = textDecorationThickness + 1.f;
776 768
777 if (deco & TextDecorationUnderline) { 769 for (const AppliedTextDecoration& decoration : decorations) {
778 const int underlineOffset = computeUnderlineOffset(styleToUse.textUnderl inePosition(), styleToUse.fontMetrics(), &m_inlineTextBox, textDecorationThickne ss); 770 if (decoration.lines() & TextDecorationUnderline) {
779 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint(0, underlineOffset), width.toFloat(), doubleOffset, 1, underline, textDecorationThi ckness, antialiasDecoration, isPrinting); 771 const int underlineOffset = computeUnderlineOffset(styleToUse.textUn derlinePosition(), styleToUse.fontMetrics(), &m_inlineTextBox, textDecorationThi ckness);
780 } 772 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint (0, underlineOffset), width.toFloat(), doubleOffset, 1, decoration, textDecorati onThickness, antialiasDecoration, isPrinting);
781 if (deco & TextDecorationOverline) { 773 }
782 paintAppliedDecoration(context, FloatPoint(localOrigin), width.toFloat() , -doubleOffset, 1, overline, textDecorationThickness, antialiasDecoration, isPr inting); 774 if (decoration.lines() & TextDecorationOverline) {
783 } 775 paintAppliedDecoration(context, FloatPoint(localOrigin), width.toFlo at(), -doubleOffset, 1, decoration, textDecorationThickness, antialiasDecoration , isPrinting);
784 if (deco & TextDecorationLineThrough) { 776 }
785 const float lineThroughOffset = 2 * baseline / 3; 777 if (decoration.lines() & TextDecorationLineThrough) {
786 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint(0, lineThroughOffset), width.toFloat(), doubleOffset, 0, linethrough, textDecoratio nThickness, antialiasDecoration, isPrinting); 778 const float lineThroughOffset = 2 * baseline / 3;
779 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint (0, lineThroughOffset), width.toFloat(), doubleOffset, 0, decoration, textDecora tionThickness, antialiasDecoration, isPrinting);
780 }
787 } 781 }
788 } 782 }
789 783
790 void InlineTextBoxPainter::paintCompositionUnderline(GraphicsContext* ctx, const LayoutPoint& boxOrigin, const CompositionUnderline& underline) 784 void InlineTextBoxPainter::paintCompositionUnderline(GraphicsContext* ctx, const LayoutPoint& boxOrigin, const CompositionUnderline& underline)
791 { 785 {
792 if (underline.color == Color::transparent) 786 if (underline.color == Color::transparent)
793 return; 787 return;
794 788
795 if (m_inlineTextBox.truncation() == cFullTruncation) 789 if (m_inlineTextBox.truncation() == cFullTruncation)
796 return; 790 return;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetri cs().ascent()); 850 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetri cs().ascent());
857 TextPainter textPainter(pt, font, run, textOrigin, boxRect, m_inline TextBox.isHorizontal()); 851 TextPainter textPainter(pt, font, run, textOrigin, boxRect, m_inline TextBox.isHorizontal());
858 852
859 textPainter.paint(sPos, ePos, length, textStyle, 0); 853 textPainter.paint(sPos, ePos, length, textStyle, 0);
860 } 854 }
861 } 855 }
862 } 856 }
863 857
864 858
865 } // namespace blink 859 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698