• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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