1 // Copyright 2017 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "core/fxge/cfx_color.h" 8 9 #include <algorithm> 10 11 #include "core/fpdfapi/parser/cpdf_array.h" 12 #include "core/fpdfapi/parser/cpdf_simple_parser.h" 13 14 namespace { 15 16 bool InRange(float comp) { 17 return comp >= 0.0f && comp <= 1.0f; 18 } 19 20 CFX_Color ConvertCMYK2GRAY(float dC, float dM, float dY, float dK) { 21 if (!InRange(dC) || !InRange(dM) || !InRange(dY) || !InRange(dK)) 22 return CFX_Color(CFX_Color::kGray); 23 return CFX_Color( 24 CFX_Color::kGray, 25 1.0f - std::min(1.0f, 0.3f * dC + 0.59f * dM + 0.11f * dY + dK)); 26 } 27 28 CFX_Color ConvertGRAY2CMYK(float dGray) { 29 if (!InRange(dGray)) 30 return CFX_Color(CFX_Color::kCMYK); 31 return CFX_Color(CFX_Color::kCMYK, 0.0f, 0.0f, 0.0f, 1.0f - dGray); 32 } 33 34 CFX_Color ConvertGRAY2RGB(float dGray) { 35 if (!InRange(dGray)) 36 return CFX_Color(CFX_Color::kRGB); 37 return CFX_Color(CFX_Color::kRGB, dGray, dGray, dGray); 38 } 39 40 CFX_Color ConvertRGB2GRAY(float dR, float dG, float dB) { 41 if (!InRange(dR) || !InRange(dG) || !InRange(dB)) 42 return CFX_Color(CFX_Color::kGray); 43 return CFX_Color(CFX_Color::kGray, 0.3f * dR + 0.59f * dG + 0.11f * dB); 44 } 45 46 CFX_Color ConvertCMYK2RGB(float dC, float dM, float dY, float dK) { 47 if (!InRange(dC) || !InRange(dM) || !InRange(dY) || !InRange(dK)) 48 return CFX_Color(CFX_Color::kRGB); 49 return CFX_Color(CFX_Color::kRGB, 1.0f - std::min(1.0f, dC + dK), 50 1.0f - std::min(1.0f, dM + dK), 51 1.0f - std::min(1.0f, dY + dK)); 52 } 53 54 CFX_Color ConvertRGB2CMYK(float dR, float dG, float dB) { 55 if (!InRange(dR) || !InRange(dG) || !InRange(dB)) 56 return CFX_Color(CFX_Color::kCMYK); 57 58 float c = 1.0f - dR; 59 float m = 1.0f - dG; 60 float y = 1.0f - dB; 61 return CFX_Color(CFX_Color::kCMYK, c, m, y, std::min(c, std::min(m, y))); 62 } 63 64 } // namespace 65 66 // Static. 67 CFX_Color CFX_Color::ParseColor(const CPDF_Array& array) { 68 CFX_Color rt; 69 switch (array.GetCount()) { 70 case 1: 71 rt = CFX_Color(CFX_Color::kGray, array.GetFloatAt(0)); 72 break; 73 case 3: 74 rt = CFX_Color(CFX_Color::kRGB, array.GetFloatAt(0), array.GetFloatAt(1), 75 array.GetFloatAt(2)); 76 break; 77 case 4: 78 rt = CFX_Color(CFX_Color::kCMYK, array.GetFloatAt(0), array.GetFloatAt(1), 79 array.GetFloatAt(2), array.GetFloatAt(3)); 80 break; 81 } 82 return rt; 83 } 84 85 // Static. 86 CFX_Color CFX_Color::ParseColor(const ByteString& str) { 87 CPDF_SimpleParser syntax(str.AsStringView()); 88 if (syntax.FindTagParamFromStart("g", 1)) 89 return CFX_Color(CFX_Color::kGray, FX_atof(syntax.GetWord())); 90 91 if (syntax.FindTagParamFromStart("rg", 3)) { 92 float f1 = FX_atof(syntax.GetWord()); 93 float f2 = FX_atof(syntax.GetWord()); 94 float f3 = FX_atof(syntax.GetWord()); 95 return CFX_Color(CFX_Color::kRGB, f1, f2, f3); 96 } 97 if (syntax.FindTagParamFromStart("k", 4)) { 98 float f1 = FX_atof(syntax.GetWord()); 99 float f2 = FX_atof(syntax.GetWord()); 100 float f3 = FX_atof(syntax.GetWord()); 101 float f4 = FX_atof(syntax.GetWord()); 102 return CFX_Color(CFX_Color::kCMYK, f1, f2, f3, f4); 103 } 104 return CFX_Color(CFX_Color::kTransparent); 105 } 106 107 CFX_Color CFX_Color::ConvertColorType(int32_t nConvertColorType) const { 108 if (nColorType == nConvertColorType) 109 return *this; 110 111 CFX_Color ret; 112 switch (nColorType) { 113 case CFX_Color::kTransparent: 114 ret = *this; 115 ret.nColorType = CFX_Color::kTransparent; 116 break; 117 case CFX_Color::kGray: 118 switch (nConvertColorType) { 119 case CFX_Color::kRGB: 120 ret = ConvertGRAY2RGB(fColor1); 121 break; 122 case CFX_Color::kCMYK: 123 ret = ConvertGRAY2CMYK(fColor1); 124 break; 125 } 126 break; 127 case CFX_Color::kRGB: 128 switch (nConvertColorType) { 129 case CFX_Color::kGray: 130 ret = ConvertRGB2GRAY(fColor1, fColor2, fColor3); 131 break; 132 case CFX_Color::kCMYK: 133 ret = ConvertRGB2CMYK(fColor1, fColor2, fColor3); 134 break; 135 } 136 break; 137 case CFX_Color::kCMYK: 138 switch (nConvertColorType) { 139 case CFX_Color::kGray: 140 ret = ConvertCMYK2GRAY(fColor1, fColor2, fColor3, fColor4); 141 break; 142 case CFX_Color::kRGB: 143 ret = ConvertCMYK2RGB(fColor1, fColor2, fColor3, fColor4); 144 break; 145 } 146 break; 147 } 148 return ret; 149 } 150 151 FX_COLORREF CFX_Color::ToFXColor(int32_t nTransparency) const { 152 CFX_Color ret; 153 switch (nColorType) { 154 case CFX_Color::kTransparent: { 155 ret = CFX_Color(CFX_Color::kTransparent, 0, 0, 0, 0); 156 break; 157 } 158 case CFX_Color::kGray: { 159 ret = ConvertGRAY2RGB(fColor1); 160 ret.fColor4 = nTransparency; 161 break; 162 } 163 case CFX_Color::kRGB: { 164 ret = CFX_Color(CFX_Color::kRGB, fColor1, fColor2, fColor3); 165 ret.fColor4 = nTransparency; 166 break; 167 } 168 case CFX_Color::kCMYK: { 169 ret = ConvertCMYK2RGB(fColor1, fColor2, fColor3, fColor4); 170 ret.fColor4 = nTransparency; 171 break; 172 } 173 } 174 return ArgbEncode(ret.fColor4, static_cast<int32_t>(ret.fColor1 * 255), 175 static_cast<int32_t>(ret.fColor2 * 255), 176 static_cast<int32_t>(ret.fColor3 * 255)); 177 } 178 179 CFX_Color CFX_Color::operator-(float fColorSub) const { 180 CFX_Color sRet(nColorType); 181 switch (nColorType) { 182 case CFX_Color::kTransparent: 183 sRet.nColorType = CFX_Color::kRGB; 184 sRet.fColor1 = std::max(1.0f - fColorSub, 0.0f); 185 sRet.fColor2 = std::max(1.0f - fColorSub, 0.0f); 186 sRet.fColor3 = std::max(1.0f - fColorSub, 0.0f); 187 break; 188 case CFX_Color::kRGB: 189 case CFX_Color::kGray: 190 case CFX_Color::kCMYK: 191 sRet.fColor1 = std::max(fColor1 - fColorSub, 0.0f); 192 sRet.fColor2 = std::max(fColor2 - fColorSub, 0.0f); 193 sRet.fColor3 = std::max(fColor3 - fColorSub, 0.0f); 194 sRet.fColor4 = std::max(fColor4 - fColorSub, 0.0f); 195 break; 196 } 197 return sRet; 198 } 199 200 CFX_Color CFX_Color::operator/(float fColorDivide) const { 201 CFX_Color sRet(nColorType); 202 switch (nColorType) { 203 case CFX_Color::kTransparent: 204 sRet.nColorType = CFX_Color::kRGB; 205 sRet.fColor1 = 1.0f / fColorDivide; 206 sRet.fColor2 = 1.0f / fColorDivide; 207 sRet.fColor3 = 1.0f / fColorDivide; 208 break; 209 case CFX_Color::kRGB: 210 case CFX_Color::kGray: 211 case CFX_Color::kCMYK: 212 sRet = *this; 213 sRet.fColor1 /= fColorDivide; 214 sRet.fColor2 /= fColorDivide; 215 sRet.fColor3 /= fColorDivide; 216 sRet.fColor4 /= fColorDivide; 217 break; 218 } 219 return sRet; 220 } 221