diff options
author | William Wilgus <me.theuser@yahoo.com> | 2018-09-23 18:25:31 +0200 |
---|---|---|
committer | William Wilgus <me.theuser@yahoo.com> | 2018-10-09 01:02:25 +0200 |
commit | c0682e094414d0748456d0b01000727039ff701c (patch) | |
tree | 2cc08bfdfe967bbe18fade1ed835d54a3f91cd23 /apps/plugins/lua/rocklib_img.c | |
parent | e4b843335bc34810c11ed405d473e6f7c94a153f (diff) | |
download | rockbox-c0682e094414d0748456d0b01000727039ff701c.tar.gz rockbox-c0682e094414d0748456d0b01000727039ff701c.zip |
Clean up rocklib_img
optimize both size and speed
fix invert for color screens
Change-Id: I7edecae32dcb3daf5b3ed984a0e5b3d463269e60
Diffstat (limited to 'apps/plugins/lua/rocklib_img.c')
-rw-r--r-- | apps/plugins/lua/rocklib_img.c | 632 |
1 files changed, 306 insertions, 326 deletions
diff --git a/apps/plugins/lua/rocklib_img.c b/apps/plugins/lua/rocklib_img.c index 083679cdbb..35c2699b5d 100644 --- a/apps/plugins/lua/rocklib_img.c +++ b/apps/plugins/lua/rocklib_img.c | |||
@@ -57,10 +57,6 @@ | |||
57 | #define ABS(a)(((a) < 0) ? - (a) :(a)) | 57 | #define ABS(a)(((a) < 0) ? - (a) :(a)) |
58 | #endif | 58 | #endif |
59 | 59 | ||
60 | #ifndef LCD_BLACK | ||
61 | #define LCD_BLACK 0x0 | ||
62 | #endif | ||
63 | |||
64 | struct rocklua_image | 60 | struct rocklua_image |
65 | { | 61 | { |
66 | int width; | 62 | int width; |
@@ -68,18 +64,18 @@ struct rocklua_image | |||
68 | int stride; | 64 | int stride; |
69 | size_t elems; | 65 | size_t elems; |
70 | fb_data *data; | 66 | fb_data *data; |
71 | fb_data dummy[1]; | 67 | fb_data dummy[1][1]; |
72 | }; | 68 | }; |
73 | 69 | ||
74 | /* holds iterator data for rlimages */ | 70 | /* holds iterator data for rlimages */ |
75 | struct rli_iter_d | 71 | struct rli_iter_d |
76 | { | 72 | { |
77 | struct rocklua_image *img; | ||
78 | fb_data *elem; | ||
79 | int x , y; | 73 | int x , y; |
80 | int x1, y1; | 74 | int x1, y1; |
81 | int x2, y2; | 75 | int x2, y2; |
82 | int dx, dy; | 76 | int dx, dy; |
77 | fb_data *elem; | ||
78 | struct rocklua_image *img; | ||
83 | }; | 79 | }; |
84 | 80 | ||
85 | /* __tostring information enums */ | 81 | /* __tostring information enums */ |
@@ -92,8 +88,8 @@ enum rli_info {RLI_INFO_ALL = 0, RLI_INFO_TYPE, RLI_INFO_WIDTH, | |||
92 | static inline fb_data invert_color(fb_data rgb) | 88 | static inline fb_data invert_color(fb_data rgb) |
93 | { | 89 | { |
94 | uint8_t r = 0xFFU - FB_UNPACK_RED(rgb); | 90 | uint8_t r = 0xFFU - FB_UNPACK_RED(rgb); |
95 | uint8_t g = 0xFFU - FB_UNPACK_RED(rgb); | 91 | uint8_t g = 0xFFU - FB_UNPACK_GREEN(rgb); |
96 | uint8_t b = 0xFFU - FB_UNPACK_RED(rgb); | 92 | uint8_t b = 0xFFU - FB_UNPACK_BLUE(rgb); |
97 | 93 | ||
98 | return FB_RGBPACK(r, g, b); | 94 | return FB_RGBPACK(r, g, b); |
99 | } | 95 | } |
@@ -244,17 +240,45 @@ static inline void swap_int(bool swap, int *v1, int *v2) | |||
244 | static void bounds_check_xy(lua_State *L, struct rocklua_image *img, | 240 | static void bounds_check_xy(lua_State *L, struct rocklua_image *img, |
245 | int nargx, int x, int nargy, int y) | 241 | int nargx, int x, int nargy, int y) |
246 | { | 242 | { |
247 | luaL_argcheck(L, x <= img->width && x > 0, nargx, ERR_IDX_RANGE); | 243 | int narg; |
248 | luaL_argcheck(L, y <= img->height && y > 0, nargy, ERR_IDX_RANGE); | 244 | |
245 | if(x > img->width || x < 1) | ||
246 | narg = nargx; | ||
247 | else if(y <= img->height && y > 0) | ||
248 | return; /* note -- return if no error */ | ||
249 | else | ||
250 | narg = nargy; | ||
251 | |||
252 | luaL_argerror(L, narg, ERR_IDX_RANGE); | ||
249 | } /* bounds_check_xy */ | 253 | } /* bounds_check_xy */ |
250 | 254 | ||
251 | static struct rocklua_image* rli_checktype(lua_State *L, int arg) | 255 | static struct rocklua_image* rli_checktype(lua_State *L, int arg) |
252 | { | 256 | { |
253 | void *ud = luaL_checkudata(L, arg, ROCKLUA_IMAGE); | 257 | #if 0 |
258 | return (struct rocklua_image*) luaL_checkudata(L, arg, ROCKLUA_IMAGE); | ||
259 | #else /* cache result */ | ||
260 | static struct rocklua_image* last = NULL; | ||
261 | void *ud = lua_touserdata(L, arg); | ||
254 | 262 | ||
255 | luaL_argcheck(L, ud != NULL, arg, "'" ROCKLUA_IMAGE "' expected"); | 263 | if(ud != NULL) |
264 | { | ||
265 | if(ud == last) | ||
266 | return last; | ||
267 | else if (lua_getmetatable(L, arg)) | ||
268 | { /* does it have a metatable? */ | ||
269 | luaL_getmetatable(L, ROCKLUA_IMAGE); /* get correct metatable */ | ||
270 | if (lua_rawequal(L, -1, -2)) | ||
271 | { /* does it have the correct mt? */ | ||
272 | lua_pop(L, 2); /* remove both metatables */ | ||
273 | last = (struct rocklua_image*) ud; | ||
274 | return last; | ||
275 | } | ||
276 | } | ||
277 | } | ||
256 | 278 | ||
257 | return (struct rocklua_image*) ud; | 279 | luaL_typerror(L, arg, ROCKLUA_IMAGE); /* else error */ |
280 | return NULL; /* to avoid warnings */ | ||
281 | #endif | ||
258 | } /* rli_checktype */ | 282 | } /* rli_checktype */ |
259 | 283 | ||
260 | static struct rocklua_image * alloc_rlimage(lua_State *L, bool alloc_data, | 284 | static struct rocklua_image * alloc_rlimage(lua_State *L, bool alloc_data, |
@@ -286,7 +310,7 @@ static struct rocklua_image * alloc_rlimage(lua_State *L, bool alloc_data, | |||
286 | /* apparent w/h is stored but behind the scenes native w/h is used */ | 310 | /* apparent w/h is stored but behind the scenes native w/h is used */ |
287 | img->width = width; | 311 | img->width = width; |
288 | img->height = height; | 312 | img->height = height; |
289 | img->stride = w_native; | 313 | img->stride = STRIDE_MAIN(w_native, h_native); |
290 | img->elems = n_elems; | 314 | img->elems = n_elems; |
291 | 315 | ||
292 | return img; | 316 | return img; |
@@ -305,14 +329,14 @@ static inline fb_data* rli_alloc(lua_State *L, int width, int height) | |||
305 | /* rliimage is pushed on the stack it is up to you to pop it */ | 329 | /* rliimage is pushed on the stack it is up to you to pop it */ |
306 | struct rocklua_image *a = alloc_rlimage(L, true, width, height); | 330 | struct rocklua_image *a = alloc_rlimage(L, true, width, height); |
307 | 331 | ||
308 | a->data = &a->dummy[0]; /* ref to beginning of alloc'd img data */ | 332 | a->data = &a->dummy[0][0]; /* ref to beginning of alloc'd img data */ |
309 | 333 | ||
310 | return a->data; | 334 | return a->data; |
311 | } /* rli_alloc */ | 335 | } /* rli_alloc */ |
312 | 336 | ||
313 | static inline fb_data data_setget(fb_data *elem, int x, int y, fb_data *val) | 337 | static inline fb_data data_set(fb_data *elem, int x, int y, fb_data *val) |
314 | { | 338 | { |
315 | fb_data old_val = FB_SCALARPACK(0); | 339 | fb_data old_val; |
316 | fb_data new_val; | 340 | fb_data new_val; |
317 | 341 | ||
318 | if(elem) | 342 | if(elem) |
@@ -328,23 +352,18 @@ static inline fb_data data_setget(fb_data *elem, int x, int y, fb_data *val) | |||
328 | else | 352 | else |
329 | pixel_to_fb(x, y, &old_val, &new_val); | 353 | pixel_to_fb(x, y, &old_val, &new_val); |
330 | } | 354 | } |
355 | else | ||
356 | old_val = FB_SCALARPACK(0); | ||
331 | 357 | ||
332 | return old_val; | 358 | return old_val; |
333 | } /* data_setget */ | ||
334 | |||
335 | static inline fb_data data_set(fb_data *elem, int x, int y, fb_data *new_val) | ||
336 | { | ||
337 | /* get and set share the same underlying function */ | ||
338 | return data_setget(elem, x, y, new_val); | ||
339 | } /* data_set */ | 359 | } /* data_set */ |
340 | 360 | ||
341 | static inline fb_data data_get(fb_data *elem, int x, int y) | 361 | static inline fb_data data_get(fb_data *elem, int x, int y) |
342 | { | 362 | { |
343 | /* get and set share the same underlying function */ | 363 | return data_set(elem, x, y, NULL); |
344 | return data_setget(elem, x, y, NULL); | ||
345 | } /* data_get */ | 364 | } /* data_get */ |
346 | 365 | ||
347 | static fb_data* rli_get_element(struct rocklua_image* img, int x, int y) | 366 | static inline fb_data* rli_get_element(struct rocklua_image* img, int x, int y) |
348 | { | 367 | { |
349 | int stride = img->stride; | 368 | int stride = img->stride; |
350 | size_t elements = img->elems; | 369 | size_t elements = img->elems; |
@@ -352,60 +371,61 @@ static fb_data* rli_get_element(struct rocklua_image* img, int x, int y) | |||
352 | 371 | ||
353 | pixel_to_native(x, y, &x, &y); | 372 | pixel_to_native(x, y, &x, &y); |
354 | 373 | ||
374 | #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE | ||
375 | /* column major address */ | ||
376 | size_t data_address = (stride * (x - 1)) + (y - 1); | ||
377 | |||
378 | /* y needs bound between 0 and stride otherwise overflow to prev/next x */ | ||
379 | if(y <= 0 || y > stride || data_address >= elements) | ||
380 | return NULL; /* data overflow */ | ||
381 | #else | ||
355 | /* row major address */ | 382 | /* row major address */ |
356 | size_t data_address = (stride * (y - 1)) + (x - 1); | 383 | size_t data_address = (stride * (y - 1)) + (x - 1); |
357 | 384 | ||
358 | /* x needs bound between 0 and stride otherwise overflow to prev/next y */ | 385 | /* x needs bound between 0 and stride otherwise overflow to prev/next y */ |
359 | if(x <= 0 || x > stride || data_address >= elements) | 386 | if(x <= 0 || x > stride || data_address >= elements) |
360 | return NULL; /* data overflow */ | 387 | return NULL; /* data overflow */ |
388 | #endif | ||
361 | 389 | ||
362 | return &data[data_address]; /* return element address */ | 390 | return &data[data_address]; /* return element address */ |
363 | } /* rli_get_element */ | 391 | } /* rli_get_element */ |
364 | 392 | ||
365 | /* Lua to C Interface for pixel set and get functions */ | 393 | /* Lua to C Interface for pixel set and get functions */ |
366 | static int rli_setget(lua_State *L, bool is_get) | 394 | static int rli_setget(lua_State *L, bool is_get, int narg_clip) |
367 | { | 395 | { |
368 | /*(set) (dst*, [x1, y1, clr, clip]) */ | 396 | /*(set) (dst*, [x1, y1, clr, clip]) */ |
369 | /*(get) (dst*, [x1, y1, clip]) */ | 397 | /*(get) (dst*, [x1, y1, clip]) */ |
370 | struct rocklua_image *a = rli_checktype(L, 1); | 398 | struct rocklua_image *a = rli_checktype(L, 1); |
371 | int x = luaL_checkint(L, 2); | 399 | int x = lua_tointeger(L, 2); |
372 | int y = luaL_checkint(L, 3); | 400 | int y = lua_tointeger(L, 3); |
373 | |||
374 | fb_data clr = FB_SCALARPACK(0); /* Arg 4 is color if set element */ | ||
375 | fb_data *p_clr = &clr; | ||
376 | 401 | ||
377 | int clip_narg; | 402 | fb_data clr; /* Arg 4 is color if set element */ |
378 | |||
379 | if(is_get) /* get element */ | ||
380 | { | ||
381 | p_clr = NULL; | ||
382 | clip_narg = 4; | ||
383 | } | ||
384 | else /* set element */ | ||
385 | { | ||
386 | clr = FB_SCALARPACK((unsigned) luaL_checknumber(L, 4)); | ||
387 | clip_narg = 5; | ||
388 | } | ||
389 | 403 | ||
390 | fb_data *element = rli_get_element(a, x, y); | 404 | fb_data *element = rli_get_element(a, x, y); |
391 | 405 | ||
392 | if(!element) | 406 | if(!element) |
393 | { | 407 | { |
394 | if(!luaL_optboolean(L, clip_narg, false)) /* Error if !clip */ | 408 | if(!lua_toboolean(L, narg_clip)) /* Error if !clip */ |
395 | bounds_check_xy(L, a, 2, x, 3, y); | 409 | bounds_check_xy(L, a, 2, x, 3, y); |
396 | 410 | ||
397 | lua_pushnil(L); | 411 | lua_pushnil(L); |
398 | return 1; | 412 | return 1; |
399 | } | 413 | } |
400 | 414 | ||
401 | lua_pushnumber(L, FB_UNPACK_SCALAR_LCD(data_setget(element, x, y, p_clr))); | 415 | if(is_get) /* get element */ |
416 | lua_pushinteger(L, FB_UNPACK_SCALAR_LCD(data_get(element, x, y))); | ||
417 | else /* set element */ | ||
418 | { | ||
419 | clr = FB_SCALARPACK((unsigned) lua_tointeger(L, 4)); | ||
420 | lua_pushinteger(L, FB_UNPACK_SCALAR_LCD(data_set(element, x, y, &clr))); | ||
421 | } | ||
402 | 422 | ||
403 | /* returns old value */ | 423 | /* returns old value */ |
404 | return 1; | 424 | return 1; |
405 | } /* rli_setget */ | 425 | } /* rli_setget */ |
406 | 426 | ||
407 | #ifdef RLI_EXTENDED | 427 | #ifdef RLI_EXTENDED |
408 | static bool init_rli_iter(struct rli_iter_d *d, | 428 | static bool rli_iter_init(struct rli_iter_d *d, |
409 | struct rocklua_image *img, | 429 | struct rocklua_image *img, |
410 | int x1, int y1, | 430 | int x1, int y1, |
411 | int x2, int y2, | 431 | int x2, int y2, |
@@ -417,11 +437,11 @@ static bool init_rli_iter(struct rli_iter_d *d, | |||
417 | swap_int((swy), &y1, &y2); | 437 | swap_int((swy), &y1, &y2); |
418 | 438 | ||
419 | /* stepping in the correct x direction ? */ | 439 | /* stepping in the correct x direction ? */ |
420 | if((dx > 0 && x1 > x2) || (dx < 0 && x1 < x2)) | 440 | if((dx ^ (x2 - x1)) < 0) |
421 | dx = -dx; | 441 | dx = -dx; |
422 | 442 | ||
423 | /* stepping in the correct y direction ? */ | 443 | /* stepping in the correct y direction ? */ |
424 | if((dy > 0 && y1 > y2) || (dy < 0 && y1 < y2)) | 444 | if((dy ^ (y2 - y1)) < 0) |
425 | dy = -dy; | 445 | dy = -dy; |
426 | 446 | ||
427 | d->img = img; | 447 | d->img = img; |
@@ -436,7 +456,33 @@ static bool init_rli_iter(struct rli_iter_d *d, | |||
436 | d->elem = rli_get_element(img, d->x, d->y); | 456 | d->elem = rli_get_element(img, d->x, d->y); |
437 | 457 | ||
438 | return(dx != 0 || dy != 0); | 458 | return(dx != 0 || dy != 0); |
439 | } /* init_rli_iter */ | 459 | } /* rli_iter_init */ |
460 | |||
461 | static struct rli_iter_d * rli_iter_create(lua_State *L) | ||
462 | { | ||
463 | struct rocklua_image *a = rli_checktype(L, 1); | ||
464 | int x1 = luaL_optint(L, 2, 1); | ||
465 | int y1 = luaL_optint(L, 3, 1); | ||
466 | int x2 = luaL_optint(L, 4, a->width); | ||
467 | int y2 = luaL_optint(L, 5, a->height); | ||
468 | int dx = luaL_optint(L, 6, 1); | ||
469 | int dy = luaL_optint(L, 7, 1); | ||
470 | bool clip = lua_toboolean(L, 8); | ||
471 | |||
472 | if(!clip) | ||
473 | { | ||
474 | bounds_check_xy(L, a, 2, x1, 3, y1); | ||
475 | bounds_check_xy(L, a, 4, x2, 5, y2); | ||
476 | } | ||
477 | |||
478 | struct rli_iter_d *ds; | ||
479 | /* create new iter + pushed onto stack */ | ||
480 | ds = (struct rli_iter_d *) lua_newuserdata(L, sizeof(struct rli_iter_d)); | ||
481 | |||
482 | rli_iter_init(ds, a, x1, y1, x2, y2, dx, dy, false, false); | ||
483 | |||
484 | return ds; | ||
485 | } | ||
440 | 486 | ||
441 | /* steps to the next point(x, y) by delta x/y, stores pointer to element | 487 | /* steps to the next point(x, y) by delta x/y, stores pointer to element |
442 | returns true if x & y haven't reached x2 & y2 | 488 | returns true if x & y haven't reached x2 & y2 |
@@ -464,11 +510,10 @@ static bool next_rli_iter(struct rli_iter_d *d) | |||
464 | return true; | 510 | return true; |
465 | } /* next_rli_iter */ | 511 | } /* next_rli_iter */ |
466 | 512 | ||
467 | static int d_line(struct rocklua_image *img, | 513 | static void d_line(struct rocklua_image *img, |
468 | int x1, int y1, | 514 | int x1, int y1, |
469 | int x2, int y2, | 515 | int x2, int y2, |
470 | fb_data *clr, | 516 | fb_data *clr) |
471 | bool clip) | ||
472 | { | 517 | { |
473 | /* NOTE! clr passed as pointer */ | 518 | /* NOTE! clr passed as pointer */ |
474 | /* Bresenham midpoint line algorithm */ | 519 | /* Bresenham midpoint line algorithm */ |
@@ -477,8 +522,8 @@ static int d_line(struct rocklua_image *img, | |||
477 | int r_a = x2 - x1; /* range of x direction called 'a' for now */ | 522 | int r_a = x2 - x1; /* range of x direction called 'a' for now */ |
478 | int r_b = y2 - y1; /* range of y direction called 'b' for now */ | 523 | int r_b = y2 - y1; /* range of y direction called 'b' for now */ |
479 | 524 | ||
480 | int s_a = 1; /* step of a direction */ | 525 | int s_a = (r_a > 0) - (r_a < 0); /* step of a direction -1, 0, 1 */ |
481 | int s_b = 1; /* step of b direction */ | 526 | int s_b = (r_b > 0) - (r_b < 0); /* step of b direction -1, 0, 1 */ |
482 | 527 | ||
483 | int d_err; | 528 | int d_err; |
484 | int numpixels; | 529 | int numpixels; |
@@ -486,42 +531,28 @@ static int d_line(struct rocklua_image *img, | |||
486 | int *a1 = &x1; /* pointer to the x var 'a' */ | 531 | int *a1 = &x1; /* pointer to the x var 'a' */ |
487 | int *b1 = &y1; /* pointer to the y var 'b' */ | 532 | int *b1 = &y1; /* pointer to the y var 'b' */ |
488 | 533 | ||
489 | if(r_a < 0) /* instead of negative range we will switch step instead */ | 534 | r_a = ABS(r_a);/* instead of negative range we switch step */ |
490 | { | 535 | r_b = ABS(r_b);/* instead of negative range we switch step */ |
491 | r_a = -r_a; | ||
492 | s_a = -s_a; | ||
493 | } | ||
494 | |||
495 | if(r_b < 0) /* instead of negative range we will switch step instead */ | ||
496 | { | ||
497 | r_b = -r_b; | ||
498 | s_b = -s_b; | ||
499 | } | ||
500 | |||
501 | x2 += s_a; /* add 1 extra point to make the whole line */ | ||
502 | y2 += s_b; /* add 1 extra point */ | ||
503 | 536 | ||
504 | if(r_b > r_a) /*if rangeY('b') > rangeX('a') swap their identities */ | 537 | if(r_b > r_a) /*if rangeY('b') > rangeX('a') swap their identities */ |
505 | { | 538 | { |
506 | a1 = &y1; | 539 | a1 = &y1; /* pointer to the y var 'a' */ |
507 | b1 = &x1; | 540 | b1 = &x1; /* pointer to the x var 'b' */ |
508 | swap_int((true), &r_a, &r_b); | 541 | swap_int((true), &r_a, &r_b); |
509 | swap_int((true), &s_a, &s_b); | 542 | swap_int((true), &s_a, &s_b); |
510 | } | 543 | } |
511 | 544 | ||
512 | d_err = ((r_b << 1) - r_a) >> 1; /* preload err of 1 step (px centered) */ | 545 | d_err = ((r_b << 1) - r_a) >> 1; /* preload err of 1 step (px centered) */ |
513 | 546 | ||
547 | /* add 1 extra point to make the whole line */ | ||
514 | numpixels = r_a + 1; | 548 | numpixels = r_a + 1; |
515 | 549 | ||
516 | r_a -= r_b; /* pre-subtract 'a' - 'b' */ | 550 | r_a -= r_b; /* pre-subtract 'a' - 'b' */ |
517 | 551 | ||
518 | for(;numpixels > 0; numpixels--) | 552 | for(; numpixels > 0; numpixels--) |
519 | { | 553 | { |
520 | element = rli_get_element(img, x1, y1); | 554 | element = rli_get_element(img, x1, y1); |
521 | if(element || clip) | 555 | data_set(element, x1, y1, clr); |
522 | data_set(element, x1, y1, clr); | ||
523 | else | ||
524 | return numpixels + 1; /* Error */ | ||
525 | 556 | ||
526 | if(d_err >= 0) /* 0 is our target midpoint(exact point on the line) */ | 557 | if(d_err >= 0) /* 0 is our target midpoint(exact point on the line) */ |
527 | { | 558 | { |
@@ -534,73 +565,60 @@ static int d_line(struct rocklua_image *img, | |||
534 | *a1 += s_a; /* whichever axis is in 'a' stepped(-1 or +1) */ | 565 | *a1 += s_a; /* whichever axis is in 'a' stepped(-1 or +1) */ |
535 | } | 566 | } |
536 | 567 | ||
537 | return 0; | ||
538 | } /* d_line */ | 568 | } /* d_line */ |
539 | 569 | ||
540 | /* ellipse worker function */ | 570 | /* ellipse worker function */ |
541 | static int d_ellipse_elements(struct rocklua_image * img, | 571 | static void d_ellipse_elements(struct rocklua_image * img, |
542 | int x1, int y1, | 572 | int x1, int y1, |
543 | int x2, int y2, | 573 | int x2, int y2, |
544 | int sx, int sy, | 574 | fb_data *clr, |
545 | fb_data *clr, | 575 | fb_data *fillclr) |
546 | fb_data *fillclr, | ||
547 | bool clip) | ||
548 | { | 576 | { |
549 | int ret = 0; | 577 | fb_data *element; |
550 | fb_data *element1, *element2, *element3, *element4; | ||
551 | 578 | ||
552 | if(fillclr && x1 - sx != x2 + sx) | 579 | if(fillclr) |
553 | { | 580 | { |
554 | ret |= d_line(img, x1, y1, x2, y1, fillclr, clip); /* I. II.*/ | 581 | d_line(img, x1, y1, x2, y1, fillclr); /* I. II.*/ |
555 | ret |= d_line(img, x1, y2, x2, y2, fillclr, clip); /* III.IV.*/ | 582 | d_line(img, x1, y2, x2, y2, fillclr); /* III.IV.*/ |
556 | } | 583 | } |
557 | 584 | ||
558 | x1 -= sx; /* shift x & y */ | 585 | element = rli_get_element(img, x2, y1); |
559 | y1 -= sy; | 586 | data_set(element, x2, y1, clr); /* I. Quadrant +x +y */ |
560 | x2 += sx; | ||
561 | y2 += sy; | ||
562 | 587 | ||
563 | element1 = rli_get_element(img, x2, y1); | 588 | element = rli_get_element(img, x1, y1); |
564 | element2 = rli_get_element(img, x1, y1); | 589 | data_set(element, x1, y1, clr); /* II. Quadrant -x +y */ |
565 | element3 = rli_get_element(img, x1, y2); | ||
566 | element4 = rli_get_element(img, x2, y2); | ||
567 | 590 | ||
568 | if(clip || (element1 && element2 && element3 && element4)) | 591 | element = rli_get_element(img, x1, y2); |
569 | { | 592 | data_set(element, x1, y2, clr); /* III. Quadrant -x -y */ |
570 | data_set(element1, x2, y1, clr); /* I. Quadrant +x +y */ | 593 | |
571 | data_set(element2, x1, y1, clr); /* II. Quadrant -x +y */ | 594 | element = rli_get_element(img, x2, y2); |
572 | data_set(element3, x1, y2, clr); /* III. Quadrant -x -y */ | 595 | data_set(element, x2, y2, clr); /* IV. Quadrant +x -y */ |
573 | data_set(element4, x2, y2, clr); /* IV. Quadrant +x -y */ | ||
574 | } | ||
575 | else | ||
576 | ret = 2; /* ERROR */ | ||
577 | 596 | ||
578 | return ret; | ||
579 | } /* d_ellipse_elements */ | 597 | } /* d_ellipse_elements */ |
580 | 598 | ||
581 | static int d_ellipse(struct rocklua_image *img, | 599 | static void d_ellipse(struct rocklua_image *img, |
582 | int x1, int y1, | 600 | int x1, int y1, |
583 | int x2, int y2, | 601 | int x2, int y2, |
584 | fb_data *clr, | 602 | fb_data *clr, |
585 | fb_data *fillclr, | 603 | fb_data *fillclr) |
586 | bool clip) | ||
587 | { | 604 | { |
588 | /* NOTE! clr and fillclr passed as pointers */ | 605 | /* NOTE! clr and fillclr passed as pointers */ |
589 | /* Rasterizing algorithm derivative of work by Alois Zingl */ | 606 | /* Rasterizing algorithm derivative of work by Alois Zingl */ |
590 | #if LCD_WIDTH > 1024 || LCD_HEIGHT > 1024 | 607 | #if (LCD_WIDTH > 1024 || LCD_HEIGHT > 1024) && defined(INT64_MAX) |
591 | /* Prevents overflow on large screens */ | 608 | /* Prevents overflow on large screens */ |
592 | double dx, dy, err, e2; | 609 | int64_t dx, dy, err, e1; |
593 | #else | 610 | #else |
594 | long dx, dy, err, e2; | 611 | int32_t dx, dy, err, e1; |
595 | #endif | 612 | #endif |
613 | /* if called with swapped points .. exchange them */ | ||
614 | swap_int((x1 > x2), &x1, &x2); | ||
615 | swap_int((y1 > y2), &y1, &y2); | ||
596 | 616 | ||
597 | int ret = 0; | 617 | int a = x2 - x1; /* diameter */ |
598 | 618 | int b = y2 - y1; /* diameter */ | |
599 | int a = ABS(x2 - x1); /* diameter */ | ||
600 | int b = ABS(y2 - y1); /* diameter */ | ||
601 | 619 | ||
602 | if(a == 0 || b == 0 || !clr) | 620 | if(a == 0 || b == 0) |
603 | return ret; /* not an error but nothing to display */ | 621 | return; /* not an error but nothing to display */ |
604 | 622 | ||
605 | int b1 = (b & 1); | 623 | int b1 = (b & 1); |
606 | b = b - (1 - b1); | 624 | b = b - (1 - b1); |
@@ -613,21 +631,16 @@ static int d_ellipse(struct rocklua_image *img, | |||
613 | 631 | ||
614 | err = dx + dy + b1 * a2; /* error of 1.step */ | 632 | err = dx + dy + b1 * a2; /* error of 1.step */ |
615 | 633 | ||
616 | /* if called with swapped points .. exchange them */ | ||
617 | swap_int((x1 > x2), &x1, &x2); | ||
618 | swap_int((y1 > y2), &y1, &y2); | ||
619 | |||
620 | y1 += (b + 1) >> 1; | 634 | y1 += (b + 1) >> 1; |
621 | y2 = y1 - b1; | 635 | y2 = y1 - b1; |
622 | 636 | ||
623 | do | 637 | do |
624 | { | 638 | { |
625 | ret = d_ellipse_elements(img, x1, y1, x2, y2, 0, 0, clr, fillclr, clip); | 639 | d_ellipse_elements(img, x1, y1, x2, y2, clr, fillclr); |
626 | 640 | ||
627 | e2 = err; | 641 | e1 = err; |
628 | 642 | ||
629 | /* using division because you can't use bit shift on doubles.. */ | 643 | if(e1 <= (dy >> 1)) /* target midpoint - y step */ |
630 | if(e2 <= (dy / 2)) /* target midpoint - y step */ | ||
631 | { | 644 | { |
632 | y1++; | 645 | y1++; |
633 | y2--; | 646 | y2--; |
@@ -635,7 +648,7 @@ static int d_ellipse(struct rocklua_image *img, | |||
635 | err += dy; | 648 | err += dy; |
636 | } | 649 | } |
637 | 650 | ||
638 | if(e2 >= (dx / 2) || err > (dy / 2)) /* target midpoint - x step */ | 651 | if(e1 >= (dx >> 1) || err > (dy >> 1)) /* target midpoint - x step */ |
639 | { | 652 | { |
640 | x1++; | 653 | x1++; |
641 | x2--; | 654 | x2--; |
@@ -643,21 +656,23 @@ static int d_ellipse(struct rocklua_image *img, | |||
643 | err += dx; | 656 | err += dx; |
644 | } | 657 | } |
645 | 658 | ||
646 | } while(ret == 0 && x1 <= x2); | 659 | } while(x1 <= x2); |
660 | |||
661 | if (fillclr && x1 - x2 <= 2) | ||
662 | fillclr = clr; | ||
647 | 663 | ||
648 | while (ret == 0 && y1 - y2 < b) /* early stop of flat ellipse a=1 finish tip */ | 664 | while (y1 - y2 < b) /* early stop of flat ellipse a=1 finish tip */ |
649 | { | 665 | { |
650 | ret = d_ellipse_elements(img, x1, y1, x2, y2, 1, 0, clr, fillclr, clip); | 666 | d_ellipse_elements(img, x1, y1, x2, y2, clr, fillclr); |
651 | 667 | ||
652 | y1++; | 668 | y1++; |
653 | y2--; | 669 | y2--; |
654 | } | 670 | } |
655 | 671 | ||
656 | return ret; | ||
657 | } /* d_ellipse */ | 672 | } /* d_ellipse */ |
658 | 673 | ||
659 | /* Lua to C Interface for line and ellipse */ | 674 | /* Lua to C Interface for line and ellipse */ |
660 | static int rli_line_ellipse(lua_State *L, bool is_ellipse) | 675 | static int rli_line_ellipse(lua_State *L, bool is_ellipse, int narg_clip) |
661 | { | 676 | { |
662 | struct rocklua_image *a = rli_checktype(L, 1); | 677 | struct rocklua_image *a = rli_checktype(L, 1); |
663 | 678 | ||
@@ -666,20 +681,12 @@ static int rli_line_ellipse(lua_State *L, bool is_ellipse) | |||
666 | int x2 = luaL_optint(L, 4, x1); | 681 | int x2 = luaL_optint(L, 4, x1); |
667 | int y2 = luaL_optint(L, 5, y1); | 682 | int y2 = luaL_optint(L, 5, y1); |
668 | 683 | ||
669 | fb_data clr = FB_SCALARPACK((unsigned) luaL_checknumber(L, 6)); | 684 | fb_data clr = FB_SCALARPACK((unsigned) lua_tointeger(L, 6)); |
670 | 685 | ||
671 | fb_data fillclr; /* fill color is index 7 if is_ellipse */ | 686 | fb_data fillclr; /* fill color is index 7 if is_ellipse */ |
672 | fb_data *p_fillclr = NULL; | 687 | fb_data *p_fillclr = NULL; |
673 | 688 | ||
674 | bool clip; | 689 | bool clip = lua_toboolean(L, narg_clip); |
675 | int clip_narg; | ||
676 | |||
677 | if(is_ellipse) | ||
678 | clip_narg = 8; | ||
679 | else | ||
680 | clip_narg = 7; | ||
681 | |||
682 | clip = luaL_optboolean(L, clip_narg, false); | ||
683 | 690 | ||
684 | if(!clip) | 691 | if(!clip) |
685 | { | 692 | { |
@@ -689,31 +696,27 @@ static int rli_line_ellipse(lua_State *L, bool is_ellipse) | |||
689 | 696 | ||
690 | if(is_ellipse) | 697 | if(is_ellipse) |
691 | { | 698 | { |
692 | if(!lua_isnoneornil(L, 7)) | 699 | if(lua_type(L, 7) == LUA_TNUMBER) |
693 | { | 700 | { |
694 | fillclr = FB_SCALARPACK((unsigned) luaL_checkint(L, 7)); | 701 | fillclr = FB_SCALARPACK((unsigned) lua_tointeger(L, 7)); |
695 | p_fillclr = &fillclr; | 702 | p_fillclr = &fillclr; |
696 | } | 703 | } |
697 | 704 | ||
698 | luaL_argcheck(L, d_ellipse(a, x1, y1, x2, y2, &clr, p_fillclr, clip) == 0, | 705 | d_ellipse(a, x1, y1, x2, y2, &clr, p_fillclr); |
699 | 1, ERR_DATA_OVF); | ||
700 | } | 706 | } |
701 | else | 707 | else |
702 | luaL_argcheck(L, d_line(a, x1, y1, x2, y2, &clr, clip) == 0, | 708 | d_line(a, x1, y1, x2, y2, &clr); |
703 | 1, ERR_DATA_OVF); | ||
704 | 709 | ||
705 | return 0; | 710 | return 0; |
706 | } /* rli_line_ellipse */ | 711 | } /* rli_line_ellipse */ |
707 | 712 | ||
708 | /* Pushes lua function from Stack at position narg to top of stack | 713 | static inline int rli_pushpixel(lua_State *L, fb_data color, int x, int y) |
709 | and puts a reference in the global registry for later use */ | ||
710 | static inline int register_luafunc(lua_State *L, int narg_funct) | ||
711 | { | 714 | { |
712 | lua_pushvalue(L, narg_funct); /* lua function */ | 715 | lua_pushinteger(L, FB_UNPACK_SCALAR_LCD(color)); |
713 | int lf_ref = luaL_ref(L, LUA_REGISTRYINDEX); | 716 | lua_pushinteger(L, x); |
714 | lua_settop(L, 0); /* clear C stack for use by lua function */ | 717 | lua_pushinteger(L, y); |
715 | return lf_ref; | 718 | return 3; |
716 | } /* register_luafunc */ | 719 | } |
717 | 720 | ||
718 | /* User defined pixel manipulations through rli_copy, rli_marshal */ | 721 | /* User defined pixel manipulations through rli_copy, rli_marshal */ |
719 | static int custom_transform(lua_State *L, | 722 | static int custom_transform(lua_State *L, |
@@ -723,42 +726,40 @@ static int custom_transform(lua_State *L, | |||
723 | fb_data *color) | 726 | fb_data *color) |
724 | { | 727 | { |
725 | (void) color; | 728 | (void) color; |
726 | 729 | (void) op; | |
727 | fb_data dst; | 730 | fb_data dst; |
728 | fb_data src; | 731 | fb_data src; |
729 | 732 | ||
730 | unsigned int params = 3; | 733 | int params; |
731 | int ret = 0; | 734 | int ret = 0; |
732 | 735 | ||
733 | lua_rawgeti(L, LUA_REGISTRYINDEX, op); | 736 | if (!lua_isfunction(L, -1)) |
737 | return ret; /* error */ | ||
738 | |||
739 | lua_pushvalue(L, -1); /* make a copy of the lua function */ | ||
734 | 740 | ||
735 | dst = data_get(ds->elem, ds->x, ds->y); | 741 | dst = data_get(ds->elem, ds->x, ds->y); |
736 | lua_pushnumber(L, FB_UNPACK_SCALAR_LCD(dst)); | 742 | params = rli_pushpixel(L, dst, ds->x, ds->y); |
737 | lua_pushnumber(L, ds->x); | ||
738 | lua_pushnumber(L, ds->y); | ||
739 | 743 | ||
740 | if(ss) /* Allows src to be omitted */ | 744 | if(ss) /* Allows src to be omitted */ |
741 | { | 745 | { |
742 | params += 3; | ||
743 | src = data_get(ss->elem, ss->x, ss->y); | 746 | src = data_get(ss->elem, ss->x, ss->y); |
744 | lua_pushnumber(L, FB_UNPACK_SCALAR_LCD(src)); | 747 | params += rli_pushpixel(L, src, ss->x, ss->y); |
745 | lua_pushnumber(L, ss->x); | ||
746 | lua_pushnumber(L, ss->y); | ||
747 | } | 748 | } |
748 | 749 | ||
749 | lua_call(L, params, 2); /* call custom function w/ n-params & 2 ret */ | 750 | lua_call(L, params, 2); /* call custom function w/ n-params & 2 ret */ |
750 | 751 | ||
751 | if(!lua_isnoneornil(L, -2)) | 752 | if(lua_type(L, -2) == LUA_TNUMBER) |
752 | { | 753 | { |
753 | ret = 1; | 754 | ret |= 1; |
754 | dst = FB_SCALARPACK((unsigned) luaL_checknumber(L, -2)); | 755 | dst = FB_SCALARPACK((unsigned) lua_tointeger(L, -2)); |
755 | data_set(ds->elem, ds->x, ds->y, &dst); | 756 | data_set(ds->elem, ds->x, ds->y, &dst); |
756 | } | 757 | } |
757 | 758 | ||
758 | if(!lua_isnoneornil(L, -1) && ss) | 759 | if(ss && (lua_type(L, -1) == LUA_TNUMBER)) |
759 | { | 760 | { |
760 | ret |= 2; | 761 | ret |= 2; |
761 | src = FB_SCALARPACK((unsigned) luaL_checknumber(L, -1)); | 762 | src = FB_SCALARPACK((unsigned) lua_tointeger(L, -1)); |
762 | data_set(ss->elem, ss->x, ss->y, &src); | 763 | data_set(ss->elem, ss->x, ss->y, &src); |
763 | } | 764 | } |
764 | 765 | ||
@@ -834,10 +835,21 @@ static int blit_transform(lua_State *L, | |||
834 | case 27: { if(dst == src) { dst = clr; } break; } | 835 | case 27: { if(dst == src) { dst = clr; } break; } |
835 | case 28: { if(dst > src) { dst = clr; } break; } | 836 | case 28: { if(dst > src) { dst = clr; } break; } |
836 | case 29: { if(dst < src) { dst = clr; } break; } | 837 | case 29: { if(dst < src) { dst = clr; } break; } |
838 | #if 0 | ||
839 | /* src unneeded */ | ||
840 | case 30: { dst = clr; break; }/* copyC */ | ||
841 | case 31: { dst = clr | dst; break; }/* DorC */ | ||
842 | case 32: { dst = clr ^ dst; break; }/* DxorC */ | ||
843 | case 33: { dst = ~(clr | dst); break; }/* nDorC */ | ||
844 | case 34: { dst = (~clr) | dst; break; }/* DornC */ | ||
845 | case 35: { dst = clr & dst; break; }/* DandC */ | ||
846 | case 36: { dst = clr & (~dst); break; }/* nDandC */ | ||
847 | case 37: { dst = ~clr; break; }/* notC */ | ||
848 | #endif | ||
837 | 849 | ||
838 | }/*switch op*/ | 850 | }/*switch op*/ |
839 | fb_data data = FB_SCALARPACK(dst); | 851 | fb_data val = FB_SCALARPACK(dst); |
840 | data_set(ds->elem, ds->x, ds->y, &data); | 852 | data_set(ds->elem, ds->x, ds->y, &val); |
841 | return 1; | 853 | return 1; |
842 | } /* blit_transform */ | 854 | } /* blit_transform */ |
843 | 855 | ||
@@ -857,6 +869,22 @@ static int invert_transform(lua_State *L, | |||
857 | 869 | ||
858 | return 1; | 870 | return 1; |
859 | } /* invert_transform */ | 871 | } /* invert_transform */ |
872 | |||
873 | static int clear_transform(lua_State *L, | ||
874 | struct rli_iter_d *ds, | ||
875 | struct rli_iter_d *ss, | ||
876 | int op, | ||
877 | fb_data *color) | ||
878 | { | ||
879 | (void) L; | ||
880 | (void) op; | ||
881 | (void) ss; | ||
882 | |||
883 | data_set(ds->elem, ds->x, ds->y, color); | ||
884 | |||
885 | return 1; | ||
886 | } /* clear_transform */ | ||
887 | |||
860 | #endif /* RLI_EXTENDED */ | 888 | #endif /* RLI_EXTENDED */ |
861 | 889 | ||
862 | /* RLI to LUA Interface functions *********************************************/ | 890 | /* RLI to LUA Interface functions *********************************************/ |
@@ -865,8 +893,7 @@ RLI_LUA rli_new(lua_State *L) | |||
865 | int width = luaL_optint(L, 1, LCD_WIDTH); | 893 | int width = luaL_optint(L, 1, LCD_WIDTH); |
866 | int height = luaL_optint(L, 2, LCD_HEIGHT); | 894 | int height = luaL_optint(L, 2, LCD_HEIGHT); |
867 | 895 | ||
868 | luaL_argcheck(L, width > 0, 1, ERR_IDX_RANGE); | 896 | luaL_argcheck(L, width > 0 && height > 0, (width <= 0) ? 1 : 2, ERR_IDX_RANGE); |
869 | luaL_argcheck(L, height > 0, 2, ERR_IDX_RANGE); | ||
870 | 897 | ||
871 | rli_alloc(L, width, height); | 898 | rli_alloc(L, width, height); |
872 | 899 | ||
@@ -876,43 +903,41 @@ RLI_LUA rli_new(lua_State *L) | |||
876 | RLI_LUA rli_set(lua_State *L) | 903 | RLI_LUA rli_set(lua_State *L) |
877 | { | 904 | { |
878 | /*(set) (dst*, [x1, y1, clr, clip]) */ | 905 | /*(set) (dst*, [x1, y1, clr, clip]) */ |
879 | /* get and set share the same underlying function */ | 906 | return rli_setget(L, false, 5); |
880 | return rli_setget(L, false); | ||
881 | } | 907 | } |
882 | 908 | ||
883 | RLI_LUA rli_get(lua_State *L) | 909 | RLI_LUA rli_get(lua_State *L) |
884 | { | 910 | { |
885 | /*(get) (dst*, [x1, y1, clip]) */ | 911 | /*(get) (dst*, [x1, y1, clip]) */ |
886 | /* get and set share the same underlying function */ | 912 | return rli_setget(L, true, 4); |
887 | return rli_setget(L, true); | ||
888 | } | 913 | } |
889 | 914 | ||
890 | RLI_LUA rli_height(lua_State *L) | 915 | RLI_LUA rli_equal(lua_State *L) |
891 | { | 916 | { |
892 | struct rocklua_image *a = rli_checktype(L, 1); | 917 | struct rocklua_image *a = rli_checktype(L, 1); |
893 | lua_pushnumber(L, a->height); | 918 | struct rocklua_image *b = rli_checktype(L, 2); |
919 | lua_pushboolean(L, a->data == b->data); | ||
894 | return 1; | 920 | return 1; |
895 | } | 921 | } |
896 | 922 | ||
897 | RLI_LUA rli_width(lua_State *L) | 923 | RLI_LUA rli_height(lua_State *L) |
898 | { | 924 | { |
899 | struct rocklua_image *a = rli_checktype(L, 1); | 925 | struct rocklua_image *a = rli_checktype(L, 1); |
900 | lua_pushnumber(L, a->width); | 926 | lua_pushinteger(L, a->height); |
901 | return 1; | 927 | return 1; |
902 | } | 928 | } |
903 | 929 | ||
904 | RLI_LUA rli_equal(lua_State *L) | 930 | RLI_LUA rli_width(lua_State *L) |
905 | { | 931 | { |
906 | struct rocklua_image *a = rli_checktype(L, 1); | 932 | struct rocklua_image *a = rli_checktype(L, 1); |
907 | struct rocklua_image *b = rli_checktype(L, 2); | 933 | lua_pushinteger(L, a->width); |
908 | lua_pushboolean(L, a->data == b->data); | ||
909 | return 1; | 934 | return 1; |
910 | } | 935 | } |
911 | 936 | ||
912 | RLI_LUA rli_size(lua_State *L) | 937 | RLI_LUA rli_size(lua_State *L) |
913 | { | 938 | { |
914 | struct rocklua_image *a = rli_checktype(L, 1); | 939 | struct rocklua_image *a = rli_checktype(L, 1); |
915 | lua_pushnumber(L, a->elems); | 940 | lua_pushinteger(L, a->elems); |
916 | return 1; | 941 | return 1; |
917 | } | 942 | } |
918 | 943 | ||
@@ -921,17 +946,17 @@ RLI_LUA rli_raw(lua_State *L) | |||
921 | /*val = (img*, index, [new_val]) */ | 946 | /*val = (img*, index, [new_val]) */ |
922 | struct rocklua_image *a = rli_checktype(L, 1); | 947 | struct rocklua_image *a = rli_checktype(L, 1); |
923 | 948 | ||
924 | size_t i = (unsigned) luaL_checkint(L, 2); | 949 | size_t i = (unsigned) lua_tointeger(L, 2); |
925 | 950 | ||
926 | fb_data val; | 951 | fb_data val; |
927 | 952 | ||
928 | luaL_argcheck(L, i > 0 && i <= (a->elems), 2, ERR_IDX_RANGE); | 953 | luaL_argcheck(L, i > 0 && i <= (a->elems), 2, ERR_IDX_RANGE); |
929 | 954 | ||
930 | lua_pushnumber(L, FB_UNPACK_SCALAR_LCD(a->data[i-1])); | 955 | lua_pushinteger(L, FB_UNPACK_SCALAR_LCD(a->data[i-1])); |
931 | 956 | ||
932 | if(!lua_isnoneornil(L, 3)) | 957 | if(lua_type(L, 3) == LUA_TNUMBER) |
933 | { | 958 | { |
934 | val = FB_SCALARPACK((unsigned) luaL_checknumber(L, 3)); | 959 | val = FB_SCALARPACK((unsigned) lua_tointeger(L, 3)); |
935 | a->data[i-1] = val; | 960 | a->data[i-1] = val; |
936 | } | 961 | } |
937 | 962 | ||
@@ -943,7 +968,7 @@ RLI_LUA rli_tostring(lua_State *L) | |||
943 | /* (img, [infoitem]) */ | 968 | /* (img, [infoitem]) */ |
944 | struct rocklua_image *a = rli_checktype(L, 1); | 969 | struct rocklua_image *a = rli_checktype(L, 1); |
945 | 970 | ||
946 | int item = (unsigned) luaL_optint(L, 2, 0); | 971 | int item = lua_tointeger(L, 2); |
947 | size_t bytes = a->elems * sizeof(fb_data); | 972 | size_t bytes = a->elems * sizeof(fb_data); |
948 | 973 | ||
949 | switch(item) | 974 | switch(item) |
@@ -956,16 +981,19 @@ RLI_LUA rli_tostring(lua_State *L) | |||
956 | a->width, a->height, a->elems, bytes, LCD_DEPTH, LCD_PIXELFORMAT); | 981 | a->width, a->height, a->elems, bytes, LCD_DEPTH, LCD_PIXELFORMAT); |
957 | break; | 982 | break; |
958 | } | 983 | } |
959 | case RLI_INFO_TYPE: { lua_pushfstring(L, ROCKLUA_IMAGE ); break; } | 984 | case RLI_INFO_TYPE: { lua_pushfstring(L, ROCKLUA_IMAGE); break; } |
960 | case RLI_INFO_WIDTH: { lua_pushfstring(L, "%d", a->width ); break; } | 985 | case RLI_INFO_WIDTH: { lua_pushinteger(L, a->width); break; } |
961 | case RLI_INFO_HEIGHT: { lua_pushfstring(L, "%d", a->height ); break; } | 986 | case RLI_INFO_HEIGHT: { lua_pushinteger(L, a->height); break; } |
962 | case RLI_INFO_ELEMS: { lua_pushfstring(L, "%d", a->elems ); break; } | 987 | case RLI_INFO_ELEMS: { lua_pushinteger(L, a->elems); break; } |
963 | case RLI_INFO_BYTES: { lua_pushfstring(L, "%d", bytes ); break; } | 988 | case RLI_INFO_BYTES: { lua_pushinteger(L, bytes); break; } |
964 | case RLI_INFO_DEPTH: { lua_pushfstring(L, "%d", LCD_DEPTH ); break; } | 989 | case RLI_INFO_DEPTH: { lua_pushinteger(L, LCD_DEPTH ); break; } |
965 | case RLI_INFO_FORMAT: { lua_pushfstring(L, "%d", LCD_PIXELFORMAT); break; } | 990 | case RLI_INFO_FORMAT: { lua_pushinteger(L, LCD_PIXELFORMAT); break; } |
966 | case RLI_INFO_ADDRESS: { lua_pushfstring(L, "%p", a->data); break; } | 991 | case RLI_INFO_ADDRESS: { lua_pushfstring(L, "%p", a->data); break; } |
967 | } | 992 | } |
968 | 993 | ||
994 | /* lua_pushstring(L, lua_tostring(L, -1)); */ | ||
995 | lua_tostring(L, -1); /* converts item at index to string */ | ||
996 | |||
969 | return 1; | 997 | return 1; |
970 | } | 998 | } |
971 | 999 | ||
@@ -974,52 +1002,38 @@ RLI_LUA rli_ellipse(lua_State *L) | |||
974 | { | 1002 | { |
975 | /* (dst*, x1, y1, x2, y2, [clr, fillclr, clip]) */ | 1003 | /* (dst*, x1, y1, x2, y2, [clr, fillclr, clip]) */ |
976 | /* line and ellipse share the same init function */ | 1004 | /* line and ellipse share the same init function */ |
977 | return rli_line_ellipse(L, true); | 1005 | return rli_line_ellipse(L, true, 8); |
978 | } | 1006 | } |
979 | 1007 | ||
980 | RLI_LUA rli_line(lua_State *L) | 1008 | RLI_LUA rli_line(lua_State *L) |
981 | { | 1009 | { |
982 | /* (dst*, x1, y1, [x2, y2, clr, clip]) */ | 1010 | /* (dst*, x1, y1, [x2, y2, clr, clip]) */ |
983 | /* line and ellipse share the same init function */ | 1011 | /* line and ellipse share the same init function */ |
984 | return rli_line_ellipse(L, false); | 1012 | return rli_line_ellipse(L, false, 7); |
985 | } | 1013 | } |
986 | 1014 | ||
987 | RLI_LUA rli_iterator(lua_State *L) { | 1015 | RLI_LUA rli_iterator(lua_State *L) { |
988 | /* see rli_iterator_factory */ | 1016 | /* see rli_iterator_factory */ |
1017 | int params = 0; | ||
989 | struct rli_iter_d *ds; | 1018 | struct rli_iter_d *ds; |
990 | ds = (struct rli_iter_d *) lua_touserdata(L, lua_upvalueindex(1)); | 1019 | ds = (struct rli_iter_d *) lua_touserdata(L, lua_upvalueindex(1)); |
991 | 1020 | ||
992 | if(ds->dx != 0 || ds->dy != 0) | 1021 | if(ds->dx != 0 || ds->dy != 0) |
993 | { | 1022 | { |
994 | lua_pushnumber(L, FB_UNPACK_SCALAR_LCD(data_get(ds->elem, ds->x, ds->y))); | 1023 | params = rli_pushpixel(L, data_get(ds->elem, ds->x, ds->y), ds->x, ds->y); |
995 | |||
996 | lua_pushinteger(L, ds->x); | ||
997 | lua_pushinteger(L, ds->y); | ||
998 | 1024 | ||
999 | next_rli_iter(ds); /* load next element */ | 1025 | next_rli_iter(ds); /* load next element */ |
1000 | |||
1001 | return 3; | ||
1002 | } | 1026 | } |
1003 | return 0; /* nothing left to do */ | 1027 | return params; /* nothing left to do */ |
1004 | } | 1028 | } |
1005 | 1029 | ||
1006 | RLI_LUA rli_iterator_factory(lua_State *L) { | 1030 | RLI_LUA rli_iterator_factory(lua_State *L) |
1007 | /* (src*, [x1, y1, x2, y2, dx, dy]) */ | 1031 | { |
1008 | struct rocklua_image *a = rli_checktype(L, 1); /*image we wish to iterate*/ | 1032 | /* (points) (img*, [x1, y1, x2, y2, dx, dy, clip]) */ |
1009 | 1033 | /* (indices 1-8 are used by rli_iter_create) */ | |
1010 | struct rli_iter_d *ds; | ||
1011 | |||
1012 | int x1 = luaL_optint(L, 2, 1); | ||
1013 | int y1 = luaL_optint(L, 3, 1); | ||
1014 | int x2 = luaL_optint(L, 4, a->width - x1 + 1); | ||
1015 | int y2 = luaL_optint(L, 5, a->height - y1 + 1); | ||
1016 | int dx = luaL_optint(L, 6, 1); | ||
1017 | int dy = luaL_optint(L, 7, 1); | ||
1018 | 1034 | ||
1019 | /* create new iter + pushed onto stack */ | 1035 | /* create new iter + pushed onto stack */ |
1020 | ds = (struct rli_iter_d *) lua_newuserdata(L, sizeof(struct rli_iter_d)); | 1036 | rli_iter_create(L); |
1021 | |||
1022 | init_rli_iter(ds, a, x1, y1, x2, y2, dx, dy, false, false); | ||
1023 | 1037 | ||
1024 | /* returns the iter function with embedded iter data(up values) */ | 1038 | /* returns the iter function with embedded iter data(up values) */ |
1025 | lua_pushcclosure(L, &rli_iterator, 1); | 1039 | lua_pushcclosure(L, &rli_iterator, 1); |
@@ -1027,66 +1041,54 @@ RLI_LUA rli_iterator_factory(lua_State *L) { | |||
1027 | return 1; | 1041 | return 1; |
1028 | } | 1042 | } |
1029 | 1043 | ||
1030 | RLI_LUA rli_marshal(lua_State *L) /* also invert */ | 1044 | RLI_LUA rli_marshal(lua_State *L) /* also invert, clear */ |
1031 | { | 1045 | { |
1032 | /* (img*, [x1, y1, x2, y2, dx, dy, clip, function]) */ | 1046 | /* (marshal/invert/clear) (img*, [x1, y1, x2, y2, dx, dy, clip, function]) */ |
1033 | struct rocklua_image *a = rli_checktype(L, 1); | 1047 | /* (indices 1-8 are used by rli_iter_create) */ |
1034 | 1048 | fb_data clr; | |
1035 | struct rli_iter_d ds; | ||
1036 | |||
1037 | int x1 = luaL_optint(L, 2, 1); | ||
1038 | int y1 = luaL_optint(L, 3, 1); | ||
1039 | int x2 = luaL_optint(L, 4, a->width); | ||
1040 | int y2 = luaL_optint(L, 5, a->height); | ||
1041 | int dx = luaL_optint(L, 6, 1); | ||
1042 | int dy = luaL_optint(L, 7, 1); | ||
1043 | bool clip = luaL_optboolean(L, 8, false); | ||
1044 | |||
1045 | int lf_ref = LUA_NOREF; /* de-ref'd without consequence */ | ||
1046 | 1049 | ||
1047 | int (*rli_trans)(lua_State *, struct rli_iter_d *, struct rli_iter_d *, int, fb_data *); | 1050 | int (*rli_trans)(lua_State *, struct rli_iter_d *, struct rli_iter_d *, int, fb_data *); |
1048 | rli_trans = invert_transform; /* default transformation */ | 1051 | int ltype = lua_type (L, 9); |
1049 | 1052 | ||
1050 | if(!clip) | 1053 | /* create new iter + pushed onto stack */ |
1054 | struct rli_iter_d *ds = rli_iter_create(L); | ||
1055 | |||
1056 | if (ltype == LUA_TNUMBER) | ||
1051 | { | 1057 | { |
1052 | bounds_check_xy(L, a, 2, x1, 3, y1); | 1058 | clr = FB_SCALARPACK((unsigned) lua_tointeger(L, 9)); |
1053 | bounds_check_xy(L, a, 4, x2, 5, y2); | 1059 | rli_trans = clear_transform; |
1054 | } | 1060 | } |
1055 | 1061 | else if(ltype == LUA_TFUNCTION) /* custom function */ | |
1056 | init_rli_iter(&ds, a, x1, y1, x2, y2, dx, dy, false, false); | ||
1057 | |||
1058 | if(lua_isfunction(L, 9)) /* custom function */ | ||
1059 | { | 1062 | { |
1060 | rli_trans = custom_transform; | 1063 | rli_trans = custom_transform; |
1061 | lf_ref = register_luafunc(L, 9); | 1064 | lua_pushvalue(L, 9); /* ensure lua function on top of stack */ |
1062 | } | 1065 | } |
1066 | else | ||
1067 | rli_trans = invert_transform; /* default transformation */ | ||
1063 | 1068 | ||
1064 | do | 1069 | do |
1065 | { | 1070 | { |
1066 | luaL_argcheck(L, clip || (ds.elem != NULL), 1, ERR_DATA_OVF); | 1071 | if(!(*rli_trans)(L, ds, NULL, 0, &clr)) |
1067 | |||
1068 | if(!(*rli_trans)(L, &ds, NULL, lf_ref, NULL)) | ||
1069 | break; /* Custom op can quit early */ | 1072 | break; /* Custom op can quit early */ |
1070 | 1073 | ||
1071 | } while(next_rli_iter(&ds)); | 1074 | } while(next_rli_iter(ds)); |
1072 | 1075 | ||
1073 | luaL_unref(L, LUA_REGISTRYINDEX, lf_ref); /* de-reference custom function */ | ||
1074 | return 0; | 1076 | return 0; |
1075 | } | 1077 | } |
1076 | 1078 | ||
1077 | RLI_LUA rli_copy(lua_State *L) | 1079 | RLI_LUA rli_copy(lua_State *L) |
1078 | { | 1080 | { |
1079 | /* (dst*, src*, [d_x, d_y, s_x, s_y, x_off, y_off, clip, [op, funct/clr]]) */ | 1081 | /* (dst*, src*, [d_x, d_y, s_x, s_y, x_off, y_off, clip, [op, funct/clr]]) */ |
1080 | struct rocklua_image *d = rli_checktype(L, 1); /*dst*/ | 1082 | struct rocklua_image *dst = rli_checktype(L, 1); /* dst */ |
1081 | struct rocklua_image *s = rli_checktype(L, 2); /*src*/ | 1083 | struct rocklua_image *src = rli_checktype(L, 2); /* src */ |
1082 | 1084 | ||
1083 | struct rli_iter_d ds; /*dst*/ | 1085 | struct rli_iter_d ds; /* dst */ |
1084 | struct rli_iter_d ss; /*src*/ | 1086 | struct rli_iter_d ss; /* src */ |
1085 | 1087 | ||
1086 | /* copy whole image if possible */ | 1088 | /* copy whole image if possible */ |
1087 | if(s->elems == d->elems && s->width == d->width && lua_gettop(L) < 3) | 1089 | if(src->elems == dst->elems && src->width == dst->width && lua_gettop(L) < 3) |
1088 | { | 1090 | { |
1089 | rb->memcpy(d->data, s->data, d->elems * sizeof(fb_data)); | 1091 | rb->memcpy(dst->data, src->data, dst->elems * sizeof(fb_data)); |
1090 | return 0; | 1092 | return 0; |
1091 | } | 1093 | } |
1092 | 1094 | ||
@@ -1095,38 +1097,41 @@ RLI_LUA rli_copy(lua_State *L) | |||
1095 | int s_x = luaL_optint(L, 5, 1); | 1097 | int s_x = luaL_optint(L, 5, 1); |
1096 | int s_y = luaL_optint(L, 6, 1); | 1098 | int s_y = luaL_optint(L, 6, 1); |
1097 | 1099 | ||
1098 | int w = MIN(d->width - d_x, s->width - s_x); | 1100 | int w = MIN(dst->width - d_x, src->width - s_x); |
1099 | int h = MIN(d->height - d_y, s->height - s_y); | 1101 | int h = MIN(dst->height - d_y, src->height - s_y); |
1100 | 1102 | ||
1101 | int x_off = luaL_optint(L, 7, w); | 1103 | int x_off = luaL_optint(L, 7, w); |
1102 | int y_off = luaL_optint(L, 8, h); | 1104 | int y_off = luaL_optint(L, 8, h); |
1103 | 1105 | ||
1104 | bool clip = luaL_optboolean(L, 9, false); | 1106 | bool clip = lua_toboolean(L, 9); |
1105 | int op = luaL_optint(L, 10, 0); | 1107 | int op; /* 10 is operation for blit */ |
1106 | fb_data clr = FB_SCALARPACK(0); /* 11 is custom function | color */ | 1108 | fb_data clr; /* 11 is custom function | color */ |
1107 | 1109 | ||
1108 | bool d_swx = (x_off < 0); /* dest swap */ | 1110 | bool d_swx = (x_off < 0); /* dest swap */ |
1109 | bool d_swy = (y_off < 0); | 1111 | bool d_swy = (y_off < 0); |
1110 | bool s_swx = false; /* src swap */ | 1112 | bool s_swx = false; /* src swap */ |
1111 | bool s_swy = false; | 1113 | bool s_swy = false; |
1112 | 1114 | ||
1113 | int (*rli_trans)(lua_State *, struct rli_iter_d *, struct rli_iter_d *, int, fb_data *); | 1115 | int (*rli_trans)(lua_State *, struct rli_iter_d *, struct rli_iter_d *, int, fb_data *); |
1114 | rli_trans = blit_transform; /* default transformation */ | ||
1115 | |||
1116 | int lf_ref = LUA_NOREF; /* de-ref'd without consequence */ | ||
1117 | 1116 | ||
1118 | if(!clip) /* Out of bounds is not allowed */ | 1117 | if(!clip) /* Out of bounds is not allowed */ |
1119 | { | 1118 | { |
1120 | bounds_check_xy(L, d, 3, d_x, 4, d_y); | 1119 | bounds_check_xy(L, dst, 3, d_x, 4, d_y); |
1121 | bounds_check_xy(L, s, 5, s_x, 6, s_y); | 1120 | bounds_check_xy(L, src, 5, s_x, 6, s_y); |
1121 | w = MIN(w, ABS(x_off)); | ||
1122 | h = MIN(h, ABS(y_off)); | ||
1123 | bounds_check_xy(L, dst, 7, d_x + w, 8, d_y + h); | ||
1124 | bounds_check_xy(L, src, 7, s_x + w, 8, s_y + h); | ||
1125 | } | ||
1126 | else | ||
1127 | { | ||
1128 | if (w < 0 || h < 0) /* not an error but nothing to display */ | ||
1129 | return 0; | ||
1130 | w = MIN(w, ABS(x_off)); | ||
1131 | h = MIN(h, ABS(y_off)); | ||
1122 | } | 1132 | } |
1123 | else if (w < 0 || h < 0) /* not an error but nothing to display */ | ||
1124 | return 0; | ||
1125 | |||
1126 | w = MIN(w, ABS(x_off)); | ||
1127 | h = MIN(h, ABS(y_off)); | ||
1128 | 1133 | ||
1129 | /* if(s->data == d->data) need to care about fill direction */ | 1134 | /* if src->data == dst->data need to care about fill direction */ |
1130 | if(d_x > s_x) | 1135 | if(d_x > s_x) |
1131 | { | 1136 | { |
1132 | d_swx = !d_swx; | 1137 | d_swx = !d_swx; |
@@ -1139,67 +1144,46 @@ RLI_LUA rli_copy(lua_State *L) | |||
1139 | s_swy = !s_swy; | 1144 | s_swy = !s_swy; |
1140 | } | 1145 | } |
1141 | 1146 | ||
1142 | init_rli_iter(&ds, d, d_x, d_y, d_x + w, d_y + h, 1, 1, d_swx, d_swy); | 1147 | rli_iter_init(&ds, dst, d_x, d_y, d_x + w, d_y + h, 1, 1, d_swx, d_swy); |
1143 | 1148 | ||
1144 | init_rli_iter(&ss, s, s_x, s_y, s_x + w, s_y + h, 1, 1, s_swx, s_swy); | 1149 | rli_iter_init(&ss, src, s_x, s_y, s_x + w, s_y + h, 1, 1, s_swx, s_swy); |
1145 | 1150 | ||
1146 | if (op == 0xFF && lua_isfunction(L, 11)) /* custom function specified.. */ | 1151 | if (lua_type(L, 11) == LUA_TFUNCTION) /* custom function supplied.. */ |
1147 | { | 1152 | { |
1148 | rli_trans = custom_transform; | 1153 | rli_trans = custom_transform; |
1149 | lf_ref = register_luafunc(L, 11); | 1154 | lua_settop(L, 11); /* ensure lua function on top of stack */ |
1150 | op = lf_ref; | 1155 | clr = 0; |
1156 | op = 0; | ||
1151 | } | 1157 | } |
1152 | else | 1158 | else |
1153 | clr = FB_SCALARPACK((unsigned) luaL_optnumber(L, 11, LCD_BLACK)); | 1159 | { |
1160 | rli_trans = blit_transform; /* default transformation */ | ||
1161 | clr = FB_SCALARPACK((unsigned) lua_tointeger(L, 11)); | ||
1162 | op = lua_tointeger(L, 10); | ||
1163 | } | ||
1154 | 1164 | ||
1155 | do | 1165 | do |
1156 | { | 1166 | { |
1157 | if(!clip) | ||
1158 | { | ||
1159 | luaL_argcheck(L, ss.elem != NULL, 2, ERR_DATA_OVF); | ||
1160 | luaL_argcheck(L, ds.elem != NULL, 1, ERR_DATA_OVF); | ||
1161 | } | ||
1162 | |||
1163 | if(!(*rli_trans)(L, &ds, &ss, op, &clr)) | 1167 | if(!(*rli_trans)(L, &ds, &ss, op, &clr)) |
1164 | break; /* Custom op can quit early */ | 1168 | break; /* Custom op can quit early */ |
1165 | 1169 | ||
1166 | } while(next_rli_iter(&ds) && next_rli_iter(&ss)); | 1170 | } while(next_rli_iter(&ds) && next_rli_iter(&ss)); |
1167 | 1171 | ||
1168 | luaL_unref(L, LUA_REGISTRYINDEX, lf_ref); /* de-reference custom function */ | ||
1169 | return 0; | 1172 | return 0; |
1170 | } | 1173 | } |
1171 | 1174 | ||
1172 | RLI_LUA rli_clear(lua_State *L) | 1175 | RLI_LUA rli_clear(lua_State *L) |
1173 | { | 1176 | { |
1174 | /* (dst*, [color, x1, y1, x2, y2, clip]) */ | 1177 | /* (clear) (dst*, [color, x1, y1, x2, y2, clip, dx, dy]) */ |
1175 | struct rocklua_image *a = rli_checktype(L, 1); | 1178 | lua_settop(L, 9); |
1176 | |||
1177 | struct rli_iter_d ds; | ||
1178 | 1179 | ||
1179 | fb_data clr = FB_SCALARPACK((unsigned) luaL_optnumber(L, 2, LCD_BLACK)); | 1180 | lua_pushvalue(L, 7); /* clip -- index 8 */ |
1180 | int x1 = luaL_optint(L, 3, 1); | 1181 | lua_remove(L, 7); |
1181 | int y1 = luaL_optint(L, 4, 1); | ||
1182 | int x2 = luaL_optint(L, 5, a->width); | ||
1183 | int y2 = luaL_optint(L, 6, a->height); | ||
1184 | bool clip = luaL_optboolean(L, 7, false); | ||
1185 | 1182 | ||
1186 | if(!clip) | 1183 | lua_pushinteger(L, lua_tointeger(L, 2)); /*color -- index 9*/ |
1187 | { | 1184 | lua_remove(L, 2); |
1188 | bounds_check_xy(L, a, 3, x1, 4, y1); | ||
1189 | bounds_check_xy(L, a, 5, x2, 6, y2); | ||
1190 | } | ||
1191 | 1185 | ||
1192 | init_rli_iter(&ds, a, x1, y1, x2, y2, 1, 1, false, false); | 1186 | return rli_marshal(L); /* (img*, [x1, y1, x2, y2, dx, dy, clip, function]) */ |
1193 | |||
1194 | do | ||
1195 | { | ||
1196 | luaL_argcheck(L, clip || (ds.elem != NULL), 1, ERR_DATA_OVF); | ||
1197 | |||
1198 | data_set(ds.elem, ds.x, ds.y, &clr); | ||
1199 | |||
1200 | } while(next_rli_iter(&ds)); | ||
1201 | |||
1202 | return 0; | ||
1203 | } | 1187 | } |
1204 | #endif /* RLI_EXTENDED */ | 1188 | #endif /* RLI_EXTENDED */ |
1205 | 1189 | ||
@@ -1236,15 +1220,11 @@ LUALIB_API int rli_init(lua_State *L) | |||
1236 | 1220 | ||
1237 | luaL_newmetatable(L, ROCKLUA_IMAGE); | 1221 | luaL_newmetatable(L, ROCKLUA_IMAGE); |
1238 | 1222 | ||
1239 | lua_pushstring(L, "__index"); | 1223 | lua_pushvalue(L, -1); /* pushes the metatable */ |
1240 | lua_pushvalue(L, -2); /* pushes the metatable */ | 1224 | lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ |
1241 | lua_settable(L, -3); /* metatable.__index = metatable */ | ||
1242 | 1225 | ||
1243 | luaL_register(L, NULL, rli_lib); | 1226 | luaL_register(L, NULL, rli_lib); |
1244 | 1227 | ||
1245 | #ifdef RLI_EXTENDED | ||
1246 | luaL_register(L, ROCKLUA_IMAGE, rli_lib); | ||
1247 | #endif | ||
1248 | return 1; | 1228 | return 1; |
1249 | } | 1229 | } |
1250 | 1230 | ||
@@ -1256,7 +1236,7 @@ LUALIB_API int rli_init(lua_State *L) | |||
1256 | * ----------------------------- | 1236 | * ----------------------------- |
1257 | */ | 1237 | */ |
1258 | 1238 | ||
1259 | #define RB_WRAP(M) static int rock_##M(lua_State UNUSED_ATTR *L) | 1239 | #define RB_WRAP(func) static int rock_##func(lua_State UNUSED_ATTR *L) |
1260 | #ifdef HAVE_LCD_BITMAP | 1240 | #ifdef HAVE_LCD_BITMAP |
1261 | RB_WRAP(lcd_framebuffer) | 1241 | RB_WRAP(lcd_framebuffer) |
1262 | { | 1242 | { |