Example #1
0
    void onDraw(SkCanvas* canvas) override {
        // Set up a gradient paint for a rect.
        // And non-gradient paint for other objects.
        canvas->drawColor(SK_ColorWHITE);

        SkPaint paint;
        paint.setStyle(SkPaint::kFill_Style);
        paint.setAntiAlias(true);
        paint.setStrokeWidth(4);
        paint.setColor(0xFFFE938C);

        SkRect rect = SkRect::MakeXYWH(10, 10, 100, 160);

        SkPoint points[2] = {
            SkPoint::Make(0.0f, 0.0f),
            SkPoint::Make(256.0f, 256.0f)
        };
        SkColor colors[2] = {SK_ColorBLUE, SK_ColorYELLOW};
        SkPaint newPaint(paint);
        newPaint.setShader(SkGradientShader::MakeLinear(
                points, colors, nullptr, 2, SkTileMode::kClamp));
        canvas->drawRect(rect, newPaint);

        SkRRect oval;
        oval.setOval(rect);
        oval.offset(40, 80);
        paint.setColor(0xFFE6B89C);
        canvas->drawRRect(oval, paint);

        paint.setColor(0xFF9CAFB7);
        canvas->drawCircle(180, 50, 25, paint);

        rect.offset(80, 50);
        paint.setColor(0xFF4281A4);
        paint.setStyle(SkPaint::kStroke_Style);
        canvas->drawRoundRect(rect, 10, 10, paint);
    }
