1// Aseprite
2// Copyright (C) 2019-2022 Igara Studio S.A.
3// Copyright (C) 2018 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "app/app.h"
13#include "app/color.h"
14#include "app/color_utils.h"
15#include "app/script/luacpp.h"
16
17namespace app {
18namespace script {
19
20namespace {
21
22app::Color Color_new(lua_State* L, int index)
23{
24 app::Color color;
25 // Copy other color
26 if (auto color2 = may_get_obj<app::Color>(L, index)) {
27 color = *color2;
28 }
29 // Convert table into a Color
30 else if (lua_istable(L, index)) {
31 // Convert { r, g, b } into a Color
32 if (lua_getfield(L, index, "r") != LUA_TNIL) {
33 lua_getfield(L, index, "g");
34 lua_getfield(L, index, "b");
35 int a = 255;
36 if (lua_getfield(L, index, "a") != LUA_TNIL)
37 a = lua_tointeger(L, -1);
38 color = app::Color::fromRgb(lua_tointeger(L, -4),
39 lua_tointeger(L, -3),
40 lua_tointeger(L, -2), a);
41 lua_pop(L, 4);
42 return color;
43 }
44 else
45 lua_pop(L, 1);
46
47 // Convert { red, green, blue } into a Color
48 if (lua_getfield(L, index, "red") != LUA_TNIL) {
49 lua_getfield(L, index, "green");
50 lua_getfield(L, index, "blue");
51 int a = 255;
52 if (lua_getfield(L, index, "alpha") != LUA_TNIL)
53 a = lua_tointeger(L, -1);
54 color = app::Color::fromRgb(lua_tointeger(L, -4),
55 lua_tointeger(L, -3),
56 lua_tointeger(L, -2), a);
57 lua_pop(L, 4);
58 return color;
59 }
60 else
61 lua_pop(L, 1);
62
63 // Convert { h, s, v } into a Color
64 if (lua_getfield(L, index, "v") != LUA_TNIL) {
65 lua_getfield(L, index, "s");
66 lua_getfield(L, index, "h");
67 int a = 255;
68 if (lua_getfield(L, index, "a") != LUA_TNIL)
69 a = lua_tointeger(L, -1);
70 color = app::Color::fromHsv(lua_tonumber(L, -2),
71 lua_tonumber(L, -3),
72 lua_tonumber(L, -4), a);
73 lua_pop(L, 4);
74 return color;
75 }
76 else
77 lua_pop(L, 1);
78
79 // Convert { hue, saturation, value } into a Color
80 if (lua_getfield(L, index, "value") != LUA_TNIL) {
81 lua_getfield(L, index, "saturation");
82 lua_getfield(L, index, "hue");
83 int a = 255;
84 if (lua_getfield(L, index, "alpha") != LUA_TNIL)
85 a = lua_tointeger(L, -1);
86 color = app::Color::fromHsv(lua_tonumber(L, -2),
87 lua_tonumber(L, -3),
88 lua_tonumber(L, -4), a);
89 lua_pop(L, 4);
90 return color;
91 }
92 else
93 lua_pop(L, 1);
94
95 // Convert { h, s, l } into a Color
96 if (lua_getfield(L, index, "l") != LUA_TNIL) {
97 lua_getfield(L, index, "s");
98 lua_getfield(L, index, "h");
99 int a = 255;
100 if (lua_getfield(L, index, "a") != LUA_TNIL)
101 a = lua_tointeger(L, -1);
102 color = app::Color::fromHsl(lua_tonumber(L, -2),
103 lua_tonumber(L, -3),
104 lua_tonumber(L, -4), a);
105 lua_pop(L, 4);
106 return color;
107 }
108 else
109 lua_pop(L, 1);
110
111 // Convert { hue, saturation, lightness } into a Color
112 if (lua_getfield(L, index, "lightness") != LUA_TNIL) {
113 lua_getfield(L, index, "saturation");
114 lua_getfield(L, index, "hue");
115 int a = 255;
116 if (lua_getfield(L, index, "alpha") != LUA_TNIL)
117 a = lua_tointeger(L, -1);
118 color = app::Color::fromHsl(lua_tonumber(L, -2),
119 lua_tonumber(L, -3),
120 lua_tonumber(L, -4), a);
121 lua_pop(L, 4);
122 return color;
123 }
124 else
125 lua_pop(L, 1);
126
127 // Convert { gray } into a Color
128 if (lua_getfield(L, index, "gray") != LUA_TNIL) {
129 int a = 255;
130 if (lua_getfield(L, index, "alpha") != LUA_TNIL)
131 a = lua_tointeger(L, -1);
132 color = app::Color::fromGray(lua_tonumber(L, -2), a);
133 lua_pop(L, 2);
134 return color;
135 }
136 else
137 lua_pop(L, 1);
138
139 // Convert { index } into a Color
140 if (lua_getfield(L, index, "index") != LUA_TNIL) {
141 int i = lua_tointeger(L, -1);
142 color = app::Color::fromIndex(i);
143 lua_pop(L, 1);
144 return color;
145 }
146 else
147 lua_pop(L, 1);
148 }
149 // raw color into app color
150 else if (!lua_isnone(L, index)) {
151 if (lua_isinteger(L, index) && (index < 0 || lua_isnone(L, index+1))) {
152 doc::color_t docColor = lua_tointeger(L, index);
153
154 // TODO depending on current pixel format?
155 switch (app_get_current_pixel_format()) {
156 case IMAGE_RGB:
157 color = app::Color::fromRgb(doc::rgba_getr(docColor),
158 doc::rgba_getg(docColor),
159 doc::rgba_getb(docColor),
160 doc::rgba_geta(docColor));
161 break;
162 case IMAGE_GRAYSCALE:
163 color = app::Color::fromGray(doc::graya_getv(docColor),
164 doc::graya_geta(docColor));
165 break;
166 case IMAGE_INDEXED:
167 color = app::Color::fromIndex(docColor);
168 break;
169 }
170 }
171 else if (index >= 0) {
172 color = app::Color::fromRgb(lua_tointeger(L, index),
173 lua_tointeger(L, index+1),
174 lua_tointeger(L, index+2),
175 lua_isnone(L, index+3) ?
176 255: lua_tointeger(L, index+3));
177 }
178 }
179 return color;
180}
181
182int Color_new(lua_State* L)
183{
184 push_obj(L, Color_new(L, 1));
185 return 1;
186}
187
188int Color_gc(lua_State* L)
189{
190 get_obj<app::Color>(L, 1)->~Color();
191 return 0;
192}
193
194int Color_eq(lua_State* L)
195{
196 const auto a = get_obj<app::Color>(L, 1);
197 const auto b = get_obj<app::Color>(L, 2);
198 lua_pushboolean(L, *a == *b);
199 return 1;
200}
201
202int Color_get_red(lua_State* L)
203{
204 const auto color = get_obj<app::Color>(L, 1);
205 lua_pushinteger(L, color->getRed());
206 return 1;
207}
208
209int Color_get_green(lua_State* L)
210{
211 const auto color = get_obj<app::Color>(L, 1);
212 lua_pushinteger(L, color->getGreen());
213 return 1;
214}
215
216int Color_get_blue(lua_State* L)
217{
218 const auto color = get_obj<app::Color>(L, 1);
219 lua_pushinteger(L, color->getBlue());
220 return 1;
221}
222
223int Color_get_alpha(lua_State* L)
224{
225 const auto color = get_obj<app::Color>(L, 1);
226 lua_pushinteger(L, color->getAlpha());
227 return 1;
228}
229
230int Color_get_hsvHue(lua_State* L)
231{
232 const auto color = get_obj<app::Color>(L, 1);
233 lua_pushnumber(L, color->getHsvHue());
234 return 1;
235}
236
237int Color_get_hsvSaturation(lua_State* L)
238{
239 const auto color = get_obj<app::Color>(L, 1);
240 lua_pushnumber(L, color->getHsvSaturation());
241 return 1;
242}
243
244int Color_get_hsvValue(lua_State* L)
245{
246 const auto color = get_obj<app::Color>(L, 1);
247 lua_pushnumber(L, color->getHsvValue());
248 return 1;
249}
250
251int Color_get_hslHue(lua_State* L)
252{
253 const auto color = get_obj<app::Color>(L, 1);
254 lua_pushnumber(L, color->getHslHue());
255 return 1;
256}
257
258int Color_get_hslSaturation(lua_State* L)
259{
260 const auto color = get_obj<app::Color>(L, 1);
261 lua_pushnumber(L, color->getHslSaturation());
262 return 1;
263}
264
265int Color_get_hslLightness(lua_State* L)
266{
267 const auto color = get_obj<app::Color>(L, 1);
268 lua_pushnumber(L, color->getHslLightness());
269 return 1;
270}
271
272int Color_get_hue(lua_State* L)
273{
274 const auto color = get_obj<app::Color>(L, 1);
275 if (color->getType() == Color::HslType)
276 return Color_get_hslHue(L);
277 else
278 return Color_get_hsvHue(L);
279}
280
281int Color_get_saturation(lua_State* L)
282{
283 const auto color = get_obj<app::Color>(L, 1);
284 if (color->getType() == Color::HslType)
285 return Color_get_hslSaturation(L);
286 else
287 return Color_get_hsvSaturation(L);
288}
289
290int Color_get_gray(lua_State* L)
291{
292 auto color = get_obj<app::Color>(L, 1);
293 lua_pushnumber(L, color->getGray());
294 return 1;
295}
296
297int Color_get_index(lua_State* L)
298{
299 auto color = get_obj<app::Color>(L, 1);
300 lua_pushinteger(L, color->getIndex());
301 return 1;
302}
303
304int Color_get_rgbaPixel(lua_State* L)
305{
306 auto color = get_obj<app::Color>(L, 1);
307 auto pixelColor = color_utils::color_for_target_mask(
308 *color, ColorTarget(ColorTarget::TransparentLayer, IMAGE_RGB, 0));
309 lua_pushinteger(L, pixelColor);
310 return 1;
311}
312
313int Color_get_grayPixel(lua_State* L)
314{
315 auto color = get_obj<app::Color>(L, 1);
316 auto pixelColor = color_utils::color_for_target_mask(
317 *color, ColorTarget(ColorTarget::TransparentLayer, IMAGE_GRAYSCALE, 0));
318 lua_pushinteger(L, pixelColor);
319 return 1;
320}
321
322int Color_set_red(lua_State* L)
323{
324 auto color = get_obj<app::Color>(L, 1);
325 *color = app::Color::fromRgb(lua_tointeger(L, 2),
326 color->getGreen(),
327 color->getBlue(),
328 color->getAlpha());
329 return 0;
330}
331
332int Color_set_green(lua_State* L)
333{
334 auto color = get_obj<app::Color>(L, 1);
335 *color = app::Color::fromRgb(color->getRed(),
336 lua_tointeger(L, 2),
337 color->getBlue(),
338 color->getAlpha());
339 return 0;
340}
341
342int Color_set_blue(lua_State* L)
343{
344 auto color = get_obj<app::Color>(L, 1);
345 *color = app::Color::fromRgb(color->getRed(),
346 color->getGreen(),
347 lua_tointeger(L, 2),
348 color->getAlpha());
349 return 0;
350}
351
352int Color_set_alpha(lua_State* L)
353{
354 auto color = get_obj<app::Color>(L, 1);
355 color->setAlpha(lua_tointeger(L, 2));
356 return 0;
357}
358
359int Color_set_hsvHue(lua_State* L)
360{
361 auto color = get_obj<app::Color>(L, 1);
362 *color = app::Color::fromHsv(lua_tonumber(L, 2),
363 color->getHsvSaturation(),
364 color->getHsvValue(),
365 color->getAlpha());
366 return 0;
367}
368
369int Color_set_hsvSaturation(lua_State* L)
370{
371 auto color = get_obj<app::Color>(L, 1);
372 *color = app::Color::fromHsv(color->getHsvHue(),
373 lua_tonumber(L, 2),
374 color->getHsvValue(),
375 color->getAlpha());
376 return 0;
377}
378
379int Color_set_hsvValue(lua_State* L)
380{
381 auto color = get_obj<app::Color>(L, 1);
382 *color = app::Color::fromHsv(color->getHsvHue(),
383 color->getHsvSaturation(),
384 lua_tonumber(L, 2),
385 color->getAlpha());
386 return 0;
387}
388
389int Color_set_hslHue(lua_State* L)
390{
391 auto color = get_obj<app::Color>(L, 1);
392 *color = app::Color::fromHsl(lua_tonumber(L, 2),
393 color->getHslSaturation(),
394 color->getHslLightness(),
395 color->getAlpha());
396 return 0;
397}
398
399int Color_set_hslSaturation(lua_State* L)
400{
401 auto color = get_obj<app::Color>(L, 1);
402 *color = app::Color::fromHsl(color->getHslHue(),
403 lua_tonumber(L, 2),
404 color->getHslLightness(),
405 color->getAlpha());
406 return 0;
407}
408
409int Color_set_hslLightness(lua_State* L)
410{
411 auto color = get_obj<app::Color>(L, 1);
412 *color = app::Color::fromHsl(color->getHslHue(),
413 color->getHslSaturation(),
414 lua_tonumber(L, 2),
415 color->getAlpha());
416 return 0;
417}
418
419int Color_set_hue(lua_State* L)
420{
421 const auto color = get_obj<app::Color>(L, 1);
422 if (color->getType() == Color::HslType)
423 return Color_set_hslHue(L);
424 else
425 return Color_set_hsvHue(L);
426}
427
428int Color_set_saturation(lua_State* L)
429{
430 const auto color = get_obj<app::Color>(L, 1);
431 if (color->getType() == Color::HslType)
432 return Color_set_hslSaturation(L);
433 else
434 return Color_set_hsvSaturation(L);
435}
436
437int Color_set_gray(lua_State* L)
438{
439 auto color = get_obj<app::Color>(L, 1);
440 *color = app::Color::fromGray(lua_tointeger(L, 2),
441 color->getAlpha());
442 return 0;
443}
444
445int Color_set_index(lua_State* L)
446{
447 auto color = get_obj<app::Color>(L, 1);
448 *color = app::Color::fromIndex(lua_tointeger(L, 2));
449 return 0;
450}
451
452const luaL_Reg Color_methods[] = {
453 { "__gc", Color_gc },
454 { "__eq", Color_eq },
455 { nullptr, nullptr }
456};
457
458const Property Color_properties[] = {
459 { "red", Color_get_red, Color_set_red },
460 { "green", Color_get_green, Color_set_green },
461 { "blue", Color_get_blue, Color_set_blue },
462 { "alpha", Color_get_alpha, Color_set_alpha },
463 { "hsvHue", Color_get_hsvHue, Color_set_hsvHue },
464 { "hsvSaturation", Color_get_hsvSaturation, Color_set_hsvSaturation },
465 { "hsvValue", Color_get_hsvValue, Color_set_hsvValue },
466 { "hslHue", Color_get_hslHue, Color_set_hslHue },
467 { "hslSaturation", Color_get_hslSaturation, Color_set_hslSaturation },
468 { "hslLightness", Color_get_hslLightness, Color_set_hslLightness },
469 { "hue", Color_get_hue, Color_set_hue },
470 { "saturation", Color_get_saturation, Color_set_saturation },
471 { "value", Color_get_hsvValue, Color_set_hsvValue },
472 { "lightness", Color_get_hslLightness, Color_set_hslLightness },
473 { "index", Color_get_index, Color_set_index },
474 { "gray", Color_get_gray, Color_set_gray },
475 { "rgbaPixel", Color_get_rgbaPixel, nullptr },
476 { "grayPixel", Color_get_grayPixel, nullptr },
477 { nullptr, nullptr, nullptr }
478};
479
480} // anonymous namespace
481
482DEF_MTNAME(app::Color);
483
484void register_color_class(lua_State* L)
485{
486 REG_CLASS(L, Color);
487 REG_CLASS_NEW(L, Color);
488 REG_CLASS_PROPERTIES(L, Color);
489}
490
491app::Color convert_args_into_color(lua_State* L, int index)
492{
493 return Color_new(L, index);
494}
495
496doc::color_t convert_args_into_pixel_color(lua_State* L, int index,
497 const doc::PixelFormat pixelFormat)
498{
499 app::Color color = convert_args_into_color(L, index);
500 return color_utils::color_for_image(color, pixelFormat);
501}
502
503} // namespace script
504} // namespace app
505