summaryrefslogtreecommitdiff
path: root/apps/plugins/lua/include_lua/draw.lua
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/lua/include_lua/draw.lua')
-rw-r--r--apps/plugins/lua/include_lua/draw.lua216
1 files changed, 9 insertions, 207 deletions
diff --git a/apps/plugins/lua/include_lua/draw.lua b/apps/plugins/lua/include_lua/draw.lua
index 0ee3e93d75..7208b63efb 100644
--- a/apps/plugins/lua/include_lua/draw.lua
+++ b/apps/plugins/lua/include_lua/draw.lua
@@ -29,7 +29,6 @@
29 _draw.ellipse_filled 29 _draw.ellipse_filled
30 _draw.ellipse_rect_filled 30 _draw.ellipse_rect_filled
31 _draw.ellipse_rect 31 _draw.ellipse_rect
32 _draw.flood_fill
33 _draw.hline 32 _draw.hline
34 _draw.image 33 _draw.image
35 _draw.line 34 _draw.line
@@ -39,7 +38,6 @@
39 _draw.rect_filled 38 _draw.rect_filled
40 _draw.rounded_rect 39 _draw.rounded_rect
41 _draw.rounded_rect_filled 40 _draw.rounded_rect_filled
42 _draw.text
43 _draw.vline 41 _draw.vline
44 42
45]] 43]]
@@ -56,21 +54,17 @@ local _draw = {} do
56 setmetatable(_draw, rocklib_image) 54 setmetatable(_draw, rocklib_image)
57 55
58 -- Internal Constants 56 -- Internal Constants
59 local _LCD = rb.lcd_framebuffer()
60 local LCD_W, LCD_H = rb.LCD_WIDTH, rb.LCD_HEIGHT
61 local BSAND = 8 -- blits color to dst if src <> 0 57 local BSAND = 8 -- blits color to dst if src <> 0
62 local _NIL = nil -- nil placeholder 58 local _NIL = nil -- nil placeholder
63 59
64 local _abs = math.abs 60
65 local _clear = rocklib_image.clear 61 local _clear = rocklib_image.clear
66 local _copy = rocklib_image.copy 62 local _copy = rocklib_image.copy
67 local _ellipse = rocklib_image.ellipse 63 local _ellipse = rocklib_image.ellipse
68 local _get = rocklib_image.get 64 local _get = rocklib_image.get
69 local _line = rocklib_image.line 65 local _line = rocklib_image.line
70 local _marshal = rocklib_image.marshal
71 local _min = math.min 66 local _min = math.min
72 local _newimg = rb.new_image 67 local _newimg = rb.new_image
73 local _points = rocklib_image.points
74 68
75 -- line 69 -- line
76 _draw.line = function(img, x1, y1, x2, y2, color, bClip) 70 _draw.line = function(img, x1, y1, x2, y2, color, bClip)
@@ -87,33 +81,22 @@ local _draw = {} do
87 _line(img, x, y, _NIL, y + length, color, bClip) 81 _line(img, x, y, _NIL, y + length, color, bClip)
88 end 82 end
89 83
90 -- draws a non-filled figure based on points in t-points 84 -- draws a non-filled rect based on points in t-points
91 local function polyline(img, x, y, t_points, color, bClosed, bClip) 85 local function polyrect(img, x, y, t_points, color, bClip)
92 if #t_points < 2 then error("not enough points", 3) end 86 local pt_first_last = t_points[1]
93 87 local pt1, pt2
94 local pt_first_last 88 for i = 1, 4, 1 do
95 89 pt1 = t_points[i]
96 if bClosed then 90 pt2 = t_points[i + 1] or pt_first_last-- first and last point
97 pt_first_last = t_points[1]
98 else
99 pt_first_last = t_points[#t_points]
100 end
101
102 for i = 1, #t_points, 1 do
103 local pt1 = t_points[i]
104
105 local pt2 = t_points[i + 1] or pt_first_last-- first and last point
106
107 _line(img, pt1[1] + x, pt1[2] + y, pt2[1] + x, pt2[2] + y, color, bClip) 91 _line(img, pt1[1] + x, pt1[2] + y, pt2[1] + x, pt2[2] + y, color, bClip)
108 end 92 end
109
110 end 93 end
111 94
112 -- rectangle 95 -- rectangle
113 local function rect(img, x, y, width, height, color, bClip) 96 local function rect(img, x, y, width, height, color, bClip)
114 if width == 0 or height == 0 then return end 97 if width == 0 or height == 0 then return end
115 98
116 polyline(img, x, y, {{0, 0}, {width, 0}, {width, height}, {0, height}}, color, true, bClip) 99 polyrect(img, x, y, {{0, 0}, {width, 0}, {width, height}, {0, height}}, color, bClip)
117 100
118 end 101 end
119 102
@@ -240,190 +223,9 @@ local _draw = {} do
240 _copy(dst, src, x, y, 1, 1, _NIL, _NIL, bClip) 223 _copy(dst, src, x, y, 1, 1, _NIL, _NIL, bClip)
241 end 224 end
242 225
243 -- floods an area of targetclr with fillclr x, y specifies the start seed
244 _draw.flood_fill = function(img, x, y, targetclr, fillclr)
245 -- scanline 4-way flood algorithm
246 -- ^
247 -- <--------x--->
248 -- v
249 -- check that target color doesn't = fill and the first point is target color
250 if targetclr == fillclr or targetclr ~= _get(img, x, y, true) then return end
251 local max_w = img:width()
252 local max_h = img:height()
253
254 local qpt = {} -- FIFO queue
255 -- rather than moving elements around in our FIFO queue
256 -- for each read; increment 'qhead' by 2
257 -- set both elements to nil and let the
258 -- garbage collector worry about it
259 -- for each write; increment 'qtail' by 2
260 -- x coordinates are in odd indices while
261 -- y coordinates are in even indices
262
263 local qtail = 0
264
265 local function check_ns(val, x, y)
266 if targetclr == val then
267 y = y - 1
268 if targetclr == _get(img, x, y, true) then -- north
269 qtail = qtail + 2
270 qpt[qtail - 1] = x
271 qpt[qtail] = y
272 end
273 y = y + 2
274 if targetclr == _get(img, x, y, true) then -- south
275 qtail = qtail + 2
276 qpt[qtail - 1] = x
277 qpt[qtail] = y
278 end
279 return fillclr
280 end
281 return _NIL -- signal marshal to stop
282 end
283
284 local function seed_pt(x, y)
285 -- should never hit max but make sure not to end early
286 for qhead = 2, 0x40000000, 2 do
287
288 if targetclr == _get(img, x, y, true) then
289 _marshal(img, x, y, 1, y, _NIL, _NIL, true, check_ns) -- west
290 _marshal(img, x + 1, y, max_w, y, _NIL, _NIL, true, check_ns) -- east
291 end
292
293 x = qpt[qhead - 1]
294 qpt[qhead - 1] = _NIL
295
296 if not x then break end
297
298 y = qpt[qhead]
299 qpt[qhead] = _NIL
300 end
301 end
302
303 seed_pt(x, y) -- Begin
304 end -- flood_fill
305
306 -- draws a closed figure based on points in t_points
307 _draw.polygon = function(img, x, y, t_points, color, fillcolor, bClip)
308 if #t_points < 2 then error("not enough points", 3) end
309
310 if fillcolor then
311 local x_min, x_max = 0, 0
312 local y_min, y_max = 0, 0
313 local w, h = 0, 0
314 -- find boundries of polygon
315 for i = 1, #t_points, 1 do
316 local pt = t_points[i]
317 if pt[1] < x_min then x_min = pt[1] end
318 if pt[1] > x_max then x_max = pt[1] end
319 if pt[2] < y_min then y_min = pt[2] end
320 if pt[2] > y_max then y_max = pt[2] end
321 end
322 w = _abs(x_max) + _abs(x_min)
323 h = _abs(y_max) + _abs(y_min)
324 x_min = x_min - 2 -- leave a border to use flood_fill
325 y_min = y_min - 2
326
327 local fill_img = _newimg(w + 3, h + 3)
328 _clear(fill_img, 0x1)
329
330 for i = 1, #t_points, 1 do
331 local pt1 = t_points[i]
332 local pt2 = t_points[i + 1] or t_points[1]-- first and last point
333 _line(fill_img, pt1[1] - x_min, pt1[2] - y_min,
334 pt2[1]- x_min, pt2[2] - y_min, 0)
335
336 end
337 _draw.flood_fill(fill_img, fill_img:width(), fill_img:height() , 0x1, 0x0)
338 _copy(img, fill_img, x - 1, y - 1, _NIL, _NIL, _NIL, _NIL, bClip, BSAND, fillcolor)
339 end
340
341 polyline(img, x, y, t_points, color, true, bClip)
342 end
343
344 -- draw text onto image if width/height are supplied text is centered
345 _draw.text = function(img, x, y, width, height, font, color, text)
346 font = font or rb.FONT_UI
347
348 local opts = {x = 0, y = 0, width = LCD_W - 1, height = LCD_H - 1,
349 font = font, drawmode = 3, fg_pattern = 0x1, bg_pattern = 0}
350
351 if rb.LCD_DEPTH == 2 then -- invert 2-bit screens
352 --vp.drawmode = bit.bxor(vp.drawmode, 4)
353 opts.fg_pattern = 3 - opts.fg_pattern
354 opts.bg_pattern = 3 - opts.bg_pattern
355 end
356 rb.set_viewport(opts)
357
358 local res, w, h = rb.font_getstringsize(text, font)
359
360 if not width then
361 width = 0
362 else
363 width = (width - w) / 2
364 end
365
366 if not height then
367 height = 0
368 else
369 height = (height - h) / 2
370 end
371
372 -- make a copy of the current screen for later
373 local screen_img = _newimg(LCD_W, LCD_H)
374 _copy(screen_img, _LCD)
375
376 -- check if the screen buffer is supplied image if so set img to the copy
377 if img == _LCD then
378 img = screen_img
379 end
380
381 -- we will be printing the text to the screen then blitting into img
382 rb.lcd_clear_display()
383
384 if w > LCD_W then -- text is too long for the screen do it in chunks
385 local l = 1
386 local resp, wp, hp
387 local lenr = text:len()
388
389 while lenr > 1 do
390 l = lenr
391 resp, wp, hp = rb.font_getstringsize(text:sub(1, l), font)
392
393 while wp >= LCD_W and l > 1 do
394 l = l - 1
395 resp, wp, hp = rb.font_getstringsize(text:sub( 1, l), font)
396 end
397
398 rb.lcd_putsxy(0, 0, text:sub(1, l))
399 text = text:sub(l)
400
401 if x + width > img:width() or y + height > img:height() then
402 break
403 end
404
405 -- using the mask we made blit color into img
406 _copy(img, _LCD, x + width, y + height, _NIL, _NIL, _NIL, _NIL, false, BSAND, color)
407 x = x + wp
408 rb.lcd_clear_display()
409 lenr = text:len()
410 end
411 else --w <= LCD_W
412 rb.lcd_putsxy(0, 0, text)
413
414 -- using the mask we made blit color into img
415 _copy(img, _LCD, x + width, y + height, _NIL, _NIL, _NIL, _NIL, false, BSAND, color)
416 end
417
418 _copy(_LCD, screen_img) -- restore screen
419 rb.set_viewport() -- set viewport default
420 return res, w, h
421 end
422
423 -- expose internal functions to the outside through _draw table 226 -- expose internal functions to the outside through _draw table
424 _draw.hline = hline 227 _draw.hline = hline
425 _draw.vline = vline 228 _draw.vline = vline
426 _draw.polyline = polyline
427 _draw.rect = rect 229 _draw.rect = rect
428 _draw.rounded_rect = rounded_rect 230 _draw.rounded_rect = rounded_rect
429end -- _draw functions 231end -- _draw functions