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 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 if (renderer->style() && renderer->style()->textDecoration() != TextDeco
rationNone) | 197 if (renderer->style() && renderer->style()->textDecoration() != TextDeco
rationNone) |
198 break; | 198 break; |
199 | 199 |
200 parentBox = parentBox->parent(); | 200 parentBox = parentBox->parent(); |
201 } | 201 } |
202 | 202 |
203 ASSERT(renderer); | 203 ASSERT(renderer); |
204 return renderer; | 204 return renderer; |
205 } | 205 } |
206 | 206 |
207 void SVGInlineTextBoxPainter::paintDecoration(GraphicsContext* context, TextDeco
ration decoration, const SVGTextFragment& fragment) | |
208 { | |
209 if (m_svgInlineTextBox.renderer().style()->textDecorationsInEffect() == Text
DecorationNone) | |
210 return; | |
211 | |
212 // Find out which render style defined the text-decoration, as its fill/stro
ke properties have to be used for drawing instead of ours. | |
213 RenderObject* decorationRenderer = findRenderObjectDefininingTextDecoration(
m_svgInlineTextBox.parent()); | |
214 RenderStyle* decorationStyle = decorationRenderer->style(); | |
215 ASSERT(decorationStyle); | |
216 | |
217 if (decorationStyle->visibility() == HIDDEN) | |
218 return; | |
219 | |
220 const SVGRenderStyle& svgDecorationStyle = decorationStyle->svgStyle(); | |
221 | |
222 for (int i = 0; i < 3; i++) { | |
223 switch (svgDecorationStyle.paintOrderType(i)) { | |
224 case PT_FILL: | |
225 if (svgDecorationStyle.hasFill()) | |
226 paintDecorationWithStyle(context, decoration, fragment, decorati
onRenderer, ApplyToFillMode); | |
227 break; | |
228 case PT_STROKE: | |
229 if (svgDecorationStyle.hasVisibleStroke()) | |
230 paintDecorationWithStyle(context, decoration, fragment, decorati
onRenderer, ApplyToStrokeMode); | |
231 break; | |
232 case PT_MARKERS: | |
233 break; | |
234 default: | |
235 ASSERT_NOT_REACHED(); | |
236 } | |
237 } | |
238 } | |
239 | 207 |
240 // Offset from the baseline for |decoration|. Positive offsets are above the bas
eline. | 208 // Offset from the baseline for |decoration|. Positive offsets are above the bas
eline. |
241 static inline float baselineOffsetForDecoration(TextDecoration decoration, const
FontMetrics& fontMetrics, float thickness) | 209 static inline float baselineOffsetForDecoration(TextDecoration decoration, const
FontMetrics& fontMetrics, float thickness) |
242 { | 210 { |
243 // FIXME: For SVG Fonts we need to use the attributes defined in the <font-f
ace> if specified. | 211 // FIXME: For SVG Fonts we need to use the attributes defined in the <font-f
ace> if specified. |
244 // Compatible with Batik/Presto. | 212 // Compatible with Batik/Presto. |
245 if (decoration == TextDecorationUnderline) | 213 if (decoration == TextDecorationUnderline) |
246 return -thickness * 1.5f; | 214 return -thickness * 1.5f; |
247 if (decoration == TextDecorationOverline) | 215 if (decoration == TextDecorationOverline) |
248 return fontMetrics.floatAscent() - thickness; | 216 return fontMetrics.floatAscent() - thickness; |
249 if (decoration == TextDecorationLineThrough) | 217 if (decoration == TextDecorationLineThrough) |
250 return fontMetrics.floatAscent() * 3 / 8.0f; | 218 return fontMetrics.floatAscent() * 3 / 8.0f; |
251 | 219 |
252 ASSERT_NOT_REACHED(); | 220 ASSERT_NOT_REACHED(); |
253 return 0.0f; | 221 return 0.0f; |
254 } | 222 } |
255 | 223 |
256 static inline float thicknessForDecoration(TextDecoration, const Font& font) | 224 static inline float thicknessForDecoration(TextDecoration, const Font& font) |
257 { | 225 { |
258 // FIXME: For SVG Fonts we need to use the attributes defined in the <font-f
ace> if specified. | 226 // FIXME: For SVG Fonts we need to use the attributes defined in the <font-f
ace> if specified. |
259 // Compatible with Batik/Presto | 227 // Compatible with Batik/Presto |
260 return font.fontDescription().computedSize() / 20.0f; | 228 return font.fontDescription().computedSize() / 20.0f; |
261 } | 229 } |
262 | 230 |
263 void SVGInlineTextBoxPainter::paintDecorationWithStyle(GraphicsContext* context,
TextDecoration decoration, | 231 void SVGInlineTextBoxPainter::paintDecoration(GraphicsContext* context, TextDeco
ration decoration, const SVGTextFragment& fragment) |
264 const SVGTextFragment& fragment, RenderObject* decorationRenderer, RenderSVG
ResourceMode resourceMode) | |
265 { | 232 { |
| 233 if (m_svgInlineTextBox.renderer().style()->textDecorationsInEffect() == Text
DecorationNone) |
| 234 return; |
| 235 |
| 236 if (fragment.width <= 0) |
| 237 return; |
| 238 |
| 239 // Find out which render style defined the text-decoration, as its fill/stro
ke properties have to be used for drawing instead of ours. |
| 240 RenderObject* decorationRenderer = findRenderObjectDefininingTextDecoration(
m_svgInlineTextBox.parent()); |
266 RenderStyle* decorationStyle = decorationRenderer->style(); | 241 RenderStyle* decorationStyle = decorationRenderer->style(); |
267 ASSERT(decorationStyle); | 242 ASSERT(decorationStyle); |
268 | 243 |
| 244 if (decorationStyle->visibility() == HIDDEN) |
| 245 return; |
| 246 |
269 float scalingFactor = 1; | 247 float scalingFactor = 1; |
270 Font scaledFont; | 248 Font scaledFont; |
271 RenderSVGInlineText::computeNewScaledFontForStyle(decorationRenderer, decora
tionStyle, scalingFactor, scaledFont); | 249 RenderSVGInlineText::computeNewScaledFontForStyle(decorationRenderer, decora
tionStyle, scalingFactor, scaledFont); |
272 ASSERT(scalingFactor); | 250 ASSERT(scalingFactor); |
273 | 251 |
274 float thickness = thicknessForDecoration(decoration, scaledFont); | 252 float thickness = thicknessForDecoration(decoration, scaledFont); |
275 | 253 if (thickness <= 0) |
276 if (fragment.width <= 0 && thickness <= 0) | |
277 return; | 254 return; |
278 | 255 |
279 float decorationOffset = baselineOffsetForDecoration(decoration, scaledFont.
fontMetrics(), thickness); | 256 float decorationOffset = baselineOffsetForDecoration(decoration, scaledFont.
fontMetrics(), thickness); |
280 FloatPoint decorationOrigin(fragment.x, fragment.y - decorationOffset / scal
ingFactor); | 257 FloatPoint decorationOrigin(fragment.x, fragment.y - decorationOffset / scal
ingFactor); |
281 | 258 |
282 Path path; | 259 Path path; |
283 path.addRect(FloatRect(decorationOrigin, FloatSize(fragment.width, thickness
/ scalingFactor))); | 260 path.addRect(FloatRect(decorationOrigin, FloatSize(fragment.width, thickness
/ scalingFactor))); |
284 | 261 |
285 GraphicsContextStateSaver stateSaver(*context, false); | 262 const SVGRenderStyle& svgDecorationStyle = decorationStyle->svgStyle(); |
286 if (!SVGRenderSupport::updateGraphicsContext(stateSaver, decorationStyle, *d
ecorationRenderer, resourceMode)) | 263 |
287 return; | 264 for (int i = 0; i < 3; i++) { |
288 SVGRenderSupport::fillOrStrokePath(context, resourceMode, path); | 265 switch (svgDecorationStyle.paintOrderType(i)) { |
| 266 case PT_FILL: |
| 267 if (svgDecorationStyle.hasFill()) { |
| 268 GraphicsContextStateSaver stateSaver(*context, false); |
| 269 if (!SVGRenderSupport::updateGraphicsContext(stateSaver, decorat
ionStyle, *decorationRenderer, ApplyToFillMode)) |
| 270 break; |
| 271 context->fillPath(path); |
| 272 } |
| 273 break; |
| 274 case PT_STROKE: |
| 275 if (svgDecorationStyle.hasVisibleStroke()) { |
| 276 GraphicsContextStateSaver stateSaver(*context, false); |
| 277 if (!SVGRenderSupport::updateGraphicsContext(stateSaver, decorat
ionStyle, *decorationRenderer, ApplyToStrokeMode)) |
| 278 break; |
| 279 context->strokePath(path); |
| 280 } |
| 281 break; |
| 282 case PT_MARKERS: |
| 283 break; |
| 284 default: |
| 285 ASSERT_NOT_REACHED(); |
| 286 } |
| 287 } |
289 } | 288 } |
290 | 289 |
291 void SVGInlineTextBoxPainter::paintTextWithShadows(GraphicsContext* context, Ren
derStyle* style, | 290 void SVGInlineTextBoxPainter::paintTextWithShadows(GraphicsContext* context, Ren
derStyle* style, |
292 TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int en
dPosition, | 291 TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int en
dPosition, |
293 RenderSVGResourceMode resourceMode) | 292 RenderSVGResourceMode resourceMode) |
294 { | 293 { |
295 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(m_svgInlineTextBox
.renderer()); | 294 RenderSVGInlineText& textRenderer = toRenderSVGInlineText(m_svgInlineTextBox
.renderer()); |
296 | 295 |
297 float scalingFactor = textRenderer.scalingFactor(); | 296 float scalingFactor = textRenderer.scalingFactor(); |
298 ASSERT(scalingFactor); | 297 ASSERT(scalingFactor); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 | 431 |
433 fragmentRect = fragmentTransform.mapRect(fragmentRect); | 432 fragmentRect = fragmentTransform.mapRect(fragmentRect); |
434 markerRect.unite(fragmentRect); | 433 markerRect.unite(fragmentRect); |
435 } | 434 } |
436 } | 435 } |
437 | 436 |
438 toRenderedDocumentMarker(marker)->setRenderedRect(textRenderer.localToAbsolu
teQuad(markerRect).enclosingBoundingBox()); | 437 toRenderedDocumentMarker(marker)->setRenderedRect(textRenderer.localToAbsolu
teQuad(markerRect).enclosingBoundingBox()); |
439 } | 438 } |
440 | 439 |
441 } // namespace blink | 440 } // namespace blink |
OLD | NEW |