From e5ff3cefe007d092daf9d0bc2b03f9ff87b2c34e Mon Sep 17 00:00:00 2001 From: "senorblanco@chromium.org" Date: Tue, 20 Dec 2011 20:58:18 +0000 Subject: [PATCH] Implement SkColorFilter::asColorMatrix() virtual, and override in SkColorMatrixFilter. Implement missing SkColorMatrixFilter::setMatrix() and setArray() functions (were in .h, just not implemented). Add a gm for color matrix filters. Review URL: http://codereview.appspot.com/5500044/ git-svn-id: http://skia.googlecode.com/svn/trunk@2909 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gm/colormatrix.cpp | 104 ++++++++++++++++++++++++++++++++++ gyp/gmslides.gypi | 1 + include/core/SkColorFilter.h | 7 +++ include/effects/SkColorMatrixFilter.h | 1 + src/core/SkColorFilter.cpp | 4 ++ src/effects/SkColorMatrixFilter.cpp | 24 ++++++++ 6 files changed, 141 insertions(+) create mode 100644 gm/colormatrix.cpp diff --git a/gm/colormatrix.cpp b/gm/colormatrix.cpp new file mode 100644 index 0000000..2c6e44c --- /dev/null +++ b/gm/colormatrix.cpp @@ -0,0 +1,104 @@ +/* + * 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 "gm.h" +#include "SkColorMatrixFilter.h" + +#define WIDTH 500 +#define HEIGHT 500 + +namespace skiagm { + +class ColorMatrixGM : public GM { +public: + ColorMatrixGM() { + this->setBGColor(0xFF808080); + fBitmap = createBitmap(64, 64); + } + +protected: + virtual SkString onShortName() { + return SkString("colormatrix"); + } + + virtual SkISize onISize() { + return make_isize(WIDTH, HEIGHT); + } + + SkBitmap createBitmap(int width, int height) { + SkBitmap bm; + bm.setConfig(SkBitmap::kARGB_8888_Config, width, height); + bm.allocPixels(); + SkCanvas canvas(bm); + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + SkPaint paint; + paint.setColor(SkColorSetARGB(255, x * 255 / width, y * 255 / height, 0)); + canvas.drawRect(SkRect::MakeXYWH(x, y, 1, 1), paint); + } + } + return bm; + } + virtual void onDraw(SkCanvas* canvas) { + + SkPaint paint; + SkColorMatrix matrix; + SkColorMatrixFilter* filter = new SkColorMatrixFilter(); + paint.setColorFilter(filter)->unref(); + + matrix.setIdentity(); + filter->setMatrix(matrix); + canvas->drawBitmap(fBitmap, 0, 0, &paint); + + matrix.setRotate(SkColorMatrix::kR_Axis, 90); + filter->setMatrix(matrix); + canvas->drawBitmap(fBitmap, 80, 0, &paint); + + matrix.setRotate(SkColorMatrix::kG_Axis, 90); + filter->setMatrix(matrix); + canvas->drawBitmap(fBitmap, 160, 0, &paint); + + matrix.setRotate(SkColorMatrix::kB_Axis, 90); + filter->setMatrix(matrix); + canvas->drawBitmap(fBitmap, 240, 0, &paint); + + matrix.setSaturation(SkFloatToScalar(0.0f)); + filter->setMatrix(matrix); + canvas->drawBitmap(fBitmap, 0, 80, &paint); + + matrix.setSaturation(SkFloatToScalar(0.5f)); + filter->setMatrix(matrix); + canvas->drawBitmap(fBitmap, 80, 80, &paint); + + matrix.setSaturation(SkFloatToScalar(1.0f)); + filter->setMatrix(matrix); + canvas->drawBitmap(fBitmap, 160, 80, &paint); + + matrix.setSaturation(SkFloatToScalar(2.0f)); + filter->setMatrix(matrix); + canvas->drawBitmap(fBitmap, 240, 80, &paint); + + matrix.setRGB2YUV(); + filter->setMatrix(matrix); + canvas->drawBitmap(fBitmap, 0, 160, &paint); + + matrix.setYUV2RGB(); + filter->setMatrix(matrix); + canvas->drawBitmap(fBitmap, 80, 160, &paint); + } + +private: + SkBitmap fBitmap; + typedef GM INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +static GM* MyFactory(void*) { return new ColorMatrixGM; } +static GMRegistry reg(MyFactory); + +} diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi index 9e86b0f..9d4a664 100644 --- a/gyp/gmslides.gypi +++ b/gyp/gmslides.gypi @@ -7,6 +7,7 @@ '../gm/bitmapfilters.cpp', '../gm/bitmapscroll.cpp', '../gm/blurs.cpp', + '../gm/colormatrix.cpp', '../gm/complexclip.cpp', '../gm/complexclip2.cpp', '../gm/cubicpaths.cpp', diff --git a/include/core/SkColorFilter.h b/include/core/SkColorFilter.h index e346996..6328e70 100644 --- a/include/core/SkColorFilter.h +++ b/include/core/SkColorFilter.h @@ -23,6 +23,13 @@ public: */ virtual bool asColorMode(SkColor* color, SkXfermode::Mode* mode); + /** + * If the filter can be represented by a 5x4 matrix, this + * returns true, and sets the matrix appropriately. + * If not, this returns false and ignores the parameter. + */ + virtual bool asColorMatrix(SkScalar matrix[20]); + /** Called with a scanline of colors, as if there was a shader installed. The implementation writes out its filtered version into result[]. Note: shader and result may be the same buffer. diff --git a/include/effects/SkColorMatrixFilter.h b/include/effects/SkColorMatrixFilter.h index 32ae7df..d5f87d0 100644 --- a/include/effects/SkColorMatrixFilter.h +++ b/include/effects/SkColorMatrixFilter.h @@ -26,6 +26,7 @@ public: virtual void filterSpan(const SkPMColor src[], int count, SkPMColor[]); virtual void filterSpan16(const uint16_t src[], int count, uint16_t[]); virtual uint32_t getFlags(); + virtual bool asColorMatrix(SkScalar matrix[20]) SK_OVERRIDE; // overrides for SkFlattenable virtual void flatten(SkFlattenableWriteBuffer& buffer); diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp index d3f5faa..e91488b 100644 --- a/src/core/SkColorFilter.cpp +++ b/src/core/SkColorFilter.cpp @@ -15,6 +15,10 @@ bool SkColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) { return false; } +bool SkColorFilter::asColorMatrix(SkScalar matrix[20]) { + return false; +} + void SkColorFilter::filterSpan16(const uint16_t s[], int count, uint16_t d[]) { SkASSERT(this->getFlags() & SkColorFilter::kHasFilter16_Flag); SkASSERT(!"missing implementation of SkColorFilter::filterSpan16"); diff --git a/src/effects/SkColorMatrixFilter.cpp b/src/effects/SkColorMatrixFilter.cpp index a58e06d..5ed8698 100644 --- a/src/effects/SkColorMatrixFilter.cpp +++ b/src/effects/SkColorMatrixFilter.cpp @@ -333,8 +333,32 @@ SkColorMatrixFilter::SkColorMatrixFilter(SkFlattenableReadBuffer& buffer) fFlags = buffer.readU32(); } +bool SkColorMatrixFilter::asColorMatrix(SkScalar matrix[20]) { + int32_t* SK_RESTRICT array = fState.fArray; + for (int i = 0; i < 20; i++) { + matrix[i] = SkFixedToScalar(array[i]); + } + if (NULL != fProc) { + // Undo the offset applied to the constant column in setup(). + SkScalar offset = SkFixedToScalar(1 << (fState.fShift - 1)); + matrix[4] -= offset; + matrix[9] -= offset; + matrix[14] -= offset; + matrix[19] -= offset; + } + return true; +} + SkFlattenable* SkColorMatrixFilter::CreateProc(SkFlattenableReadBuffer& buf) { return SkNEW_ARGS(SkColorMatrixFilter, (buf)); } +void SkColorMatrixFilter::setMatrix(const SkColorMatrix& matrix) { + setup(matrix.fMat); +} + +void SkColorMatrixFilter::setArray(const SkScalar array[20]) { + setup(array); +} + SK_DEFINE_FLATTENABLE_REGISTRAR(SkColorMatrixFilter) -- 2.7.4