| 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 |  | 
|---|
| 15 | void 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 |  | 
|---|
| 23 | void 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 |  | 
|---|
| 33 | bool 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 |  | 
|---|
| 51 | void 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 |  | 
|---|
| 81 | bool SkDrawLooper::asABlurShadow(BlurShadowRec*) const { | 
|---|
| 82 | return false; | 
|---|
| 83 | } | 
|---|
| 84 |  | 
|---|
| 85 | void 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 |  | 
|---|