| /* | 
 |  * Copyright 2013 Google Inc. | 
 |  * | 
 |  * Use of this source code is governed by a BSD-style license that can be | 
 |  * found in the LICENSE file. | 
 |  */ | 
 |  | 
 | #include "include/core/SkCanvas.h" | 
 | #include "include/core/SkMatrix.h" | 
 | #include "include/core/SkPaint.h" | 
 | #include "include/core/SkRect.h" | 
 | #include "src/core/SkArenaAlloc.h" | 
 |  | 
 | #ifdef SK_SUPPORT_LEGACY_DRAWLOOPER | 
 |  | 
 | #include "include/core/SkDrawLooper.h" | 
 |  | 
 | void SkDrawLooper::Context::Info::applyToCTM(SkMatrix* ctm) const { | 
 |     if (fApplyPostCTM) { | 
 |         ctm->postTranslate(fTranslate.fX, fTranslate.fY); | 
 |     } else { | 
 |         ctm->preTranslate(fTranslate.fX, fTranslate.fY); | 
 |     } | 
 | } | 
 |  | 
 | void SkDrawLooper::Context::Info::applyToCanvas(SkCanvas* canvas) const { | 
 |     if (fApplyPostCTM) { | 
 |         canvas->setMatrix(canvas->getLocalToDevice().postTranslate(fTranslate.fX, fTranslate.fY)); | 
 |     } else { | 
 |         canvas->translate(fTranslate.fX, fTranslate.fY); | 
 |     } | 
 | } | 
 |  | 
 | bool SkDrawLooper::canComputeFastBounds(const SkPaint& paint) const { | 
 |     SkSTArenaAlloc<48> alloc; | 
 |  | 
 |     SkDrawLooper::Context* context = this->makeContext(&alloc); | 
 |     for (;;) { | 
 |         SkPaint p(paint); | 
 |         SkDrawLooper::Context::Info info; | 
 |         if (context->next(&info, &p)) { | 
 |             if (!p.canComputeFastBounds()) { | 
 |                 return false; | 
 |             } | 
 |         } else { | 
 |             break; | 
 |         } | 
 |     } | 
 |     return true; | 
 | } | 
 |  | 
 | void SkDrawLooper::computeFastBounds(const SkPaint& paint, const SkRect& s, | 
 |                                      SkRect* dst) const { | 
 |     // src and dst rects may alias and we need to keep the original src, so copy it. | 
 |     const SkRect src = s; | 
 |  | 
 |     SkSTArenaAlloc<48> alloc; | 
 |  | 
 |     *dst = src;   // catch case where there are no loops | 
 |     SkDrawLooper::Context* context = this->makeContext(&alloc); | 
 |  | 
 |     for (bool firstTime = true;; firstTime = false) { | 
 |         SkPaint p(paint); | 
 |         SkDrawLooper::Context::Info info; | 
 |         if (context->next(&info, &p)) { | 
 |             SkRect r(src); | 
 |  | 
 |             p.computeFastBounds(r, &r); | 
 |             r.offset(info.fTranslate.fX, info.fTranslate.fY); | 
 |  | 
 |             if (firstTime) { | 
 |                 *dst = r; | 
 |             } else { | 
 |                 dst->join(r); | 
 |             } | 
 |         } else { | 
 |             break; | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | bool SkDrawLooper::asABlurShadow(BlurShadowRec*) const { | 
 |     return false; | 
 | } | 
 |  | 
 | void SkDrawLooper::apply(SkCanvas* canvas, const SkPaint& paint, | 
 |                          std::function<void(SkCanvas*, const SkPaint&)> proc) { | 
 |     SkSTArenaAlloc<256> alloc; | 
 |     Context* ctx = this->makeContext(&alloc); | 
 |     if (ctx) { | 
 |         Context::Info info; | 
 |         for (;;) { | 
 |             SkPaint p = paint; | 
 |             if (!ctx->next(&info, &p)) { | 
 |                 break; | 
 |             } | 
 |             canvas->save(); | 
 |             if (info.fApplyPostCTM) { | 
 |                 canvas->setMatrix(canvas->getLocalToDevice().postTranslate(info.fTranslate.fX, | 
 |                                                                            info.fTranslate.fY)); | 
 |             } else { | 
 |                 canvas->translate(info.fTranslate.fX, info.fTranslate.fY); | 
 |             } | 
 |             proc(canvas, p); | 
 |             canvas->restore(); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | #endif |