| 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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 LayoutUnit widthOfHiddenText = m_inlineTextBox.logicalWidth() - widt
hOfVisibleText; | 107 LayoutUnit widthOfHiddenText = m_inlineTextBox.logicalWidth() - widt
hOfVisibleText; |
| 108 // FIXME: The hit testing logic also needs to take this translation
into account. | 108 // FIXME: The hit testing logic also needs to take this translation
into account. |
| 109 LayoutSize truncationOffset(m_inlineTextBox.isLeftToRightDirection()
? widthOfHiddenText : -widthOfHiddenText, 0); | 109 LayoutSize truncationOffset(m_inlineTextBox.isLeftToRightDirection()
? widthOfHiddenText : -widthOfHiddenText, 0); |
| 110 adjustedPaintOffset.move(m_inlineTextBox.isHorizontal() ? truncation
Offset : truncationOffset.transposedSize()); | 110 adjustedPaintOffset.move(m_inlineTextBox.isHorizontal() ? truncation
Offset : truncationOffset.transposedSize()); |
| 111 } | 111 } |
| 112 } | 112 } |
| 113 | 113 |
| 114 GraphicsContext* context = paintInfo.context; | 114 GraphicsContext* context = paintInfo.context; |
| 115 const ComputedStyle& styleToUse = m_inlineTextBox.layoutObject().styleRef(m_
inlineTextBox.isFirstLineStyle()); | 115 const ComputedStyle& styleToUse = m_inlineTextBox.layoutObject().styleRef(m_
inlineTextBox.isFirstLineStyle()); |
| 116 | 116 |
| 117 FloatPoint boxOrigin = m_inlineTextBox.locationIncludingFlipping().toFloatPo
int(); | 117 LayoutPoint boxOrigin(m_inlineTextBox.locationIncludingFlipping()); |
| 118 boxOrigin.move(adjustedPaintOffset.x().toFloat(), adjustedPaintOffset.y().to
Float()); | 118 boxOrigin.move(adjustedPaintOffset.x(), adjustedPaintOffset.y()); |
| 119 FloatRect boxRect(boxOrigin, FloatSize(m_inlineTextBox.logicalWidth(), m_inl
ineTextBox.logicalHeight())); | 119 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), m_i
nlineTextBox.logicalHeight())); |
| 120 | 120 |
| 121 bool shouldRotate = false; | 121 bool shouldRotate = false; |
| 122 LayoutTextCombine* combinedText = nullptr; | 122 LayoutTextCombine* combinedText = nullptr; |
| 123 if (!m_inlineTextBox.isHorizontal()) { | 123 if (!m_inlineTextBox.isHorizontal()) { |
| 124 if (styleToUse.hasTextCombine() && m_inlineTextBox.layoutObject().isComb
ineText()) { | 124 if (styleToUse.hasTextCombine() && m_inlineTextBox.layoutObject().isComb
ineText()) { |
| 125 combinedText = &toLayoutTextCombine(m_inlineTextBox.layoutObject()); | 125 combinedText = &toLayoutTextCombine(m_inlineTextBox.layoutObject()); |
| 126 if (!combinedText->isCombined()) | 126 if (!combinedText->isCombined()) |
| 127 combinedText = nullptr; | 127 combinedText = nullptr; |
| 128 } | 128 } |
| 129 if (combinedText) { | 129 if (combinedText) { |
| 130 combinedText->updateFont(); | 130 combinedText->updateFont(); |
| 131 boxRect.setWidth(combinedText->inlineWidthForLayout()); | 131 boxRect.setWidth(combinedText->inlineWidthForLayout()); |
| 132 } else { | 132 } else { |
| 133 shouldRotate = true; | 133 shouldRotate = true; |
| 134 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Clock
wise)); | 134 context->concatCTM(TextPainter::rotation(boxRect, TextPainter::Clock
wise)); |
| 135 } | 135 } |
| 136 } | 136 } |
| 137 | 137 |
| 138 // Determine text colors. | 138 // Determine text colors. |
| 139 TextPainter::Style textStyle = TextPainter::textPaintingStyle(m_inlineTextBo
x.layoutObject(), styleToUse, paintInfo.forceBlackText(), isPrinting); | 139 TextPainter::Style textStyle = TextPainter::textPaintingStyle(m_inlineTextBo
x.layoutObject(), styleToUse, paintInfo.forceBlackText(), isPrinting); |
| 140 TextPainter::Style selectionStyle = TextPainter::selectionPaintingStyle(m_in
lineTextBox.layoutObject(), haveSelection, paintInfo.forceBlackText(), isPrintin
g, textStyle); | 140 TextPainter::Style selectionStyle = TextPainter::selectionPaintingStyle(m_in
lineTextBox.layoutObject(), haveSelection, paintInfo.forceBlackText(), isPrintin
g, textStyle); |
| 141 bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection); | 141 bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection); |
| 142 bool paintSelectedTextSeparately = !paintSelectedTextOnly && textStyle != se
lectionStyle; | 142 bool paintSelectedTextSeparately = !paintSelectedTextOnly && textStyle != se
lectionStyle; |
| 143 | 143 |
| 144 // Set our font. | 144 // Set our font. |
| 145 const Font& font = styleToUse.font(); | 145 const Font& font = styleToUse.font(); |
| 146 | 146 |
| 147 FloatPoint textOrigin = FloatPoint(boxOrigin.x(), boxOrigin.y() + font.fontM
etrics().ascent()); | 147 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetrics().asc
ent()); |
| 148 | 148 |
| 149 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
include selection | 149 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
include selection |
| 150 // and composition highlights. | 150 // and composition highlights. |
| 151 if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseT
extClip && !isPrinting) { | 151 if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseT
extClip && !isPrinting) { |
| 152 if (containsComposition) { | 152 if (containsComposition) { |
| 153 paintCompositionBackgrounds(context, boxOrigin, styleToUse, font, us
eCustomUnderlines); | 153 paintCompositionBackgrounds(context, boxOrigin, styleToUse, font, us
eCustomUnderlines); |
| 154 } | 154 } |
| 155 | 155 |
| 156 paintDocumentMarkers(context, boxOrigin, styleToUse, font, true); | 156 paintDocumentMarkers(context, boxOrigin, styleToUse, font, true); |
| 157 | 157 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 } | 264 } |
| 265 | 265 |
| 266 unsigned InlineTextBoxPainter::underlinePaintEnd(const CompositionUnderline& und
erline) | 266 unsigned InlineTextBoxPainter::underlinePaintEnd(const CompositionUnderline& und
erline) |
| 267 { | 267 { |
| 268 unsigned paintEnd = std::min(m_inlineTextBox.end() + 1, underline.endOffset)
; // end() points at the last char, not past it. | 268 unsigned paintEnd = std::min(m_inlineTextBox.end() + 1, underline.endOffset)
; // end() points at the last char, not past it. |
| 269 if (m_inlineTextBox.truncation() != cNoTruncation) | 269 if (m_inlineTextBox.truncation() != cNoTruncation) |
| 270 paintEnd = std::min(paintEnd, static_cast<unsigned>(m_inlineTextBox.star
t() + m_inlineTextBox.truncation())); | 270 paintEnd = std::min(paintEnd, static_cast<unsigned>(m_inlineTextBox.star
t() + m_inlineTextBox.truncation())); |
| 271 return paintEnd; | 271 return paintEnd; |
| 272 } | 272 } |
| 273 | 273 |
| 274 void InlineTextBoxPainter::paintCompositionBackgrounds(GraphicsContext* pt, cons
t FloatPoint& boxOrigin, const ComputedStyle& style, const Font& font, bool useC
ustomUnderlines) | 274 void InlineTextBoxPainter::paintCompositionBackgrounds(GraphicsContext* pt, cons
t LayoutPoint& boxOrigin, const ComputedStyle& style, const Font& font, bool use
CustomUnderlines) |
| 275 { | 275 { |
| 276 if (useCustomUnderlines) { | 276 if (useCustomUnderlines) { |
| 277 // Paint custom background highlights for compositions. | 277 // Paint custom background highlights for compositions. |
| 278 const Vector<CompositionUnderline>& underlines = m_inlineTextBox.layoutO
bject().frame()->inputMethodController().customCompositionUnderlines(); | 278 const Vector<CompositionUnderline>& underlines = m_inlineTextBox.layoutO
bject().frame()->inputMethodController().customCompositionUnderlines(); |
| 279 CompositionUnderlineRangeFilter filter(underlines, m_inlineTextBox.start
(), m_inlineTextBox.end()); | 279 CompositionUnderlineRangeFilter filter(underlines, m_inlineTextBox.start
(), m_inlineTextBox.end()); |
| 280 for (CompositionUnderlineRangeFilter::ConstIterator it = filter.begin();
it != filter.end(); ++it) { | 280 for (CompositionUnderlineRangeFilter::ConstIterator it = filter.begin();
it != filter.end(); ++it) { |
| 281 if (it->backgroundColor == Color::transparent) | 281 if (it->backgroundColor == Color::transparent) |
| 282 continue; | 282 continue; |
| 283 paintSingleCompositionBackgroundRun(pt, boxOrigin, style, font, it->
backgroundColor, underlinePaintStart(*it), underlinePaintEnd(*it)); | 283 paintSingleCompositionBackgroundRun(pt, boxOrigin, style, font, it->
backgroundColor, underlinePaintStart(*it), underlinePaintEnd(*it)); |
| 284 } | 284 } |
| 285 | 285 |
| 286 } else { | 286 } else { |
| 287 paintSingleCompositionBackgroundRun(pt, boxOrigin, style, font, LayoutTh
eme::theme().platformDefaultCompositionBackgroundColor(), | 287 paintSingleCompositionBackgroundRun(pt, boxOrigin, style, font, LayoutTh
eme::theme().platformDefaultCompositionBackgroundColor(), |
| 288 m_inlineTextBox.layoutObject().frame()->inputMethodController().comp
ositionStart(), | 288 m_inlineTextBox.layoutObject().frame()->inputMethodController().comp
ositionStart(), |
| 289 m_inlineTextBox.layoutObject().frame()->inputMethodController().comp
ositionEnd()); | 289 m_inlineTextBox.layoutObject().frame()->inputMethodController().comp
ositionEnd()); |
| 290 } | 290 } |
| 291 } | 291 } |
| 292 | 292 |
| 293 void InlineTextBoxPainter::paintSingleCompositionBackgroundRun(GraphicsContext*
context, const FloatPoint& boxOrigin, const ComputedStyle& style, const Font& fo
nt, Color backgroundColor, int startPos, int endPos) | 293 void InlineTextBoxPainter::paintSingleCompositionBackgroundRun(GraphicsContext*
context, const LayoutPoint& boxOrigin, const ComputedStyle& style, const Font& f
ont, Color backgroundColor, int startPos, int endPos) |
| 294 { | 294 { |
| 295 int sPos = std::max(startPos - static_cast<int>(m_inlineTextBox.start()), 0)
; | 295 int sPos = std::max(startPos - static_cast<int>(m_inlineTextBox.start()), 0)
; |
| 296 int ePos = std::min(endPos - static_cast<int>(m_inlineTextBox.start()), stat
ic_cast<int>(m_inlineTextBox.len())); | 296 int ePos = std::min(endPos - static_cast<int>(m_inlineTextBox.start()), stat
ic_cast<int>(m_inlineTextBox.len())); |
| 297 if (sPos >= ePos) | 297 if (sPos >= ePos) |
| 298 return; | 298 return; |
| 299 | 299 |
| 300 int deltaY = m_inlineTextBox.layoutObject().style()->isFlippedLinesWritingMo
de() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBottom(
) : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); | 300 int deltaY = m_inlineTextBox.layoutObject().style()->isFlippedLinesWritingMo
de() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBottom(
) : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); |
| 301 int selHeight = m_inlineTextBox.root().selectionHeight(); | 301 int selHeight = m_inlineTextBox.root().selectionHeight(); |
| 302 FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY); | 302 FloatPoint localOrigin(boxOrigin.x().toFloat(), boxOrigin.y().toFloat() - de
ltaY); |
| 303 context->drawHighlightForText(font, m_inlineTextBox.constructTextRun(style,
font), localOrigin, selHeight, backgroundColor, sPos, ePos); | 303 context->drawHighlightForText(font, m_inlineTextBox.constructTextRun(style,
font), localOrigin, selHeight, backgroundColor, sPos, ePos); |
| 304 } | 304 } |
| 305 | 305 |
| 306 void InlineTextBoxPainter::paintDocumentMarkers(GraphicsContext* pt, const Float
Point& boxOrigin, const ComputedStyle& style, const Font& font, bool background) | 306 void InlineTextBoxPainter::paintDocumentMarkers(GraphicsContext* pt, const Layou
tPoint& boxOrigin, const ComputedStyle& style, const Font& font, bool background
) |
| 307 { | 307 { |
| 308 if (!m_inlineTextBox.layoutObject().node()) | 308 if (!m_inlineTextBox.layoutObject().node()) |
| 309 return; | 309 return; |
| 310 | 310 |
| 311 DocumentMarkerVector markers = m_inlineTextBox.layoutObject().document().mar
kers().markersFor(m_inlineTextBox.layoutObject().node()); | 311 DocumentMarkerVector markers = m_inlineTextBox.layoutObject().document().mar
kers().markersFor(m_inlineTextBox.layoutObject().node()); |
| 312 DocumentMarkerVector::const_iterator markerIt = markers.begin(); | 312 DocumentMarkerVector::const_iterator markerIt = markers.begin(); |
| 313 | 313 |
| 314 // Give any document markers that touch this run a chance to draw before the
text has been drawn. | 314 // Give any document markers that touch this run a chance to draw before the
text has been drawn. |
| 315 // Note end() points at the last char, not one past it like endOffset and ra
nges do. | 315 // Note end() points at the last char, not one past it like endOffset and ra
nges do. |
| 316 for ( ; markerIt != markers.end(); ++markerIt) { | 316 for ( ; markerIt != markers.end(); ++markerIt) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 337 continue; | 337 continue; |
| 338 } | 338 } |
| 339 if (marker->startOffset() > m_inlineTextBox.end()) { | 339 if (marker->startOffset() > m_inlineTextBox.end()) { |
| 340 // marker is completely after this run, bail. A later run will pain
t it. | 340 // marker is completely after this run, bail. A later run will pain
t it. |
| 341 break; | 341 break; |
| 342 } | 342 } |
| 343 | 343 |
| 344 // marker intersects this run. Paint it. | 344 // marker intersects this run. Paint it. |
| 345 switch (marker->type()) { | 345 switch (marker->type()) { |
| 346 case DocumentMarker::Spelling: | 346 case DocumentMarker::Spelling: |
| 347 m_inlineTextBox.paintDocumentMarker(pt, FloatPointWillBeLayoutPoint(
boxOrigin), marker, style, font, false); | 347 m_inlineTextBox.paintDocumentMarker(pt, boxOrigin, marker, style, fo
nt, false); |
| 348 break; | 348 break; |
| 349 case DocumentMarker::Grammar: | 349 case DocumentMarker::Grammar: |
| 350 m_inlineTextBox.paintDocumentMarker(pt, FloatPointWillBeLayoutPoint(
boxOrigin), marker, style, font, true); | 350 m_inlineTextBox.paintDocumentMarker(pt, boxOrigin, marker, style, fo
nt, true); |
| 351 break; | 351 break; |
| 352 case DocumentMarker::TextMatch: | 352 case DocumentMarker::TextMatch: |
| 353 m_inlineTextBox.paintTextMatchMarker(pt, FloatPointWillBeLayoutPoint
(boxOrigin), marker, style, font); | 353 m_inlineTextBox.paintTextMatchMarker(pt, boxOrigin, marker, style, f
ont); |
| 354 break; | 354 break; |
| 355 default: | 355 default: |
| 356 ASSERT_NOT_REACHED(); | 356 ASSERT_NOT_REACHED(); |
| 357 } | 357 } |
| 358 } | 358 } |
| 359 } | 359 } |
| 360 | 360 |
| 361 static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(DocumentM
arker::MarkerType markerType) | 361 static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(DocumentM
arker::MarkerType markerType) |
| 362 { | 362 { |
| 363 switch (markerType) { | 363 switch (markerType) { |
| 364 case DocumentMarker::Spelling: | 364 case DocumentMarker::Spelling: |
| 365 return GraphicsContext::DocumentMarkerSpellingLineStyle; | 365 return GraphicsContext::DocumentMarkerSpellingLineStyle; |
| 366 case DocumentMarker::Grammar: | 366 case DocumentMarker::Grammar: |
| 367 return GraphicsContext::DocumentMarkerGrammarLineStyle; | 367 return GraphicsContext::DocumentMarkerGrammarLineStyle; |
| 368 default: | 368 default: |
| 369 ASSERT_NOT_REACHED(); | 369 ASSERT_NOT_REACHED(); |
| 370 return GraphicsContext::DocumentMarkerSpellingLineStyle; | 370 return GraphicsContext::DocumentMarkerSpellingLineStyle; |
| 371 } | 371 } |
| 372 } | 372 } |
| 373 | 373 |
| 374 void InlineTextBoxPainter::paintDocumentMarker(GraphicsContext* pt, const FloatP
oint& boxOrigin, DocumentMarker* marker, const ComputedStyle& style, const Font&
font, bool grammar) | 374 void InlineTextBoxPainter::paintDocumentMarker(GraphicsContext* pt, const Layout
Point& boxOrigin, DocumentMarker* marker, const ComputedStyle& style, const Font
& font, bool grammar) |
| 375 { | 375 { |
| 376 // Never print spelling/grammar markers (5327887) | 376 // Never print spelling/grammar markers (5327887) |
| 377 if (m_inlineTextBox.layoutObject().document().printing()) | 377 if (m_inlineTextBox.layoutObject().document().printing()) |
| 378 return; | 378 return; |
| 379 | 379 |
| 380 if (m_inlineTextBox.truncation() == cFullTruncation) | 380 if (m_inlineTextBox.truncation() == cFullTruncation) |
| 381 return; | 381 return; |
| 382 | 382 |
| 383 float start = 0; // start of line to draw, relative to tx | 383 LayoutUnit start = 0; // start of line to draw, relative to tx |
| 384 float width = m_inlineTextBox.logicalWidth(); // how much line to draw | 384 LayoutUnit width = m_inlineTextBox.logicalWidth(); // how much line to draw |
| 385 | 385 |
| 386 // Determine whether we need to measure text | 386 // Determine whether we need to measure text |
| 387 bool markerSpansWholeBox = true; | 387 bool markerSpansWholeBox = true; |
| 388 if (m_inlineTextBox.start() <= marker->startOffset()) | 388 if (m_inlineTextBox.start() <= marker->startOffset()) |
| 389 markerSpansWholeBox = false; | 389 markerSpansWholeBox = false; |
| 390 if ((m_inlineTextBox.end() + 1) != marker->endOffset()) // end points at the
last char, not past it | 390 if ((m_inlineTextBox.end() + 1) != marker->endOffset()) // end points at the
last char, not past it |
| 391 markerSpansWholeBox = false; | 391 markerSpansWholeBox = false; |
| 392 if (m_inlineTextBox.truncation() != cNoTruncation) | 392 if (m_inlineTextBox.truncation() != cNoTruncation) |
| 393 markerSpansWholeBox = false; | 393 markerSpansWholeBox = false; |
| 394 | 394 |
| 395 if (!markerSpansWholeBox || grammar) { | 395 if (!markerSpansWholeBox || grammar) { |
| 396 int startPosition = std::max<int>(marker->startOffset() - m_inlineTextBo
x.start(), 0); | 396 int startPosition = std::max<int>(marker->startOffset() - m_inlineTextBo
x.start(), 0); |
| 397 int endPosition = std::min<int>(marker->endOffset() - static_cast<int>(m
_inlineTextBox.start()), m_inlineTextBox.len()); | 397 int endPosition = std::min<int>(marker->endOffset() - static_cast<int>(m
_inlineTextBox.start()), m_inlineTextBox.len()); |
| 398 | 398 |
| 399 if (m_inlineTextBox.truncation() != cNoTruncation) | 399 if (m_inlineTextBox.truncation() != cNoTruncation) |
| 400 endPosition = std::min<int>(endPosition, m_inlineTextBox.truncation(
)); | 400 endPosition = std::min<int>(endPosition, m_inlineTextBox.truncation(
)); |
| 401 | 401 |
| 402 // Calculate start & width | 402 // Calculate start & width |
| 403 int deltaY = m_inlineTextBox.layoutObject().style()->isFlippedLinesWriti
ngMode() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBot
tom() : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); | 403 int deltaY = m_inlineTextBox.layoutObject().style()->isFlippedLinesWriti
ngMode() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBot
tom() : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); |
| 404 int selHeight = m_inlineTextBox.root().selectionHeight(); | 404 int selHeight = m_inlineTextBox.root().selectionHeight(); |
| 405 FloatPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY); | 405 LayoutPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY); |
| 406 TextRun run = m_inlineTextBox.constructTextRun(style, font); | 406 TextRun run = m_inlineTextBox.constructTextRun(style, font); |
| 407 | 407 |
| 408 // FIXME: Convert the document markers to float rects. | 408 // FIXME: Convert the document markers to float rects. |
| 409 IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, sta
rtPoint, selHeight, startPosition, endPosition)); | 409 IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, Flo
atPoint(startPoint), selHeight, startPosition, endPosition)); |
| 410 start = markerRect.x() - startPoint.x(); | 410 start = markerRect.x() - startPoint.x(); |
| 411 width = markerRect.width(); | 411 width = markerRect.width(); |
| 412 } | 412 } |
| 413 | 413 |
| 414 // IMPORTANT: The misspelling underline is not considered when calculating t
he text bounds, so we have to | 414 // IMPORTANT: The misspelling underline is not considered when calculating t
he text bounds, so we have to |
| 415 // make sure to fit within those bounds. This means the top pixel(s) of the
underline will overlap the | 415 // make sure to fit within those bounds. This means the top pixel(s) of the
underline will overlap the |
| 416 // bottom pixel(s) of the glyphs in smaller font sizes. The alternatives ar
e to increase the line spacing (bad!!) | 416 // bottom pixel(s) of the glyphs in smaller font sizes. The alternatives ar
e to increase the line spacing (bad!!) |
| 417 // or decrease the underline thickness. The overlap is actually the most us
eful, and matches what AppKit does. | 417 // or decrease the underline thickness. The overlap is actually the most us
eful, and matches what AppKit does. |
| 418 // So, we generally place the underline at the bottom of the text, but in la
rger fonts that's not so good so | 418 // So, we generally place the underline at the bottom of the text, but in la
rger fonts that's not so good so |
| 419 // we pin to two pixels under the baseline. | 419 // we pin to two pixels under the baseline. |
| 420 int lineThickness = misspellingLineThickness; | 420 int lineThickness = misspellingLineThickness; |
| 421 int baseline = m_inlineTextBox.layoutObject().style(m_inlineTextBox.isFirstL
ineStyle())->fontMetrics().ascent(); | 421 int baseline = m_inlineTextBox.layoutObject().style(m_inlineTextBox.isFirstL
ineStyle())->fontMetrics().ascent(); |
| 422 int descent = m_inlineTextBox.logicalHeight() - baseline; | 422 int descent = m_inlineTextBox.logicalHeight() - baseline; |
| 423 int underlineOffset; | 423 int underlineOffset; |
| 424 if (descent <= (2 + lineThickness)) { | 424 if (descent <= (lineThickness + 2)) { |
| 425 // Place the underline at the very bottom of the text in small/medium fo
nts. | 425 // Place the underline at the very bottom of the text in small/medium fo
nts. |
| 426 underlineOffset = m_inlineTextBox.logicalHeight() - lineThickness; | 426 underlineOffset = m_inlineTextBox.logicalHeight() - lineThickness; |
| 427 } else { | 427 } else { |
| 428 // In larger fonts, though, place the underline up near the baseline to
prevent a big gap. | 428 // In larger fonts, though, place the underline up near the baseline to
prevent a big gap. |
| 429 underlineOffset = baseline + 2; | 429 underlineOffset = baseline + 2; |
| 430 } | 430 } |
| 431 pt->drawLineForDocumentMarker(FloatPoint(boxOrigin.x() + start, boxOrigin.y(
) + underlineOffset), width, lineStyleForMarkerType(marker->type())); | 431 pt->drawLineForDocumentMarker(FloatPoint((boxOrigin.x() + start).toFloat(),
(boxOrigin.y() + underlineOffset).toFloat()), width.toFloat(), lineStyleForMarke
rType(marker->type())); |
| 432 } | 432 } |
| 433 | 433 |
| 434 template <InlineTextBoxPainter::PaintOptions options> | 434 template <InlineTextBoxPainter::PaintOptions options> |
| 435 void InlineTextBoxPainter::paintSelection(GraphicsContext* context, const FloatR
ect& boxRect, const ComputedStyle& style, const Font& font, Color textColor, Lay
outTextCombine* combinedText) | 435 void InlineTextBoxPainter::paintSelection(GraphicsContext* context, const Layout
Rect& boxRect, const ComputedStyle& style, const Font& font, Color textColor, La
youtTextCombine* combinedText) |
| 436 { | 436 { |
| 437 // See if we have a selection to paint at all. | 437 // See if we have a selection to paint at all. |
| 438 int sPos, ePos; | 438 int sPos, ePos; |
| 439 m_inlineTextBox.selectionStartEnd(sPos, ePos); | 439 m_inlineTextBox.selectionStartEnd(sPos, ePos); |
| 440 if (sPos >= ePos) | 440 if (sPos >= ePos) |
| 441 return; | 441 return; |
| 442 | 442 |
| 443 Color c = m_inlineTextBox.layoutObject().selectionBackgroundColor(); | 443 Color c = m_inlineTextBox.layoutObject().selectionBackgroundColor(); |
| 444 if (!c.alpha()) | 444 if (!c.alpha()) |
| 445 return; | 445 return; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 461 bool respectHyphen = ePos == length && m_inlineTextBox.hasHyphen(); | 461 bool respectHyphen = ePos == length && m_inlineTextBox.hasHyphen(); |
| 462 TextRun textRun = m_inlineTextBox.constructTextRun(style, font, string, m_in
lineTextBox.layoutObject().textLength() - m_inlineTextBox.start(), respectHyphen
? &charactersWithHyphen : 0); | 462 TextRun textRun = m_inlineTextBox.constructTextRun(style, font, string, m_in
lineTextBox.layoutObject().textLength() - m_inlineTextBox.start(), respectHyphen
? &charactersWithHyphen : 0); |
| 463 if (respectHyphen) | 463 if (respectHyphen) |
| 464 ePos = textRun.length(); | 464 ePos = textRun.length(); |
| 465 | 465 |
| 466 GraphicsContextStateSaver stateSaver(*context); | 466 GraphicsContextStateSaver stateSaver(*context); |
| 467 | 467 |
| 468 if (options == InlineTextBoxPainter::PaintOptions::CombinedText) { | 468 if (options == InlineTextBoxPainter::PaintOptions::CombinedText) { |
| 469 ASSERT(combinedText); | 469 ASSERT(combinedText); |
| 470 // We can't use the height of m_inlineTextBox because LayoutTextCombine'
s inlineTextBox is horizontal within vertical flow | 470 // We can't use the height of m_inlineTextBox because LayoutTextCombine'
s inlineTextBox is horizontal within vertical flow |
| 471 FloatRect clipRect = boxRect; | 471 LayoutRect clipRect(boxRect); |
| 472 combinedText->transformLayoutRect(clipRect); | 472 combinedText->transformLayoutRect(clipRect); |
| 473 context->clip(clipRect); | 473 context->clip(FloatRect(clipRect)); |
| 474 combinedText->transformToInlineCoordinates(*context, boxRect); | 474 combinedText->transformToInlineCoordinates(*context, boxRect); |
| 475 context->drawHighlightForText(font, textRun, boxRect.location(), boxRect
.height(), c, sPos, ePos); | 475 context->drawHighlightForText(font, textRun, FloatPoint(boxRect.location
()), boxRect.height(), c, sPos, ePos); |
| 476 return; | 476 return; |
| 477 } | 477 } |
| 478 | 478 |
| 479 LayoutUnit selectionBottom = m_inlineTextBox.root().selectionBottom(); | 479 LayoutUnit selectionBottom = m_inlineTextBox.root().selectionBottom(); |
| 480 LayoutUnit selectionTop = m_inlineTextBox.root().selectionTopAdjustedForPrec
edingBlock(); | 480 LayoutUnit selectionTop = m_inlineTextBox.root().selectionTopAdjustedForPrec
edingBlock(); |
| 481 | 481 |
| 482 int deltaY = roundToInt(m_inlineTextBox.layoutObject().style()->isFlippedLin
esWritingMode() ? selectionBottom - m_inlineTextBox.logicalBottom() : m_inlineTe
xtBox.logicalTop() - selectionTop); | 482 int deltaY = roundToInt(m_inlineTextBox.layoutObject().style()->isFlippedLin
esWritingMode() ? selectionBottom - m_inlineTextBox.logicalBottom() : m_inlineTe
xtBox.logicalTop() - selectionTop); |
| 483 int selHeight = std::max(0, roundToInt(selectionBottom - selectionTop)); | 483 int selHeight = std::max(0, roundToInt(selectionBottom - selectionTop)); |
| 484 | 484 |
| 485 FloatPoint localOrigin(boxRect.x(), boxRect.y() - deltaY); | 485 FloatPoint localOrigin(boxRect.x().toFloat(), (boxRect.y() - deltaY).toFloat
()); |
| 486 FloatRect clipRect(localOrigin, FloatSize(m_inlineTextBox.logicalWidth(), se
lHeight)); | 486 FloatRect clipRect(localOrigin, FloatSize(m_inlineTextBox.logicalWidth().toF
loat(), selHeight)); |
| 487 | 487 |
| 488 context->clip(clipRect); | 488 context->clip(clipRect); |
| 489 context->drawHighlightForText(font, textRun, localOrigin, selHeight, c, sPos
, ePos); | 489 context->drawHighlightForText(font, textRun, localOrigin, selHeight, c, sPos
, ePos); |
| 490 } | 490 } |
| 491 | 491 |
| 492 static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition,
const FontMetrics& fontMetrics, const InlineTextBox* inlineTextBox, const float
textDecorationThickness) | 492 static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition,
const FontMetrics& fontMetrics, const InlineTextBox* inlineTextBox, const float
textDecorationThickness) |
| 493 { | 493 { |
| 494 // Compute the gap between the font and the underline. Use at least one | 494 // Compute the gap between the font and the underline. Use at least one |
| 495 // pixel gap, if underline is thick then use a bigger gap. | 495 // pixel gap, if underline is thick then use a bigger gap. |
| 496 int gap = 0; | 496 int gap = 0; |
| 497 | 497 |
| 498 // Underline position of zero means draw underline on Baseline Position, | 498 // Underline position of zero means draw underline on Baseline Position, |
| 499 // in Blink we need at least 1-pixel gap to adding following check. | 499 // in Blink we need at least 1-pixel gap to adding following check. |
| 500 // Positive underline Position means underline should be drawn above baselin
e | 500 // Positive underline Position means underline should be drawn above baselin
e |
| 501 // and negative value means drawing below baseline, negating the value as in
Blink | 501 // and negative value means drawing below baseline, negating the value as in
Blink |
| 502 // downward Y-increases. | 502 // downward Y-increases. |
| 503 | 503 |
| 504 if (fontMetrics.underlinePosition()) | 504 if (fontMetrics.underlinePosition()) |
| 505 gap = -fontMetrics.underlinePosition(); | 505 gap = -fontMetrics.underlinePosition(); |
| 506 else | 506 else |
| 507 gap = std::max<int>(1, ceilf(textDecorationThickness / 2.f)); | 507 gap = std::max<int>(1, ceilf(textDecorationThickness / 2.f)); |
| 508 | 508 |
| 509 // FIXME: We support only horizontal text for now. | 509 // FIXME: We support only horizontal text for now. |
| 510 switch (underlinePosition) { | 510 switch (underlinePosition) { |
| 511 case TextUnderlinePositionAuto: | 511 case TextUnderlinePositionAuto: |
| 512 return fontMetrics.ascent() + gap; // Position underline near the alphab
etic baseline. | 512 return fontMetrics.ascent() + gap; // Position underline near the alphab
etic baseline. |
| 513 case TextUnderlinePositionUnder: { | 513 case TextUnderlinePositionUnder: { |
| 514 // Position underline relative to the under edge of the lowest element's
content box. | 514 // Position underline relative to the under edge of the lowest element's
content box. |
| 515 const float offset = inlineTextBox->root().maxLogicalTop() - inlineTextB
ox->logicalTop(); | 515 const LayoutUnit offset = inlineTextBox->root().maxLogicalTop() - inline
TextBox->logicalTop(); |
| 516 if (offset > 0) | 516 if (offset > 0) |
| 517 return inlineTextBox->logicalHeight() + gap + offset; | 517 return inlineTextBox->logicalHeight() + gap + offset; |
| 518 return inlineTextBox->logicalHeight() + gap; | 518 return inlineTextBox->logicalHeight() + gap; |
| 519 } | 519 } |
| 520 } | 520 } |
| 521 | 521 |
| 522 ASSERT_NOT_REACHED(); | 522 ASSERT_NOT_REACHED(); |
| 523 return fontMetrics.ascent() + gap; | 523 return fontMetrics.ascent() + gap; |
| 524 } | 524 } |
| 525 | 525 |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 | 687 |
| 688 switch (decoration.style) { | 688 switch (decoration.style) { |
| 689 case TextDecorationStyleWavy: | 689 case TextDecorationStyleWavy: |
| 690 strokeWavyTextDecoration(context, start + FloatPoint(0, doubleOffset * w
avyOffsetFactor), start + FloatPoint(width, doubleOffset * wavyOffsetFactor), th
ickness); | 690 strokeWavyTextDecoration(context, start + FloatPoint(0, doubleOffset * w
avyOffsetFactor), start + FloatPoint(width, doubleOffset * wavyOffsetFactor), th
ickness); |
| 691 break; | 691 break; |
| 692 case TextDecorationStyleDotted: | 692 case TextDecorationStyleDotted: |
| 693 case TextDecorationStyleDashed: | 693 case TextDecorationStyleDashed: |
| 694 context->setShouldAntialias(antialiasDecoration); | 694 context->setShouldAntialias(antialiasDecoration); |
| 695 // Fall through | 695 // Fall through |
| 696 default: | 696 default: |
| 697 context->drawLineForText(start, width, isPrinting); | 697 context->drawLineForText(FloatPoint(start), width, isPrinting); |
| 698 | 698 |
| 699 if (decoration.style == TextDecorationStyleDouble) | 699 if (decoration.style == TextDecorationStyleDouble) |
| 700 context->drawLineForText(start + FloatPoint(0, doubleOffset), width,
isPrinting); | 700 context->drawLineForText(start + FloatPoint(0, doubleOffset), width,
isPrinting); |
| 701 } | 701 } |
| 702 } | 702 } |
| 703 | 703 |
| 704 void InlineTextBoxPainter::paintDecoration(GraphicsContext* context, const Float
Point& boxOrigin, TextDecoration deco) | 704 void InlineTextBoxPainter::paintDecoration(GraphicsContext* context, const Layou
tPoint& boxOrigin, TextDecoration deco) |
| 705 { | 705 { |
| 706 GraphicsContextStateSaver stateSaver(*context); | 706 GraphicsContextStateSaver stateSaver(*context); |
| 707 | 707 |
| 708 if (m_inlineTextBox.truncation() == cFullTruncation) | 708 if (m_inlineTextBox.truncation() == cFullTruncation) |
| 709 return; | 709 return; |
| 710 | 710 |
| 711 FloatPoint localOrigin = boxOrigin; | 711 LayoutPoint localOrigin(boxOrigin); |
| 712 | 712 |
| 713 float width = m_inlineTextBox.logicalWidth(); | 713 LayoutUnit width = m_inlineTextBox.logicalWidth(); |
| 714 if (m_inlineTextBox.truncation() != cNoTruncation) { | 714 if (m_inlineTextBox.truncation() != cNoTruncation) { |
| 715 width = m_inlineTextBox.layoutObject().width(m_inlineTextBox.start(), m_
inlineTextBox.truncation(), m_inlineTextBox.textPos(), m_inlineTextBox.isLeftToR
ightDirection() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle()); | 715 width = m_inlineTextBox.layoutObject().width(m_inlineTextBox.start(), m_
inlineTextBox.truncation(), m_inlineTextBox.textPos(), m_inlineTextBox.isLeftToR
ightDirection() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle()); |
| 716 if (!m_inlineTextBox.isLeftToRightDirection()) | 716 if (!m_inlineTextBox.isLeftToRightDirection()) |
| 717 localOrigin.move(m_inlineTextBox.logicalWidth() - width, 0); | 717 localOrigin.move(m_inlineTextBox.logicalWidth() - width, 0); |
| 718 } | 718 } |
| 719 | 719 |
| 720 // Get the text decoration colors. | 720 // Get the text decoration colors. |
| 721 LayoutObject::AppliedTextDecoration underline, overline, linethrough; | 721 LayoutObject::AppliedTextDecoration underline, overline, linethrough; |
| 722 m_inlineTextBox.layoutObject().getTextDecorations(deco, underline, overline,
linethrough, true); | 722 m_inlineTextBox.layoutObject().getTextDecorations(deco, underline, overline,
linethrough, true); |
| 723 if (m_inlineTextBox.isFirstLineStyle()) | 723 if (m_inlineTextBox.isFirstLineStyle()) |
| 724 m_inlineTextBox.layoutObject().getTextDecorations(deco, underline, overl
ine, linethrough, true, true); | 724 m_inlineTextBox.layoutObject().getTextDecorations(deco, underline, overl
ine, linethrough, true, true); |
| 725 | 725 |
| 726 // Use a special function for underlines to get the positioning exactly righ
t. | 726 // Use a special function for underlines to get the positioning exactly righ
t. |
| 727 bool isPrinting = m_inlineTextBox.layoutObject().document().printing(); | 727 bool isPrinting = m_inlineTextBox.layoutObject().document().printing(); |
| 728 | 728 |
| 729 const ComputedStyle& styleToUse = m_inlineTextBox.layoutObject().styleRef(m_
inlineTextBox.isFirstLineStyle()); | 729 const ComputedStyle& styleToUse = m_inlineTextBox.layoutObject().styleRef(m_
inlineTextBox.isFirstLineStyle()); |
| 730 int baseline = styleToUse.fontMetrics().ascent(); | 730 float baseline = styleToUse.fontMetrics().ascent(); |
| 731 | 731 |
| 732 // Set the thick of the line to be 10% (or something else ?)of the computed
font size and not less than 1px. | 732 // Set the thick of the line to be 10% (or something else ?)of the computed
font size and not less than 1px. |
| 733 // Using computedFontSize should take care of zoom as well. | 733 // Using computedFontSize should take care of zoom as well. |
| 734 | 734 |
| 735 // Update Underline thickness, in case we have Faulty Font Metrics calculati
ng underline thickness by old method. | 735 // Update Underline thickness, in case we have Faulty Font Metrics calculati
ng underline thickness by old method. |
| 736 float textDecorationThickness = styleToUse.fontMetrics().underlineThickness(
); | 736 float textDecorationThickness = styleToUse.fontMetrics().underlineThickness(
); |
| 737 int fontHeightInt = (int)(styleToUse.fontMetrics().floatHeight() + 0.5); | 737 int fontHeightInt = (int)(styleToUse.fontMetrics().floatHeight() + 0.5); |
| 738 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei
ghtInt >> 1))) | 738 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei
ghtInt >> 1))) |
| 739 textDecorationThickness = std::max(1.f, styleToUse.computedFontSize() /
10.f); | 739 textDecorationThickness = std::max(1.f, styleToUse.computedFontSize() /
10.f); |
| 740 | 740 |
| 741 context->setStrokeThickness(textDecorationThickness); | 741 context->setStrokeThickness(textDecorationThickness); |
| 742 | 742 |
| 743 bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, unde
rline.style, linethrough.style) | 743 bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, unde
rline.style, linethrough.style) |
| 744 && BoxPainter::shouldAntialiasLines(context); | 744 && BoxPainter::shouldAntialiasLines(context); |
| 745 | 745 |
| 746 // Offset between lines - always non-zero, so lines never cross each other. | 746 // Offset between lines - always non-zero, so lines never cross each other. |
| 747 float doubleOffset = textDecorationThickness + 1.f; | 747 float doubleOffset = textDecorationThickness + 1.f; |
| 748 | 748 |
| 749 if (deco & TextDecorationUnderline) { | 749 if (deco & TextDecorationUnderline) { |
| 750 const int underlineOffset = computeUnderlineOffset(styleToUse.textUnderl
inePosition(), styleToUse.fontMetrics(), &m_inlineTextBox, textDecorationThickne
ss); | 750 const int underlineOffset = computeUnderlineOffset(styleToUse.textUnderl
inePosition(), styleToUse.fontMetrics(), &m_inlineTextBox, textDecorationThickne
ss); |
| 751 paintAppliedDecoration(context, localOrigin + FloatPoint(0, underlineOff
set), width, doubleOffset, 1, underline, textDecorationThickness, antialiasDecor
ation, isPrinting); | 751 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint(0,
underlineOffset), width.toFloat(), doubleOffset, 1, underline, textDecorationThi
ckness, antialiasDecoration, isPrinting); |
| 752 } | 752 } |
| 753 if (deco & TextDecorationOverline) { | 753 if (deco & TextDecorationOverline) { |
| 754 paintAppliedDecoration(context, localOrigin, width, -doubleOffset, 1, ov
erline, textDecorationThickness, antialiasDecoration, isPrinting); | 754 paintAppliedDecoration(context, FloatPoint(localOrigin), width.toFloat()
, -doubleOffset, 1, overline, textDecorationThickness, antialiasDecoration, isPr
inting); |
| 755 } | 755 } |
| 756 if (deco & TextDecorationLineThrough) { | 756 if (deco & TextDecorationLineThrough) { |
| 757 const float lineThroughOffset = 2 * baseline / 3; | 757 const float lineThroughOffset = 2 * baseline / 3; |
| 758 paintAppliedDecoration(context, localOrigin + FloatPoint(0, lineThroughO
ffset), width, doubleOffset, 0, linethrough, textDecorationThickness, antialiasD
ecoration, isPrinting); | 758 paintAppliedDecoration(context, FloatPoint(localOrigin) + FloatPoint(0,
lineThroughOffset), width.toFloat(), doubleOffset, 0, linethrough, textDecoratio
nThickness, antialiasDecoration, isPrinting); |
| 759 } | 759 } |
| 760 } | 760 } |
| 761 | 761 |
| 762 void InlineTextBoxPainter::paintCompositionUnderline(GraphicsContext* ctx, const
FloatPoint& boxOrigin, const CompositionUnderline& underline) | 762 void InlineTextBoxPainter::paintCompositionUnderline(GraphicsContext* ctx, const
LayoutPoint& boxOrigin, const CompositionUnderline& underline) |
| 763 { | 763 { |
| 764 if (m_inlineTextBox.truncation() == cFullTruncation) | 764 if (m_inlineTextBox.truncation() == cFullTruncation) |
| 765 return; | 765 return; |
| 766 | 766 |
| 767 unsigned paintStart = underlinePaintStart(underline); | 767 unsigned paintStart = underlinePaintStart(underline); |
| 768 unsigned paintEnd = underlinePaintEnd(underline); | 768 unsigned paintEnd = underlinePaintEnd(underline); |
| 769 | 769 |
| 770 // start of line to draw, relative to paintOffset. | 770 // start of line to draw, relative to paintOffset. |
| 771 float start = paintStart == static_cast<unsigned>(m_inlineTextBox.start()) ?
0 : | 771 float start = paintStart == static_cast<unsigned>(m_inlineTextBox.start()) ?
0 : |
| 772 m_inlineTextBox.layoutObject().width(m_inlineTextBox.start(), paintStart
- m_inlineTextBox.start(), m_inlineTextBox.textPos(), m_inlineTextBox.isLeftToR
ightDirection() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle()); | 772 m_inlineTextBox.layoutObject().width(m_inlineTextBox.start(), paintStart
- m_inlineTextBox.start(), m_inlineTextBox.textPos(), m_inlineTextBox.isLeftToR
ightDirection() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle()); |
| 773 // how much line to draw | 773 // how much line to draw |
| 774 float width = (paintStart == static_cast<unsigned>(m_inlineTextBox.start())
&& paintEnd == static_cast<unsigned>(m_inlineTextBox.end()) + 1) ? m_inlineTextB
ox.logicalWidth().toFloat() : | 774 float width = (paintStart == static_cast<unsigned>(m_inlineTextBox.start())
&& paintEnd == static_cast<unsigned>(m_inlineTextBox.end()) + 1) ? m_inlineTextB
ox.logicalWidth().toFloat() : |
| 775 m_inlineTextBox.layoutObject().width(paintStart, paintEnd - paintStart,
m_inlineTextBox.textPos() + start, m_inlineTextBox.isLeftToRightDirection() ? LT
R : RTL, m_inlineTextBox.isFirstLineStyle()); | 775 m_inlineTextBox.layoutObject().width(paintStart, paintEnd - paintStart,
m_inlineTextBox.textPos() + start, m_inlineTextBox.isLeftToRightDirection() ? LT
R : RTL, m_inlineTextBox.isFirstLineStyle()); |
| 776 | 776 |
| 777 // Thick marked text underlines are 2px thick as long as there is room for t
he 2px line under the baseline. | 777 // Thick marked text underlines are 2px thick as long as there is room for t
he 2px line under the baseline. |
| 778 // All other marked text underlines are 1px thick. | 778 // All other marked text underlines are 1px thick. |
| 779 // If there's not enough space the underline will touch or overlap character
s. | 779 // If there's not enough space the underline will touch or overlap character
s. |
| 780 int lineThickness = 1; | 780 int lineThickness = 1; |
| 781 int baseline = m_inlineTextBox.layoutObject().style(m_inlineTextBox.isFirstL
ineStyle())->fontMetrics().ascent(); | 781 int baseline = m_inlineTextBox.layoutObject().style(m_inlineTextBox.isFirstL
ineStyle())->fontMetrics().ascent(); |
| 782 if (underline.thick && m_inlineTextBox.logicalHeight() - baseline >= 2) | 782 if (underline.thick && m_inlineTextBox.logicalHeight() - baseline >= 2) |
| 783 lineThickness = 2; | 783 lineThickness = 2; |
| 784 | 784 |
| 785 // We need to have some space between underlines of subsequent clauses, beca
use some input methods do not use different underline styles for those. | 785 // 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 make each line shorter, which has a harmless side effect of shortening
the first and last clauses, too. | 786 // We make each line shorter, which has a harmless side effect of shortening
the first and last clauses, too. |
| 787 start += 1; | 787 start += 1; |
| 788 width -= 2; | 788 width -= 2; |
| 789 | 789 |
| 790 ctx->setStrokeColor(underline.color); | 790 ctx->setStrokeColor(underline.color); |
| 791 ctx->setStrokeThickness(lineThickness); | 791 ctx->setStrokeThickness(lineThickness); |
| 792 ctx->drawLineForText(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + m_inl
ineTextBox.logicalHeight() - lineThickness), width, m_inlineTextBox.layoutObject
().document().printing()); | 792 ctx->drawLineForText(FloatPoint(boxOrigin.x() + start, (boxOrigin.y() + m_in
lineTextBox.logicalHeight() - lineThickness).toFloat()), width, m_inlineTextBox.
layoutObject().document().printing()); |
| 793 } | 793 } |
| 794 | 794 |
| 795 void InlineTextBoxPainter::paintTextMatchMarker(GraphicsContext* pt, const Float
Point& boxOrigin, DocumentMarker* marker, const ComputedStyle& style, const Font
& font) | 795 void InlineTextBoxPainter::paintTextMatchMarker(GraphicsContext* pt, const Layou
tPoint& boxOrigin, DocumentMarker* marker, const ComputedStyle& style, const Fon
t& font) |
| 796 { | 796 { |
| 797 // Use same y positioning and height as for selection, so that when the sele
ction and this highlight are on | 797 // Use same y positioning and height as for selection, so that when the sele
ction and this highlight are on |
| 798 // the same word there are no pieces sticking out. | 798 // the same word there are no pieces sticking out. |
| 799 int deltaY = m_inlineTextBox.layoutObject().style()->isFlippedLinesWritingMo
de() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBottom(
) : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); | 799 int deltaY = m_inlineTextBox.layoutObject().style()->isFlippedLinesWritingMo
de() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBottom(
) : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); |
| 800 int selHeight = m_inlineTextBox.root().selectionHeight(); | 800 int selHeight = m_inlineTextBox.root().selectionHeight(); |
| 801 | 801 |
| 802 int sPos = std::max(marker->startOffset() - m_inlineTextBox.start(), (unsign
ed)0); | 802 int sPos = std::max(marker->startOffset() - m_inlineTextBox.start(), (unsign
ed)0); |
| 803 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(), m_inlineT
extBox.len()); | 803 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(), m_inlineT
extBox.len()); |
| 804 TextRun run = m_inlineTextBox.constructTextRun(style, font); | 804 TextRun run = m_inlineTextBox.constructTextRun(style, font); |
| 805 | 805 |
| 806 // Optionally highlight the text | 806 // Optionally highlight the text |
| 807 if (m_inlineTextBox.layoutObject().frame()->editor().markedTextMatchesAreHig
hlighted()) { | 807 if (m_inlineTextBox.layoutObject().frame()->editor().markedTextMatchesAreHig
hlighted()) { |
| 808 Color color = marker->activeMatch() ? | 808 Color color = marker->activeMatch() ? |
| 809 LayoutTheme::theme().platformActiveTextSearchHighlightColor() : | 809 LayoutTheme::theme().platformActiveTextSearchHighlightColor() : |
| 810 LayoutTheme::theme().platformInactiveTextSearchHighlightColor(); | 810 LayoutTheme::theme().platformInactiveTextSearchHighlightColor(); |
| 811 GraphicsContextStateSaver stateSaver(*pt); | 811 GraphicsContextStateSaver stateSaver(*pt); |
| 812 pt->clip(FloatRect(boxOrigin.x(), boxOrigin.y() - deltaY, m_inlineTextBo
x.logicalWidth(), selHeight)); | 812 pt->clip(FloatRect(boxOrigin.x().toFloat(), (boxOrigin.y() - deltaY).toF
loat(), m_inlineTextBox.logicalWidth().toFloat(), selHeight)); |
| 813 pt->drawHighlightForText(font, run, FloatPoint(boxOrigin.x(), boxOrigin.
y() - deltaY), selHeight, color, sPos, ePos); | 813 pt->drawHighlightForText(font, run, FloatPoint(boxOrigin.x().toFloat(),
(boxOrigin.y() - deltaY).toFloat()), selHeight, color, sPos, ePos); |
| 814 } | 814 } |
| 815 } | 815 } |
| 816 | 816 |
| 817 | 817 |
| 818 } // namespace blink | 818 } // namespace blink |
| OLD | NEW |