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