bool GrClipMaskManager::installClipEffects(const ElementList& elements,
                                           GrDrawState::AutoRestoreEffects* are,
                                           const SkVector& clipToRTOffset,
                                           const SkRect* drawBounds) {

    GrDrawState* drawState = fGpu->drawState();
    SkRect boundsInClipSpace;
    if (NULL != drawBounds) {
        boundsInClipSpace = *drawBounds;
        boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY);
    }

    are->set(drawState);
    GrRenderTarget* rt = drawState->getRenderTarget();
    ElementList::Iter iter(elements);

    bool setARE = false;
    bool failed = false;

    while (NULL != iter.get()) {
        SkRegion::Op op = iter.get()->getOp();
        bool invert;
        bool skip = false;
        switch (op) {
            case SkRegion::kReplace_Op:
                SkASSERT(iter.get() == elements.head());
                // Fallthrough, handled same as intersect.
            case SkRegion::kIntersect_Op:
                invert = false;
                if (NULL != drawBounds && iter.get()->contains(boundsInClipSpace)) {
                    skip = true;
                }
                break;
            case SkRegion::kDifference_Op:
                invert = true;
                // We don't currently have a cheap test for whether a rect is fully outside an
                // element's primitive, so don't attempt to set skip.
                break;
            default:
                failed = true;
                break;
        }
        if (failed) {
            break;
        }

        if (!skip) {
            GrEffectEdgeType edgeType;
            if (GR_AA_CLIP && iter.get()->isAA()) {
                if (rt->isMultisampled()) {
                    // Coverage based AA clips don't place nicely with MSAA.
                    failed = true;
                    break;
                }
                edgeType = invert ? kInverseFillAA_GrEffectEdgeType : kFillAA_GrEffectEdgeType;
            } else {
                edgeType = invert ? kInverseFillBW_GrEffectEdgeType : kFillBW_GrEffectEdgeType;
            }
            SkAutoTUnref<GrEffectRef> effect;
            switch (iter.get()->getType()) {
                case SkClipStack::Element::kPath_Type:
                    effect.reset(GrConvexPolyEffect::Create(edgeType, iter.get()->getPath(),
                        &clipToRTOffset));
                    break;
                case SkClipStack::Element::kRRect_Type: {
                    SkRRect rrect = iter.get()->getRRect();
                    rrect.offset(clipToRTOffset.fX, clipToRTOffset.fY);
                    effect.reset(GrRRectEffect::Create(edgeType, rrect));
                    break;
                }
                case SkClipStack::Element::kRect_Type: {
                    SkRect rect = iter.get()->getRect();
                    rect.offset(clipToRTOffset.fX, clipToRTOffset.fY);
                    effect.reset(GrConvexPolyEffect::Create(edgeType, rect));
                    break;
                }
                default:
                    break;
            }
            if (effect) {
                if (!setARE) {
                    are->set(fGpu->drawState());
                    setARE = true;
                }
                fGpu->drawState()->addCoverageEffect(effect);
            } else {
                failed = true;
                break;
            }
        }
        iter.next();
    }

    if (failed) {
        are->set(NULL);
    }

    return !failed;
}
Example #3
0
static bool get_analytic_clip_processor(const GrReducedClip::ElementList& elements,
                                        bool abortIfAA,
                                        SkVector& clipToRTOffset,
                                        const SkRect* drawBounds,
                                        sk_sp<GrFragmentProcessor>* resultFP) {
    SkRect boundsInClipSpace;
    if (drawBounds) {
        boundsInClipSpace = *drawBounds;
        boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY);
    }
    SkASSERT(elements.count() <= kMaxAnalyticElements);
    SkSTArray<kMaxAnalyticElements, sk_sp<GrFragmentProcessor>> fps;
    GrReducedClip::ElementList::Iter iter(elements);
    while (iter.get()) {
        SkRegion::Op op = iter.get()->getOp();
        bool invert;
        bool skip = false;
        switch (op) {
            case SkRegion::kReplace_Op:
                SkASSERT(iter.get() == elements.head());
                // Fallthrough, handled same as intersect.
            case SkRegion::kIntersect_Op:
                invert = false;
                if (drawBounds && iter.get()->contains(boundsInClipSpace)) {
                    skip = true;
                }
                break;
            case SkRegion::kDifference_Op:
                invert = true;
                // We don't currently have a cheap test for whether a rect is fully outside an
                // element's primitive, so don't attempt to set skip.
                break;
            default:
                return false;
        }
        if (!skip) {
            GrPrimitiveEdgeType edgeType;
            if (iter.get()->isAA()) {
                if (abortIfAA) {
                    return false;
                }
                edgeType =
                    invert ? kInverseFillAA_GrProcessorEdgeType : kFillAA_GrProcessorEdgeType;
            } else {
                edgeType =
                    invert ? kInverseFillBW_GrProcessorEdgeType : kFillBW_GrProcessorEdgeType;
            }

            switch (iter.get()->getType()) {
                case SkClipStack::Element::kPath_Type:
                    fps.emplace_back(GrConvexPolyEffect::Make(edgeType, iter.get()->getPath(),
                                                              &clipToRTOffset));
                    break;
                case SkClipStack::Element::kRRect_Type: {
                    SkRRect rrect = iter.get()->getRRect();
                    rrect.offset(clipToRTOffset.fX, clipToRTOffset.fY);
                    fps.emplace_back(GrRRectEffect::Make(edgeType, rrect));
                    break;
                }
                case SkClipStack::Element::kRect_Type: {
                    SkRect rect = iter.get()->getRect();
                    rect.offset(clipToRTOffset.fX, clipToRTOffset.fY);
                    fps.emplace_back(GrConvexPolyEffect::Make(edgeType, rect));
                    break;
                }
                default:
                    break;
            }
            if (!fps.back()) {
                return false;
            }
        }
        iter.next();
    }

    *resultFP = nullptr;
    if (fps.count()) {
        *resultFP = GrFragmentProcessor::RunInSeries(fps.begin(), fps.count());
    }
    return true;
}
Example #4
0
const GrFragmentProcessor* GrClipMaskManager::getAnalyticClipProcessor(
                                                        const GrReducedClip::ElementList& elements,
                                                        const SkVector& clipToRTOffset,
                                                        const SkRect* drawBounds) {
    SkRect boundsInClipSpace;
    if (drawBounds) {
        boundsInClipSpace = *drawBounds;
        boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY);
    }
    SkASSERT(elements.count() <= kMaxAnalyticElements);
    const GrFragmentProcessor* fps[kMaxAnalyticElements];
    for (int i = 0; i < kMaxAnalyticElements; ++i) {
        fps[i] = nullptr;
    }
    int fpCnt = 0;
    GrReducedClip::ElementList::Iter iter(elements);
    bool failed = false;
    while (iter.get()) {
        SkRegion::Op op = iter.get()->getOp();
        bool invert;
        bool skip = false;
        switch (op) {
            case SkRegion::kReplace_Op:
                SkASSERT(iter.get() == elements.head());
                // Fallthrough, handled same as intersect.
            case SkRegion::kIntersect_Op:
                invert = false;
                if (drawBounds && iter.get()->contains(boundsInClipSpace)) {
                    skip = true;
                }
                break;
            case SkRegion::kDifference_Op:
                invert = true;
                // We don't currently have a cheap test for whether a rect is fully outside an
                // element's primitive, so don't attempt to set skip.
                break;
            default:
                failed = true;
                break;
        }
        if (failed) {
            break;
        }

        if (!skip) {
            GrPrimitiveEdgeType edgeType;
            if (iter.get()->isAA()) {
                edgeType =
                    invert ? kInverseFillAA_GrProcessorEdgeType : kFillAA_GrProcessorEdgeType;
            } else {
                edgeType =
                    invert ? kInverseFillBW_GrProcessorEdgeType : kFillBW_GrProcessorEdgeType;
            }
            switch (iter.get()->getType()) {
                case SkClipStack::Element::kPath_Type:
                    fps[fpCnt] = GrConvexPolyEffect::Create(edgeType, iter.get()->getPath(),
                                                            &clipToRTOffset);
                    break;
                case SkClipStack::Element::kRRect_Type: {
                    SkRRect rrect = iter.get()->getRRect();
                    rrect.offset(clipToRTOffset.fX, clipToRTOffset.fY);
                    fps[fpCnt] = GrRRectEffect::Create(edgeType, rrect);
                    break;
                }
                case SkClipStack::Element::kRect_Type: {
                    SkRect rect = iter.get()->getRect();
                    rect.offset(clipToRTOffset.fX, clipToRTOffset.fY);
                    fps[fpCnt] = GrConvexPolyEffect::Create(edgeType, rect);
                    break;
                }
                default:
                    break;
            }
            if (!fps[fpCnt]) {
                failed = true;
                break;
            }
            fpCnt++;
        }
        iter.next();
    }

    const GrFragmentProcessor* resultFP = nullptr;
    if (!failed) {
        resultFP = GrFragmentProcessor::RunInSeries(fps, fpCnt);
    }
    for (int i = 0; i < fpCnt; ++i) {
        fps[i]->unref();
    }
    return resultFP;
}
bool GrClipMaskManager::installClipEffects(GrPipelineBuilder* pipelineBuilder,
        GrPipelineBuilder::AutoRestoreFragmentProcessors* arfp,
        const GrReducedClip::ElementList& elements,
        const SkVector& clipToRTOffset,
        const SkRect* drawBounds) {
    SkRect boundsInClipSpace;
    if (drawBounds) {
        boundsInClipSpace = *drawBounds;
        boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY);
    }

    arfp->set(pipelineBuilder);
    GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
    GrReducedClip::ElementList::Iter iter(elements);
    bool failed = false;
    while (iter.get()) {
        SkRegion::Op op = iter.get()->getOp();
        bool invert;
        bool skip = false;
        switch (op) {
        case SkRegion::kReplace_Op:
            SkASSERT(iter.get() == elements.head());
        // Fallthrough, handled same as intersect.
        case SkRegion::kIntersect_Op:
            invert = false;
            if (drawBounds && iter.get()->contains(boundsInClipSpace)) {
                skip = true;
            }
            break;
        case SkRegion::kDifference_Op:
            invert = true;
            // We don't currently have a cheap test for whether a rect is fully outside an
            // element's primitive, so don't attempt to set skip.
            break;
        default:
            failed = true;
            break;
        }
        if (failed) {
            break;
        }

        if (!skip) {
            GrPrimitiveEdgeType edgeType;
            if (iter.get()->isAA()) {
                if (rt->isMultisampled()) {
                    // Coverage based AA clips don't place nicely with MSAA.
                    failed = true;
                    break;
                }
                edgeType =
                    invert ? kInverseFillAA_GrProcessorEdgeType : kFillAA_GrProcessorEdgeType;
            } else {
                edgeType =
                    invert ? kInverseFillBW_GrProcessorEdgeType : kFillBW_GrProcessorEdgeType;
            }
            SkAutoTUnref<GrFragmentProcessor> fp;
            switch (iter.get()->getType()) {
            case SkClipStack::Element::kPath_Type:
                fp.reset(GrConvexPolyEffect::Create(edgeType, iter.get()->getPath(),
                                                    &clipToRTOffset));
                break;
            case SkClipStack::Element::kRRect_Type: {
                SkRRect rrect = iter.get()->getRRect();
                rrect.offset(clipToRTOffset.fX, clipToRTOffset.fY);
                fp.reset(GrRRectEffect::Create(edgeType, rrect));
                break;
            }
            case SkClipStack::Element::kRect_Type: {
                SkRect rect = iter.get()->getRect();
                rect.offset(clipToRTOffset.fX, clipToRTOffset.fY);
                fp.reset(GrConvexPolyEffect::Create(edgeType, rect));
                break;
            }
            default:
                break;
            }
            if (fp) {
                pipelineBuilder->addCoverageProcessor(fp);
            } else {
                failed = true;
                break;
            }
        }
        iter.next();
    }

    if (failed) {
        arfp->set(NULL);
    }
    return !failed;
}
Example #6
0
static SkRRect make_offset(const SkRRect& src, SkScalar dx, SkScalar dy) {
    SkRRect dst = src;
    dst.offset(dx, dy);
    return dst;
}