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/dom/DocumentMarkerController.h" | 8 #include "core/dom/DocumentMarkerController.h" |
9 #include "core/dom/RenderedDocumentMarker.h" | 9 #include "core/dom/RenderedDocumentMarker.h" |
10 #include "core/editing/Editor.h" | 10 #include "core/editing/Editor.h" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 // If we ever need that for SVG, it's very easy to refactor and reuse the co
de. | 49 // If we ever need that for SVG, it's very easy to refactor and reuse the co
de. |
50 | 50 |
51 if (paintInfo.phase == PaintPhaseSelection && !shouldPaintSelection()) | 51 if (paintInfo.phase == PaintPhaseSelection && !shouldPaintSelection()) |
52 return; | 52 return; |
53 | 53 |
54 LayoutSVGInlineText& textRenderer = toLayoutSVGInlineText(m_svgInlineTextBox
.layoutObject()); | 54 LayoutSVGInlineText& textRenderer = toLayoutSVGInlineText(m_svgInlineTextBox
.layoutObject()); |
55 if (!textShouldBePainted(textRenderer)) | 55 if (!textShouldBePainted(textRenderer)) |
56 return; | 56 return; |
57 | 57 |
58 LayoutObject& parentRenderer = m_svgInlineTextBox.parent()->layoutObject(); | 58 LayoutObject& parentRenderer = m_svgInlineTextBox.parent()->layoutObject(); |
59 const LayoutStyle& style = parentRenderer.styleRef(); | 59 const ComputedStyle& style = parentRenderer.styleRef(); |
60 | 60 |
61 { | 61 { |
62 DrawingRecorder recorder(paintInfo.context, m_svgInlineTextBox, DisplayI
tem::paintPhaseToDrawingType(paintInfo.phase), paintInfo.rect); | 62 DrawingRecorder recorder(paintInfo.context, m_svgInlineTextBox, DisplayI
tem::paintPhaseToDrawingType(paintInfo.phase), paintInfo.rect); |
63 if (!recorder.canUseCachedDrawing()) { | 63 if (!recorder.canUseCachedDrawing()) { |
64 InlineTextBoxPainter(m_svgInlineTextBox).paintDocumentMarkers( | 64 InlineTextBoxPainter(m_svgInlineTextBox).paintDocumentMarkers( |
65 paintInfo.context, FloatPoint(paintOffset), style, | 65 paintInfo.context, FloatPoint(paintOffset), style, |
66 textRenderer.scaledFont(), true); | 66 textRenderer.scaledFont(), true); |
67 | 67 |
68 if (!m_svgInlineTextBox.textFragments().isEmpty()) | 68 if (!m_svgInlineTextBox.textFragments().isEmpty()) |
69 paintTextFragments(paintInfo, parentRenderer); | 69 paintTextFragments(paintInfo, parentRenderer); |
70 } | 70 } |
71 } | 71 } |
72 | 72 |
73 if (style.hasOutline() && parentRenderer.isLayoutInline()) | 73 if (style.hasOutline() && parentRenderer.isLayoutInline()) |
74 InlinePainter(toLayoutInline(parentRenderer)).paintOutline(paintInfo, pa
intOffset); | 74 InlinePainter(toLayoutInline(parentRenderer)).paintOutline(paintInfo, pa
intOffset); |
75 } | 75 } |
76 | 76 |
77 void SVGInlineTextBoxPainter::paintTextFragments(const PaintInfo& paintInfo, Lay
outObject& parentRenderer) | 77 void SVGInlineTextBoxPainter::paintTextFragments(const PaintInfo& paintInfo, Lay
outObject& parentRenderer) |
78 { | 78 { |
79 const LayoutStyle& style = parentRenderer.styleRef(); | 79 const ComputedStyle& style = parentRenderer.styleRef(); |
80 const SVGLayoutStyle& svgStyle = style.svgStyle(); | 80 const SVGComputedStyle& svgStyle = style.svgStyle(); |
81 | 81 |
82 bool hasFill = svgStyle.hasFill(); | 82 bool hasFill = svgStyle.hasFill(); |
83 bool hasVisibleStroke = svgStyle.hasVisibleStroke(); | 83 bool hasVisibleStroke = svgStyle.hasVisibleStroke(); |
84 | 84 |
85 const LayoutStyle* selectionStyle = &style; | 85 const ComputedStyle* selectionStyle = &style; |
86 bool shouldPaintSelection = this->shouldPaintSelection(); | 86 bool shouldPaintSelection = this->shouldPaintSelection(); |
87 if (shouldPaintSelection) { | 87 if (shouldPaintSelection) { |
88 selectionStyle = parentRenderer.getCachedPseudoStyle(SELECTION); | 88 selectionStyle = parentRenderer.getCachedPseudoStyle(SELECTION); |
89 if (selectionStyle) { | 89 if (selectionStyle) { |
90 const SVGLayoutStyle& svgSelectionStyle = selectionStyle->svgStyle()
; | 90 const SVGComputedStyle& svgSelectionStyle = selectionStyle->svgStyle
(); |
91 | 91 |
92 if (!hasFill) | 92 if (!hasFill) |
93 hasFill = svgSelectionStyle.hasFill(); | 93 hasFill = svgSelectionStyle.hasFill(); |
94 if (!hasVisibleStroke) | 94 if (!hasVisibleStroke) |
95 hasVisibleStroke = svgSelectionStyle.hasVisibleStroke(); | 95 hasVisibleStroke = svgSelectionStyle.hasVisibleStroke(); |
96 } else { | 96 } else { |
97 selectionStyle = &style; | 97 selectionStyle = &style; |
98 } | 98 } |
99 } | 99 } |
100 | 100 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 return; | 158 return; |
159 | 159 |
160 Color backgroundColor = m_svgInlineTextBox.layoutObject().selectionBackgroun
dColor(); | 160 Color backgroundColor = m_svgInlineTextBox.layoutObject().selectionBackgroun
dColor(); |
161 if (!backgroundColor.alpha()) | 161 if (!backgroundColor.alpha()) |
162 return; | 162 return; |
163 | 163 |
164 LayoutSVGInlineText& textRenderer = toLayoutSVGInlineText(m_svgInlineTextBox
.layoutObject()); | 164 LayoutSVGInlineText& textRenderer = toLayoutSVGInlineText(m_svgInlineTextBox
.layoutObject()); |
165 if (!textShouldBePainted(textRenderer)) | 165 if (!textShouldBePainted(textRenderer)) |
166 return; | 166 return; |
167 | 167 |
168 const LayoutStyle& style = m_svgInlineTextBox.parent()->layoutObject().style
Ref(); | 168 const ComputedStyle& style = m_svgInlineTextBox.parent()->layoutObject().sty
leRef(); |
169 | 169 |
170 int startPosition, endPosition; | 170 int startPosition, endPosition; |
171 m_svgInlineTextBox.selectionStartEnd(startPosition, endPosition); | 171 m_svgInlineTextBox.selectionStartEnd(startPosition, endPosition); |
172 | 172 |
173 int fragmentStartPosition = 0; | 173 int fragmentStartPosition = 0; |
174 int fragmentEndPosition = 0; | 174 int fragmentEndPosition = 0; |
175 AffineTransform fragmentTransform; | 175 AffineTransform fragmentTransform; |
176 unsigned textFragmentsSize = m_svgInlineTextBox.textFragments().size(); | 176 unsigned textFragmentsSize = m_svgInlineTextBox.textFragments().size(); |
177 for (unsigned i = 0; i < textFragmentsSize; ++i) { | 177 for (unsigned i = 0; i < textFragmentsSize; ++i) { |
178 SVGTextFragment& fragment = m_svgInlineTextBox.textFragments().at(i); | 178 SVGTextFragment& fragment = m_svgInlineTextBox.textFragments().at(i); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 void SVGInlineTextBoxPainter::paintDecoration(const PaintInfo& paintInfo, TextDe
coration decoration, const SVGTextFragment& fragment) | 235 void SVGInlineTextBoxPainter::paintDecoration(const PaintInfo& paintInfo, TextDe
coration decoration, const SVGTextFragment& fragment) |
236 { | 236 { |
237 if (m_svgInlineTextBox.layoutObject().style()->textDecorationsInEffect() ==
TextDecorationNone) | 237 if (m_svgInlineTextBox.layoutObject().style()->textDecorationsInEffect() ==
TextDecorationNone) |
238 return; | 238 return; |
239 | 239 |
240 if (fragment.width <= 0) | 240 if (fragment.width <= 0) |
241 return; | 241 return; |
242 | 242 |
243 // Find out which render style defined the text-decoration, as its fill/stro
ke properties have to be used for drawing instead of ours. | 243 // Find out which render style defined the text-decoration, as its fill/stro
ke properties have to be used for drawing instead of ours. |
244 LayoutObject* decorationRenderer = findLayoutObjectDefininingTextDecoration(
m_svgInlineTextBox.parent()); | 244 LayoutObject* decorationRenderer = findLayoutObjectDefininingTextDecoration(
m_svgInlineTextBox.parent()); |
245 const LayoutStyle& decorationStyle = decorationRenderer->styleRef(); | 245 const ComputedStyle& decorationStyle = decorationRenderer->styleRef(); |
246 | 246 |
247 if (decorationStyle.visibility() == HIDDEN) | 247 if (decorationStyle.visibility() == HIDDEN) |
248 return; | 248 return; |
249 | 249 |
250 float scalingFactor = 1; | 250 float scalingFactor = 1; |
251 Font scaledFont; | 251 Font scaledFont; |
252 LayoutSVGInlineText::computeNewScaledFontForStyle(decorationRenderer, &decor
ationStyle, scalingFactor, scaledFont); | 252 LayoutSVGInlineText::computeNewScaledFontForStyle(decorationRenderer, &decor
ationStyle, scalingFactor, scaledFont); |
253 ASSERT(scalingFactor); | 253 ASSERT(scalingFactor); |
254 | 254 |
255 float thickness = thicknessForDecoration(decoration, scaledFont); | 255 float thickness = thicknessForDecoration(decoration, scaledFont); |
256 if (thickness <= 0) | 256 if (thickness <= 0) |
257 return; | 257 return; |
258 | 258 |
259 float decorationOffset = baselineOffsetForDecoration(decoration, scaledFont.
fontMetrics(), thickness); | 259 float decorationOffset = baselineOffsetForDecoration(decoration, scaledFont.
fontMetrics(), thickness); |
260 FloatPoint decorationOrigin(fragment.x, fragment.y - decorationOffset / scal
ingFactor); | 260 FloatPoint decorationOrigin(fragment.x, fragment.y - decorationOffset / scal
ingFactor); |
261 | 261 |
262 Path path; | 262 Path path; |
263 path.addRect(FloatRect(decorationOrigin, FloatSize(fragment.width, thickness
/ scalingFactor))); | 263 path.addRect(FloatRect(decorationOrigin, FloatSize(fragment.width, thickness
/ scalingFactor))); |
264 | 264 |
265 const SVGLayoutStyle& svgDecorationStyle = decorationStyle.svgStyle(); | 265 const SVGComputedStyle& svgDecorationStyle = decorationStyle.svgStyle(); |
266 | 266 |
267 for (int i = 0; i < 3; i++) { | 267 for (int i = 0; i < 3; i++) { |
268 switch (svgDecorationStyle.paintOrderType(i)) { | 268 switch (svgDecorationStyle.paintOrderType(i)) { |
269 case PT_FILL: | 269 case PT_FILL: |
270 if (svgDecorationStyle.hasFill()) { | 270 if (svgDecorationStyle.hasFill()) { |
271 GraphicsContextStateSaver stateSaver(*paintInfo.context, false); | 271 GraphicsContextStateSaver stateSaver(*paintInfo.context, false); |
272 if (!SVGLayoutSupport::updateGraphicsContext(paintInfo, stateSav
er, decorationStyle, *decorationRenderer, ApplyToFillMode)) | 272 if (!SVGLayoutSupport::updateGraphicsContext(paintInfo, stateSav
er, decorationStyle, *decorationRenderer, ApplyToFillMode)) |
273 break; | 273 break; |
274 paintInfo.context->fillPath(path); | 274 paintInfo.context->fillPath(path); |
275 } | 275 } |
276 break; | 276 break; |
277 case PT_STROKE: | 277 case PT_STROKE: |
278 if (svgDecorationStyle.hasVisibleStroke()) { | 278 if (svgDecorationStyle.hasVisibleStroke()) { |
279 // FIXME: Non-scaling stroke is not applied here. | 279 // FIXME: Non-scaling stroke is not applied here. |
280 GraphicsContextStateSaver stateSaver(*paintInfo.context, false); | 280 GraphicsContextStateSaver stateSaver(*paintInfo.context, false); |
281 if (!SVGLayoutSupport::updateGraphicsContext(paintInfo, stateSav
er, decorationStyle, *decorationRenderer, ApplyToStrokeMode)) | 281 if (!SVGLayoutSupport::updateGraphicsContext(paintInfo, stateSav
er, decorationStyle, *decorationRenderer, ApplyToStrokeMode)) |
282 break; | 282 break; |
283 paintInfo.context->strokePath(path); | 283 paintInfo.context->strokePath(path); |
284 } | 284 } |
285 break; | 285 break; |
286 case PT_MARKERS: | 286 case PT_MARKERS: |
287 break; | 287 break; |
288 default: | 288 default: |
289 ASSERT_NOT_REACHED(); | 289 ASSERT_NOT_REACHED(); |
290 } | 290 } |
291 } | 291 } |
292 } | 292 } |
293 | 293 |
294 void SVGInlineTextBoxPainter::paintTextWithShadows(const PaintInfo& paintInfo, c
onst LayoutStyle& style, | 294 void SVGInlineTextBoxPainter::paintTextWithShadows(const PaintInfo& paintInfo, c
onst ComputedStyle& style, |
295 TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int en
dPosition, | 295 TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int en
dPosition, |
296 LayoutSVGResourceMode resourceMode) | 296 LayoutSVGResourceMode resourceMode) |
297 { | 297 { |
298 LayoutSVGInlineText& textRenderer = toLayoutSVGInlineText(m_svgInlineTextBox
.layoutObject()); | 298 LayoutSVGInlineText& textRenderer = toLayoutSVGInlineText(m_svgInlineTextBox
.layoutObject()); |
299 | 299 |
300 float scalingFactor = textRenderer.scalingFactor(); | 300 float scalingFactor = textRenderer.scalingFactor(); |
301 ASSERT(scalingFactor); | 301 ASSERT(scalingFactor); |
302 | 302 |
303 const Font& scaledFont = textRenderer.scaledFont(); | 303 const Font& scaledFont = textRenderer.scaledFont(); |
304 const ShadowList* shadowList = style.textShadow(); | 304 const ShadowList* shadowList = style.textShadow(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 textRunPaintInfo.from = startPosition; | 342 textRunPaintInfo.from = startPosition; |
343 textRunPaintInfo.to = endPosition; | 343 textRunPaintInfo.to = endPosition; |
344 | 344 |
345 float baseline = scaledFont.fontMetrics().floatAscent(); | 345 float baseline = scaledFont.fontMetrics().floatAscent(); |
346 textRunPaintInfo.bounds = FloatRect(textOrigin.x(), textOrigin.y() - baselin
e, | 346 textRunPaintInfo.bounds = FloatRect(textOrigin.x(), textOrigin.y() - baselin
e, |
347 textSize.width(), textSize.height()); | 347 textSize.width(), textSize.height()); |
348 | 348 |
349 context->drawText(scaledFont, textRunPaintInfo, textOrigin); | 349 context->drawText(scaledFont, textRunPaintInfo, textOrigin); |
350 } | 350 } |
351 | 351 |
352 void SVGInlineTextBoxPainter::paintText(const PaintInfo& paintInfo, const Layout
Style& style, | 352 void SVGInlineTextBoxPainter::paintText(const PaintInfo& paintInfo, const Comput
edStyle& style, |
353 const LayoutStyle& selectionStyle, const SVGTextFragment& fragment, | 353 const ComputedStyle& selectionStyle, const SVGTextFragment& fragment, |
354 LayoutSVGResourceMode resourceMode, bool shouldPaintSelection) | 354 LayoutSVGResourceMode resourceMode, bool shouldPaintSelection) |
355 { | 355 { |
356 int startPosition = 0; | 356 int startPosition = 0; |
357 int endPosition = 0; | 357 int endPosition = 0; |
358 if (shouldPaintSelection) { | 358 if (shouldPaintSelection) { |
359 m_svgInlineTextBox.selectionStartEnd(startPosition, endPosition); | 359 m_svgInlineTextBox.selectionStartEnd(startPosition, endPosition); |
360 shouldPaintSelection = m_svgInlineTextBox.mapStartEndPositionsIntoFragme
ntCoordinates(fragment, startPosition, endPosition); | 360 shouldPaintSelection = m_svgInlineTextBox.mapStartEndPositionsIntoFragme
ntCoordinates(fragment, startPosition, endPosition); |
361 } | 361 } |
362 | 362 |
363 // Fast path if there is no selection, just draw the whole chunk part using
the regular style | 363 // Fast path if there is no selection, just draw the whole chunk part using
the regular style |
(...skipping 21 matching lines...) Expand all Loading... |
385 StyleDifference diff; | 385 StyleDifference diff; |
386 diff.setNeedsPaintInvalidationObject(); | 386 diff.setNeedsPaintInvalidationObject(); |
387 SVGResourcesCache::clientStyleChanged(&m_svgInlineTextBox.parent()->layo
utObject(), diff, style); | 387 SVGResourcesCache::clientStyleChanged(&m_svgInlineTextBox.parent()->layo
utObject(), diff, style); |
388 } | 388 } |
389 | 389 |
390 // Eventually draw text using regular style from the end position of the sel
ection to the end of the current chunk part | 390 // Eventually draw text using regular style from the end position of the sel
ection to the end of the current chunk part |
391 if (endPosition < static_cast<int>(fragment.length) && !paintSelectedTextOnl
y) | 391 if (endPosition < static_cast<int>(fragment.length) && !paintSelectedTextOnl
y) |
392 paintTextWithShadows(paintInfo, style, textRun, fragment, endPosition, f
ragment.length, resourceMode); | 392 paintTextWithShadows(paintInfo, style, textRun, fragment, endPosition, f
ragment.length, resourceMode); |
393 } | 393 } |
394 | 394 |
395 void SVGInlineTextBoxPainter::paintTextMatchMarker(GraphicsContext* context, con
st FloatPoint&, DocumentMarker* marker, const LayoutStyle& style, const Font& fo
nt) | 395 void SVGInlineTextBoxPainter::paintTextMatchMarker(GraphicsContext* context, con
st FloatPoint&, DocumentMarker* marker, const ComputedStyle& style, const Font&
font) |
396 { | 396 { |
397 // SVG is only interested in the TextMatch markers. | 397 // SVG is only interested in the TextMatch markers. |
398 if (marker->type() != DocumentMarker::TextMatch) | 398 if (marker->type() != DocumentMarker::TextMatch) |
399 return; | 399 return; |
400 | 400 |
401 LayoutSVGInlineText& textRenderer = toLayoutSVGInlineText(m_svgInlineTextBox
.layoutObject()); | 401 LayoutSVGInlineText& textRenderer = toLayoutSVGInlineText(m_svgInlineTextBox
.layoutObject()); |
402 | 402 |
403 FloatRect markerRect; | 403 FloatRect markerRect; |
404 AffineTransform fragmentTransform; | 404 AffineTransform fragmentTransform; |
405 for (InlineTextBox* box = textRenderer.firstTextBox(); box; box = box->nextT
extBox()) { | 405 for (InlineTextBox* box = textRenderer.firstTextBox(); box; box = box->nextT
extBox()) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 | 441 |
442 fragmentRect = fragmentTransform.mapRect(fragmentRect); | 442 fragmentRect = fragmentTransform.mapRect(fragmentRect); |
443 markerRect.unite(fragmentRect); | 443 markerRect.unite(fragmentRect); |
444 } | 444 } |
445 } | 445 } |
446 | 446 |
447 toRenderedDocumentMarker(marker)->setRenderedRect(LayoutRect(textRenderer.lo
calToAbsoluteQuad(markerRect).enclosingBoundingBox())); | 447 toRenderedDocumentMarker(marker)->setRenderedRect(LayoutRect(textRenderer.lo
calToAbsoluteQuad(markerRect).enclosingBoundingBox())); |
448 } | 448 } |
449 | 449 |
450 } // namespace blink | 450 } // namespace blink |
OLD | NEW |