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 | |
17 | namespace app { |
18 | namespace script { |
19 | |
20 | namespace { |
21 | |
22 | app::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 | |
182 | int Color_new(lua_State* L) |
183 | { |
184 | push_obj(L, Color_new(L, 1)); |
185 | return 1; |
186 | } |
187 | |
188 | int Color_gc(lua_State* L) |
189 | { |
190 | get_obj<app::Color>(L, 1)->~Color(); |
191 | return 0; |
192 | } |
193 | |
194 | int 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 | |
202 | int 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 | |
209 | int 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 | |
216 | int 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 | |
223 | int 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 | |
230 | int 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 | |
237 | int 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 | |
244 | int 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 | |
251 | int 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 | |
258 | int 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 | |
265 | int 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 | |
272 | int 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 | |
281 | int 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 | |
290 | int 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 | |
297 | int 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 | |
304 | int 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 | |
313 | int 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 | |
322 | int 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 | |
332 | int 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 | |
342 | int 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 | |
352 | int 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 | |
359 | int 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 | |
369 | int 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 | |
379 | int 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 | |
389 | int 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 | |
399 | int 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 | |
409 | int 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 | |
419 | int 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 | |
428 | int 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 | |
437 | int 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 | |
445 | int 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 | |
452 | const luaL_Reg Color_methods[] = { |
453 | { "__gc" , Color_gc }, |
454 | { "__eq" , Color_eq }, |
455 | { nullptr, nullptr } |
456 | }; |
457 | |
458 | const 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 | |
482 | DEF_MTNAME(app::Color); |
483 | |
484 | void 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 | |
491 | app::Color convert_args_into_color(lua_State* L, int index) |
492 | { |
493 | return Color_new(L, index); |
494 | } |
495 | |
496 | doc::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 | |