/* * Copyright 2012 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkColorFilterImageFilter.h" #include "SkBitmap.h" #include "SkCanvas.h" #include "SkColorMatrixFilter.h" #include "SkDevice.h" #include "SkColorFilter.h" #include "SkReadBuffer.h" #include "SkTableColorFilter.h" #include "SkWriteBuffer.h" SkColorFilterImageFilter* SkColorFilterImageFilter::Create(SkColorFilter* cf, SkImageFilter* input, const CropRect* cropRect) { if (nullptr == cf) { return nullptr; } SkColorFilter* inputCF; if (input && input->isColorFilterNode(&inputCF)) { // This is an optimization, as it collapses the hierarchy by just combining the two // colorfilters into a single one, which the new imagefilter will wrap. SkAutoUnref autoUnref(inputCF); SkAutoTUnref newCF(SkColorFilter::CreateComposeFilter(cf, inputCF)); if (newCF) { return new SkColorFilterImageFilter(newCF, input->getInput(0), cropRect); } } return new SkColorFilterImageFilter(cf, input, cropRect); } SkColorFilterImageFilter::SkColorFilterImageFilter(SkColorFilter* cf, SkImageFilter* input, const CropRect* cropRect) : INHERITED(1, &input, cropRect), fColorFilter(SkRef(cf)) { } SkFlattenable* SkColorFilterImageFilter::CreateProc(SkReadBuffer& buffer) { SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); SkAutoTUnref cf(buffer.readColorFilter()); return Create(cf, common.getInput(0), &common.cropRect()); } void SkColorFilterImageFilter::flatten(SkWriteBuffer& buffer) const { this->INHERITED::flatten(buffer); buffer.writeFlattenable(fColorFilter); } SkColorFilterImageFilter::~SkColorFilterImageFilter() { fColorFilter->unref(); } bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source, const Context& ctx, SkBitmap* result, SkIPoint* offset) const { SkBitmap src = source; SkIPoint srcOffset = SkIPoint::Make(0, 0); if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) { return false; } SkIRect bounds; if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) { return false; } SkAutoTUnref device(proxy->createDevice(bounds.width(), bounds.height())); if (nullptr == device.get()) { return false; } SkCanvas canvas(device.get()); SkPaint paint; paint.setXfermodeMode(SkXfermode::kSrc_Mode); paint.setColorFilter(fColorFilter); canvas.drawSprite(src, srcOffset.fX - bounds.fLeft, srcOffset.fY - bounds.fTop, &paint); *result = device.get()->accessBitmap(false); offset->fX = bounds.fLeft; offset->fY = bounds.fTop; return true; } bool SkColorFilterImageFilter::onIsColorFilterNode(SkColorFilter** filter) const { SkASSERT(1 == this->countInputs()); if (!this->cropRectIsSet()) { if (filter) { *filter = SkRef(fColorFilter); } return true; } return false; } bool SkColorFilterImageFilter::affectsTransparentBlack() const { return fColorFilter->affectsTransparentBlack(); } #ifndef SK_IGNORE_TO_STRING void SkColorFilterImageFilter::toString(SkString* str) const { str->appendf("SkColorFilterImageFilter: ("); str->appendf("input: ("); if (this->getInput(0)) { this->getInput(0)->toString(str); } str->appendf(") color filter: "); fColorFilter->toString(str); str->append(")"); } #endif