summaryrefslogtreecommitdiff
path: root/apps/plugins/lua/include_lua/print.lua
diff options
context:
space:
mode:
authorWilliam Wilgus <me.theuser@yahoo.com>2018-07-23 02:50:22 +0200
committerWilliam Wilgus <me.theuser@yahoo.com>2018-07-23 05:13:32 +0200
commitaf35d1991633f33965801dcb153a9860c4432816 (patch)
treeb6accfcf2914ff7f565d60b9338dfa7998e27c68 /apps/plugins/lua/include_lua/print.lua
parentef210b5fe4f72a102dcaa1f752d3022d62da8bc4 (diff)
downloadrockbox-af35d1991633f33965801dcb153a9860c4432816.tar.gz
rockbox-af35d1991633f33965801dcb153a9860c4432816.zip
Rocklua -- Extend / Fix rliImage
Some devices(1-bit / 2-bit displays) have packed bit formats that need to be unpacked in order to work on them at a pixel level. This caused a few issues on 1 & 2-bit devices: Greatly Oversized data arrays for bitmaps Improper handling of native image data Framebuffer data was near unusable without jumping through hoops Conversion between native addressing and per pixel addressing incurs extra overhead but it is much faster to do it on the 'C' side rather than in lua. Not to mention the advantage of a unified interface for the end programer ------------------------------------------------------------------- Adds a sane way to access each pixel of image data Adds: -------------------------------------------------------------------- img:clear([color],[x1],[y1],[x2],[y2]) (set whole image or a portion to a particular value) -------------------------------------------------------------------- img:invert([x1],[y1],[x2],[y2]) (inverts whole image or a portion) -------------------------------------------------------------------- img:marshal([x1],[y1],[x2],[y2],[funct]) (calls funct for each point defined by rect of x1,y1 x2,y2 returns value and allows setting value of each point return nil to terminate early) -------------------------------------------------------------------- img:points([x1],[y1],[x2],[y2],[dx],[dy]) (returns iterator function that steps delta-x and delta-y pixels each call returns value of pixel each call but doesn't allow setting to a new value compare to lua pairs method) -------------------------------------------------------------------- img:copy(src,[x1],[y1],[x2],[y2],[w],[h],[clip][operation][clr/funct]) (copies all or part of an image -- straight copy or special ops optionally calls funct for each point defined by rect of x1, y1, w, h and x2, y2, w, h for dest and src images returns value of dst and src and allows setting value of each point return nil to terminate early) -------------------------------------------------------------------- img:line(x1, y1, x2, y2, color) -------------------------------------------------------------------- img:ellipse(x1, y1, x2, y2, color, [fillcolor] -------------------------------------------------------------------- Fixed handling of 2-bit vertical integrated screens Added direct element access for saving / restoring native image etc. Added more data to tostring() handler and a way to access individual items Added equals method to see if two variables reference the same image address (doesn't check if two separate images contain the same 'picture') Optimized get and set routines Fixed out of bound x coord access shifting to next line Added lua include files to expose new functionality Finished image saving routine Static allocation of set_viewport struct faster + saves ram over dynamic Cleaned up code Fixed pixel get/set for 1/2 bit devices Fixed handling for 24-bit devices (32?) ------------------------------------------------------------------------- Example lua script to follow on forums ------------------------------------------------------------------------- Change-Id: I8a9ff0ff72aacf4b1662767ccb2b312fc355239c
Diffstat (limited to 'apps/plugins/lua/include_lua/print.lua')
-rw-r--r--apps/plugins/lua/include_lua/print.lua378
1 files changed, 378 insertions, 0 deletions
diff --git a/apps/plugins/lua/include_lua/print.lua b/apps/plugins/lua/include_lua/print.lua
new file mode 100644
index 0000000000..9b21dafb9d
--- /dev/null
+++ b/apps/plugins/lua/include_lua/print.lua
@@ -0,0 +1,378 @@
1--[[ Lua Print functions
2/***************************************************************************
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
10 *
11 * Copyright (C) 2017 William Wilgus
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22]]
23
24--[[ Exposed Functions
25
26 _print.clear
27 _print.f
28 _print.opt
29 _print.opt.area
30 _print.opt.autoupdate
31 _print.opt.color
32 _print.opt.column
33 _print.opt.defaults
34 _print.opt.get
35 _print.opt.justify
36 _print.opt.line
37 _print.opt.overflow
38 _print.opt.sel_line
39 _print.opt.set
40
41]]
42
43if not rb.lcd_framebuffer then rb.splash(rb.HZ, "No Support!") return nil end
44
45local _print = {} do
46
47 -- internal constants
48 local _clr = require("color") -- _clr functions required
49
50 local _NIL = nil -- _NIL placeholder
51 local _LCD = rb.lcd_framebuffer()
52 local LCD_W, LCD_H = rb.LCD_WIDTH, rb.LCD_HEIGHT
53 local WHITE = _clr.set(-1, 255, 255, 255)
54 local BLACK = _clr.set(0, 0, 0, 0)
55 local DRMODE_SOLID = 3
56 local col_buf, s_lines = {}, {}
57 local _p_opts = _NIL
58
59-- print internal helper functions
60--------------------------------------------------------------------------------
61 -- clamps value to >= min and <= max
62 local function clamp(val, min, max)
63 -- Warning doesn't check if min < max
64 if val < min then
65 return min
66 elseif val < max then
67 return val
68 end
69 return max
70 end
71
72 -- updates screen in specified rectangle
73 local function update_rect(x, y, w, h)
74 rb.lcd_update_rect(x - 1, y - 1,
75 clamp(x + w, 1, LCD_W) - 1,
76 clamp(y + h, 1, LCD_H) - 1)
77 end
78
79 -- Gets size of text
80 local function text_extent(msg, font)
81 font = font or rb.FONT_UI
82 -- res, w, h
83 return rb.font_getstringsize(msg, font)
84 end
85
86 -- Sets viewport size
87 local function set_viewport(vp)
88 if not vp then rb.set_viewport() return end
89
90 if rb.LCD_DEPTH == 2 then -- invert 2-bit screens
91 --vp.drawmode = bit.bxor(vp.drawmode, 4)
92 vp.fg_pattern = 3 - vp.fg_pattern
93 vp.bg_pattern = 3 - vp.bg_pattern
94 end
95 rb.set_viewport(vp)
96 end
97
98 -- shallow copy of table
99 function table_clone(t)
100 local copy = {}
101 for k, v in pairs(t) do
102 copy[k] = v
103 end
104 return copy
105 end
106
107 -- Updates a single line on the screen
108 local function update_line(enabled, opts, line, h)
109 if enabled ~= true then return end
110 local o = opts or _p_opts
111 update_rect(o.x, o.y + line * h + 1, o.width, h)
112 end
113
114 -- Clears a single line on the screen
115 local function clear_line(opts, line, h)
116 local o = opts or _p_opts
117 _LCD:clear(o.bg_pattern, o.x, o.y + line * h + 1,
118 o.x + o.width, line * h + h + o.y)
119 end
120
121 -- Sets the maximum number of lines on the screen
122 local function max_lines(opts)
123 local h = opts.height
124 local _, _, th = text_extent("W", opts.font)
125 return h / th
126 end
127
128 --saves the items displayed for side to side scroll
129 local function col_buf_insert(msg, line, _p_opts)
130 --if _p_opts.line <= 1 then col_buf = {} end
131 if not col_buf[line] then
132 table.insert(col_buf, line, msg) end
133 end
134
135 --replaces / strips escape characters
136 local function check_escapes(o, msg)
137 local tabsz = 2
138 local tabstr = string.rep(" ", tabsz)
139
140 local function repl(esc)
141 local ret = ""
142 if esc:sub(1,1) == "\t" then ret = string.rep(tabstr, esc:len()) end
143 return ret
144 end
145
146 msg = msg:gsub("(%c+)", repl)
147
148 local res, w, h = text_extent(msg, o.font)
149 return w, h, msg
150 end
151--------------------------------------------------------------------------------
152
153 -- set defaults for print view
154 local function set_defaults()
155 _p_opts = { x = 1,
156 y = 1,
157 width = LCD_W - 1,
158 height = LCD_H - 1,
159 font = rb.FONT_UI,
160 drawmode = DRMODE_SOLID,
161 fg_pattern = WHITE,
162 bg_pattern = BLACK,
163 sel_pattern = WHITE,
164 line = 1,
165 max_line = _NIL,
166 col = 0,
167 ovfl = "auto",
168 justify = "left",
169 autoupdate = true,
170 }
171 _p_opts.max_line = max_lines(_p_opts)
172
173 s_lines, col_buf = {}, {}
174 return _p_opts
175 end
176
177 -- returns table with settings for print
178 -- if bByRef is _NIL or false then a copy is returned
179 local function get_settings(bByRef)
180 _p_opts = _p_opts or set_defaults()
181 if not bByRef then return table_clone(_p_opts) end
182 return _p_opts
183 end
184
185 -- sets the settings for print with your passed table
186 local function set_settings(t_opts)
187 _p_opts = t_opts or set_defaults()
188 if t_opts then
189 _p_opts.max_line = max_lines(_p_opts)
190 col_buf = {}
191 end
192 end
193
194 -- sets colors for print
195 local function set_color(fgclr, bgclr, selclr)
196 local o = get_settings(true)
197
198 if fgclr ~= _NIL then
199 o.fg_pattern, o.sel_pattern = fgclr, fgclr
200 end
201 o.sel_pattern = selclr or o.sel_pattern
202 o.bg_pattern = bgclr or o.bg_pattern
203 end
204
205 -- helper function sets up colors/marker for selected items
206 local function show_selected(iLine, msg)
207 local o = get_settings() -- using a copy of opts so changes revert
208
209 if s_lines[iLine] == true then
210 if not rb.lcd_set_background then
211 o.drawmode = bit.bxor(o.drawmode, 4)
212 else
213 o.fg_pattern = o.bg_pattern
214 o.bg_pattern = o.sel_pattern
215 end
216 -- alternative selection method
217 --msg = "> " .. msg
218 end
219 set_viewport(o)
220 o = _NIL
221 end
222
223 -- sets line explicitly or increments line if line is _NIL
224 local function set_line(iLine)
225 local o = get_settings(true)
226
227 o.line = iLine or o.line + 1
228
229 if(o.line < 1 or o.line > o.max_line) then
230 o.line = 1
231 end
232 end
233
234 -- clears the set print area
235 local function clear()
236 local o = get_settings(true)
237 _LCD:clear(o.bg_pattern, o.x, o.y, o.x + o.width, o.y + o.height)
238 if o.autoupdate == true then rb.lcd_update() end
239 set_line(1)
240 for i=1, #col_buf do col_buf[i] = _NIL end
241 s_lines = {}
242 collectgarbage("collect")
243 end
244
245 -- screen update after each call to print.f
246 local function set_update(bAutoUpdate)
247 local o = get_settings(true)
248 o.autoupdate = bAutoUpdate or false
249 end
250
251 -- sets print area
252 local function set_area(x, y, w, h)
253 local o = get_settings(true)
254 o.x, o.y = clamp(x, 1, LCD_W), clamp(y, 1, LCD_H)
255 o.width, o.height = clamp(w, 1, LCD_W - o.x), clamp(h, 1, LCD_H - o.y)
256 o.max_line = max_lines(_p_opts)
257
258 clear()
259 return o.line, o.max_line
260 end
261
262 -- when string is longer than print width scroll -- "auto", "manual", "none"
263 local function set_overflow(str_mode)
264 -- "auto", "manual", "none"
265 local str_mode = str_mode or "auto"
266 local o = get_settings(true)
267 o.ovfl = str_mode:lower()
268 col_buf = {}
269 end
270
271 -- aligns text to: "left", "center", "right"
272 local function set_justify(str_mode)
273 -- "left", "center", "right"
274 local str_mode = str_mode or "left"
275 local o = get_settings(true)
276 o.justify = str_mode:lower()
277 end
278
279 -- selects line
280 local function select_line(iLine)
281 s_lines[iLine] = true
282 end
283
284 -- Internal print function
285 local function print_internal(t_opts, x, w, h, msg)
286
287 local o = t_opts
288 if o.justify == "center" then
289 x = x + (o.width - w) / 2
290 elseif o.justify == "right" then
291 x = x + (o.width - w)
292 end
293
294 local line = o.line - 1 -- rb is 0-based lua is 1-based
295 if(o.ovfl == "auto" and w >= o.width) then -- -o.x
296 rb.lcd_puts_scroll(0, line, msg)
297 else
298 rb.lcd_putsxy(x, line * h, msg)
299 if o.ovfl == "manual" then --save msg for later side scroll
300 col_buf_insert(msg, o.line, o)
301 end
302 end
303
304 --only update the line we changed
305 update_line(o.autoupdate, o, line, h)
306
307 set_line(_NIL) -- increments line counter
308 end
309
310 -- Helper function that acts mostly like a normal printf() would
311 local function printf(...)
312 local o = get_settings(true)
313 local w, h, msg
314 local line = o.line - 1 -- rb is 0-based lua is 1-based
315 if not (...) or (...) == "\n" then -- handles blank line / single '\n'
316 local res, w, h = text_extent(" ", o.font)
317
318 clear_line(o, line, h)
319 update_line(o.autoupdate, o, line, h)
320
321 if (...) then set_line(_NIL) end
322
323 return o.line, o.max_line, o.width, h
324 end
325
326 msg = string.format(...)
327
328 show_selected(o.line, msg)
329
330 w, h, msg = check_escapes(o, msg)
331
332 print_internal(o, o.col, w, h, msg)
333
334 return o.line, o.max_line, w, h
335 end
336
337 -- x > 0 scrolls right x < 0 scrolls left
338 local function set_column(x)
339 local o = get_settings()
340 if o.ovfl ~= "manual" then return end -- no buffer stored to scroll
341 local res, w, h, str, line
342
343 for key, value in pairs(col_buf) do
344 line = key - 1 -- rb is 0-based lua is 1-based
345 o.line = key
346
347 if value then
348 show_selected(key, value)
349 res, w, h = text_extent(value, o.font)
350 clear_line(o, line, h)
351
352 print_internal(o, x + o.col, w, h, value)
353 update_line(o.autoupdate, o, line, h)
354 end
355 end
356 o = _NIL
357 end
358
359 --expose functions to the outside through _print table
360 _print.opt = {}
361 _print.opt.column = set_column
362 _print.opt.color = set_color
363 _print.opt.area = set_area
364 _print.opt.set = set_settings
365 _print.opt.get = get_settings
366 _print.opt.defaults = set_defaults
367 _print.opt.overflow = set_overflow
368 _print.opt.justify = set_justify
369 _print.opt.sel_line = select_line
370 _print.opt.line = set_line
371 _print.opt.autoupdate = set_update
372 _print.clear = clear
373 _print.f = printf
374
375end --_print functions
376
377return _print
378