| 1 | /* |
| 2 | * Copyright 2011 Google Inc. |
| 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 "include/effects/SkColorMatrix.h" |
| 9 | |
| 10 | enum { |
| 11 | kR_Scale = 0, |
| 12 | kG_Scale = 6, |
| 13 | kB_Scale = 12, |
| 14 | kA_Scale = 18, |
| 15 | |
| 16 | kR_Trans = 4, |
| 17 | kG_Trans = 9, |
| 18 | kB_Trans = 14, |
| 19 | kA_Trans = 19, |
| 20 | }; |
| 21 | |
| 22 | static void set_concat(float result[20], const float outer[20], const float inner[20]) { |
| 23 | float tmp[20]; |
| 24 | float* target; |
| 25 | |
| 26 | if (outer == result || inner == result) { |
| 27 | target = tmp; // will memcpy answer when we're done into result |
| 28 | } else { |
| 29 | target = result; |
| 30 | } |
| 31 | |
| 32 | int index = 0; |
| 33 | for (int j = 0; j < 20; j += 5) { |
| 34 | for (int i = 0; i < 4; i++) { |
| 35 | target[index++] = outer[j + 0] * inner[i + 0] + |
| 36 | outer[j + 1] * inner[i + 5] + |
| 37 | outer[j + 2] * inner[i + 10] + |
| 38 | outer[j + 3] * inner[i + 15]; |
| 39 | } |
| 40 | target[index++] = outer[j + 0] * inner[4] + |
| 41 | outer[j + 1] * inner[9] + |
| 42 | outer[j + 2] * inner[14] + |
| 43 | outer[j + 3] * inner[19] + |
| 44 | outer[j + 4]; |
| 45 | } |
| 46 | |
| 47 | if (target != result) { |
| 48 | std::copy_n(target, 20, result); |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | void SkColorMatrix::setIdentity() { |
| 53 | fMat.fill(0.0f); |
| 54 | fMat[kR_Scale] = fMat[kG_Scale] = fMat[kB_Scale] = fMat[kA_Scale] = 1; |
| 55 | } |
| 56 | |
| 57 | void SkColorMatrix::setScale(float rScale, float gScale, float bScale, float aScale) { |
| 58 | fMat.fill(0.0f); |
| 59 | fMat[kR_Scale] = rScale; |
| 60 | fMat[kG_Scale] = gScale; |
| 61 | fMat[kB_Scale] = bScale; |
| 62 | fMat[kA_Scale] = aScale; |
| 63 | } |
| 64 | |
| 65 | void SkColorMatrix::postTranslate(float dr, float dg, float db, float da) { |
| 66 | fMat[kR_Trans] += dr; |
| 67 | fMat[kG_Trans] += dg; |
| 68 | fMat[kB_Trans] += db; |
| 69 | fMat[kA_Trans] += da; |
| 70 | } |
| 71 | |
| 72 | /////////////////////////////////////////////////////////////////////////////// |
| 73 | |
| 74 | void SkColorMatrix::setConcat(const SkColorMatrix& matA, const SkColorMatrix& matB) { |
| 75 | set_concat(fMat.data(), matA.fMat.data(), matB.fMat.data()); |
| 76 | } |
| 77 | |
| 78 | /////////////////////////////////////////////////////////////////////////////// |
| 79 | |
| 80 | static void setrow(float row[], float r, float g, float b) { |
| 81 | row[0] = r; |
| 82 | row[1] = g; |
| 83 | row[2] = b; |
| 84 | } |
| 85 | |
| 86 | static const float kHueR = 0.213f; |
| 87 | static const float kHueG = 0.715f; |
| 88 | static const float kHueB = 0.072f; |
| 89 | |
| 90 | void SkColorMatrix::setSaturation(float sat) { |
| 91 | fMat.fill(0.0f); |
| 92 | |
| 93 | const float R = kHueR * (1 - sat); |
| 94 | const float G = kHueG * (1 - sat); |
| 95 | const float B = kHueB * (1 - sat); |
| 96 | |
| 97 | setrow(fMat.data() + 0, R + sat, G, B); |
| 98 | setrow(fMat.data() + 5, R, G + sat, B); |
| 99 | setrow(fMat.data() + 10, R, G, B + sat); |
| 100 | fMat[kA_Scale] = 1; |
| 101 | } |
| 102 | |