1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2013 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
9cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h"
10cb93a386Sopenharmony_ci#include "include/core/SkPaint.h"
11cb93a386Sopenharmony_ci#include "include/core/SkRect.h"
12cb93a386Sopenharmony_ci#include "src/core/SkArenaAlloc.h"
13cb93a386Sopenharmony_ci
14cb93a386Sopenharmony_ci#ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_ci#include "include/core/SkDrawLooper.h"
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_civoid SkDrawLooper::Context::Info::applyToCTM(SkMatrix* ctm) const {
19cb93a386Sopenharmony_ci    if (fApplyPostCTM) {
20cb93a386Sopenharmony_ci        ctm->postTranslate(fTranslate.fX, fTranslate.fY);
21cb93a386Sopenharmony_ci    } else {
22cb93a386Sopenharmony_ci        ctm->preTranslate(fTranslate.fX, fTranslate.fY);
23cb93a386Sopenharmony_ci    }
24cb93a386Sopenharmony_ci}
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_civoid SkDrawLooper::Context::Info::applyToCanvas(SkCanvas* canvas) const {
27cb93a386Sopenharmony_ci    if (fApplyPostCTM) {
28cb93a386Sopenharmony_ci        canvas->setMatrix(canvas->getLocalToDevice().postTranslate(fTranslate.fX, fTranslate.fY));
29cb93a386Sopenharmony_ci    } else {
30cb93a386Sopenharmony_ci        canvas->translate(fTranslate.fX, fTranslate.fY);
31cb93a386Sopenharmony_ci    }
32cb93a386Sopenharmony_ci}
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_cibool SkDrawLooper::canComputeFastBounds(const SkPaint& paint) const {
35cb93a386Sopenharmony_ci    SkSTArenaAlloc<48> alloc;
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_ci    SkDrawLooper::Context* context = this->makeContext(&alloc);
38cb93a386Sopenharmony_ci    for (;;) {
39cb93a386Sopenharmony_ci        SkPaint p(paint);
40cb93a386Sopenharmony_ci        SkDrawLooper::Context::Info info;
41cb93a386Sopenharmony_ci        if (context->next(&info, &p)) {
42cb93a386Sopenharmony_ci            if (!p.canComputeFastBounds()) {
43cb93a386Sopenharmony_ci                return false;
44cb93a386Sopenharmony_ci            }
45cb93a386Sopenharmony_ci        } else {
46cb93a386Sopenharmony_ci            break;
47cb93a386Sopenharmony_ci        }
48cb93a386Sopenharmony_ci    }
49cb93a386Sopenharmony_ci    return true;
50cb93a386Sopenharmony_ci}
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_civoid SkDrawLooper::computeFastBounds(const SkPaint& paint, const SkRect& s,
53cb93a386Sopenharmony_ci                                     SkRect* dst) const {
54cb93a386Sopenharmony_ci    // src and dst rects may alias and we need to keep the original src, so copy it.
55cb93a386Sopenharmony_ci    const SkRect src = s;
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ci    SkSTArenaAlloc<48> alloc;
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_ci    *dst = src;   // catch case where there are no loops
60cb93a386Sopenharmony_ci    SkDrawLooper::Context* context = this->makeContext(&alloc);
61cb93a386Sopenharmony_ci
62cb93a386Sopenharmony_ci    for (bool firstTime = true;; firstTime = false) {
63cb93a386Sopenharmony_ci        SkPaint p(paint);
64cb93a386Sopenharmony_ci        SkDrawLooper::Context::Info info;
65cb93a386Sopenharmony_ci        if (context->next(&info, &p)) {
66cb93a386Sopenharmony_ci            SkRect r(src);
67cb93a386Sopenharmony_ci
68cb93a386Sopenharmony_ci            p.computeFastBounds(r, &r);
69cb93a386Sopenharmony_ci            r.offset(info.fTranslate.fX, info.fTranslate.fY);
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_ci            if (firstTime) {
72cb93a386Sopenharmony_ci                *dst = r;
73cb93a386Sopenharmony_ci            } else {
74cb93a386Sopenharmony_ci                dst->join(r);
75cb93a386Sopenharmony_ci            }
76cb93a386Sopenharmony_ci        } else {
77cb93a386Sopenharmony_ci            break;
78cb93a386Sopenharmony_ci        }
79cb93a386Sopenharmony_ci    }
80cb93a386Sopenharmony_ci}
81cb93a386Sopenharmony_ci
82cb93a386Sopenharmony_cibool SkDrawLooper::asABlurShadow(BlurShadowRec*) const {
83cb93a386Sopenharmony_ci    return false;
84cb93a386Sopenharmony_ci}
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_civoid SkDrawLooper::apply(SkCanvas* canvas, const SkPaint& paint,
87cb93a386Sopenharmony_ci                         std::function<void(SkCanvas*, const SkPaint&)> proc) {
88cb93a386Sopenharmony_ci    SkSTArenaAlloc<256> alloc;
89cb93a386Sopenharmony_ci    Context* ctx = this->makeContext(&alloc);
90cb93a386Sopenharmony_ci    if (ctx) {
91cb93a386Sopenharmony_ci        Context::Info info;
92cb93a386Sopenharmony_ci        for (;;) {
93cb93a386Sopenharmony_ci            SkPaint p = paint;
94cb93a386Sopenharmony_ci            if (!ctx->next(&info, &p)) {
95cb93a386Sopenharmony_ci                break;
96cb93a386Sopenharmony_ci            }
97cb93a386Sopenharmony_ci            canvas->save();
98cb93a386Sopenharmony_ci            if (info.fApplyPostCTM) {
99cb93a386Sopenharmony_ci                canvas->setMatrix(canvas->getLocalToDevice().postTranslate(info.fTranslate.fX,
100cb93a386Sopenharmony_ci                                                                           info.fTranslate.fY));
101cb93a386Sopenharmony_ci            } else {
102cb93a386Sopenharmony_ci                canvas->translate(info.fTranslate.fX, info.fTranslate.fY);
103cb93a386Sopenharmony_ci            }
104cb93a386Sopenharmony_ci            proc(canvas, p);
105cb93a386Sopenharmony_ci            canvas->restore();
106cb93a386Sopenharmony_ci        }
107cb93a386Sopenharmony_ci    }
108cb93a386Sopenharmony_ci}
109cb93a386Sopenharmony_ci
110cb93a386Sopenharmony_ci#endif
111