1 /* libs/graphics/sgl/SkColor.cpp 2 ** 3 ** Copyright 2006, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #include "SkColor.h" 19 #include "SkColorPriv.h" 20 21 SkPMColor SkPreMultiplyARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { 22 if (a != 255) { 23 #if 0 24 unsigned scale = SkAlpha255To256(a); 25 r = SkAlphaMul(r, scale); 26 g = SkAlphaMul(g, scale); 27 b = SkAlphaMul(b, scale); 28 #else 29 r = SkMulDiv255Round(r, a); 30 g = SkMulDiv255Round(g, a); 31 b = SkMulDiv255Round(b, a); 32 #endif 33 } 34 return SkPackARGB32(a, r, g, b); 35 } 36 37 SkPMColor SkPreMultiplyColor(SkColor c) { 38 unsigned a = SkColorGetA(c); 39 unsigned r = SkColorGetR(c); 40 unsigned g = SkColorGetG(c); 41 unsigned b = SkColorGetB(c); 42 43 return SkPreMultiplyARGB(a, r, g, b); 44 } 45 46 ////////////////////////////////////////////////////////////////////////////////////////////// 47 48 static inline SkScalar ByteToScalar(U8CPU x) { 49 SkASSERT(x <= 255); 50 return SkIntToScalar(x) / 255; 51 } 52 53 static inline SkScalar ByteDivToScalar(int numer, U8CPU denom) { 54 // cast to keep the answer signed 55 return SkIntToScalar(numer) / (int)denom; 56 } 57 58 void SkRGBToHSV(U8CPU r, U8CPU g, U8CPU b, SkScalar hsv[3]) { 59 SkASSERT(hsv); 60 61 unsigned min = SkMin32(r, SkMin32(g, b)); 62 unsigned max = SkMax32(r, SkMax32(g, b)); 63 unsigned delta = max - min; 64 65 SkScalar v = ByteToScalar(max); 66 SkASSERT(v >= 0 && v <= SK_Scalar1); 67 68 if (0 == delta) { // we're a shade of gray 69 hsv[0] = 0; 70 hsv[1] = 0; 71 hsv[2] = v; 72 return; 73 } 74 75 SkScalar s = ByteDivToScalar(delta, max); 76 SkASSERT(s >= 0 && s <= SK_Scalar1); 77 78 SkScalar h; 79 if (r == max) { 80 h = ByteDivToScalar(g - b, delta); 81 } else if (g == max) { 82 h = SkIntToScalar(2) + ByteDivToScalar(b - r, delta); 83 } else { // b == max 84 h = SkIntToScalar(4) + ByteDivToScalar(r - g, delta); 85 } 86 87 h *= 60; 88 if (h < 0) { 89 h += SkIntToScalar(360); 90 } 91 SkASSERT(h >= 0 && h < SkIntToScalar(360)); 92 93 hsv[0] = h; 94 hsv[1] = s; 95 hsv[2] = v; 96 } 97 98 static inline U8CPU UnitScalarToByte(SkScalar x) { 99 if (x < 0) { 100 return 0; 101 } 102 if (x >= SK_Scalar1) { 103 return 255; 104 } 105 return SkScalarToFixed(x) >> 8; 106 } 107 108 SkColor SkHSVToColor(U8CPU a, const SkScalar hsv[3]) { 109 SkASSERT(hsv); 110 111 U8CPU s = UnitScalarToByte(hsv[1]); 112 U8CPU v = UnitScalarToByte(hsv[2]); 113 114 if (0 == s) { // shade of gray 115 return SkColorSetARGB(a, v, v, v); 116 } 117 SkFixed hx = (hsv[0] < 0 || hsv[0] >= SkIntToScalar(360)) ? 0 : SkScalarToFixed(hsv[0]/60); 118 SkFixed f = hx & 0xFFFF; 119 120 unsigned v_scale = SkAlpha255To256(v); 121 unsigned p = SkAlphaMul(255 - s, v_scale); 122 unsigned q = SkAlphaMul(255 - (s * f >> 16), v_scale); 123 unsigned t = SkAlphaMul(255 - (s * (SK_Fixed1 - f) >> 16), v_scale); 124 125 unsigned r, g, b; 126 127 SkASSERT((unsigned)(hx >> 16) < 6); 128 switch (hx >> 16) { 129 case 0: r = v; g = t; b = p; break; 130 case 1: r = q; g = v; b = p; break; 131 case 2: r = p; g = v; b = t; break; 132 case 3: r = p; g = q; b = v; break; 133 case 4: r = t; g = p; b = v; break; 134 default: r = v; g = p; b = q; break; 135 } 136 return SkColorSetARGB(a, r, g, b); 137 } 138 139