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
InRange(float comp)16 bool InRange(float comp) {
17 return comp >= 0.0f && comp <= 1.0f;
18 }
19
ConvertCMYK2GRAY(float dC,float dM,float dY,float dK)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
ConvertGRAY2CMYK(float dGray)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
ConvertGRAY2RGB(float dGray)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
ConvertRGB2GRAY(float dR,float dG,float dB)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
ConvertCMYK2RGB(float dC,float dM,float dY,float dK)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
ConvertRGB2CMYK(float dR,float dG,float dB)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.
ParseColor(const CPDF_Array & array)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.
ParseColor(const ByteString & str)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
ConvertColorType(int32_t nConvertColorType) const107 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
ToFXColor(int32_t nTransparency) const151 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
operator -(float fColorSub) const179 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
operator /(float fColorDivide) const200 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