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 "core/paint/InlineTextBoxPainter.h" | 5 #include "core/paint/InlineTextBoxPainter.h" |
6 | 6 |
7 #include "core/editing/CompositionUnderline.h" | 7 #include "core/editing/CompositionUnderline.h" |
8 #include "core/editing/Editor.h" | 8 #include "core/editing/Editor.h" |
9 #include "core/editing/markers/DocumentMarkerController.h" | 9 #include "core/editing/markers/DocumentMarkerController.h" |
10 #include "core/editing/markers/RenderedDocumentMarker.h" | 10 #include "core/editing/markers/RenderedDocumentMarker.h" |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 | 144 |
145 // Determine text colors. | 145 // Determine text colors. |
146 TextPainter::Style textStyle = TextPainter::textPaintingStyle(m_inlineTextBo
x.getLineLayoutItem(), styleToUse, paintInfo); | 146 TextPainter::Style textStyle = TextPainter::textPaintingStyle(m_inlineTextBo
x.getLineLayoutItem(), styleToUse, paintInfo); |
147 TextPainter::Style selectionStyle = TextPainter::selectionPaintingStyle(m_in
lineTextBox.getLineLayoutItem(), haveSelection, paintInfo, textStyle); | 147 TextPainter::Style selectionStyle = TextPainter::selectionPaintingStyle(m_in
lineTextBox.getLineLayoutItem(), haveSelection, paintInfo, textStyle); |
148 bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection); | 148 bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection); |
149 bool paintSelectedTextSeparately = !paintSelectedTextOnly && textStyle != se
lectionStyle; | 149 bool paintSelectedTextSeparately = !paintSelectedTextOnly && textStyle != se
lectionStyle; |
150 | 150 |
151 // Set our font. | 151 // Set our font. |
152 const Font& font = styleToUse.font(); | 152 const Font& font = styleToUse.font(); |
153 | 153 |
154 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetrics().asc
ent()); | 154 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.getFontMetrics().
ascent()); |
155 | 155 |
156 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
include selection | 156 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
include selection |
157 // and composition highlights. | 157 // and composition highlights. |
158 if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseT
extClip && !isPrinting) { | 158 if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseT
extClip && !isPrinting) { |
159 paintDocumentMarkers(paintInfo, boxOrigin, styleToUse, font, DocumentMar
kerPaintPhase::Background); | 159 paintDocumentMarkers(paintInfo, boxOrigin, styleToUse, font, DocumentMar
kerPaintPhase::Background); |
160 | 160 |
161 const LayoutObject& textBoxLayoutObject = *LineLayoutAPIShim::layoutObje
ctFrom(m_inlineTextBox.getLineLayoutItem()); | 161 const LayoutObject& textBoxLayoutObject = *LineLayoutAPIShim::layoutObje
ctFrom(m_inlineTextBox.getLineLayoutItem()); |
162 if (haveSelection && !paintsCompositionMarkers(textBoxLayoutObject)) { | 162 if (haveSelection && !paintsCompositionMarkers(textBoxLayoutObject)) { |
163 if (combinedText) | 163 if (combinedText) |
164 paintSelection<InlineTextBoxPainter::PaintOptions::CombinedText>
(context, boxRect, styleToUse, font, selectionStyle.fillColor, combinedText); | 164 paintSelection<InlineTextBoxPainter::PaintOptions::CombinedText>
(context, boxRect, styleToUse, font, selectionStyle.fillColor, combinedText); |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 width = LayoutUnit(markerRect.width()); | 415 width = LayoutUnit(markerRect.width()); |
416 } | 416 } |
417 | 417 |
418 // IMPORTANT: The misspelling underline is not considered when calculating t
he text bounds, so we have to | 418 // IMPORTANT: The misspelling underline is not considered when calculating t
he text bounds, so we have to |
419 // make sure to fit within those bounds. This means the top pixel(s) of the
underline will overlap the | 419 // make sure to fit within those bounds. This means the top pixel(s) of the
underline will overlap the |
420 // bottom pixel(s) of the glyphs in smaller font sizes. The alternatives ar
e to increase the line spacing (bad!!) | 420 // bottom pixel(s) of the glyphs in smaller font sizes. The alternatives ar
e to increase the line spacing (bad!!) |
421 // or decrease the underline thickness. The overlap is actually the most us
eful, and matches what AppKit does. | 421 // or decrease the underline thickness. The overlap is actually the most us
eful, and matches what AppKit does. |
422 // So, we generally place the underline at the bottom of the text, but in la
rger fonts that's not so good so | 422 // So, we generally place the underline at the bottom of the text, but in la
rger fonts that's not so good so |
423 // we pin to two pixels under the baseline. | 423 // we pin to two pixels under the baseline. |
424 int lineThickness = misspellingLineThickness; | 424 int lineThickness = misspellingLineThickness; |
425 int baseline = m_inlineTextBox.getLineLayoutItem().style(m_inlineTextBox.isF
irstLineStyle())->fontMetrics().ascent(); | 425 int baseline = m_inlineTextBox.getLineLayoutItem().style(m_inlineTextBox.isF
irstLineStyle())->getFontMetrics().ascent(); |
426 int descent = m_inlineTextBox.logicalHeight() - baseline; | 426 int descent = m_inlineTextBox.logicalHeight() - baseline; |
427 int underlineOffset; | 427 int underlineOffset; |
428 if (descent <= (lineThickness + 2)) { | 428 if (descent <= (lineThickness + 2)) { |
429 // Place the underline at the very bottom of the text in small/medium fo
nts. | 429 // Place the underline at the very bottom of the text in small/medium fo
nts. |
430 underlineOffset = m_inlineTextBox.logicalHeight() - lineThickness; | 430 underlineOffset = m_inlineTextBox.logicalHeight() - lineThickness; |
431 } else { | 431 } else { |
432 // In larger fonts, though, place the underline up near the baseline to
prevent a big gap. | 432 // In larger fonts, though, place the underline up near the baseline to
prevent a big gap. |
433 underlineOffset = baseline + 2; | 433 underlineOffset = baseline + 2; |
434 } | 434 } |
435 context.drawLineForDocumentMarker(FloatPoint((boxOrigin.x() + start).toFloat
(), (boxOrigin.y() + underlineOffset).toFloat()), width.toFloat(), lineStyleForM
arkerType(marker->type())); | 435 context.drawLineForDocumentMarker(FloatPoint((boxOrigin.x() + start).toFloat
(), (boxOrigin.y() + underlineOffset).toFloat()), width.toFloat(), lineStyleForM
arkerType(marker->type())); |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 LayoutObject::AppliedTextDecoration underline, overline, linethrough; | 746 LayoutObject::AppliedTextDecoration underline, overline, linethrough; |
747 LayoutObject& textBoxLayoutObject = *LineLayoutAPIShim::layoutObjectFrom(m_i
nlineTextBox.getLineLayoutItem()); | 747 LayoutObject& textBoxLayoutObject = *LineLayoutAPIShim::layoutObjectFrom(m_i
nlineTextBox.getLineLayoutItem()); |
748 textBoxLayoutObject.getTextDecorations(deco, underline, overline, linethroug
h, true); | 748 textBoxLayoutObject.getTextDecorations(deco, underline, overline, linethroug
h, true); |
749 if (m_inlineTextBox.isFirstLineStyle()) | 749 if (m_inlineTextBox.isFirstLineStyle()) |
750 textBoxLayoutObject.getTextDecorations(deco, underline, overline, lineth
rough, true, true); | 750 textBoxLayoutObject.getTextDecorations(deco, underline, overline, lineth
rough, true, true); |
751 | 751 |
752 // Use a special function for underlines to get the positioning exactly righ
t. | 752 // Use a special function for underlines to get the positioning exactly righ
t. |
753 bool isPrinting = paintInfo.isPrinting(); | 753 bool isPrinting = paintInfo.isPrinting(); |
754 | 754 |
755 const ComputedStyle& styleToUse = textBoxLayoutObject.styleRef(m_inlineTextB
ox.isFirstLineStyle()); | 755 const ComputedStyle& styleToUse = textBoxLayoutObject.styleRef(m_inlineTextB
ox.isFirstLineStyle()); |
756 float baseline = styleToUse.fontMetrics().ascent(); | 756 float baseline = styleToUse.getFontMetrics().ascent(); |
757 | 757 |
758 // Set the thick of the line to be 10% (or something else ?)of the computed
font size and not less than 1px. | 758 // Set the thick of the line to be 10% (or something else ?)of the computed
font size and not less than 1px. |
759 // Using computedFontSize should take care of zoom as well. | 759 // Using computedFontSize should take care of zoom as well. |
760 | 760 |
761 // Update Underline thickness, in case we have Faulty Font Metrics calculati
ng underline thickness by old method. | 761 // Update Underline thickness, in case we have Faulty Font Metrics calculati
ng underline thickness by old method. |
762 float textDecorationThickness = styleToUse.fontMetrics().underlineThickness(
); | 762 float textDecorationThickness = styleToUse.getFontMetrics().underlineThickne
ss(); |
763 int fontHeightInt = (int)(styleToUse.fontMetrics().floatHeight() + 0.5); | 763 int fontHeightInt = (int)(styleToUse.getFontMetrics().floatHeight() + 0.5); |
764 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei
ghtInt >> 1))) | 764 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei
ghtInt >> 1))) |
765 textDecorationThickness = std::max(1.f, styleToUse.computedFontSize() /
10.f); | 765 textDecorationThickness = std::max(1.f, styleToUse.computedFontSize() /
10.f); |
766 | 766 |
767 context.setStrokeThickness(textDecorationThickness); | 767 context.setStrokeThickness(textDecorationThickness); |
768 | 768 |
769 bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, unde
rline.style, linethrough.style); | 769 bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, unde
rline.style, linethrough.style); |
770 | 770 |
771 // Offset between lines - always non-zero, so lines never cross each other. | 771 // Offset between lines - always non-zero, so lines never cross each other. |
772 float doubleOffset = textDecorationThickness + 1.f; | 772 float doubleOffset = textDecorationThickness + 1.f; |
773 | 773 |
774 if (deco & TextDecorationUnderline) { | 774 if (deco & TextDecorationUnderline) { |
775 const int underlineOffset = computeUnderlineOffset(styleToUse.getTextUnd
erlinePosition(), styleToUse.fontMetrics(), &m_inlineTextBox, textDecorationThic
kness); | 775 const int underlineOffset = computeUnderlineOffset(styleToUse.getTextUnd
erlinePosition(), styleToUse.getFontMetrics(), &m_inlineTextBox, textDecorationT
hickness); |
776 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint(0,
underlineOffset), width.toFloat(), doubleOffset, 1, underline, textDecorationThi
ckness, antialiasDecoration, isPrinting); | 776 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint(0,
underlineOffset), width.toFloat(), doubleOffset, 1, underline, textDecorationThi
ckness, antialiasDecoration, isPrinting); |
777 } | 777 } |
778 if (deco & TextDecorationOverline) { | 778 if (deco & TextDecorationOverline) { |
779 paintAppliedDecoration(context, FloatPoint(localOrigin), width.toFloat()
, -doubleOffset, 1, overline, textDecorationThickness, antialiasDecoration, isPr
inting); | 779 paintAppliedDecoration(context, FloatPoint(localOrigin), width.toFloat()
, -doubleOffset, 1, overline, textDecorationThickness, antialiasDecoration, isPr
inting); |
780 } | 780 } |
781 if (deco & TextDecorationLineThrough) { | 781 if (deco & TextDecorationLineThrough) { |
782 const float lineThroughOffset = 2 * baseline / 3; | 782 const float lineThroughOffset = 2 * baseline / 3; |
783 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint(0,
lineThroughOffset), width.toFloat(), doubleOffset, 0, linethrough, textDecoratio
nThickness, antialiasDecoration, isPrinting); | 783 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint(0,
lineThroughOffset), width.toFloat(), doubleOffset, 0, linethrough, textDecoratio
nThickness, antialiasDecoration, isPrinting); |
784 } | 784 } |
785 } | 785 } |
(...skipping 20 matching lines...) Expand all Loading... |
806 // |logicalWidth| - |start| - |width|. We will draw that line, but | 806 // |logicalWidth| - |start| - |width|. We will draw that line, but |
807 // backwards: |logicalWidth| - |start| - |width| to |logicalWidth| - |start|
. | 807 // backwards: |logicalWidth| - |start| - |width| to |logicalWidth| - |start|
. |
808 if (!m_inlineTextBox.isLeftToRightDirection()) | 808 if (!m_inlineTextBox.isLeftToRightDirection()) |
809 start = m_inlineTextBox.logicalWidth().toFloat() - width - start; | 809 start = m_inlineTextBox.logicalWidth().toFloat() - width - start; |
810 | 810 |
811 | 811 |
812 // Thick marked text underlines are 2px thick as long as there is room for t
he 2px line under the baseline. | 812 // Thick marked text underlines are 2px thick as long as there is room for t
he 2px line under the baseline. |
813 // All other marked text underlines are 1px thick. | 813 // All other marked text underlines are 1px thick. |
814 // If there's not enough space the underline will touch or overlap character
s. | 814 // If there's not enough space the underline will touch or overlap character
s. |
815 int lineThickness = 1; | 815 int lineThickness = 1; |
816 int baseline = m_inlineTextBox.getLineLayoutItem().style(m_inlineTextBox.isF
irstLineStyle())->fontMetrics().ascent(); | 816 int baseline = m_inlineTextBox.getLineLayoutItem().style(m_inlineTextBox.isF
irstLineStyle())->getFontMetrics().ascent(); |
817 if (underline.thick && m_inlineTextBox.logicalHeight() - baseline >= 2) | 817 if (underline.thick && m_inlineTextBox.logicalHeight() - baseline >= 2) |
818 lineThickness = 2; | 818 lineThickness = 2; |
819 | 819 |
820 // We need to have some space between underlines of subsequent clauses, beca
use some input methods do not use different underline styles for those. | 820 // We need to have some space between underlines of subsequent clauses, beca
use some input methods do not use different underline styles for those. |
821 // We make each line shorter, which has a harmless side effect of shortening
the first and last clauses, too. | 821 // We make each line shorter, which has a harmless side effect of shortening
the first and last clauses, too. |
822 start += 1; | 822 start += 1; |
823 width -= 2; | 823 width -= 2; |
824 | 824 |
825 context.setStrokeColor(underline.color); | 825 context.setStrokeColor(underline.color); |
826 context.setStrokeThickness(lineThickness); | 826 context.setStrokeThickness(lineThickness); |
(...skipping 12 matching lines...) Expand all Loading... |
839 | 839 |
840 Color textColor = LayoutTheme::theme().platformTextSearchColor(marker->activ
eMatch()); | 840 Color textColor = LayoutTheme::theme().platformTextSearchColor(marker->activ
eMatch()); |
841 if (style.visitedDependentColor(CSSPropertyColor) == textColor) | 841 if (style.visitedDependentColor(CSSPropertyColor) == textColor) |
842 return; | 842 return; |
843 TextPainter::Style textStyle; | 843 TextPainter::Style textStyle; |
844 textStyle.currentColor = textStyle.fillColor = textStyle.strokeColor = textS
tyle.emphasisMarkColor = textColor; | 844 textStyle.currentColor = textStyle.fillColor = textStyle.strokeColor = textS
tyle.emphasisMarkColor = textColor; |
845 textStyle.strokeWidth = style.textStrokeWidth(); | 845 textStyle.strokeWidth = style.textStrokeWidth(); |
846 textStyle.shadow = 0; | 846 textStyle.shadow = 0; |
847 | 847 |
848 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), m_i
nlineTextBox.logicalHeight())); | 848 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), m_i
nlineTextBox.logicalHeight())); |
849 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetrics().asc
ent()); | 849 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.getFontMetrics().
ascent()); |
850 TextPainter textPainter(paintInfo.context, font, run, textOrigin, boxRect, m
_inlineTextBox.isHorizontal()); | 850 TextPainter textPainter(paintInfo.context, font, run, textOrigin, boxRect, m
_inlineTextBox.isHorizontal()); |
851 | 851 |
852 textPainter.paint(sPos, ePos, m_inlineTextBox.len(), textStyle, 0); | 852 textPainter.paint(sPos, ePos, m_inlineTextBox.len(), textStyle, 0); |
853 } | 853 } |
854 | 854 |
855 void InlineTextBoxPainter::paintTextMatchMarkerBackground(const PaintInfo& paint
Info, const LayoutPoint& boxOrigin, DocumentMarker* marker, const ComputedStyle&
style, const Font& font) | 855 void InlineTextBoxPainter::paintTextMatchMarkerBackground(const PaintInfo& paint
Info, const LayoutPoint& boxOrigin, DocumentMarker* marker, const ComputedStyle&
style, const Font& font) |
856 { | 856 { |
857 if (!LineLayoutAPIShim::layoutObjectFrom(m_inlineTextBox.getLineLayoutItem()
)->frame()->editor().markedTextMatchesAreHighlighted()) | 857 if (!LineLayoutAPIShim::layoutObjectFrom(m_inlineTextBox.getLineLayoutItem()
)->frame()->editor().markedTextMatchesAreHighlighted()) |
858 return; | 858 return; |
859 | 859 |
860 // Use same y positioning and height as for selection, so that when the sele
ction and this highlight are on | 860 // Use same y positioning and height as for selection, so that when the sele
ction and this highlight are on |
861 // the same word there are no pieces sticking out. | 861 // the same word there are no pieces sticking out. |
862 int deltaY = m_inlineTextBox.getLineLayoutItem().style()->isFlippedLinesWrit
ingMode() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBo
ttom() : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); | 862 int deltaY = m_inlineTextBox.getLineLayoutItem().style()->isFlippedLinesWrit
ingMode() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBo
ttom() : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); |
863 int selHeight = m_inlineTextBox.root().selectionHeight(); | 863 int selHeight = m_inlineTextBox.root().selectionHeight(); |
864 | 864 |
865 int sPos = std::max(marker->startOffset() - m_inlineTextBox.start(), (unsign
ed)0); | 865 int sPos = std::max(marker->startOffset() - m_inlineTextBox.start(), (unsign
ed)0); |
866 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(), m_inlineT
extBox.len()); | 866 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(), m_inlineT
extBox.len()); |
867 TextRun run = m_inlineTextBox.constructTextRun(style, font); | 867 TextRun run = m_inlineTextBox.constructTextRun(style, font); |
868 | 868 |
869 Color color = LayoutTheme::theme().platformTextSearchHighlightColor(marker->
activeMatch()); | 869 Color color = LayoutTheme::theme().platformTextSearchHighlightColor(marker->
activeMatch()); |
870 GraphicsContext& context = paintInfo.context; | 870 GraphicsContext& context = paintInfo.context; |
871 GraphicsContextStateSaver stateSaver(context); | 871 GraphicsContextStateSaver stateSaver(context); |
872 context.clip(FloatRect(boxOrigin.x().toFloat(), (boxOrigin.y() - deltaY).toF
loat(), m_inlineTextBox.logicalWidth().toFloat(), selHeight)); | 872 context.clip(FloatRect(boxOrigin.x().toFloat(), (boxOrigin.y() - deltaY).toF
loat(), m_inlineTextBox.logicalWidth().toFloat(), selHeight)); |
873 context.drawHighlightForText(font, run, FloatPoint(boxOrigin.x().toFloat(),
(boxOrigin.y() - deltaY).toFloat()), selHeight, color, sPos, ePos); | 873 context.drawHighlightForText(font, run, FloatPoint(boxOrigin.x().toFloat(),
(boxOrigin.y() - deltaY).toFloat()), selHeight, color, sPos, ePos); |
874 } | 874 } |
875 | 875 |
876 | 876 |
877 } // namespace blink | 877 } // namespace blink |
OLD | NEW |