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); }
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); }