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