| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/paint/InlineTextBoxPainter.h" | 5 #include "core/paint/InlineTextBoxPainter.h" |
| 6 | 6 |
| 7 #include "core/editing/CompositionUnderline.h" | 7 #include "core/editing/CompositionUnderline.h" |
| 8 #include "core/editing/Editor.h" | 8 #include "core/editing/Editor.h" |
| 9 #include "core/editing/markers/DocumentMarkerController.h" | 9 #include "core/editing/markers/DocumentMarkerController.h" |
| 10 #include "core/frame/LocalFrame.h" | 10 #include "core/frame/LocalFrame.h" |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 void InlineTextBoxPainter::paintSingleCompositionBackgroundRun(GraphicsContext&
context, const LayoutPoint& boxOrigin, const ComputedStyle& style, const Font& f
ont, Color backgroundColor, int startPos, int endPos) | 279 void InlineTextBoxPainter::paintSingleCompositionBackgroundRun(GraphicsContext&
context, const LayoutPoint& boxOrigin, const ComputedStyle& style, const Font& f
ont, Color backgroundColor, int startPos, int endPos) |
| 280 { | 280 { |
| 281 if (backgroundColor == Color::transparent) | 281 if (backgroundColor == Color::transparent) |
| 282 return; | 282 return; |
| 283 | 283 |
| 284 int sPos = std::max(startPos - static_cast<int>(m_inlineTextBox.start()), 0)
; | 284 int sPos = std::max(startPos - static_cast<int>(m_inlineTextBox.start()), 0)
; |
| 285 int ePos = std::min(endPos - static_cast<int>(m_inlineTextBox.start()), stat
ic_cast<int>(m_inlineTextBox.len())); | 285 int ePos = std::min(endPos - static_cast<int>(m_inlineTextBox.start()), stat
ic_cast<int>(m_inlineTextBox.len())); |
| 286 if (sPos >= ePos) | 286 if (sPos >= ePos) |
| 287 return; | 287 return; |
| 288 | 288 |
| 289 int deltaY = m_inlineTextBox.getLineLayoutItem().style()->isFlippedLinesWrit
ingMode() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBo
ttom() : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); | 289 int deltaY = (m_inlineTextBox.getLineLayoutItem().style()->isFlippedLinesWri
tingMode() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalB
ottom() : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop()).
toInt(); |
| 290 int selHeight = m_inlineTextBox.root().selectionHeight(); | 290 int selHeight = m_inlineTextBox.root().selectionHeight().toInt(); |
| 291 FloatPoint localOrigin(boxOrigin.x().toFloat(), boxOrigin.y().toFloat() - de
ltaY); | 291 FloatPoint localOrigin(boxOrigin.x().toFloat(), boxOrigin.y().toFloat() - de
ltaY); |
| 292 context.drawHighlightForText(font, m_inlineTextBox.constructTextRun(style),
localOrigin, selHeight, backgroundColor, sPos, ePos); | 292 context.drawHighlightForText(font, m_inlineTextBox.constructTextRun(style),
localOrigin, selHeight, backgroundColor, sPos, ePos); |
| 293 } | 293 } |
| 294 | 294 |
| 295 void InlineTextBoxPainter::paintDocumentMarkers(const PaintInfo& paintInfo, cons
t LayoutPoint& boxOrigin, const ComputedStyle& style, const Font& font, Document
MarkerPaintPhase markerPaintPhase) | 295 void InlineTextBoxPainter::paintDocumentMarkers(const PaintInfo& paintInfo, cons
t LayoutPoint& boxOrigin, const ComputedStyle& style, const Font& font, Document
MarkerPaintPhase markerPaintPhase) |
| 296 { | 296 { |
| 297 if (!m_inlineTextBox.getLineLayoutItem().node()) | 297 if (!m_inlineTextBox.getLineLayoutItem().node()) |
| 298 return; | 298 return; |
| 299 | 299 |
| 300 DocumentMarkerVector markers = m_inlineTextBox.getLineLayoutItem().document(
).markers().markersFor(m_inlineTextBox.getLineLayoutItem().node()); | 300 DocumentMarkerVector markers = m_inlineTextBox.getLineLayoutItem().document(
).markers().markersFor(m_inlineTextBox.getLineLayoutItem().node()); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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.getLineLayoutItem().style()->isFlippedLines
WritingMode() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logic
alBottom() : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(
); | 403 int deltaY = (m_inlineTextBox.getLineLayoutItem().style()->isFlippedLine
sWritingMode() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logi
calBottom() : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop
()).toInt(); |
| 404 int selHeight = m_inlineTextBox.root().selectionHeight(); | 404 int selHeight = m_inlineTextBox.root().selectionHeight().toInt(); |
| 405 LayoutPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY); | 405 LayoutPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY); |
| 406 TextRun run = m_inlineTextBox.constructTextRun(style); | 406 TextRun run = m_inlineTextBox.constructTextRun(style); |
| 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, Flo
atPoint(startPoint), 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 = LayoutUnit(markerRect.width()); | 411 width = LayoutUnit(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.getLineLayoutItem().style(m_inlineTextBox.isF
irstLineStyle())->getFontMetrics().ascent(); | 421 int baseline = m_inlineTextBox.getLineLayoutItem().style(m_inlineTextBox.isF
irstLineStyle())->getFontMetrics().ascent(); |
| 422 int descent = m_inlineTextBox.logicalHeight() - baseline; | 422 int descent = (m_inlineTextBox.logicalHeight() - baseline).toInt(); |
| 423 int underlineOffset; | 423 int underlineOffset; |
| 424 if (descent <= (lineThickness + 2)) { | 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).toIn
t(); |
| 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 context.drawLineForDocumentMarker(FloatPoint((boxOrigin.x() + start).toFloat
(), (boxOrigin.y() + underlineOffset).toFloat()), width.toFloat(), lineStyleForM
arkerType(marker->type())); | 431 context.drawLineForDocumentMarker(FloatPoint((boxOrigin.x() + start).toFloat
(), (boxOrigin.y() + underlineOffset).toFloat()), width.toFloat(), lineStyleForM
arkerType(marker->type())); |
| 432 } | 432 } |
| 433 | 433 |
| 434 template <InlineTextBoxPainter::PaintOptions options> | 434 template <InlineTextBoxPainter::PaintOptions options> |
| 435 void InlineTextBoxPainter::paintSelection(GraphicsContext& context, const Layout
Rect& boxRect, const ComputedStyle& style, const Font& font, Color textColor, La
youtTextCombine* combinedText) | 435 void InlineTextBoxPainter::paintSelection(GraphicsContext& context, const Layout
Rect& boxRect, const ComputedStyle& style, const Font& font, Color textColor, La
youtTextCombine* combinedText) |
| 436 { | 436 { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 459 TextRun textRun = m_inlineTextBox.constructTextRun(style, string, m_inlineTe
xtBox.getLineLayoutItem().textLength() - m_inlineTextBox.start(), respectHyphen
? &charactersWithHyphen : 0); | 459 TextRun textRun = m_inlineTextBox.constructTextRun(style, string, m_inlineTe
xtBox.getLineLayoutItem().textLength() - m_inlineTextBox.start(), respectHyphen
? &charactersWithHyphen : 0); |
| 460 if (respectHyphen) | 460 if (respectHyphen) |
| 461 ePos = textRun.length(); | 461 ePos = textRun.length(); |
| 462 | 462 |
| 463 GraphicsContextStateSaver stateSaver(context); | 463 GraphicsContextStateSaver stateSaver(context); |
| 464 | 464 |
| 465 if (options == InlineTextBoxPainter::PaintOptions::CombinedText) { | 465 if (options == InlineTextBoxPainter::PaintOptions::CombinedText) { |
| 466 ASSERT(combinedText); | 466 ASSERT(combinedText); |
| 467 // We can't use the height of m_inlineTextBox because LayoutTextCombine'
s inlineTextBox is horizontal within vertical flow | 467 // We can't use the height of m_inlineTextBox because LayoutTextCombine'
s inlineTextBox is horizontal within vertical flow |
| 468 combinedText->transformToInlineCoordinates(context, boxRect, true); | 468 combinedText->transformToInlineCoordinates(context, boxRect, true); |
| 469 context.drawHighlightForText(font, textRun, FloatPoint(boxRect.location(
)), boxRect.height(), c, sPos, ePos); | 469 context.drawHighlightForText(font, textRun, FloatPoint(boxRect.location(
)), boxRect.height().toInt(), c, sPos, ePos); |
| 470 return; | 470 return; |
| 471 } | 471 } |
| 472 | 472 |
| 473 LayoutUnit selectionBottom = m_inlineTextBox.root().selectionBottom(); | 473 LayoutUnit selectionBottom = m_inlineTextBox.root().selectionBottom(); |
| 474 LayoutUnit selectionTop = m_inlineTextBox.root().selectionTop(); | 474 LayoutUnit selectionTop = m_inlineTextBox.root().selectionTop(); |
| 475 | 475 |
| 476 int deltaY = roundToInt(m_inlineTextBox.getLineLayoutItem().style()->isFlipp
edLinesWritingMode() ? selectionBottom - m_inlineTextBox.logicalBottom() : m_inl
ineTextBox.logicalTop() - selectionTop); | 476 int deltaY = roundToInt(m_inlineTextBox.getLineLayoutItem().style()->isFlipp
edLinesWritingMode() ? selectionBottom - m_inlineTextBox.logicalBottom() : m_inl
ineTextBox.logicalTop() - selectionTop); |
| 477 int selHeight = std::max(0, roundToInt(selectionBottom - selectionTop)); | 477 int selHeight = std::max(0, roundToInt(selectionBottom - selectionTop)); |
| 478 | 478 |
| 479 FloatPoint localOrigin(boxRect.x().toFloat(), (boxRect.y() - deltaY).toFloat
()); | 479 FloatPoint localOrigin(boxRect.x().toFloat(), (boxRect.y() - deltaY).toFloat
()); |
| 480 LayoutRect selectionRect = LayoutRect(font.selectionRectForText(textRun, loc
alOrigin, selHeight, sPos, ePos)); | 480 LayoutRect selectionRect = LayoutRect(font.selectionRectForText(textRun, loc
alOrigin, selHeight, sPos, ePos)); |
| 481 if (m_inlineTextBox.hasWrappedSelectionNewline() | 481 if (m_inlineTextBox.hasWrappedSelectionNewline() |
| 482 // For line breaks, just painting a selection where the line break itsel
f is rendered is sufficient. | 482 // For line breaks, just painting a selection where the line break itsel
f is rendered is sufficient. |
| 483 && !m_inlineTextBox.isLineBreak()) | 483 && !m_inlineTextBox.isLineBreak()) |
| 484 expandToIncludeNewlineForSelection(selectionRect); | 484 expandToIncludeNewlineForSelection(selectionRect); |
| 485 | 485 |
| 486 // Line breaks report themselves as having zero width for layout purposes, | 486 // Line breaks report themselves as having zero width for layout purposes, |
| 487 // and so will end up positioned at (0, 0), even though we paint their | 487 // and so will end up positioned at (0, 0), even though we paint their |
| 488 // selection highlight with character width. For RTL then, we have to | 488 // selection highlight with character width. For RTL then, we have to |
| 489 // explicitly shift the selection rect over to paint in the right location. | 489 // explicitly shift the selection rect over to paint in the right location. |
| 490 if (!m_inlineTextBox.isLeftToRightDirection() && m_inlineTextBox.isLineBreak
()) | 490 if (!m_inlineTextBox.isLeftToRightDirection() && m_inlineTextBox.isLineBreak
()) { |
| 491 selectionRect.move(-selectionRect.width(), 0); | 491 // TODO(crbug.com/638981): Is the conversion to int intentional? |
| 492 selectionRect.move(-selectionRect.width().toInt(), 0); |
| 493 } |
| 492 | 494 |
| 493 context.fillRect(FloatRect(selectionRect), c); | 495 context.fillRect(FloatRect(selectionRect), c); |
| 494 } | 496 } |
| 495 | 497 |
| 496 void InlineTextBoxPainter::expandToIncludeNewlineForSelection(LayoutRect& rect) | 498 void InlineTextBoxPainter::expandToIncludeNewlineForSelection(LayoutRect& rect) |
| 497 { | 499 { |
| 498 FloatRectOutsets outsets = FloatRectOutsets(); | 500 FloatRectOutsets outsets = FloatRectOutsets(); |
| 499 float spaceWidth = m_inlineTextBox.newlineSpaceWidth(); | 501 float spaceWidth = m_inlineTextBox.newlineSpaceWidth(); |
| 500 if (m_inlineTextBox.isLeftToRightDirection()) | 502 if (m_inlineTextBox.isLeftToRightDirection()) |
| 501 outsets.setRight(spaceWidth); | 503 outsets.setRight(spaceWidth); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 522 gap = std::max<int>(1, ceilf(textDecorationThickness / 2.f)); | 524 gap = std::max<int>(1, ceilf(textDecorationThickness / 2.f)); |
| 523 | 525 |
| 524 // FIXME: We support only horizontal text for now. | 526 // FIXME: We support only horizontal text for now. |
| 525 switch (underlinePosition) { | 527 switch (underlinePosition) { |
| 526 case TextUnderlinePositionAuto: | 528 case TextUnderlinePositionAuto: |
| 527 return fontMetrics.ascent() + gap; // Position underline near the alphab
etic baseline. | 529 return fontMetrics.ascent() + gap; // Position underline near the alphab
etic baseline. |
| 528 case TextUnderlinePositionUnder: { | 530 case TextUnderlinePositionUnder: { |
| 529 // Position underline relative to the under edge of the lowest element's
content box. | 531 // Position underline relative to the under edge of the lowest element's
content box. |
| 530 const LayoutUnit offset = inlineTextBox->root().maxLogicalTop() - inline
TextBox->logicalTop(); | 532 const LayoutUnit offset = inlineTextBox->root().maxLogicalTop() - inline
TextBox->logicalTop(); |
| 531 if (offset > 0) | 533 if (offset > 0) |
| 532 return inlineTextBox->logicalHeight() + gap + offset; | 534 return (inlineTextBox->logicalHeight() + gap + offset).toInt(); |
| 533 return inlineTextBox->logicalHeight() + gap; | 535 return (inlineTextBox->logicalHeight() + gap).toInt(); |
| 534 } | 536 } |
| 535 } | 537 } |
| 536 | 538 |
| 537 ASSERT_NOT_REACHED(); | 539 ASSERT_NOT_REACHED(); |
| 538 return fontMetrics.ascent() + gap; | 540 return fontMetrics.ascent() + gap; |
| 539 } | 541 } |
| 540 | 542 |
| 541 static bool shouldSetDecorationAntialias(TextDecorationStyle decorationStyle) | 543 static bool shouldSetDecorationAntialias(TextDecorationStyle decorationStyle) |
| 542 { | 544 { |
| 543 return decorationStyle == TextDecorationStyleDotted || decorationStyle == Te
xtDecorationStyleDashed; | 545 return decorationStyle == TextDecorationStyleDotted || decorationStyle == Te
xtDecorationStyleDashed; |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 861 int sPos = std::max(marker->startOffset() - m_inlineTextBox.start(), (unsign
ed)0); | 863 int sPos = std::max(marker->startOffset() - m_inlineTextBox.start(), (unsign
ed)0); |
| 862 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(), m_inlineT
extBox.len()); | 864 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(), m_inlineT
extBox.len()); |
| 863 TextRun run = m_inlineTextBox.constructTextRun(style); | 865 TextRun run = m_inlineTextBox.constructTextRun(style); |
| 864 | 866 |
| 865 Color color = LayoutTheme::theme().platformTextSearchHighlightColor(marker->
activeMatch()); | 867 Color color = LayoutTheme::theme().platformTextSearchHighlightColor(marker->
activeMatch()); |
| 866 GraphicsContext& context = paintInfo.context; | 868 GraphicsContext& context = paintInfo.context; |
| 867 GraphicsContextStateSaver stateSaver(context); | 869 GraphicsContextStateSaver stateSaver(context); |
| 868 | 870 |
| 869 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), m_i
nlineTextBox.logicalHeight())); | 871 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), m_i
nlineTextBox.logicalHeight())); |
| 870 context.clip(FloatRect(boxRect)); | 872 context.clip(FloatRect(boxRect)); |
| 871 context.drawHighlightForText(font, run, FloatPoint(boxOrigin), boxRect.heigh
t(), color, sPos, ePos); | 873 context.drawHighlightForText(font, run, FloatPoint(boxOrigin), boxRect.heigh
t().toInt(), color, sPos, ePos); |
| 872 } | 874 } |
| 873 | 875 |
| 874 | 876 |
| 875 } // namespace blink | 877 } // namespace blink |
| OLD | NEW |