| 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/dom/DocumentMarkerController.h" | 8 #include "core/dom/DocumentMarkerController.h" |
| 9 #include "core/dom/RenderedDocumentMarker.h" | 9 #include "core/dom/RenderedDocumentMarker.h" |
| 10 #include "core/editing/CompositionUnderline.h" | 10 #include "core/editing/CompositionUnderline.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 | 36 |
| 37 static TextBlobPtr* addToTextBlobCache(InlineTextBox& inlineTextBox) | 37 static TextBlobPtr* addToTextBlobCache(InlineTextBox& inlineTextBox) |
| 38 { | 38 { |
| 39 if (!gTextBlobCache) | 39 if (!gTextBlobCache) |
| 40 gTextBlobCache = new InlineTextBoxBlobCacheMap; | 40 gTextBlobCache = new InlineTextBoxBlobCacheMap; |
| 41 return &gTextBlobCache->add(&inlineTextBox, nullptr).storedValue->value; | 41 return &gTextBlobCache->add(&inlineTextBox, nullptr).storedValue->value; |
| 42 } | 42 } |
| 43 | 43 |
| 44 void InlineTextBoxPainter::paint(const PaintInfo& paintInfo, const LayoutPoint&
paintOffset) | 44 void InlineTextBoxPainter::paint(const PaintInfo& paintInfo, const LayoutPoint&
paintOffset) |
| 45 { | 45 { |
| 46 if (m_inlineTextBox.isLineBreak() || !paintInfo.shouldPaintWithinRoot(&m_inl
ineTextBox.renderer()) || m_inlineTextBox.renderer().style()->visibility() != VI
SIBLE | 46 if (m_inlineTextBox.isLineBreak() || !paintInfo.shouldPaintWithinRoot(&m_inl
ineTextBox.layoutObject()) || m_inlineTextBox.layoutObject().style()->visibility
() != VISIBLE |
| 47 || m_inlineTextBox.truncation() == cFullTruncation || paintInfo.phase ==
PaintPhaseOutline || !m_inlineTextBox.len()) | 47 || m_inlineTextBox.truncation() == cFullTruncation || paintInfo.phase ==
PaintPhaseOutline || !m_inlineTextBox.len()) |
| 48 return; | 48 return; |
| 49 | 49 |
| 50 ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintP
haseChildOutlines); | 50 ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintP
haseChildOutlines); |
| 51 | 51 |
| 52 LayoutRect logicalVisualOverflow = m_inlineTextBox.logicalOverflowRect(); | 52 LayoutRect logicalVisualOverflow = m_inlineTextBox.logicalOverflowRect(); |
| 53 LayoutUnit logicalStart = logicalVisualOverflow.x() + (m_inlineTextBox.isHor
izontal() ? paintOffset.x() : paintOffset.y()); | 53 LayoutUnit logicalStart = logicalVisualOverflow.x() + (m_inlineTextBox.isHor
izontal() ? paintOffset.x() : paintOffset.y()); |
| 54 LayoutUnit logicalExtent = logicalVisualOverflow.width(); | 54 LayoutUnit logicalExtent = logicalVisualOverflow.width(); |
| 55 | 55 |
| 56 LayoutUnit paintEnd = m_inlineTextBox.isHorizontal() ? paintInfo.rect.maxX()
: paintInfo.rect.maxY(); | 56 LayoutUnit paintEnd = m_inlineTextBox.isHorizontal() ? paintInfo.rect.maxX()
: paintInfo.rect.maxY(); |
| 57 LayoutUnit paintStart = m_inlineTextBox.isHorizontal() ? paintInfo.rect.x()
: paintInfo.rect.y(); | 57 LayoutUnit paintStart = m_inlineTextBox.isHorizontal() ? paintInfo.rect.x()
: paintInfo.rect.y(); |
| 58 | 58 |
| 59 // We round the y-axis to ensure consistent line heights. | 59 // We round the y-axis to ensure consistent line heights. |
| 60 LayoutPoint adjustedPaintOffset = LayoutPoint(paintOffset.x(), paintOffset.y
().round()); | 60 LayoutPoint adjustedPaintOffset = LayoutPoint(paintOffset.x(), paintOffset.y
().round()); |
| 61 | 61 |
| 62 if (logicalStart >= paintEnd || logicalStart + logicalExtent <= paintStart) | 62 if (logicalStart >= paintEnd || logicalStart + logicalExtent <= paintStart) |
| 63 return; | 63 return; |
| 64 | 64 |
| 65 bool isPrinting = m_inlineTextBox.renderer().document().printing(); | 65 bool isPrinting = m_inlineTextBox.layoutObject().document().printing(); |
| 66 | 66 |
| 67 // Determine whether or not we're selected. | 67 // Determine whether or not we're selected. |
| 68 bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip &&
m_inlineTextBox.selectionState() != LayoutObject::SelectionNone; | 68 bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip &&
m_inlineTextBox.selectionState() != LayoutObject::SelectionNone; |
| 69 if (!haveSelection && paintInfo.phase == PaintPhaseSelection) { | 69 if (!haveSelection && paintInfo.phase == PaintPhaseSelection) { |
| 70 // When only painting the selection, don't bother to paint if there is n
one. | 70 // When only painting the selection, don't bother to paint if there is n
one. |
| 71 return; | 71 return; |
| 72 } | 72 } |
| 73 | 73 |
| 74 // The text clip phase already has a DrawingRecorder. Text clips are initiat
ed only in BoxPainter::paintLayerExtended, which is already | 74 // The text clip phase already has a DrawingRecorder. Text clips are initiat
ed only in BoxPainter::paintLayerExtended, which is already |
| 75 // within a DrawingRecorder. | 75 // within a DrawingRecorder. |
| 76 OwnPtr<DrawingRecorder> drawingRecorder; | 76 OwnPtr<DrawingRecorder> drawingRecorder; |
| 77 if (RuntimeEnabledFeatures::slimmingPaintEnabled() && paintInfo.phase != Pai
ntPhaseTextClip) { | 77 if (RuntimeEnabledFeatures::slimmingPaintEnabled() && paintInfo.phase != Pai
ntPhaseTextClip) { |
| 78 LayoutRect paintRect = logicalVisualOverflow; | 78 LayoutRect paintRect = logicalVisualOverflow; |
| 79 paintRect.moveBy(adjustedPaintOffset); | 79 paintRect.moveBy(adjustedPaintOffset); |
| 80 drawingRecorder = adoptPtr(new DrawingRecorder(paintInfo.context, m_inli
neTextBox.displayItemClient(), DisplayItem::paintPhaseToDrawingType(paintInfo.ph
ase), paintRect)); | 80 drawingRecorder = adoptPtr(new DrawingRecorder(paintInfo.context, m_inli
neTextBox.displayItemClient(), DisplayItem::paintPhaseToDrawingType(paintInfo.ph
ase), paintRect)); |
| 81 if (drawingRecorder->canUseCachedDrawing()) | 81 if (drawingRecorder->canUseCachedDrawing()) |
| 82 return; | 82 return; |
| 83 } | 83 } |
| 84 | 84 |
| 85 if (m_inlineTextBox.truncation() != cNoTruncation) { | 85 if (m_inlineTextBox.truncation() != cNoTruncation) { |
| 86 if (m_inlineTextBox.renderer().containingBlock()->style()->isLeftToRight
Direction() != m_inlineTextBox.isLeftToRightDirection()) { | 86 if (m_inlineTextBox.layoutObject().containingBlock()->style()->isLeftToR
ightDirection() != m_inlineTextBox.isLeftToRightDirection()) { |
| 87 // Make the visible fragment of text hug the edge closest to the res
t of the run by moving the origin | 87 // Make the visible fragment of text hug the edge closest to the res
t of the run by moving the origin |
| 88 // at which we start drawing text. | 88 // at which we start drawing text. |
| 89 // e.g. In the case of LTR text truncated in an RTL Context, the cor
rect behavior is: | 89 // e.g. In the case of LTR text truncated in an RTL Context, the cor
rect behavior is: |
| 90 // |Hello|CBA| -> |...He|CBA| | 90 // |Hello|CBA| -> |...He|CBA| |
| 91 // In order to draw the fragment "He" aligned to the right edge of i
t's box, we need to start drawing | 91 // In order to draw the fragment "He" aligned to the right edge of i
t's box, we need to start drawing |
| 92 // farther to the right. | 92 // farther to the right. |
| 93 // NOTE: WebKit's behavior differs from that of IE which appears to
just overlay the ellipsis on top of the | 93 // NOTE: WebKit's behavior differs from that of IE which appears to
just overlay the ellipsis on top of the |
| 94 // truncated string i.e. |Hello|CBA| -> |...lo|CBA| | 94 // truncated string i.e. |Hello|CBA| -> |...lo|CBA| |
| 95 LayoutUnit widthOfVisibleText = m_inlineTextBox.renderer().width(m_i
nlineTextBox.start(), m_inlineTextBox.truncation(), m_inlineTextBox.textPos(), m
_inlineTextBox.isLeftToRightDirection() ? LTR : RTL, m_inlineTextBox.isFirstLine
Style()); | 95 LayoutUnit widthOfVisibleText = m_inlineTextBox.layoutObject().width
(m_inlineTextBox.start(), m_inlineTextBox.truncation(), m_inlineTextBox.textPos(
), m_inlineTextBox.isLeftToRightDirection() ? LTR : RTL, m_inlineTextBox.isFirst
LineStyle()); |
| 96 LayoutUnit widthOfHiddenText = m_inlineTextBox.logicalWidth() - widt
hOfVisibleText; | 96 LayoutUnit widthOfHiddenText = m_inlineTextBox.logicalWidth() - widt
hOfVisibleText; |
| 97 // FIXME: The hit testing logic also needs to take this translation
into account. | 97 // FIXME: The hit testing logic also needs to take this translation
into account. |
| 98 LayoutSize truncationOffset(m_inlineTextBox.isLeftToRightDirection()
? widthOfHiddenText : -widthOfHiddenText, 0); | 98 LayoutSize truncationOffset(m_inlineTextBox.isLeftToRightDirection()
? widthOfHiddenText : -widthOfHiddenText, 0); |
| 99 adjustedPaintOffset.move(m_inlineTextBox.isHorizontal() ? truncation
Offset : truncationOffset.transposedSize()); | 99 adjustedPaintOffset.move(m_inlineTextBox.isHorizontal() ? truncation
Offset : truncationOffset.transposedSize()); |
| 100 } | 100 } |
| 101 } | 101 } |
| 102 | 102 |
| 103 GraphicsContext* context = paintInfo.context; | 103 GraphicsContext* context = paintInfo.context; |
| 104 const LayoutStyle& styleToUse = m_inlineTextBox.renderer().styleRef(m_inline
TextBox.isFirstLineStyle()); | 104 const LayoutStyle& styleToUse = m_inlineTextBox.layoutObject().styleRef(m_in
lineTextBox.isFirstLineStyle()); |
| 105 | 105 |
| 106 FloatPoint boxOrigin = m_inlineTextBox.locationIncludingFlipping().toFloatPo
int(); | 106 FloatPoint boxOrigin = m_inlineTextBox.locationIncludingFlipping().toFloatPo
int(); |
| 107 boxOrigin.move(adjustedPaintOffset.x().toFloat(), adjustedPaintOffset.y().to
Float()); | 107 boxOrigin.move(adjustedPaintOffset.x().toFloat(), adjustedPaintOffset.y().to
Float()); |
| 108 FloatRect boxRect(boxOrigin, FloatSize(m_inlineTextBox.logicalWidth(), m_inl
ineTextBox.logicalHeight())); | 108 FloatRect boxRect(boxOrigin, FloatSize(m_inlineTextBox.logicalWidth(), m_inl
ineTextBox.logicalHeight())); |
| 109 | 109 |
| 110 bool shouldRotate = false; | 110 bool shouldRotate = false; |
| 111 LayoutTextCombine* combinedText = nullptr; | 111 LayoutTextCombine* combinedText = nullptr; |
| 112 if (!m_inlineTextBox.isHorizontal()) { | 112 if (!m_inlineTextBox.isHorizontal()) { |
| 113 if (styleToUse.hasTextCombine() && m_inlineTextBox.renderer().isCombineT
ext()) { | 113 if (styleToUse.hasTextCombine() && m_inlineTextBox.layoutObject().isComb
ineText()) { |
| 114 combinedText = &toLayoutTextCombine(m_inlineTextBox.renderer()); | 114 combinedText = &toLayoutTextCombine(m_inlineTextBox.layoutObject()); |
| 115 if (!combinedText->isCombined()) | 115 if (!combinedText->isCombined()) |
| 116 combinedText = nullptr; | 116 combinedText = nullptr; |
| 117 } | 117 } |
| 118 if (combinedText) { | 118 if (combinedText) { |
| 119 combinedText->updateFont(); | 119 combinedText->updateFont(); |
| 120 boxRect.setWidth(combinedText->inlineWidthForLayout()); | 120 boxRect.setWidth(combinedText->inlineWidthForLayout()); |
| 121 } else { | 121 } else { |
| 122 shouldRotate = true; | 122 shouldRotate = true; |
| 123 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Clock
wise)); | 123 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Clock
wise)); |
| 124 } | 124 } |
| 125 } | 125 } |
| 126 | 126 |
| 127 // Determine whether or not we have composition underlines to draw. | 127 // Determine whether or not we have composition underlines to draw. |
| 128 bool containsComposition = m_inlineTextBox.renderer().node() && m_inlineText
Box.renderer().frame()->inputMethodController().compositionNode() == m_inlineTex
tBox.renderer().node(); | 128 bool containsComposition = m_inlineTextBox.layoutObject().node() && m_inline
TextBox.layoutObject().frame()->inputMethodController().compositionNode() == m_i
nlineTextBox.layoutObject().node(); |
| 129 bool useCustomUnderlines = containsComposition && m_inlineTextBox.renderer()
.frame()->inputMethodController().compositionUsesCustomUnderlines(); | 129 bool useCustomUnderlines = containsComposition && m_inlineTextBox.layoutObje
ct().frame()->inputMethodController().compositionUsesCustomUnderlines(); |
| 130 | 130 |
| 131 // Determine text colors. | 131 // Determine text colors. |
| 132 TextPainter::Style textStyle = TextPainter::textPaintingStyle(m_inlineTextBo
x.renderer(), styleToUse, paintInfo.forceBlackText(), isPrinting); | 132 TextPainter::Style textStyle = TextPainter::textPaintingStyle(m_inlineTextBo
x.layoutObject(), styleToUse, paintInfo.forceBlackText(), isPrinting); |
| 133 TextPainter::Style selectionStyle = TextPainter::selectionPaintingStyle(m_in
lineTextBox.renderer(), haveSelection, paintInfo.forceBlackText(), isPrinting, t
extStyle); | 133 TextPainter::Style selectionStyle = TextPainter::selectionPaintingStyle(m_in
lineTextBox.layoutObject(), haveSelection, paintInfo.forceBlackText(), isPrintin
g, textStyle); |
| 134 bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection); | 134 bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection); |
| 135 bool paintSelectedTextSeparately = !paintSelectedTextOnly && textStyle != se
lectionStyle; | 135 bool paintSelectedTextSeparately = !paintSelectedTextOnly && textStyle != se
lectionStyle; |
| 136 | 136 |
| 137 // Set our font. | 137 // Set our font. |
| 138 const Font& font = styleToUse.font(); | 138 const Font& font = styleToUse.font(); |
| 139 | 139 |
| 140 FloatPoint textOrigin = FloatPoint(boxOrigin.x(), boxOrigin.y() + font.fontM
etrics().ascent()); | 140 FloatPoint textOrigin = FloatPoint(boxOrigin.x(), boxOrigin.y() + font.fontM
etrics().ascent()); |
| 141 | 141 |
| 142 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
include selection | 142 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
include selection |
| 143 // and composition highlights. | 143 // and composition highlights. |
| 144 if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseT
extClip && !isPrinting) { | 144 if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseT
extClip && !isPrinting) { |
| 145 if (containsComposition) { | 145 if (containsComposition) { |
| 146 paintCompositionBackgrounds(context, boxOrigin, styleToUse, font, us
eCustomUnderlines); | 146 paintCompositionBackgrounds(context, boxOrigin, styleToUse, font, us
eCustomUnderlines); |
| 147 } | 147 } |
| 148 | 148 |
| 149 paintDocumentMarkers(context, boxOrigin, styleToUse, font, true); | 149 paintDocumentMarkers(context, boxOrigin, styleToUse, font, true); |
| 150 | 150 |
| 151 if (haveSelection && !useCustomUnderlines) { | 151 if (haveSelection && !useCustomUnderlines) { |
| 152 if (combinedText) | 152 if (combinedText) |
| 153 paintSelection<InlineTextBoxPainter::PaintOptions::CombinedText>
(context, boxRect, styleToUse, font, selectionStyle.fillColor, combinedText); | 153 paintSelection<InlineTextBoxPainter::PaintOptions::CombinedText>
(context, boxRect, styleToUse, font, selectionStyle.fillColor, combinedText); |
| 154 else | 154 else |
| 155 paintSelection<InlineTextBoxPainter::PaintOptions::Normal>(conte
xt, boxRect, styleToUse, font, selectionStyle.fillColor); | 155 paintSelection<InlineTextBoxPainter::PaintOptions::Normal>(conte
xt, boxRect, styleToUse, font, selectionStyle.fillColor); |
| 156 } | 156 } |
| 157 } | 157 } |
| 158 | 158 |
| 159 // 2. Now paint the foreground, including text and decorations like underlin
e/overline (in quirks mode only). | 159 // 2. Now paint the foreground, including text and decorations like underlin
e/overline (in quirks mode only). |
| 160 int length = m_inlineTextBox.len(); | 160 int length = m_inlineTextBox.len(); |
| 161 StringView string = m_inlineTextBox.renderer().text().createView(); | 161 StringView string = m_inlineTextBox.layoutObject().text().createView(); |
| 162 ASSERT(m_inlineTextBox.start() + length <= string.length()); | 162 ASSERT(m_inlineTextBox.start() + length <= string.length()); |
| 163 if (static_cast<unsigned>(length) != string.length() || m_inlineTextBox.star
t()) | 163 if (static_cast<unsigned>(length) != string.length() || m_inlineTextBox.star
t()) |
| 164 string.narrow(m_inlineTextBox.start(), length); | 164 string.narrow(m_inlineTextBox.start(), length); |
| 165 int maximumLength = m_inlineTextBox.renderer().textLength() - m_inlineTextBo
x.start(); | 165 int maximumLength = m_inlineTextBox.layoutObject().textLength() - m_inlineTe
xtBox.start(); |
| 166 | 166 |
| 167 StringBuilder charactersWithHyphen; | 167 StringBuilder charactersWithHyphen; |
| 168 TextRun textRun = m_inlineTextBox.constructTextRun(styleToUse, font, string,
maximumLength, m_inlineTextBox.hasHyphen() ? &charactersWithHyphen : 0); | 168 TextRun textRun = m_inlineTextBox.constructTextRun(styleToUse, font, string,
maximumLength, m_inlineTextBox.hasHyphen() ? &charactersWithHyphen : 0); |
| 169 if (m_inlineTextBox.hasHyphen()) | 169 if (m_inlineTextBox.hasHyphen()) |
| 170 length = textRun.length(); | 170 length = textRun.length(); |
| 171 | 171 |
| 172 int selectionStart = 0; | 172 int selectionStart = 0; |
| 173 int selectionEnd = 0; | 173 int selectionEnd = 0; |
| 174 if (paintSelectedTextOnly || paintSelectedTextSeparately) | 174 if (paintSelectedTextOnly || paintSelectedTextSeparately) |
| 175 m_inlineTextBox.selectionStartEnd(selectionStart, selectionEnd); | 175 m_inlineTextBox.selectionStartEnd(selectionStart, selectionEnd); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 paintDecoration(context, boxOrigin, textDecorations); | 230 paintDecoration(context, boxOrigin, textDecorations); |
| 231 if (combinedText) | 231 if (combinedText) |
| 232 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Count
erclockwise)); | 232 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Count
erclockwise)); |
| 233 } | 233 } |
| 234 | 234 |
| 235 if (paintInfo.phase == PaintPhaseForeground) { | 235 if (paintInfo.phase == PaintPhaseForeground) { |
| 236 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); | 236 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); |
| 237 | 237 |
| 238 // Paint custom underlines for compositions. | 238 // Paint custom underlines for compositions. |
| 239 if (useCustomUnderlines) { | 239 if (useCustomUnderlines) { |
| 240 const Vector<CompositionUnderline>& underlines = m_inlineTextBox.ren
derer().frame()->inputMethodController().customCompositionUnderlines(); | 240 const Vector<CompositionUnderline>& underlines = m_inlineTextBox.lay
outObject().frame()->inputMethodController().customCompositionUnderlines(); |
| 241 CompositionUnderlineRangeFilter filter(underlines, m_inlineTextBox.s
tart(), m_inlineTextBox.end()); | 241 CompositionUnderlineRangeFilter filter(underlines, m_inlineTextBox.s
tart(), m_inlineTextBox.end()); |
| 242 for (CompositionUnderlineRangeFilter::ConstIterator it = filter.begi
n(); it != filter.end(); ++it) { | 242 for (CompositionUnderlineRangeFilter::ConstIterator it = filter.begi
n(); it != filter.end(); ++it) { |
| 243 if (it->color == Color::transparent) | 243 if (it->color == Color::transparent) |
| 244 continue; | 244 continue; |
| 245 paintCompositionUnderline(context, boxOrigin, *it); | 245 paintCompositionUnderline(context, boxOrigin, *it); |
| 246 } | 246 } |
| 247 } | 247 } |
| 248 } | 248 } |
| 249 | 249 |
| 250 if (shouldRotate) | 250 if (shouldRotate) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 261 unsigned paintEnd = std::min(m_inlineTextBox.end() + 1, underline.endOffset)
; // end() points at the last char, not past it. | 261 unsigned paintEnd = std::min(m_inlineTextBox.end() + 1, underline.endOffset)
; // end() points at the last char, not past it. |
| 262 if (m_inlineTextBox.truncation() != cNoTruncation) | 262 if (m_inlineTextBox.truncation() != cNoTruncation) |
| 263 paintEnd = std::min(paintEnd, static_cast<unsigned>(m_inlineTextBox.star
t() + m_inlineTextBox.truncation())); | 263 paintEnd = std::min(paintEnd, static_cast<unsigned>(m_inlineTextBox.star
t() + m_inlineTextBox.truncation())); |
| 264 return paintEnd; | 264 return paintEnd; |
| 265 } | 265 } |
| 266 | 266 |
| 267 void InlineTextBoxPainter::paintCompositionBackgrounds(GraphicsContext* pt, cons
t FloatPoint& boxOrigin, const LayoutStyle& style, const Font& font, bool useCus
tomUnderlines) | 267 void InlineTextBoxPainter::paintCompositionBackgrounds(GraphicsContext* pt, cons
t FloatPoint& boxOrigin, const LayoutStyle& style, const Font& font, bool useCus
tomUnderlines) |
| 268 { | 268 { |
| 269 if (useCustomUnderlines) { | 269 if (useCustomUnderlines) { |
| 270 // Paint custom background highlights for compositions. | 270 // Paint custom background highlights for compositions. |
| 271 const Vector<CompositionUnderline>& underlines = m_inlineTextBox.rendere
r().frame()->inputMethodController().customCompositionUnderlines(); | 271 const Vector<CompositionUnderline>& underlines = m_inlineTextBox.layoutO
bject().frame()->inputMethodController().customCompositionUnderlines(); |
| 272 CompositionUnderlineRangeFilter filter(underlines, m_inlineTextBox.start
(), m_inlineTextBox.end()); | 272 CompositionUnderlineRangeFilter filter(underlines, m_inlineTextBox.start
(), m_inlineTextBox.end()); |
| 273 for (CompositionUnderlineRangeFilter::ConstIterator it = filter.begin();
it != filter.end(); ++it) { | 273 for (CompositionUnderlineRangeFilter::ConstIterator it = filter.begin();
it != filter.end(); ++it) { |
| 274 if (it->backgroundColor == Color::transparent) | 274 if (it->backgroundColor == Color::transparent) |
| 275 continue; | 275 continue; |
| 276 paintSingleCompositionBackgroundRun(pt, boxOrigin, style, font, it->
backgroundColor, underlinePaintStart(*it), underlinePaintEnd(*it)); | 276 paintSingleCompositionBackgroundRun(pt, boxOrigin, style, font, it->
backgroundColor, underlinePaintStart(*it), underlinePaintEnd(*it)); |
| 277 } | 277 } |
| 278 | 278 |
| 279 } else { | 279 } else { |
| 280 paintSingleCompositionBackgroundRun(pt, boxOrigin, style, font, LayoutTh
eme::theme().platformDefaultCompositionBackgroundColor(), | 280 paintSingleCompositionBackgroundRun(pt, boxOrigin, style, font, LayoutTh
eme::theme().platformDefaultCompositionBackgroundColor(), |
| 281 m_inlineTextBox.renderer().frame()->inputMethodController().composit
ionStart(), | 281 m_inlineTextBox.layoutObject().frame()->inputMethodController().comp
ositionStart(), |
| 282 m_inlineTextBox.renderer().frame()->inputMethodController().composit
ionEnd()); | 282 m_inlineTextBox.layoutObject().frame()->inputMethodController().comp
ositionEnd()); |
| 283 } | 283 } |
| 284 } | 284 } |
| 285 | 285 |
| 286 void InlineTextBoxPainter::paintSingleCompositionBackgroundRun(GraphicsContext*
context, const FloatPoint& boxOrigin, const LayoutStyle& style, const Font& font
, Color backgroundColor, int startPos, int endPos) | 286 void InlineTextBoxPainter::paintSingleCompositionBackgroundRun(GraphicsContext*
context, const FloatPoint& boxOrigin, const LayoutStyle& style, const Font& font
, Color backgroundColor, int startPos, int endPos) |
| 287 { | 287 { |
| 288 int sPos = std::max(startPos - static_cast<int>(m_inlineTextBox.start()), 0)
; | 288 int sPos = std::max(startPos - static_cast<int>(m_inlineTextBox.start()), 0)
; |
| 289 int ePos = std::min(endPos - static_cast<int>(m_inlineTextBox.start()), stat
ic_cast<int>(m_inlineTextBox.len())); | 289 int ePos = std::min(endPos - static_cast<int>(m_inlineTextBox.start()), stat
ic_cast<int>(m_inlineTextBox.len())); |
| 290 if (sPos >= ePos) | 290 if (sPos >= ePos) |
| 291 return; | 291 return; |
| 292 | 292 |
| 293 int deltaY = m_inlineTextBox.renderer().style()->isFlippedLinesWritingMode()
? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBottom() :
m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); | 293 int deltaY = m_inlineTextBox.layoutObject().style()->isFlippedLinesWritingMo
de() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBottom(
) : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); |
| 294 int selHeight = m_inlineTextBox.root().selectionHeight(); | 294 int selHeight = m_inlineTextBox.root().selectionHeight(); |
| 295 FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY); | 295 FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY); |
| 296 context->drawHighlightForText(font, m_inlineTextBox.constructTextRun(style,
font), localOrigin, selHeight, backgroundColor, sPos, ePos); | 296 context->drawHighlightForText(font, m_inlineTextBox.constructTextRun(style,
font), localOrigin, selHeight, backgroundColor, sPos, ePos); |
| 297 } | 297 } |
| 298 | 298 |
| 299 void InlineTextBoxPainter::paintDocumentMarkers(GraphicsContext* pt, const Float
Point& boxOrigin, const LayoutStyle& style, const Font& font, bool background) | 299 void InlineTextBoxPainter::paintDocumentMarkers(GraphicsContext* pt, const Float
Point& boxOrigin, const LayoutStyle& style, const Font& font, bool background) |
| 300 { | 300 { |
| 301 if (!m_inlineTextBox.renderer().node()) | 301 if (!m_inlineTextBox.layoutObject().node()) |
| 302 return; | 302 return; |
| 303 | 303 |
| 304 DocumentMarkerVector markers = m_inlineTextBox.renderer().document().markers
().markersFor(m_inlineTextBox.renderer().node()); | 304 DocumentMarkerVector markers = m_inlineTextBox.layoutObject().document().mar
kers().markersFor(m_inlineTextBox.layoutObject().node()); |
| 305 DocumentMarkerVector::const_iterator markerIt = markers.begin(); | 305 DocumentMarkerVector::const_iterator markerIt = markers.begin(); |
| 306 | 306 |
| 307 // Give any document markers that touch this run a chance to draw before the
text has been drawn. | 307 // Give any document markers that touch this run a chance to draw before the
text has been drawn. |
| 308 // Note end() points at the last char, not one past it like endOffset and ra
nges do. | 308 // Note end() points at the last char, not one past it like endOffset and ra
nges do. |
| 309 for ( ; markerIt != markers.end(); ++markerIt) { | 309 for ( ; markerIt != markers.end(); ++markerIt) { |
| 310 DocumentMarker* marker = *markerIt; | 310 DocumentMarker* marker = *markerIt; |
| 311 | 311 |
| 312 // Paint either the background markers or the foreground markers, but no
t both | 312 // Paint either the background markers or the foreground markers, but no
t both |
| 313 switch (marker->type()) { | 313 switch (marker->type()) { |
| 314 case DocumentMarker::Grammar: | 314 case DocumentMarker::Grammar: |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 return GraphicsContext::DocumentMarkerGrammarLineStyle; | 360 return GraphicsContext::DocumentMarkerGrammarLineStyle; |
| 361 default: | 361 default: |
| 362 ASSERT_NOT_REACHED(); | 362 ASSERT_NOT_REACHED(); |
| 363 return GraphicsContext::DocumentMarkerSpellingLineStyle; | 363 return GraphicsContext::DocumentMarkerSpellingLineStyle; |
| 364 } | 364 } |
| 365 } | 365 } |
| 366 | 366 |
| 367 void InlineTextBoxPainter::paintDocumentMarker(GraphicsContext* pt, const FloatP
oint& boxOrigin, DocumentMarker* marker, const LayoutStyle& style, const Font& f
ont, bool grammar) | 367 void InlineTextBoxPainter::paintDocumentMarker(GraphicsContext* pt, const FloatP
oint& boxOrigin, DocumentMarker* marker, const LayoutStyle& style, const Font& f
ont, bool grammar) |
| 368 { | 368 { |
| 369 // Never print spelling/grammar markers (5327887) | 369 // Never print spelling/grammar markers (5327887) |
| 370 if (m_inlineTextBox.renderer().document().printing()) | 370 if (m_inlineTextBox.layoutObject().document().printing()) |
| 371 return; | 371 return; |
| 372 | 372 |
| 373 if (m_inlineTextBox.truncation() == cFullTruncation) | 373 if (m_inlineTextBox.truncation() == cFullTruncation) |
| 374 return; | 374 return; |
| 375 | 375 |
| 376 float start = 0; // start of line to draw, relative to tx | 376 float start = 0; // start of line to draw, relative to tx |
| 377 float width = m_inlineTextBox.logicalWidth(); // how much line to draw | 377 float width = m_inlineTextBox.logicalWidth(); // how much line to draw |
| 378 | 378 |
| 379 // Determine whether we need to measure text | 379 // Determine whether we need to measure text |
| 380 bool markerSpansWholeBox = true; | 380 bool markerSpansWholeBox = true; |
| 381 if (m_inlineTextBox.start() <= marker->startOffset()) | 381 if (m_inlineTextBox.start() <= marker->startOffset()) |
| 382 markerSpansWholeBox = false; | 382 markerSpansWholeBox = false; |
| 383 if ((m_inlineTextBox.end() + 1) != marker->endOffset()) // end points at the
last char, not past it | 383 if ((m_inlineTextBox.end() + 1) != marker->endOffset()) // end points at the
last char, not past it |
| 384 markerSpansWholeBox = false; | 384 markerSpansWholeBox = false; |
| 385 if (m_inlineTextBox.truncation() != cNoTruncation) | 385 if (m_inlineTextBox.truncation() != cNoTruncation) |
| 386 markerSpansWholeBox = false; | 386 markerSpansWholeBox = false; |
| 387 | 387 |
| 388 if (!markerSpansWholeBox || grammar) { | 388 if (!markerSpansWholeBox || grammar) { |
| 389 int startPosition = std::max<int>(marker->startOffset() - m_inlineTextBo
x.start(), 0); | 389 int startPosition = std::max<int>(marker->startOffset() - m_inlineTextBo
x.start(), 0); |
| 390 int endPosition = std::min<int>(marker->endOffset() - static_cast<int>(m
_inlineTextBox.start()), m_inlineTextBox.len()); | 390 int endPosition = std::min<int>(marker->endOffset() - static_cast<int>(m
_inlineTextBox.start()), m_inlineTextBox.len()); |
| 391 | 391 |
| 392 if (m_inlineTextBox.truncation() != cNoTruncation) | 392 if (m_inlineTextBox.truncation() != cNoTruncation) |
| 393 endPosition = std::min<int>(endPosition, m_inlineTextBox.truncation(
)); | 393 endPosition = std::min<int>(endPosition, m_inlineTextBox.truncation(
)); |
| 394 | 394 |
| 395 // Calculate start & width | 395 // Calculate start & width |
| 396 int deltaY = m_inlineTextBox.renderer().style()->isFlippedLinesWritingMo
de() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBottom(
) : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); | 396 int deltaY = m_inlineTextBox.layoutObject().style()->isFlippedLinesWriti
ngMode() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBot
tom() : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); |
| 397 int selHeight = m_inlineTextBox.root().selectionHeight(); | 397 int selHeight = m_inlineTextBox.root().selectionHeight(); |
| 398 FloatPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY); | 398 FloatPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY); |
| 399 TextRun run = m_inlineTextBox.constructTextRun(style, font); | 399 TextRun run = m_inlineTextBox.constructTextRun(style, font); |
| 400 | 400 |
| 401 // FIXME: Convert the document markers to float rects. | 401 // FIXME: Convert the document markers to float rects. |
| 402 IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, sta
rtPoint, selHeight, startPosition, endPosition)); | 402 IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, sta
rtPoint, selHeight, startPosition, endPosition)); |
| 403 start = markerRect.x() - startPoint.x(); | 403 start = markerRect.x() - startPoint.x(); |
| 404 width = markerRect.width(); | 404 width = markerRect.width(); |
| 405 | 405 |
| 406 // Store rendered rects for bad grammar markers, so we can hit-test agai
nst it elsewhere in order to | 406 // Store rendered rects for bad grammar markers, so we can hit-test agai
nst it elsewhere in order to |
| 407 // display a toolTip. We don't do this for misspelling markers. | 407 // display a toolTip. We don't do this for misspelling markers. |
| 408 if (grammar) { | 408 if (grammar) { |
| 409 markerRect.move(-boxOrigin.x(), -boxOrigin.y()); | 409 markerRect.move(-boxOrigin.x(), -boxOrigin.y()); |
| 410 markerRect = m_inlineTextBox.renderer().localToAbsoluteQuad(FloatRec
t(markerRect)).enclosingBoundingBox(); | 410 markerRect = m_inlineTextBox.layoutObject().localToAbsoluteQuad(Floa
tRect(markerRect)).enclosingBoundingBox(); |
| 411 toRenderedDocumentMarker(marker)->setRenderedRect(LayoutRect(markerR
ect)); | 411 toRenderedDocumentMarker(marker)->setRenderedRect(LayoutRect(markerR
ect)); |
| 412 } | 412 } |
| 413 } | 413 } |
| 414 | 414 |
| 415 // IMPORTANT: The misspelling underline is not considered when calculating t
he text bounds, so we have to | 415 // IMPORTANT: The misspelling underline is not considered when calculating t
he text bounds, so we have to |
| 416 // make sure to fit within those bounds. This means the top pixel(s) of the
underline will overlap the | 416 // make sure to fit within those bounds. This means the top pixel(s) of the
underline will overlap the |
| 417 // bottom pixel(s) of the glyphs in smaller font sizes. The alternatives ar
e to increase the line spacing (bad!!) | 417 // bottom pixel(s) of the glyphs in smaller font sizes. The alternatives ar
e to increase the line spacing (bad!!) |
| 418 // or decrease the underline thickness. The overlap is actually the most us
eful, and matches what AppKit does. | 418 // or decrease the underline thickness. The overlap is actually the most us
eful, and matches what AppKit does. |
| 419 // So, we generally place the underline at the bottom of the text, but in la
rger fonts that's not so good so | 419 // So, we generally place the underline at the bottom of the text, but in la
rger fonts that's not so good so |
| 420 // we pin to two pixels under the baseline. | 420 // we pin to two pixels under the baseline. |
| 421 int lineThickness = misspellingLineThickness; | 421 int lineThickness = misspellingLineThickness; |
| 422 int baseline = m_inlineTextBox.renderer().style(m_inlineTextBox.isFirstLineS
tyle())->fontMetrics().ascent(); | 422 int baseline = m_inlineTextBox.layoutObject().style(m_inlineTextBox.isFirstL
ineStyle())->fontMetrics().ascent(); |
| 423 int descent = m_inlineTextBox.logicalHeight() - baseline; | 423 int descent = m_inlineTextBox.logicalHeight() - baseline; |
| 424 int underlineOffset; | 424 int underlineOffset; |
| 425 if (descent <= (2 + lineThickness)) { | 425 if (descent <= (2 + lineThickness)) { |
| 426 // Place the underline at the very bottom of the text in small/medium fo
nts. | 426 // Place the underline at the very bottom of the text in small/medium fo
nts. |
| 427 underlineOffset = m_inlineTextBox.logicalHeight() - lineThickness; | 427 underlineOffset = m_inlineTextBox.logicalHeight() - lineThickness; |
| 428 } else { | 428 } else { |
| 429 // In larger fonts, though, place the underline up near the baseline to
prevent a big gap. | 429 // In larger fonts, though, place the underline up near the baseline to
prevent a big gap. |
| 430 underlineOffset = baseline + 2; | 430 underlineOffset = baseline + 2; |
| 431 } | 431 } |
| 432 pt->drawLineForDocumentMarker(FloatPoint(boxOrigin.x() + start, boxOrigin.y(
) + underlineOffset), width, lineStyleForMarkerType(marker->type())); | 432 pt->drawLineForDocumentMarker(FloatPoint(boxOrigin.x() + start, boxOrigin.y(
) + underlineOffset), width, lineStyleForMarkerType(marker->type())); |
| 433 } | 433 } |
| 434 | 434 |
| 435 template <InlineTextBoxPainter::PaintOptions options> | 435 template <InlineTextBoxPainter::PaintOptions options> |
| 436 void InlineTextBoxPainter::paintSelection(GraphicsContext* context, const FloatR
ect& boxRect, const LayoutStyle& style, const Font& font, Color textColor, Layou
tTextCombine* combinedText) | 436 void InlineTextBoxPainter::paintSelection(GraphicsContext* context, const FloatR
ect& boxRect, const LayoutStyle& style, const Font& font, Color textColor, Layou
tTextCombine* combinedText) |
| 437 { | 437 { |
| 438 // See if we have a selection to paint at all. | 438 // See if we have a selection to paint at all. |
| 439 int sPos, ePos; | 439 int sPos, ePos; |
| 440 m_inlineTextBox.selectionStartEnd(sPos, ePos); | 440 m_inlineTextBox.selectionStartEnd(sPos, ePos); |
| 441 if (sPos >= ePos) | 441 if (sPos >= ePos) |
| 442 return; | 442 return; |
| 443 | 443 |
| 444 Color c = m_inlineTextBox.renderer().selectionBackgroundColor(); | 444 Color c = m_inlineTextBox.layoutObject().selectionBackgroundColor(); |
| 445 if (!c.alpha()) | 445 if (!c.alpha()) |
| 446 return; | 446 return; |
| 447 | 447 |
| 448 // If the text color ends up being the same as the selection background, inv
ert the selection | 448 // If the text color ends up being the same as the selection background, inv
ert the selection |
| 449 // background. | 449 // background. |
| 450 if (textColor == c) | 450 if (textColor == c) |
| 451 c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); | 451 c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); |
| 452 | 452 |
| 453 // If the text is truncated, let the thing being painted in the truncation | 453 // If the text is truncated, let the thing being painted in the truncation |
| 454 // draw its own highlight. | 454 // draw its own highlight. |
| 455 int length = m_inlineTextBox.truncation() != cNoTruncation ? m_inlineTextBox
.truncation() : m_inlineTextBox.len(); | 455 int length = m_inlineTextBox.truncation() != cNoTruncation ? m_inlineTextBox
.truncation() : m_inlineTextBox.len(); |
| 456 StringView string = m_inlineTextBox.renderer().text().createView(); | 456 StringView string = m_inlineTextBox.layoutObject().text().createView(); |
| 457 | 457 |
| 458 if (string.length() != static_cast<unsigned>(length) || m_inlineTextBox.star
t()) | 458 if (string.length() != static_cast<unsigned>(length) || m_inlineTextBox.star
t()) |
| 459 string.narrow(m_inlineTextBox.start(), length); | 459 string.narrow(m_inlineTextBox.start(), length); |
| 460 | 460 |
| 461 StringBuilder charactersWithHyphen; | 461 StringBuilder charactersWithHyphen; |
| 462 bool respectHyphen = ePos == length && m_inlineTextBox.hasHyphen(); | 462 bool respectHyphen = ePos == length && m_inlineTextBox.hasHyphen(); |
| 463 TextRun textRun = m_inlineTextBox.constructTextRun(style, font, string, m_in
lineTextBox.renderer().textLength() - m_inlineTextBox.start(), respectHyphen ? &
charactersWithHyphen : 0); | 463 TextRun textRun = m_inlineTextBox.constructTextRun(style, font, string, m_in
lineTextBox.layoutObject().textLength() - m_inlineTextBox.start(), respectHyphen
? &charactersWithHyphen : 0); |
| 464 if (respectHyphen) | 464 if (respectHyphen) |
| 465 ePos = textRun.length(); | 465 ePos = textRun.length(); |
| 466 | 466 |
| 467 GraphicsContextStateSaver stateSaver(*context); | 467 GraphicsContextStateSaver stateSaver(*context); |
| 468 | 468 |
| 469 if (options == InlineTextBoxPainter::PaintOptions::CombinedText) { | 469 if (options == InlineTextBoxPainter::PaintOptions::CombinedText) { |
| 470 ASSERT(combinedText); | 470 ASSERT(combinedText); |
| 471 // We can't use the height of m_inlineTextBox because LayoutTextCombine'
s inlineTextBox is horizontal within vertical flow | 471 // We can't use the height of m_inlineTextBox because LayoutTextCombine'
s inlineTextBox is horizontal within vertical flow |
| 472 FloatRect clipRect = boxRect; | 472 FloatRect clipRect = boxRect; |
| 473 combinedText->transformLayoutRect(clipRect); | 473 combinedText->transformLayoutRect(clipRect); |
| 474 context->clip(clipRect); | 474 context->clip(clipRect); |
| 475 combinedText->transformToInlineCoordinates(*context, boxRect); | 475 combinedText->transformToInlineCoordinates(*context, boxRect); |
| 476 context->drawHighlightForText(font, textRun, boxRect.location(), boxRect
.height(), c, sPos, ePos); | 476 context->drawHighlightForText(font, textRun, boxRect.location(), boxRect
.height(), c, sPos, ePos); |
| 477 return; | 477 return; |
| 478 } | 478 } |
| 479 | 479 |
| 480 LayoutUnit selectionBottom = m_inlineTextBox.root().selectionBottom(); | 480 LayoutUnit selectionBottom = m_inlineTextBox.root().selectionBottom(); |
| 481 LayoutUnit selectionTop = m_inlineTextBox.root().selectionTopAdjustedForPrec
edingBlock(); | 481 LayoutUnit selectionTop = m_inlineTextBox.root().selectionTopAdjustedForPrec
edingBlock(); |
| 482 | 482 |
| 483 int deltaY = roundToInt(m_inlineTextBox.renderer().style()->isFlippedLinesWr
itingMode() ? selectionBottom - m_inlineTextBox.logicalBottom() : m_inlineTextBo
x.logicalTop() - selectionTop); | 483 int deltaY = roundToInt(m_inlineTextBox.layoutObject().style()->isFlippedLin
esWritingMode() ? selectionBottom - m_inlineTextBox.logicalBottom() : m_inlineTe
xtBox.logicalTop() - selectionTop); |
| 484 int selHeight = std::max(0, roundToInt(selectionBottom - selectionTop)); | 484 int selHeight = std::max(0, roundToInt(selectionBottom - selectionTop)); |
| 485 | 485 |
| 486 FloatPoint localOrigin(boxRect.x(), boxRect.y() - deltaY); | 486 FloatPoint localOrigin(boxRect.x(), boxRect.y() - deltaY); |
| 487 FloatRect clipRect(localOrigin, FloatSize(m_inlineTextBox.logicalWidth(), se
lHeight)); | 487 FloatRect clipRect(localOrigin, FloatSize(m_inlineTextBox.logicalWidth(), se
lHeight)); |
| 488 | 488 |
| 489 context->clip(clipRect); | 489 context->clip(clipRect); |
| 490 context->drawHighlightForText(font, textRun, localOrigin, selHeight, c, sPos
, ePos); | 490 context->drawHighlightForText(font, textRun, localOrigin, selHeight, c, sPos
, ePos); |
| 491 } | 491 } |
| 492 | 492 |
| 493 static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition,
const FontMetrics& fontMetrics, const InlineTextBox* inlineTextBox, const float
textDecorationThickness) | 493 static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition,
const FontMetrics& fontMetrics, const InlineTextBox* inlineTextBox, const float
textDecorationThickness) |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 { | 706 { |
| 707 GraphicsContextStateSaver stateSaver(*context); | 707 GraphicsContextStateSaver stateSaver(*context); |
| 708 | 708 |
| 709 if (m_inlineTextBox.truncation() == cFullTruncation) | 709 if (m_inlineTextBox.truncation() == cFullTruncation) |
| 710 return; | 710 return; |
| 711 | 711 |
| 712 FloatPoint localOrigin = boxOrigin; | 712 FloatPoint localOrigin = boxOrigin; |
| 713 | 713 |
| 714 float width = m_inlineTextBox.logicalWidth(); | 714 float width = m_inlineTextBox.logicalWidth(); |
| 715 if (m_inlineTextBox.truncation() != cNoTruncation) { | 715 if (m_inlineTextBox.truncation() != cNoTruncation) { |
| 716 width = m_inlineTextBox.renderer().width(m_inlineTextBox.start(), m_inli
neTextBox.truncation(), m_inlineTextBox.textPos(), m_inlineTextBox.isLeftToRight
Direction() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle()); | 716 width = m_inlineTextBox.layoutObject().width(m_inlineTextBox.start(), m_
inlineTextBox.truncation(), m_inlineTextBox.textPos(), m_inlineTextBox.isLeftToR
ightDirection() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle()); |
| 717 if (!m_inlineTextBox.isLeftToRightDirection()) | 717 if (!m_inlineTextBox.isLeftToRightDirection()) |
| 718 localOrigin.move(m_inlineTextBox.logicalWidth() - width, 0); | 718 localOrigin.move(m_inlineTextBox.logicalWidth() - width, 0); |
| 719 } | 719 } |
| 720 | 720 |
| 721 // Get the text decoration colors. | 721 // Get the text decoration colors. |
| 722 LayoutObject::AppliedTextDecoration underline, overline, linethrough; | 722 LayoutObject::AppliedTextDecoration underline, overline, linethrough; |
| 723 m_inlineTextBox.renderer().getTextDecorations(deco, underline, overline, lin
ethrough, true); | 723 m_inlineTextBox.layoutObject().getTextDecorations(deco, underline, overline,
linethrough, true); |
| 724 if (m_inlineTextBox.isFirstLineStyle()) | 724 if (m_inlineTextBox.isFirstLineStyle()) |
| 725 m_inlineTextBox.renderer().getTextDecorations(deco, underline, overline,
linethrough, true, true); | 725 m_inlineTextBox.layoutObject().getTextDecorations(deco, underline, overl
ine, linethrough, true, true); |
| 726 | 726 |
| 727 // Use a special function for underlines to get the positioning exactly righ
t. | 727 // Use a special function for underlines to get the positioning exactly righ
t. |
| 728 bool isPrinting = m_inlineTextBox.renderer().document().printing(); | 728 bool isPrinting = m_inlineTextBox.layoutObject().document().printing(); |
| 729 | 729 |
| 730 const LayoutStyle& styleToUse = m_inlineTextBox.renderer().styleRef(m_inline
TextBox.isFirstLineStyle()); | 730 const LayoutStyle& styleToUse = m_inlineTextBox.layoutObject().styleRef(m_in
lineTextBox.isFirstLineStyle()); |
| 731 int baseline = styleToUse.fontMetrics().ascent(); | 731 int baseline = styleToUse.fontMetrics().ascent(); |
| 732 | 732 |
| 733 // Set the thick of the line to be 10% (or something else ?)of the computed
font size and not less than 1px. | 733 // Set the thick of the line to be 10% (or something else ?)of the computed
font size and not less than 1px. |
| 734 // Using computedFontSize should take care of zoom as well. | 734 // Using computedFontSize should take care of zoom as well. |
| 735 | 735 |
| 736 // Update Underline thickness, in case we have Faulty Font Metrics calculati
ng underline thickness by old method. | 736 // Update Underline thickness, in case we have Faulty Font Metrics calculati
ng underline thickness by old method. |
| 737 float textDecorationThickness = styleToUse.fontMetrics().underlineThickness(
); | 737 float textDecorationThickness = styleToUse.fontMetrics().underlineThickness(
); |
| 738 int fontHeightInt = (int)(styleToUse.fontMetrics().floatHeight() + 0.5); | 738 int fontHeightInt = (int)(styleToUse.fontMetrics().floatHeight() + 0.5); |
| 739 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei
ghtInt >> 1))) | 739 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei
ghtInt >> 1))) |
| 740 textDecorationThickness = std::max(1.f, styleToUse.computedFontSize() /
10.f); | 740 textDecorationThickness = std::max(1.f, styleToUse.computedFontSize() /
10.f); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 763 void InlineTextBoxPainter::paintCompositionUnderline(GraphicsContext* ctx, const
FloatPoint& boxOrigin, const CompositionUnderline& underline) | 763 void InlineTextBoxPainter::paintCompositionUnderline(GraphicsContext* ctx, const
FloatPoint& boxOrigin, const CompositionUnderline& underline) |
| 764 { | 764 { |
| 765 if (m_inlineTextBox.truncation() == cFullTruncation) | 765 if (m_inlineTextBox.truncation() == cFullTruncation) |
| 766 return; | 766 return; |
| 767 | 767 |
| 768 unsigned paintStart = underlinePaintStart(underline); | 768 unsigned paintStart = underlinePaintStart(underline); |
| 769 unsigned paintEnd = underlinePaintEnd(underline); | 769 unsigned paintEnd = underlinePaintEnd(underline); |
| 770 | 770 |
| 771 // start of line to draw, relative to paintOffset. | 771 // start of line to draw, relative to paintOffset. |
| 772 float start = paintStart == static_cast<unsigned>(m_inlineTextBox.start()) ?
0 : | 772 float start = paintStart == static_cast<unsigned>(m_inlineTextBox.start()) ?
0 : |
| 773 m_inlineTextBox.renderer().width(m_inlineTextBox.start(), paintStart - m
_inlineTextBox.start(), m_inlineTextBox.textPos(), m_inlineTextBox.isLeftToRight
Direction() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle()); | 773 m_inlineTextBox.layoutObject().width(m_inlineTextBox.start(), paintStart
- m_inlineTextBox.start(), m_inlineTextBox.textPos(), m_inlineTextBox.isLeftToR
ightDirection() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle()); |
| 774 // how much line to draw | 774 // how much line to draw |
| 775 float width = (paintStart == static_cast<unsigned>(m_inlineTextBox.start())
&& paintEnd == static_cast<unsigned>(m_inlineTextBox.end()) + 1) ? m_inlineTextB
ox.logicalWidth().toFloat() : | 775 float width = (paintStart == static_cast<unsigned>(m_inlineTextBox.start())
&& paintEnd == static_cast<unsigned>(m_inlineTextBox.end()) + 1) ? m_inlineTextB
ox.logicalWidth().toFloat() : |
| 776 m_inlineTextBox.renderer().width(paintStart, paintEnd - paintStart, m_in
lineTextBox.textPos() + start, m_inlineTextBox.isLeftToRightDirection() ? LTR :
RTL, m_inlineTextBox.isFirstLineStyle()); | 776 m_inlineTextBox.layoutObject().width(paintStart, paintEnd - paintStart,
m_inlineTextBox.textPos() + start, m_inlineTextBox.isLeftToRightDirection() ? LT
R : RTL, m_inlineTextBox.isFirstLineStyle()); |
| 777 | 777 |
| 778 // Thick marked text underlines are 2px thick as long as there is room for t
he 2px line under the baseline. | 778 // Thick marked text underlines are 2px thick as long as there is room for t
he 2px line under the baseline. |
| 779 // All other marked text underlines are 1px thick. | 779 // All other marked text underlines are 1px thick. |
| 780 // If there's not enough space the underline will touch or overlap character
s. | 780 // If there's not enough space the underline will touch or overlap character
s. |
| 781 int lineThickness = 1; | 781 int lineThickness = 1; |
| 782 int baseline = m_inlineTextBox.renderer().style(m_inlineTextBox.isFirstLineS
tyle())->fontMetrics().ascent(); | 782 int baseline = m_inlineTextBox.layoutObject().style(m_inlineTextBox.isFirstL
ineStyle())->fontMetrics().ascent(); |
| 783 if (underline.thick && m_inlineTextBox.logicalHeight() - baseline >= 2) | 783 if (underline.thick && m_inlineTextBox.logicalHeight() - baseline >= 2) |
| 784 lineThickness = 2; | 784 lineThickness = 2; |
| 785 | 785 |
| 786 // We need to have some space between underlines of subsequent clauses, beca
use some input methods do not use different underline styles for those. | 786 // We need to have some space between underlines of subsequent clauses, beca
use some input methods do not use different underline styles for those. |
| 787 // We make each line shorter, which has a harmless side effect of shortening
the first and last clauses, too. | 787 // We make each line shorter, which has a harmless side effect of shortening
the first and last clauses, too. |
| 788 start += 1; | 788 start += 1; |
| 789 width -= 2; | 789 width -= 2; |
| 790 | 790 |
| 791 ctx->setStrokeColor(underline.color); | 791 ctx->setStrokeColor(underline.color); |
| 792 ctx->setStrokeThickness(lineThickness); | 792 ctx->setStrokeThickness(lineThickness); |
| 793 ctx->drawLineForText(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + m_inl
ineTextBox.logicalHeight() - lineThickness), width, m_inlineTextBox.renderer().d
ocument().printing()); | 793 ctx->drawLineForText(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + m_inl
ineTextBox.logicalHeight() - lineThickness), width, m_inlineTextBox.layoutObject
().document().printing()); |
| 794 } | 794 } |
| 795 | 795 |
| 796 void InlineTextBoxPainter::paintTextMatchMarker(GraphicsContext* pt, const Float
Point& boxOrigin, DocumentMarker* marker, const LayoutStyle& style, const Font&
font) | 796 void InlineTextBoxPainter::paintTextMatchMarker(GraphicsContext* pt, const Float
Point& boxOrigin, DocumentMarker* marker, const LayoutStyle& style, const Font&
font) |
| 797 { | 797 { |
| 798 // Use same y positioning and height as for selection, so that when the sele
ction and this highlight are on | 798 // Use same y positioning and height as for selection, so that when the sele
ction and this highlight are on |
| 799 // the same word there are no pieces sticking out. | 799 // the same word there are no pieces sticking out. |
| 800 int deltaY = m_inlineTextBox.renderer().style()->isFlippedLinesWritingMode()
? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBottom() :
m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); | 800 int deltaY = m_inlineTextBox.layoutObject().style()->isFlippedLinesWritingMo
de() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBottom(
) : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); |
| 801 int selHeight = m_inlineTextBox.root().selectionHeight(); | 801 int selHeight = m_inlineTextBox.root().selectionHeight(); |
| 802 | 802 |
| 803 int sPos = std::max(marker->startOffset() - m_inlineTextBox.start(), (unsign
ed)0); | 803 int sPos = std::max(marker->startOffset() - m_inlineTextBox.start(), (unsign
ed)0); |
| 804 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(), m_inlineT
extBox.len()); | 804 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(), m_inlineT
extBox.len()); |
| 805 TextRun run = m_inlineTextBox.constructTextRun(style, font); | 805 TextRun run = m_inlineTextBox.constructTextRun(style, font); |
| 806 | 806 |
| 807 // Always compute and store the rect associated with this marker. The comput
ed rect is in absolute coordinates. | 807 // Always compute and store the rect associated with this marker. The comput
ed rect is in absolute coordinates. |
| 808 IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, IntPoin
t(m_inlineTextBox.x(), m_inlineTextBox.root().selectionTop()), selHeight, sPos,
ePos)); | 808 IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, IntPoin
t(m_inlineTextBox.x(), m_inlineTextBox.root().selectionTop()), selHeight, sPos,
ePos)); |
| 809 markerRect = m_inlineTextBox.renderer().localToAbsoluteQuad(FloatRect(marker
Rect)).enclosingBoundingBox(); | 809 markerRect = m_inlineTextBox.layoutObject().localToAbsoluteQuad(FloatRect(ma
rkerRect)).enclosingBoundingBox(); |
| 810 toRenderedDocumentMarker(marker)->setRenderedRect(LayoutRect(markerRect)); | 810 toRenderedDocumentMarker(marker)->setRenderedRect(LayoutRect(markerRect)); |
| 811 | 811 |
| 812 // Optionally highlight the text | 812 // Optionally highlight the text |
| 813 if (m_inlineTextBox.renderer().frame()->editor().markedTextMatchesAreHighlig
hted()) { | 813 if (m_inlineTextBox.layoutObject().frame()->editor().markedTextMatchesAreHig
hlighted()) { |
| 814 Color color = marker->activeMatch() ? | 814 Color color = marker->activeMatch() ? |
| 815 LayoutTheme::theme().platformActiveTextSearchHighlightColor() : | 815 LayoutTheme::theme().platformActiveTextSearchHighlightColor() : |
| 816 LayoutTheme::theme().platformInactiveTextSearchHighlightColor(); | 816 LayoutTheme::theme().platformInactiveTextSearchHighlightColor(); |
| 817 GraphicsContextStateSaver stateSaver(*pt); | 817 GraphicsContextStateSaver stateSaver(*pt); |
| 818 pt->clip(FloatRect(boxOrigin.x(), boxOrigin.y() - deltaY, m_inlineTextBo
x.logicalWidth(), selHeight)); | 818 pt->clip(FloatRect(boxOrigin.x(), boxOrigin.y() - deltaY, m_inlineTextBo
x.logicalWidth(), selHeight)); |
| 819 pt->drawHighlightForText(font, run, FloatPoint(boxOrigin.x(), boxOrigin.
y() - deltaY), selHeight, color, sPos, ePos); | 819 pt->drawHighlightForText(font, run, FloatPoint(boxOrigin.x(), boxOrigin.
y() - deltaY), selHeight, color, sPos, ePos); |
| 820 } | 820 } |
| 821 } | 821 } |
| 822 | 822 |
| 823 | 823 |
| 824 } // namespace blink | 824 } // namespace blink |
| OLD | NEW |