예제 #1
0
void SVGLayoutSupport::applyStrokeStyleToStrokeData(StrokeData& strokeData,
                                                    const ComputedStyle& style,
                                                    const LayoutObject& object,
                                                    float dashScaleFactor) {
  ASSERT(object.node());
  ASSERT(object.node()->isSVGElement());

  const SVGComputedStyle& svgStyle = style.svgStyle();

  SVGLengthContext lengthContext(toSVGElement(object.node()));
  strokeData.setThickness(lengthContext.valueForLength(svgStyle.strokeWidth()));
  strokeData.setLineCap(svgStyle.capStyle());
  strokeData.setLineJoin(svgStyle.joinStyle());
  strokeData.setMiterLimit(svgStyle.strokeMiterLimit());

  DashArray dashArray =
      resolveSVGDashArray(*svgStyle.strokeDashArray(), style, lengthContext);
  float dashOffset =
      lengthContext.valueForLength(svgStyle.strokeDashOffset(), style);
  // Apply scaling from 'pathLength'.
  if (dashScaleFactor != 1) {
    ASSERT(dashScaleFactor >= 0);
    dashOffset *= dashScaleFactor;
    for (auto& dashItem : dashArray)
      dashItem *= dashScaleFactor;
  }
  strokeData.setLineDash(dashArray, dashOffset);
}
예제 #2
0
void SVGLayoutSupport::applyStrokeStyleToStrokeData(StrokeData& strokeData, const ComputedStyle& style, const LayoutObject& object)
{
    ASSERT(object.node());
    ASSERT(object.node()->isSVGElement());

    const SVGComputedStyle& svgStyle = style.svgStyle();

    SVGLengthContext lengthContext(toSVGElement(object.node()));
    strokeData.setThickness(lengthContext.valueForLength(svgStyle.strokeWidth()));
    strokeData.setLineCap(svgStyle.capStyle());
    strokeData.setLineJoin(svgStyle.joinStyle());
    strokeData.setMiterLimit(svgStyle.strokeMiterLimit());

    DashArray dashArray = resolveSVGDashArray(*svgStyle.strokeDashArray(), style, lengthContext);
    strokeData.setLineDash(dashArray, lengthContext.valueForLength(svgStyle.strokeDashOffset(), style));
}
예제 #3
0
파일: Path.cpp 프로젝트: coinpayee/blink
FloatRect Path::strokeBoundingRect(const StrokeData& strokeData) const
{
    SkPaint paint;
    strokeData.setupPaint(&paint);
    SkPath boundingPath;
    paint.getFillPath(m_path, &boundingPath);

    return boundingPath.getBounds();
}
예제 #4
0
파일: Path.cpp 프로젝트: coinpayee/blink
bool Path::strokeContains(const FloatPoint& point, const StrokeData& strokeData) const
{
    SkPaint paint;
    strokeData.setupPaint(&paint);
    SkPath strokePath;
    paint.getFillPath(m_path, &strokePath);

    return SkPathContainsPoint(strokePath, point, SkPath::kWinding_FillType);
}
void CanvasRenderingContext2D::drawFocusRing(const Path& path) {
  m_usageCounters.numDrawFocusCalls++;
  if (!drawingCanvas())
    return;

  SkColor color = LayoutTheme::theme().focusRingColor().rgb();
  const int focusRingWidth = 5;

  drawPlatformFocusRing(path.getSkPath(), drawingCanvas(), color,
                        focusRingWidth);

  // We need to add focusRingWidth to dirtyRect.
  StrokeData strokeData;
  strokeData.setThickness(focusRingWidth);

  SkIRect dirtyRect;
  if (!computeDirtyRect(path.strokeBoundingRect(strokeData), &dirtyRect))
    return;

  didDraw(dirtyRect);
}
예제 #6
0
파일: Path.cpp 프로젝트: mirror/chromium
// FIXME: this method ignores the CTM and may yield inaccurate results for large
// scales.
SkPath Path::strokePath(const StrokeData& strokeData) const {
  SkPaint paint;
  strokeData.setupPaint(&paint);

  // Skia stroke resolution scale. This is multiplied by 4 internally
  // (i.e. 1.0 corresponds to 1/4 pixel res).
  static const SkScalar kResScale = 0.3f;

  SkPath strokePath;
  paint.getFillPath(m_path, &strokePath, nullptr, kResScale);

  return strokePath;
}
void SVGShapePainter::paint(const PaintInfo& paintInfo)
{
    if (paintInfo.phase != PaintPhaseForeground
        || m_layoutSVGShape.style()->visibility() == HIDDEN
        || m_layoutSVGShape.isShapeEmpty())
        return;

    FloatRect boundingBox = m_layoutSVGShape.paintInvalidationRectInLocalCoordinates();
    if (!paintInfo.cullRect().intersectsCullRect(m_layoutSVGShape.localTransform(), boundingBox))
        return;

    PaintInfo paintInfoBeforeFiltering(paintInfo);
    // Shapes cannot have children so do not call updateCullRect.
    TransformRecorder transformRecorder(paintInfoBeforeFiltering.context, m_layoutSVGShape, m_layoutSVGShape.localTransform());
    {
        SVGPaintContext paintContext(m_layoutSVGShape, paintInfoBeforeFiltering);
        if (paintContext.applyClipMaskAndFilterIfNecessary() && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintContext.paintInfo().context, m_layoutSVGShape, paintContext.paintInfo().phase, LayoutPoint())) {
            LayoutObjectDrawingRecorder recorder(paintContext.paintInfo().context, m_layoutSVGShape, paintContext.paintInfo().phase, boundingBox, LayoutPoint());
            const SVGComputedStyle& svgStyle = m_layoutSVGShape.style()->svgStyle();

            bool shouldAntiAlias = svgStyle.shapeRendering() != SR_CRISPEDGES;

            for (int i = 0; i < 3; i++) {
                switch (svgStyle.paintOrderType(i)) {
                case PT_FILL: {
                    SkPaint fillPaint;
                    if (!SVGPaintContext::paintForLayoutObject(paintContext.paintInfo(), m_layoutSVGShape.styleRef(), m_layoutSVGShape, ApplyToFillMode, fillPaint))
                        break;
                    fillPaint.setAntiAlias(shouldAntiAlias);
                    fillShape(paintContext.paintInfo().context, fillPaint, fillRuleFromStyle(paintContext.paintInfo(), svgStyle));
                    break;
                }
                case PT_STROKE:
                    if (svgStyle.hasVisibleStroke()) {
                        GraphicsContextStateSaver stateSaver(paintContext.paintInfo().context, false);
                        AffineTransform nonScalingTransform;
                        const AffineTransform* additionalPaintServerTransform = 0;

                        if (m_layoutSVGShape.hasNonScalingStroke()) {
                            nonScalingTransform = m_layoutSVGShape.nonScalingStrokeTransform();
                            if (!setupNonScalingStrokeContext(nonScalingTransform, stateSaver))
                                return;

                            // Non-scaling stroke needs to reset the transform back to the host transform.
                            additionalPaintServerTransform = &nonScalingTransform;
                        }

                        SkPaint strokePaint;
                        if (!SVGPaintContext::paintForLayoutObject(paintContext.paintInfo(), m_layoutSVGShape.styleRef(), m_layoutSVGShape, ApplyToStrokeMode, strokePaint, additionalPaintServerTransform))
                            break;
                        strokePaint.setAntiAlias(shouldAntiAlias);

                        StrokeData strokeData;
                        SVGLayoutSupport::applyStrokeStyleToStrokeData(strokeData, m_layoutSVGShape.styleRef(), m_layoutSVGShape, m_layoutSVGShape.dashScaleFactor());
                        strokeData.setupPaint(&strokePaint);

                        strokeShape(paintContext.paintInfo().context, strokePaint);
                    }
                    break;
                case PT_MARKERS:
                    paintMarkers(paintContext.paintInfo(), boundingBox);
                    break;
                default:
                    ASSERT_NOT_REACHED();
                    break;
                }
            }
        }
    }

    if (m_layoutSVGShape.style()->outlineWidth()) {
        PaintInfo outlinePaintInfo(paintInfoBeforeFiltering);
        outlinePaintInfo.phase = PaintPhaseSelfOutlineOnly;
        ObjectPainter(m_layoutSVGShape).paintOutline(outlinePaintInfo, LayoutPoint(boundingBox.location()));
    }
}
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();
        }
    }
}