xref: /aosp_15_r20/external/pdfium/fxjs/cjs_color.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2014 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 "fxjs/cjs_color.h"
8 
9 #include <algorithm>
10 #include <vector>
11 
12 #include "core/fxge/cfx_color.h"
13 #include "fxjs/cjs_event_context.h"
14 #include "fxjs/cjs_object.h"
15 #include "fxjs/cjs_runtime.h"
16 #include "fxjs/fxv8.h"
17 #include "fxjs/js_define.h"
18 #include "v8/include/v8-container.h"
19 
20 const JSPropertySpec CJS_Color::PropertySpecs[] = {
21     {"black", get_black_static, set_black_static},
22     {"blue", get_blue_static, set_blue_static},
23     {"cyan", get_cyan_static, set_cyan_static},
24     {"dkGray", get_dark_gray_static, set_dark_gray_static},
25     {"gray", get_gray_static, set_gray_static},
26     {"green", get_green_static, set_green_static},
27     {"ltGray", get_light_gray_static, set_light_gray_static},
28     {"magenta", get_magenta_static, set_magenta_static},
29     {"red", get_red_static, set_red_static},
30     {"transparent", get_transparent_static, set_transparent_static},
31     {"white", get_white_static, set_white_static},
32     {"yellow", get_yellow_static, set_yellow_static}};
33 
34 const JSMethodSpec CJS_Color::MethodSpecs[] = {{"convert", convert_static},
35                                                {"equal", equal_static}};
36 
37 uint32_t CJS_Color::ObjDefnID = 0;
38 const char CJS_Color::kName[] = "color";
39 
40 // static
GetObjDefnID()41 uint32_t CJS_Color::GetObjDefnID() {
42   return ObjDefnID;
43 }
44 
45 // static
DefineJSObjects(CFXJS_Engine * pEngine)46 void CJS_Color::DefineJSObjects(CFXJS_Engine* pEngine) {
47   ObjDefnID = pEngine->DefineObj(CJS_Color::kName, FXJSOBJTYPE_STATIC,
48                                  JSConstructor<CJS_Color>, JSDestructor);
49   DefineProps(pEngine, ObjDefnID, PropertySpecs);
50   DefineMethods(pEngine, ObjDefnID, MethodSpecs);
51 }
52 
53 // static
ConvertPWLColorToArray(CJS_Runtime * pRuntime,const CFX_Color & color)54 v8::Local<v8::Array> CJS_Color::ConvertPWLColorToArray(CJS_Runtime* pRuntime,
55                                                        const CFX_Color& color) {
56   v8::Local<v8::Array> array;
57   switch (color.nColorType) {
58     case CFX_Color::Type::kTransparent:
59       array = pRuntime->NewArray();
60       pRuntime->PutArrayElement(array, 0, pRuntime->NewString("T"));
61       break;
62     case CFX_Color::Type::kGray:
63       array = pRuntime->NewArray();
64       pRuntime->PutArrayElement(array, 0, pRuntime->NewString("G"));
65       pRuntime->PutArrayElement(array, 1, pRuntime->NewNumber(color.fColor1));
66       break;
67     case CFX_Color::Type::kRGB:
68       array = pRuntime->NewArray();
69       pRuntime->PutArrayElement(array, 0, pRuntime->NewString("RGB"));
70       pRuntime->PutArrayElement(array, 1, pRuntime->NewNumber(color.fColor1));
71       pRuntime->PutArrayElement(array, 2, pRuntime->NewNumber(color.fColor2));
72       pRuntime->PutArrayElement(array, 3, pRuntime->NewNumber(color.fColor3));
73       break;
74     case CFX_Color::Type::kCMYK:
75       array = pRuntime->NewArray();
76       pRuntime->PutArrayElement(array, 0, pRuntime->NewString("CMYK"));
77       pRuntime->PutArrayElement(array, 1, pRuntime->NewNumber(color.fColor1));
78       pRuntime->PutArrayElement(array, 2, pRuntime->NewNumber(color.fColor2));
79       pRuntime->PutArrayElement(array, 3, pRuntime->NewNumber(color.fColor3));
80       pRuntime->PutArrayElement(array, 4, pRuntime->NewNumber(color.fColor4));
81       break;
82   }
83   return array;
84 }
85 
86 // static
ConvertArrayToPWLColor(CJS_Runtime * pRuntime,v8::Local<v8::Array> array)87 CFX_Color CJS_Color::ConvertArrayToPWLColor(CJS_Runtime* pRuntime,
88                                             v8::Local<v8::Array> array) {
89   size_t nArrayLen = pRuntime->GetArrayLength(array);
90   if (nArrayLen == 0)
91     return CFX_Color();
92 
93   WideString sSpace =
94       pRuntime->ToWideString(pRuntime->GetArrayElement(array, 0));
95   if (sSpace.EqualsASCII("T"))
96     return CFX_Color(CFX_Color::Type::kTransparent);
97 
98   float d1 = 0;
99   if (nArrayLen > 1) {
100     d1 = static_cast<float>(
101         pRuntime->ToDouble(pRuntime->GetArrayElement(array, 1)));
102   }
103   if (sSpace.EqualsASCII("G"))
104     return CFX_Color(CFX_Color::Type::kGray, d1);
105 
106   float d2 = 0;
107   float d3 = 0;
108   if (nArrayLen > 2) {
109     d2 = static_cast<float>(
110         pRuntime->ToDouble(pRuntime->GetArrayElement(array, 2)));
111   }
112   if (nArrayLen > 3) {
113     d3 = static_cast<float>(
114         pRuntime->ToDouble(pRuntime->GetArrayElement(array, 3)));
115   }
116   if (sSpace.EqualsASCII("RGB"))
117     return CFX_Color(CFX_Color::Type::kRGB, d1, d2, d3);
118 
119   float d4 = 0;
120   if (nArrayLen > 4) {
121     d4 = static_cast<float>(
122         pRuntime->ToDouble(pRuntime->GetArrayElement(array, 4)));
123   }
124   if (sSpace.EqualsASCII("CMYK"))
125     return CFX_Color(CFX_Color::Type::kCMYK, d1, d2, d3, d4);
126 
127   return CFX_Color();
128 }
129 
CJS_Color(v8::Local<v8::Object> pObject,CJS_Runtime * pRuntime)130 CJS_Color::CJS_Color(v8::Local<v8::Object> pObject, CJS_Runtime* pRuntime)
131     : CJS_Object(pObject, pRuntime),
132       m_crTransparent(CFX_Color::Type::kTransparent),
133       m_crBlack(CFX_Color::Type::kGray, 0),
134       m_crWhite(CFX_Color::Type::kGray, 1),
135       m_crRed(CFX_Color::Type::kRGB, 1, 0, 0),
136       m_crGreen(CFX_Color::Type::kRGB, 0, 1, 0),
137       m_crBlue(CFX_Color::Type::kRGB, 0, 0, 1),
138       m_crCyan(CFX_Color::Type::kCMYK, 1, 0, 0, 0),
139       m_crMagenta(CFX_Color::Type::kCMYK, 0, 1, 0, 0),
140       m_crYellow(CFX_Color::Type::kCMYK, 0, 0, 1, 0),
141       m_crDKGray(CFX_Color::Type::kGray, 0.25),
142       m_crGray(CFX_Color::Type::kGray, 0.5),
143       m_crLTGray(CFX_Color::Type::kGray, 0.75) {}
144 
145 CJS_Color::~CJS_Color() = default;
146 
get_transparent(CJS_Runtime * pRuntime)147 CJS_Result CJS_Color::get_transparent(CJS_Runtime* pRuntime) {
148   return GetPropertyHelper(pRuntime, &m_crTransparent);
149 }
150 
set_transparent(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)151 CJS_Result CJS_Color::set_transparent(CJS_Runtime* pRuntime,
152                                       v8::Local<v8::Value> vp) {
153   return SetPropertyHelper(pRuntime, vp, &m_crTransparent);
154 }
155 
get_black(CJS_Runtime * pRuntime)156 CJS_Result CJS_Color::get_black(CJS_Runtime* pRuntime) {
157   return GetPropertyHelper(pRuntime, &m_crBlack);
158 }
159 
set_black(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)160 CJS_Result CJS_Color::set_black(CJS_Runtime* pRuntime,
161                                 v8::Local<v8::Value> vp) {
162   return SetPropertyHelper(pRuntime, vp, &m_crBlack);
163 }
164 
get_white(CJS_Runtime * pRuntime)165 CJS_Result CJS_Color::get_white(CJS_Runtime* pRuntime) {
166   return GetPropertyHelper(pRuntime, &m_crWhite);
167 }
168 
set_white(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)169 CJS_Result CJS_Color::set_white(CJS_Runtime* pRuntime,
170                                 v8::Local<v8::Value> vp) {
171   return SetPropertyHelper(pRuntime, vp, &m_crWhite);
172 }
173 
get_red(CJS_Runtime * pRuntime)174 CJS_Result CJS_Color::get_red(CJS_Runtime* pRuntime) {
175   return GetPropertyHelper(pRuntime, &m_crRed);
176 }
177 
set_red(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)178 CJS_Result CJS_Color::set_red(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
179   return SetPropertyHelper(pRuntime, vp, &m_crRed);
180 }
181 
get_green(CJS_Runtime * pRuntime)182 CJS_Result CJS_Color::get_green(CJS_Runtime* pRuntime) {
183   return GetPropertyHelper(pRuntime, &m_crGreen);
184 }
185 
set_green(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)186 CJS_Result CJS_Color::set_green(CJS_Runtime* pRuntime,
187                                 v8::Local<v8::Value> vp) {
188   return SetPropertyHelper(pRuntime, vp, &m_crGreen);
189 }
190 
get_blue(CJS_Runtime * pRuntime)191 CJS_Result CJS_Color::get_blue(CJS_Runtime* pRuntime) {
192   return GetPropertyHelper(pRuntime, &m_crBlue);
193 }
194 
set_blue(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)195 CJS_Result CJS_Color::set_blue(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
196   return SetPropertyHelper(pRuntime, vp, &m_crBlue);
197 }
198 
get_cyan(CJS_Runtime * pRuntime)199 CJS_Result CJS_Color::get_cyan(CJS_Runtime* pRuntime) {
200   return GetPropertyHelper(pRuntime, &m_crCyan);
201 }
202 
set_cyan(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)203 CJS_Result CJS_Color::set_cyan(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
204   return SetPropertyHelper(pRuntime, vp, &m_crCyan);
205 }
206 
get_magenta(CJS_Runtime * pRuntime)207 CJS_Result CJS_Color::get_magenta(CJS_Runtime* pRuntime) {
208   return GetPropertyHelper(pRuntime, &m_crMagenta);
209 }
210 
set_magenta(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)211 CJS_Result CJS_Color::set_magenta(CJS_Runtime* pRuntime,
212                                   v8::Local<v8::Value> vp) {
213   return SetPropertyHelper(pRuntime, vp, &m_crMagenta);
214 }
215 
get_yellow(CJS_Runtime * pRuntime)216 CJS_Result CJS_Color::get_yellow(CJS_Runtime* pRuntime) {
217   return GetPropertyHelper(pRuntime, &m_crYellow);
218 }
219 
set_yellow(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)220 CJS_Result CJS_Color::set_yellow(CJS_Runtime* pRuntime,
221                                  v8::Local<v8::Value> vp) {
222   return SetPropertyHelper(pRuntime, vp, &m_crYellow);
223 }
224 
get_dark_gray(CJS_Runtime * pRuntime)225 CJS_Result CJS_Color::get_dark_gray(CJS_Runtime* pRuntime) {
226   return GetPropertyHelper(pRuntime, &m_crDKGray);
227 }
228 
set_dark_gray(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)229 CJS_Result CJS_Color::set_dark_gray(CJS_Runtime* pRuntime,
230                                     v8::Local<v8::Value> vp) {
231   return SetPropertyHelper(pRuntime, vp, &m_crDKGray);
232 }
233 
get_gray(CJS_Runtime * pRuntime)234 CJS_Result CJS_Color::get_gray(CJS_Runtime* pRuntime) {
235   return GetPropertyHelper(pRuntime, &m_crGray);
236 }
237 
set_gray(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)238 CJS_Result CJS_Color::set_gray(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
239   return SetPropertyHelper(pRuntime, vp, &m_crGray);
240 }
241 
get_light_gray(CJS_Runtime * pRuntime)242 CJS_Result CJS_Color::get_light_gray(CJS_Runtime* pRuntime) {
243   return GetPropertyHelper(pRuntime, &m_crLTGray);
244 }
245 
set_light_gray(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)246 CJS_Result CJS_Color::set_light_gray(CJS_Runtime* pRuntime,
247                                      v8::Local<v8::Value> vp) {
248   return SetPropertyHelper(pRuntime, vp, &m_crLTGray);
249 }
250 
GetPropertyHelper(CJS_Runtime * pRuntime,CFX_Color * var)251 CJS_Result CJS_Color::GetPropertyHelper(CJS_Runtime* pRuntime, CFX_Color* var) {
252   v8::Local<v8::Value> array = ConvertPWLColorToArray(pRuntime, *var);
253   if (array.IsEmpty())
254     return CJS_Result::Success(pRuntime->NewArray());
255 
256   return CJS_Result::Success(array);
257 }
258 
SetPropertyHelper(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp,CFX_Color * var)259 CJS_Result CJS_Color::SetPropertyHelper(CJS_Runtime* pRuntime,
260                                         v8::Local<v8::Value> vp,
261                                         CFX_Color* var) {
262   if (vp.IsEmpty())
263     return CJS_Result::Failure(JSMessage::kParamError);
264 
265   if (!vp->IsArray())
266     return CJS_Result::Failure(JSMessage::kTypeError);
267 
268   *var = ConvertArrayToPWLColor(pRuntime, pRuntime->ToArray(vp));
269   return CJS_Result::Success();
270 }
271 
convert(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)272 CJS_Result CJS_Color::convert(CJS_Runtime* pRuntime,
273                               const std::vector<v8::Local<v8::Value>>& params) {
274   if (params.size() < 2)
275     return CJS_Result::Failure(JSMessage::kParamError);
276 
277   if (!fxv8::IsArray(params[0]))
278     return CJS_Result::Failure(JSMessage::kTypeError);
279 
280   WideString sDestSpace = pRuntime->ToWideString(params[1]);
281   CFX_Color::Type nColorType = CFX_Color::Type::kTransparent;
282   if (sDestSpace.EqualsASCII("T"))
283     nColorType = CFX_Color::Type::kTransparent;
284   else if (sDestSpace.EqualsASCII("G"))
285     nColorType = CFX_Color::Type::kGray;
286   else if (sDestSpace.EqualsASCII("RGB"))
287     nColorType = CFX_Color::Type::kRGB;
288   else if (sDestSpace.EqualsASCII("CMYK"))
289     nColorType = CFX_Color::Type::kCMYK;
290 
291   CFX_Color color =
292       ConvertArrayToPWLColor(pRuntime, pRuntime->ToArray(params[0]));
293   v8::Local<v8::Value> array =
294       ConvertPWLColorToArray(pRuntime, color.ConvertColorType(nColorType));
295   if (array.IsEmpty())
296     return CJS_Result::Success(pRuntime->NewArray());
297 
298   return CJS_Result::Success(array);
299 }
300 
equal(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)301 CJS_Result CJS_Color::equal(CJS_Runtime* pRuntime,
302                             const std::vector<v8::Local<v8::Value>>& params) {
303   if (params.size() < 2)
304     return CJS_Result::Failure(JSMessage::kParamError);
305 
306   if (!fxv8::IsArray(params[0]) || !fxv8::IsArray(params[1]))
307     return CJS_Result::Failure(JSMessage::kTypeError);
308 
309   CFX_Color color1 =
310       ConvertArrayToPWLColor(pRuntime, pRuntime->ToArray(params[0]));
311   CFX_Color color2 =
312       ConvertArrayToPWLColor(pRuntime, pRuntime->ToArray(params[1]));
313 
314   // Relies on higher values having more components.
315   CFX_Color::Type best = std::max(color1.nColorType, color2.nColorType);
316   return CJS_Result::Success(pRuntime->NewBoolean(
317       color1.ConvertColorType(best) == color2.ConvertColorType(best)));
318 }
319