Exemplo n.º 1
0
void LayoutSVGShape::createPath() {
  if (!m_path)
    m_path = WTF::makeUnique<Path>();
  *m_path = toSVGGeometryElement(element())->asPath();
  if (m_rareData.get())
    m_rareData->m_cachedNonScalingStrokePath.clear();
}
void LayoutSVGShape::createPath()
{
    if (!m_path)
        m_path = adoptPtr(new Path());
    *m_path = toSVGGeometryElement(element())->asPath();
    if (m_rareData.get())
        m_rareData->m_cachedNonScalingStrokePath.clear();
}
Exemplo n.º 3
0
void SVGUseElement::toClipPath(Path& path) const
{
    ASSERT(path.isEmpty());

    const SVGGraphicsElement* element = targetGraphicsElementForClipping();

    if (!element)
        return;

    if (element->isSVGGeometryElement()) {
        toSVGGeometryElement(*element).toClipPath(path);
        // FIXME: Avoid manual resolution of x/y here. Its potentially harmful.
        SVGLengthContext lengthContext(this);
        path.translate(FloatSize(m_x->currentValue()->value(lengthContext), m_y->currentValue()->value(lengthContext)));
        path.transform(calculateAnimatedLocalTransform());
    }
}
bool LayoutSVGResourceClipper::calculateClipContentPathIfNeeded()
{
    if (!m_clipContentPath.isEmpty())
        return true;

    // If the current clip-path gets clipped itself, we have to fallback to masking.
    if (style()->svgStyle().hasClipper())
        return false;

    unsigned opCount = 0;
    bool usingBuilder = false;
    SkOpBuilder clipPathBuilder;

    for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
        LayoutObject* childLayoutObject = childElement->layoutObject();
        if (!childLayoutObject)
            continue;
        // Only shapes or paths are supported for direct clipping. We need to fallback to masking for texts.
        if (childLayoutObject->isSVGText()) {
            m_clipContentPath.clear();
            return false;
        }
        if (!childElement->isSVGGraphicsElement())
            continue;

        const ComputedStyle* style = childLayoutObject->style();
        if (!style || style->display() == NONE || style->visibility() != VISIBLE)
            continue;

        // Current shape in clip-path gets clipped too. Fallback to masking.
        if (style->svgStyle().hasClipper()) {
            m_clipContentPath.clear();
            return false;
        }

        // First clip shape.
        if (m_clipContentPath.isEmpty()) {
            if (isSVGGeometryElement(childElement))
                toSVGGeometryElement(childElement)->toClipPath(m_clipContentPath);
            else if (isSVGUseElement(childElement))
                toSVGUseElement(childElement)->toClipPath(m_clipContentPath);

            continue;
        }

        // Multiple shapes require PathOps. In some degenerate cases PathOps can exhibit quadratic
        // behavior, so we cap the number of ops to a reasonable count.
        const unsigned kMaxOps = 42;
        if (!RuntimeEnabledFeatures::pathOpsSVGClippingEnabled() || ++opCount > kMaxOps) {
            m_clipContentPath.clear();
            return false;
        }

        // Second clip shape => start using the builder.
        if (!usingBuilder) {
            clipPathBuilder.add(m_clipContentPath.skPath(), kUnion_SkPathOp);
            usingBuilder = true;
        }

        Path subPath;
        if (isSVGGeometryElement(childElement))
            toSVGGeometryElement(childElement)->toClipPath(subPath);
        else if (isSVGUseElement(childElement))
            toSVGUseElement(childElement)->toClipPath(subPath);

        clipPathBuilder.add(subPath.skPath(), kUnion_SkPathOp);
    }

    if (usingBuilder) {
        SkPath resolvedPath;
        clipPathBuilder.resolve(&resolvedPath);
        m_clipContentPath = resolvedPath;
    }

    return true;
}
Exemplo n.º 5
0
float LayoutSVGShape::dashScaleFactor() const {
  if (!styleRef().svgStyle().strokeDashArray()->size())
    return 1;
  return toSVGGeometryElement(*element()).pathLengthScaleFactor();
}