Пример #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);
}
Пример #2
0
void OpaqueRegionSkia::didDrawPoints(const PlatformContextSkia* context, const AffineTransform& transform, SkCanvas::PointMode mode, int numPoints, const SkPoint points[], const SkPaint& paint)
{
    if (!numPoints)
        return;

    SkRect rect;
    rect.fLeft = points[0].fX;
    rect.fRight = points[0].fX + 1;
    rect.fTop = points[0].fY;
    rect.fBottom = points[0].fY + 1;

    for (int i = 1; i < numPoints; ++i) {
        rect.fLeft = std::min(rect.fLeft, points[i].fX);
        rect.fRight = std::max(rect.fRight, points[i].fX + 1);
        rect.fTop = std::min(rect.fTop, points[i].fY);
        rect.fBottom = std::max(rect.fBottom, points[i].fY + 1);
    }

    bool opaque = paintIsOpaque(paint);
    bool fillsBounds = false;

    if (!paint.canComputeFastBounds())
        didDrawUnbounded(paint, opaque);
    else {
        rect = paint.computeFastBounds(rect, &rect);
        didDraw(context, transform, rect, paint, opaque, fillsBounds);
    }
}
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);
}
Пример #5
0
void OpaqueRegionSkia::didDrawUnbounded(const SkPaint& paint)
{
    // 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;

    bool checkFillOnly = false;
    if (m_canvasLayerStack.isEmpty()) {
        bool lastLayerDrawsOpaque = paintIsOpaque(paint, 0, checkFillOnly);
        preservesOpaque = xfermodePreservesOpaque(paint, lastLayerDrawsOpaque);
    } else {
        bool lastLayerDrawsOpaque = paintIsOpaque(m_canvasLayerStack[0].paint, 0, checkFillOnly);
        preservesOpaque = xfermodePreservesOpaque(m_canvasLayerStack[0].paint, lastLayerDrawsOpaque);
    }

    if (!preservesOpaque) {
        // We don't know what was drawn on so just destroy the known opaque area.
        m_opaqueRect = SkRect::MakeEmpty();
    }
}
Пример #6
0
void OpaqueRegionSkia::didDrawRect(const PlatformContextSkia* context, const AffineTransform& transform, const SkRect& fillRect, const SkPaint& paint, const SkBitmap* bitmap)
{
    // Any stroking may put alpha in pixels even if the filling part does not.
    if (paint.getStyle() != SkPaint::kFill_Style) {
        bool opaque = paintIsOpaque(paint, bitmap);
        bool fillsBounds = false;

        if (!paint.canComputeFastBounds())
            didDrawUnbounded(paint, opaque);
        else {
            SkRect strokeRect;
            strokeRect = paint.computeFastBounds(fillRect, &strokeRect);
            didDraw(context, transform, strokeRect, paint, opaque, fillsBounds);
        }
    }

    bool checkFillOnly = true;
    bool opaque = paintIsOpaque(paint, bitmap, checkFillOnly);
    bool fillsBounds = paint.getStyle() != SkPaint::kStroke_Style;
    didDraw(context, transform, fillRect, paint, opaque, fillsBounds);
}
void OpaqueRegionSkia::didDrawUnbounded(const GraphicsContext* context, const SkPaint& paint, DrawType drawType)
{
    bool drawsOpaque = paintIsOpaque(paint, drawType, 0);
    bool preservesOpaque = xfermodePreservesOpaque(paint, drawsOpaque);

    if (preservesOpaque)
        return;

    SkRect deviceClipRect;
    getDeviceClipAsRect(context, deviceClipRect);
    markRectAsNonOpaque(deviceClipRect);
}
Пример #8
0
void OpaqueRegionSkia::didDrawBounded(const PlatformContextSkia* context, const AffineTransform& transform, const SkRect& bounds, const SkPaint& paint)
{
    bool opaque = paintIsOpaque(paint);
    bool fillsBounds = false;

    if (!paint.canComputeFastBounds())
        didDrawUnbounded(paint, opaque);
    else {
        SkRect rect;
        rect = paint.computeFastBounds(bounds, &rect);
        didDraw(context, transform, rect, paint, opaque, fillsBounds);
    }
}
Пример #9
0
void OpaqueRegionSkia::didDrawPath(const PlatformContextSkia* context, const AffineTransform& transform, const SkPath& path, const SkPaint& paint)
{
    SkRect rect;
    if (path.isRect(&rect)) {
        didDrawRect(context, transform, rect, paint, 0);
        return;
    }

    bool opaque = paintIsOpaque(paint);
    bool fillsBounds = false;

    if (!paint.canComputeFastBounds())
        didDrawUnbounded(paint, opaque);
    else {
        rect = paint.computeFastBounds(path.getBounds(), &rect);
        didDraw(context, transform, rect, paint, opaque, fillsBounds);
    }
}