123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- /*
- * Copyright 2011 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/SkColor.h"
- #include "include/core/SkMaskFilter.h"
- #include "include/core/SkString.h"
- #include "include/core/SkUnPreMultiply.h"
- #include "include/effects/SkBlurDrawLooper.h"
- #include "include/effects/SkLayerDrawLooper.h"
- #include "src/core/SkArenaAlloc.h"
- #include "src/core/SkBlendModePriv.h"
- #include "src/core/SkColorSpacePriv.h"
- #include "src/core/SkMaskFilterBase.h"
- #include "src/core/SkReadBuffer.h"
- #include "src/core/SkStringUtils.h"
- #include "src/core/SkWriteBuffer.h"
- #include "src/core/SkXfermodePriv.h"
- SkLayerDrawLooper::LayerInfo::LayerInfo() {
- fPaintBits = 0; // ignore our paint fields
- fColorMode = SkBlendMode::kDst; // ignore our color
- fOffset.set(0, 0);
- fPostTranslate = false;
- }
- SkLayerDrawLooper::SkLayerDrawLooper()
- : fRecs(nullptr),
- fCount(0) {
- }
- SkLayerDrawLooper::~SkLayerDrawLooper() {
- Rec* rec = fRecs;
- while (rec) {
- Rec* next = rec->fNext;
- delete rec;
- rec = next;
- }
- }
- SkLayerDrawLooper::Context*
- SkLayerDrawLooper::makeContext(SkCanvas* canvas, SkArenaAlloc* alloc) const {
- canvas->save();
- return alloc->make<LayerDrawLooperContext>(this);
- }
- static SkColor4f xferColor(const SkColor4f& src, const SkColor4f& dst, SkBlendMode mode) {
- switch (mode) {
- case SkBlendMode::kSrc:
- return src;
- case SkBlendMode::kDst:
- return dst;
- default: {
- SkPMColor4f pmS = src.premul();
- SkPMColor4f pmD = dst.premul();
- return SkBlendMode_Apply(mode, pmS, pmD).unpremul();
- }
- }
- }
- // Even with kEntirePaint_Bits, we always ensure that the master paint's
- // text-encoding is respected, since that controls how we interpret the
- // text/length parameters of a draw[Pos]Text call.
- void SkLayerDrawLooper::LayerDrawLooperContext::ApplyInfo(
- SkPaint* dst, const SkPaint& src, const LayerInfo& info) {
- SkColor4f srcColor = src.getColor4f();
- #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
- // The framework may respect the alpha value on the original paint.
- // Match this legacy behavior.
- if (src.getAlpha() == 255) {
- srcColor.fA = dst->getColor4f().fA;
- }
- #endif
- dst->setColor4f(xferColor(srcColor, dst->getColor4f(), (SkBlendMode)info.fColorMode),
- sk_srgb_singleton());
- BitFlags bits = info.fPaintBits;
- if (0 == bits) {
- return;
- }
- if (kEntirePaint_Bits == bits) {
- // we've already computed these, so save it from the assignment
- bool aa = dst->isAntiAlias();
- bool di = dst->isDither();
- SkColor4f c = dst->getColor4f();
- *dst = src;
- dst->setAntiAlias(aa);
- dst->setDither(di);
- dst->setColor4f(c, sk_srgb_singleton());
- return;
- }
- if (bits & kStyle_Bit) {
- dst->setStyle(src.getStyle());
- dst->setStrokeWidth(src.getStrokeWidth());
- dst->setStrokeMiter(src.getStrokeMiter());
- dst->setStrokeCap(src.getStrokeCap());
- dst->setStrokeJoin(src.getStrokeJoin());
- }
- if (bits & kPathEffect_Bit) {
- dst->setPathEffect(src.refPathEffect());
- }
- if (bits & kMaskFilter_Bit) {
- dst->setMaskFilter(src.refMaskFilter());
- }
- if (bits & kShader_Bit) {
- dst->setShader(src.refShader());
- }
- if (bits & kColorFilter_Bit) {
- dst->setColorFilter(src.refColorFilter());
- }
- if (bits & kXfermode_Bit) {
- dst->setBlendMode(src.getBlendMode());
- }
- // we don't override these
- #if 0
- dst->setTypeface(src.getTypeface());
- dst->setTextSize(src.getTextSize());
- dst->setTextScaleX(src.getTextScaleX());
- dst->setRasterizer(src.getRasterizer());
- dst->setLooper(src.getLooper());
- dst->setTextEncoding(src.getTextEncoding());
- dst->setHinting(src.getHinting());
- #endif
- }
- // Should we add this to canvas?
- static void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) {
- SkMatrix m = canvas->getTotalMatrix();
- m.postTranslate(dx, dy);
- canvas->setMatrix(m);
- }
- SkLayerDrawLooper::LayerDrawLooperContext::LayerDrawLooperContext(
- const SkLayerDrawLooper* looper) : fCurrRec(looper->fRecs) {}
- bool SkLayerDrawLooper::LayerDrawLooperContext::next(SkCanvas* canvas,
- SkPaint* paint) {
- canvas->restore();
- if (nullptr == fCurrRec) {
- return false;
- }
- ApplyInfo(paint, fCurrRec->fPaint, fCurrRec->fInfo);
- canvas->save();
- if (fCurrRec->fInfo.fPostTranslate) {
- postTranslate(canvas, fCurrRec->fInfo.fOffset.fX,
- fCurrRec->fInfo.fOffset.fY);
- } else {
- canvas->translate(fCurrRec->fInfo.fOffset.fX,
- fCurrRec->fInfo.fOffset.fY);
- }
- fCurrRec = fCurrRec->fNext;
- return true;
- }
- bool SkLayerDrawLooper::asABlurShadow(BlurShadowRec* bsRec) const {
- if (fCount != 2) {
- return false;
- }
- const Rec* rec = fRecs;
- // bottom layer needs to be just blur(maskfilter)
- if ((rec->fInfo.fPaintBits & ~kMaskFilter_Bit)) {
- return false;
- }
- if (SkBlendMode::kSrc != (SkBlendMode)rec->fInfo.fColorMode) {
- return false;
- }
- const SkMaskFilter* mf = rec->fPaint.getMaskFilter();
- if (nullptr == mf) {
- return false;
- }
- SkMaskFilterBase::BlurRec maskBlur;
- if (!as_MFB(mf)->asABlur(&maskBlur)) {
- return false;
- }
- rec = rec->fNext;
- // top layer needs to be "plain"
- if (rec->fInfo.fPaintBits) {
- return false;
- }
- if (SkBlendMode::kDst != (SkBlendMode)rec->fInfo.fColorMode) {
- return false;
- }
- if (!rec->fInfo.fOffset.equals(0, 0)) {
- return false;
- }
- if (bsRec) {
- bsRec->fSigma = maskBlur.fSigma;
- bsRec->fOffset = fRecs->fInfo.fOffset;
- // TODO: Update BlurShadowRec to use SkColor4f?
- bsRec->fColor = fRecs->fPaint.getColor();
- bsRec->fStyle = maskBlur.fStyle;
- }
- return true;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void SkLayerDrawLooper::flatten(SkWriteBuffer& buffer) const {
- buffer.writeInt(fCount);
- Rec* rec = fRecs;
- for (int i = 0; i < fCount; i++) {
- // Legacy "flagsmask" field -- now ignored, remove when we bump version
- buffer.writeInt(0);
- buffer.writeInt(rec->fInfo.fPaintBits);
- buffer.writeInt((int)rec->fInfo.fColorMode);
- buffer.writePoint(rec->fInfo.fOffset);
- buffer.writeBool(rec->fInfo.fPostTranslate);
- buffer.writePaint(rec->fPaint);
- rec = rec->fNext;
- }
- }
- sk_sp<SkFlattenable> SkLayerDrawLooper::CreateProc(SkReadBuffer& buffer) {
- int count = buffer.readInt();
- Builder builder;
- for (int i = 0; i < count; i++) {
- LayerInfo info;
- // Legacy "flagsmask" field -- now ignored, remove when we bump version
- (void)buffer.readInt();
- info.fPaintBits = buffer.readInt();
- info.fColorMode = (SkBlendMode)buffer.readInt();
- buffer.readPoint(&info.fOffset);
- info.fPostTranslate = buffer.readBool();
- buffer.readPaint(builder.addLayerOnTop(info), nullptr);
- if (!buffer.isValid()) {
- return nullptr;
- }
- }
- return builder.detach();
- }
- SkLayerDrawLooper::Builder::Builder()
- : fRecs(nullptr),
- fTopRec(nullptr),
- fCount(0) {
- }
- SkLayerDrawLooper::Builder::~Builder() {
- Rec* rec = fRecs;
- while (rec) {
- Rec* next = rec->fNext;
- delete rec;
- rec = next;
- }
- }
- SkPaint* SkLayerDrawLooper::Builder::addLayer(const LayerInfo& info) {
- fCount += 1;
- Rec* rec = new Rec;
- rec->fNext = fRecs;
- rec->fInfo = info;
- fRecs = rec;
- if (nullptr == fTopRec) {
- fTopRec = rec;
- }
- return &rec->fPaint;
- }
- void SkLayerDrawLooper::Builder::addLayer(SkScalar dx, SkScalar dy) {
- LayerInfo info;
- info.fOffset.set(dx, dy);
- (void)this->addLayer(info);
- }
- SkPaint* SkLayerDrawLooper::Builder::addLayerOnTop(const LayerInfo& info) {
- fCount += 1;
- Rec* rec = new Rec;
- rec->fNext = nullptr;
- rec->fInfo = info;
- if (nullptr == fRecs) {
- fRecs = rec;
- } else {
- SkASSERT(fTopRec);
- fTopRec->fNext = rec;
- }
- fTopRec = rec;
- return &rec->fPaint;
- }
- sk_sp<SkDrawLooper> SkLayerDrawLooper::Builder::detach() {
- SkLayerDrawLooper* looper = new SkLayerDrawLooper;
- looper->fCount = fCount;
- looper->fRecs = fRecs;
- fCount = 0;
- fRecs = nullptr;
- fTopRec = nullptr;
- return sk_sp<SkDrawLooper>(looper);
- }
- sk_sp<SkDrawLooper> SkBlurDrawLooper::Make(SkColor color, SkScalar sigma, SkScalar dx, SkScalar dy)
- {
- return Make(SkColor4f::FromColor(color), sk_srgb_singleton(), sigma, dx, dy);
- }
- sk_sp<SkDrawLooper> SkBlurDrawLooper::Make(SkColor4f color, SkColorSpace* cs,
- SkScalar sigma, SkScalar dx, SkScalar dy)
- {
- sk_sp<SkMaskFilter> blur = nullptr;
- if (sigma > 0.0f) {
- blur = SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, sigma, true);
- }
- SkLayerDrawLooper::Builder builder;
- // First layer
- SkLayerDrawLooper::LayerInfo defaultLayer;
- builder.addLayer(defaultLayer);
- // Blur layer
- SkLayerDrawLooper::LayerInfo blurInfo;
- blurInfo.fColorMode = SkBlendMode::kSrc;
- blurInfo.fPaintBits = SkLayerDrawLooper::kMaskFilter_Bit;
- blurInfo.fOffset = SkVector::Make(dx, dy);
- SkPaint* paint = builder.addLayer(blurInfo);
- paint->setMaskFilter(std::move(blur));
- paint->setColor4f(color, cs);
- return builder.detach();
- }
|