1 #include "lua/internal.hpp"
2 #include "core/framebuffer.hpp"
3 #include "library/framebuffer.hpp"
4 #include "library/lua-framebuffer.hpp"
5 #include "library/minmax.hpp"
6 #include "library/png.hpp"
7 #include "library/sha256.hpp"
8 #include "library/serialization.hpp"
9 #include "library/string.hpp"
10 #include "library/zip.hpp"
11 #include "lua/bitmap.hpp"
12 #include "library/threadtypes.hpp"
16 std::vector
<char> lua_dbitmap::save_png() const
21 img
.has_palette
= false;
22 img
.has_alpha
= false;
23 img
.data
.resize(width
* height
);
24 for(size_t i
= 0; i
< width
* height
; i
++) {
25 const framebuffer::color
& c
= pixels
[i
];
28 img
.data
[i
] = c
.orig
+ ((uint32_t)(c
.origa
- (c
.origa
>> 7) + (c
.origa
>> 8)) << 24);
30 std::ostringstream tmp1
;
32 std::string tmp2
= tmp1
.str();
33 return std::vector
<char>(tmp2
.begin(), tmp2
.end());
36 std::vector
<char> lua_bitmap::save_png(const lua_palette
& pal
) const
41 img
.has_palette
= true;
42 img
.has_alpha
= false;
43 img
.data
.resize(width
* height
);
44 img
.palette
.resize(pal
.colors
.size());
45 for(size_t i
= 0; i
< width
* height
; i
++) {
46 img
.data
[i
] = pixels
[i
];
48 for(size_t i
= 0; i
< pal
.colors
.size(); i
++) {
49 const framebuffer::color
& c
= pal
.colors
[i
];
52 img
.palette
[i
] = c
.orig
+ ((uint32_t)(c
.origa
- (c
.origa
>> 7) + (c
.origa
>> 8)) << 24);
54 std::ostringstream tmp1
;
56 std::string tmp2
= tmp1
.str();
57 return std::vector
<char>(tmp2
.begin(), tmp2
.end());
62 const char* base64chars
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
64 struct render_object_bitmap
: public framebuffer::object
66 render_object_bitmap(int32_t _x
, int32_t _y
, lua::objpin
<lua_bitmap
> _bitmap
,
67 lua::objpin
<lua_palette
> _palette
) throw()
75 render_object_bitmap(int32_t _x
, int32_t _y
, lua::objpin
<lua_dbitmap
> _bitmap
) throw()
82 ~render_object_bitmap() throw()
86 bool kill_request(void* obj
) throw()
88 return kill_request_ifeq(p
.object(), obj
) ||
89 kill_request_ifeq(b
.object(), obj
) ||
90 kill_request_ifeq(b2
.object(), obj
);
93 template<bool T
> void composite_op(struct framebuffer::fb
<T
>& scr
) throw()
96 p
->palette_mutex
.lock();
97 uint32_t originx
= scr
.get_origin_x();
98 uint32_t originy
= scr
.get_origin_y();
101 framebuffer::color
* palette
;
103 palette
= &p
->colors
[0];
104 for(auto& c
: p
->colors
)
106 pallim
= p
->colors
.size();
110 for(auto& c
: b2
->pixels
)
120 framebuffer::clip_range(originx
, scr
.get_width(), x
, xmin
, xmax
);
121 framebuffer::clip_range(originy
, scr
.get_height(), y
, ymin
, ymax
);
122 for(int32_t r
= ymin
; r
< ymax
; r
++) {
123 typename
framebuffer::fb
<T
>::element_t
* rptr
= scr
.rowptr(y
+ r
+ originy
);
124 size_t eptr
= x
+ xmin
+ originx
;
126 for(int32_t c
= xmin
; c
< xmax
; c
++, eptr
++) {
127 uint16_t i
= b
->pixels
[r
* b
->width
+ c
];
129 palette
[i
].apply(rptr
[eptr
]);
132 for(int32_t c
= xmin
; c
< xmax
; c
++, eptr
++)
133 b2
->pixels
[r
* b2
->width
+ c
].apply(rptr
[eptr
]);
136 p
->palette_mutex
.unlock();
138 void operator()(struct framebuffer::fb
<false>& x
) throw() { composite_op(x
); }
139 void operator()(struct framebuffer::fb
<true>& x
) throw() { composite_op(x
); }
140 void clone(framebuffer::queue
& q
) const throw(std::bad_alloc
) { q
.clone_helper(this); }
144 lua::objpin
<lua_bitmap
> b
;
145 lua::objpin
<lua_dbitmap
> b2
;
146 lua::objpin
<lua_palette
> p
;
149 lua::fnptr
gui_bitmap(lua_func_misc
, "gui.bitmap_draw", [](lua::state
& L
, const std::string
& fname
)
151 if(lua::_class
<lua_bitmap
>::is(L
, 3))
152 return lua::_class
<lua_bitmap
>::get(L
, 3, fname
.c_str())->_draw(L
, fname
, false);
153 else if(lua::_class
<lua_dbitmap
>::is(L
, 3))
154 return lua::_class
<lua_dbitmap
>::get(L
, 3, fname
.c_str())->_draw(L
, fname
, false);
156 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 3 for " + fname
);
160 lua::fnptr
gui_cpalette(lua_func_misc
, "gui.palette_new", [](lua::state
& L
, const std::string
& fname
)
162 lua::_class
<lua_palette
>::create(L
);
166 lua::fnptr2
gui_cbitmap(lua_func_misc
, "gui.bitmap_new", [](lua::state
& L
, lua::parameters
& P
)
168 auto w
= P
.arg
<uint32_t>();
169 auto h
= P
.arg
<uint32_t>();
170 auto d
= P
.arg
<bool>();
172 auto c
= P
.color(-1);
173 lua_dbitmap
* b
= lua::_class
<lua_dbitmap
>::create(L
, w
, h
);
174 for(size_t i
= 0; i
< b
->width
* b
->height
; i
++)
177 uint16_t c
= P
.arg_opt
<uint16_t>(0);
178 lua_bitmap
* b
= lua::_class
<lua_bitmap
>::create(L
, w
, h
);
179 for(size_t i
= 0; i
< b
->width
* b
->height
; i
++)
185 lua::fnptr
gui_epalette(lua_func_misc
, "gui.palette_set", [](lua::state
& L
, const std::string
& fname
)
187 lua_palette
* p
= lua::_class
<lua_palette
>::get(L
, 1, fname
.c_str());
188 return p
->set(L
, fname
);
191 lua::fnptr
pset_bitmap(lua_func_misc
, "gui.bitmap_pset", [](lua::state
& L
, const std::string
& fname
)
193 if(lua::_class
<lua_bitmap
>::is(L
, 1))
194 return lua::_class
<lua_bitmap
>::get(L
, 1, fname
.c_str())->pset(L
, fname
);
195 else if(lua::_class
<lua_dbitmap
>::is(L
, 1))
196 return lua::_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str())->pset(L
, fname
);
198 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for " + fname
);
202 lua::fnptr
pget_bitmap(lua_func_misc
, "gui.bitmap_pget", [](lua::state
& L
, const std::string
& fname
)
204 if(lua::_class
<lua_bitmap
>::is(L
, 1))
205 return lua::_class
<lua_bitmap
>::get(L
, 1, fname
.c_str())->pget(L
, fname
);
206 else if(lua::_class
<lua_dbitmap
>::is(L
, 1))
207 return lua::_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str())->pget(L
, fname
);
209 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for " + fname
);
213 lua::fnptr
size_bitmap(lua_func_misc
, "gui.bitmap_size", [](lua::state
& L
, const std::string
& fname
)
215 if(lua::_class
<lua_bitmap
>::is(L
, 1))
216 return lua::_class
<lua_bitmap
>::get(L
, 1, fname
.c_str())->size(L
, fname
);
217 else if(lua::_class
<lua_dbitmap
>::is(L
, 1))
218 return lua::_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str())->size(L
, fname
);
220 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for " + fname
);
224 lua::fnptr
hash_bitmap(lua_func_misc
, "gui.bitmap_hash", [](lua::state
& L
, const std::string
& fname
)
226 if(lua::_class
<lua_bitmap
>::is(L
, 1))
227 return lua::_class
<lua_bitmap
>::get(L
, 1, fname
.c_str())->hash(L
, fname
);
228 else if(lua::_class
<lua_dbitmap
>::is(L
, 1))
229 return lua::_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str())->hash(L
, fname
);
231 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for " + fname
);
235 lua::fnptr
hash_palette(lua_func_misc
, "gui.palette_hash", [](lua::state
& L
, const std::string
& fname
)
237 lua_palette
* p
= lua::_class
<lua_palette
>::get(L
, 1, fname
.c_str());
238 return p
->hash(L
, fname
);
241 struct operand_dbitmap
243 typedef framebuffer::color pixel_t
;
244 typedef framebuffer::color rpixel_t
;
245 operand_dbitmap(lua_dbitmap
& _bitmap
)
246 : bitmap(_bitmap
), _transparent(-1)
248 pixels
= &bitmap
.pixels
[0];
250 size_t get_width() { return bitmap
.width
; }
251 size_t get_height() { return bitmap
.height
; }
252 const rpixel_t
& read(size_t idx
) { return pixels
[idx
]; }
253 const pixel_t
& lookup(const rpixel_t
& p
) { return p
; }
254 void write(size_t idx
, const pixel_t
& v
) { pixels
[idx
] = v
; }
255 bool is_opaque(const rpixel_t
& p
) { return p
.origa
> 0; }
256 const pixel_t
& transparent() { return _transparent
; }
260 framebuffer::color _transparent
;
263 struct operand_bitmap
265 typedef uint16_t pixel_t
;
266 typedef uint16_t rpixel_t
;
267 operand_bitmap(lua_bitmap
& _bitmap
)
270 pixels
= &bitmap
.pixels
[0];
272 size_t get_width() { return bitmap
.width
; }
273 size_t get_height() { return bitmap
.height
; }
274 const rpixel_t
& read(size_t idx
) { return pixels
[idx
]; }
275 const pixel_t
& lookup(const rpixel_t
& p
) { return p
; }
276 void write(size_t idx
, const pixel_t
& v
) { pixels
[idx
] = v
; }
277 bool is_opaque(const rpixel_t
& p
) { return p
> 0; }
278 pixel_t
transparent() { return 0; }
284 struct operand_bitmap_pal
286 typedef framebuffer::color pixel_t
;
287 typedef uint16_t rpixel_t
;
288 operand_bitmap_pal(lua_bitmap
& _bitmap
, lua_palette
& _palette
)
289 : bitmap(_bitmap
), palette(_palette
), _transparent(-1)
291 pixels
= &bitmap
.pixels
[0];
292 limit
= palette
.colors
.size();
293 pal
= &palette
.colors
[0];
295 size_t get_width() { return bitmap
.width
; }
296 size_t get_height() { return bitmap
.height
; }
297 const rpixel_t
& read(size_t idx
) { return pixels
[idx
]; }
298 const pixel_t
& lookup(const rpixel_t
& p
) { return *((p
< limit
) ? pal
+ p
: &_transparent
); }
299 bool is_opaque(const rpixel_t
& p
) { return p
> 0; }
300 const pixel_t
& transparent() { return _transparent
; }
303 lua_palette
& palette
;
305 framebuffer::color
* pal
;
307 framebuffer::color _transparent
;
312 bool iskey(uint16_t& c
) const { return false; }
313 bool iskey(framebuffer::color
& c
) const { return false; }
316 struct colorkey_direct
318 colorkey_direct(uint64_t _ck
)
320 framebuffer::color
c(_ck
);
324 bool iskey(framebuffer::color
& c
) const { return (c
.orig
== ck
&& c
.origa
== cka
); }
329 struct colorkey_palette
331 colorkey_palette(uint64_t _ck
) { ck
= _ck
; }
332 bool iskey(uint16_t& c
) const { return (c
== ck
); }
336 template<class _src
, class _dest
, class colorkey
> struct srcdest
338 srcdest(_dest Xdest
, _src Xsrc
, const colorkey
& _ckey
)
339 : dest(Xdest
), src(Xsrc
), ckey(_ckey
)
341 swidth
= src
.get_width();
342 sheight
= src
.get_height();
343 dwidth
= dest
.get_width();
344 dheight
= dest
.get_height();
346 void copy(size_t didx
, size_t sidx
)
348 typename
_src::rpixel_t c
= src
.read(sidx
);
350 dest
.write(didx
, src
.lookup(c
));
352 size_t swidth
, sheight
, dwidth
, dheight
;
359 template<class _src
, class _dest
, class colorkey
> srcdest
<_src
, _dest
, colorkey
> mk_srcdest(_dest dest
,
360 _src src
, const colorkey
& ckey
)
362 return srcdest
<_src
, _dest
, colorkey
>(dest
, src
, ckey
);
365 struct srcdest_priority
367 srcdest_priority(lua_bitmap
& dest
, lua_bitmap
& src
)
369 darray
= &dest
.pixels
[0];
370 sarray
= &src
.pixels
[0];
372 sheight
= src
.height
;
374 dheight
= dest
.height
;
376 void copy(size_t didx
, size_t sidx
)
378 uint16_t c
= sarray
[sidx
];
382 size_t swidth
, sheight
, dwidth
, dheight
;
404 porterduff_oper
get_pd_oper(const std::string
& oper
)
406 if(oper
== "Src") return PD_SRC
;
407 if(oper
== "Atop") return PD_ATOP
;
408 if(oper
== "Over") return PD_OVER
;
409 if(oper
== "In") return PD_IN
;
410 if(oper
== "Out") return PD_OUT
;
411 if(oper
== "Dest") return PD_DEST
;
412 if(oper
== "DestAtop") return PD_DEST_ATOP
;
413 if(oper
== "DestOver") return PD_DEST_OVER
;
414 if(oper
== "DestIn") return PD_DEST_IN
;
415 if(oper
== "DestOut") return PD_DEST_OUT
;
416 if(oper
== "Clear") return PD_CLEAR
;
417 if(oper
== "Xor") return PD_XOR
;
418 (stringfmt() << "Bad Porter-Duff operator '" << oper
<< "'").throwex();
421 template<porterduff_oper oper
, class _src
, class _dest
> struct srcdest_porterduff
423 srcdest_porterduff(_dest Xdest
, _src Xsrc
)
424 : dest(Xdest
), src(Xsrc
)
426 swidth
= src
.get_width();
427 sheight
= src
.get_height();
428 dwidth
= dest
.get_width();
429 dheight
= dest
.get_height();
431 void copy(size_t didx
, size_t sidx
)
433 typename
_dest::rpixel_t vd
= dest
.read(didx
);
434 typename
_src::rpixel_t vs
= src
.read(sidx
);
435 bool od
= dest
.is_opaque(vd
);
436 bool os
= src
.is_opaque(vs
);
437 typename
_dest::pixel_t ld
= dest
.lookup(vd
);
438 typename
_src::pixel_t ls
= src
.lookup(vs
);
439 typename
_dest::pixel_t t
= dest
.transparent();
440 typename
_dest::pixel_t r
;
442 case PD_SRC
: r
= ls
; break;
443 case PD_ATOP
: r
= od
? (os
? ls
: ld
) : t
; break;
444 case PD_OVER
: r
= os
? ls
: ld
; break;
445 case PD_IN
: r
= (od
& os
) ? ls
: t
; break;
446 case PD_OUT
: r
= (!od
&& os
) ? ls
: t
; break;
447 case PD_DEST
: r
= ld
; break;
448 case PD_DEST_ATOP
: r
= os
? (od
? ld
: ls
) : t
; break;
449 case PD_DEST_OVER
: r
= od
? ld
: ls
; break;
450 case PD_DEST_IN
: r
= (od
& os
) ? ld
: t
; break;
451 case PD_DEST_OUT
: r
= (od
& !os
) ? ld
: t
; break;
452 case PD_CLEAR
: r
= t
; break;
453 case PD_XOR
: r
= od
? (os
? t
: ld
) : ls
; break;
457 size_t swidth
, sheight
, dwidth
, dheight
;
463 template<porterduff_oper oper
, class _src
, class _dest
> srcdest_porterduff
<oper
, _src
, _dest
>
464 mk_porterduff(_dest dest
, _src src
)
466 return srcdest_porterduff
<oper
, _src
, _dest
>(dest
, src
);
469 template<class srcdest
>
470 void xblit_copy(srcdest sd
, uint32_t dx
, uint32_t dy
, uint32_t sx
, uint32_t sy
, uint32_t w
, uint32_t h
)
472 while((dx
+ w
> sd
.dwidth
|| sx
+ w
> sd
.swidth
) && w
> 0)
474 while((dy
+ h
> sd
.dheight
|| sy
+ h
> sd
.sheight
) && h
> 0)
476 if(dx
+ w
< w
|| dy
+ h
< h
) return; //Don't do overflowing blits.
477 if(sx
+ w
< w
|| sy
+ h
< h
) return; //Don't do overflowing blits.
478 size_t sidx
= sy
* sd
.swidth
+ sx
;
479 size_t didx
= dy
* sd
.dwidth
+ dx
;
480 size_t srskip
= sd
.swidth
- w
;
481 size_t drskip
= sd
.dwidth
- w
;
482 for(uint32_t j
= 0; j
< h
; j
++) {
483 for(uint32_t i
= 0; i
< w
; i
++) {
493 template<class srcdest
>
494 void xblit_scaled(srcdest sd
, uint32_t dx
, uint32_t dy
, uint32_t sx
, uint32_t sy
, uint32_t w
, uint32_t h
,
495 uint32_t hscl
, uint32_t vscl
)
497 w
= max(static_cast<uint32_t>(sd
.dwidth
/ hscl
), w
);
498 h
= max(static_cast<uint32_t>(sd
.dheight
/ vscl
), h
);
499 while((dx
+ hscl
* w
> sd
.dwidth
|| sx
+ w
> sd
.swidth
) && w
> 0)
501 while((dy
+ vscl
* h
> sd
.dheight
|| sy
+ h
> sd
.sheight
) && h
> 0)
503 if(dx
+ hscl
* w
< dx
|| dy
+ vscl
* h
< dy
) return; //Don't do overflowing blits.
504 if(sx
+ w
< w
|| sy
+ h
< h
) return; //Don't do overflowing blits.
505 size_t sidx
= sy
* sd
.swidth
+ sx
;
506 size_t didx
= dy
* sd
.dwidth
+ dx
;
507 size_t drskip
= sd
.dwidth
- hscl
* w
;
508 uint32_t _w
= hscl
* w
;
509 for(uint32_t j
= 0; j
< vscl
* h
; j
++) {
510 uint32_t _sidx
= sidx
;
511 for(uint32_t i
= 0; i
< _w
; i
+= hscl
) {
512 for(uint32_t k
= 0; k
< hscl
; k
++)
513 sd
.copy(didx
+ k
, _sidx
);
517 if((j
% vscl
) == vscl
- 1)
523 template<bool scaled
, class srcdest
>
524 inline void xblit(srcdest sd
, uint32_t dx
, uint32_t dy
, uint32_t sx
, uint32_t sy
, uint32_t w
, uint32_t h
,
525 uint32_t hscl
, uint32_t vscl
)
528 xblit_scaled(sd
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
530 xblit_copy(sd
, dx
, dy
, sx
, sy
, w
, h
);
533 template<bool scaled
, class src
, class dest
>
534 inline void xblit_pal(dest _dest
, src _src
, uint64_t ck
, uint32_t dx
, uint32_t dy
, uint32_t sx
,
535 uint32_t sy
, uint32_t w
, uint32_t h
, uint32_t hscl
, uint32_t vscl
)
538 xblit
<scaled
>(mk_srcdest(_dest
, _src
, colorkey_none()), dx
, dy
, sx
, sy
, w
, h
,
541 xblit
<scaled
>(mk_srcdest(_dest
, _src
, colorkey_palette(ck
)), dx
, dy
, sx
, sy
, w
, h
,
545 template<bool scaled
, class src
, class dest
>
546 inline void xblit_dir(dest _dest
, src _src
, uint64_t ck
, uint32_t dx
, uint32_t dy
, uint32_t sx
,
547 uint32_t sy
, uint32_t w
, uint32_t h
, uint32_t hscl
, uint32_t vscl
)
549 if(ck
== 0x100000000ULL
)
550 xblit
<scaled
>(mk_srcdest(_dest
, _src
, colorkey_none()), dx
, dy
, sx
, sy
, w
, h
,
553 xblit
<scaled
>(mk_srcdest(_dest
, _src
, colorkey_direct(ck
)), dx
, dy
, sx
, sy
, w
, h
,
557 template<bool scaled
, porterduff_oper oper
, class src
, class dest
>
558 inline void xblit_pduff2(dest _dest
, src _src
, uint32_t dx
, uint32_t dy
, uint32_t sx
,
559 uint32_t sy
, uint32_t w
, uint32_t h
, uint32_t hscl
, uint32_t vscl
)
561 xblit
<scaled
>(mk_porterduff
<oper
>(_dest
, _src
), dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
564 template<bool scaled
, class src
, class dest
>
565 inline void xblit_pduff(dest _dest
, src _src
, uint32_t dx
, uint32_t dy
, uint32_t sx
,
566 uint32_t sy
, uint32_t w
, uint32_t h
, uint32_t hscl
, uint32_t vscl
, porterduff_oper oper
)
570 xblit_pduff2
<scaled
, PD_ATOP
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
573 xblit_pduff2
<scaled
, PD_CLEAR
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
576 xblit_pduff2
<scaled
, PD_DEST
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
579 xblit_pduff2
<scaled
, PD_DEST_ATOP
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
582 xblit_pduff2
<scaled
, PD_DEST_IN
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
585 xblit_pduff2
<scaled
, PD_DEST_OUT
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
588 xblit_pduff2
<scaled
, PD_DEST_OVER
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
591 xblit_pduff2
<scaled
, PD_IN
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
594 xblit_pduff2
<scaled
, PD_OUT
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
597 xblit_pduff2
<scaled
, PD_OVER
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
600 xblit_pduff2
<scaled
, PD_SRC
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
603 xblit_pduff2
<scaled
, PD_XOR
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
608 lua::fnptr
blit_bitmap(lua_func_misc
, "gui.bitmap_blit", [](lua::state
& L
, const std::string
& fname
)
610 if(lua::_class
<lua_bitmap
>::is(L
, 1))
611 return lua::_class
<lua_bitmap
>::get(L
, 1, fname
.c_str())->blit
<false, false>(L
, fname
);
612 else if(lua::_class
<lua_dbitmap
>::is(L
, 1))
613 return lua::_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str())->blit
<false, false>(L
, fname
);
615 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for " + fname
);
619 lua::fnptr
blit_bitmap_s(lua_func_misc
, "gui.bitmap_blit_scaled", [](lua::state
& L
, const std::string
& fname
)
621 if(lua::_class
<lua_bitmap
>::is(L
, 1))
622 return lua::_class
<lua_bitmap
>::get(L
, 1, fname
.c_str())->blit
<true, false>(L
, fname
);
623 else if(lua::_class
<lua_dbitmap
>::is(L
, 1))
624 return lua::_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str())->blit
<true, false>(L
, fname
);
626 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for " + fname
);
630 lua::fnptr
blit_bitmap_pd(lua_func_misc
, "gui.bitmap_blit_porterduff", [](lua::state
& L
,
631 const std::string
& fname
) -> int {
632 if(lua::_class
<lua_bitmap
>::is(L
, 1))
633 return lua::_class
<lua_bitmap
>::get(L
, 1, fname
.c_str())->blit
<false, true>(L
, fname
);
634 else if(lua::_class
<lua_dbitmap
>::is(L
, 1))
635 return lua::_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str())->blit
<false, true>(L
, fname
);
637 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for " + fname
);
641 lua::fnptr
blit_bitmap_spd(lua_func_misc
, "gui.bitmap_blit_scaled_porterduff", [](lua::state
& L
,
642 const std::string
& fname
) -> int {
643 if(lua::_class
<lua_bitmap
>::is(L
, 1))
644 return lua::_class
<lua_bitmap
>::get(L
, 1, fname
.c_str())->blit
<true, true>(L
, fname
);
645 else if(lua::_class
<lua_dbitmap
>::is(L
, 1))
646 return lua::_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str())->blit
<true, true>(L
, fname
);
648 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for " + fname
);
652 lua::fnptr
blit_bitmap_p(lua_func_misc
, "gui.bitmap_blit_priority", [](lua::state
& L
,
653 const std::string
& fname
) -> int {
654 return lua::_class
<lua_bitmap
>::get(L
, 1, fname
.c_str())->blit_priority
<false>(L
, fname
);
657 lua::fnptr
blit_bitmap_sp(lua_func_misc
, "gui.bitmap_blit_scaled_priority", [](lua::state
& L
,
658 const std::string
& fname
) -> int {
659 return lua::_class
<lua_bitmap
>::get(L
, 1, fname
.c_str())->blit_priority
<true>(L
, fname
);
662 int bitmap_load_fn(lua::state
& L
, std::function
<lua_loaded_bitmap()> src
)
667 lua_dbitmap
* b
= lua::_class
<lua_dbitmap
>::create(L
, bitmap
.w
, bitmap
.h
);
668 for(size_t i
= 0; i
< bitmap
.w
* bitmap
.h
; i
++)
669 b
->pixels
[i
] = framebuffer::color(bitmap
.bitmap
[i
]);
672 lua_bitmap
* b
= lua::_class
<lua_bitmap
>::create(L
, bitmap
.w
, bitmap
.h
);
673 lua_palette
* p
= lua::_class
<lua_palette
>::create(L
);
674 for(size_t i
= 0; i
< bitmap
.w
* bitmap
.h
; i
++)
675 b
->pixels
[i
] = bitmap
.bitmap
[i
];
676 p
->colors
.resize(bitmap
.palette
.size());
677 for(size_t i
= 0; i
< bitmap
.palette
.size(); i
++)
678 p
->colors
[i
] = framebuffer::color(bitmap
.palette
[i
]);
683 lua::fnptr
gui_loadbitmap(lua_func_misc
, "gui.bitmap_load", [](lua::state
& L
,
684 const std::string
& fname
) -> int {
686 std::string name
= L
.get_string(1, fname
.c_str());
687 if(L
.type(2) != LUA_TNIL
&& L
.type(2) != LUA_TNONE
)
688 name2
= L
.get_string(2, fname
.c_str());
689 return bitmap_load_fn(L
, [&name
, &name2
]() -> lua_loaded_bitmap
{
690 std::string name3
= zip::resolverel(name
, name2
);
691 return lua_loaded_bitmap::load(name3
);
695 lua::fnptr
gui_loadbitmap2(lua_func_misc
, "gui.bitmap_load_str", [](lua::state
& L
,
696 const std::string
& fname
) -> int {
697 std::string contents
= L
.get_string(1, fname
.c_str());
698 return bitmap_load_fn(L
, [&contents
]() -> lua_loaded_bitmap
{
699 std::istringstream
strm(contents
);
700 return lua_loaded_bitmap::load(strm
);
704 inline int64_t mangle_color(uint32_t c
)
709 return ((256 - (c
>> 24) - (c
>> 31)) << 24) | (c
& 0xFFFFFF);
712 int base64val(char ch
)
714 if(ch
>= 'A' && ch
<= 'Z')
716 if(ch
>= 'a' && ch
<= 'z')
718 if(ch
>= '0' && ch
<= '9')
724 if(ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n')
731 std::string
base64_encode(const std::string
& str
)
733 std::ostringstream x
;
737 mem
= (mem
<< 8) + (unsigned char)i
;
739 uint8_t c1
= (mem
>> 18) & 0x3F;
740 uint8_t c2
= (mem
>> 12) & 0x3F;
741 uint8_t c3
= (mem
>> 6) & 0x3F;
742 uint8_t c4
= mem
& 0x3F;
743 x
<< base64chars
[c1
];
744 x
<< base64chars
[c2
];
745 x
<< base64chars
[c3
];
746 x
<< base64chars
[c4
];
752 uint8_t c1
= (mem
>> 10) & 0x3F;
753 uint8_t c2
= (mem
>> 4) & 0x3F;
754 uint8_t c3
= (mem
<< 2) & 0x3F;
755 x
<< base64chars
[c1
];
756 x
<< base64chars
[c2
];
757 x
<< base64chars
[c3
];
761 uint8_t c1
= (mem
>> 2) & 0x3F;
762 uint8_t c2
= (mem
<< 4) & 0x3F;
763 x
<< base64chars
[c1
];
764 x
<< base64chars
[c2
];
770 std::string
base64_decode(const std::string
& str
)
774 uint32_t memsize
= 1;
776 std::ostringstream x
;
778 int v
= base64val(i
);
781 posmod
= (posmod
+ 1) & 3;
782 if(v
== -2 && (posmod
== 1 || posmod
== 2))
783 throw std::runtime_error("Invalid Base64");
789 throw std::runtime_error("Invalid Base64");
790 memory
= memory
* 64 + v
;
791 memsize
= memsize
* 64;
794 x
<< static_cast<uint8_t>(memory
/ memsize
);
802 int bitmap_load_png_fn(lua::state
& L
, T
& src
)
804 png::decoder
img(src
);
805 if(img
.has_palette
) {
806 lua_bitmap
* b
= lua::_class
<lua_bitmap
>::create(L
, img
.width
, img
.height
);
807 lua_palette
* p
= lua::_class
<lua_palette
>::create(L
);
808 for(size_t i
= 0; i
< img
.width
* img
.height
; i
++)
809 b
->pixels
[i
] = img
.data
[i
];
810 p
->colors
.resize(img
.palette
.size());
811 for(size_t i
= 0; i
< img
.palette
.size(); i
++)
812 p
->colors
[i
] = framebuffer::color(mangle_color(img
.palette
[i
]));
815 lua_dbitmap
* b
= lua::_class
<lua_dbitmap
>::create(L
, img
.width
, img
.height
);
816 for(size_t i
= 0; i
< img
.width
* img
.height
; i
++)
817 b
->pixels
[i
] = framebuffer::color(mangle_color(img
.data
[i
]));
822 lua::fnptr
gui_loadbitmappng(lua_func_misc
, "gui.bitmap_load_png", [](lua::state
& L
,
823 const std::string
& fname
) -> int {
825 std::string name
= L
.get_string(1, fname
.c_str());
826 if(L
.type(2) != LUA_TNIL
&& L
.type(2) != LUA_TNONE
)
827 name2
= L
.get_string(2, fname
.c_str());
828 std::string filename
= zip::resolverel(name
, name2
);
829 return bitmap_load_png_fn(L
, filename
);
832 lua::fnptr
gui_loadbitmappng2(lua_func_misc
, "gui.bitmap_load_png_str", [](lua::state
& L
,
833 const std::string
& fname
) -> int {
834 std::string contents
= base64_decode(L
.get_string(1, fname
.c_str()));
835 std::istringstream
strm(contents
);
836 return bitmap_load_png_fn(L
, strm
);
839 lua::fnptr
gui_savebitmappng(lua_func_misc
, "gui.bitmap_save_png", [](lua::state
& L
,
840 const std::string
& fname
) -> int {
842 while(L
.type(slot
) == LUA_TSTRING
)
844 if(lua::_class
<lua_bitmap
>::is(L
, slot
))
845 return lua::_class
<lua_bitmap
>::get(L
, slot
, fname
.c_str())->_save_png(L
, fname
, false);
846 else if(lua::_class
<lua_dbitmap
>::is(L
, slot
))
847 return lua::_class
<lua_dbitmap
>::get(L
, slot
, fname
.c_str())->_save_png(L
, fname
, false);
849 throw std::runtime_error("Expected BITMAP or DBITMAP as first non-string argument for " +
854 int bitmap_palette_fn(lua::state
& L
, std::istream
& s
)
856 lua_palette
* p
= lua::_class
<lua_palette
>::create(L
);
859 std::getline(s
, line
);
862 if(!regex_match("[ \t]*(#.*)?", line
)) {
864 } else if(r
= regex("[ \t]*([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]*", line
)) {
865 int64_t cr
, cg
, cb
, ca
;
866 cr
= parse_value
<uint8_t>(r
[1]);
867 cg
= parse_value
<uint8_t>(r
[2]);
868 cb
= parse_value
<uint8_t>(r
[3]);
869 ca
= 256 - parse_value
<uint16_t>(r
[4]);
872 p
->colors
.push_back(framebuffer::color(-1));
874 p
->colors
.push_back(framebuffer::color((ca
<< 24) | (cr
<< 16)
876 } else if(r
= regex("[ \t]*([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]*", line
)) {
878 cr
= parse_value
<uint8_t>(r
[1]);
879 cg
= parse_value
<uint8_t>(r
[2]);
880 cb
= parse_value
<uint8_t>(r
[3]);
881 p
->colors
.push_back(framebuffer::color((cr
<< 16) | (cg
<< 8) | cb
));
882 } else if(r
= regex("[ \t]*([^ \t]|[^ \t].*[^ \t])[ \t]*", line
)) {
883 p
->colors
.push_back(framebuffer::color(r
[1]));
885 throw std::runtime_error("Invalid line format (" + line
+ ")");
890 lua::fnptr
gui_loadpalette(lua_func_misc
, "gui.bitmap_load_pal", [](lua::state
& L
,
891 const std::string
& fname
) -> int {
893 std::string name
= L
.get_string(1, fname
.c_str());
894 if(L
.type(2) != LUA_TNIL
&& L
.type(2) != LUA_TNONE
)
895 name2
= L
.get_string(2, fname
.c_str());
896 std::istream
& s
= zip::openrel(name
, name2
);
898 int r
= bitmap_palette_fn(L
, s
);
907 lua::fnptr
gui_loadpalette2(lua_func_misc
, "gui.bitmap_load_pal_str", [](lua::state
& L
,
908 const std::string
& fname
) -> int {
909 std::string content
= L
.get_string(1, fname
.c_str());
910 std::istringstream
s(content
);
911 return bitmap_palette_fn(L
, s
);
914 lua::fnptr
gui_dpalette(lua_func_misc
, "gui.palette_debug", [](lua::state
& L
,
915 const std::string
& fname
) -> int {
916 lua_palette
* p
= lua::_class
<lua_palette
>::get(L
, 1, fname
.c_str());
917 return p
->debug(L
, fname
);
920 inline framebuffer::color
tadjust(framebuffer::color c
, uint16_t adj
)
922 uint32_t rgb
= c
.orig
;
923 uint32_t a
= c
.origa
;
928 return framebuffer::color(-1);
930 return framebuffer::color(rgb
| ((uint32_t)(256 - a
) << 24));
933 lua::fnptr
adjust_trans(lua_func_misc
, "gui.adjust_transparency", [](lua::state
& L
,
934 const std::string
& fname
) -> int {
935 if(lua::_class
<lua_dbitmap
>::is(L
, 1))
936 return lua::_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str())->adjust_transparency(L
, fname
);
937 else if(lua::_class
<lua_palette
>::is(L
, 1))
938 return lua::_class
<lua_palette
>::get(L
, 1, fname
.c_str())->adjust_transparency(L
, fname
);
940 throw std::runtime_error("Expected BITMAP or PALETTE as argument 1 for "
941 "gui.adjust_transparency");
945 lua::_class
<lua_palette
> class_palette("PALETTE");
946 lua::_class
<lua_bitmap
> class_bitmap("BITMAP");
947 lua::_class
<lua_dbitmap
> class_dbitmap("DBITMAP");
951 lua_palette::lua_palette(lua::state
& L
)
953 lua::objclass
<lua_palette
>().bind_multi(L
, {
954 {"set", &lua_palette::set
},
955 {"hash", &lua_palette::hash
},
956 {"debug", &lua_palette::debug
},
957 {"adjust_transparency", &lua_palette::adjust_transparency
},
961 lua_palette::~lua_palette()
965 std::string
lua_palette::print()
967 size_t s
= colors
.size();
968 return (stringfmt() << s
<< " " << ((s
!= 1) ? "colors" : "color")).str();
971 int lua_palette::set(lua::state
& L
, const std::string
& fname
)
973 uint16_t c
= L
.get_numeric_argument
<uint16_t>(2, fname
.c_str());
974 auto nc
= lua_get_fb_color(L
, 3, fname
);
975 //The mutex lock protects only the internals of colors array.
976 if(this->colors
.size() <= c
) {
977 this->palette_mutex
.lock();
978 this->colors
.resize(static_cast<uint32_t>(c
) + 1);
979 this->palette_mutex
.unlock();
981 this->colors
[c
] = nc
;
985 int lua_palette::hash(lua::state
& L
, const std::string
& fname
)
988 const int buffersize
= 256;
990 char buf
[buffersize
];
991 unsigned realsize
= 0;
992 for(unsigned i
= 0; i
< this->colors
.size(); i
++)
993 if(this->colors
[i
].origa
) realsize
= i
+ 1;
994 for(unsigned i
= 0; i
< realsize
; i
++) {
995 if(bufferuse
+ 6 > buffersize
) {
996 h
.write(buf
, bufferuse
);
999 serialization::u32b(buf
+ bufferuse
+ 0, this->colors
[i
].orig
);
1000 serialization::u16b(buf
+ bufferuse
+ 4, this->colors
[i
].origa
);
1003 if(bufferuse
> 0) h
.write(buf
, bufferuse
);
1004 L
.pushlstring(h
.read());
1008 int lua_palette::debug(lua::state
& L
, const std::string
& fname
)
1011 for(auto c
: this->colors
)
1012 messages
<< "Color #" << (i
++) << ": " << c
.orig
<< ":" << c
.origa
<< std::endl
;
1016 int lua_palette::adjust_transparency(lua::state
& L
, const std::string
& fname
)
1018 uint16_t tadj
= L
.get_numeric_argument
<uint16_t>(2, fname
.c_str());
1019 for(auto& c
: this->colors
)
1020 c
= tadjust(c
, tadj
);
1025 lua_bitmap::lua_bitmap(lua::state
& L
, uint32_t w
, uint32_t h
)
1027 lua::objclass
<lua_bitmap
>().bind_multi(L
, {
1028 {"draw", &lua_bitmap::draw
},
1029 {"pset", &lua_bitmap::pset
},
1030 {"pget", &lua_bitmap::pget
},
1031 {"size", &lua_bitmap::size
},
1032 {"hash", &lua_bitmap::hash
},
1033 {"blit", &lua_bitmap::blit
<false, false>},
1034 {"blit_priority", &lua_bitmap::blit_priority
<false>},
1035 {"blit_scaled", &lua_bitmap::blit
<true, false>},
1036 {"blit_scaled_priority", &lua_bitmap::blit_priority
<true>},
1037 {"blit_porterduff", &lua_bitmap::blit
<false, true>},
1038 {"blit_scaled_porterduff", &lua_bitmap::blit
<true, true>},
1039 {"save_png", &lua_bitmap::save_png
},
1043 pixels
.resize(width
* height
);
1044 memset(&pixels
[0], 0, width
* height
);
1047 lua_bitmap::~lua_bitmap()
1049 render_kill_request(this);
1052 std::string
lua_bitmap::print()
1054 return (stringfmt() << width
<< "*" << height
).str();
1057 int lua_bitmap::draw(lua::state
& L
, const std::string
& fname
)
1059 return _draw(L
, fname
, true);
1062 int lua_bitmap::_draw(lua::state
& L
, const std::string
& fname
, bool is_method
)
1066 int arg_x
= is_method
? 2 : 1;
1067 int arg_y
= arg_x
+ 1;
1068 int arg_b
= is_method
? 1 : 3;
1069 int32_t x
= L
.get_numeric_argument
<int32_t>(arg_x
, fname
.c_str());
1070 int32_t y
= L
.get_numeric_argument
<int32_t>(arg_y
, fname
.c_str());
1071 auto b
= lua::_class
<lua_bitmap
>::pin(L
, arg_b
, fname
.c_str());
1072 auto p
= lua::_class
<lua_palette
>::pin(L
, 4, fname
.c_str());
1073 lua_render_ctx
->queue
->create_add
<render_object_bitmap
>(x
, y
, b
, p
);
1077 int lua_bitmap::pset(lua::state
& L
, const std::string
& fname
)
1079 uint32_t x
= L
.get_numeric_argument
<uint32_t>(2, fname
.c_str());
1080 uint32_t y
= L
.get_numeric_argument
<uint32_t>(3, fname
.c_str());
1081 uint16_t c
= L
.get_numeric_argument
<uint16_t>(4, fname
.c_str());
1082 if(x
>= this->width
|| y
>= this->height
)
1084 this->pixels
[y
* this->width
+ x
] = c
;
1088 int lua_bitmap::pget(lua::state
& L
, const std::string
& fname
)
1090 uint32_t x
= L
.get_numeric_argument
<uint32_t>(2, fname
.c_str());
1091 uint32_t y
= L
.get_numeric_argument
<uint32_t>(3, fname
.c_str());
1092 if(x
>= this->width
|| y
>= this->height
)
1094 L
.pushnumber(this->pixels
[y
* this->width
+ x
]);
1098 int lua_bitmap::size(lua::state
& L
, const std::string
& fname
)
1100 L
.pushnumber(this->width
);
1101 L
.pushnumber(this->height
);
1105 int lua_bitmap::hash(lua::state
& L
, const std::string
& fname
)
1108 const int buffersize
= 256;
1110 char buf
[buffersize
];
1111 memset(buf
, 0, buffersize
);
1112 serialization::u64b(buf
+ 0, this->width
);
1113 serialization::u64b(buf
+ 8, this->height
);
1115 for(unsigned i
= 0; i
< this->width
* this->height
; i
++) {
1116 if(bufferuse
+ 2 > buffersize
) {
1117 h
.write(buf
, bufferuse
);
1120 serialization::u16b(buf
+ bufferuse
+ 0, this->pixels
[i
]);
1123 if(bufferuse
> 0) h
.write(buf
, bufferuse
);
1124 L
.pushlstring(h
.read());
1128 template<bool scaled
, bool porterduff
> int lua_bitmap::blit(lua::state
& L
, const std::string
& fname
)
1130 uint32_t dx
= L
.get_numeric_argument
<uint32_t>(2, fname
.c_str());
1131 uint32_t dy
= L
.get_numeric_argument
<uint32_t>(3, fname
.c_str());
1132 bool src_d
= lua::_class
<lua_dbitmap
>::is(L
, 4);
1133 bool src_p
= lua::_class
<lua_bitmap
>::is(L
, 4);
1134 if(!src_d
&& !src_p
)
1135 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 4 for " + fname
);
1136 uint32_t sx
= L
.get_numeric_argument
<uint32_t>(5, fname
.c_str());
1137 uint32_t sy
= L
.get_numeric_argument
<uint32_t>(6, fname
.c_str());
1138 uint32_t w
= L
.get_numeric_argument
<uint32_t>(7, fname
.c_str());
1139 uint32_t h
= L
.get_numeric_argument
<uint32_t>(8, fname
.c_str());
1140 uint32_t hscl
, vscl
;
1142 hscl
= L
.get_numeric_argument
<uint32_t>(9, fname
.c_str());
1144 L
.get_numeric_argument
<uint32_t>(10, vscl
, fname
.c_str());
1147 porterduff_oper pd_oper
;
1149 std::string oper
= L
.get_string(scaled
? 11 : 9, fname
.c_str());
1150 pd_oper
= get_pd_oper(oper
);
1152 L
.get_numeric_argument
<int64_t>(scaled
? 11 : 9, ck
, fname
.c_str());
1154 lua_bitmap
* sb
= lua::_class
<lua_bitmap
>::get(L
, 4, fname
.c_str());
1156 xblit_pduff
<scaled
>(operand_bitmap(*this), operand_bitmap(*sb
), dx
, dy
, sx
, sy
, w
, h
,
1157 hscl
, vscl
, pd_oper
);
1159 xblit_pal
<scaled
>(operand_bitmap(*this), operand_bitmap(*sb
), ck
, dx
, dy
, sx
, sy
, w
, h
,
1162 throw std::runtime_error("If parameter 1 to " + fname
+ " is paletted, parameter 4 must be "
1167 template<bool scaled
> int lua_bitmap::blit_priority(lua::state
& L
, const std::string
& fname
)
1169 uint32_t dx
= L
.get_numeric_argument
<uint32_t>(2, fname
.c_str());
1170 uint32_t dy
= L
.get_numeric_argument
<uint32_t>(3, fname
.c_str());
1171 lua_bitmap
* sb
= lua::_class
<lua_bitmap
>::get(L
, 4, fname
.c_str());
1172 uint32_t sx
= L
.get_numeric_argument
<uint32_t>(5, fname
.c_str());
1173 uint32_t sy
= L
.get_numeric_argument
<uint32_t>(6, fname
.c_str());
1174 uint32_t w
= L
.get_numeric_argument
<uint32_t>(7, fname
.c_str());
1175 uint32_t h
= L
.get_numeric_argument
<uint32_t>(8, fname
.c_str());
1176 uint32_t hscl
, vscl
;
1178 hscl
= L
.get_numeric_argument
<uint32_t>(9, fname
.c_str());
1180 L
.get_numeric_argument
<uint32_t>(10, vscl
, fname
.c_str());
1182 xblit
<scaled
>(srcdest_priority(*this, *sb
), dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
1186 int lua_bitmap::save_png(lua::state
& L
, const std::string
& fname
)
1188 return _save_png(L
, fname
, true);
1191 int lua_bitmap::_save_png(lua::state
& L
, const std::string
& fname
, bool is_method
)
1193 int index
= is_method
? 2 : 1;
1195 std::string name
, name2
;
1196 if(L
.type(index
) == LUA_TSTRING
) {
1197 name
= L
.get_string(index
, fname
.c_str());
1200 if(L
.type(index
) == LUA_TSTRING
) {
1201 name2
= L
.get_string(index
, fname
.c_str());
1204 lua_palette
* p
= lua::_class
<lua_palette
>::get(L
, index
+ (is_method
? 0 : 1), fname
.c_str());
1205 auto buf
= this->save_png(*p
);
1206 if(L
.type(oindex
) == LUA_TSTRING
) {
1207 std::string filename
= zip::resolverel(name
, name2
);
1208 std::ofstream
strm(filename
, std::ios::binary
);
1210 throw std::runtime_error("Can't open output file");
1211 strm
.write(&buf
[0], buf
.size());
1213 throw std::runtime_error("Can't write output file");
1216 std::ostringstream strm
;
1217 strm
.write(&buf
[0], buf
.size());
1218 L
.pushlstring(base64_encode(strm
.str()));
1224 lua_dbitmap::lua_dbitmap(lua::state
& L
, uint32_t w
, uint32_t h
)
1226 lua::objclass
<lua_dbitmap
>().bind_multi(L
, {
1227 {"draw", &lua_dbitmap::draw
},
1228 {"pset", &lua_dbitmap::pset
},
1229 {"pget", &lua_dbitmap::pget
},
1230 {"size", &lua_dbitmap::size
},
1231 {"hash", &lua_dbitmap::hash
},
1232 {"blit", &lua_dbitmap::blit
<false, false>},
1233 {"blit_scaled", &lua_dbitmap::blit
<true, false>},
1234 {"blit_porterduff", &lua_dbitmap::blit
<false, true>},
1235 {"blit_scaled_porterduff", &lua_dbitmap::blit
<true, true>},
1236 {"save_png", &lua_dbitmap::save_png
},
1237 {"adjust_transparency", &lua_dbitmap::adjust_transparency
},
1241 pixels
.resize(width
* height
);
1244 lua_dbitmap::~lua_dbitmap()
1246 render_kill_request(this);
1249 std::string
lua_dbitmap::print()
1251 return (stringfmt() << width
<< "*" << height
).str();
1254 int lua_dbitmap::draw(lua::state
& L
, const std::string
& fname
)
1256 return _draw(L
, fname
, true);
1259 int lua_dbitmap::_draw(lua::state
& L
, const std::string
& fname
, bool is_method
)
1263 int arg_x
= is_method
? 2 : 1;
1264 int arg_y
= arg_x
+ 1;
1265 int arg_b
= is_method
? 1 : 3;
1266 int32_t x
= L
.get_numeric_argument
<int32_t>(arg_x
, fname
.c_str());
1267 int32_t y
= L
.get_numeric_argument
<int32_t>(arg_y
, fname
.c_str());
1268 auto b
= lua::_class
<lua_dbitmap
>::pin(L
, arg_b
, fname
.c_str());
1269 lua_render_ctx
->queue
->create_add
<render_object_bitmap
>(x
, y
, b
);
1273 int lua_dbitmap::pset(lua::state
& L
, const std::string
& fname
)
1275 uint32_t x
= L
.get_numeric_argument
<uint32_t>(2, fname
.c_str());
1276 uint32_t y
= L
.get_numeric_argument
<uint32_t>(3, fname
.c_str());
1277 auto c
= lua_get_fb_color(L
, 4, fname
);
1278 if(x
>= this->width
|| y
>= this->height
)
1280 this->pixels
[y
* this->width
+ x
] = c
;
1284 int lua_dbitmap::pget(lua::state
& L
, const std::string
& fname
)
1286 uint32_t x
= L
.get_numeric_argument
<uint32_t>(2, fname
.c_str());
1287 uint32_t y
= L
.get_numeric_argument
<uint32_t>(3, fname
.c_str());
1288 if(x
>= this->width
|| y
>= this->height
)
1290 L
.pushnumber((this->pixels
[y
* this->width
+ x
]).asnumber());
1294 int lua_dbitmap::size(lua::state
& L
, const std::string
& fname
)
1296 L
.pushnumber(this->width
);
1297 L
.pushnumber(this->height
);
1301 int lua_dbitmap::hash(lua::state
& L
, const std::string
& fname
)
1304 const int buffersize
= 256;
1306 char buf
[buffersize
];
1307 memset(buf
, 0, buffersize
);
1308 serialization::u64b(buf
+ 0, this->width
);
1309 serialization::u64b(buf
+ 4, this->height
);
1311 for(unsigned i
= 0; i
< this->width
* this->height
; i
++) {
1312 if(bufferuse
+ 6 > buffersize
) {
1313 h
.write(buf
, bufferuse
);
1316 serialization::u32b(buf
+ bufferuse
+ 0, this->pixels
[i
].orig
);
1317 serialization::u16b(buf
+ bufferuse
+ 4, this->pixels
[i
].origa
);
1320 if(bufferuse
> 0) h
.write(buf
, bufferuse
);
1321 L
.pushlstring(h
.read());
1325 template<bool scaled
, bool porterduff
> int lua_dbitmap::blit(lua::state
& L
, const std::string
& fname
)
1327 lua::parameters
P(L
, fname
);
1329 auto dx
= P
.arg
<uint32_t>();
1330 auto dy
= P
.arg
<uint32_t>();
1331 bool src_d
= P
.is
<lua_dbitmap
>();
1332 bool src_p
= P
.is
<lua_bitmap
>();
1333 int sidx
= P
.skip();
1334 if(!src_d
&& !src_p
)
1335 P
.expected("BITMAP or DBITMAP", sidx
);
1338 spal
= P
.skip(); //Reserve for palette.
1339 auto sx
= P
.arg
<uint32_t>();
1340 auto sy
= P
.arg
<uint32_t>();
1341 auto w
= P
.arg
<uint32_t>();
1342 auto h
= P
.arg
<uint32_t>();
1343 uint32_t hscl
, vscl
;
1345 hscl
= P
.arg_opt
<uint32_t>(1);
1346 vscl
= P
.arg_opt
<uint32_t>(hscl
);
1348 int64_t ckx
= 0x100000000ULL
;
1349 porterduff_oper pd_oper
;
1351 pd_oper
= get_pd_oper(P
.arg
<std::string
>());
1353 //Hack: Direct-color bitmaps should take color spec, with special NONE value.
1355 ckx
= P
.arg_opt
<int64_t>(0x10000);
1356 else if(P
.is_novalue())
1359 ckx
= P
.color(0).asnumber();
1362 operand_dbitmap
dest(*this);
1364 operand_dbitmap
src(*P
.arg
<lua_dbitmap
*>(sidx
));
1366 xblit_pduff
<scaled
>(dest
, src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
, pd_oper
);
1368 xblit_dir
<scaled
>(dest
, src
, ckx
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
1370 operand_bitmap_pal
src(*P
.arg
<lua_bitmap
*>(sidx
), *P
.arg
<lua_palette
*>(spal
));
1372 xblit_pduff
<scaled
>(dest
, src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
, pd_oper
);
1374 xblit_pal
<scaled
>(dest
, src
, ckx
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
1379 int lua_dbitmap::save_png(lua::state
& L
, const std::string
& fname
)
1381 return _save_png(L
, fname
, true);
1384 int lua_dbitmap::_save_png(lua::state
& L
, const std::string
& fname
, bool is_method
)
1386 int index
= is_method
? 2 : 1;
1387 std::string name
, name2
;
1388 if(L
.type(index
) == LUA_TSTRING
)
1389 name
= L
.get_string(index
, fname
.c_str());
1390 if(L
.type(index
+ 1) == LUA_TSTRING
)
1391 name2
= L
.get_string(index
+ 1, fname
.c_str());
1392 auto buf
= this->save_png();
1393 if(L
.type(index
) == LUA_TSTRING
) {
1394 std::string filename
= zip::resolverel(name
, name2
);
1395 std::ofstream
strm(filename
, std::ios::binary
);
1397 throw std::runtime_error("Can't open output file");
1398 strm
.write(&buf
[0], buf
.size());
1400 throw std::runtime_error("Can't write output file");
1403 std::ostringstream strm
;
1404 strm
.write(&buf
[0], buf
.size());
1405 L
.pushlstring(base64_encode(strm
.str()));
1410 int lua_dbitmap::adjust_transparency(lua::state
& L
, const std::string
& fname
)
1412 uint16_t tadj
= L
.get_numeric_argument
<uint16_t>(2, fname
.c_str());
1413 for(auto& c
: this->pixels
)
1414 c
= tadjust(c
, tadj
);