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 |