| 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 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 // tests for != PaintPhaseTextClip. | 258 // tests for != PaintPhaseTextClip. |
| 259 if (m_inlineTextBox.getLineLayoutItem().style()->visibility() != EVisibility
::Visible | 259 if (m_inlineTextBox.getLineLayoutItem().style()->visibility() != EVisibility
::Visible |
| 260 || m_inlineTextBox.truncation() == cFullTruncation | 260 || m_inlineTextBox.truncation() == cFullTruncation |
| 261 || !m_inlineTextBox.len()) | 261 || !m_inlineTextBox.len()) |
| 262 return false; | 262 return false; |
| 263 return true; | 263 return true; |
| 264 } | 264 } |
| 265 | 265 |
| 266 unsigned InlineTextBoxPainter::underlinePaintStart(const CompositionUnderline& u
nderline) | 266 unsigned InlineTextBoxPainter::underlinePaintStart(const CompositionUnderline& u
nderline) |
| 267 { | 267 { |
| 268 return std::max(static_cast<unsigned>(m_inlineTextBox.start()), underline.st
artOffset()); | 268 DCHECK(m_inlineTextBox.truncation() != cFullTruncation); |
| 269 DCHECK(m_inlineTextBox.len()); |
| 270 |
| 271 // Start painting at the beginning of the text or the specified underline |
| 272 // start offset, whichever is higher. |
| 273 unsigned paintStart = std::max(m_inlineTextBox.start(), underline.startOffse
t()); |
| 274 // Cap the maximum paint start to (if no truncation) the last character, |
| 275 // else the last character before the truncation ellipsis. |
| 276 return std::min(paintStart, (m_inlineTextBox.truncation() == cNoTruncation)
? |
| 277 m_inlineTextBox.end() : m_inlineTextBox.start() + m_inlineTextBox.trunca
tion() - 1); |
| 269 } | 278 } |
| 270 | 279 |
| 271 unsigned InlineTextBoxPainter::underlinePaintEnd(const CompositionUnderline& und
erline) | 280 unsigned InlineTextBoxPainter::underlinePaintEnd(const CompositionUnderline& und
erline) |
| 272 { | 281 { |
| 282 DCHECK(m_inlineTextBox.truncation() != cFullTruncation); |
| 283 DCHECK(m_inlineTextBox.len()); |
| 284 |
| 285 // End painting just past the end of the text or the specified underline end |
| 286 // offset, whichever is lower. |
| 273 unsigned paintEnd = std::min(m_inlineTextBox.end() + 1, underline.endOffset(
)); // end() points at the last char, not past it. | 287 unsigned paintEnd = std::min(m_inlineTextBox.end() + 1, underline.endOffset(
)); // end() points at the last char, not past it. |
| 274 if (m_inlineTextBox.truncation() != cNoTruncation) | 288 // Cap the maximum paint end to (if no truncation) one past the last |
| 275 paintEnd = std::min(paintEnd, static_cast<unsigned>(m_inlineTextBox.star
t() + m_inlineTextBox.truncation())); | 289 // character, else one past the last character before the truncation |
| 276 return paintEnd; | 290 // ellipsis. |
| 291 return std::min(paintEnd, (m_inlineTextBox.truncation() == cNoTruncation) ? |
| 292 m_inlineTextBox.end() + 1 : m_inlineTextBox.start() + m_inlineTextBox.tr
uncation()); |
| 277 } | 293 } |
| 278 | 294 |
| 279 void InlineTextBoxPainter::paintSingleCompositionBackgroundRun(GraphicsContext&
context, const LayoutPoint& boxOrigin, const ComputedStyle& style, const Font& f
ont, Color backgroundColor, int startPos, int endPos) | 295 void InlineTextBoxPainter::paintSingleCompositionBackgroundRun(GraphicsContext&
context, const LayoutPoint& boxOrigin, const ComputedStyle& style, const Font& f
ont, Color backgroundColor, int startPos, int endPos) |
| 280 { | 296 { |
| 281 if (backgroundColor == Color::transparent) | 297 if (backgroundColor == Color::transparent) |
| 282 return; | 298 return; |
| 283 | 299 |
| 284 int sPos = std::max(startPos - static_cast<int>(m_inlineTextBox.start()), 0)
; | 300 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())); | 301 int ePos = std::min(endPos - static_cast<int>(m_inlineTextBox.start()), stat
ic_cast<int>(m_inlineTextBox.len())); |
| 286 if (sPos >= ePos) | 302 if (sPos >= ePos) |
| 287 return; | 303 return; |
| 288 | 304 |
| 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(); | 305 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().toInt(); | 306 int selHeight = m_inlineTextBox.root().selectionHeight().toInt(); |
| 291 FloatPoint localOrigin(boxOrigin.x().toFloat(), boxOrigin.y().toFloat() - de
ltaY); | 307 FloatPoint localOrigin(boxOrigin.x().toFloat(), boxOrigin.y().toFloat() - de
ltaY); |
| 292 context.drawHighlightForText(font, m_inlineTextBox.constructTextRun(style),
localOrigin, selHeight, backgroundColor, sPos, ePos); | 308 context.drawHighlightForText(font, m_inlineTextBox.constructTextRun(style),
localOrigin, selHeight, backgroundColor, sPos, ePos); |
| 293 } | 309 } |
| 294 | 310 |
| 295 void InlineTextBoxPainter::paintDocumentMarkers(const PaintInfo& paintInfo, cons
t LayoutPoint& boxOrigin, const ComputedStyle& style, const Font& font, Document
MarkerPaintPhase markerPaintPhase) | 311 void InlineTextBoxPainter::paintDocumentMarkers(const PaintInfo& paintInfo, cons
t LayoutPoint& boxOrigin, const ComputedStyle& style, const Font& font, Document
MarkerPaintPhase markerPaintPhase) |
| 296 { | 312 { |
| 297 if (!m_inlineTextBox.getLineLayoutItem().node()) | 313 if (!m_inlineTextBox.getLineLayoutItem().node()) |
| 298 return; | 314 return; |
| 299 | 315 |
| 316 DCHECK(m_inlineTextBox.truncation() != cFullTruncation); |
| 317 DCHECK(m_inlineTextBox.len()); |
| 318 |
| 300 DocumentMarkerVector markers = m_inlineTextBox.getLineLayoutItem().document(
).markers().markersFor(m_inlineTextBox.getLineLayoutItem().node()); | 319 DocumentMarkerVector markers = m_inlineTextBox.getLineLayoutItem().document(
).markers().markersFor(m_inlineTextBox.getLineLayoutItem().node()); |
| 301 DocumentMarkerVector::const_iterator markerIt = markers.begin(); | 320 DocumentMarkerVector::const_iterator markerIt = markers.begin(); |
| 302 | 321 |
| 303 // Give any document markers that touch this run a chance to draw before the
text has been drawn. | 322 // Give any document markers that touch this run a chance to draw before the
text has been drawn. |
| 304 // Note end() points at the last char, not one past it like endOffset and ra
nges do. | 323 // Note end() points at the last char, not one past it like endOffset and ra
nges do. |
| 305 for ( ; markerIt != markers.end(); ++markerIt) { | 324 for ( ; markerIt != markers.end(); ++markerIt) { |
| 306 DocumentMarker* marker = *markerIt; | 325 DocumentMarker* marker = *markerIt; |
| 307 | 326 |
| 308 // Paint either the background markers or the foreground markers, but no
t both | 327 // Paint either the background markers or the foreground markers, but no
t both |
| 309 switch (marker->type()) { | 328 switch (marker->type()) { |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 unsigned start = m_inlineTextBox.start(); | 473 unsigned start = m_inlineTextBox.start(); |
| 455 int length = m_inlineTextBox.len(); | 474 int length = m_inlineTextBox.len(); |
| 456 bool ltr = m_inlineTextBox.isLeftToRightDirection(); | 475 bool ltr = m_inlineTextBox.isLeftToRightDirection(); |
| 457 bool flowIsLTR = m_inlineTextBox.getLineLayoutItem().style()->isLeftToRightD
irection(); | 476 bool flowIsLTR = m_inlineTextBox.getLineLayoutItem().style()->isLeftToRightD
irection(); |
| 458 if (m_inlineTextBox.truncation() != cNoTruncation) { | 477 if (m_inlineTextBox.truncation() != cNoTruncation) { |
| 459 start = ltr == flowIsLTR ? m_inlineTextBox.start() : m_inlineTextBox.tru
ncation(); | 478 start = ltr == flowIsLTR ? m_inlineTextBox.start() : m_inlineTextBox.tru
ncation(); |
| 460 length = ltr == flowIsLTR ? m_inlineTextBox.truncation() : m_inlineTextB
ox.len() - m_inlineTextBox.truncation(); | 479 length = ltr == flowIsLTR ? m_inlineTextBox.truncation() : m_inlineTextB
ox.len() - m_inlineTextBox.truncation(); |
| 461 } | 480 } |
| 462 StringView string(m_inlineTextBox.getLineLayoutItem().text(), start, static_
cast<unsigned>(length)); | 481 StringView string(m_inlineTextBox.getLineLayoutItem().text(), start, static_
cast<unsigned>(length)); |
| 463 | 482 |
| 464 | |
| 465 StringBuilder charactersWithHyphen; | 483 StringBuilder charactersWithHyphen; |
| 466 bool respectHyphen = ePos == length && m_inlineTextBox.hasHyphen(); | 484 bool respectHyphen = ePos == length && m_inlineTextBox.hasHyphen(); |
| 467 TextRun textRun = m_inlineTextBox.constructTextRun(style, string, m_inlineTe
xtBox.getLineLayoutItem().textLength() - m_inlineTextBox.start(), respectHyphen
? &charactersWithHyphen : 0); | 485 TextRun textRun = m_inlineTextBox.constructTextRun(style, string, m_inlineTe
xtBox.getLineLayoutItem().textLength() - m_inlineTextBox.start(), respectHyphen
? &charactersWithHyphen : 0); |
| 468 if (respectHyphen) | 486 if (respectHyphen) |
| 469 ePos = textRun.length(); | 487 ePos = textRun.length(); |
| 470 | 488 |
| 471 GraphicsContextStateSaver stateSaver(context); | 489 GraphicsContextStateSaver stateSaver(context); |
| 472 | 490 |
| 473 if (options == InlineTextBoxPainter::PaintOptions::CombinedText) { | 491 if (options == InlineTextBoxPainter::PaintOptions::CombinedText) { |
| 474 ASSERT(combinedText); | 492 ASSERT(combinedText); |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 792 void InlineTextBoxPainter::paintCompositionUnderline(GraphicsContext& context, c
onst LayoutPoint& boxOrigin, const CompositionUnderline& underline) | 810 void InlineTextBoxPainter::paintCompositionUnderline(GraphicsContext& context, c
onst LayoutPoint& boxOrigin, const CompositionUnderline& underline) |
| 793 { | 811 { |
| 794 if (underline.color() == Color::transparent) | 812 if (underline.color() == Color::transparent) |
| 795 return; | 813 return; |
| 796 | 814 |
| 797 if (m_inlineTextBox.truncation() == cFullTruncation) | 815 if (m_inlineTextBox.truncation() == cFullTruncation) |
| 798 return; | 816 return; |
| 799 | 817 |
| 800 unsigned paintStart = underlinePaintStart(underline); | 818 unsigned paintStart = underlinePaintStart(underline); |
| 801 unsigned paintEnd = underlinePaintEnd(underline); | 819 unsigned paintEnd = underlinePaintEnd(underline); |
| 820 DCHECK_LT(paintStart, paintEnd); |
| 802 | 821 |
| 803 // start of line to draw | 822 // start of line to draw |
| 804 float start = paintStart == static_cast<unsigned>(m_inlineTextBox.start()) ?
0 : | 823 float start = paintStart == m_inlineTextBox.start() ? 0 : |
| 805 m_inlineTextBox.getLineLayoutItem().width(m_inlineTextBox.start(), paint
Start - m_inlineTextBox.start(), m_inlineTextBox.textPos(), m_inlineTextBox.isLe
ftToRightDirection() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle()); | 824 m_inlineTextBox.getLineLayoutItem().width(m_inlineTextBox.start(), paint
Start - m_inlineTextBox.start(), m_inlineTextBox.textPos(), m_inlineTextBox.isLe
ftToRightDirection() ? LTR : RTL, m_inlineTextBox.isFirstLineStyle()); |
| 806 // how much line to draw | 825 // how much line to draw |
| 807 float width; | 826 float width; |
| 808 bool ltr = m_inlineTextBox.isLeftToRightDirection(); | 827 bool ltr = m_inlineTextBox.isLeftToRightDirection(); |
| 809 bool flowIsLTR = m_inlineTextBox.getLineLayoutItem().style()->isLeftToRightD
irection(); | 828 bool flowIsLTR = m_inlineTextBox.getLineLayoutItem().style()->isLeftToRightD
irection(); |
| 810 if (paintStart == static_cast<unsigned>(m_inlineTextBox.start()) && paintEnd
== static_cast<unsigned>(m_inlineTextBox.end()) + 1) { | 829 if (paintStart == m_inlineTextBox.start() && paintEnd == m_inlineTextBox.end
() + 1) { |
| 811 width = m_inlineTextBox.logicalWidth().toFloat(); | 830 width = m_inlineTextBox.logicalWidth().toFloat(); |
| 812 } else { | 831 } else { |
| 813 width = m_inlineTextBox.getLineLayoutItem().width(ltr == flowIsLTR ? pai
ntStart : paintEnd, ltr == flowIsLTR ? paintEnd - paintStart : m_inlineTextBox.l
en() - paintEnd, LayoutUnit(m_inlineTextBox.textPos() + start), flowIsLTR ? LTR
: RTL, m_inlineTextBox.isFirstLineStyle()); | 832 unsigned paintFrom = ltr == flowIsLTR ? paintStart : paintEnd; |
| 833 unsigned paintLength = ltr == flowIsLTR ? paintEnd - paintStart : m_inli
neTextBox.start() + m_inlineTextBox.len() - paintEnd; |
| 834 width = m_inlineTextBox.getLineLayoutItem().width(paintFrom, paintLength
, |
| 835 LayoutUnit(m_inlineTextBox.textPos() + start), flowIsLTR ? LTR : RTL
, m_inlineTextBox.isFirstLineStyle()); |
| 814 } | 836 } |
| 815 // In RTL mode, start and width are computed from the right end of the text
box: | 837 // In RTL mode, start and width are computed from the right end of the text
box: |
| 816 // starting at |logicalWidth| - |start| and continuing left by |width| to | 838 // starting at |logicalWidth| - |start| and continuing left by |width| to |
| 817 // |logicalWidth| - |start| - |width|. We will draw that line, but | 839 // |logicalWidth| - |start| - |width|. We will draw that line, but |
| 818 // backwards: |logicalWidth| - |start| - |width| to |logicalWidth| - |start|
. | 840 // backwards: |logicalWidth| - |start| - |width| to |logicalWidth| - |start|
. |
| 819 if (!flowIsLTR) | 841 if (!flowIsLTR) |
| 820 start = m_inlineTextBox.logicalWidth().toFloat() - width - start; | 842 start = m_inlineTextBox.logicalWidth().toFloat() - width - start; |
| 821 | 843 |
| 822 | |
| 823 // Thick marked text underlines are 2px thick as long as there is room for t
he 2px line under the baseline. | 844 // Thick marked text underlines are 2px thick as long as there is room for t
he 2px line under the baseline. |
| 824 // All other marked text underlines are 1px thick. | 845 // All other marked text underlines are 1px thick. |
| 825 // If there's not enough space the underline will touch or overlap character
s. | 846 // If there's not enough space the underline will touch or overlap character
s. |
| 826 int lineThickness = 1; | 847 int lineThickness = 1; |
| 827 int baseline = m_inlineTextBox.getLineLayoutItem().style(m_inlineTextBox.isF
irstLineStyle())->getFontMetrics().ascent(); | 848 int baseline = m_inlineTextBox.getLineLayoutItem().style(m_inlineTextBox.isF
irstLineStyle())->getFontMetrics().ascent(); |
| 828 if (underline.thick() && m_inlineTextBox.logicalHeight() - baseline >= 2) | 849 if (underline.thick() && m_inlineTextBox.logicalHeight() - baseline >= 2) |
| 829 lineThickness = 2; | 850 lineThickness = 2; |
| 830 | 851 |
| 831 // We need to have some space between underlines of subsequent clauses, beca
use some input methods do not use different underline styles for those. | 852 // We need to have some space between underlines of subsequent clauses, beca
use some input methods do not use different underline styles for those. |
| 832 // We make each line shorter, which has a harmless side effect of shortening
the first and last clauses, too. | 853 // We make each line shorter, which has a harmless side effect of shortening
the first and last clauses, too. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 874 | 895 |
| 875 Color color = LayoutTheme::theme().platformTextSearchHighlightColor(marker->
activeMatch()); | 896 Color color = LayoutTheme::theme().platformTextSearchHighlightColor(marker->
activeMatch()); |
| 876 GraphicsContext& context = paintInfo.context; | 897 GraphicsContext& context = paintInfo.context; |
| 877 GraphicsContextStateSaver stateSaver(context); | 898 GraphicsContextStateSaver stateSaver(context); |
| 878 | 899 |
| 879 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), m_i
nlineTextBox.logicalHeight())); | 900 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), m_i
nlineTextBox.logicalHeight())); |
| 880 context.clip(FloatRect(boxRect)); | 901 context.clip(FloatRect(boxRect)); |
| 881 context.drawHighlightForText(font, run, FloatPoint(boxOrigin), boxRect.heigh
t().toInt(), color, sPos, ePos); | 902 context.drawHighlightForText(font, run, FloatPoint(boxOrigin), boxRect.heigh
t().toInt(), color, sPos, ePos); |
| 882 } | 903 } |
| 883 | 904 |
| 884 | |
| 885 } // namespace blink | 905 } // namespace blink |
| OLD | NEW |