Merge "Emulate replace clip ops using SkAndroidFrameworkUtils::ResetClip"
This commit is contained in:
committed by
Android (Google) Code Review
commit
f19b1dfd60
@@ -27,6 +27,7 @@ X(ClipPath)
|
||||
X(ClipRect)
|
||||
X(ClipRRect)
|
||||
X(ClipRegion)
|
||||
X(ResetClip)
|
||||
X(DrawPaint)
|
||||
X(DrawBehind)
|
||||
X(DrawPath)
|
||||
|
||||
@@ -187,6 +187,11 @@ struct ClipRegion final : Op {
|
||||
SkClipOp op;
|
||||
void draw(SkCanvas* c, const SkMatrix&) const { c->clipRegion(region, op); }
|
||||
};
|
||||
struct ResetClip final : Op {
|
||||
static const auto kType = Type::ResetClip;
|
||||
ResetClip() {}
|
||||
void draw(SkCanvas* c, const SkMatrix&) const { SkAndroidFrameworkUtils::ResetClip(c); }
|
||||
};
|
||||
|
||||
struct DrawPaint final : Op {
|
||||
static const auto kType = Type::DrawPaint;
|
||||
@@ -662,6 +667,9 @@ void DisplayListData::clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
|
||||
void DisplayListData::clipRegion(const SkRegion& region, SkClipOp op) {
|
||||
this->push<ClipRegion>(0, region, op);
|
||||
}
|
||||
void DisplayListData::resetClip() {
|
||||
this->push<ResetClip>(0);
|
||||
}
|
||||
|
||||
void DisplayListData::drawPaint(const SkPaint& paint) {
|
||||
this->push<DrawPaint>(0, paint);
|
||||
@@ -969,6 +977,14 @@ void RecordingCanvas::onClipRegion(const SkRegion& region, SkClipOp op) {
|
||||
fDL->clipRegion(region, op);
|
||||
this->INHERITED::onClipRegion(region, op);
|
||||
}
|
||||
void RecordingCanvas::onResetClip() {
|
||||
// This is part of "replace op" emulation, but rely on the following intersection
|
||||
// clip to potentially mark the clip as complex. If we are already complex, we do
|
||||
// not reset the complexity so that we don't break the contract that no higher
|
||||
// save point has a complex clip when "not complex".
|
||||
fDL->resetClip();
|
||||
this->INHERITED::onResetClip();
|
||||
}
|
||||
|
||||
void RecordingCanvas::onDrawPaint(const SkPaint& paint) {
|
||||
fDL->drawPaint(paint);
|
||||
|
||||
@@ -97,6 +97,7 @@ private:
|
||||
void clipRect(const SkRect&, SkClipOp, bool aa);
|
||||
void clipRRect(const SkRRect&, SkClipOp, bool aa);
|
||||
void clipRegion(const SkRegion&, SkClipOp);
|
||||
void resetClip();
|
||||
|
||||
void drawPaint(const SkPaint&);
|
||||
void drawBehind(const SkPaint&);
|
||||
@@ -169,6 +170,7 @@ public:
|
||||
void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;
|
||||
void onClipPath(const SkPath&, SkClipOp, ClipEdgeStyle) override;
|
||||
void onClipRegion(const SkRegion&, SkClipOp) override;
|
||||
void onResetClip() override;
|
||||
|
||||
void onDrawPaint(const SkPaint&) override;
|
||||
void onDrawBehind(const SkPaint&) override;
|
||||
|
||||
@@ -396,6 +396,22 @@ bool SkiaCanvas::clipPath(const SkPath* path, SkClipOp op) {
|
||||
return !mCanvas->isClipEmpty();
|
||||
}
|
||||
|
||||
bool SkiaCanvas::replaceClipRect_deprecated(float left, float top, float right, float bottom) {
|
||||
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
|
||||
|
||||
// Emulated clip rects are not recorded for partial saves, since
|
||||
// partial saves have been removed from the public API.
|
||||
SkAndroidFrameworkUtils::ResetClip(mCanvas);
|
||||
mCanvas->clipRect(rect, SkClipOp::kIntersect);
|
||||
return !mCanvas->isClipEmpty();
|
||||
}
|
||||
|
||||
bool SkiaCanvas::replaceClipPath_deprecated(const SkPath* path) {
|
||||
SkAndroidFrameworkUtils::ResetClip(mCanvas);
|
||||
mCanvas->clipPath(*path, SkClipOp::kIntersect, true);
|
||||
return !mCanvas->isClipEmpty();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas state operations: Filters
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -94,6 +94,9 @@ public:
|
||||
virtual bool quickRejectPath(const SkPath& path) const override;
|
||||
virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) override;
|
||||
virtual bool clipPath(const SkPath* path, SkClipOp op) override;
|
||||
virtual bool replaceClipRect_deprecated(float left, float top, float right,
|
||||
float bottom) override;
|
||||
virtual bool replaceClipPath_deprecated(const SkPath* path) override;
|
||||
|
||||
virtual PaintFilter* getPaintFilter() override;
|
||||
virtual void setPaintFilter(sk_sp<PaintFilter> paintFilter) override;
|
||||
|
||||
@@ -54,13 +54,10 @@ bool CanvasStateHelper::internalSave(SaveEntry saveEntry) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Assert that the cast from SkClipOp to SkRegion::Op is valid
|
||||
// Assert that the cast from SkClipOp to SkRegion::Op is valid.
|
||||
// SkClipOp is a subset of SkRegion::Op and only supports difference and intersect.
|
||||
static_assert(static_cast<int>(SkClipOp::kDifference) == SkRegion::Op::kDifference_Op);
|
||||
static_assert(static_cast<int>(SkClipOp::kIntersect) == SkRegion::Op::kIntersect_Op);
|
||||
static_assert(static_cast<int>(SkClipOp::kUnion_deprecated) == SkRegion::Op::kUnion_Op);
|
||||
static_assert(static_cast<int>(SkClipOp::kXOR_deprecated) == SkRegion::Op::kXOR_Op);
|
||||
static_assert(static_cast<int>(SkClipOp::kReverseDifference_deprecated) == SkRegion::Op::kReverseDifference_Op);
|
||||
static_assert(static_cast<int>(SkClipOp::kReplace_deprecated) == SkRegion::Op::kReplace_Op);
|
||||
|
||||
void CanvasStateHelper::internalClipRect(const SkRect& rect, SkClipOp op) {
|
||||
clip().opRect(rect, transform(), mInitialBounds, (SkRegion::Op)op, false);
|
||||
|
||||
@@ -185,6 +185,12 @@ public:
|
||||
|
||||
virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) = 0;
|
||||
virtual bool clipPath(const SkPath* path, SkClipOp op) = 0;
|
||||
// Resets clip to wide open, used to emulate the now-removed SkClipOp::kReplace on
|
||||
// apps with compatibility < P. Canvases for version P and later are restricted to
|
||||
// intersect and difference at the Java level, matching SkClipOp's definition.
|
||||
// NOTE: These functions are deprecated and will be removed in a future release
|
||||
virtual bool replaceClipRect_deprecated(float left, float top, float right, float bottom) = 0;
|
||||
virtual bool replaceClipPath_deprecated(const SkPath* path) = 0;
|
||||
|
||||
// filters
|
||||
virtual PaintFilter* getPaintFilter() = 0;
|
||||
|
||||
@@ -188,14 +188,10 @@ static jboolean quickRejectPath(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jl
|
||||
return result ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
// SkRegion::Op and SkClipOp are numerically identical, so we can freely cast
|
||||
// from one to the other (though SkClipOp is destined to become a strict subset)
|
||||
// SkClipOp is a strict subset of SkRegion::Op and is castable back and forth for their
|
||||
// shared operations (intersect and difference).
|
||||
static_assert(SkRegion::kDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kDifference), "");
|
||||
static_assert(SkRegion::kIntersect_Op == static_cast<SkRegion::Op>(SkClipOp::kIntersect), "");
|
||||
static_assert(SkRegion::kUnion_Op == static_cast<SkRegion::Op>(SkClipOp::kUnion_deprecated), "");
|
||||
static_assert(SkRegion::kXOR_Op == static_cast<SkRegion::Op>(SkClipOp::kXOR_deprecated), "");
|
||||
static_assert(SkRegion::kReverseDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kReverseDifference_deprecated), "");
|
||||
static_assert(SkRegion::kReplace_Op == static_cast<SkRegion::Op>(SkClipOp::kReplace_deprecated), "");
|
||||
|
||||
static jboolean clipRect(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jfloat l, jfloat t,
|
||||
jfloat r, jfloat b, jint opHandle) {
|
||||
@@ -203,16 +199,16 @@ static jboolean clipRect(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jfloat l,
|
||||
SkRegion::Op rgnOp = static_cast<SkRegion::Op>(opHandle);
|
||||
bool nonEmptyClip;
|
||||
switch (rgnOp) {
|
||||
case SkRegion::Op::kReplace_Op:
|
||||
// For now replace can still be handled as an SkClipOp but will be emulated in the
|
||||
// future
|
||||
[[fallthrough]];
|
||||
case SkRegion::Op::kIntersect_Op:
|
||||
case SkRegion::Op::kDifference_Op:
|
||||
// Intersect and difference are supported clip operations
|
||||
nonEmptyClip =
|
||||
get_canvas(canvasHandle)->clipRect(l, t, r, b, static_cast<SkClipOp>(rgnOp));
|
||||
break;
|
||||
case SkRegion::Op::kReplace_Op:
|
||||
// Replace is emulated to support legacy apps older than P
|
||||
nonEmptyClip = get_canvas(canvasHandle)->replaceClipRect_deprecated(l, t, r, b);
|
||||
break;
|
||||
default:
|
||||
// All other operations would expand the clip and are no longer supported,
|
||||
// so log and skip (to avoid breaking legacy apps).
|
||||
@@ -230,14 +226,13 @@ static jboolean clipPath(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jlong pat
|
||||
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
|
||||
bool nonEmptyClip;
|
||||
switch (rgnOp) {
|
||||
case SkRegion::Op::kReplace_Op:
|
||||
// For now replace can still be handled as an SkClipOp but will be emulated in the
|
||||
// future
|
||||
[[fallthrough]];
|
||||
case SkRegion::Op::kIntersect_Op:
|
||||
case SkRegion::Op::kDifference_Op:
|
||||
nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, static_cast<SkClipOp>(rgnOp));
|
||||
break;
|
||||
case SkRegion::Op::kReplace_Op:
|
||||
nonEmptyClip = get_canvas(canvasHandle)->replaceClipPath_deprecated(path);
|
||||
break;
|
||||
default:
|
||||
ALOGW("Ignoring unsupported clip operation %d", opHandle);
|
||||
SkRect clipBounds; // ignored
|
||||
|
||||
@@ -52,6 +52,8 @@ protected:
|
||||
mOutput << mIdent << "clipRegion" << std::endl;
|
||||
}
|
||||
|
||||
void onResetClip() override { mOutput << mIdent << "resetClip" << std::endl; }
|
||||
|
||||
void onDrawPaint(const SkPaint&) override { mOutput << mIdent << "drawPaint" << std::endl; }
|
||||
|
||||
void onDrawPath(const SkPath&, const SkPaint&) override {
|
||||
|
||||
@@ -382,7 +382,7 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clip_replace) {
|
||||
std::vector<sp<RenderNode>> nodes;
|
||||
nodes.push_back(TestUtils::createSkiaNode(
|
||||
20, 20, 30, 30, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
|
||||
canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace_deprecated);
|
||||
canvas.replaceClipRect_deprecated(0, -20, 10, 30);
|
||||
canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
|
||||
}));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user