| /* | |
| * 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 |