bool SVGClipPainter::prepareEffect(const LayoutObject& target, const FloatRect& targetBoundingBox,
    const FloatRect& paintInvalidationRect, GraphicsContext& context, ClipperState& clipperState)
{
    ASSERT(clipperState == ClipperNotApplied);
    ASSERT_WITH_SECURITY_IMPLICATION(!m_clip.needsLayout());

    m_clip.clearInvalidationMask();

    if (paintInvalidationRect.isEmpty() || m_clip.hasCycle())
        return false;

    SVGClipExpansionCycleHelper inClipExpansionChange(m_clip);

    AffineTransform animatedLocalTransform = toSVGClipPathElement(m_clip.element())->calculateAnimatedLocalTransform();
    // When drawing a clip for non-SVG elements, the CTM does not include the zoom factor.
    // In this case, we need to apply the zoom scale explicitly - but only for clips with
    // userSpaceOnUse units (the zoom is accounted for objectBoundingBox-resolved lengths).
    if (!target.isSVG() && m_clip.clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) {
        ASSERT(m_clip.style());
        animatedLocalTransform.scale(m_clip.style()->effectiveZoom());
    }

    // First, try to apply the clip as a clipPath.
    Path clipPath;
    if (m_clip.asPath(animatedLocalTransform, targetBoundingBox, clipPath)) {
        clipperState = ClipperAppliedPath;
        context.getPaintController().createAndAppend<BeginClipPathDisplayItem>(target, clipPath);
        return true;
    }

    // Fall back to masking.
    clipperState = ClipperAppliedMask;

    // Begin compositing the clip mask.
    CompositingRecorder::beginCompositing(context, target, SkXfermode::kSrcOver_Mode, 1, &paintInvalidationRect);
    {
        if (!drawClipAsMask(context, target, targetBoundingBox, paintInvalidationRect, animatedLocalTransform)) {
            // End the clip mask's compositor.
            CompositingRecorder::endCompositing(context, target);
            return false;
        }
    }

    // Masked content layer start.
    CompositingRecorder::beginCompositing(context, target, SkXfermode::kSrcIn_Mode, 1, &paintInvalidationRect);

    return true;
}
Exemplo n.º 2
0
bool SVGClipPainter::prepareEffect(const LayoutObject& target,
                                   const FloatRect& targetBoundingBox,
                                   const FloatRect& visualRect,
                                   const FloatPoint& layerPositionOffset,
                                   GraphicsContext& context,
                                   ClipperState& clipperState) {
  DCHECK_EQ(clipperState, ClipperState::NotApplied);
  SECURITY_DCHECK(!m_clip.needsLayout());

  m_clip.clearInvalidationMask();

  if (m_clip.hasCycle())
    return false;

  SVGClipExpansionCycleHelper inClipExpansionChange(m_clip);

  AffineTransform animatedLocalTransform =
      toSVGClipPathElement(m_clip.element())
          ->calculateTransform(SVGElement::IncludeMotionTransform);
  // When drawing a clip for non-SVG elements, the CTM does not include the zoom
  // factor.  In this case, we need to apply the zoom scale explicitly - but
  // only for clips with userSpaceOnUse units (the zoom is accounted for
  // objectBoundingBox-resolved lengths).
  if (!target.isSVG() &&
      m_clip.clipPathUnits() == SVGUnitTypes::kSvgUnitTypeUserspaceonuse) {
    DCHECK(m_clip.style());
    animatedLocalTransform.scale(m_clip.style()->effectiveZoom());
  }

  // First, try to apply the clip as a clipPath.
  Path clipPath;
  if (m_clip.asPath(animatedLocalTransform, targetBoundingBox, clipPath)) {
    AffineTransform positionTransform;
    positionTransform.translate(layerPositionOffset.x(),
                                layerPositionOffset.y());
    clipPath.transform(positionTransform);
    clipperState = ClipperState::AppliedPath;
    context.getPaintController().createAndAppend<BeginClipPathDisplayItem>(
        target, clipPath);
    return true;
  }

  // Fall back to masking.
  clipperState = ClipperState::AppliedMask;

  // Begin compositing the clip mask.
  CompositingRecorder::beginCompositing(context, target, SkBlendMode::kSrcOver,
                                        1, &visualRect);
  {
    if (!drawClipAsMask(context, target, targetBoundingBox, visualRect,
                        animatedLocalTransform, layerPositionOffset)) {
      // End the clip mask's compositor.
      CompositingRecorder::endCompositing(context, target);
      return false;
    }
  }

  // Masked content layer start.
  CompositingRecorder::beginCompositing(context, target, SkBlendMode::kSrcIn, 1,
                                        &visualRect);

  return true;
}