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 "config.h" | 5 #include "config.h" |
6 #include "core/paint/InlineTextBoxPainter.h" | 6 #include "core/paint/InlineTextBoxPainter.h" |
7 | 7 |
8 #include "core/editing/CompositionUnderline.h" | 8 #include "core/editing/CompositionUnderline.h" |
9 #include "core/editing/Editor.h" | 9 #include "core/editing/Editor.h" |
10 #include "core/editing/markers/DocumentMarkerController.h" | 10 #include "core/editing/markers/DocumentMarkerController.h" |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
149 bool paintSelectedTextSeparately = !paintSelectedTextOnly && textStyle != se lectionStyle; | 149 bool paintSelectedTextSeparately = !paintSelectedTextOnly && textStyle != se lectionStyle; |
150 | 150 |
151 // Set our font. | 151 // Set our font. |
152 const Font& font = styleToUse.font(); | 152 const Font& font = styleToUse.font(); |
153 | 153 |
154 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetrics().asc ent()); | 154 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetrics().asc ent()); |
155 | 155 |
156 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds include selection | 156 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds include selection |
157 // and composition highlights. | 157 // and composition highlights. |
158 if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseT extClip && !isPrinting) { | 158 if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseT extClip && !isPrinting) { |
159 paintDocumentMarkers(context, boxOrigin, styleToUse, font, true); | 159 paintDocumentMarkers(paintInfo, boxOrigin, styleToUse, font, true); |
160 | 160 |
161 if (haveSelection && !paintsCompositionMarkers(textBoxLayoutObject)) { | 161 if (haveSelection && !paintsCompositionMarkers(textBoxLayoutObject)) { |
162 if (combinedText) | 162 if (combinedText) |
163 paintSelection<InlineTextBoxPainter::PaintOptions::CombinedText> (context, boxRect, styleToUse, font, selectionStyle.fillColor, combinedText); | 163 paintSelection<InlineTextBoxPainter::PaintOptions::CombinedText> (context, boxRect, styleToUse, font, selectionStyle.fillColor, combinedText); |
164 else | 164 else |
165 paintSelection<InlineTextBoxPainter::PaintOptions::Normal>(conte xt, boxRect, styleToUse, font, selectionStyle.fillColor); | 165 paintSelection<InlineTextBoxPainter::PaintOptions::Normal>(conte xt, boxRect, styleToUse, font, selectionStyle.fillColor); |
166 } | 166 } |
167 } | 167 } |
168 | 168 |
169 // 2. Now paint the foreground, including text and decorations like underlin e/overline (in quirks mode only). | 169 // 2. Now paint the foreground, including text and decorations like underlin e/overline (in quirks mode only). |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
236 GraphicsContextStateSaver stateSaver(context, false); | 236 GraphicsContextStateSaver stateSaver(context, false); |
237 TextPainter::updateGraphicsContext(context, textStyle, m_inlineTextBox.i sHorizontal(), stateSaver); | 237 TextPainter::updateGraphicsContext(context, textStyle, m_inlineTextBox.i sHorizontal(), stateSaver); |
238 if (combinedText) | 238 if (combinedText) |
239 context.concatCTM(TextPainter::rotation(boxRect, TextPainter::Clockw ise)); | 239 context.concatCTM(TextPainter::rotation(boxRect, TextPainter::Clockw ise)); |
240 paintDecoration(paintInfo, boxOrigin, textDecorations); | 240 paintDecoration(paintInfo, boxOrigin, textDecorations); |
241 if (combinedText) | 241 if (combinedText) |
242 context.concatCTM(TextPainter::rotation(boxRect, TextPainter::Counte rclockwise)); | 242 context.concatCTM(TextPainter::rotation(boxRect, TextPainter::Counte rclockwise)); |
243 } | 243 } |
244 | 244 |
245 if (paintInfo.phase == PaintPhaseForeground) | 245 if (paintInfo.phase == PaintPhaseForeground) |
246 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); | 246 paintDocumentMarkers(paintInfo, boxOrigin, styleToUse, font, false); |
247 | 247 |
248 if (shouldRotate) | 248 if (shouldRotate) |
249 context.concatCTM(TextPainter::rotation(boxRect, TextPainter::Counterclo ckwise)); | 249 context.concatCTM(TextPainter::rotation(boxRect, TextPainter::Counterclo ckwise)); |
250 } | 250 } |
251 | 251 |
252 bool InlineTextBoxPainter::shouldPaintTextBox(const PaintInfo& paintInfo) | 252 bool InlineTextBoxPainter::shouldPaintTextBox(const PaintInfo& paintInfo) |
253 { | 253 { |
254 // When painting selection, we want to include a highlight when the | 254 // When painting selection, we want to include a highlight when the |
255 // selection spans line breaks. In other cases such as invisible elements | 255 // selection spans line breaks. In other cases such as invisible elements |
256 // or those with no text that are not line breaks, we can skip painting | 256 // or those with no text that are not line breaks, we can skip painting |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
291 int ePos = std::min(endPos - static_cast<int>(m_inlineTextBox.start()), stat ic_cast<int>(m_inlineTextBox.len())); | 291 int ePos = std::min(endPos - static_cast<int>(m_inlineTextBox.start()), stat ic_cast<int>(m_inlineTextBox.len())); |
292 if (sPos >= ePos) | 292 if (sPos >= ePos) |
293 return; | 293 return; |
294 | 294 |
295 int deltaY = m_inlineTextBox.lineLayoutItem().style()->isFlippedLinesWriting Mode() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBotto m() : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); | 295 int deltaY = m_inlineTextBox.lineLayoutItem().style()->isFlippedLinesWriting Mode() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBotto m() : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); |
296 int selHeight = m_inlineTextBox.root().selectionHeight(); | 296 int selHeight = m_inlineTextBox.root().selectionHeight(); |
297 FloatPoint localOrigin(boxOrigin.x().toFloat(), boxOrigin.y().toFloat() - de ltaY); | 297 FloatPoint localOrigin(boxOrigin.x().toFloat(), boxOrigin.y().toFloat() - de ltaY); |
298 context.drawHighlightForText(font, m_inlineTextBox.constructTextRun(style, f ont), localOrigin, selHeight, backgroundColor, sPos, ePos); | 298 context.drawHighlightForText(font, m_inlineTextBox.constructTextRun(style, f ont), localOrigin, selHeight, backgroundColor, sPos, ePos); |
299 } | 299 } |
300 | 300 |
301 void InlineTextBoxPainter::paintDocumentMarkers(GraphicsContext& context, const LayoutPoint& boxOrigin, const ComputedStyle& style, const Font& font, bool backg round) | 301 void InlineTextBoxPainter::paintDocumentMarkers(const PaintInfo& paintInfo, cons t LayoutPoint& boxOrigin, const ComputedStyle& style, const Font& font, bool bac kground) |
302 { | 302 { |
303 if (!m_inlineTextBox.lineLayoutItem().node()) | 303 if (!m_inlineTextBox.lineLayoutItem().node()) |
304 return; | 304 return; |
305 | 305 |
306 DocumentMarkerVector markers = m_inlineTextBox.lineLayoutItem().document().m arkers().markersFor(m_inlineTextBox.lineLayoutItem().node()); | 306 DocumentMarkerVector markers = m_inlineTextBox.lineLayoutItem().document().m arkers().markersFor(m_inlineTextBox.lineLayoutItem().node()); |
307 DocumentMarkerVector::const_iterator markerIt = markers.begin(); | 307 DocumentMarkerVector::const_iterator markerIt = markers.begin(); |
308 | 308 |
309 // Give any document markers that touch this run a chance to draw before the text has been drawn. | 309 // Give any document markers that touch this run a chance to draw before the text has been drawn. |
310 // Note end() points at the last char, not one past it like endOffset and ra nges do. | 310 // Note end() points at the last char, not one past it like endOffset and ra nges do. |
311 for ( ; markerIt != markers.end(); ++markerIt) { | 311 for ( ; markerIt != markers.end(); ++markerIt) { |
312 DocumentMarker* marker = *markerIt; | 312 DocumentMarker* marker = *markerIt; |
313 | 313 |
314 // Paint either the background markers or the foreground markers, but no t both | 314 // Paint either the background markers or the foreground markers, but no t both |
315 switch (marker->type()) { | 315 switch (marker->type()) { |
316 case DocumentMarker::Grammar: | 316 case DocumentMarker::Grammar: |
317 case DocumentMarker::Spelling: | 317 case DocumentMarker::Spelling: |
318 if (background) | 318 if (background) |
319 continue; | 319 continue; |
320 break; | 320 break; |
321 case DocumentMarker::TextMatch: | 321 case DocumentMarker::TextMatch: |
322 if (!background) | |
323 continue; | |
324 break; | 322 break; |
fs
2015/12/17 10:10:54
Nit: Maybe drop this too now that TextMatch is in
ramya.v
2015/12/18 03:43:32
Done.
| |
325 case DocumentMarker::Composition: | 323 case DocumentMarker::Composition: |
326 break; | 324 break; |
327 default: | 325 default: |
328 continue; | 326 continue; |
329 } | 327 } |
330 | 328 |
331 if (marker->endOffset() <= m_inlineTextBox.start()) { | 329 if (marker->endOffset() <= m_inlineTextBox.start()) { |
332 // marker is completely before this run. This might be a marker tha t sits before the | 330 // marker is completely before this run. This might be a marker tha t sits before the |
333 // first run we draw, or markers that were within runs we skipped du e to truncation. | 331 // first run we draw, or markers that were within runs we skipped du e to truncation. |
334 continue; | 332 continue; |
335 } | 333 } |
336 if (marker->startOffset() > m_inlineTextBox.end()) { | 334 if (marker->startOffset() > m_inlineTextBox.end()) { |
337 // marker is completely after this run, bail. A later run will pain t it. | 335 // marker is completely after this run, bail. A later run will pain t it. |
338 break; | 336 break; |
339 } | 337 } |
340 | 338 |
341 // marker intersects this run. Paint it. | 339 // marker intersects this run. Paint it. |
342 switch (marker->type()) { | 340 switch (marker->type()) { |
343 case DocumentMarker::Spelling: | 341 case DocumentMarker::Spelling: |
344 m_inlineTextBox.paintDocumentMarker(context, boxOrigin, marker, styl e, font, false); | 342 m_inlineTextBox.paintDocumentMarker(paintInfo.context, boxOrigin, ma rker, style, font, false); |
345 break; | 343 break; |
346 case DocumentMarker::Grammar: | 344 case DocumentMarker::Grammar: |
347 m_inlineTextBox.paintDocumentMarker(context, boxOrigin, marker, styl e, font, true); | 345 m_inlineTextBox.paintDocumentMarker(paintInfo.context, boxOrigin, ma rker, style, font, true); |
348 break; | 346 break; |
349 case DocumentMarker::TextMatch: | 347 case DocumentMarker::TextMatch: |
350 m_inlineTextBox.paintTextMatchMarker(context, boxOrigin, marker, sty le, font); | 348 if (background) |
349 m_inlineTextBox.paintTextMatchMarkerBackground(paintInfo, boxOri gin, marker, style, font); | |
350 else | |
351 m_inlineTextBox.paintTextMatchMarkerForeground(paintInfo, boxOri gin, marker, style, font); | |
351 break; | 352 break; |
352 case DocumentMarker::Composition: | 353 case DocumentMarker::Composition: |
353 { | 354 { |
354 CompositionUnderline underline(marker->startOffset(), marker->en dOffset(), marker->underlineColor(), marker->thick(), marker->backgroundColor()) ; | 355 CompositionUnderline underline(marker->startOffset(), marker->en dOffset(), marker->underlineColor(), marker->thick(), marker->backgroundColor()) ; |
355 if (background) | 356 if (background) |
356 paintSingleCompositionBackgroundRun(context, boxOrigin, styl e, font, underline.backgroundColor, underlinePaintStart(underline), underlinePai ntEnd(underline)); | 357 paintSingleCompositionBackgroundRun(paintInfo.context, boxOr igin, style, font, underline.backgroundColor, underlinePaintStart(underline), un derlinePaintEnd(underline)); |
357 else | 358 else |
358 paintCompositionUnderline(context, boxOrigin, underline); | 359 paintCompositionUnderline(paintInfo.context, boxOrigin, unde rline); |
359 } | 360 } |
360 break; | 361 break; |
361 default: | 362 default: |
362 ASSERT_NOT_REACHED(); | 363 ASSERT_NOT_REACHED(); |
363 } | 364 } |
364 } | 365 } |
365 } | 366 } |
366 | 367 |
367 static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(DocumentM arker::MarkerType markerType) | 368 static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(DocumentM arker::MarkerType markerType) |
368 { | 369 { |
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
823 // We need to have some space between underlines of subsequent clauses, beca use some input methods do not use different underline styles for those. | 824 // We need to have some space between underlines of subsequent clauses, beca use some input methods do not use different underline styles for those. |
824 // We make each line shorter, which has a harmless side effect of shortening the first and last clauses, too. | 825 // We make each line shorter, which has a harmless side effect of shortening the first and last clauses, too. |
825 start += 1; | 826 start += 1; |
826 width -= 2; | 827 width -= 2; |
827 | 828 |
828 context.setStrokeColor(underline.color); | 829 context.setStrokeColor(underline.color); |
829 context.setStrokeThickness(lineThickness); | 830 context.setStrokeThickness(lineThickness); |
830 context.drawLineForText(FloatPoint(boxOrigin.x() + start, (boxOrigin.y() + m _inlineTextBox.logicalHeight() - lineThickness).toFloat()), width, m_inlineTextB ox.lineLayoutItem().document().printing()); | 831 context.drawLineForText(FloatPoint(boxOrigin.x() + start, (boxOrigin.y() + m _inlineTextBox.logicalHeight() - lineThickness).toFloat()), width, m_inlineTextB ox.lineLayoutItem().document().printing()); |
831 } | 832 } |
832 | 833 |
833 void InlineTextBoxPainter::paintTextMatchMarker(GraphicsContext& context, const LayoutPoint& boxOrigin, DocumentMarker* marker, const ComputedStyle& style, cons t Font& font) | 834 void InlineTextBoxPainter::paintTextMatchMarkerForeground(const PaintInfo& paint Info, const LayoutPoint& boxOrigin, DocumentMarker* marker, const ComputedStyle& style, const Font& font) |
834 { | 835 { |
836 if (!LineLayoutPaintShim::layoutObjectFrom(m_inlineTextBox.lineLayoutItem()) ->frame()->editor().markedTextMatchesAreHighlighted()) | |
837 return; | |
838 | |
839 // TODO(ramya.v): Extract this into a helper function and share many copies of this code. | |
840 int sPos = std::max(marker->startOffset() - m_inlineTextBox.start(), (unsign ed)0); | |
841 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(), m_inlineT extBox.len()); | |
842 TextRun run = m_inlineTextBox.constructTextRun(style, font); | |
843 | |
844 Color textColor = marker->activeMatch() ? | |
fs
2015/12/17 10:10:54
Could just pass the predicate as the argument inst
ramya.v
2015/12/18 03:43:32
Done.
| |
845 LayoutTheme::theme().platformTextSearchColor(true) : | |
846 LayoutTheme::theme().platformTextSearchColor(false); | |
847 if (style.visitedDependentColor(CSSPropertyColor) == textColor) | |
848 return; | |
849 TextPainter::Style textStyle; | |
850 // When we use the text as a clip, we only care about the alpha, thus we mak e all the colors black. | |
fs
2015/12/17 10:10:54
This comment doesn't appear to make much sense in
ramya.v
2015/12/18 03:43:32
Done.
| |
851 textStyle.currentColor = textStyle.fillColor = textStyle.strokeColor = textS tyle.emphasisMarkColor = textColor; | |
852 textStyle.strokeWidth = style.textStrokeWidth(); | |
853 textStyle.shadow = 0; | |
854 | |
855 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidth(), m_i nlineTextBox.logicalHeight())); | |
856 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetrics().asc ent()); | |
857 TextPainter textPainter(paintInfo.context, font, run, textOrigin, boxRect, m _inlineTextBox.isHorizontal()); | |
858 | |
859 textPainter.paint(sPos, ePos, m_inlineTextBox.len(), textStyle, 0); | |
860 } | |
861 | |
862 void InlineTextBoxPainter::paintTextMatchMarkerBackground(const PaintInfo& paint Info, const LayoutPoint& boxOrigin, DocumentMarker* marker, const ComputedStyle& style, const Font& font) | |
863 { | |
864 if (!LineLayoutPaintShim::layoutObjectFrom(m_inlineTextBox.lineLayoutItem()) ->frame()->editor().markedTextMatchesAreHighlighted()) | |
865 return; | |
866 | |
835 // Use same y positioning and height as for selection, so that when the sele ction and this highlight are on | 867 // Use same y positioning and height as for selection, so that when the sele ction and this highlight are on |
836 // the same word there are no pieces sticking out. | 868 // the same word there are no pieces sticking out. |
837 int deltaY = m_inlineTextBox.lineLayoutItem().style()->isFlippedLinesWriting Mode() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBotto m() : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); | 869 int deltaY = m_inlineTextBox.lineLayoutItem().style()->isFlippedLinesWriting Mode() ? m_inlineTextBox.root().selectionBottom() - m_inlineTextBox.logicalBotto m() : m_inlineTextBox.logicalTop() - m_inlineTextBox.root().selectionTop(); |
838 int selHeight = m_inlineTextBox.root().selectionHeight(); | 870 int selHeight = m_inlineTextBox.root().selectionHeight(); |
839 | 871 |
840 int sPos = std::max(marker->startOffset() - m_inlineTextBox.start(), (unsign ed)0); | 872 int sPos = std::max(marker->startOffset() - m_inlineTextBox.start(), (unsign ed)0); |
841 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(), m_inlineT extBox.len()); | 873 int ePos = std::min(marker->endOffset() - m_inlineTextBox.start(), m_inlineT extBox.len()); |
842 TextRun run = m_inlineTextBox.constructTextRun(style, font); | 874 TextRun run = m_inlineTextBox.constructTextRun(style, font); |
843 | 875 |
844 // Optionally highlight the text | 876 Color color = marker->activeMatch() ? |
fs
2015/12/17 10:10:54
Same suggestion as for the equivalent code above (
ramya.v
2015/12/18 03:43:32
Done.
| |
845 if (LineLayoutPaintShim::layoutObjectFrom(m_inlineTextBox.lineLayoutItem())- >frame()->editor().markedTextMatchesAreHighlighted()) { | 877 LayoutTheme::theme().platformTextSearchHighlightColor(true) : |
846 Color color = marker->activeMatch() ? | 878 LayoutTheme::theme().platformTextSearchHighlightColor(false); |
847 LayoutTheme::theme().platformActiveTextSearchHighlightColor() : | 879 GraphicsContext& pt = paintInfo.context; |
fs
2015/12/17 10:10:54
pt -> context
ramya.v
2015/12/18 03:43:32
Done.
| |
848 LayoutTheme::theme().platformInactiveTextSearchHighlightColor(); | 880 GraphicsContextStateSaver stateSaver(pt); |
849 GraphicsContextStateSaver stateSaver(context); | 881 pt.clip(FloatRect(boxOrigin.x().toFloat(), (boxOrigin.y() - deltaY).toFloat( ), m_inlineTextBox.logicalWidth().toFloat(), selHeight)); |
850 context.clip(FloatRect(boxOrigin.x().toFloat(), (boxOrigin.y() - deltaY) .toFloat(), m_inlineTextBox.logicalWidth().toFloat(), selHeight)); | 882 pt.drawHighlightForText(font, run, FloatPoint(boxOrigin.x().toFloat(), (boxO rigin.y() - deltaY).toFloat()), selHeight, color, sPos, ePos); |
851 context.drawHighlightForText(font, run, FloatPoint(boxOrigin.x().toFloat (), (boxOrigin.y() - deltaY).toFloat()), selHeight, color, sPos, ePos); | |
852 | |
853 // Also Highlight the text with color:transparent | |
854 if (style.visitedDependentColor(CSSPropertyColor) == Color::transparent) { | |
855 int length = m_inlineTextBox.len(); | |
856 TextPainter::Style textStyle; | |
857 // When we use the text as a clip, we only care about the alpha, thu s we make all the colors black. | |
858 textStyle.currentColor = textStyle.fillColor = textStyle.strokeColor = textStyle.emphasisMarkColor = Color::black; | |
859 textStyle.strokeWidth = style.textStrokeWidth(); | |
860 textStyle.shadow = 0; | |
861 | |
862 LayoutRect boxRect(boxOrigin, LayoutSize(m_inlineTextBox.logicalWidt h(), m_inlineTextBox.logicalHeight())); | |
863 LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetri cs().ascent()); | |
864 TextPainter textPainter(context, font, run, textOrigin, boxRect, m_i nlineTextBox.isHorizontal()); | |
865 | |
866 textPainter.paint(sPos, ePos, length, textStyle, 0); | |
867 } | |
868 } | |
869 } | 883 } |
870 | 884 |
871 | 885 |
872 } // namespace blink | 886 } // namespace blink |
OLD | NEW |