summaryrefslogtreecommitdiff
path: root/apps/plugins/lua/rocklib_img.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/lua/rocklib_img.c')
-rw-r--r--apps/plugins/lua/rocklib_img.c632
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
64struct rocklua_image 60struct 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 */
75struct rli_iter_d 71struct 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,
92static inline fb_data invert_color(fb_data rgb) 88static 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)
244static void bounds_check_xy(lua_State *L, struct rocklua_image *img, 240static 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
251static struct rocklua_image* rli_checktype(lua_State *L, int arg) 255static 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
260static struct rocklua_image * alloc_rlimage(lua_State *L, bool alloc_data, 284static 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
313static inline fb_data data_setget(fb_data *elem, int x, int y, fb_data *val) 337static 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
335static 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
341static inline fb_data data_get(fb_data *elem, int x, int y) 361static 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
347static fb_data* rli_get_element(struct rocklua_image* img, int x, int y) 366static 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 */
366static int rli_setget(lua_State *L, bool is_get) 394static 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
408static bool init_rli_iter(struct rli_iter_d *d, 428static 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
461static 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
467static int d_line(struct rocklua_image *img, 513static 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 */
541static int d_ellipse_elements(struct rocklua_image * img, 571static 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
581static int d_ellipse(struct rocklua_image *img, 599static 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 */
660static int rli_line_ellipse(lua_State *L, bool is_ellipse) 675static 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 713static 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 */
710static 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 */
719static int custom_transform(lua_State *L, 722static 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
873static 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)
876RLI_LUA rli_set(lua_State *L) 903RLI_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
883RLI_LUA rli_get(lua_State *L) 909RLI_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
890RLI_LUA rli_height(lua_State *L) 915RLI_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
897RLI_LUA rli_width(lua_State *L) 923RLI_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
904RLI_LUA rli_equal(lua_State *L) 930RLI_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
912RLI_LUA rli_size(lua_State *L) 937RLI_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
980RLI_LUA rli_line(lua_State *L) 1008RLI_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
987RLI_LUA rli_iterator(lua_State *L) { 1015RLI_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
1006RLI_LUA rli_iterator_factory(lua_State *L) { 1030RLI_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
1030RLI_LUA rli_marshal(lua_State *L) /* also invert */ 1044RLI_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
1077RLI_LUA rli_copy(lua_State *L) 1079RLI_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
1172RLI_LUA rli_clear(lua_State *L) 1175RLI_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
1261RB_WRAP(lcd_framebuffer) 1241RB_WRAP(lcd_framebuffer)
1262{ 1242{