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/SVGInlineTextBoxPainter.h" | 6 #include "core/paint/SVGInlineTextBoxPainter.h" |
7 | 7 |
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/editing/markers/RenderedDocumentMarker.h" | 10 #include "core/editing/markers/RenderedDocumentMarker.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 return; | 58 return; |
59 | 59 |
60 DisplayItem::Type displayItemType = DisplayItem::paintPhaseToDrawingType(pai
ntInfo.phase); | 60 DisplayItem::Type displayItemType = DisplayItem::paintPhaseToDrawingType(pai
ntInfo.phase); |
61 if (!DrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_svgInl
ineTextBox, displayItemType)) { | 61 if (!DrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_svgInl
ineTextBox, displayItemType)) { |
62 LayoutObject& parentLayoutObject = *LineLayoutPaintShim::layoutObjectFro
m(m_svgInlineTextBox.parent()->lineLayoutItem()); | 62 LayoutObject& parentLayoutObject = *LineLayoutPaintShim::layoutObjectFro
m(m_svgInlineTextBox.parent()->lineLayoutItem()); |
63 const ComputedStyle& style = parentLayoutObject.styleRef(); | 63 const ComputedStyle& style = parentLayoutObject.styleRef(); |
64 | 64 |
65 // TODO(chrishtr): passing the cull rect is incorrect. | 65 // TODO(chrishtr): passing the cull rect is incorrect. |
66 DrawingRecorder recorder(paintInfo.context, m_svgInlineTextBox, displayI
temType, FloatRect(paintInfo.cullRect().m_rect)); | 66 DrawingRecorder recorder(paintInfo.context, m_svgInlineTextBox, displayI
temType, FloatRect(paintInfo.cullRect().m_rect)); |
67 InlineTextBoxPainter(m_svgInlineTextBox).paintDocumentMarkers( | 67 InlineTextBoxPainter(m_svgInlineTextBox).paintDocumentMarkers( |
68 paintInfo.context, paintOffset, style, | 68 paintInfo, paintOffset, style, |
69 textLayoutObject.scaledFont(), true); | 69 textLayoutObject.scaledFont(), DocumentMarkerPaintPhase::Background)
; |
70 | 70 |
71 if (!m_svgInlineTextBox.textFragments().isEmpty()) | 71 if (!m_svgInlineTextBox.textFragments().isEmpty()) |
72 paintTextFragments(paintInfo, parentLayoutObject); | 72 paintTextFragments(paintInfo, parentLayoutObject); |
| 73 |
| 74 InlineTextBoxPainter(m_svgInlineTextBox).paintDocumentMarkers( |
| 75 paintInfo, paintOffset, style, |
| 76 textLayoutObject.scaledFont(), DocumentMarkerPaintPhase::Foreground)
; |
73 } | 77 } |
74 } | 78 } |
75 | 79 |
76 void SVGInlineTextBoxPainter::paintTextFragments(const PaintInfo& paintInfo, Lay
outObject& parentLayoutObject) | 80 void SVGInlineTextBoxPainter::paintTextFragments(const PaintInfo& paintInfo, Lay
outObject& parentLayoutObject) |
77 { | 81 { |
78 const ComputedStyle& style = parentLayoutObject.styleRef(); | 82 const ComputedStyle& style = parentLayoutObject.styleRef(); |
79 const SVGComputedStyle& svgStyle = style.svgStyle(); | 83 const SVGComputedStyle& svgStyle = style.svgStyle(); |
80 | 84 |
81 bool hasFill = svgStyle.hasFill(); | 85 bool hasFill = svgStyle.hasFill(); |
82 bool hasVisibleStroke = svgStyle.hasVisibleStroke(); | 86 bool hasVisibleStroke = svgStyle.hasVisibleStroke(); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 | 166 |
163 LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(*LineLayoutPai
ntShim::layoutObjectFrom(m_svgInlineTextBox.lineLayoutItem())); | 167 LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(*LineLayoutPai
ntShim::layoutObjectFrom(m_svgInlineTextBox.lineLayoutItem())); |
164 if (!textShouldBePainted(textLayoutObject)) | 168 if (!textShouldBePainted(textLayoutObject)) |
165 return; | 169 return; |
166 | 170 |
167 const ComputedStyle& style = m_svgInlineTextBox.parent()->lineLayoutItem().s
tyleRef(); | 171 const ComputedStyle& style = m_svgInlineTextBox.parent()->lineLayoutItem().s
tyleRef(); |
168 | 172 |
169 int startPosition, endPosition; | 173 int startPosition, endPosition; |
170 m_svgInlineTextBox.selectionStartEnd(startPosition, endPosition); | 174 m_svgInlineTextBox.selectionStartEnd(startPosition, endPosition); |
171 | 175 |
172 int fragmentStartPosition = 0; | |
173 int fragmentEndPosition = 0; | |
174 AffineTransform fragmentTransform; | 176 AffineTransform fragmentTransform; |
175 unsigned textFragmentsSize = m_svgInlineTextBox.textFragments().size(); | 177 const Vector<SVGTextFragmentWithRange> fragmentInfoList = collectFragmentsIn
Range(startPosition, endPosition); |
176 for (unsigned i = 0; i < textFragmentsSize; ++i) { | 178 for (const SVGTextFragmentWithRange& fragmentWithRange : fragmentInfoList) { |
177 const SVGTextFragment& fragment = m_svgInlineTextBox.textFragments().at(
i); | 179 const SVGTextFragment& fragment = fragmentWithRange.fragment; |
178 | |
179 fragmentStartPosition = startPosition; | |
180 fragmentEndPosition = endPosition; | |
181 if (!m_svgInlineTextBox.mapStartEndPositionsIntoFragmentCoordinates(frag
ment, fragmentStartPosition, fragmentEndPosition)) | |
182 continue; | |
183 | |
184 GraphicsContextStateSaver stateSaver(paintInfo.context); | 180 GraphicsContextStateSaver stateSaver(paintInfo.context); |
185 fragment.buildFragmentTransform(fragmentTransform); | 181 fragment.buildFragmentTransform(fragmentTransform); |
186 if (!fragmentTransform.isIdentity()) | 182 if (!fragmentTransform.isIdentity()) |
187 paintInfo.context.concatCTM(fragmentTransform); | 183 paintInfo.context.concatCTM(fragmentTransform); |
188 | 184 |
189 paintInfo.context.setFillColor(backgroundColor); | 185 paintInfo.context.setFillColor(backgroundColor); |
190 paintInfo.context.fillRect(m_svgInlineTextBox.selectionRectForTextFragme
nt(fragment, fragmentStartPosition, fragmentEndPosition, style), backgroundColor
); | 186 paintInfo.context.fillRect(m_svgInlineTextBox.selectionRectForTextFragme
nt(fragment, fragmentWithRange.startPosition, fragmentWithRange.endPosition, sty
le), backgroundColor); |
191 } | 187 } |
192 } | 188 } |
193 | 189 |
194 static inline LayoutObject* findLayoutObjectDefininingTextDecoration(InlineFlowB
ox* parentBox) | 190 static inline LayoutObject* findLayoutObjectDefininingTextDecoration(InlineFlowB
ox* parentBox) |
195 { | 191 { |
196 // Lookup first layout object in parent hierarchy which has text-decoration
set. | 192 // Lookup first layout object in parent hierarchy which has text-decoration
set. |
197 LayoutObject* layoutObject = 0; | 193 LayoutObject* layoutObject = 0; |
198 while (parentBox) { | 194 while (parentBox) { |
199 layoutObject = LineLayoutPaintShim::layoutObjectFrom(parentBox->lineLayo
utItem()); | 195 layoutObject = LineLayoutPaintShim::layoutObjectFrom(parentBox->lineLayo
utItem()); |
200 | 196 |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 } | 411 } |
416 | 412 |
417 // Eventually draw text using regular style from the end position of the sel
ection to the end of the current chunk part | 413 // Eventually draw text using regular style from the end position of the sel
ection to the end of the current chunk part |
418 if (endPosition < static_cast<int>(fragment.length) && !paintSelectedTextOnl
y) { | 414 if (endPosition < static_cast<int>(fragment.length) && !paintSelectedTextOnl
y) { |
419 SkPaint paint; | 415 SkPaint paint; |
420 if (setupTextPaint(paintInfo, style, resourceMode, paint)) | 416 if (setupTextPaint(paintInfo, style, resourceMode, paint)) |
421 paintText(paintInfo, textRun, fragment, endPosition, fragment.length
, paint); | 417 paintText(paintInfo, textRun, fragment, endPosition, fragment.length
, paint); |
422 } | 418 } |
423 } | 419 } |
424 | 420 |
425 void SVGInlineTextBoxPainter::paintTextMatchMarker(GraphicsContext& context, con
st LayoutPoint&, DocumentMarker* marker, const ComputedStyle& style, const Font&
font) | 421 Vector<SVGTextFragmentWithRange> SVGInlineTextBoxPainter::collectTextMatches(Doc
umentMarker* marker) const |
426 { | 422 { |
427 // SVG is only interested in the TextMatch markers. | 423 const Vector<SVGTextFragmentWithRange> emptyTextMatchList; |
| 424 |
| 425 // SVG does not support grammar or spellcheck markers, so skip anything but
TextMatch. |
428 if (marker->type() != DocumentMarker::TextMatch) | 426 if (marker->type() != DocumentMarker::TextMatch) |
| 427 return emptyTextMatchList; |
| 428 |
| 429 if (!LineLayoutPaintShim::layoutObjectFrom(m_svgInlineTextBox.lineLayoutItem
())->frame()->editor().markedTextMatchesAreHighlighted()) |
| 430 return emptyTextMatchList; |
| 431 |
| 432 int markerStartPosition = std::max<int>(marker->startOffset() - m_svgInlineT
extBox.start(), 0); |
| 433 int markerEndPosition = std::min<int>(marker->endOffset() - m_svgInlineTextB
ox.start(), m_svgInlineTextBox.len()); |
| 434 |
| 435 if (markerStartPosition >= markerEndPosition) |
| 436 return emptyTextMatchList; |
| 437 |
| 438 return collectFragmentsInRange(markerStartPosition, markerEndPosition); |
| 439 } |
| 440 |
| 441 Vector<SVGTextFragmentWithRange> SVGInlineTextBoxPainter::collectFragmentsInRang
e(int startPosition, int endPosition) const |
| 442 { |
| 443 Vector<SVGTextFragmentWithRange> fragmentInfoList; |
| 444 const Vector<SVGTextFragment>& fragments = m_svgInlineTextBox.textFragments(
); |
| 445 for (const SVGTextFragment& fragment : fragments) { |
| 446 // TODO(ramya.v): If these can't be negative we should use unsigned. |
| 447 int fragmentStartPosition = startPosition; |
| 448 int fragmentEndPosition = endPosition; |
| 449 if (!m_svgInlineTextBox.mapStartEndPositionsIntoFragmentCoordinates(frag
ment, fragmentStartPosition, fragmentEndPosition)) |
| 450 continue; |
| 451 |
| 452 fragmentInfoList.append(SVGTextFragmentWithRange(fragment, fragmentStart
Position, fragmentEndPosition)); |
| 453 } |
| 454 return fragmentInfoList; |
| 455 } |
| 456 |
| 457 void SVGInlineTextBoxPainter::paintTextMatchMarkerForeground(const PaintInfo& pa
intInfo, const LayoutPoint& point, DocumentMarker* marker, const ComputedStyle&
style, const Font& font) |
| 458 { |
| 459 const Vector<SVGTextFragmentWithRange> textMatchInfoList = collectTextMatche
s(marker); |
| 460 if (textMatchInfoList.isEmpty()) |
429 return; | 461 return; |
430 | 462 |
431 LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(*LineLayoutPai
ntShim::layoutObjectFrom(m_svgInlineTextBox.lineLayoutItem())); | 463 Color textColor = LayoutTheme::theme().platformTextSearchColor(marker->activ
eMatch()); |
| 464 |
| 465 SkPaint fillPaint; |
| 466 fillPaint.setColor(textColor.rgb()); |
| 467 fillPaint.setAntiAlias(true); |
| 468 |
| 469 SkPaint strokePaint; |
| 470 bool shouldPaintStroke = false; |
| 471 if (setupTextPaint(paintInfo, style, ApplyToStrokeMode, strokePaint)) { |
| 472 shouldPaintStroke = true; |
| 473 strokePaint.setLooper(nullptr); |
| 474 strokePaint.setColor(textColor.rgb()); |
| 475 } |
432 | 476 |
433 AffineTransform fragmentTransform; | 477 AffineTransform fragmentTransform; |
434 for (InlineTextBox* box = textLayoutObject.firstTextBox(); box; box = box->n
extTextBox()) { | 478 for (const SVGTextFragmentWithRange& textMatchInfo : textMatchInfoList) { |
435 if (!box->isSVGInlineTextBox()) | 479 const SVGTextFragment& fragment = textMatchInfo.fragment; |
436 continue; | 480 GraphicsContextStateSaver stateSaver(paintInfo.context); |
| 481 fragment.buildFragmentTransform(fragmentTransform); |
| 482 if (!fragmentTransform.isIdentity()) |
| 483 paintInfo.context.concatCTM(fragmentTransform); |
437 | 484 |
438 SVGInlineTextBox* textBox = toSVGInlineTextBox(box); | 485 TextRun textRun = m_svgInlineTextBox.constructTextRun(style, fragment); |
439 | 486 paintText(paintInfo, textRun, fragment, textMatchInfo.startPosition, tex
tMatchInfo.endPosition, fillPaint); |
440 int markerStartPosition = std::max<int>(marker->startOffset() - textBox-
>start(), 0); | 487 if (shouldPaintStroke) |
441 int markerEndPosition = std::min<int>(marker->endOffset() - textBox->sta
rt(), textBox->len()); | 488 paintText(paintInfo, textRun, fragment, textMatchInfo.startPosition,
textMatchInfo.endPosition, strokePaint); |
442 | |
443 if (markerStartPosition >= markerEndPosition) | |
444 continue; | |
445 | |
446 const Vector<SVGTextFragment>& fragments = textBox->textFragments(); | |
447 unsigned textFragmentsSize = fragments.size(); | |
448 for (unsigned i = 0; i < textFragmentsSize; ++i) { | |
449 const SVGTextFragment& fragment = fragments.at(i); | |
450 | |
451 int fragmentStartPosition = markerStartPosition; | |
452 int fragmentEndPosition = markerEndPosition; | |
453 if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment,
fragmentStartPosition, fragmentEndPosition)) | |
454 continue; | |
455 | |
456 FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragm
ent, fragmentStartPosition, fragmentEndPosition, style); | |
457 fragment.buildFragmentTransform(fragmentTransform); | |
458 | |
459 // Draw the marker highlight. | |
460 if (LineLayoutPaintShim::layoutObjectFrom(m_svgInlineTextBox.lineLay
outItem())->frame()->editor().markedTextMatchesAreHighlighted()) { | |
461 Color color = marker->activeMatch() ? | |
462 LayoutTheme::theme().platformActiveTextSearchHighlightColor(
) : | |
463 LayoutTheme::theme().platformInactiveTextSearchHighlightColo
r(); | |
464 GraphicsContextStateSaver stateSaver(context); | |
465 if (!fragmentTransform.isIdentity()) | |
466 context.concatCTM(fragmentTransform); | |
467 context.setFillColor(color); | |
468 context.fillRect(fragmentRect, color); | |
469 } | |
470 } | |
471 } | 489 } |
472 } | 490 } |
473 | 491 |
| 492 void SVGInlineTextBoxPainter::paintTextMatchMarkerBackground(const PaintInfo& pa
intInfo, const LayoutPoint& point, DocumentMarker* marker, const ComputedStyle&
style, const Font& font) |
| 493 { |
| 494 const Vector<SVGTextFragmentWithRange> textMatchInfoList = collectTextMatche
s(marker); |
| 495 if (textMatchInfoList.isEmpty()) |
| 496 return; |
| 497 |
| 498 Color color = LayoutTheme::theme().platformTextSearchHighlightColor(marker->
activeMatch()); |
| 499 AffineTransform fragmentTransform; |
| 500 for (const SVGTextFragmentWithRange& textMatchInfo : textMatchInfoList) { |
| 501 const SVGTextFragment& fragment = textMatchInfo.fragment; |
| 502 |
| 503 GraphicsContextStateSaver stateSaver(paintInfo.context, false); |
| 504 fragment.buildFragmentTransform(fragmentTransform); |
| 505 if (!fragmentTransform.isIdentity()) { |
| 506 stateSaver.save(); |
| 507 paintInfo.context.concatCTM(fragmentTransform); |
| 508 } |
| 509 FloatRect fragmentRect = m_svgInlineTextBox.selectionRectForTextFragment
(fragment, textMatchInfo.startPosition, textMatchInfo.endPosition, style); |
| 510 paintInfo.context.setFillColor(color); |
| 511 paintInfo.context.fillRect(fragmentRect); |
| 512 } |
| 513 } |
| 514 |
474 } // namespace blink | 515 } // namespace blink |
OLD | NEW |