blob: 9de4d436732c928be227c3756a01d079d8a90a68 [file] [log] [blame]
/*
* 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/SkDrawLooper.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "src/core/SkArenaAlloc.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) {
SkMatrix ctm = canvas->getTotalMatrix();
ctm.postTranslate(fTranslate.fX, fTranslate.fY);
canvas->setMatrix(ctm);
} 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) {
SkMatrix ctm = canvas->getTotalMatrix();
ctm.postTranslate(info.fTranslate.fX, info.fTranslate.fY);
canvas->setMatrix(ctm);
} else {
canvas->translate(info.fTranslate.fX, info.fTranslate.fY);
}
proc(canvas, p);
canvas->restore();
}
}
}