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