1 /* 2 * Copyright 2012 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkColorFilterImageFilter.h" 9 #include "SkBitmap.h" 10 #include "SkCanvas.h" 11 #include "SkColorMatrixFilter.h" 12 #include "SkDevice.h" 13 #include "SkColorFilter.h" 14 #include "SkReadBuffer.h" 15 #include "SkTableColorFilter.h" 16 #include "SkWriteBuffer.h" 17 18 SkColorFilterImageFilter* SkColorFilterImageFilter::Create(SkColorFilter* cf, 19 SkImageFilter* input, const CropRect* cropRect) { 20 if (NULL == cf) { 21 return NULL; 22 } 23 24 SkColorFilter* inputCF; 25 if (input && input->isColorFilterNode(&inputCF)) { 26 // This is an optimization, as it collapses the hierarchy by just combining the two 27 // colorfilters into a single one, which the new imagefilter will wrap. 28 SkAutoUnref autoUnref(inputCF); 29 SkAutoTUnref<SkColorFilter> newCF(SkColorFilter::CreateComposeFilter(cf, inputCF)); 30 if (newCF) { 31 return SkNEW_ARGS(SkColorFilterImageFilter, (newCF, input->getInput(0), cropRect)); 32 } 33 } 34 35 return SkNEW_ARGS(SkColorFilterImageFilter, (cf, input, cropRect)); 36 } 37 38 SkColorFilterImageFilter::SkColorFilterImageFilter(SkColorFilter* cf, 39 SkImageFilter* input, const CropRect* cropRect) 40 : INHERITED(1, &input, cropRect), fColorFilter(SkRef(cf)) { 41 } 42 43 SkFlattenable* SkColorFilterImageFilter::CreateProc(SkReadBuffer& buffer) { 44 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); 45 SkAutoTUnref<SkColorFilter> cf(buffer.readColorFilter()); 46 return Create(cf, common.getInput(0), &common.cropRect()); 47 } 48 49 void SkColorFilterImageFilter::flatten(SkWriteBuffer& buffer) const { 50 this->INHERITED::flatten(buffer); 51 buffer.writeFlattenable(fColorFilter); 52 } 53 54 SkColorFilterImageFilter::~SkColorFilterImageFilter() { 55 fColorFilter->unref(); 56 } 57 58 bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source, 59 const Context& ctx, 60 SkBitmap* result, 61 SkIPoint* offset) const { 62 SkBitmap src = source; 63 SkIPoint srcOffset = SkIPoint::Make(0, 0); 64 if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) { 65 return false; 66 } 67 68 SkIRect bounds; 69 if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) { 70 return false; 71 } 72 73 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height())); 74 if (NULL == device.get()) { 75 return false; 76 } 77 SkCanvas canvas(device.get()); 78 SkPaint paint; 79 80 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 81 paint.setColorFilter(fColorFilter); 82 canvas.drawSprite(src, srcOffset.fX - bounds.fLeft, srcOffset.fY - bounds.fTop, &paint); 83 84 *result = device.get()->accessBitmap(false); 85 offset->fX = bounds.fLeft; 86 offset->fY = bounds.fTop; 87 return true; 88 } 89 90 bool SkColorFilterImageFilter::onIsColorFilterNode(SkColorFilter** filter) const { 91 SkASSERT(1 == this->countInputs()); 92 if (!this->cropRectIsSet()) { 93 if (filter) { 94 *filter = SkRef(fColorFilter); 95 } 96 return true; 97 } 98 return false; 99 } 100 101 #ifndef SK_IGNORE_TO_STRING 102 void SkColorFilterImageFilter::toString(SkString* str) const { 103 str->appendf("SkColorFilterImageFilter: ("); 104 105 str->appendf("input: ("); 106 107 if (this->getInput(0)) { 108 this->getInput(0)->toString(str); 109 } 110 111 str->appendf(") color filter: "); 112 fColorFilter->toString(str); 113 114 str->append(")"); 115 } 116 #endif 117