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

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 again Created 5 years, 2 months 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 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 textPainter.paint(selectionStart, selectionEnd, length, selectionStyle, cachedTextBlob); 229 textPainter.paint(selectionStart, selectionEnd, length, selectionStyle, cachedTextBlob);
229 } 230 }
230 231
231 // Paint decorations 232 // Paint decorations
232 TextDecoration textDecorations = styleToUse.textDecorationsInEffect(); 233 TextDecoration textDecorations = styleToUse.textDecorationsInEffect();
233 if (textDecorations != TextDecorationNone && !paintSelectedTextOnly) { 234 if (textDecorations != TextDecorationNone && !paintSelectedTextOnly) {
234 GraphicsContextStateSaver stateSaver(*context, false); 235 GraphicsContextStateSaver stateSaver(*context, false);
235 TextPainter::updateGraphicsContext(context, textStyle, m_inlineTextBox.i sHorizontal(), stateSaver); 236 TextPainter::updateGraphicsContext(context, textStyle, m_inlineTextBox.i sHorizontal(), stateSaver);
236 if (combinedText) 237 if (combinedText)
237 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Clock wise)); 238 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Clock wise));
238 paintDecoration(paintInfo, boxOrigin, textDecorations); 239 paintDecorations(paintInfo, boxOrigin, styleToUse.appliedTextDecorations ());
239 if (combinedText) 240 if (combinedText)
240 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Count erclockwise)); 241 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Count erclockwise));
241 } 242 }
242 243
243 if (paintInfo.phase == PaintPhaseForeground) 244 if (paintInfo.phase == PaintPhaseForeground)
244 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); 245 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false);
245 246
246 if (shouldRotate) 247 if (shouldRotate)
247 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Countercl ockwise)); 248 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Countercl ockwise));
248 } 249 }
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 536
536 ASSERT_NOT_REACHED(); 537 ASSERT_NOT_REACHED();
537 return fontMetrics.ascent() + gap; 538 return fontMetrics.ascent() + gap;
538 } 539 }
539 540
540 static bool shouldSetDecorationAntialias(TextDecorationStyle decorationStyle) 541 static bool shouldSetDecorationAntialias(TextDecorationStyle decorationStyle)
541 { 542 {
542 return decorationStyle == TextDecorationStyleDotted || decorationStyle == Te xtDecorationStyleDashed; 543 return decorationStyle == TextDecorationStyleDotted || decorationStyle == Te xtDecorationStyleDashed;
543 } 544 }
544 545
545 static bool shouldSetDecorationAntialias(TextDecorationStyle underline, TextDeco rationStyle overline, TextDecorationStyle linethrough)
546 {
547 return shouldSetDecorationAntialias(underline) || shouldSetDecorationAntiali as(overline) || shouldSetDecorationAntialias(linethrough);
548 }
549
550 static StrokeStyle textDecorationStyleToStrokeStyle(TextDecorationStyle decorati onStyle) 546 static StrokeStyle textDecorationStyleToStrokeStyle(TextDecorationStyle decorati onStyle)
551 { 547 {
552 StrokeStyle strokeStyle = SolidStroke; 548 StrokeStyle strokeStyle = SolidStroke;
553 switch (decorationStyle) { 549 switch (decorationStyle) {
554 case TextDecorationStyleSolid: 550 case TextDecorationStyleSolid:
555 strokeStyle = SolidStroke; 551 strokeStyle = SolidStroke;
556 break; 552 break;
557 case TextDecorationStyleDouble: 553 case TextDecorationStyleDouble:
558 strokeStyle = DoubleStroke; 554 strokeStyle = DoubleStroke;
559 break; 555 break;
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 x += 2 * step; 683 x += 2 * step;
688 path.addBezierCurveTo(controlPoint1, controlPoint2, FloatPoint(x, yA xis)); 684 path.addBezierCurveTo(controlPoint1, controlPoint2, FloatPoint(x, yA xis));
689 } 685 }
690 } 686 }
691 687
692 context->setShouldAntialias(true); 688 context->setShouldAntialias(true);
693 context->strokePath(path); 689 context->strokePath(path);
694 } 690 }
695 691
696 static void paintAppliedDecoration(GraphicsContext* context, FloatPoint start, f loat width, float doubleOffset, int wavyOffsetFactor, 692 static void paintAppliedDecoration(GraphicsContext* context, FloatPoint start, f loat width, float doubleOffset, int wavyOffsetFactor,
697 LayoutObject::AppliedTextDecoration decoration, float thickness, bool antial iasDecoration, bool isPrinting) 693 AppliedTextDecoration decoration, float thickness, bool antialiasDecoration, bool isPrinting)
698 { 694 {
699 context->setStrokeStyle(textDecorationStyleToStrokeStyle(decoration.style)); 695 context->setStrokeStyle(textDecorationStyleToStrokeStyle(decoration.style()) );
700 context->setStrokeColor(decoration.color); 696 context->setStrokeColor(decoration.color());
701 697
702 switch (decoration.style) { 698 switch (decoration.style()) {
703 case TextDecorationStyleWavy: 699 case TextDecorationStyleWavy:
704 strokeWavyTextDecoration(context, start + FloatPoint(0, doubleOffset * w avyOffsetFactor), start + FloatPoint(width, doubleOffset * wavyOffsetFactor), th ickness); 700 strokeWavyTextDecoration(context, start + FloatPoint(0, doubleOffset * w avyOffsetFactor), start + FloatPoint(width, doubleOffset * wavyOffsetFactor), th ickness);
705 break; 701 break;
706 case TextDecorationStyleDotted: 702 case TextDecorationStyleDotted:
707 case TextDecorationStyleDashed: 703 case TextDecorationStyleDashed:
708 context->setShouldAntialias(antialiasDecoration); 704 context->setShouldAntialias(antialiasDecoration);
709 // Fall through 705 // Fall through
710 default: 706 default:
711 context->drawLineForText(FloatPoint(start), width, isPrinting); 707 context->drawLineForText(FloatPoint(start), width, isPrinting);
712 708
713 if (decoration.style == TextDecorationStyleDouble) 709 if (decoration.style() == TextDecorationStyleDouble)
714 context->drawLineForText(start + FloatPoint(0, doubleOffset), width, isPrinting); 710 context->drawLineForText(start + FloatPoint(0, doubleOffset), width, isPrinting);
715 } 711 }
716 } 712 }
717 713
718 void InlineTextBoxPainter::paintDecoration(const PaintInfo& paintInfo, const Lay outPoint& boxOrigin, TextDecoration deco) 714 void InlineTextBoxPainter::paintDecorations(const PaintInfo& paintInfo, const La youtPoint& boxOrigin, const Vector<AppliedTextDecoration>& decorations)
719 { 715 {
720 if (m_inlineTextBox.truncation() == cFullTruncation) 716 if (m_inlineTextBox.truncation() == cFullTruncation)
721 return; 717 return;
722 718
723 GraphicsContext* context = paintInfo.context; 719 GraphicsContext* context = paintInfo.context;
724 GraphicsContextStateSaver stateSaver(*context); 720 GraphicsContextStateSaver stateSaver(*context);
725 721
726 LayoutPoint localOrigin(boxOrigin); 722 LayoutPoint localOrigin(boxOrigin);
727 723
728 LayoutUnit width = m_inlineTextBox.logicalWidth(); 724 LayoutUnit width = m_inlineTextBox.logicalWidth();
729 if (m_inlineTextBox.truncation() != cNoTruncation) { 725 if (m_inlineTextBox.truncation() != cNoTruncation) {
730 width = m_inlineTextBox.lineLayoutItem().width(m_inlineTextBox.start(), m_inlineTextBox.truncation(), m_inlineTextBox.textPos(), m_inlineTextBox.isLeftT oRightDirection() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle()); 726 width = m_inlineTextBox.lineLayoutItem().width(m_inlineTextBox.start(), m_inlineTextBox.truncation(), m_inlineTextBox.textPos(), m_inlineTextBox.isLeftT oRightDirection() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle());
731 if (!m_inlineTextBox.isLeftToRightDirection()) 727 if (!m_inlineTextBox.isLeftToRightDirection())
732 localOrigin.move(m_inlineTextBox.logicalWidth() - width, 0); 728 localOrigin.move(m_inlineTextBox.logicalWidth() - width, 0);
733 } 729 }
734 730
735 // Get the text decoration colors.
736 LayoutObject::AppliedTextDecoration underline, overline, linethrough;
737 LayoutObject& textBoxLayoutObject = *LineLayoutPaintShim::layoutObjectFrom(m _inlineTextBox.lineLayoutItem());
738 textBoxLayoutObject.getTextDecorations(deco, underline, overline, linethroug h, true);
739 if (m_inlineTextBox.isFirstLineStyle())
740 textBoxLayoutObject.getTextDecorations(deco, underline, overline, lineth rough, true, true);
741
742 // Use a special function for underlines to get the positioning exactly righ t. 731 // Use a special function for underlines to get the positioning exactly righ t.
743 bool isPrinting = paintInfo.isPrinting(); 732 bool isPrinting = paintInfo.isPrinting();
744 733
734 LayoutObject& textBoxLayoutObject = *LineLayoutPaintShim::layoutObjectFrom(m _inlineTextBox.lineLayoutItem());
745 const ComputedStyle& styleToUse = textBoxLayoutObject.styleRef(m_inlineTextB ox.isFirstLineStyle()); 735 const ComputedStyle& styleToUse = textBoxLayoutObject.styleRef(m_inlineTextB ox.isFirstLineStyle());
746 float baseline = styleToUse.fontMetrics().ascent(); 736 float baseline = styleToUse.fontMetrics().ascent();
747 737
748 // Set the thick of the line to be 10% (or something else ?)of the computed font size and not less than 1px. 738 // Set the thick of the line to be 10% (or something else ?)of the computed font size and not less than 1px.
749 // Using computedFontSize should take care of zoom as well. 739 // Using computedFontSize should take care of zoom as well.
750 740
751 // Update Underline thickness, in case we have Faulty Font Metrics calculati ng underline thickness by old method. 741 // Update Underline thickness, in case we have Faulty Font Metrics calculati ng underline thickness by old method.
752 float textDecorationThickness = styleToUse.fontMetrics().underlineThickness( ); 742 float textDecorationThickness = styleToUse.fontMetrics().underlineThickness( );
753 int fontHeightInt = (int)(styleToUse.fontMetrics().floatHeight() + 0.5); 743 int fontHeightInt = (int)(styleToUse.fontMetrics().floatHeight() + 0.5);
754 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei ghtInt >> 1))) 744 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei ghtInt >> 1)))
755 textDecorationThickness = std::max(1.f, styleToUse.computedFontSize() / 10.f); 745 textDecorationThickness = std::max(1.f, styleToUse.computedFontSize() / 10.f);
756 746
757 context->setStrokeThickness(textDecorationThickness); 747 context->setStrokeThickness(textDecorationThickness);
758 748
759 bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, unde rline.style, linethrough.style); 749 bool antialiasDecoration = false;
750 for (const AppliedTextDecoration& decoration : decorations)
751 antialiasDecoration |= shouldSetDecorationAntialias(decoration.style());
760 752
761 // Offset between lines - always non-zero, so lines never cross each other. 753 // Offset between lines - always non-zero, so lines never cross each other.
762 float doubleOffset = textDecorationThickness + 1.f; 754 float doubleOffset = textDecorationThickness + 1.f;
763 755
764 if (deco & TextDecorationUnderline) { 756 for (const AppliedTextDecoration& decoration : decorations) {
765 const int underlineOffset = computeUnderlineOffset(styleToUse.textUnderl inePosition(), styleToUse.fontMetrics(), &m_inlineTextBox, textDecorationThickne ss); 757 if (decoration.lines() & TextDecorationUnderline) {
766 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint(0, underlineOffset), width.toFloat(), doubleOffset, 1, underline, textDecorationThi ckness, antialiasDecoration, isPrinting); 758 const int underlineOffset = computeUnderlineOffset(styleToUse.textUn derlinePosition(), styleToUse.fontMetrics(), &m_inlineTextBox, textDecorationThi ckness);
767 } 759 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint (0, underlineOffset), width.toFloat(), doubleOffset, 1, decoration, textDecorati onThickness, antialiasDecoration, isPrinting);
768 if (deco & TextDecorationOverline) { 760 }
769 paintAppliedDecoration(context, FloatPoint(localOrigin), width.toFloat() , -doubleOffset, 1, overline, textDecorationThickness, antialiasDecoration, isPr inting); 761 if (decoration.lines() & TextDecorationOverline) {
770 } 762 paintAppliedDecoration(context, FloatPoint(localOrigin), width.toFlo at(), -doubleOffset, 1, decoration, textDecorationThickness, antialiasDecoration , isPrinting);
771 if (deco & TextDecorationLineThrough) { 763 }
772 const float lineThroughOffset = 2 * baseline / 3; 764 if (decoration.lines() & TextDecorationLineThrough) {
773 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint(0, lineThroughOffset), width.toFloat(), doubleOffset, 0, linethrough, textDecoratio nThickness, antialiasDecoration, isPrinting); 765 const float lineThroughOffset = 2 * baseline / 3;
766 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint (0, lineThroughOffset), width.toFloat(), doubleOffset, 0, decoration, textDecora tionThickness, antialiasDecoration, isPrinting);
767 }
774 } 768 }
775 } 769 }
776 770
777 void InlineTextBoxPainter::paintCompositionUnderline(GraphicsContext* ctx, const LayoutPoint& boxOrigin, const CompositionUnderline& underline) 771 void InlineTextBoxPainter::paintCompositionUnderline(GraphicsContext* ctx, const LayoutPoint& boxOrigin, const CompositionUnderline& underline)
778 { 772 {
779 if (underline.color == Color::transparent) 773 if (underline.color == Color::transparent)
780 return; 774 return;
781 775
782 if (m_inlineTextBox.truncation() == cFullTruncation) 776 if (m_inlineTextBox.truncation() == cFullTruncation)
783 return; 777 return;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetri cs().ascent()); 837 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetri cs().ascent());
844 TextPainter textPainter(pt, font, run, textOrigin, boxRect, m_inline TextBox.isHorizontal()); 838 TextPainter textPainter(pt, font, run, textOrigin, boxRect, m_inline TextBox.isHorizontal());
845 839
846 textPainter.paint(sPos, ePos, length, textStyle, 0); 840 textPainter.paint(sPos, ePos, length, textStyle, 0);
847 } 841 }
848 } 842 }
849 } 843 }
850 844
851 845
852 } // namespace blink 846 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698