Chromium Code Reviews| 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(), InlineTextBoxPainter::DocumentMarkerP aintPhase::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(), InlineTextBoxPainter::DocumentMarkerP aintPhase::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 Vector<SVGTextFragmentWithRange> fragmentInfoList = collectFragmentsInRange( 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(con st PaintInfo& paintInfo, DocumentMarker* marker) |
|
fs
2015/12/18 11:35:17
|paintInfo| isn't used.
ramya.v
2015/12/21 08:13:49
Done.
| |
| 426 { | 422 { |
| 427 // SVG is only interested in the TextMatch markers. | 423 Vector<SVGTextFragmentWithRange> textMatchInfoList; |
| 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 textMatchInfoList; | |
| 428 | |
| 429 if (!LineLayoutPaintShim::layoutObjectFrom(m_svgInlineTextBox.lineLayoutItem ())->frame()->editor().markedTextMatchesAreHighlighted()) | |
| 430 return textMatchInfoList; | |
| 431 | |
| 432 int markerStartPosition = std::max<int>(marker->startOffset() - m_svgInlineT extBox.start(), 0); | |
|
pdr.
2015/12/19 02:39:45
Can these be negative? If not, lets use unsigned (
ramya.v
2015/12/21 08:13:49
This would depend on collectFragmentsInRange, mapS
fs
2015/12/21 12:00:01
I believe this one can - the only guarantee (made
| |
| 433 int markerEndPosition = std::min<int>(marker->endOffset() - m_svgInlineTextB ox.start(), m_svgInlineTextBox.len()); | |
| 434 | |
| 435 if (markerStartPosition >= markerEndPosition) | |
| 436 return textMatchInfoList; | |
| 437 | |
| 438 textMatchInfoList = collectFragmentsInRange(markerStartPosition, markerEndPo sition); | |
|
fs
2015/12/18 11:35:17
Could just make this a tail-call ("return collectF
ramya.v
2015/12/21 08:13:49
Done.
| |
| 439 return textMatchInfoList; | |
| 440 } | |
| 441 | |
| 442 Vector<SVGTextFragmentWithRange> SVGInlineTextBoxPainter::collectFragmentsInRang e(int startPosition, int endPosition) | |
| 443 { | |
| 444 Vector<SVGTextFragmentWithRange> fragmentInfoList; | |
| 445 const Vector<SVGTextFragment>& fragments = m_svgInlineTextBox.textFragments( ); | |
| 446 unsigned textFragmentsSize = fragments.size(); | |
| 447 for (unsigned i = 0; i < textFragmentsSize; ++i) { | |
|
fs
2015/12/18 11:35:17
Use range-based for-loop.
ramya.v
2015/12/21 08:13:49
Done.
| |
| 448 const SVGTextFragment& fragment = fragments.at(i); | |
| 449 | |
| 450 int fragmentStartPosition = startPosition; | |
| 451 int fragmentEndPosition = endPosition; | |
| 452 if (!m_svgInlineTextBox.mapStartEndPositionsIntoFragmentCoordinates(frag ment, fragmentStartPosition, fragmentEndPosition)) | |
| 453 continue; | |
| 454 | |
| 455 fragmentInfoList.append(SVGTextFragmentWithRange(fragment, fragmentStart Position, fragmentEndPosition)); | |
| 456 } | |
| 457 return fragmentInfoList; | |
| 458 } | |
| 459 | |
| 460 void SVGInlineTextBoxPainter::paintTextMatchMarkerForeground(const PaintInfo& pa intInfo, const LayoutPoint& point, DocumentMarker* marker, const ComputedStyle& style, const Font& font) | |
| 461 { | |
| 462 Vector<SVGTextFragmentWithRange> textMatchInfoList = collectTextMatches(pain tInfo, marker); | |
| 463 if (textMatchInfoList.isEmpty()) | |
| 429 return; | 464 return; |
| 430 | 465 |
| 431 LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(*LineLayoutPai ntShim::layoutObjectFrom(m_svgInlineTextBox.lineLayoutItem())); | 466 Color textColor = LayoutTheme::theme().platformTextSearchColor(marker->activ eMatch()); |
| 467 AffineTransform fragmentTransform; | |
| 468 for (const SVGTextFragmentWithRange& textMatchInfo : textMatchInfoList) { | |
| 469 const SVGTextFragment& fragment = textMatchInfo.fragment; | |
| 470 GraphicsContextStateSaver stateSaver(paintInfo.context); | |
| 471 fragment.buildFragmentTransform(fragmentTransform); | |
| 472 if (!fragmentTransform.isIdentity()) | |
| 473 paintInfo.context.concatCTM(fragmentTransform); | |
| 432 | 474 |
| 433 AffineTransform fragmentTransform; | 475 TextRun textRun = m_svgInlineTextBox.constructTextRun(style, fragment); |
| 434 for (InlineTextBox* box = textLayoutObject.firstTextBox(); box; box = box->n extTextBox()) { | 476 SkPaint paint; |
| 435 if (!box->isSVGInlineTextBox()) | 477 if (setupTextPaint(paintInfo, style, ApplyToFillMode, paint)) { |
|
fs
2015/12/18 11:35:17
Since this does not depend on anything within the
ramya.v
2015/12/21 08:13:49
Moved setupPaint out of loop. As with other browse
fs
2015/12/21 12:00:01
That's odd... It does look like it happens for the
ramya.v
2015/12/21 13:01:55
To file a bug, same test case, if I directly load
fs
2015/12/21 13:13:24
Ok, so it's in the test-runner only... better make
| |
| 436 continue; | 478 paint.setColor(textColor.rgb()); |
| 437 | 479 paintText(paintInfo, textRun, fragment, textMatchInfo.startPosition, textMatchInfo.endPosition, paint); |
| 438 SVGInlineTextBox* textBox = toSVGInlineTextBox(box); | |
| 439 | |
| 440 int markerStartPosition = std::max<int>(marker->startOffset() - textBox- >start(), 0); | |
| 441 int markerEndPosition = std::min<int>(marker->endOffset() - textBox->sta rt(), textBox->len()); | |
| 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 } | 480 } |
| 471 } | 481 } |
| 472 } | 482 } |
| 473 | 483 |
| 484 void SVGInlineTextBoxPainter::paintTextMatchMarkerBackground(const PaintInfo& pa intInfo, const LayoutPoint& point, DocumentMarker* marker, const ComputedStyle& style, const Font& font) | |
| 485 { | |
| 486 Vector<SVGTextFragmentWithRange> textMatchInfoList = collectTextMatches(pain tInfo, marker); | |
| 487 if (textMatchInfoList.isEmpty()) | |
| 488 return; | |
| 489 | |
| 490 Color color = LayoutTheme::theme().platformTextSearchHighlightColor(marker-> activeMatch()); | |
| 491 AffineTransform fragmentTransform; | |
| 492 for (const SVGTextFragmentWithRange& textMatchInfo : textMatchInfoList) { | |
| 493 const SVGTextFragment& fragment = textMatchInfo.fragment; | |
| 494 GraphicsContextStateSaver stateSaver(paintInfo.context); | |
| 495 fragment.buildFragmentTransform(fragmentTransform); | |
| 496 if (!fragmentTransform.isIdentity()) | |
| 497 paintInfo.context.concatCTM(fragmentTransform); | |
| 498 FloatRect fragmentRect = m_svgInlineTextBox.selectionRectForTextFragment (fragment, textMatchInfo.startPosition, textMatchInfo.endPosition, style); | |
| 499 paintInfo.context.setFillColor(color); | |
| 500 paintInfo.context.fillRect(fragmentRect, color); | |
|
fs
2015/12/18 11:35:17
Passing color to fillRect is redundant with setFil
ramya.v
2015/12/21 08:13:49
Done.
| |
| 501 } | |
| 502 } | |
| 503 | |
| 474 } // namespace blink | 504 } // namespace blink |
| OLD | NEW |