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