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 "fpdfsdk/pdfwindow/cpwl_color.h"
8 
9 #include <algorithm>
10 
11 namespace {
12 
InRange(FX_FLOAT comp)13 bool InRange(FX_FLOAT comp) {
14   return comp >= 0.0f && comp <= 1.0f;
15 }
16 
ConvertCMYK2GRAY(FX_FLOAT dC,FX_FLOAT dM,FX_FLOAT dY,FX_FLOAT dK)17 CPWL_Color ConvertCMYK2GRAY(FX_FLOAT dC,
18                             FX_FLOAT dM,
19                             FX_FLOAT dY,
20                             FX_FLOAT dK) {
21   if (!InRange(dC) || !InRange(dM) || !InRange(dY) || !InRange(dK))
22     return CPWL_Color(COLORTYPE_GRAY);
23   return CPWL_Color(
24       COLORTYPE_GRAY,
25       1.0f - std::min(1.0f, 0.3f * dC + 0.59f * dM + 0.11f * dY + dK));
26 }
27 
ConvertGRAY2CMYK(FX_FLOAT dGray)28 CPWL_Color ConvertGRAY2CMYK(FX_FLOAT dGray) {
29   if (!InRange(dGray))
30     return CPWL_Color(COLORTYPE_CMYK);
31   return CPWL_Color(COLORTYPE_CMYK, 0.0f, 0.0f, 0.0f, 1.0f - dGray);
32 }
33 
ConvertGRAY2RGB(FX_FLOAT dGray)34 CPWL_Color ConvertGRAY2RGB(FX_FLOAT dGray) {
35   if (!InRange(dGray))
36     return CPWL_Color(COLORTYPE_RGB);
37   return CPWL_Color(COLORTYPE_RGB, dGray, dGray, dGray);
38 }
39 
ConvertRGB2GRAY(FX_FLOAT dR,FX_FLOAT dG,FX_FLOAT dB)40 CPWL_Color ConvertRGB2GRAY(FX_FLOAT dR, FX_FLOAT dG, FX_FLOAT dB) {
41   if (!InRange(dR) || !InRange(dG) || !InRange(dB))
42     return CPWL_Color(COLORTYPE_GRAY);
43   return CPWL_Color(COLORTYPE_GRAY, 0.3f * dR + 0.59f * dG + 0.11f * dB);
44 }
45 
ConvertCMYK2RGB(FX_FLOAT dC,FX_FLOAT dM,FX_FLOAT dY,FX_FLOAT dK)46 CPWL_Color ConvertCMYK2RGB(FX_FLOAT dC, FX_FLOAT dM, FX_FLOAT dY, FX_FLOAT dK) {
47   if (!InRange(dC) || !InRange(dM) || !InRange(dY) || !InRange(dK))
48     return CPWL_Color(COLORTYPE_RGB);
49   return CPWL_Color(COLORTYPE_RGB, 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(FX_FLOAT dR,FX_FLOAT dG,FX_FLOAT dB)54 CPWL_Color ConvertRGB2CMYK(FX_FLOAT dR, FX_FLOAT dG, FX_FLOAT dB) {
55   if (!InRange(dR) || !InRange(dG) || !InRange(dB))
56     return CPWL_Color(COLORTYPE_CMYK);
57 
58   FX_FLOAT c = 1.0f - dR;
59   FX_FLOAT m = 1.0f - dG;
60   FX_FLOAT y = 1.0f - dB;
61   return CPWL_Color(COLORTYPE_CMYK, c, m, y, std::min(c, std::min(m, y)));
62 }
63 
64 }  // namespace
65 
ConvertColorType(int32_t nConvertColorType) const66 CPWL_Color CPWL_Color::ConvertColorType(int32_t nConvertColorType) const {
67   if (nColorType == nConvertColorType)
68     return *this;
69 
70   CPWL_Color ret;
71   switch (nColorType) {
72     case COLORTYPE_TRANSPARENT:
73       ret = *this;
74       ret.nColorType = COLORTYPE_TRANSPARENT;
75       break;
76     case COLORTYPE_GRAY:
77       switch (nConvertColorType) {
78         case COLORTYPE_RGB:
79           ret = ConvertGRAY2RGB(fColor1);
80           break;
81         case COLORTYPE_CMYK:
82           ret = ConvertGRAY2CMYK(fColor1);
83           break;
84       }
85       break;
86     case COLORTYPE_RGB:
87       switch (nConvertColorType) {
88         case COLORTYPE_GRAY:
89           ret = ConvertRGB2GRAY(fColor1, fColor2, fColor3);
90           break;
91         case COLORTYPE_CMYK:
92           ret = ConvertRGB2CMYK(fColor1, fColor2, fColor3);
93           break;
94       }
95       break;
96     case COLORTYPE_CMYK:
97       switch (nConvertColorType) {
98         case COLORTYPE_GRAY:
99           ret = ConvertCMYK2GRAY(fColor1, fColor2, fColor3, fColor4);
100           break;
101         case COLORTYPE_RGB:
102           ret = ConvertCMYK2RGB(fColor1, fColor2, fColor3, fColor4);
103           break;
104       }
105       break;
106   }
107   return ret;
108 }
109 
ToFXColor(int32_t nTransparency) const110 FX_COLORREF CPWL_Color::ToFXColor(int32_t nTransparency) const {
111   CPWL_Color ret;
112   switch (nColorType) {
113     case COLORTYPE_TRANSPARENT: {
114       ret = CPWL_Color(COLORTYPE_TRANSPARENT, 0, 0, 0, 0);
115       break;
116     }
117     case COLORTYPE_GRAY: {
118       ret = ConvertGRAY2RGB(fColor1);
119       ret.fColor4 = nTransparency;
120       break;
121     }
122     case COLORTYPE_RGB: {
123       ret = CPWL_Color(COLORTYPE_RGB, fColor1, fColor2, fColor3);
124       ret.fColor4 = nTransparency;
125       break;
126     }
127     case COLORTYPE_CMYK: {
128       ret = ConvertCMYK2RGB(fColor1, fColor2, fColor3, fColor4);
129       ret.fColor4 = nTransparency;
130       break;
131     }
132   }
133   return ArgbEncode(ret.fColor4, static_cast<int32_t>(ret.fColor1 * 255),
134                     static_cast<int32_t>(ret.fColor2 * 255),
135                     static_cast<int32_t>(ret.fColor3 * 255));
136 }
137 
operator -(FX_FLOAT fColorSub) const138 CPWL_Color CPWL_Color::operator-(FX_FLOAT fColorSub) const {
139   CPWL_Color sRet(nColorType);
140   switch (nColorType) {
141     case COLORTYPE_TRANSPARENT:
142       sRet.nColorType = COLORTYPE_RGB;
143       sRet.fColor1 = std::max(1.0f - fColorSub, 0.0f);
144       sRet.fColor2 = std::max(1.0f - fColorSub, 0.0f);
145       sRet.fColor3 = std::max(1.0f - fColorSub, 0.0f);
146       break;
147     case COLORTYPE_RGB:
148     case COLORTYPE_GRAY:
149     case COLORTYPE_CMYK:
150       sRet.fColor1 = std::max(fColor1 - fColorSub, 0.0f);
151       sRet.fColor2 = std::max(fColor2 - fColorSub, 0.0f);
152       sRet.fColor3 = std::max(fColor3 - fColorSub, 0.0f);
153       sRet.fColor4 = std::max(fColor4 - fColorSub, 0.0f);
154       break;
155   }
156   return sRet;
157 }
158 
operator /(FX_FLOAT fColorDivide) const159 CPWL_Color CPWL_Color::operator/(FX_FLOAT fColorDivide) const {
160   CPWL_Color sRet(nColorType);
161   switch (nColorType) {
162     case COLORTYPE_TRANSPARENT:
163       sRet.nColorType = COLORTYPE_RGB;
164       sRet.fColor1 = 1.0f / fColorDivide;
165       sRet.fColor2 = 1.0f / fColorDivide;
166       sRet.fColor3 = 1.0f / fColorDivide;
167       break;
168     case COLORTYPE_RGB:
169     case COLORTYPE_GRAY:
170     case COLORTYPE_CMYK:
171       sRet = *this;
172       sRet.fColor1 /= fColorDivide;
173       sRet.fColor2 /= fColorDivide;
174       sRet.fColor3 /= fColorDivide;
175       sRet.fColor4 /= fColorDivide;
176       break;
177   }
178   return sRet;
179 }
180