void SVGInlineTextBoxPainter::paintTextWithShadows(const PaintInfo& paintInfo, const ComputedStyle& style, TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int endPosition, LayoutSVGResourceMode resourceMode) { LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(m_svgInlineTextBox.layoutObject()); float scalingFactor = textLayoutObject.scalingFactor(); ASSERT(scalingFactor); const Font& scaledFont = textLayoutObject.scaledFont(); const ShadowList* shadowList = style.textShadow(); GraphicsContext* context = paintInfo.context; // Text shadows are disabled when printing. http://crbug.com/258321 bool hasShadow = shadowList && !context->printing(); FloatPoint textOrigin(fragment.x, fragment.y); FloatSize textSize(fragment.width, fragment.height); AffineTransform paintServerTransform; const AffineTransform* additionalPaintServerTransform = 0; GraphicsContextStateSaver stateSaver(*context, false); if (scalingFactor != 1) { textOrigin.scale(scalingFactor, scalingFactor); textSize.scale(scalingFactor); stateSaver.save(); context->scale(1 / scalingFactor, 1 / scalingFactor); // Adjust the paint-server coordinate space. paintServerTransform.scale(scalingFactor); additionalPaintServerTransform = &paintServerTransform; } SkPaint paint; if (!SVGPaintContext::paintForLayoutObject(paintInfo, style, m_svgInlineTextBox.parent()->layoutObject(), resourceMode, paint, additionalPaintServerTransform)) return; paint.setAntiAlias(true); if (hasShadow) { OwnPtr<DrawLooperBuilder> drawLooperBuilder = shadowList->createDrawLooper(DrawLooperBuilder::ShadowRespectsAlpha, style.visitedDependentColor(CSSPropertyColor)); RefPtr<SkDrawLooper> drawLooper = drawLooperBuilder->detachDrawLooper(); paint.setLooper(drawLooper.get()); } if (resourceMode == ApplyToStrokeMode) { StrokeData strokeData; SVGLayoutSupport::applyStrokeStyleToStrokeData(strokeData, style, m_svgInlineTextBox.parent()->layoutObject()); if (style.svgStyle().vectorEffect() != VE_NON_SCALING_STROKE) strokeData.setThickness(strokeData.thickness() * scalingFactor); strokeData.setupPaint(&paint); } TextRunPaintInfo textRunPaintInfo(textRun); textRunPaintInfo.from = startPosition; textRunPaintInfo.to = endPosition; float baseline = scaledFont.fontMetrics().floatAscent(); textRunPaintInfo.bounds = FloatRect(textOrigin.x(), textOrigin.y() - baseline, textSize.width(), textSize.height()); context->drawText(scaledFont, textRunPaintInfo, textOrigin, paint); }
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(); } } }