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