18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkColorFilter_DEFINED 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkColorFilter_DEFINED 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1171fecc32b1b4f71ef3c6467b1f5e0b55c2a12428Mike Reed#include "SkBlendMode.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColor.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFlattenable.h" 1406ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman#include "SkRefCnt.h" 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1667e78c9e47c38a51816412a24a10f4fe2db142a3bsalomon@google.comclass GrContext; 17d3ebb48320cf1b7e969974673e4bd7743816985ebungemanclass GrFragmentProcessor; 18ac04fef619ad3939a25e66bdaef6f6b1e7f5ca50Herb Derbyclass SkArenaAlloc; 19d3ebb48320cf1b7e969974673e4bd7743816985ebungemanclass SkBitmap; 20618d304eb394d64779be0ecdc5eff898242faa8fBrian Osmanclass SkColorSpace; 219a5c47f4effba3b48a9a8c7c144b72b532d06efemtkleinclass SkRasterPipeline; 22c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 23fb6deed66c20f86c86c105f41dbbf3f3c4a47e4creed@google.com/** 24fb6deed66c20f86c86c105f41dbbf3f3c4a47e4creed@google.com * ColorFilters are optional objects in the drawing pipeline. When present in 25fb6deed66c20f86c86c105f41dbbf3f3c4a47e4creed@google.com * a paint, they are called with the "src" colors, and return new colors, which 26fb6deed66c20f86c86c105f41dbbf3f3c4a47e4creed@google.com * are then passed onto the next stage (either ImageFilter or Xfermode). 27fb6deed66c20f86c86c105f41dbbf3f3c4a47e4creed@google.com * 28fb6deed66c20f86c86c105f41dbbf3f3c4a47e4creed@google.com * All subclasses are required to be reentrant-safe : it must be legal to share 29fb6deed66c20f86c86c105f41dbbf3f3c4a47e4creed@google.com * the same instance between several threads. 30fb6deed66c20f86c86c105f41dbbf3f3c4a47e4creed@google.com */ 318c3ff17e2cab6f7c798b9f8ff4515c4a3d3fd9d1bsalomon@google.comclass SK_API SkColorFilter : public SkFlattenable { 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com /** 3443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com * If the filter can be represented by a source color plus Mode, this 3543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com * returns true, and sets (if not NULL) the color and mode appropriately. 3643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com * If not, this returns false and ignores the parameters. 3743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com */ 38faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed virtual bool asColorMode(SkColor* color, SkBlendMode* bmode) const; 3943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com 40e5ff3cefe007d092daf9d0bc2b03f9ff87b2c34esenorblanco@chromium.org /** 41e5ff3cefe007d092daf9d0bc2b03f9ff87b2c34esenorblanco@chromium.org * If the filter can be represented by a 5x4 matrix, this 42e5ff3cefe007d092daf9d0bc2b03f9ff87b2c34esenorblanco@chromium.org * returns true, and sets the matrix appropriately. 43e5ff3cefe007d092daf9d0bc2b03f9ff87b2c34esenorblanco@chromium.org * If not, this returns false and ignores the parameter. 44e5ff3cefe007d092daf9d0bc2b03f9ff87b2c34esenorblanco@chromium.org */ 45bada64428a52b4fc1f31a0a1982c2301ec57601creed@google.com virtual bool asColorMatrix(SkScalar matrix[20]) const; 46e5ff3cefe007d092daf9d0bc2b03f9ff87b2c34esenorblanco@chromium.org 477191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com /** 487191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com * If the filter can be represented by per-component table, return true, 497191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com * and if table is not null, copy the bitmap containing the table into it. 507191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com * 517191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com * The table bitmap will be in SkBitmap::kA8_Config. Each row corresponding 527191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com * to each component in ARGB order. e.g. row[0] == alpha, row[1] == red, 537191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com * etc. To transform a color, you (logically) perform the following: 547191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com * 557191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com * a' = *table.getAddr8(a, 0); 567191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com * r' = *table.getAddr8(r, 1); 577191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com * g' = *table.getAddr8(g, 2); 587191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com * b' = *table.getAddr8(b, 3); 597191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com * 607191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com * The original component value is the horizontal index for a given row, 617191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com * and the stored value at that index is the new value for that component. 627191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com */ 63b2ad101313cfba9c06a3a4dc06531766bcbec73bbsalomon@google.com virtual bool asComponentTable(SkBitmap* table) const; 647191840eec5ac3b5f5814e4df3cf18264b0b0a4dreed@google.com 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Called with a scanline of colors, as if there was a shader installed. 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com The implementation writes out its filtered version into result[]. 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Note: shader and result may be the same buffer. 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param src array of colors, possibly generated by a shader 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param count the number of entries in the src[] and result[] arrays 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param result written by the filter 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 7262a320c8d444cd04e4f2952c269ea4cbd58dee64reed virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) const = 0; 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 746d3cef930ad19b0f55543ca40f7a07030f4fe508reed virtual void filterSpan4f(const SkPM4f src[], int count, SkPM4f result[]) const; 756d3cef930ad19b0f55543ca40f7a07030f4fe508reed 76ac04fef619ad3939a25e66bdaef6f6b1e7f5ca50Herb Derby bool appendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, 77744908e5e81f81f34288a1b5547aa4ea990ad13dMike Klein bool shaderIsOpaque) const; 789a5c47f4effba3b48a9a8c7c144b72b532d06efemtklein 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com enum Flags { 8062a320c8d444cd04e4f2952c269ea4cbd58dee64reed /** If set the filter methods will not change the alpha channel of the colors. 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 826d3cef930ad19b0f55543ca40f7a07030f4fe508reed kAlphaUnchanged_Flag = 1 << 0, 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8562a320c8d444cd04e4f2952c269ea4cbd58dee64reed /** Returns the flags for this filter. Override in subclasses to return custom flags. 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 87bada64428a52b4fc1f31a0a1982c2301ec57601creed@google.com virtual uint32_t getFlags() const { return 0; } 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 896b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com /** 908a8d841d485ff36b64d838575eb3735c1ddcf929reed * If this subclass can optimally createa composition with the inner filter, return it as 918a8d841d485ff36b64d838575eb3735c1ddcf929reed * a new filter (which the caller must unref() when it is done). If no such optimization 928a8d841d485ff36b64d838575eb3735c1ddcf929reed * is known, return NULL. 938a8d841d485ff36b64d838575eb3735c1ddcf929reed * 948a8d841d485ff36b64d838575eb3735c1ddcf929reed * e.g. result(color) == this_filter(inner(color)) 958a8d841d485ff36b64d838575eb3735c1ddcf929reed */ 96d053ce9c54d4e5937a142278359e5a4cde18095ereed virtual sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter>) const { return nullptr; } 978a8d841d485ff36b64d838575eb3735c1ddcf929reed 988a8d841d485ff36b64d838575eb3735c1ddcf929reed /** 996b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com * Apply this colorfilter to the specified SkColor. This routine handles 1006b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com * converting to SkPMColor, calling the filter, and then converting back 1016b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com * to SkColor. This method is not virtual, but will call filterSpan() 1026b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com * which is virtual. 1036b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com */ 104bada64428a52b4fc1f31a0a1982c2301ec57601creed@google.com SkColor filterColor(SkColor) const; 1051447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com 106f7cdb06d62bd732599c7ee407dfd76d32d671755reed /** 107f7cdb06d62bd732599c7ee407dfd76d32d671755reed * Filters a single color. 108f7cdb06d62bd732599c7ee407dfd76d32d671755reed */ 109f7cdb06d62bd732599c7ee407dfd76d32d671755reed SkColor4f filterColor4f(const SkColor4f&) const; 110f7cdb06d62bd732599c7ee407dfd76d32d671755reed 111845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com /** Create a colorfilter that uses the specified color and mode. 112845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com If the Mode is DST, this function will return NULL (since that 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mode will have no effect on the result). 114845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com @param c The source color used with the specified mode 1157d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed @param mode The blend that is applied to each color in 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com the colorfilter's filterSpan[16,32] methods 117845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com @return colorfilter object that applies the src color and mode, 118845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com or NULL if the mode will have no effect. 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 1207d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed static sk_sp<SkColorFilter> MakeModeFilter(SkColor c, SkBlendMode mode); 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 122db873d8677a2d4ecfe38a794a5d868301bdeeabereed /** Construct a colorfilter whose effect is to first apply the inner filter and then apply 123db873d8677a2d4ecfe38a794a5d868301bdeeabereed * the outer filter to the result of the inner's. 124db873d8677a2d4ecfe38a794a5d868301bdeeabereed * The reference counts for outer and inner are incremented. 125dc812222a7488d2a0e39b4a09c81c9f000d4b869reed * 126dc812222a7488d2a0e39b4a09c81c9f000d4b869reed * Due to internal limits, it is possible that this will return NULL, so the caller must 127dc812222a7488d2a0e39b4a09c81c9f000d4b869reed * always check. 128db873d8677a2d4ecfe38a794a5d868301bdeeabereed */ 129d053ce9c54d4e5937a142278359e5a4cde18095ereed static sk_sp<SkColorFilter> MakeComposeFilter(sk_sp<SkColorFilter> outer, 130d053ce9c54d4e5937a142278359e5a4cde18095ereed sk_sp<SkColorFilter> inner); 131db873d8677a2d4ecfe38a794a5d868301bdeeabereed 1328610002ff81fb5d81d1b7c312b5d0a8b05b41e13bsalomon /** Construct a color filter that transforms a color by a 4x5 matrix. The matrix is in row- 1338610002ff81fb5d81d1b7c312b5d0a8b05b41e13bsalomon * major order and the translation column is specified in unnormalized, 0...255, space. 1348610002ff81fb5d81d1b7c312b5d0a8b05b41e13bsalomon */ 135d053ce9c54d4e5937a142278359e5a4cde18095ereed static sk_sp<SkColorFilter> MakeMatrixFilterRowMajor255(const SkScalar array[20]); 136d053ce9c54d4e5937a142278359e5a4cde18095ereed 13706ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman#if SK_SUPPORT_GPU 138cff10b21a9934afc540d121b493b204335829589reed /** 139e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon * A subclass may implement this factory function to work with the GPU backend. It returns 140e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon * a GrFragmentProcessor that implemets the color filter in GPU shader code. 141cff10b21a9934afc540d121b493b204335829589reed * 142e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon * The fragment processor receives a premultiplied input color and produces a premultiplied 143e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon * output color. 144b7affb56bb295d52e543d6f0e45ba45acf42dcd6reed * 145e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon * A null return indicates that the color filter isn't implemented for the GPU backend. 14667e78c9e47c38a51816412a24a10f4fe2db142a3bsalomon@google.com */ 147618d304eb394d64779be0ecdc5eff898242faa8fBrian Osman virtual sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, 148618d304eb394d64779be0ecdc5eff898242faa8fBrian Osman SkColorSpace* dstColorSpace) const; 14906ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman#endif 15067e78c9e47c38a51816412a24a10f4fe2db142a3bsalomon@google.com 1510abdf766d395ed3b7059511425f431589eca05f6senorblanco bool affectsTransparentBlack() const { 1520abdf766d395ed3b7059511425f431589eca05f6senorblanco return this->filterColor(0) != 0; 1530abdf766d395ed3b7059511425f431589eca05f6senorblanco } 1540abdf766d395ed3b7059511425f431589eca05f6senorblanco 1550f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org SK_TO_STRING_PUREVIRT() 1561202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com 157a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.com SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() 1583b37545bc594a96de45eba62dea0ce478750f2a9mtklein SK_DEFINE_FLATTENABLE_TYPE(SkColorFilter) 159c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected: 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkColorFilter() {} 1621447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com 163ac04fef619ad3939a25e66bdaef6f6b1e7f5ca50Herb Derby virtual bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, 164744908e5e81f81f34288a1b5547aa4ea990ad13dMike Klein bool shaderIsOpaque) const; 1659a5c47f4effba3b48a9a8c7c144b72b532d06efemtklein 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 167dc812222a7488d2a0e39b4a09c81c9f000d4b869reed /* 168dc812222a7488d2a0e39b4a09c81c9f000d4b869reed * Returns 1 if this is a single filter (not a composition of other filters), otherwise it 169dc812222a7488d2a0e39b4a09c81c9f000d4b869reed * reutrns the number of leaf-node filters in a composition. This should be the same value 170dc812222a7488d2a0e39b4a09c81c9f000d4b869reed * as the number of GrFragmentProcessors returned by asFragmentProcessors's array parameter. 171dc812222a7488d2a0e39b4a09c81c9f000d4b869reed * 172dc812222a7488d2a0e39b4a09c81c9f000d4b869reed * e.g. compose(filter, compose(compose(filter, filter), filter)) --> 4 173dc812222a7488d2a0e39b4a09c81c9f000d4b869reed */ 174dc812222a7488d2a0e39b4a09c81c9f000d4b869reed virtual int privateComposedFilterCount() const { return 1; } 175dc812222a7488d2a0e39b4a09c81c9f000d4b869reed friend class SkComposeColorFilter; 176dc812222a7488d2a0e39b4a09c81c9f000d4b869reed 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkFlattenable INHERITED; 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 181