1 #include "lua/internal.hpp"
2 #include "core/framebuffer.hpp"
3 #include "library/framebuffer.hpp"
4 #include "library/png-codec.hpp"
5 #include "library/sha256.hpp"
6 #include "library/serialization.hpp"
7 #include "library/string.hpp"
8 #include "library/zip.hpp"
9 #include "lua/bitmap.hpp"
10 #include "library/threadtypes.hpp"
14 lua_bitmap::lua_bitmap(lua_state
& L
, uint32_t w
, uint32_t h
)
18 pixels
.resize(width
* height
);
19 memset(&pixels
[0], 0, width
* height
);
22 lua_bitmap::~lua_bitmap()
24 render_kill_request(this);
27 std::string
lua_bitmap::print()
29 return (stringfmt() << width
<< "*" << height
).str();
32 lua_dbitmap::lua_dbitmap(lua_state
& L
, uint32_t w
, uint32_t h
)
36 pixels
.resize(width
* height
);
39 lua_dbitmap::~lua_dbitmap()
41 render_kill_request(this);
44 std::string
lua_dbitmap::print()
46 return (stringfmt() << width
<< "*" << height
).str();
49 lua_palette::lua_palette(lua_state
& L
)
53 lua_palette::~lua_palette()
57 std::string
lua_palette::print()
59 size_t s
= colors
.size();
60 return (stringfmt() << s
<< " " << ((s
!= 1) ? "colors" : "color")).str();
63 std::vector
<char> lua_dbitmap::save_png() const
65 png_encodedable_image img
;
68 img
.has_palette
= false;
69 img
.has_alpha
= false;
70 img
.data
.resize(width
* height
);
71 for(size_t i
= 0; i
< width
* height
; i
++) {
72 const framebuffer::color
& c
= pixels
[i
];
75 img
.data
[i
] = c
.orig
+ ((uint32_t)(c
.origa
- (c
.origa
>> 7) + (c
.origa
>> 8)) << 24);
77 std::ostringstream tmp1
;
79 std::string tmp2
= tmp1
.str();
80 return std::vector
<char>(tmp2
.begin(), tmp2
.end());
83 std::vector
<char> lua_bitmap::save_png(const lua_palette
& pal
) const
85 png_encodedable_image img
;
88 img
.has_palette
= true;
89 img
.has_alpha
= false;
90 img
.data
.resize(width
* height
);
91 img
.palette
.resize(pal
.colors
.size());
92 for(size_t i
= 0; i
< width
* height
; i
++) {
93 img
.data
[i
] = pixels
[i
];
95 for(size_t i
= 0; i
< pal
.colors
.size(); i
++) {
96 const framebuffer::color
& c
= pal
.colors
[i
];
99 img
.palette
[i
] = c
.orig
+ ((uint32_t)(c
.origa
- (c
.origa
>> 7) + (c
.origa
>> 8)) << 24);
101 std::ostringstream tmp1
;
103 std::string tmp2
= tmp1
.str();
104 return std::vector
<char>(tmp2
.begin(), tmp2
.end());
109 const char* base64chars
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
111 struct render_object_bitmap
: public framebuffer::object
113 render_object_bitmap(int32_t _x
, int32_t _y
, lua_obj_pin
<lua_bitmap
> _bitmap
,
114 lua_obj_pin
<lua_palette
> _palette
) throw()
122 render_object_bitmap(int32_t _x
, int32_t _y
, lua_obj_pin
<lua_dbitmap
> _bitmap
) throw()
129 ~render_object_bitmap() throw()
133 bool kill_request(void* obj
) throw()
135 return kill_request_ifeq(p
.object(), obj
) ||
136 kill_request_ifeq(b
.object(), obj
) ||
137 kill_request_ifeq(b2
.object(), obj
);
140 template<bool T
> void composite_op(struct framebuffer::fb
<T
>& scr
) throw()
143 p
->palette_mutex
.lock();
144 uint32_t originx
= scr
.get_origin_x();
145 uint32_t originy
= scr
.get_origin_y();
148 framebuffer::color
* palette
;
150 palette
= &p
->colors
[0];
151 for(auto& c
: p
->colors
)
153 pallim
= p
->colors
.size();
157 for(auto& c
: b2
->pixels
)
167 framebuffer::clip_range(originx
, scr
.get_width(), x
, xmin
, xmax
);
168 framebuffer::clip_range(originy
, scr
.get_height(), y
, ymin
, ymax
);
169 for(int32_t r
= ymin
; r
< ymax
; r
++) {
170 typename
framebuffer::fb
<T
>::element_t
* rptr
= scr
.rowptr(y
+ r
+ originy
);
171 size_t eptr
= x
+ xmin
+ originx
;
173 for(int32_t c
= xmin
; c
< xmax
; c
++, eptr
++) {
174 uint16_t i
= b
->pixels
[r
* b
->width
+ c
];
176 palette
[i
].apply(rptr
[eptr
]);
179 for(int32_t c
= xmin
; c
< xmax
; c
++, eptr
++)
180 b2
->pixels
[r
* b2
->width
+ c
].apply(rptr
[eptr
]);
183 p
->palette_mutex
.unlock();
185 void operator()(struct framebuffer::fb
<false>& x
) throw() { composite_op(x
); }
186 void operator()(struct framebuffer::fb
<true>& x
) throw() { composite_op(x
); }
187 void clone(framebuffer::queue
& q
) const throw(std::bad_alloc
) { q
.clone_helper(this); }
191 lua_obj_pin
<lua_bitmap
> b
;
192 lua_obj_pin
<lua_dbitmap
> b2
;
193 lua_obj_pin
<lua_palette
> p
;
196 function_ptr_luafun
gui_bitmap(lua_func_misc
, "gui.bitmap_draw", [](lua_state
& L
, const std::string
& fname
)
200 int32_t x
= L
.get_numeric_argument
<int32_t>(1, fname
.c_str());
201 int32_t y
= L
.get_numeric_argument
<int32_t>(2, fname
.c_str());
202 if(lua_class
<lua_bitmap
>::is(L
, 3)) {
203 lua_class
<lua_bitmap
>::get(L
, 3, fname
.c_str());
204 lua_class
<lua_palette
>::get(L
, 4, fname
.c_str());
205 auto b
= lua_class
<lua_bitmap
>::pin(L
, 3, fname
.c_str());
206 auto p
= lua_class
<lua_palette
>::pin(L
, 4, fname
.c_str());
207 lua_render_ctx
->queue
->create_add
<render_object_bitmap
>(x
, y
, b
, p
);
208 } else if(lua_class
<lua_dbitmap
>::is(L
, 3)) {
209 lua_class
<lua_dbitmap
>::get(L
, 3, fname
.c_str());
210 auto b
= lua_class
<lua_dbitmap
>::pin(L
, 3, fname
.c_str());
211 lua_render_ctx
->queue
->create_add
<render_object_bitmap
>(x
, y
, b
);
213 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 3 for gui.bitmap_draw.");
217 function_ptr_luafun
gui_cpalette(lua_func_misc
, "gui.palette_new", [](lua_state
& L
, const std::string
& fname
)
219 lua_class
<lua_palette
>::create(L
);
223 function_ptr_luafun
gui_cbitmap(lua_func_misc
, "gui.bitmap_new", [](lua_state
& L
, const std::string
& fname
)
225 uint32_t w
= L
.get_numeric_argument
<uint32_t>(1, fname
.c_str());
226 uint32_t h
= L
.get_numeric_argument
<uint32_t>(2, fname
.c_str());
227 bool d
= L
.get_bool(3, fname
.c_str());
230 L
.get_numeric_argument
<int64_t>(4, c
, fname
.c_str());
231 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::create(L
, w
, h
);
232 for(size_t i
= 0; i
< b
->width
* b
->height
; i
++)
233 b
->pixels
[i
] = framebuffer::color(c
);
236 L
.get_numeric_argument
<uint16_t>(4, c
, fname
.c_str());
237 lua_bitmap
* b
= lua_class
<lua_bitmap
>::create(L
, w
, h
);
238 for(size_t i
= 0; i
< b
->width
* b
->height
; i
++)
244 function_ptr_luafun
gui_epalette(lua_func_misc
, "gui.palette_set", [](lua_state
& L
, const std::string
& fname
)
246 lua_palette
* p
= lua_class
<lua_palette
>::get(L
, 1, fname
.c_str());
247 uint16_t c
= L
.get_numeric_argument
<uint16_t>(2, fname
.c_str());
248 int64_t nval
= L
.get_numeric_argument
<int64_t>(3, fname
.c_str());
249 framebuffer::color
nc(nval
);
250 //The mutex lock protects only the internals of colors array.
251 if(p
->colors
.size() <= c
) {
252 p
->palette_mutex
.lock();
253 p
->colors
.resize(static_cast<uint32_t>(c
) + 1);
254 p
->palette_mutex
.unlock();
260 function_ptr_luafun
pset_bitmap(lua_func_misc
, "gui.bitmap_pset", [](lua_state
& L
, const std::string
& fname
)
262 uint32_t x
= L
.get_numeric_argument
<uint32_t>(2, fname
.c_str());
263 uint32_t y
= L
.get_numeric_argument
<uint32_t>(3, fname
.c_str());
264 if(lua_class
<lua_bitmap
>::is(L
, 1)) {
265 lua_bitmap
* b
= lua_class
<lua_bitmap
>::get(L
, 1, fname
.c_str());
266 uint16_t c
= L
.get_numeric_argument
<uint16_t>(4, fname
.c_str());
267 if(x
>= b
->width
|| y
>= b
->height
)
269 b
->pixels
[y
* b
->width
+ x
] = c
;
270 } else if(lua_class
<lua_dbitmap
>::is(L
, 1)) {
271 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str());
272 int64_t c
= L
.get_numeric_argument
<int64_t>(4, fname
.c_str());
273 if(x
>= b
->width
|| y
>= b
->height
)
275 b
->pixels
[y
* b
->width
+ x
] = framebuffer::color(c
);
277 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for gui.bitmap_pset.");
281 inline int64_t demultiply_color(const framebuffer::color
& c
)
286 return c
.orig
| ((uint32_t)(256 - c
.origa
) << 24);
289 function_ptr_luafun
pget_bitmap(lua_func_misc
, "gui.bitmap_pget", [](lua_state
& L
, const std::string
& fname
)
291 uint32_t x
= L
.get_numeric_argument
<uint32_t>(2, fname
.c_str());
292 uint32_t y
= L
.get_numeric_argument
<uint32_t>(3, fname
.c_str());
293 if(lua_class
<lua_bitmap
>::is(L
, 1)) {
294 lua_bitmap
* b
= lua_class
<lua_bitmap
>::get(L
, 1, fname
.c_str());
295 if(x
>= b
->width
|| y
>= b
->height
)
297 L
.pushnumber(b
->pixels
[y
* b
->width
+ x
]);
298 } else if(lua_class
<lua_dbitmap
>::is(L
, 1)) {
299 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str());
300 if(x
>= b
->width
|| y
>= b
->height
)
302 L
.pushnumber(demultiply_color(b
->pixels
[y
* b
->width
+ x
]));
304 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for gui.bitmap_pget.");
308 function_ptr_luafun
size_bitmap(lua_func_misc
, "gui.bitmap_size", [](lua_state
& L
, const std::string
& fname
)
310 if(lua_class
<lua_bitmap
>::is(L
, 1)) {
311 lua_bitmap
* b
= lua_class
<lua_bitmap
>::get(L
, 1, fname
.c_str());
312 L
.pushnumber(b
->width
);
313 L
.pushnumber(b
->height
);
314 } else if(lua_class
<lua_dbitmap
>::is(L
, 1)) {
315 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str());
316 L
.pushnumber(b
->width
);
317 L
.pushnumber(b
->height
);
319 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for gui.bitmap_size.");
323 function_ptr_luafun
hash_bitmap(lua_func_misc
, "gui.bitmap_hash", [](lua_state
& L
, const std::string
& fname
)
326 const int buffersize
= 256;
328 char buf
[buffersize
];
329 memset(buf
, 0, buffersize
);
330 if(lua_class
<lua_bitmap
>::is(L
, 1)) {
331 lua_bitmap
* b
= lua_class
<lua_bitmap
>::get(L
, 1, fname
.c_str());
332 serialization::u64b(buf
+ 0, b
->width
);
333 serialization::u64b(buf
+ 8, b
->height
);
335 for(unsigned i
= 0; i
< b
->width
* b
->height
; i
++) {
336 if(bufferuse
+ 2 > buffersize
) {
337 h
.write(buf
, bufferuse
);
340 serialization::u16b(buf
+ bufferuse
+ 0, b
->pixels
[i
]);
343 if(bufferuse
> 0) h
.write(buf
, bufferuse
);
344 L
.pushlstring(h
.read());
346 } else if(lua_class
<lua_dbitmap
>::is(L
, 1)) {
347 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str());
348 serialization::u64b(buf
+ 0, b
->width
);
349 serialization::u64b(buf
+ 4, b
->height
);
351 for(unsigned i
= 0; i
< b
->width
* b
->height
; i
++) {
352 if(bufferuse
+ 6 > buffersize
) {
353 h
.write(buf
, bufferuse
);
356 serialization::u32b(buf
+ bufferuse
+ 0, b
->pixels
[i
].orig
);
357 serialization::u16b(buf
+ bufferuse
+ 4, b
->pixels
[i
].origa
);
360 if(bufferuse
> 0) h
.write(buf
, bufferuse
);
361 L
.pushlstring(h
.read());
364 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for gui.bitmap_hash.");
367 function_ptr_luafun
hash_palette(lua_func_misc
, "gui.palette_hash", [](lua_state
& L
, const std::string
& fname
)
369 lua_palette
* p
= lua_class
<lua_palette
>::get(L
, 1, fname
.c_str());
371 const int buffersize
= 256;
373 char buf
[buffersize
];
374 unsigned realsize
= 0;
375 for(unsigned i
= 0; i
< p
->colors
.size(); i
++)
376 if(p
->colors
[i
].origa
) realsize
= i
+ 1;
377 for(unsigned i
= 0; i
< realsize
; i
++) {
378 if(bufferuse
+ 6 > buffersize
) {
379 h
.write(buf
, bufferuse
);
382 serialization::u32b(buf
+ bufferuse
+ 0, p
->colors
[i
].orig
);
383 serialization::u16b(buf
+ bufferuse
+ 4, p
->colors
[i
].origa
);
386 if(bufferuse
> 0) h
.write(buf
, bufferuse
);
387 L
.pushlstring(h
.read());
393 bool iskey(uint16_t& c
) const { return false; }
394 bool iskey(framebuffer::color
& c
) const { return false; }
397 struct colorkey_direct
399 colorkey_direct(uint64_t _ck
)
401 framebuffer::color
c(_ck
);
405 bool iskey(framebuffer::color
& c
) const { return (c
.orig
== ck
&& c
.origa
== cka
); }
410 struct colorkey_palette
412 colorkey_palette(uint64_t _ck
) { ck
= _ck
; }
413 bool iskey(uint16_t& c
) const { return (c
== ck
); }
417 template<class colorkey
> struct srcdest_direct
419 srcdest_direct(lua_dbitmap
& dest
, lua_dbitmap
& src
, const colorkey
& _ckey
)
422 darray
= &dest
.pixels
[0];
423 sarray
= &src
.pixels
[0];
425 sheight
= src
.height
;
427 dheight
= dest
.height
;
429 void copy(size_t didx
, size_t sidx
)
431 framebuffer::color c
= sarray
[sidx
];
435 size_t swidth
, sheight
, dwidth
, dheight
;
437 framebuffer::color
* sarray
;
438 framebuffer::color
* darray
;
439 const colorkey
& ckey
;
442 template<class colorkey
> struct srcdest_palette
444 srcdest_palette(lua_bitmap
& dest
, lua_bitmap
& src
, const colorkey
& _ckey
)
447 darray
= &dest
.pixels
[0];
448 sarray
= &src
.pixels
[0];
450 sheight
= src
.height
;
452 dheight
= dest
.height
;
454 void copy(size_t didx
, size_t sidx
)
456 uint16_t c
= sarray
[sidx
];
460 size_t swidth
, sheight
, dwidth
, dheight
;
464 const colorkey
& ckey
;
467 template<class colorkey
> struct srcdest_paletted
469 typedef framebuffer::color ptype
;
470 srcdest_paletted(lua_dbitmap
& dest
, lua_bitmap
& src
, lua_palette
& palette
, const colorkey
& _ckey
)
471 : ckey(_ckey
), transparent(-1)
473 darray
= &dest
.pixels
[0];
474 sarray
= &src
.pixels
[0];
475 limit
= palette
.colors
.size();
476 pal
= &palette
.colors
[0];
478 sheight
= src
.height
;
480 dheight
= dest
.height
;
482 void copy(size_t didx
, size_t sidx
)
484 uint16_t c
= sarray
[sidx
];
486 darray
[didx
] = (c
< limit
) ? pal
[c
] : transparent
;
488 size_t swidth
, sheight
, dwidth
, dheight
;
491 framebuffer::color
* darray
;
492 framebuffer::color
* pal
;
494 framebuffer::color transparent
;
495 const colorkey
& ckey
;
498 template<class srcdest
>
499 void blit(srcdest sd
, uint32_t dx
, uint32_t dy
, uint32_t sx
, uint32_t sy
, uint32_t w
, uint32_t h
)
501 while((dx
+ w
> sd
.dwidth
|| sx
+ w
> sd
.swidth
) && w
> 0)
503 while((dy
+ h
> sd
.dheight
|| sy
+ h
> sd
.sheight
) && h
> 0)
505 size_t sidx
= sy
* sd
.swidth
+ sx
;
506 size_t didx
= dy
* sd
.dwidth
+ dx
;
507 size_t srskip
= sd
.swidth
- w
;
508 size_t drskip
= sd
.dwidth
- w
;
509 for(uint32_t j
= 0; j
< h
; j
++) {
510 for(uint32_t i
= 0; i
< w
; i
++) {
520 function_ptr_luafun
blit_bitmap(lua_func_misc
, "gui.bitmap_blit", [](lua_state
& L
, const std::string
& fname
)
525 bool dst_d
= lua_class
<lua_dbitmap
>::is(L
, dsts
= slot
);
526 bool dst_p
= lua_class
<lua_bitmap
>::is(L
, slot
++);
528 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 1 for gui.bitmap_blit");
529 uint32_t dx
= L
.get_numeric_argument
<uint32_t>(slot
++, fname
.c_str());
530 uint32_t dy
= L
.get_numeric_argument
<uint32_t>(slot
++, fname
.c_str());
531 bool src_d
= lua_class
<lua_dbitmap
>::is(L
, srcs
= slot
);
532 bool src_p
= lua_class
<lua_bitmap
>::is(L
, slot
++);
534 throw std::runtime_error("Expected BITMAP or DBITMAP as argument 4 for gui.bitmap_blit");
536 slot
++; //Reserve slot 5 for palette.
537 uint32_t sx
= L
.get_numeric_argument
<uint32_t>(slot
++, fname
.c_str());
538 uint32_t sy
= L
.get_numeric_argument
<uint32_t>(slot
++, fname
.c_str());
539 uint32_t w
= L
.get_numeric_argument
<uint32_t>(slot
++, fname
.c_str());
540 uint32_t h
= L
.get_numeric_argument
<uint32_t>(slot
++, fname
.c_str());
541 int64_t ck
= 0x100000000ULL
;
542 L
.get_numeric_argument
<int64_t>(slot
++, ck
, fname
.c_str());
545 lua_dbitmap
* db
= lua_class
<lua_dbitmap
>::get(L
, dsts
, fname
.c_str());
546 lua_dbitmap
* sb
= lua_class
<lua_dbitmap
>::get(L
, srcs
, fname
.c_str());
547 if(ck
== 0x100000000ULL
)
548 blit(srcdest_direct
<colorkey_none
>(*db
, *sb
, colorkey_none()), dx
, dy
, sx
, sy
, w
, h
);
550 blit(srcdest_direct
<colorkey_direct
>(*db
, *sb
, colorkey_direct(ck
)), dx
, dy
, sx
, sy
, w
,
552 } else if(dst_p
&& src_p
) {
553 lua_bitmap
* db
= lua_class
<lua_bitmap
>::get(L
, dsts
, fname
.c_str());
554 lua_bitmap
* sb
= lua_class
<lua_bitmap
>::get(L
, srcs
, fname
.c_str());
556 blit(srcdest_palette
<colorkey_none
>(*db
, *sb
, colorkey_none()), dx
, dy
, sx
, sy
, w
, h
);
558 blit(srcdest_palette
<colorkey_palette
>(*db
, *sb
, colorkey_palette(ck
)), dx
, dy
, sx
, sy
,
560 } else if(dst_d
&& src_p
) {
561 lua_dbitmap
* db
= lua_class
<lua_dbitmap
>::get(L
, dsts
, fname
.c_str());
562 lua_bitmap
* sb
= lua_class
<lua_bitmap
>::get(L
, srcs
, fname
.c_str());
563 lua_palette
* pal
= lua_class
<lua_palette
>::get(L
, srcs
+ 1, fname
.c_str());
565 blit(srcdest_paletted
<colorkey_none
>(*db
, *sb
, *pal
, colorkey_none()), dx
, dy
, sx
, sy
,
568 blit(srcdest_paletted
<colorkey_palette
>(*db
, *sb
, *pal
, colorkey_palette(ck
)), dx
, dy
,
571 throw std::runtime_error("If parameter 1 to gui.bitmap_blit is paletted, parameter 4 must be "
576 int bitmap_load_fn(lua_state
& L
, std::function
<lua_loaded_bitmap()> src
)
581 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::create(L
, bitmap
.w
, bitmap
.h
);
582 for(size_t i
= 0; i
< bitmap
.w
* bitmap
.h
; i
++)
583 b
->pixels
[i
] = framebuffer::color(bitmap
.bitmap
[i
]);
586 lua_bitmap
* b
= lua_class
<lua_bitmap
>::create(L
, bitmap
.w
, bitmap
.h
);
587 lua_palette
* p
= lua_class
<lua_palette
>::create(L
);
588 for(size_t i
= 0; i
< bitmap
.w
* bitmap
.h
; i
++)
589 b
->pixels
[i
] = bitmap
.bitmap
[i
];
590 p
->colors
.resize(bitmap
.palette
.size());
591 for(size_t i
= 0; i
< bitmap
.palette
.size(); i
++)
592 p
->colors
[i
] = framebuffer::color(bitmap
.palette
[i
]);
597 function_ptr_luafun
gui_loadbitmap(lua_func_misc
, "gui.bitmap_load", [](lua_state
& L
,
598 const std::string
& fname
) -> int {
600 std::string name
= L
.get_string(1, fname
.c_str());
601 if(L
.type(2) != LUA_TNIL
&& L
.type(2) != LUA_TNONE
)
602 name2
= L
.get_string(2, fname
.c_str());
603 return bitmap_load_fn(L
, [&name
, &name2
]() -> lua_loaded_bitmap
{
604 std::string name3
= zip::resolverel(name
, name2
);
605 return lua_loaded_bitmap::load(name3
);
609 function_ptr_luafun
gui_loadbitmap2(lua_func_misc
, "gui.bitmap_load_str", [](lua_state
& L
,
610 const std::string
& fname
) -> int {
611 std::string contents
= L
.get_string(1, fname
.c_str());
612 return bitmap_load_fn(L
, [&contents
]() -> lua_loaded_bitmap
{
613 std::istringstream
strm(contents
);
614 return lua_loaded_bitmap::load(strm
);
618 inline int64_t mangle_color(uint32_t c
)
623 return ((256 - (c
>> 24) - (c
>> 31)) << 24) | (c
& 0xFFFFFF);
626 int base64val(char ch
)
628 if(ch
>= 'A' && ch
<= 'Z')
630 if(ch
>= 'a' && ch
<= 'z')
632 if(ch
>= '0' && ch
<= '9')
638 if(ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n')
645 std::string
base64_encode(const std::string
& str
)
647 std::ostringstream x
;
651 mem
= (mem
<< 8) + (unsigned char)i
;
653 uint8_t c1
= (mem
>> 18) & 0x3F;
654 uint8_t c2
= (mem
>> 12) & 0x3F;
655 uint8_t c3
= (mem
>> 6) & 0x3F;
656 uint8_t c4
= mem
& 0x3F;
657 x
<< base64chars
[c1
];
658 x
<< base64chars
[c2
];
659 x
<< base64chars
[c3
];
660 x
<< base64chars
[c4
];
666 uint8_t c1
= (mem
>> 10) & 0x3F;
667 uint8_t c2
= (mem
>> 4) & 0x3F;
668 uint8_t c3
= (mem
<< 2) & 0x3F;
669 x
<< base64chars
[c1
];
670 x
<< base64chars
[c2
];
671 x
<< base64chars
[c3
];
675 uint8_t c1
= (mem
>> 2) & 0x3F;
676 uint8_t c2
= (mem
<< 4) & 0x3F;
677 x
<< base64chars
[c1
];
678 x
<< base64chars
[c2
];
684 std::string
base64_decode(const std::string
& str
)
688 uint32_t memsize
= 1;
690 std::ostringstream x
;
692 int v
= base64val(i
);
695 posmod
= (posmod
+ 1) & 3;
696 if(v
== -2 && (posmod
== 1 || posmod
== 2))
697 throw std::runtime_error("Invalid Base64");
703 throw std::runtime_error("Invalid Base64");
704 memory
= memory
* 64 + v
;
705 memsize
= memsize
* 64;
708 x
<< static_cast<uint8_t>(memory
/ memsize
);
716 int bitmap_load_png_fn(lua_state
& L
, T
& src
)
718 png_decoded_image
img(src
);
719 if(img
.has_palette
) {
720 lua_bitmap
* b
= lua_class
<lua_bitmap
>::create(L
, img
.width
, img
.height
);
721 lua_palette
* p
= lua_class
<lua_palette
>::create(L
);
722 for(size_t i
= 0; i
< img
.width
* img
.height
; i
++)
723 b
->pixels
[i
] = img
.data
[i
];
724 p
->colors
.resize(img
.palette
.size());
725 for(size_t i
= 0; i
< img
.palette
.size(); i
++)
726 p
->colors
[i
] = framebuffer::color(mangle_color(img
.palette
[i
]));
729 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::create(L
, img
.width
, img
.height
);
730 for(size_t i
= 0; i
< img
.width
* img
.height
; i
++)
731 b
->pixels
[i
] = framebuffer::color(mangle_color(img
.data
[i
]));
736 void bitmap_save_png_fn(lua_state
& L
, std::function
<void(const std::vector
<char>& buf
)> fn
, int index
,
737 const std::string
& fname
)
739 std::vector
<char> buf
;
740 if(lua_class
<lua_bitmap
>::is(L
, index
)) {
741 lua_bitmap
* b
= lua_class
<lua_bitmap
>::get(L
, index
, fname
.c_str());
742 lua_palette
* p
= lua_class
<lua_palette
>::get(L
, index
+ 1, fname
.c_str());
743 buf
= b
->save_png(*p
);
744 } else if(lua_class
<lua_dbitmap
>::is(L
, index
)) {
745 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::get(L
, index
, fname
.c_str());
748 (stringfmt() << "Expected BITMAP or DBITMAP as argument " << index
749 << " for gui.bitmap_save_png.").throwex();
754 function_ptr_luafun
gui_loadbitmappng(lua_func_misc
, "gui.bitmap_load_png", [](lua_state
& L
,
755 const std::string
& fname
) -> int {
757 std::string name
= L
.get_string(1, fname
.c_str());
758 if(L
.type(2) != LUA_TNIL
&& L
.type(2) != LUA_TNONE
)
759 name2
= L
.get_string(2, fname
.c_str());
760 std::string filename
= zip::resolverel(name
, name2
);
761 return bitmap_load_png_fn(L
, filename
);
764 function_ptr_luafun
gui_loadbitmappng2(lua_func_misc
, "gui.bitmap_load_png_str", [](lua_state
& L
,
765 const std::string
& fname
) -> int {
766 std::string contents
= base64_decode(L
.get_string(1, fname
.c_str()));
767 std::istringstream
strm(contents
);
768 return bitmap_load_png_fn(L
, strm
);
771 function_ptr_luafun
gui_savebitmappng(lua_func_misc
, "gui.bitmap_save_png", [](lua_state
& L
,
772 const std::string
& fname
) -> int {
774 std::string name
, name2
;
775 if(L
.type(index
) == LUA_TSTRING
) {
776 name
= L
.get_string(index
, fname
.c_str());
779 if(L
.type(index
) == LUA_TSTRING
) {
780 name2
= L
.get_string(index
, fname
.c_str());
784 std::string filename
= zip::resolverel(name
, name2
);
785 std::ofstream
strm(filename
, std::ios::binary
);
787 throw std::runtime_error("Can't open output file");
788 bitmap_save_png_fn(L
, [&strm
](const std::vector
<char>& x
) { strm
.write(&x
[0], x
.size()); },
791 throw std::runtime_error("Can't write output file");
794 std::ostringstream strm
;
795 bitmap_save_png_fn(L
, [&strm
](const std::vector
<char>& x
) { strm
.write(&x
[0], x
.size()); }, 1,
797 L
.pushlstring(base64_encode(strm
.str()));
802 int bitmap_palette_fn(lua_state
& L
, std::istream
& s
)
804 lua_palette
* p
= lua_class
<lua_palette
>::create(L
);
807 std::getline(s
, line
);
810 if(r
= regex("[ \t]*([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]*", line
)) {
811 int64_t cr
, cg
, cb
, ca
;
812 cr
= parse_value
<uint8_t>(r
[1]);
813 cg
= parse_value
<uint8_t>(r
[2]);
814 cb
= parse_value
<uint8_t>(r
[3]);
815 ca
= 256 - parse_value
<uint16_t>(r
[4]);
818 p
->colors
.push_back(framebuffer::color(-1));
820 p
->colors
.push_back(framebuffer::color((ca
<< 24) | (cr
<< 16)
822 } else if(r
= regex("[ \t]*([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]*", line
)) {
824 cr
= parse_value
<uint8_t>(r
[1]);
825 cg
= parse_value
<uint8_t>(r
[2]);
826 cb
= parse_value
<uint8_t>(r
[3]);
827 p
->colors
.push_back(framebuffer::color((cr
<< 16) | (cg
<< 8) | cb
));
828 } else if(regex_match("[ \t]*transparent[ \t]*", line
)) {
829 p
->colors
.push_back(framebuffer::color(-1));
830 } else if(!regex_match("[ \t]*(#.*)?", line
))
831 throw std::runtime_error("Invalid line format (" + line
+ ")");
836 function_ptr_luafun
gui_loadpalette(lua_func_misc
, "gui.bitmap_load_pal", [](lua_state
& L
,
837 const std::string
& fname
) -> int {
839 std::string name
= L
.get_string(1, fname
.c_str());
840 if(L
.type(2) != LUA_TNIL
&& L
.type(2) != LUA_TNONE
)
841 name2
= L
.get_string(2, fname
.c_str());
842 std::istream
& s
= zip::openrel(name
, name2
);
844 int r
= bitmap_palette_fn(L
, s
);
853 function_ptr_luafun
gui_loadpalette2(lua_func_misc
, "gui.bitmap_load_pal_str", [](lua_state
& L
,
854 const std::string
& fname
) -> int {
855 std::string content
= L
.get_string(1, fname
.c_str());
856 std::istringstream
s(content
);
857 return bitmap_palette_fn(L
, s
);
860 function_ptr_luafun
gui_dpalette(lua_func_misc
, "gui.palette_debug", [](lua_state
& L
,
861 const std::string
& fname
) -> int {
862 lua_palette
* p
= lua_class
<lua_palette
>::get(L
, 1, fname
.c_str());
864 for(auto c
: p
->colors
)
865 messages
<< "Color #" << (i
++) << ": " << c
.orig
<< ":" << c
.origa
<< std::endl
;
869 inline framebuffer::color
tadjust(framebuffer::color c
, uint16_t adj
)
871 uint32_t rgb
= c
.orig
;
872 uint32_t a
= c
.origa
;
877 return framebuffer::color(-1);
879 return framebuffer::color(rgb
| ((uint32_t)(256 - a
) << 24));
882 function_ptr_luafun
adjust_trans(lua_func_misc
, "gui.adjust_transparency", [](lua_state
& L
,
883 const std::string
& fname
) -> int {
884 uint16_t tadj
= L
.get_numeric_argument
<uint16_t>(2, fname
.c_str());
885 if(lua_class
<lua_dbitmap
>::is(L
, 1)) {
886 lua_dbitmap
* b
= lua_class
<lua_dbitmap
>::get(L
, 1, fname
.c_str());
887 for(auto& c
: b
->pixels
)
888 c
= tadjust(c
, tadj
);
889 } else if(lua_class
<lua_palette
>::is(L
, 1)) {
890 lua_palette
* p
= lua_class
<lua_palette
>::get(L
, 1, fname
.c_str());
891 for(auto& c
: p
->colors
)
892 c
= tadjust(c
, tadj
);
894 throw std::runtime_error("Expected BITMAP or PALETTE as argument 1 for "
895 "gui.adjust_transparency");
900 lua_class
<lua_palette
> class_palette("PALETTE");
901 lua_class
<lua_bitmap
> class_bitmap("BITMAP");
902 lua_class
<lua_dbitmap
> class_dbitmap("DBITMAP");