Example #1
0
void OpaqueRegionSkia::didDraw(const PlatformContextSkia* context, const SkRect& rect, const SkPaint& paint, const SkBitmap* sourceBitmap, bool fillsBounds, DrawType drawType)
{
    SkRect targetRect = rect;

    // Apply the transform to device coordinate space.
    SkMatrix canvasTransform = context->canvas()->getTotalMatrix();
    if (!canvasTransform.mapRect(&targetRect))
        fillsBounds = false;

    // Apply the current clip in device coordinate space.
    if (context->canvas()->getClipType() != SkCanvas::kRect_ClipType)
        fillsBounds = false;
    else {
        SkIRect deviceClip;
        if (!context->canvas()->getClipDeviceBounds(&deviceClip))
            return;
        if (!targetRect.intersect(SkIntToScalar(deviceClip.fLeft), SkIntToScalar(deviceClip.fTop), SkIntToScalar(deviceClip.fRight), SkIntToScalar(deviceClip.fBottom)))
            return;
    }

    bool checkFillOnly = drawType == FillOnly;
    bool lastLayerDrawsOpaque = paintIsOpaque(paint, sourceBitmap, checkFillOnly);

    bool xfersOpaque = xfermodeIsOpaque(paint, lastLayerDrawsOpaque);

    // Apply the SkCanvas layers we will be drawing through.
    for (size_t i = m_canvasLayerStack.size(); i > 0; --i) {
        const CanvasLayerState& canvasLayer = m_canvasLayerStack[i-1];

        // FIXME: We could still track the opaque part but it's always empty right now anyways.
        if (canvasLayer.hasImageMask && !canvasLayer.imageOpaqueRect.contains(targetRect))
            fillsBounds = false;

        bool checkFillOnly = drawType == FillOnly;
        lastLayerDrawsOpaque = paintIsOpaque(canvasLayer.paint, 0, checkFillOnly);
        // If any layer doesn't paint opaque, then the result will not be opaque.
        xfersOpaque &= xfermodeIsOpaque(canvasLayer.paint, lastLayerDrawsOpaque);
    }

    // Preserving opaque only matters for the bottom-most layer. Its contents are either opaque or not, and if not
    // then we care if it preserves the opaqueness of the target device when it is drawn into the device.
    bool preservesOpaque;
    if (m_canvasLayerStack.isEmpty())
        preservesOpaque = xfermodePreservesOpaque(paint, lastLayerDrawsOpaque);
    else
        preservesOpaque = xfermodePreservesOpaque(m_canvasLayerStack[0].paint, lastLayerDrawsOpaque);

    if (fillsBounds && xfersOpaque)
        markRectAsOpaque(targetRect);
    else if (SkRect::Intersects(targetRect, m_opaqueRect) && !preservesOpaque)
        markRectAsNonOpaque(targetRect);
}
Example #2
0
void OpaqueRegionSkia::didDraw(const PlatformContextSkia* context, const AffineTransform& transform, const SkRect& rect, const SkPaint& paint, bool drawsOpaque, bool fillsBounds)
{
    SkRect targetRect = rect;

    // Apply the transform to device coordinate space.
    SkMatrix canvasTransform = context->canvas()->getTotalMatrix();
    if (!canvasTransform.mapRect(&targetRect))
        fillsBounds = false;

    // Apply the current clip in device coordinate space.
    if (context->canvas()->getClipType() != SkCanvas::kRect_ClipType)
        fillsBounds = false;
    else {
        SkIRect deviceClip;
        context->canvas()->getClipDeviceBounds(&deviceClip);
        if (!targetRect.intersect(SkIntToScalar(deviceClip.fLeft), SkIntToScalar(deviceClip.fTop), SkIntToScalar(deviceClip.fRight), SkIntToScalar(deviceClip.fBottom)))
            return;
    }
    if (!context->clippedToImage().isOpaque())
        fillsBounds = false;

    // Apply the transform to the tracking space.
    SkMatrix canvasToTargetTransform = transform;
    if (!canvasToTargetTransform.mapRect(&targetRect))
        fillsBounds = false;

    if (fillsBounds && xfermodeIsOpaque(paint, drawsOpaque))
        markRectAsOpaque(targetRect);
    else if (SkRect::Intersects(targetRect, m_opaqueRect) && !xfermodePreservesOpaque(paint, drawsOpaque))
        markRectAsNonOpaque(targetRect);
}
void OpaqueRegionSkia::applyOpaqueRegionFromLayer(const GraphicsContext* context, const SkRect& layerOpaqueRect, const SkPaint& paint)
{
    SkRect deviceClipRect;
    bool deviceClipIsARect = getDeviceClipAsRect(context, deviceClipRect);

    if (deviceClipRect.isEmpty())
        return;

    SkRect sourceOpaqueRect = layerOpaqueRect;
    // Save the opaque area in the destination, so we can preserve the parts of it under the source opaque area if possible.
    SkRect destinationOpaqueRect = currentTrackingOpaqueRect();

    bool outsideSourceOpaqueRectPreservesOpaque = xfermodePreservesOpaque(paint, false);
    if (!outsideSourceOpaqueRectPreservesOpaque)
        markRectAsNonOpaque(deviceClipRect);

    if (!deviceClipIsARect)
        return;
    if (!sourceOpaqueRect.intersect(deviceClipRect))
        return;

    bool sourceOpaqueRectDrawsOpaque = paintIsOpaque(paint, FillOnly, 0);
    bool sourceOpaqueRectXfersOpaque = xfermodeIsOpaque(paint, sourceOpaqueRectDrawsOpaque);
    bool sourceOpaqueRectPreservesOpaque = xfermodePreservesOpaque(paint, sourceOpaqueRectDrawsOpaque);

    // If the layer's opaque area is being drawn opaque in the layer below, then mark it opaque. Otherwise,
    // if it preserves opaque then keep the intersection of the two.
    if (sourceOpaqueRectXfersOpaque)
        markRectAsOpaque(sourceOpaqueRect);
    else if (sourceOpaqueRectPreservesOpaque && sourceOpaqueRect.intersect(destinationOpaqueRect))
        markRectAsOpaque(sourceOpaqueRect);
}
void OpaqueRegionSkia::didDraw(const GraphicsContext* context, const SkRect& rect, const SkPaint& paint, const SkBitmap* sourceBitmap, bool fillsBounds, DrawType drawType)
{
    SkRect targetRect = rect;

    // Apply the transform to device coordinate space.
    SkMatrix canvasTransform = context->canvas()->getTotalMatrix();
    if (!canvasTransform.mapRect(&targetRect))
        fillsBounds = false;

    // Apply the current clip.
    SkRect deviceClipRect;
    if (!getDeviceClipAsRect(context, deviceClipRect))
        fillsBounds = false;
    else if (!targetRect.intersect(deviceClipRect))
        return;

    bool drawsOpaque = paintIsOpaque(paint, drawType, sourceBitmap);
    bool xfersOpaque = xfermodeIsOpaque(paint, drawsOpaque);
    bool preservesOpaque = xfermodePreservesOpaque(paint, drawsOpaque);

    if (fillsBounds && xfersOpaque)
        markRectAsOpaque(targetRect);
    else if (!preservesOpaque)
        markRectAsNonOpaque(targetRect);
}