xref: /aosp_15_r20/external/pdfium/core/fxge/cfx_color.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2017 The PDFium Authors
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 "third_party/base/notreached.h"
12 
13 // Color types are ordered by increasing number of components so we can choose
14 // a best color type during some conversions.
15 static_assert(CFX_Color::Type::kTransparent < CFX_Color::Type::kGray,
16               "color type values must be ordered");
17 static_assert(CFX_Color::Type::kGray < CFX_Color::Type::kRGB,
18               "color type values must be ordered");
19 static_assert(CFX_Color::Type::kRGB < CFX_Color::Type::kCMYK,
20               "color type values must be ordered");
21 
22 namespace {
23 
InRange(float comp)24 bool InRange(float comp) {
25   return comp >= 0.0f && comp <= 1.0f;
26 }
27 
ConvertCMYK2GRAY(float dC,float dM,float dY,float dK)28 CFX_Color ConvertCMYK2GRAY(float dC, float dM, float dY, float dK) {
29   if (!InRange(dC) || !InRange(dM) || !InRange(dY) || !InRange(dK))
30     return CFX_Color(CFX_Color::Type::kGray);
31   return CFX_Color(
32       CFX_Color::Type::kGray,
33       1.0f - std::min(1.0f, 0.3f * dC + 0.59f * dM + 0.11f * dY + dK));
34 }
35 
ConvertGRAY2CMYK(float dGray)36 CFX_Color ConvertGRAY2CMYK(float dGray) {
37   if (!InRange(dGray))
38     return CFX_Color(CFX_Color::Type::kCMYK);
39   return CFX_Color(CFX_Color::Type::kCMYK, 0.0f, 0.0f, 0.0f, 1.0f - dGray);
40 }
41 
ConvertGRAY2RGB(float dGray)42 CFX_Color ConvertGRAY2RGB(float dGray) {
43   if (!InRange(dGray))
44     return CFX_Color(CFX_Color::Type::kRGB);
45   return CFX_Color(CFX_Color::Type::kRGB, dGray, dGray, dGray);
46 }
47 
ConvertRGB2GRAY(float dR,float dG,float dB)48 CFX_Color ConvertRGB2GRAY(float dR, float dG, float dB) {
49   if (!InRange(dR) || !InRange(dG) || !InRange(dB))
50     return CFX_Color(CFX_Color::Type::kGray);
51   return CFX_Color(CFX_Color::Type::kGray, 0.3f * dR + 0.59f * dG + 0.11f * dB);
52 }
53 
ConvertCMYK2RGB(float dC,float dM,float dY,float dK)54 CFX_Color ConvertCMYK2RGB(float dC, float dM, float dY, float dK) {
55   if (!InRange(dC) || !InRange(dM) || !InRange(dY) || !InRange(dK))
56     return CFX_Color(CFX_Color::Type::kRGB);
57   return CFX_Color(CFX_Color::Type::kRGB, 1.0f - std::min(1.0f, dC + dK),
58                    1.0f - std::min(1.0f, dM + dK),
59                    1.0f - std::min(1.0f, dY + dK));
60 }
61 
ConvertRGB2CMYK(float dR,float dG,float dB)62 CFX_Color ConvertRGB2CMYK(float dR, float dG, float dB) {
63   if (!InRange(dR) || !InRange(dG) || !InRange(dB))
64     return CFX_Color(CFX_Color::Type::kCMYK);
65 
66   float c = 1.0f - dR;
67   float m = 1.0f - dG;
68   float y = 1.0f - dB;
69   return CFX_Color(CFX_Color::Type::kCMYK, c, m, y,
70                    std::min(c, std::min(m, y)));
71 }
72 
73 }  // namespace
74 
ConvertColorType(Type nConvertColorType) const75 CFX_Color CFX_Color::ConvertColorType(Type nConvertColorType) const {
76   if (nColorType == nConvertColorType)
77     return *this;
78 
79   CFX_Color ret;
80   switch (nColorType) {
81     case CFX_Color::Type::kTransparent:
82       ret = *this;
83       ret.nColorType = CFX_Color::Type::kTransparent;
84       break;
85     case CFX_Color::Type::kGray:
86       switch (nConvertColorType) {
87         case CFX_Color::Type::kTransparent:
88           break;
89         case CFX_Color::Type::kGray:
90           NOTREACHED_NORETURN();
91         case CFX_Color::Type::kRGB:
92           ret = ConvertGRAY2RGB(fColor1);
93           break;
94         case CFX_Color::Type::kCMYK:
95           ret = ConvertGRAY2CMYK(fColor1);
96           break;
97       }
98       break;
99     case CFX_Color::Type::kRGB:
100       switch (nConvertColorType) {
101         case CFX_Color::Type::kTransparent:
102           break;
103         case CFX_Color::Type::kGray:
104           ret = ConvertRGB2GRAY(fColor1, fColor2, fColor3);
105           break;
106         case CFX_Color::Type::kRGB:
107           NOTREACHED_NORETURN();
108         case CFX_Color::Type::kCMYK:
109           ret = ConvertRGB2CMYK(fColor1, fColor2, fColor3);
110           break;
111       }
112       break;
113     case CFX_Color::Type::kCMYK:
114       switch (nConvertColorType) {
115         case CFX_Color::Type::kTransparent:
116           break;
117         case CFX_Color::Type::kGray:
118           ret = ConvertCMYK2GRAY(fColor1, fColor2, fColor3, fColor4);
119           break;
120         case CFX_Color::Type::kRGB:
121           ret = ConvertCMYK2RGB(fColor1, fColor2, fColor3, fColor4);
122           break;
123         case CFX_Color::Type::kCMYK:
124           NOTREACHED_NORETURN();
125       }
126       break;
127   }
128   return ret;
129 }
130 
ToFXColor(int32_t nTransparency) const131 FX_COLORREF CFX_Color::ToFXColor(int32_t nTransparency) const {
132   CFX_Color ret;
133   switch (nColorType) {
134     case CFX_Color::Type::kTransparent: {
135       ret = CFX_Color(CFX_Color::Type::kTransparent, 0, 0, 0, 0);
136       break;
137     }
138     case CFX_Color::Type::kGray: {
139       ret = ConvertGRAY2RGB(fColor1);
140       ret.fColor4 = nTransparency;
141       break;
142     }
143     case CFX_Color::Type::kRGB: {
144       ret = CFX_Color(CFX_Color::Type::kRGB, fColor1, fColor2, fColor3);
145       ret.fColor4 = nTransparency;
146       break;
147     }
148     case CFX_Color::Type::kCMYK: {
149       ret = ConvertCMYK2RGB(fColor1, fColor2, fColor3, fColor4);
150       ret.fColor4 = nTransparency;
151       break;
152     }
153   }
154   return ArgbEncode(ret.fColor4, static_cast<int32_t>(ret.fColor1 * 255),
155                     static_cast<int32_t>(ret.fColor2 * 255),
156                     static_cast<int32_t>(ret.fColor3 * 255));
157 }
158 
operator -(float fColorSub) const159 CFX_Color CFX_Color::operator-(float fColorSub) const {
160   CFX_Color sRet(nColorType);
161   switch (nColorType) {
162     case CFX_Color::Type::kTransparent:
163       sRet.nColorType = CFX_Color::Type::kRGB;
164       sRet.fColor1 = std::max(1.0f - fColorSub, 0.0f);
165       sRet.fColor2 = std::max(1.0f - fColorSub, 0.0f);
166       sRet.fColor3 = std::max(1.0f - fColorSub, 0.0f);
167       break;
168     case CFX_Color::Type::kRGB:
169     case CFX_Color::Type::kGray:
170     case CFX_Color::Type::kCMYK:
171       sRet.fColor1 = std::max(fColor1 - fColorSub, 0.0f);
172       sRet.fColor2 = std::max(fColor2 - fColorSub, 0.0f);
173       sRet.fColor3 = std::max(fColor3 - fColorSub, 0.0f);
174       sRet.fColor4 = std::max(fColor4 - fColorSub, 0.0f);
175       break;
176   }
177   return sRet;
178 }
179 
operator /(float fColorDivide) const180 CFX_Color CFX_Color::operator/(float fColorDivide) const {
181   CFX_Color sRet(nColorType);
182   switch (nColorType) {
183     case CFX_Color::Type::kTransparent:
184       sRet.nColorType = CFX_Color::Type::kRGB;
185       sRet.fColor1 = 1.0f / fColorDivide;
186       sRet.fColor2 = 1.0f / fColorDivide;
187       sRet.fColor3 = 1.0f / fColorDivide;
188       break;
189     case CFX_Color::Type::kRGB:
190     case CFX_Color::Type::kGray:
191     case CFX_Color::Type::kCMYK:
192       sRet = *this;
193       sRet.fColor1 /= fColorDivide;
194       sRet.fColor2 /= fColorDivide;
195       sRet.fColor3 /= fColorDivide;
196       sRet.fColor4 /= fColorDivide;
197       break;
198   }
199   return sRet;
200 }
201