| 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 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 552 int selectionEnd = 0; | 552 int selectionEnd = 0; |
| 553 if (paintSelectedTextOnly || paintSelectedTextSeparately) | 553 if (paintSelectedTextOnly || paintSelectedTextSeparately) |
| 554 m_inlineTextBox.selectionStartEnd(selectionStart, selectionEnd); | 554 m_inlineTextBox.selectionStartEnd(selectionStart, selectionEnd); |
| 555 | 555 |
| 556 bool respectHyphen = | 556 bool respectHyphen = |
| 557 selectionEnd == static_cast<int>(m_inlineTextBox.len()) && | 557 selectionEnd == static_cast<int>(m_inlineTextBox.len()) && |
| 558 m_inlineTextBox.hasHyphen(); | 558 m_inlineTextBox.hasHyphen(); |
| 559 if (respectHyphen) | 559 if (respectHyphen) |
| 560 selectionEnd = textRun.length(); | 560 selectionEnd = textRun.length(); |
| 561 | 561 |
| 562 bool ltr = m_inlineTextBox.isLeftToRightDirection(); | |
| 563 bool flowIsLTR = | |
| 564 m_inlineTextBox.getLineLayoutItem().style()->isLeftToRightDirection(); | |
| 565 if (m_inlineTextBox.truncation() != cNoTruncation) { | 562 if (m_inlineTextBox.truncation() != cNoTruncation) { |
| 566 // In a mixed-direction flow the ellipsis is at the start of the text | |
| 567 // rather than at the end of it. | |
| 568 selectionStart = | 563 selectionStart = |
| 569 ltr == flowIsLTR | 564 std::min<int>(selectionStart, m_inlineTextBox.truncation()); |
| 570 ? std::min<int>(selectionStart, m_inlineTextBox.truncation()) | 565 selectionEnd = std::min<int>(selectionEnd, m_inlineTextBox.truncation()); |
| 571 : std::max<int>(selectionStart, m_inlineTextBox.truncation()); | 566 length = m_inlineTextBox.truncation(); |
| 572 selectionEnd = | |
| 573 ltr == flowIsLTR | |
| 574 ? std::min<int>(selectionEnd, m_inlineTextBox.truncation()) | |
| 575 : std::max<int>(selectionEnd, m_inlineTextBox.truncation()); | |
| 576 length = ltr == flowIsLTR ? m_inlineTextBox.truncation() : textRun.length(); | |
| 577 } | 567 } |
| 578 | 568 |
| 579 TextPainter textPainter(context, font, textRun, textOrigin, boxRect, | 569 TextPainter textPainter(context, font, textRun, textOrigin, boxRect, |
| 580 m_inlineTextBox.isHorizontal()); | 570 m_inlineTextBox.isHorizontal()); |
| 581 TextEmphasisPosition emphasisMarkPosition; | 571 TextEmphasisPosition emphasisMarkPosition; |
| 582 bool hasTextEmphasis = | 572 bool hasTextEmphasis = |
| 583 m_inlineTextBox.getEmphasisMarkPosition(styleToUse, emphasisMarkPosition); | 573 m_inlineTextBox.getEmphasisMarkPosition(styleToUse, emphasisMarkPosition); |
| 584 if (hasTextEmphasis) | 574 if (hasTextEmphasis) |
| 585 textPainter.setEmphasisMark(styleToUse.textEmphasisMarkString(), | 575 textPainter.setEmphasisMark(styleToUse.textEmphasisMarkString(), |
| 586 emphasisMarkPosition); | 576 emphasisMarkPosition); |
| 587 if (combinedText) | 577 if (combinedText) |
| 588 textPainter.setCombinedText(combinedText); | 578 textPainter.setCombinedText(combinedText); |
| 589 if (m_inlineTextBox.truncation() != cNoTruncation && ltr != flowIsLTR) | |
| 590 textPainter.setEllipsisOffset(m_inlineTextBox.truncation()); | |
| 591 | 579 |
| 592 if (!paintSelectedTextOnly) { | 580 if (!paintSelectedTextOnly) { |
| 593 int startOffset = 0; | 581 int startOffset = 0; |
| 594 int endOffset = length; | 582 int endOffset = length; |
| 583 if (paintSelectedTextSeparately && selectionStart < selectionEnd) { |
| 584 startOffset = selectionEnd; |
| 585 endOffset = selectionStart; |
| 586 } |
| 595 // Where the text and its flow have opposite directions then our offset into | 587 // Where the text and its flow have opposite directions then our offset into |
| 596 // the text given by |truncation| is at the start of the part that will be | 588 // the text given by |truncation| is at the start of the part that will be |
| 597 // visible. | 589 // visible. |
| 598 if (m_inlineTextBox.truncation() != cNoTruncation && ltr != flowIsLTR) { | 590 if (m_inlineTextBox.truncation() != cNoTruncation && |
| 591 m_inlineTextBox.getLineLayoutItem() |
| 592 .containingBlock() |
| 593 .style() |
| 594 ->isLeftToRightDirection() != |
| 595 m_inlineTextBox.isLeftToRightDirection()) { |
| 599 startOffset = m_inlineTextBox.truncation(); | 596 startOffset = m_inlineTextBox.truncation(); |
| 600 endOffset = textRun.length(); | 597 endOffset = textRun.length(); |
| 601 } | 598 } |
| 602 | 599 |
| 603 if (paintSelectedTextSeparately && selectionStart < selectionEnd) { | |
| 604 startOffset = selectionEnd; | |
| 605 endOffset = selectionStart; | |
| 606 } | |
| 607 | |
| 608 // FIXME: This cache should probably ultimately be held somewhere else. | 600 // FIXME: This cache should probably ultimately be held somewhere else. |
| 609 // A hashmap is convenient to avoid a memory hit when the | 601 // A hashmap is convenient to avoid a memory hit when the |
| 610 // RuntimeEnabledFeature is off. | 602 // RuntimeEnabledFeature is off. |
| 611 bool textBlobIsCacheable = startOffset == 0 && endOffset == length; | 603 bool textBlobIsCacheable = startOffset == 0 && endOffset == length; |
| 612 TextBlobPtr* cachedTextBlob = 0; | 604 TextBlobPtr* cachedTextBlob = 0; |
| 613 if (textBlobIsCacheable) | 605 if (textBlobIsCacheable) |
| 614 cachedTextBlob = addToTextBlobCache(m_inlineTextBox); | 606 cachedTextBlob = addToTextBlobCache(m_inlineTextBox); |
| 615 textPainter.paint(startOffset, endOffset, length, textStyle, | 607 textPainter.paint(startOffset, endOffset, length, textStyle, |
| 616 cachedTextBlob); | 608 cachedTextBlob); |
| 617 } | 609 } |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 946 c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); | 938 c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); |
| 947 | 939 |
| 948 // If the text is truncated, let the thing being painted in the truncation | 940 // If the text is truncated, let the thing being painted in the truncation |
| 949 // draw its own highlight. | 941 // draw its own highlight. |
| 950 unsigned start = m_inlineTextBox.start(); | 942 unsigned start = m_inlineTextBox.start(); |
| 951 int length = m_inlineTextBox.len(); | 943 int length = m_inlineTextBox.len(); |
| 952 bool ltr = m_inlineTextBox.isLeftToRightDirection(); | 944 bool ltr = m_inlineTextBox.isLeftToRightDirection(); |
| 953 bool flowIsLTR = | 945 bool flowIsLTR = |
| 954 m_inlineTextBox.getLineLayoutItem().style()->isLeftToRightDirection(); | 946 m_inlineTextBox.getLineLayoutItem().style()->isLeftToRightDirection(); |
| 955 if (m_inlineTextBox.truncation() != cNoTruncation) { | 947 if (m_inlineTextBox.truncation() != cNoTruncation) { |
| 956 // In a mixed-direction flow the ellipsis is at the start of the text | 948 start = ltr == flowIsLTR ? m_inlineTextBox.start() |
| 957 // so we need to start after it. Otherwise we just need to make sure | 949 : m_inlineTextBox.truncation(); |
| 958 // the end of the text is where the ellipsis starts. | 950 length = ltr == flowIsLTR |
| 959 if (ltr != flowIsLTR) | 951 ? m_inlineTextBox.truncation() |
| 960 sPos = std::max<int>(sPos, m_inlineTextBox.truncation()); | 952 : m_inlineTextBox.len() - m_inlineTextBox.truncation(); |
| 961 else | |
| 962 length = m_inlineTextBox.truncation(); | |
| 963 } | 953 } |
| 964 StringView string(m_inlineTextBox.getLineLayoutItem().text(), start, | 954 StringView string(m_inlineTextBox.getLineLayoutItem().text(), start, |
| 965 static_cast<unsigned>(length)); | 955 static_cast<unsigned>(length)); |
| 966 | 956 |
| 967 StringBuilder charactersWithHyphen; | 957 StringBuilder charactersWithHyphen; |
| 968 bool respectHyphen = ePos == length && m_inlineTextBox.hasHyphen(); | 958 bool respectHyphen = ePos == length && m_inlineTextBox.hasHyphen(); |
| 969 TextRun textRun = m_inlineTextBox.constructTextRun( | 959 TextRun textRun = m_inlineTextBox.constructTextRun( |
| 970 style, string, m_inlineTextBox.getLineLayoutItem().textLength() - | 960 style, string, m_inlineTextBox.getLineLayoutItem().textLength() - |
| 971 m_inlineTextBox.start(), | 961 m_inlineTextBox.start(), |
| 972 respectHyphen ? &charactersWithHyphen : 0); | 962 respectHyphen ? &charactersWithHyphen : 0); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 991 int deltaY = roundToInt( | 981 int deltaY = roundToInt( |
| 992 m_inlineTextBox.getLineLayoutItem().style()->isFlippedLinesWritingMode() | 982 m_inlineTextBox.getLineLayoutItem().style()->isFlippedLinesWritingMode() |
| 993 ? selectionBottom - m_inlineTextBox.logicalBottom() | 983 ? selectionBottom - m_inlineTextBox.logicalBottom() |
| 994 : m_inlineTextBox.logicalTop() - selectionTop); | 984 : m_inlineTextBox.logicalTop() - selectionTop); |
| 995 int selHeight = std::max(0, roundToInt(selectionBottom - selectionTop)); | 985 int selHeight = std::max(0, roundToInt(selectionBottom - selectionTop)); |
| 996 | 986 |
| 997 FloatPoint localOrigin(boxRect.x().toFloat(), | 987 FloatPoint localOrigin(boxRect.x().toFloat(), |
| 998 (boxRect.y() - deltaY).toFloat()); | 988 (boxRect.y() - deltaY).toFloat()); |
| 999 LayoutRect selectionRect = LayoutRect( | 989 LayoutRect selectionRect = LayoutRect( |
| 1000 font.selectionRectForText(textRun, localOrigin, selHeight, sPos, ePos)); | 990 font.selectionRectForText(textRun, localOrigin, selHeight, sPos, ePos)); |
| 1001 // For line breaks, just painting a selection where the line break itself | 991 if (m_inlineTextBox.hasWrappedSelectionNewline() |
| 1002 // is rendered is sufficient. Don't select it if there's an ellipsis | 992 // For line breaks, just painting a selection where the line break itself |
| 1003 // there. | 993 // is rendered is sufficient. |
| 1004 if (m_inlineTextBox.hasWrappedSelectionNewline() && | 994 && !m_inlineTextBox.isLineBreak()) |
| 1005 m_inlineTextBox.truncation() == cNoTruncation && | |
| 1006 !m_inlineTextBox.isLineBreak()) | |
| 1007 expandToIncludeNewlineForSelection(selectionRect); | 995 expandToIncludeNewlineForSelection(selectionRect); |
| 1008 | 996 |
| 1009 // Line breaks report themselves as having zero width for layout purposes, | 997 // Line breaks report themselves as having zero width for layout purposes, |
| 1010 // and so will end up positioned at (0, 0), even though we paint their | 998 // and so will end up positioned at (0, 0), even though we paint their |
| 1011 // selection highlight with character width. For RTL then, we have to | 999 // selection highlight with character width. For RTL then, we have to |
| 1012 // explicitly shift the selection rect over to paint in the right location. | 1000 // explicitly shift the selection rect over to paint in the right location. |
| 1013 if (!m_inlineTextBox.isLeftToRightDirection() && | 1001 if (!m_inlineTextBox.isLeftToRightDirection() && |
| 1014 m_inlineTextBox.isLineBreak()) | 1002 m_inlineTextBox.isLineBreak()) |
| 1015 selectionRect.move(-selectionRect.width(), LayoutUnit()); | 1003 selectionRect.move(-selectionRect.width(), LayoutUnit()); |
| 1016 if (!flowIsLTR && !ltr && m_inlineTextBox.truncation() != cNoTruncation) | 1004 if (!flowIsLTR && m_inlineTextBox.truncation() != cNoTruncation) |
| 1017 selectionRect.move(m_inlineTextBox.logicalWidth() - selectionRect.width(), | 1005 selectionRect.move(m_inlineTextBox.logicalWidth() - selectionRect.width(), |
| 1018 LayoutUnit()); | 1006 LayoutUnit()); |
| 1019 | 1007 |
| 1020 context.fillRect(FloatRect(selectionRect), c); | 1008 context.fillRect(FloatRect(selectionRect), c); |
| 1021 } | 1009 } |
| 1022 | 1010 |
| 1023 void InlineTextBoxPainter::expandToIncludeNewlineForSelection( | 1011 void InlineTextBoxPainter::expandToIncludeNewlineForSelection( |
| 1024 LayoutRect& rect) { | 1012 LayoutRect& rect) { |
| 1025 FloatRectOutsets outsets = FloatRectOutsets(); | 1013 FloatRectOutsets outsets = FloatRectOutsets(); |
| 1026 float spaceWidth = m_inlineTextBox.newlineSpaceWidth(); | 1014 float spaceWidth = m_inlineTextBox.newlineSpaceWidth(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1043 GraphicsContextStateSaver stateSaver(context); | 1031 GraphicsContextStateSaver stateSaver(context); |
| 1044 | 1032 |
| 1045 LayoutPoint localOrigin(boxOrigin); | 1033 LayoutPoint localOrigin(boxOrigin); |
| 1046 | 1034 |
| 1047 LayoutUnit width = m_inlineTextBox.logicalWidth(); | 1035 LayoutUnit width = m_inlineTextBox.logicalWidth(); |
| 1048 if (m_inlineTextBox.truncation() != cNoTruncation) { | 1036 if (m_inlineTextBox.truncation() != cNoTruncation) { |
| 1049 bool ltr = m_inlineTextBox.isLeftToRightDirection(); | 1037 bool ltr = m_inlineTextBox.isLeftToRightDirection(); |
| 1050 bool flowIsLTR = | 1038 bool flowIsLTR = |
| 1051 m_inlineTextBox.getLineLayoutItem().style()->isLeftToRightDirection(); | 1039 m_inlineTextBox.getLineLayoutItem().style()->isLeftToRightDirection(); |
| 1052 width = LayoutUnit(m_inlineTextBox.getLineLayoutItem().width( | 1040 width = LayoutUnit(m_inlineTextBox.getLineLayoutItem().width( |
| 1053 ltr == flowIsLTR | 1041 ltr == flowIsLTR ? m_inlineTextBox.start() |
| 1054 ? m_inlineTextBox.start() | 1042 : m_inlineTextBox.truncation(), |
| 1055 : m_inlineTextBox.start() + m_inlineTextBox.truncation(), | |
| 1056 ltr == flowIsLTR ? m_inlineTextBox.truncation() | 1043 ltr == flowIsLTR ? m_inlineTextBox.truncation() |
| 1057 : m_inlineTextBox.len() - m_inlineTextBox.truncation(), | 1044 : m_inlineTextBox.len() - m_inlineTextBox.truncation(), |
| 1058 m_inlineTextBox.textPos(), | 1045 m_inlineTextBox.textPos(), |
| 1059 flowIsLTR ? TextDirection::Ltr : TextDirection::Rtl, | 1046 flowIsLTR ? TextDirection::Ltr : TextDirection::Rtl, |
| 1060 m_inlineTextBox.isFirstLineStyle())); | 1047 m_inlineTextBox.isFirstLineStyle())); |
| 1061 if (!flowIsLTR) | 1048 if (!flowIsLTR) |
| 1062 localOrigin.move(m_inlineTextBox.logicalWidth() - width, LayoutUnit()); | 1049 localOrigin.move(m_inlineTextBox.logicalWidth() - width, LayoutUnit()); |
| 1063 } | 1050 } |
| 1064 | 1051 |
| 1065 LayoutObject& textBoxLayoutObject = inlineLayoutObject(); | 1052 LayoutObject& textBoxLayoutObject = inlineLayoutObject(); |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1289 | 1276 |
| 1290 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), | 1277 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), |
| 1291 m_inlineTextBox.logicalHeight())); | 1278 m_inlineTextBox.logicalHeight())); |
| 1292 context.clip(FloatRect(boxRect)); | 1279 context.clip(FloatRect(boxRect)); |
| 1293 context.drawHighlightForText(font, run, FloatPoint(boxOrigin), | 1280 context.drawHighlightForText(font, run, FloatPoint(boxOrigin), |
| 1294 boxRect.height().toInt(), color, | 1281 boxRect.height().toInt(), color, |
| 1295 paintOffsets.first, paintOffsets.second); | 1282 paintOffsets.first, paintOffsets.second); |
| 1296 } | 1283 } |
| 1297 | 1284 |
| 1298 } // namespace blink | 1285 } // namespace blink |
| OLD | NEW |