| 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 18 matching lines...) Expand all Loading... |
| 29 const InlineTextBox& textBox) { | 29 const InlineTextBox& textBox) { |
| 30 const unsigned startOffset = marker.startOffset() > textBox.start() | 30 const unsigned startOffset = marker.startOffset() > textBox.start() |
| 31 ? marker.startOffset() - textBox.start() | 31 ? marker.startOffset() - textBox.start() |
| 32 : 0U; | 32 : 0U; |
| 33 const unsigned endOffset = | 33 const unsigned endOffset = |
| 34 std::min(marker.endOffset() - textBox.start(), textBox.len()); | 34 std::min(marker.endOffset() - textBox.start(), textBox.len()); |
| 35 return std::make_pair(startOffset, endOffset); | 35 return std::make_pair(startOffset, endOffset); |
| 36 } | 36 } |
| 37 } | 37 } |
| 38 | 38 |
| 39 static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition, | 39 static LineLayoutItem enclosingUnderlineObject( |
| 40 const InlineTextBox* inlineTextBox) { |
| 41 bool firstLine = inlineTextBox->isFirstLineStyle(); |
| 42 for (LineLayoutItem current = inlineTextBox->parent()->getLineLayoutItem(); |
| 43 ;) { |
| 44 if (current.isLayoutBlock()) |
| 45 return current; |
| 46 if (!current.isLayoutInline() || current.isRubyText()) |
| 47 return nullptr; |
| 48 |
| 49 const ComputedStyle& styleToUse = current.styleRef(firstLine); |
| 50 if (styleToUse.getTextDecoration() & TextDecorationUnderline) |
| 51 return current; |
| 52 |
| 53 current = current.parent(); |
| 54 if (!current) |
| 55 return current; |
| 56 |
| 57 if (Node* node = current.node()) { |
| 58 if (isHTMLAnchorElement(node) || node->hasTagName(HTMLNames::fontTag)) |
| 59 return current; |
| 60 } |
| 61 } |
| 62 } |
| 63 |
| 64 static LayoutUnit computeUnderlineOffsetForUnder( |
| 65 const ComputedStyle& style, |
| 66 const InlineTextBox* inlineTextBox) { |
| 67 const RootInlineBox& root = inlineTextBox->root(); |
| 68 LineLayoutItem decorationObject = enclosingUnderlineObject(inlineTextBox); |
| 69 if (style.isFlippedLinesWritingMode()) { |
| 70 LayoutUnit position = inlineTextBox->logicalTop(); |
| 71 return position - |
| 72 root.minLogicalTopForUnderline(decorationObject, position); |
| 73 } else { |
| 74 LayoutUnit position = inlineTextBox->logicalBottom(); |
| 75 return root.maxLogicalBottomForUnderline(decorationObject, position) - |
| 76 position; |
| 77 } |
| 78 } |
| 79 |
| 80 static int computeUnderlineOffset(const ComputedStyle& style, |
| 40 const FontMetrics& fontMetrics, | 81 const FontMetrics& fontMetrics, |
| 41 const InlineTextBox* inlineTextBox, | 82 const InlineTextBox* inlineTextBox, |
| 42 const float textDecorationThickness) { | 83 const float textDecorationThickness) { |
| 43 // Compute the gap between the font and the underline. Use at least one | 84 // Compute the gap between the font and the underline. Use at least one |
| 44 // pixel gap, if underline is thick then use a bigger gap. | 85 // pixel gap, if underline is thick then use a bigger gap. |
| 45 int gap = 0; | 86 int gap = 0; |
| 46 | 87 |
| 47 // Underline position of zero means draw underline on Baseline Position, | 88 // Underline position of zero means draw underline on Baseline Position, |
| 48 // in Blink we need at least 1-pixel gap to adding following check. | 89 // in Blink we need at least 1-pixel gap to adding following check. |
| 49 // Positive underline Position means underline should be drawn above baselin e | 90 // Positive underline Position means underline should be drawn above baselin e |
| 50 // and negative value means drawing below baseline, negating the value as in | 91 // and negative value means drawing below baseline, negating the value as in |
| 51 // Blink | 92 // Blink |
| 52 // downward Y-increases. | 93 // downward Y-increases. |
| 53 | 94 |
| 54 if (fontMetrics.underlinePosition()) | 95 if (fontMetrics.underlinePosition()) |
| 55 gap = -fontMetrics.underlinePosition(); | 96 gap = -fontMetrics.underlinePosition(); |
| 56 else | 97 else |
| 57 gap = std::max<int>(1, ceilf(textDecorationThickness / 2.f)); | 98 gap = std::max<int>(1, ceilf(textDecorationThickness / 2.f)); |
| 58 | 99 |
| 59 // FIXME: We support only horizontal text for now. | 100 // FIXME: We support only horizontal text for now. |
| 60 switch (underlinePosition) { | 101 switch (style.getTextUnderlinePosition()) { |
| 61 case TextUnderlinePositionAuto: | 102 case TextUnderlinePositionAuto: |
| 62 return fontMetrics.ascent() + | 103 return fontMetrics.ascent() + |
| 63 gap; // Position underline near the alphabetic baseline. | 104 gap; // Position underline near the alphabetic baseline. |
| 64 case TextUnderlinePositionUnder: { | 105 case TextUnderlinePositionUnder: { |
| 65 // Position underline relative to the under edge of the lowest element's | 106 // Position underline relative to the under edge of the lowest element's |
| 66 // content box. | 107 // content box. |
| 67 const LayoutUnit offset = | 108 LayoutUnit offset = computeUnderlineOffsetForUnder(style, inlineTextBox); |
| 68 inlineTextBox->root().maxLogicalTop() - inlineTextBox->logicalTop(); | 109 offset = inlineTextBox->logicalHeight() + std::max(offset, LayoutUnit()); |
| 69 if (offset > 0) | 110 return offset.toInt() + gap; |
| 70 return (inlineTextBox->logicalHeight() + gap + offset).toInt(); | |
| 71 return (inlineTextBox->logicalHeight() + gap).toInt(); | |
| 72 } | 111 } |
| 73 } | 112 } |
| 74 | 113 |
| 75 NOTREACHED(); | 114 NOTREACHED(); |
| 76 return fontMetrics.ascent() + gap; | 115 return fontMetrics.ascent() + gap; |
| 77 } | 116 } |
| 78 | 117 |
| 79 static bool shouldSetDecorationAntialias( | 118 static bool shouldSetDecorationAntialias( |
| 80 const Vector<AppliedTextDecoration>& decorations) { | 119 const Vector<AppliedTextDecoration>& decorations) { |
| 81 for (const AppliedTextDecoration& decoration : decorations) { | 120 for (const AppliedTextDecoration& decoration : decorations) { |
| (...skipping 1010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1092 bool antialiasDecoration = shouldSetDecorationAntialias(decorations); | 1131 bool antialiasDecoration = shouldSetDecorationAntialias(decorations); |
| 1093 | 1132 |
| 1094 // Offset between lines - always non-zero, so lines never cross each other. | 1133 // Offset between lines - always non-zero, so lines never cross each other. |
| 1095 float doubleOffset = textDecorationThickness + 1.f; | 1134 float doubleOffset = textDecorationThickness + 1.f; |
| 1096 bool skipIntercepts = | 1135 bool skipIntercepts = |
| 1097 styleToUse.getTextDecorationSkip() & TextDecorationSkipInk; | 1136 styleToUse.getTextDecorationSkip() & TextDecorationSkipInk; |
| 1098 | 1137 |
| 1099 for (const AppliedTextDecoration& decoration : decorations) { | 1138 for (const AppliedTextDecoration& decoration : decorations) { |
| 1100 TextDecoration lines = decoration.lines(); | 1139 TextDecoration lines = decoration.lines(); |
| 1101 if ((lines & TextDecorationUnderline) && fontData) { | 1140 if ((lines & TextDecorationUnderline) && fontData) { |
| 1102 const int underlineOffset = computeUnderlineOffset( | 1141 const int underlineOffset = |
| 1103 styleToUse.getTextUnderlinePosition(), fontData->getFontMetrics(), | 1142 computeUnderlineOffset(styleToUse, fontData->getFontMetrics(), |
| 1104 &m_inlineTextBox, textDecorationThickness); | 1143 &m_inlineTextBox, textDecorationThickness); |
| 1105 AppliedDecorationPainter decorationPainter( | 1144 AppliedDecorationPainter decorationPainter( |
| 1106 context, FloatPoint(localOrigin) + FloatPoint(0, underlineOffset), | 1145 context, FloatPoint(localOrigin) + FloatPoint(0, underlineOffset), |
| 1107 width.toFloat(), decoration, textDecorationThickness, doubleOffset, 1, | 1146 width.toFloat(), decoration, textDecorationThickness, doubleOffset, 1, |
| 1108 antialiasDecoration); | 1147 antialiasDecoration); |
| 1109 if (skipIntercepts) { | 1148 if (skipIntercepts) { |
| 1110 textPainter.clipDecorationsStripe( | 1149 textPainter.clipDecorationsStripe( |
| 1111 -baseline + decorationPainter.decorationBounds().y() - | 1150 -baseline + decorationPainter.decorationBounds().y() - |
| 1112 FloatPoint(localOrigin).y(), | 1151 FloatPoint(localOrigin).y(), |
| 1113 decorationPainter.decorationBounds().height(), | 1152 decorationPainter.decorationBounds().height(), |
| 1114 textDecorationThickness); | 1153 textDecorationThickness); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1284 | 1323 |
| 1285 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), | 1324 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), |
| 1286 m_inlineTextBox.logicalHeight())); | 1325 m_inlineTextBox.logicalHeight())); |
| 1287 context.clip(FloatRect(boxRect)); | 1326 context.clip(FloatRect(boxRect)); |
| 1288 context.drawHighlightForText(font, run, FloatPoint(boxOrigin), | 1327 context.drawHighlightForText(font, run, FloatPoint(boxOrigin), |
| 1289 boxRect.height().toInt(), color, | 1328 boxRect.height().toInt(), color, |
| 1290 paintOffsets.first, paintOffsets.second); | 1329 paintOffsets.first, paintOffsets.second); |
| 1291 } | 1330 } |
| 1292 | 1331 |
| 1293 } // namespace blink | 1332 } // namespace blink |
| OLD | NEW |