void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, ETextDecoration decoration, const SVGTextFragment& fragment, RenderObject* decorationRenderer) { ASSERT(!m_paintingResource); ASSERT(m_paintingResourceMode != ApplyToDefaultMode); RenderStyle* decorationStyle = decorationRenderer->style(); ASSERT(decorationStyle); float scalingFactor = 1; Font scaledFont; RenderSVGInlineText::computeNewScaledFontForStyle(decorationRenderer, decorationStyle, scalingFactor, scaledFont); ASSERT(scalingFactor); // The initial y value refers to overline position. float thickness = thicknessForDecoration(decoration, scaledFont); if (fragment.width <= 0 && thickness <= 0) return; FloatPoint decorationOrigin(fragment.x, fragment.y); float width = fragment.width; const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics(); GraphicsContextStateSaver stateSaver(*context); if (scalingFactor != 1) { width *= scalingFactor; decorationOrigin.scale(scalingFactor, scalingFactor); AffineTransform newTransform = context->getCTM(); newTransform.scale(1 / scalingFactor); normalizeTransform(newTransform); context->setCTM(newTransform); } decorationOrigin.move(0, -scaledFontMetrics.floatAscent() + positionOffsetForDecoration(decoration, scaledFontMetrics, thickness)); Path path; path.addRect(FloatRect(decorationOrigin, FloatSize(width, thickness))); if (acquirePaintingResource(context, scalingFactor, decorationRenderer, decorationStyle)) releasePaintingResource(context, &path); }
void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, TextDecoration decoration, const SVGTextFragment& fragment, RenderObject* decorationRenderer) { ASSERT(!m_paintingResource); ASSERT(m_paintingResourceMode != ApplyToDefaultMode); RenderStyle* decorationStyle = decorationRenderer->style(); ASSERT(decorationStyle); float scalingFactor = 1; Font scaledFont; RenderSVGInlineText::computeNewScaledFontForStyle(decorationRenderer, decorationStyle, scalingFactor, scaledFont); ASSERT(scalingFactor); // The initial y value refers to overline position. float thickness = thicknessForDecoration(decoration, scaledFont); if (fragment.width <= 0 && thickness <= 0) return; FloatPoint decorationOrigin(fragment.x, fragment.y); float width = fragment.width; const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics(); GraphicsContextStateSaver stateSaver(*context, false); if (scalingFactor != 1) { stateSaver.save(); width *= scalingFactor; decorationOrigin.scale(scalingFactor, scalingFactor); context->scale(FloatSize(1 / scalingFactor, 1 / scalingFactor)); } decorationOrigin.move(0, -scaledFontMetrics.floatAscent() + positionOffsetForDecoration(decoration, scaledFontMetrics, thickness)); Path path; path.addRect(FloatRect(decorationOrigin, FloatSize(width, thickness))); // acquirePaintingResource also modifies state if the scalingFactor is non-identity. // Above we have saved the state for this case. if (acquirePaintingResource(context, scalingFactor, decorationRenderer, decorationStyle)) releasePaintingResource(context, &path); }
void SVGInlineTextBoxPainter::paintDecoration(const PaintInfo& paintInfo, TextDecoration decoration, const SVGTextFragment& fragment) { if (m_svgInlineTextBox.layoutObject().style()->textDecorationsInEffect() == TextDecorationNone) return; if (fragment.width <= 0) return; // Find out which style defined the text-decoration, as its fill/stroke properties have to be used for drawing instead of ours. LayoutObject* decorationLayoutObject = findLayoutObjectDefininingTextDecoration(m_svgInlineTextBox.parent()); const ComputedStyle& decorationStyle = decorationLayoutObject->styleRef(); if (decorationStyle.visibility() == HIDDEN) return; float scalingFactor = 1; Font scaledFont; LayoutSVGInlineText::computeNewScaledFontForStyle(decorationLayoutObject, &decorationStyle, scalingFactor, scaledFont); ASSERT(scalingFactor); float thickness = thicknessForDecoration(decoration, scaledFont); if (thickness <= 0) return; float decorationOffset = baselineOffsetForDecoration(decoration, scaledFont.fontMetrics(), thickness); FloatPoint decorationOrigin(fragment.x, fragment.y - decorationOffset / scalingFactor); Path path; path.addRect(FloatRect(decorationOrigin, FloatSize(fragment.width, thickness / scalingFactor))); const SVGComputedStyle& svgDecorationStyle = decorationStyle.svgStyle(); for (int i = 0; i < 3; i++) { switch (svgDecorationStyle.paintOrderType(i)) { case PT_FILL: if (svgDecorationStyle.hasFill()) { SkPaint fillPaint; if (!SVGPaintContext::paintForLayoutObject(paintInfo, decorationStyle, *decorationLayoutObject, ApplyToFillMode, fillPaint)) break; fillPaint.setAntiAlias(true); paintInfo.context->drawPath(path.skPath(), fillPaint); } break; case PT_STROKE: if (svgDecorationStyle.hasVisibleStroke()) { SkPaint strokePaint; if (!SVGPaintContext::paintForLayoutObject(paintInfo, decorationStyle, *decorationLayoutObject, ApplyToStrokeMode, strokePaint)) break; strokePaint.setAntiAlias(true); StrokeData strokeData; SVGLayoutSupport::applyStrokeStyleToStrokeData(strokeData, decorationStyle, *decorationLayoutObject); if (svgDecorationStyle.vectorEffect() == VE_NON_SCALING_STROKE) strokeData.setThickness(strokeData.thickness() / scalingFactor); strokeData.setupPaint(&strokePaint); paintInfo.context->drawPath(path.skPath(), strokePaint); } break; case PT_MARKERS: break; default: ASSERT_NOT_REACHED(); } } }