···36363737local _blit ={} do
38383939- _blit.CUSTOM = 0xFF --user defined blit function func(dst_val, x, y, src_val, x, y)
3939+ _blit.CUSTOM = nil --user defined blit function func(dst_val, x, y, src_val, x, y)
4040 _blit.BCOPY = 0x0 --copy (use :copy() instead it is slightly faster
4141 _blit.BOR = 0x1 --OR source and dest pixels
4242 _blit.BXOR = 0x2 --XOR source and dest pixels
+10-21
apps/plugins/lua/include_lua/color.lua
···4949 maxstate = (bit.lshift(1, 24) - 1)
5050 end
51515252- local function init(v)
5353- return v or 0
5454- end
5555-5652 -- clamps value to >= min and <= max rolls over to opposite
5753 local function clamp_roll(val, min, max)
5858- if min > max then
5959- local swap = min
6060- min, max = max, swap
6161- end
6262-5454+ -- Warning doesn't check if min < max
6355 if val < min then
6456 val = max
6557 elseif val > max then
···7264 -- sets color -- monochrome / greyscale use 'set' -- color targets 'r,b,g'
7365 -- on monochrome/ greyscale targets:
7466 -- '-1' sets the highest 'color' state & 0 is the minimum 'color' state
7575- local function clrset(set, r, g, b)
6767+ _clr.set = function(set, r, g, b)
7668 local color = set or 0
77697870 if IS_COLOR_TARGET then
7979- if (r ~= _NIL or g ~= _NIL or b ~= _NIL) then
8080- r, g, b = init(r), init(g), init(b)
7171+ if (r or g or b) then
7272+ r, g, b = (r or 0), (g or 0), (b or 0)
8173 color = rb.lcd_rgbpack(r, g, b)
8274 end
8375 end
···8678 end -- clrset
87798880 -- de/increments current color by 'inc' -- optionally color targets by 'r,g,b'
8989- local function clrinc(current, inc, r, g, b)
8181+ _clr.inc = function(current, inc, r, g, b)
9082 local color = 0
9183 current = current or color
9284 inc = inc or 1
93859486 if IS_COLOR_TARGET then
9587 local ru, gu, bu = rb.lcd_rgbunpack(current);
9696- if (r ~= _NIL or g ~= _NIL or b ~= _NIL) then
9797- r, g, b = init(r), init(g), init(b)
8888+ if (r or g or b) then
8989+ r, g, b = (r or 0), (g or 0), (b or 0)
9890 ru = ru + r; gu = gu + g; bu = bu + b
9999- color = rb.lcd_rgbpack(ru, gu, bu)
10091 else
101101- ru = ru + inc; gu = gu + inc; bu = bu + inc
102102- color = rb.lcd_rgbpack(ru, gu, bu)
9292+ ru = ru + inc; gu = gu + inc; bu = bu + inc
10393 end
9494+9595+ color = rb.lcd_rgbpack(ru, gu, bu)
10496 else
10597 color = current + inc
10698 end
···108100 return clamp_roll(color, 0, maxstate)
109101 end -- clrinc
110102111111- -- expose functions to the outside through _clr table
112112- _clr.set = clrset
113113- _clr.inc = clrinc
114103end -- color functions
115104116105return _clr
+96-133
apps/plugins/lua/include_lua/draw.lua
···52525353local _draw = {} do
54545555+ local rocklib_image = getmetatable(rb.lcd_framebuffer())
5656+ setmetatable(_draw, rocklib_image)
5757+5558 -- Internal Constants
5659 local _LCD = rb.lcd_framebuffer()
5760 local LCD_W, LCD_H = rb.LCD_WIDTH, rb.LCD_HEIGHT
5861 local BSAND = 8 -- blits color to dst if src <> 0
5962 local _NIL = nil -- nil placeholder
60636161- local function set_viewport(vp)
6262- if not vp then rb.set_viewport() return end
6363- if rb.LCD_DEPTH == 2 then -- invert 2-bit screens
6464- --vp.drawmode = bit.bxor(vp.drawmode, 4)
6565- vp.fg_pattern = 3 - vp.fg_pattern
6666- vp.bg_pattern = 3 - vp.bg_pattern
6767- end
6868- rb.set_viewport(vp)
6969- end
6464+ local _abs = math.abs
6565+ local _clear = rocklib_image.clear
6666+ local _copy = rocklib_image.copy
6767+ local _ellipse = rocklib_image.ellipse
6868+ local _get = rocklib_image.get
6969+ local _line = rocklib_image.line
7070+ local _marshal = rocklib_image.marshal
7171+ local _min = math.min
7272+ local _newimg = rb.new_image
7373+ local _points = rocklib_image.points
70747175 -- line
7272- local function line(img, x1, y1, x2, y2, color, bClip)
7373- img:line(x1, y1, x2, y2, color, bClip)
7676+ _draw.line = function(img, x1, y1, x2, y2, color, bClip)
7777+ _line(img, x1, y1, x2, y2, color, bClip)
7478 end
75797680 -- horizontal line; x, y define start point; length in horizontal direction
7781 local function hline(img, x, y , length, color, bClip)
7878- img:line(x, y, x + length, _NIL, color, bClip)
8282+ _line(img, x, y, x + length, _NIL, color, bClip)
7983 end
80848185 -- vertical line; x, y define start point; length in vertical direction
8286 local function vline(img, x, y , length, color, bClip)
8383- img:line(x, y, _NIL, y + length, color, bClip)
8787+ _line(img, x, y, _NIL, y + length, color, bClip)
8488 end
85898690 -- draws a non-filled figure based on points in t-points
···100104101105 local pt2 = t_points[i + 1] or pt_first_last-- first and last point
102106103103- img:line(pt1[1] + x, pt1[2] + y, pt2[1]+x, pt2[2]+y, color, bClip)
107107+ _line(img, pt1[1] + x, pt1[2] + y, pt2[1] + x, pt2[2] + y, color, bClip)
104108 end
105109106110 end
···109113 local function rect(img, x, y, width, height, color, bClip)
110114 if width == 0 or height == 0 then return end
111115112112- local ppt = {{0, 0}, {width, 0}, {width, height}, {0, height}}
113113- polyline(img, x, y, ppt, color, true, bClip)
114114- --[[
115115- vline(img, x, y, height, color, bClip);
116116- vline(img, x + width, y, height, color, bClip);
117117- hline(img, x, y, width, color, bClip);
118118- hline(img, x, y + height, width, color, bClip);]]
116116+ polyline(img, x, y, {{0, 0}, {width, 0}, {width, height}, {0, height}}, color, true, bClip)
117117+119118 end
120119121120 -- filled rect, fillcolor is color if left empty
122122- local function rect_filled(img, x, y, width, height, color, fillcolor, bClip)
121121+ _draw.rect_filled = function(img, x, y, width, height, color, fillcolor, bClip)
123122 if width == 0 or height == 0 then return end
124123125124 if not fillcolor then
126126- img:clear(color, x, y, x + width, y + height, bClip)
125125+ _clear(img, color, x, y, x + width, y + height, bClip)
127126 else
128128- img:clear(fillcolor, x, y, x + width, y + height, bClip)
127127+ _clear(img, fillcolor, x, y, x + width, y + height, bClip)
129128 rect(img, x, y, width, height, color, bClip)
130129 end
131130 end
132131133132 -- circle cx,cy define center point
134134- local function circle(img, cx, cy, radius, color, bClip)
133133+ _draw.circle = function(img, cx, cy, radius, color, bClip)
135134 local r = radius
136136- img:ellipse(cx - r, cy - r, cx + r, cy + r, color, _NIL, bClip)
135135+ _ellipse(img, cx - r, cy - r, cx + r, cy + r, color, _NIL, bClip)
137136 end
138137139138 -- filled circle cx,cy define center, fillcolor is color if left empty
140140- local function circle_filled(img, cx, cy, radius, color, fillcolor, bClip)
139139+ _draw.circle_filled = function(img, cx, cy, radius, color, fillcolor, bClip)
141140 fillcolor = fillcolor or color
142141 local r = radius
143143- img:ellipse(cx - r, cy - r, cx + r, cy + r, color, fillcolor, bClip)
142142+ _ellipse(img, cx - r, cy - r, cx + r, cy + r, color, fillcolor, bClip)
144143 end
145144146145 -- ellipse that fits into defined rect
147147- local function ellipse_rect(img, x1, y1, x2, y2, color, bClip)
148148- img:ellipse(x1, y1, x2, y2, color, _NIL, bClip)
146146+ _draw.ellipse_rect = function(img, x1, y1, x2, y2, color, bClip)
147147+ _ellipse(img, x1, y1, x2, y2, color, _NIL, bClip)
149148 end
150149151150 --ellipse that fits into defined rect, fillcolor is color if left empty
152152- local function ellipse_rect_filled(img, x1, y1, x2, y2, color, fillcolor, bClip)
151151+ _draw.ellipse_rect_filled = function(img, x1, y1, x2, y2, color, fillcolor, bClip)
153152 if not fillcolor then fillcolor = color end
154153155155- img:ellipse(x1, y1, x2, y2, color, fillcolor, bClip)
154154+ _ellipse(img, x1, y1, x2, y2, color, fillcolor, bClip)
156155 end
157156158157 -- ellipse cx, cy define center point; a, b the major/minor axis
159159- local function ellipse(img, cx, cy, a, b, color, bClip)
160160- img:ellipse(cx - a, cy - b, cx + a, cy + b, color, _NIL, bClip)
158158+ _draw.ellipse = function(img, cx, cy, a, b, color, bClip)
159159+ _ellipse(img, cx - a, cy - b, cx + a, cy + b, color, _NIL, bClip)
161160 end
162161163162 -- filled ellipse cx, cy define center point; a, b the major/minor axis
164163 -- fillcolor is color if left empty
165165- local function ellipse_filled(img, cx, cy, a, b, color, fillcolor, bClip)
164164+ _draw.ellipse_filled = function(img, cx, cy, a, b, color, fillcolor, bClip)
166165 if not fillcolor then fillcolor = color end
167166168168- img:ellipse(cx - a, cy - b, cx + a, cy + b, color, fillcolor, bClip)
167167+ _ellipse(img, cx - a, cy - b, cx + a, cy + b, color, fillcolor, bClip)
169168 end
170169171170 -- rounded rectangle
172171 local function rounded_rect(img, x, y, w, h, radius, color, bClip)
173172 local c_img
174174-175175- local function blit(dx, dy, sx, sy, ox, oy)
176176- img:copy(c_img, dx, dy, sx, sy, ox, oy, bClip, BSAND, color)
177177- end
178178-179173 if w == 0 or h == 0 then return end
180174181175 -- limit the radius of the circle otherwise it will overtake the rect
182182- radius = math.min(w / 2, radius)
183183- radius = math.min(h / 2, radius)
176176+ radius = _min(w / 2, radius)
177177+ radius = _min(h / 2, radius)
184178185179 local r = radius
186180187187- c_img = rb.new_image(r * 2 + 1, r * 2 + 1)
188188- c_img:clear(0)
189189- circle(c_img, r + 1, r + 1, r, 0xFFFFFF)
181181+ c_img = _newimg(r * 2 + 1, r * 2 + 1)
182182+ _clear(c_img, 0)
183183+ _ellipse(c_img, 1, 1, 1 + r + r, 1 + r + r, 0x1, _NIL, bClip)
190184191185 -- copy 4 pieces of circle to their respective corners
192192- blit(x, y, _NIL, _NIL, r + 1, r + 1) --TL
193193- blit(x + w - r - 2, y, r, _NIL, r + 1, r + 1) --TR
194194- blit(x , y + h - r - 2, _NIL, r, r + 1, _NIL) --BL
195195- blit(x + w - r - 2, y + h - r - 2, r, r, r + 1, r + 1)--BR
186186+ _copy(img, c_img, x, y, _NIL, _NIL, r + 1, r + 1, bClip, BSAND, color) --TL
187187+ _copy(img, c_img, x + w - r - 2, y, r, _NIL, r + 1, r + 1, bClip, BSAND, color) --TR
188188+ _copy(img, c_img, x , y + h - r - 2, _NIL, r, r + 1, _NIL, bClip, BSAND, color) --BL
189189+ _copy(img, c_img, x + w - r - 2, y + h - r - 2, r, r, r + 1, r + 1, bClip, BSAND, color)--BR
196190 c_img = _NIL
197191198192 vline(img, x, y + r, h - r * 2, color, bClip);
···202196 end
203197204198 -- rounded rectangle fillcolor is color if left empty
205205- local function rounded_rect_filled(img, x, y, w, h, radius, color, fillcolor, bClip)
199199+ _draw.rounded_rect_filled = function(img, x, y, w, h, radius, color, fillcolor, bClip)
206200 local c_img
207201208208- local function blit(dx, dy, sx, sy, ox, oy)
209209- img:copy(c_img, dx, dy, sx, sy, ox, oy, bClip, BSAND, fillcolor)
210210- end
211211-212202 if w == 0 or h == 0 then return end
213203214204 if not fillcolor then fillcolor = color end
215205216206 -- limit the radius of the circle otherwise it will overtake the rect
217217- radius = math.min(w / 2, radius)
218218- radius = math.min(h / 2, radius)
207207+ radius = _min(w / 2, radius)
208208+ radius = _min(h / 2, radius)
219209220210 local r = radius
221211222222- c_img = rb.new_image(r * 2 + 1, r * 2 + 1)
223223- c_img:clear(0)
224224- circle_filled(c_img, r + 1, r + 1, r, fillcolor)
212212+ c_img = _newimg(r * 2 + 1, r * 2 + 1)
213213+ _clear(c_img, 0)
214214+ _ellipse(c_img, 1, 1, 1 + r + r, 1 + r + r, 0x1, 0x1, bClip)
225215226216 -- copy 4 pieces of circle to their respective corners
227227- blit(x, y, _NIL, _NIL, r + 1, r + 1) --TL
228228- blit(x + w - r - 2, y, r, _NIL, r + 1, r + 1) --TR
229229- blit(x, y + h - r - 2, _NIL, r, r + 1, _NIL) --BL
230230- blit(x + w - r - 2, y + h - r - 2, r, r, r + 1, r + 1) --BR
217217+ _copy(img, c_img, x, y, _NIL, _NIL, r + 1, r + 1, bClip, BSAND, fillcolor) --TL
218218+ _copy(img, c_img, x + w - r - 2, y, r, _NIL, r + 1, r + 1, bClip, BSAND, fillcolor) --TR
219219+ _copy(img, c_img, x, y + h - r - 2, _NIL, r, r + 1, _NIL, bClip, BSAND, fillcolor) --BL
220220+ _copy(img, c_img, x + w - r - 2, y + h - r - 2, r, r, r + 1, r + 1, bClip, BSAND, fillcolor) --BR
231221 c_img = _NIL
232222233223 -- finish filling areas circles didn't cover
234234- img:clear(fillcolor, x + r, y, x + w - r, y + h - 1, bClip)
235235- img:clear(fillcolor, x, y + r, x + r, y + h - r, bClip)
236236- img:clear(fillcolor, x + w - r, y + r, x + w - 1, y + h - r - 1, bClip)
224224+ _clear(img, fillcolor, x + r, y, x + w - r, y + h - 1, bClip)
225225+ _clear(img, fillcolor, x, y + r, x + r, y + h - r, bClip)
226226+ _clear(img, fillcolor, x + w - r, y + r, x + w - 1, y + h - r - 1, bClip)
237227238228 if fillcolor ~= color then
239229 rounded_rect(img, x, y, w, h, r, color, bClip)
···241231 end
242232243233 -- draws an image at xy coord in dest image
244244- local function image(dst, src, x, y, bClip)
234234+ _draw.image = function(dst, src, x, y, bClip)
245235 if not src then --make sure an image was passed, otherwise bail
246236 rb.splash(rb.HZ, "No Image!")
247237 return _NIL
248238 end
249239250250- dst:copy(src, x, y, 1, 1, _NIL, _NIL, bClip)
240240+ _copy(dst, src, x, y, 1, 1, _NIL, _NIL, bClip)
251241 end
252242253243 -- floods an area of targetclr with fillclr x, y specifies the start seed
254254- function flood_fill(img, x, y, targetclr, fillclr)
244244+ _draw.flood_fill = function(img, x, y, targetclr, fillclr)
255245 -- scanline 4-way flood algorithm
256246 -- ^
257247 -- <--------x--->
258248 -- v
259249 -- check that target color doesn't = fill and the first point is target color
260260- if targetclr == fillclr or targetclr ~= img:get(x,y, true) then return end
250250+ if targetclr == fillclr or targetclr ~= _get(img, x, y, true) then return end
261251 local max_w = img:width()
262252 local max_h = img:height()
263253···271261 -- y coordinates are in even indices
272262273263 local qtail = 0
274274- local iter_n; -- North iteration
275275- local iter_s; -- South iteration
276264277265 local function check_ns(val, x, y)
278266 if targetclr == val then
279279- if targetclr == iter_n() then
267267+ y = y - 1
268268+ if targetclr == _get(img, x, y, true) then -- north
280269 qtail = qtail + 2
281270 qpt[qtail - 1] = x
282282- qpt[qtail] = (y - 1)
271271+ qpt[qtail] = y
283272 end
284284-285285- if targetclr == iter_s() then
273273+ y = y + 2
274274+ if targetclr == _get(img, x, y, true) then -- south
286275 qtail = qtail + 2
287276 qpt[qtail - 1] = x
288288- qpt[qtail] = (y + 1)
277277+ qpt[qtail] = y
289278 end
290279 return fillclr
291280 end
···293282 end
294283295284 local function seed_pt(x, y)
296296- -- will never hit max_w * max_h^2 but make sure not to end early
297297- for qhead = 2, max_w * max_h * max_w * max_h, 2 do
298298-299299- if targetclr == img:get(x, y, true) then
300300- iter_n = img:points(x, y - 1, 1, y - 1)
301301- iter_s = img:points(x, y + 1, 1, y + 1)
302302- img:marshal(x, y, 1, y, _NIL, _NIL, true, check_ns)
285285+ -- should never hit max but make sure not to end early
286286+ for qhead = 2, 0x40000000, 2 do
303287304304- iter_n = img:points(x + 1, y - 1, max_w, y - 1)
305305- iter_s = img:points(x + 1, y + 1, max_w, y + 1)
306306- img:marshal(x + 1, y, max_w, y, _NIL, _NIL, true, check_ns)
288288+ if targetclr == _get(img, x, y, true) then
289289+ _marshal(img, x, y, 1, y, _NIL, _NIL, true, check_ns) -- west
290290+ _marshal(img, x + 1, y, max_w, y, _NIL, _NIL, true, check_ns) -- east
307291 end
308292309293 x = qpt[qhead - 1]
···320304 end -- flood_fill
321305322306 -- draws a closed figure based on points in t_points
323323- local function polygon(img, x, y, t_points, color, fillcolor, bClip)
307307+ _draw.polygon = function(img, x, y, t_points, color, fillcolor, bClip)
324308 if #t_points < 2 then error("not enough points", 3) end
325309326310 if fillcolor then
···335319 if pt[2] < y_min then y_min = pt[2] end
336320 if pt[2] > y_max then y_max = pt[2] end
337321 end
338338- w = math.abs(x_max) + math.abs(x_min)
339339- h = math.abs(y_max) + math.abs(y_min)
322322+ w = _abs(x_max) + _abs(x_min)
323323+ h = _abs(y_max) + _abs(y_min)
340324 x_min = x_min - 2 -- leave a border to use flood_fill
341325 y_min = y_min - 2
342326343343- local fill_img = rb.new_image(w + 3, h + 3)
344344- fill_img:clear(0xFFFFFF)
327327+ local fill_img = _newimg(w + 3, h + 3)
328328+ _clear(fill_img, 0x1)
345329346330 for i = 1, #t_points, 1 do
347331 local pt1 = t_points[i]
348332 local pt2 = t_points[i + 1] or t_points[1]-- first and last point
349349- fill_img:line(pt1[1] - x_min, pt1[2] - y_min,
333333+ _line(fill_img, pt1[1] - x_min, pt1[2] - y_min,
350334 pt2[1]- x_min, pt2[2] - y_min, 0)
351335352336 end
353353- flood_fill(fill_img, fill_img:width(), fill_img:height() , 1, 0)
354354- img:copy(fill_img, x - 1, y - 1, _NIL, _NIL, _NIL, _NIL, bClip, BSAND, fillcolor)
337337+ _draw.flood_fill(fill_img, fill_img:width(), fill_img:height() , 0x1, 0x0)
338338+ _copy(img, fill_img, x - 1, y - 1, _NIL, _NIL, _NIL, _NIL, bClip, BSAND, fillcolor)
355339 end
356340357341 polyline(img, x, y, t_points, color, true, bClip)
358342 end
359343360344 -- draw text onto image if width/height are supplied text is centered
361361- local function text(img, x, y, width, height, font, color, text)
345345+ _draw.text = function(img, x, y, width, height, font, color, text)
362346 font = font or rb.FONT_UI
363347364348 local opts = {x = 0, y = 0, width = LCD_W - 1, height = LCD_H - 1,
365365- font = font, drawmode = 3, fg_pattern = 0xFFFFFF, bg_pattern = 0}
366366- set_viewport(opts)
349349+ font = font, drawmode = 3, fg_pattern = 0x1, bg_pattern = 0}
350350+351351+ if rb.LCD_DEPTH == 2 then -- invert 2-bit screens
352352+ --vp.drawmode = bit.bxor(vp.drawmode, 4)
353353+ vp.fg_pattern = 3 - vp.fg_pattern
354354+ vp.bg_pattern = 3 - vp.bg_pattern
355355+ end
356356+ rb.set_viewport(opts)
367357368358 local res, w, h = rb.font_getstringsize(text, font)
369359···380370 end
381371382372 -- make a copy of the current screen for later
383383- local screen_img = rb.new_image(LCD_W, LCD_H)
384384- screen_img:copy(_LCD)
373373+ local screen_img = _newimg(LCD_W, LCD_H)
374374+ _copy(screen_img, _LCD)
385375386376 -- check if the screen buffer is supplied image if so set img to the copy
387377 if img == _LCD then
···391381 -- we will be printing the text to the screen then blitting into img
392382 rb.lcd_clear_display()
393383394394- local function blit(dx, dy)
395395- img:copy(_LCD, dx, dy, _NIL, _NIL, _NIL, _NIL, false, BSAND, color)
396396- end
397397-398384 if w > LCD_W then -- text is too long for the screen do it in chunks
399385 local l = 1
400386 local resp, wp, hp
···417403 end
418404419405 -- using the mask we made blit color into img
420420- blit(x + width, y + height)
406406+ _copy(img, _LCD, x + width, y + height, _NIL, _NIL, _NIL, _NIL, false, BSAND, color)
421407 x = x + wp
422408 rb.lcd_clear_display()
423409 lenr = text:len()
···426412 rb.lcd_putsxy(0, 0, text)
427413428414 -- using the mask we made blit color into img
429429- blit(x + width, y + height)
415415+ _copy(img, _LCD, x + width, y + height, _NIL, _NIL, _NIL, _NIL, false, BSAND, color)
430416 end
431417432432- _LCD:copy(screen_img) -- restore screen
433433- set_viewport() -- set viewport default
418418+ _copy(_LCD, screen_img) -- restore screen
419419+ rb.set_viewport() -- set viewport default
434420 return res, w, h
435421 end
436422437437- -- expose functions to the outside through _draw table
438438- _draw.image = image
439439- _draw.text = text
440440- _draw.line = line
423423+ -- expose internal functions to the outside through _draw table
441424 _draw.hline = hline
442425 _draw.vline = vline
443443- _draw.polygon = polygon
444426 _draw.polyline = polyline
445427 _draw.rect = rect
446446- _draw.circle = circle
447447- _draw.ellipse = ellipse
448448- _draw.flood_fill = flood_fill
449449- _draw.ellipse_rect = ellipse_rect
450428 _draw.rounded_rect = rounded_rect
451451- -- filled functions use color as fillcolor if fillcolor is left empty...
452452- _draw.rect_filled = rect_filled
453453- _draw.circle_filled = circle_filled
454454- _draw.ellipse_filled = ellipse_filled
455455- _draw.ellipse_rect_filled = ellipse_rect_filled
456456- _draw.rounded_rect_filled = rounded_rect_filled
457457-458458- -- adds the above _draw functions into the metatable for RLI_IMAGE
459459- local ex = getmetatable(rb.lcd_framebuffer())
460460- for k, v in pairs(_draw) do
461461- if ex[k] == _NIL then
462462- ex[k] = v
463463- end
464464- end
465465-466429end -- _draw functions
467430468431return _draw
+51-66
apps/plugins/lua/include_lua/image.lua
···65656666local _img = {} do
67676868+ local rocklib_image = getmetatable(rb.lcd_framebuffer())
6969+ setmetatable(_img, rocklib_image)
7070+6871 -- internal constants
6972 local _NIL = nil -- _NIL placeholder
7073 local _math = require("math_ex") -- math functions needed
7174 local LCD_W, LCD_H = rb.LCD_WIDTH, rb.LCD_HEIGHT
7575+7676+ local _copy = rocklib_image.copy
7777+ local _get = rocklib_image.get
7878+ local _marshal = rocklib_image.marshal
7979+ local _points = rocklib_image.points
72807381 -- returns new image -of- img sized to fit w/h tiling to fit if needed
7474- local function tile(img, w, h)
8282+ _img.tile = function(img, w, h)
7583 local hs , ws = img:height(), img:width()
7684 local t_img = rb.new_image(w, h)
77857878- for x = 1, w, ws do t_img:copy(img, x, 1, 1, 1) end
7979- for y = hs, h, hs do t_img:copy(t_img, 1, y, 1, 1, w, hs) end
8686+ for x = 1, w, ws do _copy(t_img, img, x, 1, 1, 1) end
8787+ for y = hs, h, hs do _copy(t_img, t_img, 1, y, 1, 1, w, hs) end
8088 return t_img
8189 end
82908391 -- resizes src to size of dst
8484- local function resize(dst, src)
9292+ _img.resize = function(dst, src)
8593 -- simple nearest neighbor resize derived from rockbox - pluginlib_bmp.c
8694 -- pretty rough results highly recommend building one more suited..
8795 local dw, dh = dst:width(), dst:height()
88968989- local xstep = (bit.lshift(src:width(),8) / (dw)) + 1
9090- local ystep = (bit.lshift(src:height(),8) / (dh))
9797+ local xstep = (bit.lshift(src:width(), 8) / (dw)) + 1
9898+ local ystep = (bit.lshift(src:height(), 8) / (dh))
919992100 local xpos, ypos = 0, 0
93101 local src_x, src_y
9410295103 -- walk the dest get src pixel
9696- function rsz_trans(val, x, y)
104104+ local function rsz_trans(val, x, y)
97105 if x == 1 then
98106 src_y = bit.rshift(ypos,8) + 1
99107 xpos = xstep - bit.rshift(xstep,4) + 1
···101109 end
102110 src_x = bit.rshift(xpos,8) + 1
103111 xpos = xpos + xstep
104104- return (src:get(src_x, src_y, true) or 0)
112112+ return (_get(src, src_x, src_y, true) or 0)
105113 end
106114 --/* (dst*, [x1, y1, x2, y2, dx, dy, clip, function]) */
107107- dst:marshal(1, 1, dw, dh, _NIL, _NIL, false, rsz_trans)
115115+ _marshal(dst, 1, 1, dw, dh, _NIL, _NIL, false, rsz_trans)
108116 end
109117110118 -- returns new image -of- img rotated in whole degrees 0 - 360
111111- local function rotate(img, degrees)
119119+ _img.rotate = function(img, degrees)
112120 -- we do this backwards as if dest was the unrotated object
113121 degrees = 360 - degrees
114122 local c, s = _math.d_cos(degrees), _math.d_sin(degrees)
···133141 |_____| |_______| |_______| ]]
134142135143 -- walk the dest get translated src pixel, oversamples src to fill gaps
136136- function rot_trans(val, x, y)
144144+ local function rot_trans(val, x, y)
137145 -- move center x/y to the origin
138146 local xtran = x - d_xctr;
139147 local ytran = y - d_yctr;
···142150 local yrot = ((xtran * s) + (ytran * c)) / 10000 + s_yctr
143151 local xrot = ((xtran * c) - (ytran * s)) / 10000 + s_xctr
144152 -- upper left of src image back to origin, copy src pixel
145145- return img:get(xrot, yrot, true) or 0
153153+ return _get(img, xrot, yrot, true) or 0
146154 end
147147- r_img:marshal(1, 1, dw, dh, _NIL, _NIL, false, rot_trans)
155155+ _marshal(r_img, 1, 1, dw, dh, _NIL, _NIL, false, rot_trans)
148156 return r_img
149157 end
150158151159 -- saves img to file: name
152152- local function save(img, name)
160160+ _img.save = function(img, name)
153161 -- bmp saving derived from rockbox - screendump.c
154162 -- bitdepth is limited by the device
155163 -- eg. device displays greyscale, rgb images are saved greyscale
156164 local file
157157-165165+ local bbuffer = {} -- concat buffer for s_bytes
158166 local fbuffer = {} -- concat buffer for file writes, reused
159159-160160- local function dump_fbuffer(thresh)
161161- if #fbuffer >= thresh then
162162- file:write(table.concat(fbuffer))
163163- for i=1, #fbuffer do fbuffer[i] = _NIL end -- reuse table
164164- end
165165- end
166167167168 local function s_bytesLE(bits, value)
168169 -- bits must be multiples of 8 (sizeof byte)
169170 local byte
170170- local result = ""
171171- for b = 1, bit.rshift(bits, 3) do
171171+ local nbytes = bit.rshift(bits, 3)
172172+ for b = 1, nbytes do
172173 if value > 0 then
173174 byte = value % 256
174175 value = (value - byte) / 256
175175- result = result .. string.char(byte)
176176 else
177177- result = result .. string.char(0)
177177+ byte = 0
178178 end
179179+ bbuffer[b] = string.char(byte)
179180 end
180180- return result
181181+ return table.concat(bbuffer, _NIL, 1, nbytes)
181182 end
182183183184 local function s_bytesBE(bits, value)
184185 -- bits must be multiples of 8 (sizeof byte)
185186 local byte
186186- local result = ""
187187- for b = 1, bit.rshift(bits, 3) do
187187+ local nbytes = bit.rshift(bits, 3)
188188+ for b = nbytes, 1, -1 do
188189 if value > 0 then
189190 byte = value % 256
190191 value = (value - byte) / 256
191191- result = string.char(byte) .. result
192192 else
193193- result = string.char(0) .. result
193193+ byte = 0
194194 end
195195+ bbuffer[b] = string.char(byte)
195196 end
196196- return result
197197+ return table.concat(bbuffer, _NIL, 1, nbytes)
197198 end
198199199199- local function c_cmp(color, shift)
200200- -- [RR][GG][BB]
201201- return bit.band(bit.rshift(color, shift), 0xFF)
202202- end
203203-204204- local cmp = {["r"] = function(c) return c_cmp(c, 16) end,
205205- ["g"] = function(c) return c_cmp(c, 08) end,
206206- ["b"] = function(c) return c_cmp(c, 00) end}
200200+ local cmp = {["r"] = function(c) return bit.band(bit.rshift(c, 16), 0xFF) end,
201201+ ["g"] = function(c) return bit.band(bit.rshift(c, 08), 0xFF) end,
202202+ ["b"] = function(c) return bit.band(c, 0xFF) end}
207203208204 local function bmp_color(color)
209205 return s_bytesLE(8, cmp.b(color))..
···314310 end
315311 end
316312317317- dump_fbuffer(0) -- write the header to the file now
313313+ file:write(table.concat(fbuffer))-- write the header to the file now
314314+ for i=1, #fbuffer do fbuffer[i] = _NIL end -- reuse table
318315319316 local imgdata = fbuffer
320317 -- pad rows to a multiple of 4 bytes
···327324 end
328325329326 -- Bitmap lines start at bottom unless biHeight is negative
330330- for point in img:points(1, h, w + bytesleft, 1) do
327327+ for point in _points(img, 1, h, w + bytesleft, 1) do
331328 imgdata[#imgdata + 1] = fs_bytes_E(bpp, point or 0)
332332- dump_fbuffer(31) -- buffered write, increase # for performance
329329+330330+ if #fbuffer >= 31 then -- buffered write, increase # for performance
331331+ file:write(table.concat(fbuffer))
332332+ for i=1, #fbuffer do fbuffer[i] = _NIL end -- reuse table
333333+ end
334334+333335 end
334334-335335- dump_fbuffer(0) --write leftovers to file
336336+ file:write(table.concat(fbuffer)) --write leftovers to file
337337+ fbuffer = _NIL
336338337339 file:close()
338340 end -- save(img, name)
339341340342 --searches an image for target color
341341- local function search(img, x1, y1, x2, y2, targetclr, variation, stepx, stepy)
343343+ _img.search = function(img, x1, y1, x2, y2, targetclr, variation, stepx, stepy)
342344343345 if variation > 128 then variation = 128 end
344346 if variation < -128 then variation = -128 end
···352354 targetl = swap
353355 end
354356355355- for point, x, y in img:points(x1, y1, x2, y2, stepx, stepy) do
357357+ for point, x, y in _points(img, x1, y1, x2, y2, stepx, stepy) do
356358 if point >= targetl and point <= targeth then
357359 return point, x, y
358360 end
···362364363365 --[[ we won't be extending these into RLI_IMAGE]]
364366 -- creates a new rbimage size w x h
365365- local function new(w, h)
367367+ _img.new = function(w, h)
366368 return rb.new_image(w, h)
367369 end
368370369371 -- returns new image -of- file: name (_NIL if error)
370370- local function load(name)
372372+ _img.load = function(name)
371373 return rb.read_bmp_file("/" .. name)
372374 end
373375···381383 _img.RLI_INFO_DEPTH = 0x6
382384 _img.RLI_INFO_FORMAT = 0x7
383385 _img.RLI_INFO_ADDRESS = 0x8
384384-385385- -- expose functions to the outside through _img table
386386- _img.save = save
387387- _img.search = search
388388- _img.rotate = rotate
389389- _img.resize = resize
390390- _img.tile = tile
391391-392392- -- adds the above _img functions into the metatable for RLI_IMAGE
393393- local ex = getmetatable(rb.lcd_framebuffer())
394394- for k, v in pairs(_img) do
395395- if ex[k] == _NIL then ex[k] = v end
396396- end
397397- -- not exposed through RLI_IMAGE
398398- _img.new = new
399399- _img.load = load
400400-401386end -- _img functions
402387403388return _img
+13-11
apps/plugins/lua/include_lua/lcd.lua
···51515252 --internal constants
5353 local _NIL = nil -- _NIL placeholder
5454- local LCD_W, LCD_H = rb.LCD_WIDTH, rb.LCD_HEIGHT
55545655 -- clamps value to >= min and <= max
5756 local function clamp(val, min, max)
···6564 end
66656766 -- return a copy of lcd screen
6868- local function duplicate(t, screen_img)
6767+ _lcd.duplicate = function(t, screen_img)
6968 screen_img = screen_img or rb.new_image()
7069 screen_img:copy(rb.lcd_framebuffer())
7170 return screen_img
7271 end
73727473 -- updates screen in specified rectangle
7575- local function update_rect(t, x, y, w, h)
7474+ _lcd.update_rect = function(t, x, y, w, h)
7675 rb.lcd_update_rect(x - 1, y - 1,
7777- clamp(x + w, 1, LCD_W) - 1,
7878- clamp(y + h, 1, LCD_H) - 1)
7676+ clamp(x + w, 1, rb.LCD_WIDTH) - 1,
7777+ clamp(y + h, 1, rb.LCD_HEIGHT) - 1)
7978 end
80798180 -- clears lcd, optional.. ([color, x1, y1, x2, y2, clip])
8282- local function clear(t, clr, ...)
8181+ _lcd.clear = function(t, clr, ...)
8382 rb.lcd_scroll_stop() --rb really doesn't like bg change while scroll
8483 if clr == _NIL and ... == _NIL then
8584 rb.lcd_clear_display()
···8988 end
90899190 -- loads an image to the screen
9292- local function image(t, src, x, y)
9191+ _lcd.image = function(t, src, x, y)
9392 if not src then --make sure an image was passed, otherwise bail
9493 rb.splash(rb.HZ, "No Image!")
9594 return _NIL
···9897 end
999810099 -- Formattable version of splash
101101- local function splashf(t, timeout, ...)
100100+ _lcd.splashf = function(t, timeout, ...)
102101 rb.splash(timeout, string.format(...))
103102 end
104103105104 -- Gets size of text
106106- local function text_extent(t, msg, font)
105105+ _lcd.text_extent = function(t, msg, font)
107106 font = font or rb.FONT_UI
108107109108 return rb.font_getstringsize(msg, font)
110109 end
111110112111 -- Sets viewport size
113113- local function set_viewport(t, vp)
112112+ _lcd.set_viewport = function(t, vp)
114113 if not vp then rb.set_viewport() return end
115114 if rb.LCD_DEPTH == 2 then -- invert 2-bit screens
116115 --vp.drawmode = bit.bxor(vp.drawmode, 4)
···133132 end
134133135134 --expose functions to the outside through _lcd table
135135+--[[
136136 _lcd.text_extent = text_extent
137137 _lcd.set_viewport = set_viewport
138138 _lcd.duplicate = duplicate
139139- _lcd.update = rb.lcd_update
139139+ _lcd.update = _update
140140 _lcd.update_rect = update_rect
141141 _lcd.clear = clear
142142 _lcd.splashf = splashf
143143 _lcd.image = image
144144+]]
145145+ _lcd.update = rb.lcd_update
144146 _lcd.DEPTH = rb.LCD_DEPTH
145147 _lcd.W = rb.LCD_WIDTH
146148 _lcd.H = rb.LCD_HEIGHT
+36-44
apps/plugins/lua/include_lua/print.lua
···49495050 local _NIL = nil -- _NIL placeholder
5151 local _LCD = rb.lcd_framebuffer()
5252- local LCD_W, LCD_H = rb.LCD_WIDTH, rb.LCD_HEIGHT
5352 local WHITE = _clr.set(-1, 255, 255, 255)
5453 local BLACK = _clr.set(0, 0, 0, 0)
5554 local DRMODE_SOLID = 3
5655 local col_buf, s_lines = {}, {}
5756 local _p_opts = _NIL
5858-5757+ local tabstring = string.rep(" ", 2)
5958-- print internal helper functions
6059--------------------------------------------------------------------------------
6160 -- clamps value to >= min and <= max
···6766 return val
6867 end
6968 return max
7070- end
7171-7272- -- updates screen in specified rectangle
7373- local function update_rect(x, y, w, h)
7474- rb.lcd_update_rect(x - 1, y - 1,
7575- clamp(x + w, 1, LCD_W) - 1,
7676- clamp(y + h, 1, LCD_H) - 1)
7769 end
78707971 -- Gets size of text
8072 local function text_extent(msg, font)
8181- font = font or rb.FONT_UI
8273 -- res, w, h
8383- return rb.font_getstringsize(msg, font)
8484- end
8585-8686- -- Sets viewport size
8787- local function set_viewport(vp)
8888- if not vp then rb.set_viewport() return end
8989-9090- if rb.LCD_DEPTH == 2 then -- invert 2-bit screens
9191- --vp.drawmode = bit.bxor(vp.drawmode, 4)
9292- vp.fg_pattern = 3 - vp.fg_pattern
9393- vp.bg_pattern = 3 - vp.bg_pattern
9494- end
9595- rb.set_viewport(vp)
9696- end
9797-9898- -- shallow copy of table
9999- function table_clone(t)
100100- local copy = {}
101101- for k, v in pairs(t) do
102102- copy[k] = v
103103- end
104104- return copy
7474+ return rb.font_getstringsize(msg, font or rb.FONT_UI)
10575 end
1067610777 -- Updates a single line on the screen
10878 local function update_line(enabled, opts, line, h)
10979 if enabled ~= true then return end
11080 local o = opts or _p_opts
111111- update_rect(o.x, o.y + line * h + 1, o.width, h)
8181+ -- updates screen in specified rectangle
8282+ rb.lcd_update_rect(o.x - 1, o.y + line * h,
8383+ clamp(o.x + o.width, 1, rb.LCD_WIDTH) - 1,
8484+ clamp(o.y + line * h + 1 + h, 1, rb.LCD_HEIGHT) - 1)
11285 end
1138611487 -- Clears a single line on the screen
···129102 local function col_buf_insert(msg, line, _p_opts)
130103 --if _p_opts.line <= 1 then col_buf = {} end
131104 if not col_buf[line] then
132132- table.insert(col_buf, line, msg) end
105105+ table.insert(col_buf, line, msg)
106106+ end
133107 end
134108135135- --replaces / strips escape characters
109109+ --replaces / strips tab characters
136110 local function check_escapes(o, msg)
111111+--[[ --for replacing a variety of escapes
137112 local tabsz = 2
138113 local tabstr = string.rep(" ", tabsz)
139139-140114 local function repl(esc)
141115 local ret = ""
142116 if esc:sub(1,1) == "\t" then ret = string.rep(tabstr, esc:len()) end
143117 return ret
144118 end
145145-146119 msg = msg:gsub("(%c+)", repl)
147147-120120+]]
121121+ msg = msg:gsub("\t", tabstring)
148122 local res, w, h = text_extent(msg, o.font)
149123 return w, h, msg
150124 end
···154128 local function set_defaults()
155129 _p_opts = { x = 1,
156130 y = 1,
157157- width = LCD_W - 1,
158158- height = LCD_H - 1,
131131+ width = rb.LCD_WIDTH - 1,
132132+ height = rb.LCD_HEIGHT - 1,
159133 font = rb.FONT_UI,
160134 drawmode = DRMODE_SOLID,
161135 fg_pattern = WHITE,
···178152 -- if bByRef is _NIL or false then a copy is returned
179153 local function get_settings(bByRef)
180154 _p_opts = _p_opts or set_defaults()
181181- if not bByRef then return table_clone(_p_opts) end
155155+ if not bByRef then
156156+ -- shallow copy of table
157157+ local copy = {}
158158+ for k, v in pairs(_p_opts) do
159159+ copy[k] = v
160160+ end
161161+ return copy
162162+ end
163163+182164 return _p_opts
183165 end
184166···216198 -- alternative selection method
217199 --msg = "> " .. msg
218200 end
219219- set_viewport(o)
201201+202202+ if not o then rb.set_viewport() return end
203203+204204+ if rb.LCD_DEPTH == 2 then -- invert 2-bit screens
205205+ o.fg_pattern = 3 - o.fg_pattern
206206+ o.bg_pattern = 3 - o.bg_pattern
207207+ end
208208+209209+ rb.set_viewport(o)
210210+220211 o = _NIL
221212 end
222213···251242 -- sets print area
252243 local function set_area(x, y, w, h)
253244 local o = get_settings(true)
254254- o.x, o.y = clamp(x, 1, LCD_W), clamp(y, 1, LCD_H)
255255- o.width, o.height = clamp(w, 1, LCD_W - o.x), clamp(h, 1, LCD_H - o.y)
245245+ o.x, o.y = clamp(x, 1, rb.LCD_WIDTH), clamp(y, 1, rb.LCD_HEIGHT)
246246+ o.width, o.height = clamp(w, 1, rb.LCD_WIDTH - o.x), clamp(h, 1, rb.LCD_HEIGHT - o.y)
256247 o.max_line = max_lines(_p_opts)
257248258249 clear()
···312303 local o = get_settings(true)
313304 local w, h, msg
314305 local line = o.line - 1 -- rb is 0-based lua is 1-based
306306+315307 if not (...) or (...) == "\n" then -- handles blank line / single '\n'
316308 local res, w, h = text_extent(" ", o.font)
317309
+306-326
apps/plugins/lua/rocklib_img.c
···5757#define ABS(a)(((a) < 0) ? - (a) :(a))
5858#endif
59596060-#ifndef LCD_BLACK
6161-#define LCD_BLACK 0x0
6262-#endif
6363-6460struct rocklua_image
6561{
6662 int width;
···6864 int stride;
6965 size_t elems;
7066 fb_data *data;
7171- fb_data dummy[1];
6767+ fb_data dummy[1][1];
7268};
73697470/* holds iterator data for rlimages */
7571struct rli_iter_d
7672{
7777- struct rocklua_image *img;
7878- fb_data *elem;
7973 int x , y;
8074 int x1, y1;
8175 int x2, y2;
8276 int dx, dy;
7777+ fb_data *elem;
7878+ struct rocklua_image *img;
8379};
84808581/* __tostring information enums */
···9288static inline fb_data invert_color(fb_data rgb)
9389{
9490 uint8_t r = 0xFFU - FB_UNPACK_RED(rgb);
9595- uint8_t g = 0xFFU - FB_UNPACK_RED(rgb);
9696- uint8_t b = 0xFFU - FB_UNPACK_RED(rgb);
9191+ uint8_t g = 0xFFU - FB_UNPACK_GREEN(rgb);
9292+ uint8_t b = 0xFFU - FB_UNPACK_BLUE(rgb);
97939894 return FB_RGBPACK(r, g, b);
9995}
···244240static void bounds_check_xy(lua_State *L, struct rocklua_image *img,
245241 int nargx, int x, int nargy, int y)
246242{
247247- luaL_argcheck(L, x <= img->width && x > 0, nargx, ERR_IDX_RANGE);
248248- luaL_argcheck(L, y <= img->height && y > 0, nargy, ERR_IDX_RANGE);
243243+ int narg;
244244+245245+ if(x > img->width || x < 1)
246246+ narg = nargx;
247247+ else if(y <= img->height && y > 0)
248248+ return; /* note -- return if no error */
249249+ else
250250+ narg = nargy;
251251+252252+ luaL_argerror(L, narg, ERR_IDX_RANGE);
249253} /* bounds_check_xy */
250254251255static struct rocklua_image* rli_checktype(lua_State *L, int arg)
252256{
253253- void *ud = luaL_checkudata(L, arg, ROCKLUA_IMAGE);
257257+#if 0
258258+ return (struct rocklua_image*) luaL_checkudata(L, arg, ROCKLUA_IMAGE);
259259+#else /* cache result */
260260+ static struct rocklua_image* last = NULL;
261261+ void *ud = lua_touserdata(L, arg);
254262255255- luaL_argcheck(L, ud != NULL, arg, "'" ROCKLUA_IMAGE "' expected");
263263+ if(ud != NULL)
264264+ {
265265+ if(ud == last)
266266+ return last;
267267+ else if (lua_getmetatable(L, arg))
268268+ { /* does it have a metatable? */
269269+ luaL_getmetatable(L, ROCKLUA_IMAGE); /* get correct metatable */
270270+ if (lua_rawequal(L, -1, -2))
271271+ { /* does it have the correct mt? */
272272+ lua_pop(L, 2); /* remove both metatables */
273273+ last = (struct rocklua_image*) ud;
274274+ return last;
275275+ }
276276+ }
277277+ }
256278257257- return (struct rocklua_image*) ud;
279279+ luaL_typerror(L, arg, ROCKLUA_IMAGE); /* else error */
280280+ return NULL; /* to avoid warnings */
281281+#endif
258282} /* rli_checktype */
259283260284static struct rocklua_image * alloc_rlimage(lua_State *L, bool alloc_data,
···286310 /* apparent w/h is stored but behind the scenes native w/h is used */
287311 img->width = width;
288312 img->height = height;
289289- img->stride = w_native;
313313+ img->stride = STRIDE_MAIN(w_native, h_native);
290314 img->elems = n_elems;
291315292316 return img;
···305329 /* rliimage is pushed on the stack it is up to you to pop it */
306330 struct rocklua_image *a = alloc_rlimage(L, true, width, height);
307331308308- a->data = &a->dummy[0]; /* ref to beginning of alloc'd img data */
332332+ a->data = &a->dummy[0][0]; /* ref to beginning of alloc'd img data */
309333310334 return a->data;
311335} /* rli_alloc */
312336313313-static inline fb_data data_setget(fb_data *elem, int x, int y, fb_data *val)
337337+static inline fb_data data_set(fb_data *elem, int x, int y, fb_data *val)
314338{
315315- fb_data old_val = FB_SCALARPACK(0);
339339+ fb_data old_val;
316340 fb_data new_val;
317341318342 if(elem)
···328352 else
329353 pixel_to_fb(x, y, &old_val, &new_val);
330354 }
355355+ else
356356+ old_val = FB_SCALARPACK(0);
331357332358 return old_val;
333333-} /* data_setget */
334334-335335-static inline fb_data data_set(fb_data *elem, int x, int y, fb_data *new_val)
336336-{
337337- /* get and set share the same underlying function */
338338- return data_setget(elem, x, y, new_val);
339359} /* data_set */
340360341361static inline fb_data data_get(fb_data *elem, int x, int y)
342362{
343343- /* get and set share the same underlying function */
344344- return data_setget(elem, x, y, NULL);
363363+ return data_set(elem, x, y, NULL);
345364} /* data_get */
346365347347-static fb_data* rli_get_element(struct rocklua_image* img, int x, int y)
366366+static inline fb_data* rli_get_element(struct rocklua_image* img, int x, int y)
348367{
349368 int stride = img->stride;
350369 size_t elements = img->elems;
···352371353372 pixel_to_native(x, y, &x, &y);
354373374374+#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
375375+ /* column major address */
376376+ size_t data_address = (stride * (x - 1)) + (y - 1);
377377+378378+ /* y needs bound between 0 and stride otherwise overflow to prev/next x */
379379+ if(y <= 0 || y > stride || data_address >= elements)
380380+ return NULL; /* data overflow */
381381+#else
355382 /* row major address */
356383 size_t data_address = (stride * (y - 1)) + (x - 1);
357384358385 /* x needs bound between 0 and stride otherwise overflow to prev/next y */
359386 if(x <= 0 || x > stride || data_address >= elements)
360387 return NULL; /* data overflow */
388388+#endif
361389362390 return &data[data_address]; /* return element address */
363391} /* rli_get_element */
364392365393/* Lua to C Interface for pixel set and get functions */
366366-static int rli_setget(lua_State *L, bool is_get)
394394+static int rli_setget(lua_State *L, bool is_get, int narg_clip)
367395{
368396 /*(set) (dst*, [x1, y1, clr, clip]) */
369397 /*(get) (dst*, [x1, y1, clip]) */
370398 struct rocklua_image *a = rli_checktype(L, 1);
371371- int x = luaL_checkint(L, 2);
372372- int y = luaL_checkint(L, 3);
373373-374374- fb_data clr = FB_SCALARPACK(0); /* Arg 4 is color if set element */
375375- fb_data *p_clr = &clr;
399399+ int x = lua_tointeger(L, 2);
400400+ int y = lua_tointeger(L, 3);
376401377377- int clip_narg;
378378-379379- if(is_get) /* get element */
380380- {
381381- p_clr = NULL;
382382- clip_narg = 4;
383383- }
384384- else /* set element */
385385- {
386386- clr = FB_SCALARPACK((unsigned) luaL_checknumber(L, 4));
387387- clip_narg = 5;
388388- }
402402+ fb_data clr; /* Arg 4 is color if set element */
389403390404 fb_data *element = rli_get_element(a, x, y);
391405392406 if(!element)
393407 {
394394- if(!luaL_optboolean(L, clip_narg, false)) /* Error if !clip */
408408+ if(!lua_toboolean(L, narg_clip)) /* Error if !clip */
395409 bounds_check_xy(L, a, 2, x, 3, y);
396410397411 lua_pushnil(L);
398412 return 1;
399413 }
400414401401- lua_pushnumber(L, FB_UNPACK_SCALAR_LCD(data_setget(element, x, y, p_clr)));
415415+ if(is_get) /* get element */
416416+ lua_pushinteger(L, FB_UNPACK_SCALAR_LCD(data_get(element, x, y)));
417417+ else /* set element */
418418+ {
419419+ clr = FB_SCALARPACK((unsigned) lua_tointeger(L, 4));
420420+ lua_pushinteger(L, FB_UNPACK_SCALAR_LCD(data_set(element, x, y, &clr)));
421421+ }
402422403423 /* returns old value */
404424 return 1;
405425} /* rli_setget */
406426407427#ifdef RLI_EXTENDED
408408-static bool init_rli_iter(struct rli_iter_d *d,
428428+static bool rli_iter_init(struct rli_iter_d *d,
409429 struct rocklua_image *img,
410430 int x1, int y1,
411431 int x2, int y2,
···417437 swap_int((swy), &y1, &y2);
418438419439 /* stepping in the correct x direction ? */
420420- if((dx > 0 && x1 > x2) || (dx < 0 && x1 < x2))
440440+ if((dx ^ (x2 - x1)) < 0)
421441 dx = -dx;
422442423443 /* stepping in the correct y direction ? */
424424- if((dy > 0 && y1 > y2) || (dy < 0 && y1 < y2))
444444+ if((dy ^ (y2 - y1)) < 0)
425445 dy = -dy;
426446427447 d->img = img;
···436456 d->elem = rli_get_element(img, d->x, d->y);
437457438458 return(dx != 0 || dy != 0);
439439-} /* init_rli_iter */
459459+} /* rli_iter_init */
460460+461461+static struct rli_iter_d * rli_iter_create(lua_State *L)
462462+{
463463+ struct rocklua_image *a = rli_checktype(L, 1);
464464+ int x1 = luaL_optint(L, 2, 1);
465465+ int y1 = luaL_optint(L, 3, 1);
466466+ int x2 = luaL_optint(L, 4, a->width);
467467+ int y2 = luaL_optint(L, 5, a->height);
468468+ int dx = luaL_optint(L, 6, 1);
469469+ int dy = luaL_optint(L, 7, 1);
470470+ bool clip = lua_toboolean(L, 8);
471471+472472+ if(!clip)
473473+ {
474474+ bounds_check_xy(L, a, 2, x1, 3, y1);
475475+ bounds_check_xy(L, a, 4, x2, 5, y2);
476476+ }
477477+478478+ struct rli_iter_d *ds;
479479+ /* create new iter + pushed onto stack */
480480+ ds = (struct rli_iter_d *) lua_newuserdata(L, sizeof(struct rli_iter_d));
481481+482482+ rli_iter_init(ds, a, x1, y1, x2, y2, dx, dy, false, false);
483483+484484+ return ds;
485485+}
440486441487/* steps to the next point(x, y) by delta x/y, stores pointer to element
442488 returns true if x & y haven't reached x2 & y2
···464510 return true;
465511} /* next_rli_iter */
466512467467-static int d_line(struct rocklua_image *img,
468468- int x1, int y1,
469469- int x2, int y2,
470470- fb_data *clr,
471471- bool clip)
513513+static void d_line(struct rocklua_image *img,
514514+ int x1, int y1,
515515+ int x2, int y2,
516516+ fb_data *clr)
472517{
473518 /* NOTE! clr passed as pointer */
474519 /* Bresenham midpoint line algorithm */
···477522 int r_a = x2 - x1; /* range of x direction called 'a' for now */
478523 int r_b = y2 - y1; /* range of y direction called 'b' for now */
479524480480- int s_a = 1; /* step of a direction */
481481- int s_b = 1; /* step of b direction */
525525+ int s_a = (r_a > 0) - (r_a < 0); /* step of a direction -1, 0, 1 */
526526+ int s_b = (r_b > 0) - (r_b < 0); /* step of b direction -1, 0, 1 */
482527483528 int d_err;
484529 int numpixels;
···486531 int *a1 = &x1; /* pointer to the x var 'a' */
487532 int *b1 = &y1; /* pointer to the y var 'b' */
488533489489- if(r_a < 0) /* instead of negative range we will switch step instead */
490490- {
491491- r_a = -r_a;
492492- s_a = -s_a;
493493- }
494494-495495- if(r_b < 0) /* instead of negative range we will switch step instead */
496496- {
497497- r_b = -r_b;
498498- s_b = -s_b;
499499- }
500500-501501- x2 += s_a; /* add 1 extra point to make the whole line */
502502- y2 += s_b; /* add 1 extra point */
534534+ r_a = ABS(r_a);/* instead of negative range we switch step */
535535+ r_b = ABS(r_b);/* instead of negative range we switch step */
503536504537 if(r_b > r_a) /*if rangeY('b') > rangeX('a') swap their identities */
505538 {
506506- a1 = &y1;
507507- b1 = &x1;
539539+ a1 = &y1; /* pointer to the y var 'a' */
540540+ b1 = &x1; /* pointer to the x var 'b' */
508541 swap_int((true), &r_a, &r_b);
509542 swap_int((true), &s_a, &s_b);
510543 }
511544512545 d_err = ((r_b << 1) - r_a) >> 1; /* preload err of 1 step (px centered) */
513546547547+ /* add 1 extra point to make the whole line */
514548 numpixels = r_a + 1;
515549516550 r_a -= r_b; /* pre-subtract 'a' - 'b' */
517551518518- for(;numpixels > 0; numpixels--)
552552+ for(; numpixels > 0; numpixels--)
519553 {
520554 element = rli_get_element(img, x1, y1);
521521- if(element || clip)
522522- data_set(element, x1, y1, clr);
523523- else
524524- return numpixels + 1; /* Error */
555555+ data_set(element, x1, y1, clr);
525556526557 if(d_err >= 0) /* 0 is our target midpoint(exact point on the line) */
527558 {
···534565 *a1 += s_a; /* whichever axis is in 'a' stepped(-1 or +1) */
535566 }
536567537537- return 0;
538568} /* d_line */
539569540570/* ellipse worker function */
541541-static int d_ellipse_elements(struct rocklua_image * img,
542542- int x1, int y1,
543543- int x2, int y2,
544544- int sx, int sy,
545545- fb_data *clr,
546546- fb_data *fillclr,
547547- bool clip)
571571+static void d_ellipse_elements(struct rocklua_image * img,
572572+ int x1, int y1,
573573+ int x2, int y2,
574574+ fb_data *clr,
575575+ fb_data *fillclr)
548576{
549549- int ret = 0;
550550- fb_data *element1, *element2, *element3, *element4;
577577+ fb_data *element;
551578552552- if(fillclr && x1 - sx != x2 + sx)
579579+ if(fillclr)
553580 {
554554- ret |= d_line(img, x1, y1, x2, y1, fillclr, clip); /* I. II.*/
555555- ret |= d_line(img, x1, y2, x2, y2, fillclr, clip); /* III.IV.*/
581581+ d_line(img, x1, y1, x2, y1, fillclr); /* I. II.*/
582582+ d_line(img, x1, y2, x2, y2, fillclr); /* III.IV.*/
556583 }
557584558558- x1 -= sx; /* shift x & y */
559559- y1 -= sy;
560560- x2 += sx;
561561- y2 += sy;
585585+ element = rli_get_element(img, x2, y1);
586586+ data_set(element, x2, y1, clr); /* I. Quadrant +x +y */
562587563563- element1 = rli_get_element(img, x2, y1);
564564- element2 = rli_get_element(img, x1, y1);
565565- element3 = rli_get_element(img, x1, y2);
566566- element4 = rli_get_element(img, x2, y2);
588588+ element = rli_get_element(img, x1, y1);
589589+ data_set(element, x1, y1, clr); /* II. Quadrant -x +y */
567590568568- if(clip || (element1 && element2 && element3 && element4))
569569- {
570570- data_set(element1, x2, y1, clr); /* I. Quadrant +x +y */
571571- data_set(element2, x1, y1, clr); /* II. Quadrant -x +y */
572572- data_set(element3, x1, y2, clr); /* III. Quadrant -x -y */
573573- data_set(element4, x2, y2, clr); /* IV. Quadrant +x -y */
574574- }
575575- else
576576- ret = 2; /* ERROR */
591591+ element = rli_get_element(img, x1, y2);
592592+ data_set(element, x1, y2, clr); /* III. Quadrant -x -y */
577593578578- return ret;
594594+ element = rli_get_element(img, x2, y2);
595595+ data_set(element, x2, y2, clr); /* IV. Quadrant +x -y */
596596+579597} /* d_ellipse_elements */
580598581581-static int d_ellipse(struct rocklua_image *img,
599599+static void d_ellipse(struct rocklua_image *img,
582600 int x1, int y1,
583601 int x2, int y2,
584602 fb_data *clr,
585585- fb_data *fillclr,
586586- bool clip)
603603+ fb_data *fillclr)
587604{
588605 /* NOTE! clr and fillclr passed as pointers */
589606 /* Rasterizing algorithm derivative of work by Alois Zingl */
590590-#if LCD_WIDTH > 1024 || LCD_HEIGHT > 1024
607607+#if (LCD_WIDTH > 1024 || LCD_HEIGHT > 1024) && defined(INT64_MAX)
591608 /* Prevents overflow on large screens */
592592- double dx, dy, err, e2;
609609+ int64_t dx, dy, err, e1;
593610#else
594594- long dx, dy, err, e2;
611611+ int32_t dx, dy, err, e1;
595612#endif
596596-597597- int ret = 0;
613613+ /* if called with swapped points .. exchange them */
614614+ swap_int((x1 > x2), &x1, &x2);
615615+ swap_int((y1 > y2), &y1, &y2);
598616599599- int a = ABS(x2 - x1); /* diameter */
600600- int b = ABS(y2 - y1); /* diameter */
617617+ int a = x2 - x1; /* diameter */
618618+ int b = y2 - y1; /* diameter */
601619602602- if(a == 0 || b == 0 || !clr)
603603- return ret; /* not an error but nothing to display */
620620+ if(a == 0 || b == 0)
621621+ return; /* not an error but nothing to display */
604622605623 int b1 = (b & 1);
606624 b = b - (1 - b1);
···613631614632 err = dx + dy + b1 * a2; /* error of 1.step */
615633616616- /* if called with swapped points .. exchange them */
617617- swap_int((x1 > x2), &x1, &x2);
618618- swap_int((y1 > y2), &y1, &y2);
619619-620634 y1 += (b + 1) >> 1;
621635 y2 = y1 - b1;
622636623637 do
624638 {
625625- ret = d_ellipse_elements(img, x1, y1, x2, y2, 0, 0, clr, fillclr, clip);
639639+ d_ellipse_elements(img, x1, y1, x2, y2, clr, fillclr);
626640627627- e2 = err;
641641+ e1 = err;
628642629629- /* using division because you can't use bit shift on doubles.. */
630630- if(e2 <= (dy / 2)) /* target midpoint - y step */
643643+ if(e1 <= (dy >> 1)) /* target midpoint - y step */
631644 {
632645 y1++;
633646 y2--;
···635648 err += dy;
636649 }
637650638638- if(e2 >= (dx / 2) || err > (dy / 2)) /* target midpoint - x step */
651651+ if(e1 >= (dx >> 1) || err > (dy >> 1)) /* target midpoint - x step */
639652 {
640653 x1++;
641654 x2--;
···643656 err += dx;
644657 }
645658646646- } while(ret == 0 && x1 <= x2);
659659+ } while(x1 <= x2);
660660+661661+ if (fillclr && x1 - x2 <= 2)
662662+ fillclr = clr;
647663648648- while (ret == 0 && y1 - y2 < b) /* early stop of flat ellipse a=1 finish tip */
664664+ while (y1 - y2 < b) /* early stop of flat ellipse a=1 finish tip */
649665 {
650650- ret = d_ellipse_elements(img, x1, y1, x2, y2, 1, 0, clr, fillclr, clip);
666666+ d_ellipse_elements(img, x1, y1, x2, y2, clr, fillclr);
651667652668 y1++;
653669 y2--;
654670 }
655671656656- return ret;
657672} /* d_ellipse */
658673659674/* Lua to C Interface for line and ellipse */
660660-static int rli_line_ellipse(lua_State *L, bool is_ellipse)
675675+static int rli_line_ellipse(lua_State *L, bool is_ellipse, int narg_clip)
661676{
662677 struct rocklua_image *a = rli_checktype(L, 1);
663678···666681 int x2 = luaL_optint(L, 4, x1);
667682 int y2 = luaL_optint(L, 5, y1);
668683669669- fb_data clr = FB_SCALARPACK((unsigned) luaL_checknumber(L, 6));
684684+ fb_data clr = FB_SCALARPACK((unsigned) lua_tointeger(L, 6));
670685671686 fb_data fillclr; /* fill color is index 7 if is_ellipse */
672687 fb_data *p_fillclr = NULL;
673688674674- bool clip;
675675- int clip_narg;
676676-677677- if(is_ellipse)
678678- clip_narg = 8;
679679- else
680680- clip_narg = 7;
681681-682682- clip = luaL_optboolean(L, clip_narg, false);
689689+ bool clip = lua_toboolean(L, narg_clip);
683690684691 if(!clip)
685692 {
···689696690697 if(is_ellipse)
691698 {
692692- if(!lua_isnoneornil(L, 7))
699699+ if(lua_type(L, 7) == LUA_TNUMBER)
693700 {
694694- fillclr = FB_SCALARPACK((unsigned) luaL_checkint(L, 7));
701701+ fillclr = FB_SCALARPACK((unsigned) lua_tointeger(L, 7));
695702 p_fillclr = &fillclr;
696703 }
697704698698- luaL_argcheck(L, d_ellipse(a, x1, y1, x2, y2, &clr, p_fillclr, clip) == 0,
699699- 1, ERR_DATA_OVF);
705705+ d_ellipse(a, x1, y1, x2, y2, &clr, p_fillclr);
700706 }
701707 else
702702- luaL_argcheck(L, d_line(a, x1, y1, x2, y2, &clr, clip) == 0,
703703- 1, ERR_DATA_OVF);
708708+ d_line(a, x1, y1, x2, y2, &clr);
704709705710 return 0;
706711} /* rli_line_ellipse */
707712708708-/* Pushes lua function from Stack at position narg to top of stack
709709- and puts a reference in the global registry for later use */
710710-static inline int register_luafunc(lua_State *L, int narg_funct)
713713+static inline int rli_pushpixel(lua_State *L, fb_data color, int x, int y)
711714{
712712- lua_pushvalue(L, narg_funct); /* lua function */
713713- int lf_ref = luaL_ref(L, LUA_REGISTRYINDEX);
714714- lua_settop(L, 0); /* clear C stack for use by lua function */
715715- return lf_ref;
716716-} /* register_luafunc */
715715+ lua_pushinteger(L, FB_UNPACK_SCALAR_LCD(color));
716716+ lua_pushinteger(L, x);
717717+ lua_pushinteger(L, y);
718718+ return 3;
719719+}
717720718721/* User defined pixel manipulations through rli_copy, rli_marshal */
719722static int custom_transform(lua_State *L,
···723726 fb_data *color)
724727{
725728 (void) color;
726726-729729+ (void) op;
727730 fb_data dst;
728731 fb_data src;
729732730730- unsigned int params = 3;
733733+ int params;
731734 int ret = 0;
732735733733- lua_rawgeti(L, LUA_REGISTRYINDEX, op);
736736+ if (!lua_isfunction(L, -1))
737737+ return ret; /* error */
738738+739739+ lua_pushvalue(L, -1); /* make a copy of the lua function */
734740735741 dst = data_get(ds->elem, ds->x, ds->y);
736736- lua_pushnumber(L, FB_UNPACK_SCALAR_LCD(dst));
737737- lua_pushnumber(L, ds->x);
738738- lua_pushnumber(L, ds->y);
742742+ params = rli_pushpixel(L, dst, ds->x, ds->y);
739743740744 if(ss) /* Allows src to be omitted */
741745 {
742742- params += 3;
743746 src = data_get(ss->elem, ss->x, ss->y);
744744- lua_pushnumber(L, FB_UNPACK_SCALAR_LCD(src));
745745- lua_pushnumber(L, ss->x);
746746- lua_pushnumber(L, ss->y);
747747+ params += rli_pushpixel(L, src, ss->x, ss->y);
747748 }
748749749750 lua_call(L, params, 2); /* call custom function w/ n-params & 2 ret */
750751751751- if(!lua_isnoneornil(L, -2))
752752+ if(lua_type(L, -2) == LUA_TNUMBER)
752753 {
753753- ret = 1;
754754- dst = FB_SCALARPACK((unsigned) luaL_checknumber(L, -2));
754754+ ret |= 1;
755755+ dst = FB_SCALARPACK((unsigned) lua_tointeger(L, -2));
755756 data_set(ds->elem, ds->x, ds->y, &dst);
756757 }
757758758758- if(!lua_isnoneornil(L, -1) && ss)
759759+ if(ss && (lua_type(L, -1) == LUA_TNUMBER))
759760 {
760761 ret |= 2;
761761- src = FB_SCALARPACK((unsigned) luaL_checknumber(L, -1));
762762+ src = FB_SCALARPACK((unsigned) lua_tointeger(L, -1));
762763 data_set(ss->elem, ss->x, ss->y, &src);
763764 }
764765···834835 case 27: { if(dst == src) { dst = clr; } break; }
835836 case 28: { if(dst > src) { dst = clr; } break; }
836837 case 29: { if(dst < src) { dst = clr; } break; }
838838+#if 0
839839+ /* src unneeded */
840840+ case 30: { dst = clr; break; }/* copyC */
841841+ case 31: { dst = clr | dst; break; }/* DorC */
842842+ case 32: { dst = clr ^ dst; break; }/* DxorC */
843843+ case 33: { dst = ~(clr | dst); break; }/* nDorC */
844844+ case 34: { dst = (~clr) | dst; break; }/* DornC */
845845+ case 35: { dst = clr & dst; break; }/* DandC */
846846+ case 36: { dst = clr & (~dst); break; }/* nDandC */
847847+ case 37: { dst = ~clr; break; }/* notC */
848848+#endif
837849838850 }/*switch op*/
839839- fb_data data = FB_SCALARPACK(dst);
840840- data_set(ds->elem, ds->x, ds->y, &data);
851851+ fb_data val = FB_SCALARPACK(dst);
852852+ data_set(ds->elem, ds->x, ds->y, &val);
841853 return 1;
842854} /* blit_transform */
843855···857869858870 return 1;
859871} /* invert_transform */
872872+873873+static int clear_transform(lua_State *L,
874874+ struct rli_iter_d *ds,
875875+ struct rli_iter_d *ss,
876876+ int op,
877877+ fb_data *color)
878878+{
879879+ (void) L;
880880+ (void) op;
881881+ (void) ss;
882882+883883+ data_set(ds->elem, ds->x, ds->y, color);
884884+885885+ return 1;
886886+} /* clear_transform */
887887+860888#endif /* RLI_EXTENDED */
861889862890/* RLI to LUA Interface functions *********************************************/
···865893 int width = luaL_optint(L, 1, LCD_WIDTH);
866894 int height = luaL_optint(L, 2, LCD_HEIGHT);
867895868868- luaL_argcheck(L, width > 0, 1, ERR_IDX_RANGE);
869869- luaL_argcheck(L, height > 0, 2, ERR_IDX_RANGE);
896896+ luaL_argcheck(L, width > 0 && height > 0, (width <= 0) ? 1 : 2, ERR_IDX_RANGE);
870897871898 rli_alloc(L, width, height);
872899···876903RLI_LUA rli_set(lua_State *L)
877904{
878905 /*(set) (dst*, [x1, y1, clr, clip]) */
879879- /* get and set share the same underlying function */
880880- return rli_setget(L, false);
906906+ return rli_setget(L, false, 5);
881907}
882908883909RLI_LUA rli_get(lua_State *L)
884910{
885911 /*(get) (dst*, [x1, y1, clip]) */
886886- /* get and set share the same underlying function */
887887- return rli_setget(L, true);
912912+ return rli_setget(L, true, 4);
888913}
889914890890-RLI_LUA rli_height(lua_State *L)
915915+RLI_LUA rli_equal(lua_State *L)
891916{
892917 struct rocklua_image *a = rli_checktype(L, 1);
893893- lua_pushnumber(L, a->height);
918918+ struct rocklua_image *b = rli_checktype(L, 2);
919919+ lua_pushboolean(L, a->data == b->data);
894920 return 1;
895921}
896922897897-RLI_LUA rli_width(lua_State *L)
923923+RLI_LUA rli_height(lua_State *L)
898924{
899925 struct rocklua_image *a = rli_checktype(L, 1);
900900- lua_pushnumber(L, a->width);
926926+ lua_pushinteger(L, a->height);
901927 return 1;
902928}
903929904904-RLI_LUA rli_equal(lua_State *L)
930930+RLI_LUA rli_width(lua_State *L)
905931{
906932 struct rocklua_image *a = rli_checktype(L, 1);
907907- struct rocklua_image *b = rli_checktype(L, 2);
908908- lua_pushboolean(L, a->data == b->data);
933933+ lua_pushinteger(L, a->width);
909934 return 1;
910935}
911936912937RLI_LUA rli_size(lua_State *L)
913938{
914939 struct rocklua_image *a = rli_checktype(L, 1);
915915- lua_pushnumber(L, a->elems);
940940+ lua_pushinteger(L, a->elems);
916941 return 1;
917942}
918943···921946 /*val = (img*, index, [new_val]) */
922947 struct rocklua_image *a = rli_checktype(L, 1);
923948924924- size_t i = (unsigned) luaL_checkint(L, 2);
949949+ size_t i = (unsigned) lua_tointeger(L, 2);
925950926951 fb_data val;
927952928953 luaL_argcheck(L, i > 0 && i <= (a->elems), 2, ERR_IDX_RANGE);
929954930930- lua_pushnumber(L, FB_UNPACK_SCALAR_LCD(a->data[i-1]));
955955+ lua_pushinteger(L, FB_UNPACK_SCALAR_LCD(a->data[i-1]));
931956932932- if(!lua_isnoneornil(L, 3))
957957+ if(lua_type(L, 3) == LUA_TNUMBER)
933958 {
934934- val = FB_SCALARPACK((unsigned) luaL_checknumber(L, 3));
959959+ val = FB_SCALARPACK((unsigned) lua_tointeger(L, 3));
935960 a->data[i-1] = val;
936961 }
937962···943968 /* (img, [infoitem]) */
944969 struct rocklua_image *a = rli_checktype(L, 1);
945970946946- int item = (unsigned) luaL_optint(L, 2, 0);
971971+ int item = lua_tointeger(L, 2);
947972 size_t bytes = a->elems * sizeof(fb_data);
948973949974 switch(item)
···956981 a->width, a->height, a->elems, bytes, LCD_DEPTH, LCD_PIXELFORMAT);
957982 break;
958983 }
959959- case RLI_INFO_TYPE: { lua_pushfstring(L, ROCKLUA_IMAGE ); break; }
960960- case RLI_INFO_WIDTH: { lua_pushfstring(L, "%d", a->width ); break; }
961961- case RLI_INFO_HEIGHT: { lua_pushfstring(L, "%d", a->height ); break; }
962962- case RLI_INFO_ELEMS: { lua_pushfstring(L, "%d", a->elems ); break; }
963963- case RLI_INFO_BYTES: { lua_pushfstring(L, "%d", bytes ); break; }
964964- case RLI_INFO_DEPTH: { lua_pushfstring(L, "%d", LCD_DEPTH ); break; }
965965- case RLI_INFO_FORMAT: { lua_pushfstring(L, "%d", LCD_PIXELFORMAT); break; }
966966- case RLI_INFO_ADDRESS: { lua_pushfstring(L, "%p", a->data); break; }
984984+ case RLI_INFO_TYPE: { lua_pushfstring(L, ROCKLUA_IMAGE); break; }
985985+ case RLI_INFO_WIDTH: { lua_pushinteger(L, a->width); break; }
986986+ case RLI_INFO_HEIGHT: { lua_pushinteger(L, a->height); break; }
987987+ case RLI_INFO_ELEMS: { lua_pushinteger(L, a->elems); break; }
988988+ case RLI_INFO_BYTES: { lua_pushinteger(L, bytes); break; }
989989+ case RLI_INFO_DEPTH: { lua_pushinteger(L, LCD_DEPTH ); break; }
990990+ case RLI_INFO_FORMAT: { lua_pushinteger(L, LCD_PIXELFORMAT); break; }
991991+ case RLI_INFO_ADDRESS: { lua_pushfstring(L, "%p", a->data); break; }
967992 }
968993994994+ /* lua_pushstring(L, lua_tostring(L, -1)); */
995995+ lua_tostring(L, -1); /* converts item at index to string */
996996+969997 return 1;
970998}
971999···9741002{
9751003 /* (dst*, x1, y1, x2, y2, [clr, fillclr, clip]) */
9761004 /* line and ellipse share the same init function */
977977- return rli_line_ellipse(L, true);
10051005+ return rli_line_ellipse(L, true, 8);
9781006}
97910079801008RLI_LUA rli_line(lua_State *L)
9811009{
9821010 /* (dst*, x1, y1, [x2, y2, clr, clip]) */
9831011 /* line and ellipse share the same init function */
984984- return rli_line_ellipse(L, false);
10121012+ return rli_line_ellipse(L, false, 7);
9851013}
98610149871015RLI_LUA rli_iterator(lua_State *L) {
9881016 /* see rli_iterator_factory */
10171017+ int params = 0;
9891018 struct rli_iter_d *ds;
9901019 ds = (struct rli_iter_d *) lua_touserdata(L, lua_upvalueindex(1));
99110209921021 if(ds->dx != 0 || ds->dy != 0)
9931022 {
994994- lua_pushnumber(L, FB_UNPACK_SCALAR_LCD(data_get(ds->elem, ds->x, ds->y)));
995995-996996- lua_pushinteger(L, ds->x);
997997- lua_pushinteger(L, ds->y);
10231023+ params = rli_pushpixel(L, data_get(ds->elem, ds->x, ds->y), ds->x, ds->y);
99810249991025 next_rli_iter(ds); /* load next element */
10001000-10011001- return 3;
10021026 }
10031003- return 0; /* nothing left to do */
10271027+ return params; /* nothing left to do */
10041028}
1005102910061006-RLI_LUA rli_iterator_factory(lua_State *L) {
10071007- /* (src*, [x1, y1, x2, y2, dx, dy]) */
10081008- struct rocklua_image *a = rli_checktype(L, 1); /*image we wish to iterate*/
10091009-10101010- struct rli_iter_d *ds;
10111011-10121012- int x1 = luaL_optint(L, 2, 1);
10131013- int y1 = luaL_optint(L, 3, 1);
10141014- int x2 = luaL_optint(L, 4, a->width - x1 + 1);
10151015- int y2 = luaL_optint(L, 5, a->height - y1 + 1);
10161016- int dx = luaL_optint(L, 6, 1);
10171017- int dy = luaL_optint(L, 7, 1);
10301030+RLI_LUA rli_iterator_factory(lua_State *L)
10311031+{
10321032+ /* (points) (img*, [x1, y1, x2, y2, dx, dy, clip]) */
10331033+ /* (indices 1-8 are used by rli_iter_create) */
1018103410191035 /* create new iter + pushed onto stack */
10201020- ds = (struct rli_iter_d *) lua_newuserdata(L, sizeof(struct rli_iter_d));
10211021-10221022- init_rli_iter(ds, a, x1, y1, x2, y2, dx, dy, false, false);
10361036+ rli_iter_create(L);
1023103710241038 /* returns the iter function with embedded iter data(up values) */
10251039 lua_pushcclosure(L, &rli_iterator, 1);
···10271041 return 1;
10281042}
1029104310301030-RLI_LUA rli_marshal(lua_State *L) /* also invert */
10441044+RLI_LUA rli_marshal(lua_State *L) /* also invert, clear */
10311045{
10321032- /* (img*, [x1, y1, x2, y2, dx, dy, clip, function]) */
10331033- struct rocklua_image *a = rli_checktype(L, 1);
10341034-10351035- struct rli_iter_d ds;
10361036-10371037- int x1 = luaL_optint(L, 2, 1);
10381038- int y1 = luaL_optint(L, 3, 1);
10391039- int x2 = luaL_optint(L, 4, a->width);
10401040- int y2 = luaL_optint(L, 5, a->height);
10411041- int dx = luaL_optint(L, 6, 1);
10421042- int dy = luaL_optint(L, 7, 1);
10431043- bool clip = luaL_optboolean(L, 8, false);
10441044-10451045- int lf_ref = LUA_NOREF; /* de-ref'd without consequence */
10461046+ /* (marshal/invert/clear) (img*, [x1, y1, x2, y2, dx, dy, clip, function]) */
10471047+ /* (indices 1-8 are used by rli_iter_create) */
10481048+ fb_data clr;
1046104910471050 int (*rli_trans)(lua_State *, struct rli_iter_d *, struct rli_iter_d *, int, fb_data *);
10481048- rli_trans = invert_transform; /* default transformation */
10511051+ int ltype = lua_type (L, 9);
1049105210501050- if(!clip)
10531053+ /* create new iter + pushed onto stack */
10541054+ struct rli_iter_d *ds = rli_iter_create(L);
10551055+10561056+ if (ltype == LUA_TNUMBER)
10511057 {
10521052- bounds_check_xy(L, a, 2, x1, 3, y1);
10531053- bounds_check_xy(L, a, 4, x2, 5, y2);
10581058+ clr = FB_SCALARPACK((unsigned) lua_tointeger(L, 9));
10591059+ rli_trans = clear_transform;
10541060 }
10551055-10561056- init_rli_iter(&ds, a, x1, y1, x2, y2, dx, dy, false, false);
10571057-10581058- if(lua_isfunction(L, 9)) /* custom function */
10611061+ else if(ltype == LUA_TFUNCTION) /* custom function */
10591062 {
10601063 rli_trans = custom_transform;
10611061- lf_ref = register_luafunc(L, 9);
10641064+ lua_pushvalue(L, 9); /* ensure lua function on top of stack */
10621065 }
10661066+ else
10671067+ rli_trans = invert_transform; /* default transformation */
1063106810641069 do
10651070 {
10661066- luaL_argcheck(L, clip || (ds.elem != NULL), 1, ERR_DATA_OVF);
10671067-10681068- if(!(*rli_trans)(L, &ds, NULL, lf_ref, NULL))
10711071+ if(!(*rli_trans)(L, ds, NULL, 0, &clr))
10691072 break; /* Custom op can quit early */
1070107310711071- } while(next_rli_iter(&ds));
10741074+ } while(next_rli_iter(ds));
1072107510731073- luaL_unref(L, LUA_REGISTRYINDEX, lf_ref); /* de-reference custom function */
10741076 return 0;
10751077}
1076107810771079RLI_LUA rli_copy(lua_State *L)
10781080{
10791081 /* (dst*, src*, [d_x, d_y, s_x, s_y, x_off, y_off, clip, [op, funct/clr]]) */
10801080- struct rocklua_image *d = rli_checktype(L, 1); /*dst*/
10811081- struct rocklua_image *s = rli_checktype(L, 2); /*src*/
10821082+ struct rocklua_image *dst = rli_checktype(L, 1); /* dst */
10831083+ struct rocklua_image *src = rli_checktype(L, 2); /* src */
1082108410831083- struct rli_iter_d ds; /*dst*/
10841084- struct rli_iter_d ss; /*src*/
10851085+ struct rli_iter_d ds; /* dst */
10861086+ struct rli_iter_d ss; /* src */
1085108710861088 /* copy whole image if possible */
10871087- if(s->elems == d->elems && s->width == d->width && lua_gettop(L) < 3)
10891089+ if(src->elems == dst->elems && src->width == dst->width && lua_gettop(L) < 3)
10881090 {
10891089- rb->memcpy(d->data, s->data, d->elems * sizeof(fb_data));
10911091+ rb->memcpy(dst->data, src->data, dst->elems * sizeof(fb_data));
10901092 return 0;
10911093 }
10921094···10951097 int s_x = luaL_optint(L, 5, 1);
10961098 int s_y = luaL_optint(L, 6, 1);
1097109910981098- int w = MIN(d->width - d_x, s->width - s_x);
10991099- int h = MIN(d->height - d_y, s->height - s_y);
11001100+ int w = MIN(dst->width - d_x, src->width - s_x);
11011101+ int h = MIN(dst->height - d_y, src->height - s_y);
1100110211011103 int x_off = luaL_optint(L, 7, w);
11021104 int y_off = luaL_optint(L, 8, h);
1103110511041104- bool clip = luaL_optboolean(L, 9, false);
11051105- int op = luaL_optint(L, 10, 0);
11061106- fb_data clr = FB_SCALARPACK(0); /* 11 is custom function | color */
11061106+ bool clip = lua_toboolean(L, 9);
11071107+ int op; /* 10 is operation for blit */
11081108+ fb_data clr; /* 11 is custom function | color */
1107110911081110 bool d_swx = (x_off < 0); /* dest swap */
11091111 bool d_swy = (y_off < 0);
11101110- bool s_swx = false; /* src swap */
11121112+ bool s_swx = false; /* src swap */
11111113 bool s_swy = false;
1112111411131115 int (*rli_trans)(lua_State *, struct rli_iter_d *, struct rli_iter_d *, int, fb_data *);
11141114- rli_trans = blit_transform; /* default transformation */
11151115-11161116- int lf_ref = LUA_NOREF; /* de-ref'd without consequence */
1117111611181117 if(!clip) /* Out of bounds is not allowed */
11191118 {
11201120- bounds_check_xy(L, d, 3, d_x, 4, d_y);
11211121- bounds_check_xy(L, s, 5, s_x, 6, s_y);
11191119+ bounds_check_xy(L, dst, 3, d_x, 4, d_y);
11201120+ bounds_check_xy(L, src, 5, s_x, 6, s_y);
11211121+ w = MIN(w, ABS(x_off));
11221122+ h = MIN(h, ABS(y_off));
11231123+ bounds_check_xy(L, dst, 7, d_x + w, 8, d_y + h);
11241124+ bounds_check_xy(L, src, 7, s_x + w, 8, s_y + h);
11221125 }
11231123- else if (w < 0 || h < 0) /* not an error but nothing to display */
11241124- return 0;
11251125-11261126- w = MIN(w, ABS(x_off));
11271127- h = MIN(h, ABS(y_off));
11261126+ else
11271127+ {
11281128+ if (w < 0 || h < 0) /* not an error but nothing to display */
11291129+ return 0;
11301130+ w = MIN(w, ABS(x_off));
11311131+ h = MIN(h, ABS(y_off));
11321132+ }
1128113311291129- /* if(s->data == d->data) need to care about fill direction */
11341134+ /* if src->data == dst->data need to care about fill direction */
11301135 if(d_x > s_x)
11311136 {
11321137 d_swx = !d_swx;
···11391144 s_swy = !s_swy;
11401145 }
1141114611421142- init_rli_iter(&ds, d, d_x, d_y, d_x + w, d_y + h, 1, 1, d_swx, d_swy);
11471147+ rli_iter_init(&ds, dst, d_x, d_y, d_x + w, d_y + h, 1, 1, d_swx, d_swy);
1143114811441144- init_rli_iter(&ss, s, s_x, s_y, s_x + w, s_y + h, 1, 1, s_swx, s_swy);
11491149+ rli_iter_init(&ss, src, s_x, s_y, s_x + w, s_y + h, 1, 1, s_swx, s_swy);
1145115011461146- if (op == 0xFF && lua_isfunction(L, 11)) /* custom function specified.. */
11511151+ if (lua_type(L, 11) == LUA_TFUNCTION) /* custom function supplied.. */
11471152 {
11481153 rli_trans = custom_transform;
11491149- lf_ref = register_luafunc(L, 11);
11501150- op = lf_ref;
11541154+ lua_settop(L, 11); /* ensure lua function on top of stack */
11551155+ clr = 0;
11561156+ op = 0;
11511157 }
11521158 else
11531153- clr = FB_SCALARPACK((unsigned) luaL_optnumber(L, 11, LCD_BLACK));
11591159+ {
11601160+ rli_trans = blit_transform; /* default transformation */
11611161+ clr = FB_SCALARPACK((unsigned) lua_tointeger(L, 11));
11621162+ op = lua_tointeger(L, 10);
11631163+ }
1154116411551165 do
11561166 {
11571157- if(!clip)
11581158- {
11591159- luaL_argcheck(L, ss.elem != NULL, 2, ERR_DATA_OVF);
11601160- luaL_argcheck(L, ds.elem != NULL, 1, ERR_DATA_OVF);
11611161- }
11621162-11631167 if(!(*rli_trans)(L, &ds, &ss, op, &clr))
11641168 break; /* Custom op can quit early */
1165116911661170 } while(next_rli_iter(&ds) && next_rli_iter(&ss));
1167117111681168- luaL_unref(L, LUA_REGISTRYINDEX, lf_ref); /* de-reference custom function */
11691172 return 0;
11701173}
1171117411721175RLI_LUA rli_clear(lua_State *L)
11731176{
11741174- /* (dst*, [color, x1, y1, x2, y2, clip]) */
11751175- struct rocklua_image *a = rli_checktype(L, 1);
11771177+ /* (clear) (dst*, [color, x1, y1, x2, y2, clip, dx, dy]) */
11781178+ lua_settop(L, 9);
1176117911771177- struct rli_iter_d ds;
11781178-11791179- fb_data clr = FB_SCALARPACK((unsigned) luaL_optnumber(L, 2, LCD_BLACK));
11801180- int x1 = luaL_optint(L, 3, 1);
11811181- int y1 = luaL_optint(L, 4, 1);
11821182- int x2 = luaL_optint(L, 5, a->width);
11831183- int y2 = luaL_optint(L, 6, a->height);
11841184- bool clip = luaL_optboolean(L, 7, false);
11851185-11861186- if(!clip)
11871187- {
11881188- bounds_check_xy(L, a, 3, x1, 4, y1);
11891189- bounds_check_xy(L, a, 5, x2, 6, y2);
11901190- }
11801180+ lua_pushvalue(L, 7); /* clip -- index 8 */
11811181+ lua_remove(L, 7);
1191118211921192- init_rli_iter(&ds, a, x1, y1, x2, y2, 1, 1, false, false);
11831183+ lua_pushinteger(L, lua_tointeger(L, 2)); /*color -- index 9*/
11841184+ lua_remove(L, 2);
1193118511941194- do
11951195- {
11961196- luaL_argcheck(L, clip || (ds.elem != NULL), 1, ERR_DATA_OVF);
11971197-11981198- data_set(ds.elem, ds.x, ds.y, &clr);
11991199-12001200- } while(next_rli_iter(&ds));
12011201-12021202- return 0;
11861186+ return rli_marshal(L); /* (img*, [x1, y1, x2, y2, dx, dy, clip, function]) */
12031187}
12041188#endif /* RLI_EXTENDED */
12051189···1236122012371221 luaL_newmetatable(L, ROCKLUA_IMAGE);
1238122212391239- lua_pushstring(L, "__index");
12401240- lua_pushvalue(L, -2); /* pushes the metatable */
12411241- lua_settable(L, -3); /* metatable.__index = metatable */
12231223+ lua_pushvalue(L, -1); /* pushes the metatable */
12241224+ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
1242122512431226 luaL_register(L, NULL, rli_lib);
1244122712451245-#ifdef RLI_EXTENDED
12461246- luaL_register(L, ROCKLUA_IMAGE, rli_lib);
12471247-#endif
12481228 return 1;
12491229}
12501230···12561236 * -----------------------------
12571237 */
1258123812591259-#define RB_WRAP(M) static int rock_##M(lua_State UNUSED_ATTR *L)
12391239+#define RB_WRAP(func) static int rock_##func(lua_State UNUSED_ATTR *L)
12601240#ifdef HAVE_LCD_BITMAP
12611241RB_WRAP(lcd_framebuffer)
12621242{