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

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, 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/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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698