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(), 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 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 const Vector<SVGTextFragmentWithRange> SVGInlineTextBoxPainter::collectTextMatch es(DocumentMarker* marker) |
| 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 const Vector<SVGTextFragmentWithRange> SVGInlineTextBoxPainter::collectFragments InRange(int startPosition, int endPosition) | |
| 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 Vector<SVGTextFragmentWithRange> textMatchInfoList = collectTextMatches(mark er); | |
| 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 shouldApplyToStrokeMode = false; | |
|
fs
2015/12/21 12:00:01
Nit: shouldPaintStroke
ramya.v
2015/12/21 13:01:56
Done.
| |
| 471 if (setupTextPaint(paintInfo, style, ApplyToStrokeMode, strokePaint)) { | |
|
fs
2015/12/21 12:00:01
This will also apply text-shadow, so that should b
ramya.v
2015/12/21 13:01:56
Done.
| |
| 472 shouldApplyToStrokeMode = true; | |
| 473 strokePaint.setColor(textColor.rgb()); | |
| 474 } | |
| 432 | 475 |
| 433 AffineTransform fragmentTransform; | 476 AffineTransform fragmentTransform; |
| 434 for (InlineTextBox* box = textLayoutObject.firstTextBox(); box; box = box->n extTextBox()) { | 477 for (const SVGTextFragmentWithRange& textMatchInfo : textMatchInfoList) { |
| 435 if (!box->isSVGInlineTextBox()) | 478 const SVGTextFragment& fragment = textMatchInfo.fragment; |
| 436 continue; | 479 GraphicsContextStateSaver stateSaver(paintInfo.context); |
| 480 fragment.buildFragmentTransform(fragmentTransform); | |
| 481 if (!fragmentTransform.isIdentity()) | |
| 482 paintInfo.context.concatCTM(fragmentTransform); | |
| 437 | 483 |
| 438 SVGInlineTextBox* textBox = toSVGInlineTextBox(box); | 484 TextRun textRun = m_svgInlineTextBox.constructTextRun(style, fragment); |
| 439 | 485 paintText(paintInfo, textRun, fragment, textMatchInfo.startPosition, tex tMatchInfo.endPosition, fillPaint); |
| 440 int markerStartPosition = std::max<int>(marker->startOffset() - textBox- >start(), 0); | 486 if (shouldApplyToStrokeMode) |
| 441 int markerEndPosition = std::min<int>(marker->endOffset() - textBox->sta rt(), textBox->len()); | 487 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 } | 488 } |
| 472 } | 489 } |
| 473 | 490 |
| 491 void SVGInlineTextBoxPainter::paintTextMatchMarkerBackground(const PaintInfo& pa intInfo, const LayoutPoint& point, DocumentMarker* marker, const ComputedStyle& style, const Font& font) | |
| 492 { | |
| 493 Vector<SVGTextFragmentWithRange> textMatchInfoList = collectTextMatches(mark er); | |
| 494 if (textMatchInfoList.isEmpty()) | |
| 495 return; | |
| 496 | |
| 497 Color color = LayoutTheme::theme().platformTextSearchHighlightColor(marker-> activeMatch()); | |
| 498 AffineTransform fragmentTransform; | |
| 499 for (const SVGTextFragmentWithRange& textMatchInfo : textMatchInfoList) { | |
| 500 const SVGTextFragment& fragment = textMatchInfo.fragment; | |
| 501 | |
| 502 GraphicsContextStateSaver stateSaver(paintInfo.context, false); | |
| 503 fragment.buildFragmentTransform(fragmentTransform); | |
| 504 if (!fragmentTransform.isIdentity()) { | |
| 505 stateSaver.save(); | |
| 506 paintInfo.context.concatCTM(fragmentTransform); | |
| 507 } | |
| 508 FloatRect fragmentRect = m_svgInlineTextBox.selectionRectForTextFragment (fragment, textMatchInfo.startPosition, textMatchInfo.endPosition, style); | |
| 509 paintInfo.context.setFillColor(color); | |
| 510 paintInfo.context.fillRect(fragmentRect); | |
| 511 } | |
| 512 } | |
| 513 | |
| 474 } // namespace blink | 514 } // namespace blink |
| OLD | NEW |