예제 #1
0
bool SkRasterClip::op(const SkPath& path, const SkMatrix& matrix, const SkIRect& bounds,
                      SkRegion::Op op, bool doAA) {
    AUTO_RASTERCLIP_VALIDATE(*this);

    if (fForceConservativeRects) {
        SkIRect ir;
        switch (mutate_conservative_op(&op, path.isInverseFillType())) {
            case kDoNothing_MutateResult:
                return !this->isEmpty();
            case kReplaceClippedAgainstGlobalBounds_MutateResult:
                ir = bounds;
                break;
            case kContinue_MutateResult: {
                SkRect bounds = path.getBounds();
                matrix.mapRect(&bounds);
                ir = bounds.roundOut();
                break;
            }
        }
        return this->op(ir, op);
    }

    // base is used to limit the size (and therefore memory allocation) of the
    // region that results from scan converting devPath.
    SkRegion base;

    SkPath devPath;
    if (matrix.isIdentity()) {
        devPath = path;
    } else {
        path.transform(matrix, &devPath);
        devPath.setIsVolatile(true);
    }
    if (SkRegion::kIntersect_Op == op) {
        // since we are intersect, we can do better (tighter) with currRgn's
        // bounds, than just using the device. However, if currRgn is complex,
        // our region blitter may hork, so we do that case in two steps.
        if (this->isRect()) {
            // FIXME: we should also be able to do this when this->isBW(),
            // but relaxing the test above triggers GM asserts in
            // SkRgnBuilder::blitH(). We need to investigate what's going on.
            return this->setPath(devPath, this->bwRgn(), doAA);
        } else {
            base.setRect(this->getBounds());
            SkRasterClip clip(fForceConservativeRects);
            clip.setPath(devPath, base, doAA);
            return this->op(clip, op);
        }
    } else {
        base.setRect(bounds);

        if (SkRegion::kReplace_Op == op) {
            return this->setPath(devPath, base, doAA);
        } else {
            SkRasterClip clip(fForceConservativeRects);
            clip.setPath(devPath, base, doAA);
            return this->op(clip, op);
        }
    }
}
예제 #2
0
bool SkRasterClip::op(const SkRect& localRect, const SkMatrix& matrix, const SkIRect& bounds,
                      SkRegion::Op op, bool doAA) {
    AUTO_RASTERCLIP_VALIDATE(*this);
    SkRect devRect;

    if (fForceConservativeRects) {
        SkIRect ir;
        switch (mutate_conservative_op(&op, false)) {
            case kDoNothing_MutateResult:
                return !this->isEmpty();
            case kReplaceClippedAgainstGlobalBounds_MutateResult:
                ir = bounds;
                break;
            case kContinue_MutateResult:
                matrix.mapRect(&devRect, localRect);
                ir = devRect.roundOut();
                break;
        }
        return this->op(ir, op);
    }
    const bool isScaleTrans = matrix.isScaleTranslate();
    if (!isScaleTrans) {
        SkPath path;
        path.addRect(localRect);
        path.setIsVolatile(true);
        return this->op(path, matrix, bounds, op, doAA);
    }

    matrix.mapRect(&devRect, localRect);

    if (fIsBW && doAA) {
        // check that the rect really needs aa, or is it close enought to
        // integer boundaries that we can just treat it as a BW rect?
        if (nearly_integral(devRect.fLeft) && nearly_integral(devRect.fTop) &&
            nearly_integral(devRect.fRight) && nearly_integral(devRect.fBottom)) {
            doAA = false;
        }
    }

    if (fIsBW && !doAA) {
        SkIRect ir;
        devRect.round(&ir);
        (void)fBW.op(ir, op);
    } else {
        if (fIsBW) {
            this->convertToAA();
        }
        (void)fAA.op(devRect, op, doAA);
    }
    return this->updateCacheAndReturnNonEmpty();
}
예제 #3
0
bool SkRasterClip::op(const SkPath& path, const SkISize& size, SkRegion::Op op, bool doAA) {
    // base is used to limit the size (and therefore memory allocation) of the
    // region that results from scan converting devPath.
    SkRegion base;

    if (fForceConservativeRects) {
        SkIRect ir;
        switch (mutate_conservative_op(&op, path.isInverseFillType())) {
            case kDoNothing_MutateResult:
                return !this->isEmpty();
            case kReplaceClippedAgainstGlobalBounds_MutateResult:
                ir = SkIRect::MakeSize(size);
                break;
            case kContinue_MutateResult:
                ir = path.getBounds().roundOut();
                break;
        }
        return this->op(ir, op);
    }

    if (SkRegion::kIntersect_Op == op) {
        // since we are intersect, we can do better (tighter) with currRgn's
        // bounds, than just using the device. However, if currRgn is complex,
        // our region blitter may hork, so we do that case in two steps.
        if (this->isRect()) {
            // FIXME: we should also be able to do this when this->isBW(),
            // but relaxing the test above triggers GM asserts in
            // SkRgnBuilder::blitH(). We need to investigate what's going on.
            return this->setPath(path, this->bwRgn(), doAA);
        } else {
            base.setRect(this->getBounds());
            SkRasterClip clip(fForceConservativeRects);
            clip.setPath(path, base, doAA);
            return this->op(clip, op);
        }
    } else {
        base.setRect(0, 0, size.width(), size.height());
        
        if (SkRegion::kReplace_Op == op) {
            return this->setPath(path, base, doAA);
        } else {
            SkRasterClip clip(fForceConservativeRects);
            clip.setPath(path, base, doAA);
            return this->op(clip, op);
        }
    }
}
예제 #4
0
void SkConservativeClip::opRect(const SkRect& localRect, const SkMatrix& ctm,
                                const SkIRect& devBounds, SkRegion::Op op, bool doAA) {
    SkIRect ir;
    switch (mutate_conservative_op(&op, false)) {
        case kDoNothing_MutateResult:
            return;
        case kReplaceClippedAgainstGlobalBounds_MutateResult:
            ir = devBounds;
            break;
        case kContinue_MutateResult: {
            SkRect devRect;
            ctm.mapRect(&devRect, localRect);
            ir = doAA ? devRect.roundOut() : devRect.round();
        } break;
    }
    this->opIRect(ir, op);
}
예제 #5
0
void SkConservativeClip::opPath(const SkPath& path, const SkMatrix& ctm, const SkIRect& devBounds,
                                SkRegion::Op op, bool doAA) {
    SkIRect ir;
    switch (mutate_conservative_op(&op, path.isInverseFillType())) {
        case kDoNothing_MutateResult:
            return;
        case kReplaceClippedAgainstGlobalBounds_MutateResult:
            ir = devBounds;
            break;
        case kContinue_MutateResult: {
            SkRect bounds = path.getBounds();
            ctm.mapRect(&bounds);
            ir = bounds.roundOut();
            break;
        }
    }
    return this->opIRect(ir, op);
}
예제 #6
0
bool SkRasterClip::op(const SkRect& r, const SkISize& size, SkRegion::Op op, bool doAA) {
    AUTO_RASTERCLIP_VALIDATE(*this);

    if (fForceConservativeRects) {
        SkIRect ir;
        switch (mutate_conservative_op(&op, false)) {
            case kDoNothing_MutateResult:
                return !this->isEmpty();
            case kReplaceClippedAgainstGlobalBounds_MutateResult:
                ir = SkIRect::MakeSize(size);
                break;
            case kContinue_MutateResult:
                ir = r.roundOut();
                break;
        }
        return this->op(ir, op);
    }
    
    if (fIsBW && doAA) {
        // check that the rect really needs aa, or is it close enought to
        // integer boundaries that we can just treat it as a BW rect?
        if (nearly_integral(r.fLeft) && nearly_integral(r.fTop) &&
            nearly_integral(r.fRight) && nearly_integral(r.fBottom)) {
            doAA = false;
        }
    }

    if (fIsBW && !doAA) {
        SkIRect ir;
        r.round(&ir);
        (void)fBW.op(ir, op);
    } else {
        if (fIsBW) {
            this->convertToAA();
        }
        (void)fAA.op(r, op, doAA);
    }
    return this->updateCacheAndReturnNonEmpty();
}