summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2024-04-05 00:38:35 -0400
committerWilliam Wilgus <me.theuser@yahoo.com>2024-04-18 13:11:51 -0400
commita6570b7d378b6236c40d2e2bd983f7d53ad479e3 (patch)
tree6e1562a78c07a1fe0e05b36cf10542aff5ca7482
parent7f1b49693cd84b6e03e05d8a980fb99f26a781b1 (diff)
downloadrockbox-a6570b7d378b6236c40d2e2bd983f7d53ad479e3.tar.gz
rockbox-a6570b7d378b6236c40d2e2bd983f7d53ad479e3.zip
lua use lcd_drawline to draw lines inside rliimages
rewrite draw_text to use new viewport buffer set_viewport now accepts rliimage to allowe interfacing with rb. functions fix long standing 2-bit bug with text drawing in lua fix 2-bit img saving bug (i'm guessing just a one off, just enabled clipping) fix font_getstringsize bug fix shape of numbers draw_num.lua also add auto centering add page scrolling to printtable add a new demo script 'stars' Change-Id: I866905cee82ee89ebc0eb020a56a7ecdb101bf5e
-rw-r--r--apps/plugins/lua/include_lua/draw_num.lua21
-rw-r--r--apps/plugins/lua/include_lua/draw_text.lua85
-rw-r--r--apps/plugins/lua/include_lua/image_save.lua2
-rw-r--r--apps/plugins/lua/include_lua/printtable.lua9
-rw-r--r--apps/plugins/lua/rocklib_img.c150
-rwxr-xr-xapps/plugins/lua_scripts/rlimg.lua14
-rw-r--r--apps/plugins/lua_scripts/stars.lua256
7 files changed, 431 insertions, 106 deletions
diff --git a/apps/plugins/lua/include_lua/draw_num.lua b/apps/plugins/lua/include_lua/draw_num.lua
index 0f42c1f9f5..831e23e71e 100644
--- a/apps/plugins/lua/include_lua/draw_num.lua
+++ b/apps/plugins/lua/include_lua/draw_num.lua
@@ -20,17 +20,13 @@
20 * 20 *
21 ****************************************************************************/ 21 ****************************************************************************/
22]] 22]]
23
24--[[ Exposed Functions 23--[[ Exposed Functions
25 _draw_nums.print; binary (base = 2) , octal (base = 8), hexadecimal (base = 16) 24 _draw_nums.print; binary (base = 2) , octal (base = 8), hexadecimal (base = 16)
26 _draw_nums.nums; table of number characters 25 _draw_nums.nums; table of number characters
27]] 26]]
28
29if not rb.lcd_framebuffer then rb.splash(rb.HZ, "No Support!") return nil end 27if not rb.lcd_framebuffer then rb.splash(rb.HZ, "No Support!") return nil end
30
31local _draw_nums = {} do 28local _draw_nums = {} do
32 local _poly = require "draw_poly" 29 local _poly = require "draw_poly"
33
34 -- every 2 elements is an x, y coord pair 30 -- every 2 elements is an x, y coord pair
35 -- n[?] = {x,y,x,y,x,y} 31 -- n[?] = {x,y,x,y,x,y}
36 local nums = { 32 local nums = {
@@ -43,11 +39,11 @@ local _draw_nums = {} do
43 [2] = {1,1,3,1,4,2,4,3,3,4,1,5,1,7,4,7}, 39 [2] = {1,1,3,1,4,2,4,3,3,4,1,5,1,7,4,7},
44 [3] = {1,1,3,1,4,2,4,3,3,4,2,4,3,4,4,5,4,6,3,7,1,7}, 40 [3] = {1,1,3,1,4,2,4,3,3,4,2,4,3,4,4,5,4,6,3,7,1,7},
45 [4] = {1,1,1,3,2,4,4,4,4,1,4,7}, 41 [4] = {1,1,1,3,2,4,4,4,4,1,4,7},
46 [5] = {1,1,4,1,1,1,1,4,3,4,4,5,4,7,1,7}, 42 [5] = {1,1,4,1,1,1,1,4,3,4,4,5,4,6,3,7,1,7},
47 [6] = {1,2,1,4,1,6,2,7,3,7,4,6,4,4,1,4,1,2,2,1,4,1}, 43 [6] = {1,2,1,4,1,6,2,7,3,7,4,6,4,5,3,4,1,4,1,2,2,1,3,1,4,2},
48 [7] = {1,1,4,1,4,2,1,7}, 44 [7] = {1,1,4,1,4,2,1,7},
49 [8] = {1,2,1,6,2,7,3,7,4,6,4,4,1,4,4,4,4,2,3,1,2,1,1,2}, 45 [8] = {1,2,4,5,4,6,3,7,2,7,1,6,1,5,4,2,3,1,2,1,1,2},
50 [9] = {4,6,4,4,4,2,3,1,2,1,1,2,1,4,4,4,4,6,3,7,1,7}, 46 [9] = {4,6,4,4,4,2,3,1,2,1,1,2,1,3,2,4,4,4,4,6,3,7,2,7,1,6},
51 [10] = {1,7,1,4,4,4,4,7,4,2,3,1,2,1,1,2,1,4}, 47 [10] = {1,7,1,4,4,4,4,7,4,2,3,1,2,1,1,2,1,4},
52 [11] = {1,1,1,7,3,7,4,6,4,5,3,4,1,4,3,4,4,3,4,2,3,1,1,1}, 48 [11] = {1,1,1,7,3,7,4,6,4,5,3,4,1,4,3,4,4,3,4,2,3,1,1,1},
53 [12] = {4,2,3,1,2,1,1,2,1,6,2,7,3,7,4,6}, 49 [12] = {4,2,3,1,2,1,1,2,1,6,2,7,3,7,4,6},
@@ -56,8 +52,6 @@ local _draw_nums = {} do
56 [15] = {4,1,1,1,1,4,3,4,1,4,1,7}, 52 [15] = {4,1,1,1,1,4,3,4,1,4,1,7},
57 } 53 }
58 _draw_nums.nums = nums 54 _draw_nums.nums = nums
59
60
61 _draw_nums.print = function(img, num, x, y, chrw, color, base, prefix, bClip, scale_x, scale_y, t_nums) 55 _draw_nums.print = function(img, num, x, y, chrw, color, base, prefix, bClip, scale_x, scale_y, t_nums)
62 scale_x = scale_x or 1 56 scale_x = scale_x or 1
63 scale_y = scale_y or 1 57 scale_y = scale_y or 1
@@ -65,7 +59,6 @@ local _draw_nums = {} do
65 prefix = (prefix == nil or prefix == true) and true or false 59 prefix = (prefix == nil or prefix == true) and true or false
66 t_nums = t_nums or nums 60 t_nums = t_nums or nums
67 local max_x, max_y, digits = 0, 0, {} 61 local max_x, max_y, digits = 0, 0, {}
68
69 if num <= 0 then 62 if num <= 0 then
70 if num < 0 then 63 if num < 0 then
71 digits[-3] = -1 64 digits[-3] = -1
@@ -74,7 +67,6 @@ local _draw_nums = {} do
74 digits[0] = 0 67 digits[0] = 0
75 end 68 end
76 end 69 end
77
78 if not prefix and (base == 2 or base == 8 or base == 16) then 70 if not prefix and (base == 2 or base == 8 or base == 16) then
79 -- no prefix 71 -- no prefix
80 elseif base == 2 then 72 elseif base == 2 then
@@ -92,23 +84,20 @@ local _draw_nums = {} do
92 error("unknown number base: " .. base) 84 error("unknown number base: " .. base)
93 return nil 85 return nil
94 end 86 end
95
96 while num > 0 do -- get each digit (LeastSignificant) 87 while num > 0 do -- get each digit (LeastSignificant)
97 digits[#digits + 1] = num % base; 88 digits[#digits + 1] = num % base;
98 num=num/base; 89 num=num/base;
99 end 90 end
100
101 digits[#digits + 1] = digits[0] -- zero 91 digits[#digits + 1] = digits[0] -- zero
102 digits[#digits + 1] = digits[-1] -- base prefix 92 digits[#digits + 1] = digits[-1] -- base prefix
103 digits[#digits + 1] = digits[-2] -- base prefix (hex) 93 digits[#digits + 1] = digits[-2] -- base prefix (hex)
104 digits[#digits + 1] = digits[-3] -- neg sign 94 digits[#digits + 1] = digits[-3] -- neg sign
105
106 for i = #digits, 1, -1 do 95 for i = #digits, 1, -1 do
107 max_x, max_y = _poly.polyline(img, x, y, t_nums[digits[i]], 96 max_x, max_y = _poly.polyline(img, x, y, t_nums[digits[i]],
108 color, false, bClip, scale_x, scale_y) 97 color, false, bClip, scale_x, scale_y)
98 if chrw == 0 then chrw = max_x end
109 x = x + chrw 99 x = x + chrw
110 end 100 end
111
112 return x, y + max_y, chrw 101 return x, y + max_y, chrw
113 end 102 end
114end 103end
diff --git a/apps/plugins/lua/include_lua/draw_text.lua b/apps/plugins/lua/include_lua/draw_text.lua
index 3722931c2c..1d44954a5c 100644
--- a/apps/plugins/lua/include_lua/draw_text.lua
+++ b/apps/plugins/lua/include_lua/draw_text.lua
@@ -23,7 +23,6 @@
23-- draw text onto image if width/height are supplied text is centered 23-- draw text onto image if width/height are supplied text is centered
24 24
25if not rb.lcd_framebuffer then rb.splash(rb.HZ, "No Support!") return nil end 25if not rb.lcd_framebuffer then rb.splash(rb.HZ, "No Support!") return nil end
26
27do 26do
28 -- Internal Constants 27 -- Internal Constants
29 local rocklib_image = getmetatable(rb.lcd_framebuffer()) 28 local rocklib_image = getmetatable(rb.lcd_framebuffer())
@@ -40,81 +39,35 @@ do
40 return function(img, x, y, width, height, font, color, text) 39 return function(img, x, y, width, height, font, color, text)
41 font = font or rb.FONT_UI 40 font = font or rb.FONT_UI
42 41
43 local opts = {x = 0, y = 0, width = LCD_W - 1, height = LCD_H - 1,
44 font = font, drawmode = 3, fg_pattern = 0x1, bg_pattern = 0}
45
46 if rb.LCD_DEPTH == 2 then -- invert 2-bit screens
47 --vp.drawmode = bit.bxor(vp.drawmode, 4)
48 opts.fg_pattern = 3 - opts.fg_pattern
49 opts.bg_pattern = 3 - opts.bg_pattern
50 end
51 rb.set_viewport(opts)
52 42
53 local res, w, h = rb.font_getstringsize(text, font) 43 if rb.lcd_rgbpack ~= _NIL then -- Color target
54 44 rb.set_viewport(img, {fg_pattern = color, font = font, drawmode = 2})--DRMODE_FG
55 if not width then
56 width = 0
57 else 45 else
58 width = (width - w) / 2 46 if color ~= 0 then color = 3 end--DRMODE_SOLID
47 rb.set_viewport(img, {font = font, drawmode = color})
59 end 48 end
60 49
61 if not height then 50 if width or height then
62 height = 0 51 local res, w, h = rb.font_getstringsize(text, font)
63 else
64 height = (height - h) / 2
65 end
66
67 -- make a copy of the current screen for later
68 --local screen_img = _newimg(LCD_W, LCD_H)
69 local screen_img = _newimg(LCD_W, h * 2)
70 _copy(screen_img, _LCD)
71
72 -- check if the screen buffer is supplied image if so set img to the copy
73 if img == _LCD then
74 img = screen_img
75 end
76 52
77 -- we will be printing the text to the screen then blitting into img 53 if not width then
78 --rb.lcd_clear_display() 54 width = 0
79 _clear(_LCD, opts.bg_pattern or 0, 1, 1, LCD_W, h * 2) 55 else
80 56 width = (width - w) / 2
81 if w > LCD_W then -- text is too long for the screen do it in chunks 57 end
82 local l = 1
83 local resp, wp, hp
84 local lenr = text:len()
85
86 while lenr > 1 do
87 l = lenr
88 resp, wp, hp = rb.font_getstringsize(text:sub(1, l), font)
89
90 while wp >= LCD_W and l > 1 do
91 l = l - 1
92 resp, wp, hp = rb.font_getstringsize(text:sub( 1, l), font)
93 end
94
95 rb.lcd_putsxy(0, 0, text:sub(1, l))
96 text = text:sub(l)
97
98 if x + width > img:width() or y + height > img:height() then
99 break
100 end
101
102 -- using the mask we made blit color into img
103 _copy(img, _LCD, x + width, y + height, _NIL, _NIL, _NIL, _NIL, false, BSAND, color)
104 x = x + wp
105 --rb.lcd_clear_display()
106 _clear(_LCD, opts.bg_pattern or 0, 1, 1, LCD_W, h * 2)
107 58
108 lenr = text:len() 59 if not height then
60 height = 0
61 else
62 height = (height - h) / 2
109 end 63 end
110 else --w <= LCD_W 64 x = width + x
111 rb.lcd_putsxy(0, 0, text) 65 y = height + y
112 66
113 -- using the mask we made blit color into img
114 _copy(img, _LCD, x + width, y + height, _NIL, _NIL, _NIL, _NIL, false, BSAND, color)
115 end 67 end
116 68
117 _copy(_LCD, screen_img) -- restore screen 69 rb.lcd_putsxy(x, y, text)
70
118 rb.set_viewport() -- set viewport default 71 rb.set_viewport() -- set viewport default
119 return res, w, h 72 return res, w, h
120 end 73 end
diff --git a/apps/plugins/lua/include_lua/image_save.lua b/apps/plugins/lua/include_lua/image_save.lua
index 4735af46d7..27e63ca65a 100644
--- a/apps/plugins/lua/include_lua/image_save.lua
+++ b/apps/plugins/lua/include_lua/image_save.lua
@@ -198,7 +198,7 @@ do
198 end 198 end
199 199
200 -- Bitmap lines start at bottom unless biHeight is negative 200 -- Bitmap lines start at bottom unless biHeight is negative
201 for point in _points(img, 1, h, w + bytesleft, 1) do 201 for point in _points(img, 1, h, w + bytesleft, 1, 1, 1, true) do
202 imgdata[#imgdata + 1] = fs_bytes_E(bpp, point or 0) 202 imgdata[#imgdata + 1] = fs_bytes_E(bpp, point or 0)
203 203
204 if #fbuffer >= 31 then -- buffered write, increase # for performance 204 if #fbuffer >= 31 then -- buffered write, increase # for performance
diff --git a/apps/plugins/lua/include_lua/printtable.lua b/apps/plugins/lua/include_lua/printtable.lua
index c70fc1343f..02f3935ae6 100644
--- a/apps/plugins/lua/include_lua/printtable.lua
+++ b/apps/plugins/lua/include_lua/printtable.lua
@@ -145,13 +145,14 @@ function print_table(t, t_count, settings)
145 145
146 local wrap, justify, start, curpos, co_routine, hasheader, m_sel 146 local wrap, justify, start, curpos, co_routine, hasheader, m_sel
147 local header_fgc, header_bgc, item_fgc, item_bgc, item_selc 147 local header_fgc, header_bgc, item_fgc, item_bgc, item_selc
148 local table_linedesc, drawsep, overflow, dpad_fn 148 local table_linedesc, drawsep, overflow, dpad_fn, pagescroll
149 do 149 do
150 local s = settings or _print.get_settings() 150 local s = settings or _print.get_settings()
151 wrap, justify = s.wrap, s.justify 151 wrap, justify = s.wrap, s.justify
152 start, curpos = s.start, s.curpos 152 start, curpos = s.start, s.curpos
153 co_routine = s.co_routine 153 co_routine = s.co_routine
154 hasheader = s.hasheader 154 hasheader = s.hasheader
155 pagescroll = s.pagescroll
155 drawsep = s.drawsep 156 drawsep = s.drawsep
156 sb_width = s.sb_width or sb_width 157 sb_width = s.sb_width or sb_width
157 m_sel = false 158 m_sel = false
@@ -234,8 +235,13 @@ function print_table(t, t_count, settings)
234 dpad_fn(t_p.col, -1, -t_p.col_scrl, t_p.row, -1, -t_p.row_scrl, 235 dpad_fn(t_p.col, -1, -t_p.col_scrl, t_p.row, -1, -t_p.row_scrl,
235 nil, overflow, (t_p.row + t_p.vcursor - 1)) 236 nil, overflow, (t_p.row + t_p.vcursor - 1))
236 237
238
239 if pagescroll == true then
240 t_p.row = t_p.row + y_chg * maxline - 1
241 end
237 t_p.vcursor = t_p.vcursor + y_chg 242 t_p.vcursor = t_p.vcursor + y_chg
238 243
244
239 if t_p.vcursor > maxline or t_p.vcursor < t_p.vcursor_min then 245 if t_p.vcursor > maxline or t_p.vcursor < t_p.vcursor_min then
240 t_p.row = yi 246 t_p.row = yi
241 end 247 end
@@ -268,6 +274,7 @@ function print_table(t, t_count, settings)
268 elseif y_chg ~= 0 then 274 elseif y_chg ~= 0 then
269 --t_p.col = 0 -- reset column to the beginning 275 --t_p.col = 0 -- reset column to the beginning
270 _print.clear() 276 _print.clear()
277
271 _print.opt.sel_line(t_p.vcursor) 278 _print.opt.sel_line(t_p.vcursor)
272 279
273 t_p.row_scrl = set_accel(timeb, t_p.row_scrl, t_p) 280 t_p.row_scrl = set_accel(timeb, t_p.row_scrl, t_p)
diff --git a/apps/plugins/lua/rocklib_img.c b/apps/plugins/lua/rocklib_img.c
index 68e5325ce0..1857fbec5d 100644
--- a/apps/plugins/lua/rocklib_img.c
+++ b/apps/plugins/lua/rocklib_img.c
@@ -81,6 +81,57 @@ struct rli_iter_d
81 struct rocklua_image *img; 81 struct rocklua_image *img;
82}; 82};
83 83
84/* viewport for rliimages to use rb functions */
85static struct viewport img_vp =
86{
87 .x = 0,
88 .y = 0,
89 .width = 0,
90 .height = 0,
91 .font = FONT_UI,
92 .drawmode = DRMODE_SOLID,
93#if LCD_DEPTH > 1
94 .fg_pattern = LCD_WHITE,
95 .bg_pattern = LCD_BLACK,
96#endif
97};
98
99static void *img_address_fn(int x, int y)
100{
101/* Address lookup function
102 * core will use this to get an address from x/y coord
103 * depending on the lcd function core sometimes uses this for
104 * only the first and last address
105 * and handles subsequent address based on stride */
106
107 struct frame_buffer_t *fb = img_vp.buffer;
108/* LCD_STRIDEFORMAT & LCD_NATIVE_STRIDE macros allow Horiz screens to work with RB */
109#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
110 size_t element = (x * LCD_NATIVE_STRIDE(fb->stride)) + y;
111#else
112 size_t element = (y * LCD_NATIVE_STRIDE(fb->stride)) + x;
113#endif
114 /* use mod fb->elems to protect from buffer ovfl */
115 return fb->fb_ptr + (element % fb->elems);
116}
117/* sets an image into a vp to be used by rockbox image functions */
118static void img_set_as_vp(struct rocklua_image *img, struct viewport *vp)
119{
120 int w = img->width;
121 int h = img->height;
122 vp->x = 0;
123 vp->y = 0;
124 vp->width = w;
125 vp->height = h;
126
127 static struct frame_buffer_t fb;/* warning passed to external fns */
128 fb.elems = LCD_NBELEMS(w, h); /* recalculate these rb expects num pixels */
129 fb.stride = STRIDE_MAIN(w, h); /* recalculate these */
130 fb.data = img->data;
131 fb.get_address_fn = &img_address_fn;
132 rb->viewport_set_buffer(vp, &fb, SCREEN_MAIN); /* not multiscreen aware yet */
133}
134
84/* __tostring information enums */ 135/* __tostring information enums */
85enum rli_info {RLI_INFO_ALL = 0, RLI_INFO_TYPE, RLI_INFO_WIDTH, 136enum rli_info {RLI_INFO_ALL = 0, RLI_INFO_TYPE, RLI_INFO_WIDTH,
86 RLI_INFO_HEIGHT, RLI_INFO_ELEMS, RLI_INFO_BYTES, 137 RLI_INFO_HEIGHT, RLI_INFO_ELEMS, RLI_INFO_BYTES,
@@ -261,7 +312,7 @@ static void bounds_check_xy(lua_State *L, struct rocklua_image *img,
261 luaL_argerror(L, narg, ERR_IDX_RANGE); 312 luaL_argerror(L, narg, ERR_IDX_RANGE);
262} /* bounds_check_xy */ 313} /* bounds_check_xy */
263 314
264static struct rocklua_image* rli_checktype(lua_State *L, int arg) 315static struct rocklua_image* rli_checktype_opt(lua_State *L, int arg)
265{ 316{
266#if 0 317#if 0
267 return (struct rocklua_image*) luaL_checkudata(L, arg, ROCKLUA_IMAGE); 318 return (struct rocklua_image*) luaL_checkudata(L, arg, ROCKLUA_IMAGE);
@@ -284,10 +335,17 @@ static struct rocklua_image* rli_checktype(lua_State *L, int arg)
284 } 335 }
285 } 336 }
286 } 337 }
287 338 /* Not a ROCKLUA IMAGE */
288 luaL_typerror(L, arg, ROCKLUA_IMAGE); /* else error */ 339 return NULL;
289 return NULL; /* to avoid warnings */
290#endif 340#endif
341} /* rli_checktype_opt*/
342
343static struct rocklua_image* rli_checktype(lua_State *L, int arg)
344{
345 struct rocklua_image *img = rli_checktype_opt(L, arg);
346 if (img == NULL)
347 luaL_typerror(L, arg, ROCKLUA_IMAGE);
348 return img;
291} /* rli_checktype */ 349} /* rli_checktype */
292 350
293static struct rocklua_image * alloc_rlimage(lua_State *L, bool alloc_data, 351static struct rocklua_image * alloc_rlimage(lua_State *L, bool alloc_data,
@@ -519,6 +577,7 @@ static bool next_rli_iter(struct rli_iter_d *d)
519 return true; 577 return true;
520} /* next_rli_iter */ 578} /* next_rli_iter */
521 579
580#if 0
522static void d_line(struct rocklua_image *img, 581static void d_line(struct rocklua_image *img,
523 int x1, int y1, 582 int x1, int y1,
524 int x2, int y2, 583 int x2, int y2,
@@ -575,6 +634,38 @@ static void d_line(struct rocklua_image *img,
575 } 634 }
576 635
577} /* d_line */ 636} /* d_line */
637#endif
638
639
640static void d_line(struct rocklua_image *img,
641 int x1, int y1,
642 int x2, int y2,
643 fb_data *clr)
644{
645 /* NOTE! clr passed as pointer */
646#if LCD_DEPTH == 2
647 img_vp.fg_pattern = 0x55 * (~(*clr) & 3);
648 img_vp.drawmode = DRMODE_FG;
649#elif LCD_DEPTH > 1
650 img_vp.fg_pattern = *clr;
651 img_vp.drawmode = DRMODE_FG;
652#else /* bit of a hack to make sure lines show properly from lua */
653 /* use rb.lcd_drawline if you want full control */
654
655 img_vp.drawmode = *clr & (DRMODE_SOLID|DRMODE_INVERSEVID);
656 if (img_vp.drawmode != (DRMODE_SOLID|DRMODE_INVERSEVID))
657 img_vp.drawmode = DRMODE_SOLID;
658#endif
659
660 img_set_as_vp(img, &img_vp);
661
662 struct viewport *oldvp = rb->screens[SCREEN_MAIN]->set_viewport(&img_vp);
663
664 rb->lcd_drawline(x1 - 1, y1 - 1 , x2 - 1, y2 - 1);
665
666 rb->screens[SCREEN_MAIN]->set_viewport(oldvp);
667
668} /* d_line */
578 669
579/* ellipse worker function */ 670/* ellipse worker function */
580static void d_ellipse_elements(struct rocklua_image * img, 671static void d_ellipse_elements(struct rocklua_image * img,
@@ -1266,9 +1357,21 @@ RB_WRAP(lcd_clear_display)
1266 1357
1267RB_WRAP(lcd_set_drawmode) 1358RB_WRAP(lcd_set_drawmode)
1268{ 1359{
1360 int previous;
1269 int mode = (int) luaL_checkint(L, 1); 1361 int mode = (int) luaL_checkint(L, 1);
1270 RB_SCREENS(L, 2, set_drawmode, mode); 1362 if (rli_checktype_opt(L, 2) != NULL) /* is rliimage? */
1271 return 0; 1363 {
1364 previous = img_vp.drawmode;
1365 img_vp.drawmode = mode;
1366 }
1367 else
1368 {
1369 struct viewport *vp = *(RB_SCREEN_STRUCT(L, 2)->current_viewport);
1370 previous = vp->drawmode;
1371 RB_SCREENS(L, 2, set_drawmode, mode);
1372 }
1373 lua_pushinteger(L, previous);
1374 return 1;
1272} 1375}
1273 1376
1274/* helper function for lcd_puts functions */ 1377/* helper function for lcd_puts functions */
@@ -1443,6 +1546,7 @@ RB_WRAP(lcd_scroll_stop)
1443 1546
1444static inline struct viewport* opt_viewport(lua_State *L, 1547static inline struct viewport* opt_viewport(lua_State *L,
1445 int narg, 1548 int narg,
1549 bool set_coords,
1446 struct viewport* vp, 1550 struct viewport* vp,
1447 struct viewport* alt) 1551 struct viewport* alt)
1448{ 1552{
@@ -1450,14 +1554,23 @@ static inline struct viewport* opt_viewport(lua_State *L,
1450 return alt; 1554 return alt;
1451 1555
1452 luaL_checktype(L, narg, LUA_TTABLE); 1556 luaL_checktype(L, narg, LUA_TTABLE);
1453 1557 if (set_coords)
1454 vp->x = check_tablevalue(L, "x", narg); 1558 {
1455 vp->y = check_tablevalue(L, "y", narg); 1559 vp->x = check_tablevalue(L, "x", narg);
1456 vp->width = check_tablevalue(L, "width", narg); 1560 vp->y = check_tablevalue(L, "y", narg);
1457 vp->height = check_tablevalue(L, "height", narg); 1561 vp->width = check_tablevalue(L, "width", narg);
1458 vp->font = check_tablevalue(L, "font", narg); 1562 vp->height = check_tablevalue(L, "height", narg);
1563 }
1564 vp->font = check_tablevalue_def(L, "font", narg, FONT_UI);
1459 vp->drawmode = check_tablevalue_def(L, "drawmode", narg, DRMODE_SOLID); 1565 vp->drawmode = check_tablevalue_def(L, "drawmode", narg, DRMODE_SOLID);
1460#if LCD_DEPTH > 1 1566
1567#if LCD_DEPTH == 2
1568 unsigned int fg = check_tablevalue(L, "fg_pattern", narg);
1569 unsigned int bg = check_tablevalue(L, "bg_pattern", narg);
1570 /*invert fg and bg patterns (3-)*/
1571 vp->fg_pattern = 0x55 * (3 - (~(fg) & 3));
1572 vp->bg_pattern = 0x55 * (3 - (~(bg) & 3));
1573#elif LCD_DEPTH > 1
1461 vp->fg_pattern = (unsigned int) check_tablevalue(L, "fg_pattern", narg); 1574 vp->fg_pattern = (unsigned int) check_tablevalue(L, "fg_pattern", narg);
1462 vp->bg_pattern = (unsigned int) check_tablevalue(L, "bg_pattern", narg); 1575 vp->bg_pattern = (unsigned int) check_tablevalue(L, "bg_pattern", narg);
1463#endif 1576#endif
@@ -1467,8 +1580,15 @@ static inline struct viewport* opt_viewport(lua_State *L,
1467 1580
1468RB_WRAP(set_viewport) 1581RB_WRAP(set_viewport)
1469{ 1582{
1583 void *ud = rli_checktype_opt(L, 1);
1584 if (ud != NULL)
1585 {
1586 img_set_as_vp((struct rocklua_image*) ud, &img_vp);
1587 RB_SCREENS(L, 3, set_viewport, opt_viewport(L, 2, false, &img_vp, &img_vp));
1588 return 0;
1589 }
1470 static struct viewport vp; 1590 static struct viewport vp;
1471 RB_SCREENS(L, 2, set_viewport, opt_viewport(L, 1, &vp, NULL)); 1591 RB_SCREENS(L, 2, set_viewport, opt_viewport(L, 1, true, &vp, NULL));
1472 return 0; 1592 return 0;
1473} 1593}
1474 1594
@@ -1489,7 +1609,7 @@ RB_WRAP(font_getstringsize)
1489 else 1609 else
1490 fontnumber = FONT_SYSFIXED; 1610 fontnumber = FONT_SYSFIXED;
1491 1611
1492 if lua_isnil(L, 2) 1612 if lua_isnoneornil(L, 2)
1493 result = RB_SCREENS(L, 3, getstringsize, str, &w, &h); 1613 result = RB_SCREENS(L, 3, getstringsize, str, &w, &h);
1494 else 1614 else
1495 result = rb->font_getstringsize(str, &w, &h, fontnumber); 1615 result = rb->font_getstringsize(str, &w, &h, fontnumber);
diff --git a/apps/plugins/lua_scripts/rlimg.lua b/apps/plugins/lua_scripts/rlimg.lua
index c9dde65ed4..c4eefc7aa9 100755
--- a/apps/plugins/lua_scripts/rlimg.lua
+++ b/apps/plugins/lua_scripts/rlimg.lua
@@ -76,7 +76,7 @@ local BLUE = _clr.set(WHITE, 0, 0, 255)
76------------------------------------------- 76-------------------------------------------
77local clrs 77local clrs
78local CANCEL_BUTTON = rb.actions.PLA_CANCEL 78local CANCEL_BUTTON = rb.actions.PLA_CANCEL
79 79local LCD_DEPTH = rb.LCD_DEPTH
80-- EXAMPLES ---------------------------------------------------------------------- EXAMPLES--------------------------------------------------------------------- 80-- EXAMPLES ---------------------------------------------------------------------- EXAMPLES---------------------------------------------------------------------
81function my_blit(dst_val, dx, dy, src_val, sx, sy) 81function my_blit(dst_val, dx, dy, src_val, sx, sy)
82 -- user defined blit operation 82 -- user defined blit operation
@@ -84,7 +84,7 @@ function my_blit(dst_val, dx, dy, src_val, sx, sy)
84 --you may change pixels in both the source and dest image 84 --you may change pixels in both the source and dest image
85 --return nil to stop early 85 --return nil to stop early
86 86
87 if _lcd.DEPTH < 2 then 87 if LCD_DEPTH < 2 then
88 return src_val 88 return src_val
89 end 89 end
90 90
@@ -518,7 +518,7 @@ function twist(img)
518 for ix = 1, _lcd.W, w do 518 for ix = 1, _lcd.W, w do
519 y_col = y_col + 1 519 y_col = y_col + 1
520 y = ims.y_pos[(y_col % 2) + 1] 520 y = ims.y_pos[(y_col % 2) + 1]
521 if _lcd.DEPTH > 1 then 521 if LCD_DEPTH > 1 then
522 _lcd:copy(ims.strip, ix, 1, 1, y, w, h, false, _blit.BDEQC, colors[1]) 522 _lcd:copy(ims.strip, ix, 1, 1, y, w, h, false, _blit.BDEQC, colors[1])
523 else 523 else
524 _lcd:copy(ims.strip, ix, 1, 1, y, w, h, false, _blit.BSAND) 524 _lcd:copy(ims.strip, ix, 1, 1, y, w, h, false, _blit.BSAND)
@@ -767,10 +767,10 @@ function long_text()
767 local wait = 0 767 local wait = 0
768 w = w + wp * 3 768 w = w + wp * 3
769 h = h + 4 769 h = h + 4
770 local img = _img.new(w + 1, h) 770 local img = _img.new(w + 1, h + 1)
771 img:clear(BLACK) 771 img:clear(BLACK)
772 _draw.rounded_rect_filled(img, 1, 1, w, h, 15, WHITE) 772 _draw.rounded_rect_filled(img, 1, 1, w, h, 15, WHITE)
773 _draw_text(img, 1, 2, nil, nil, nil, BLACK, txt) 773 _draw_text(img, 1, 1, nil, nil, nil, BLACK, txt)
774 774
775 for p = -w + 1, w - 1 do 775 for p = -w + 1, w - 1 do
776 wait = 0 776 wait = 0
@@ -858,7 +858,7 @@ function main_menu()
858 [14] = function(EXIT_) return true end 858 [14] = function(EXIT_) return true end
859 } 859 }
860 860
861 if _lcd.DEPTH < 2 then 861 if LCD_DEPTH < 2 then
862 table.remove(mt, 10) 862 table.remove(mt, 10)
863 table.remove(ft, 10) 863 table.remove(ft, 10)
864 end 864 end
@@ -880,7 +880,7 @@ _timer("main") -- keep track of how long the program ran
880-- Clear the screen 880-- Clear the screen
881_lcd:clear(BLACK) 881_lcd:clear(BLACK)
882 882
883if _lcd.DEPTH > 1 then 883if LCD_DEPTH > 1 then
884--draw a gradient using available colors 884--draw a gradient using available colors
885if IS_COLOR_TARGET == true then 885if IS_COLOR_TARGET == true then
886 clrs = { 886 clrs = {
diff --git a/apps/plugins/lua_scripts/stars.lua b/apps/plugins/lua_scripts/stars.lua
new file mode 100644
index 0000000000..14fae0c4b7
--- /dev/null
+++ b/apps/plugins/lua_scripts/stars.lua
@@ -0,0 +1,256 @@
1--[[
2 __________ __ ___.
3 Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 \/ \/ \/ \/ \/
8 $Id$
9
10 Copyright (C) 2024 William Wilgus
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 as published by the Free Software Foundation; either version 2
14 of the License, or (at your option) any later version.
15 This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 KIND, either express or implied.
17]]--
18--https://nullprogram.com/blog/2011/06/13/ [Infinite Parallax Starfield]
19
20-- Imports
21local _clr = require("color") -- clrset, clrinc provides device independent colors
22local _lcd = require("lcd") -- lcd helper functions
23local _draw = require("draw") -- draw all the things (primitives)
24local _poly = require("draw_poly") -- vector drawing with tables of coords
25require("actions")
26--'CONSTANTS' (in lua there really is no such thing as all vars are mutable)
27--------------------------------------------------------
28--colors for fg/bg ------------------------
29--first number of each quad is fallback for monochrome devices, excluded columns default to 0
30local WHITE = _clr.set(-1, 255, 255, 255)
31local BLACK = _clr.set(0, 0, 0, 0)
32local RED = _clr.set(WHITE, 100)
33local GREEN = _clr.set(WHITE, 0, 100)
34local BGREEN = _clr.set(WHITE, 0, 255)
35local BLUE = _clr.set(WHITE, 0, 0, 100)
36
37local STAR_SEED = 0x9d2c5680;
38local STAR_TILE_SIZE = math.max(rb.LCD_WIDTH, rb.LCD_HEIGHT) * 4;
39local bxor, band, rshift, lshift, arshift = bit.bxor, bit.band, bit.rshift, bit.lshift, bit.arshift
40local random, randomseed = math.random, math.randomseed
41local start_x, start_y, start_z
42
43-- load users coords from file if it exists
44local fname = rb.PLUGIN_DATA_DIR .. "/stars.pos"
45file = io.open(fname, "r")
46if file then
47 local v = 0
48 for line in file:lines() do
49 v = v + 1
50 if v == 1 then
51 start_x = tonumber(line) or 0
52 elseif v == 2 then
53 start_y = tonumber(line) or 0
54 elseif v == 3 then
55 start_z = tonumber(line) or 0
56 else
57 break;
58 end
59 end
60 io.close( file )
61end
62
63-- Robert Jenkins' 96 bit Mix Function.
64local function mix (a, b, c)
65 a=a-b; a=a-c; a=bxor(a, (rshift(c, 13)));
66 b=b-c; b=b-a; b=bxor(b, (lshift(a, 8)));
67 c=c-a; c=c-b; c=bxor(c, (rshift(b, 13)));
68 a=a-b; a=a-c; a=bxor(a, (rshift(c, 12)));
69 b=b-c; b=b-a; b=bxor(b, (lshift(a, 16)));
70 c=c-a; c=c-b; c=bxor(c, (rshift(b, 5)));
71 a=a-b; a=a-c; a=bxor(a, (rshift(c, 3)));
72 b=b-c; b=b-a; b=bxor(b, (lshift(a, 10)));
73 c=c-a; c=c-b; c=bxor(c, (rshift(b, 15)));
74
75 return c
76end
77
78-- given 32 bit number returns a table of 8 nibbles (4 bits)
79local function s_bytes_nib(bits, value)
80 -- bits must be multiples of 8 (sizeof byte)
81 local bbuffer = {}
82 local byte
83 local nbytes = bit.rshift(bits, 3)
84 for b = 1, nbytes do
85 if value > 0 then
86 byte = value % 256
87 value = (value - byte) / 256
88 else
89 byte = 0
90 end
91 bbuffer[#bbuffer + 1] = band(byte,0xF)
92 bbuffer[#bbuffer + 1] = band(rshift(byte, 2), 0xF)
93 end
94 return bbuffer
95end
96
97--[[ given table t and total elems desired uses random elems of t
98 and random numbers between 1 and max_v if #t < total_elems]]
99function randomize_table(t, total_elems, max_v)
100 local rand_t = {}
101 local i = 1
102 repeat
103 local v = t[random(1, total_elems)]
104 if v then
105 rand_t[i] = v
106 else
107 rand_t[i] = random(1, max_v)
108 end
109 i = i + 1
110 until i > total_elems
111 return rand_t
112end
113
114local function drawship(img, x, y, color, ship_t)
115 --_poly.polyline(img, x, y, ship_t, color, true, true)
116 _poly.polygon(img, x, y, ship_t, color, BLACK, true)
117end
118
119local function draw_astroid(img, x, y, size, shape, color, scale_x, scale_y)
120 --the random number generator gets seeded with the hash so we get the same figure each time
121 randomseed(shape)
122 -- we also use the 4 bytes of the hash as 4 coord pairs and randomly generate 8 more (16) half the size (8)
123 local uniq_t = randomize_table(s_bytes_nib(32, shape), 16, 8)
124 _poly.polyline(img, x, y, uniq_t, color, true, true, scale_x or 1, scale_y or 1)
125 --_poly.polygon(img, x, y, uniq_t, color, color, true, scale_x or 1, scale_y or 1) --filled figures
126end
127
128local function drawStars (img, xoff, yoff, starscale, color, scale_x, scale_y)
129 local size = STAR_TILE_SIZE / starscale
130 local s_x, s_y = scale_x, scale_y
131 local w, h = rb.LCD_WIDTH, rb.LCD_HEIGHT
132
133 -- Top-left tile's top-left position
134 local sx = ((xoff - w/2) / size) * size - size;
135 local sy = ((yoff - h/2) / size) * size - size;
136
137 --Draw each tile currently in view.
138 for i = sx, w + sx + size*3, size do
139 for j = sy, h + sy + size*3, size do
140 local hash = mix(STAR_SEED, (i / size), (j / size))
141 for n = 0, 2 do
142 local px = (hash % size) + (i - xoff);
143 hash = arshift(hash, 3)
144
145 local py = (hash % size) + (j - yoff);
146 hash = arshift(hash, 3)
147
148 if px > 0 and px < w and py > 0 and py < h then
149 if n > 0 and starscale < 5 then
150 draw_astroid(img, px, py, n, hash, color, s_x, s_y)
151 else
152 if scale_x > 1 then
153 img:set(px, py, color)
154 img:set(px + 1, py, color)
155 elseif scale_y > 1 then
156 img:set(px, py, color)
157 img:set(px, py + 1, color)
158 else
159 img:set(px, py, color)
160 end
161 end
162 end
163 end
164 end
165 end
166end
167
168do
169 local act = rb.actions
170 local quit = false
171 local last_action = 0
172 local x,y,z = start_x or 0, start_y or 0, start_z or 8
173 local x_fast = rb.LCD_WIDTH / 4
174 local y_fast = rb.LCD_HEIGHT / 4
175 local ship_x = (rb.LCD_WIDTH - 0xF) / 2
176 local ship_y = rb.LCD_HEIGHT - (rb.LCD_HEIGHT / 3)
177 local scale_x, scale_y = 1, 1
178 -- vector draw the ship points for each direction (<>^v)
179 local ship_lt_t = {0,7, 15,0, 9,7, 15,15, 0,7}
180 local ship_rt_t = {0,0, 5,7, 0,15, 15,7, 0,0}
181 local ship_up_t = {0,15, 7,0, 15,15, 7,9, 0,15}
182 local ship_dn_t = {0,0, 7,15, 15,0, 7,5, 0,0}
183 local ship_t = ship_up_t
184
185 function action_event(action)
186 if action == act.PLA_EXIT or action == act.PLA_CANCEL then
187 quit = true
188 start_x, start_y, start_z = x, y, z
189 elseif action == act.PLA_RIGHT_REPEAT then
190 x = x + x_fast
191 scale_x = scale_x + 1
192 scale_y = 1
193 elseif action == act.PLA_LEFT_REPEAT then
194 x = x - x_fast
195 scale_x = scale_x + 1
196 scale_y = 1
197 elseif action == act.PLA_UP_REPEAT then
198 y = y - y_fast
199 scale_y = scale_y + 1
200 scale_x = 1
201 elseif action == act.PLA_DOWN_REPEAT then
202 y = y + y_fast
203 scale_y = scale_y + 1
204 scale_x = 1
205 elseif action == act.PLA_RIGHT then
206 x = x + 1
207 ship_t = ship_rt_t
208 elseif action == act.PLA_LEFT then
209 x = x - 1
210 ship_t = ship_lt_t
211 elseif action == act.PLA_UP then
212 y = y - 1
213 ship_t = ship_up_t
214 elseif action == act.PLA_DOWN then
215 y = y + 1
216 ship_t = ship_dn_t
217 elseif action == act.PLA_SELECT then
218 z = z + 4
219 if z > 16 then z = 0 end
220 elseif action == act.ACTION_NONE then
221 scale_x = 1
222 scale_y = 1
223 end
224
225 _lcd:clear(BLACK)
226 for i = 0, z, 4 do
227 drawStars(_LCD, x, y, i+1, RED, scale_x, scale_y)
228 drawStars(_LCD, x, y, i+2, GREEN, scale_x, scale_y)
229 drawStars(_LCD, x, y, i+3, BLUE, scale_x, scale_y)
230 drawStars(_LCD, x, y, i+4, WHITE, scale_x, scale_y)
231 end
232 drawship(_LCD, ship_x, ship_y, BGREEN, ship_t)
233 _lcd:update()
234
235 last_action = action
236 end
237
238 function action_set_quit(bQuit)
239 quit = bQuit
240 end
241
242 function action_quit()
243 return quit
244 end
245end
246
247action_event(rb.actions.ACTION_NONE) -- we can call this now but not after registering..
248local eva = rockev.register("action", action_event)
249
250while not action_quit() do rb.sleep(rb.HZ) end
251
252if start_x and start_y then
253 file = io.open(fname, "w")
254 file:write(start_x, "\n", start_y, "\n", start_z, "\n")
255 io.close( file )
256end