Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e30b53ce authored by Tom Hudson's avatar Tom Hudson
Browse files

Enter RectangleMode when the clip region is a rectangle

ClipArea's region mode implementation store the region's boundary in
a rectangle, and if the region is that rectangle, set its region to
empty.  This is a bug, since as long as the ClipArea is in region
mode it treats its region as determinitive. When the next clipping
operation comes in, it is tested against the empty region instead of
against the valid rect.

Discovered via Skia GM testing.

Change-Id: I3bbc4e81c8d68636061f830156e017e9b5c7e587
parent b13f44bc
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -234,7 +234,7 @@ bool ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform,
bool ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) {
    enterRegionMode();
    mClipRegion.op(region, op);
    setClipRectToRegionBounds();
    onClipRegionUpdated();
    return true;
}

@@ -263,6 +263,9 @@ void ClipArea::enterRectangleMode() {
bool ClipArea::rectangleModeClipRectWithTransform(const Rect& r,
        const mat4* transform, SkRegion::Op op) {

    // TODO: we should be able to handle kReplace_Op efficiently without
    // going through RegionMode and later falling back into RectangleMode.

    if (op != SkRegion::kIntersect_Op) {
        enterRegionMode();
        return regionModeClipRectWithTransform(r, transform, op);
@@ -324,15 +327,16 @@ bool ClipArea::rectangleListModeClipRectWithTransform(float left, float top,
 */

void ClipArea::enterRegionMode() {
    if (mMode != kModeRegion) {
        if (mMode == kModeRectangle) {
    Mode oldMode = mMode;
    mMode = kModeRegion;
    if (oldMode != kModeRegion) {
        if (oldMode == kModeRectangle) {
            mClipRegion.setRect(mClipRect.left, mClipRect.top,
                    mClipRect.right, mClipRect.bottom);
        } else {
            mClipRegion = mRectangleList.convertToRegion(createViewportRegion());
            setClipRectToRegionBounds();
            onClipRegionUpdated();
        }
        mMode = kModeRegion;
    }
}

@@ -342,7 +346,7 @@ bool ClipArea::regionModeClipRectWithTransform(const Rect& r,
    SkRegion transformedRectRegion;
    regionFromPath(transformedRect, transformedRectRegion);
    mClipRegion.op(transformedRectRegion, op);
    setClipRectToRegionBounds();
    onClipRegionUpdated();
    return true;
}

@@ -352,12 +356,13 @@ bool ClipArea::regionModeClipRectWithTransform(float left, float top,
            transform, op);
}

void ClipArea::setClipRectToRegionBounds() {
void ClipArea::onClipRegionUpdated() {
    if (!mClipRegion.isEmpty()) {
        mClipRect.set(mClipRegion.getBounds());

        if (mClipRegion.isRect()) {
            mClipRegion.setEmpty();
            enterRectangleMode();
        }
    } else {
        mClipRect.setEmpty();
+1 −1
Original line number Diff line number Diff line
@@ -144,7 +144,7 @@ private:
            float bottom, const mat4* transform, SkRegion::Op op);

    void ensureClipRegion();
    void setClipRectToRegionBounds();
    void onClipRegionUpdated();
    bool clipRegionOp(float left, float top, float right, float bottom,
            SkRegion::Op op);