1 #include "lua/internal.hpp"
2 #include "core/framebuffer.hpp"
3 #include "core/instance.hpp"
4 #include "core/messages.hpp"
5 #include "core/misc.hpp"
6 #include "library/lua-framebuffer.hpp"
7 #include "library/minmax.hpp"
8 #include "library/png.hpp"
9 #include "library/sha256.hpp"
10 #include "library/serialization.hpp"
11 #include "library/string.hpp"
12 #include "library/zip.hpp"
13 #include "lua/bitmap.hpp"
14 #include "library/threads.hpp"
18 std::vector
<char> lua_dbitmap::save_png() const
23 img
.has_palette
= false;
24 img
.has_alpha
= false;
25 img
.data
.resize(width
* height
);
26 for(size_t i
= 0; i
< width
* height
; i
++) {
27 const framebuffer::color
& c
= pixels
[i
];
30 img
.data
[i
] = c
.orig
+ ((uint32_t)(c
.origa
- (c
.origa
>> 7) + (c
.origa
>> 8)) << 24);
32 std::ostringstream tmp1
;
34 std::string tmp2
= tmp1
.str();
35 return std::vector
<char>(tmp2
.begin(), tmp2
.end());
38 std::vector
<char> lua_bitmap::save_png(const lua_palette
& pal
) const
43 img
.has_palette
= true;
44 img
.has_alpha
= false;
45 img
.data
.resize(width
* height
);
46 img
.palette
.resize(pal
.color_count
);
47 for(size_t i
= 0; i
< width
* height
; i
++) {
48 img
.data
[i
] = pixels
[i
];
50 for(size_t i
= 0; i
< pal
.color_count
; i
++) {
51 const framebuffer::color
& c
= pal
.colors
[i
];
54 img
.palette
[i
] = c
.orig
+ ((uint32_t)(c
.origa
- (c
.origa
>> 7) + (c
.origa
>> 8)) << 24);
56 std::ostringstream tmp1
;
58 std::string tmp2
= tmp1
.str();
59 return std::vector
<char>(tmp2
.begin(), tmp2
.end());
64 const char* CONST_base64chars
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
66 struct render_object_bitmap
: public framebuffer::object
68 render_object_bitmap(int32_t _x
, int32_t _y
, lua::objpin
<lua_bitmap
>& _bitmap
,
69 lua::objpin
<lua_palette
>& _palette
, int32_t _x0
, int32_t _y0
, uint32_t _dw
, uint32_t _dh
,
70 bool _outside
) throw()
83 render_object_bitmap(int32_t _x
, int32_t _y
, lua::objpin
<lua_dbitmap
>& _bitmap
, int32_t _x0
,
84 int32_t _y0
, uint32_t _dw
, uint32_t _dh
, bool _outside
) throw()
96 ~render_object_bitmap() throw()
100 bool kill_request(void* obj
) throw()
102 return kill_request_ifeq(p
.object(), obj
) ||
103 kill_request_ifeq(b
.object(), obj
) ||
104 kill_request_ifeq(b2
.object(), obj
);
107 template<bool T
> void composite_op(struct framebuffer::fb
<T
>& scr
) throw()
109 uint32_t oX
= x
+ scr
.get_origin_x() - x0
;
110 uint32_t oY
= y
+ scr
.get_origin_y() - y0
;
120 range bX
= ((range::make_w(scr
.get_width()) - oX
) & range::make_w(w
) &
121 range::make_s(x0
, dw
));
122 range bY
= ((range::make_w(scr
.get_height()) - oY
) & range::make_w(h
) &
123 range::make_s(y0
, dh
));
124 range sX
= range::make_s(-x
+ x0
, scr
.get_last_blit_width());
125 range sY
= range::make_s(-y
+ y0
, scr
.get_last_blit_height());
128 lua_bitmap_composite(scr
, oX
, oY
, bX
, bY
, sX
, sY
, outside
,
129 lua_bitmap_holder
<T
>(*b
, *p
));
131 lua_bitmap_composite(scr
, oX
, oY
, bX
, bY
, sX
, sY
, outside
,
132 lua_dbitmap_holder
<T
>(*b2
));
134 void operator()(struct framebuffer::fb
<false>& x
) throw() { composite_op(x
); }
135 void operator()(struct framebuffer::fb
<true>& x
) throw() { composite_op(x
); }
136 void clone(framebuffer::queue
& q
) const throw(std::bad_alloc
) { q
.clone_helper(this); }
140 lua::objpin
<lua_bitmap
> b
;
141 lua::objpin
<lua_dbitmap
> b2
;
142 lua::objpin
<lua_palette
> p
;
150 struct operand_dbitmap
152 typedef framebuffer::color pixel_t
;
153 typedef framebuffer::color rpixel_t
;
154 operand_dbitmap(lua_dbitmap
& _bitmap
)
155 : bitmap(_bitmap
), _transparent(-1)
157 pixels
= bitmap
.pixels
;
159 size_t get_width() { return bitmap
.width
; }
160 size_t get_height() { return bitmap
.height
; }
161 const rpixel_t
& read(size_t idx
) { return pixels
[idx
]; }
162 const pixel_t
& lookup(const rpixel_t
& p
) { return p
; }
163 void write(size_t idx
, const pixel_t
& v
) { pixels
[idx
] = v
; }
164 bool is_opaque(const rpixel_t
& p
) { return p
.origa
> 0; }
165 const pixel_t
& transparent() { return _transparent
; }
169 framebuffer::color _transparent
;
172 struct operand_bitmap
174 typedef uint16_t pixel_t
;
175 typedef uint16_t rpixel_t
;
176 operand_bitmap(lua_bitmap
& _bitmap
)
179 pixels
= bitmap
.pixels
;
181 size_t get_width() { return bitmap
.width
; }
182 size_t get_height() { return bitmap
.height
; }
183 const rpixel_t
& read(size_t idx
) { return pixels
[idx
]; }
184 const pixel_t
& lookup(const rpixel_t
& p
) { return p
; }
185 void write(size_t idx
, const pixel_t
& v
) { pixels
[idx
] = v
; }
186 bool is_opaque(const rpixel_t
& p
) { return p
> 0; }
187 pixel_t
transparent() { return 0; }
193 struct operand_bitmap_pal
195 typedef framebuffer::color pixel_t
;
196 typedef uint16_t rpixel_t
;
197 operand_bitmap_pal(lua_bitmap
& _bitmap
, lua_palette
& _palette
)
198 : bitmap(_bitmap
), palette(_palette
), _transparent(-1)
200 pixels
= bitmap
.pixels
;
201 limit
= palette
.color_count
;
202 pal
= palette
.colors
;
204 size_t get_width() { return bitmap
.width
; }
205 size_t get_height() { return bitmap
.height
; }
206 const rpixel_t
& read(size_t idx
) { return pixels
[idx
]; }
207 const pixel_t
& lookup(const rpixel_t
& p
) { return *((p
< limit
) ? pal
+ p
: &_transparent
); }
208 bool is_opaque(const rpixel_t
& p
) { return p
> 0; }
209 const pixel_t
& transparent() { return _transparent
; }
212 lua_palette
& palette
;
214 framebuffer::color
* pal
;
216 framebuffer::color _transparent
;
221 bool iskey(uint16_t& c
) const { return false; }
222 bool iskey(framebuffer::color
& c
) const { return false; }
225 struct colorkey_direct
227 colorkey_direct(uint64_t _ck
)
229 framebuffer::color
c(_ck
);
233 bool iskey(framebuffer::color
& c
) const { return (c
.orig
== ck
&& c
.origa
== cka
); }
238 struct colorkey_palette
240 colorkey_palette(uint64_t _ck
) { ck
= _ck
; }
241 bool iskey(uint16_t& c
) const { return (c
== ck
); }
245 template<class _src
, class _dest
, class colorkey
> struct srcdest
247 srcdest(_dest Xdest
, _src Xsrc
, const colorkey
& _ckey
)
248 : dest(Xdest
), src(Xsrc
), ckey(_ckey
)
250 swidth
= src
.get_width();
251 sheight
= src
.get_height();
252 dwidth
= dest
.get_width();
253 dheight
= dest
.get_height();
255 void copy(size_t didx
, size_t sidx
)
257 typename
_src::rpixel_t c
= src
.read(sidx
);
259 dest
.write(didx
, src
.lookup(c
));
261 size_t swidth
, sheight
, dwidth
, dheight
;
268 template<class _src
, class _dest
, class colorkey
> srcdest
<_src
, _dest
, colorkey
> mk_srcdest(_dest dest
,
269 _src src
, const colorkey
& ckey
)
271 return srcdest
<_src
, _dest
, colorkey
>(dest
, src
, ckey
);
274 struct srcdest_priority
276 srcdest_priority(lua_bitmap
& dest
, lua_bitmap
& src
)
278 darray
= dest
.pixels
;
281 sheight
= src
.height
;
283 dheight
= dest
.height
;
285 void copy(size_t didx
, size_t sidx
)
287 uint16_t c
= sarray
[sidx
];
291 size_t swidth
, sheight
, dwidth
, dheight
;
313 porterduff_oper
get_pd_oper(const std::string
& oper
)
315 if(oper
== "Src") return PD_SRC
;
316 if(oper
== "Atop") return PD_ATOP
;
317 if(oper
== "Over") return PD_OVER
;
318 if(oper
== "In") return PD_IN
;
319 if(oper
== "Out") return PD_OUT
;
320 if(oper
== "Dest") return PD_DEST
;
321 if(oper
== "DestAtop") return PD_DEST_ATOP
;
322 if(oper
== "DestOver") return PD_DEST_OVER
;
323 if(oper
== "DestIn") return PD_DEST_IN
;
324 if(oper
== "DestOut") return PD_DEST_OUT
;
325 if(oper
== "Clear") return PD_CLEAR
;
326 if(oper
== "Xor") return PD_XOR
;
327 (stringfmt() << "Bad Porter-Duff operator '" << oper
<< "'").throwex();
328 return PD_SRC
; //NOTREACHED
331 template<porterduff_oper oper
, class _src
, class _dest
> struct srcdest_porterduff
333 srcdest_porterduff(_dest Xdest
, _src Xsrc
)
334 : dest(Xdest
), src(Xsrc
)
336 swidth
= src
.get_width();
337 sheight
= src
.get_height();
338 dwidth
= dest
.get_width();
339 dheight
= dest
.get_height();
341 void copy(size_t didx
, size_t sidx
)
343 typename
_dest::rpixel_t vd
= dest
.read(didx
);
344 typename
_src::rpixel_t vs
= src
.read(sidx
);
345 bool od
= dest
.is_opaque(vd
);
346 bool os
= src
.is_opaque(vs
);
347 typename
_dest::pixel_t ld
= dest
.lookup(vd
);
348 typename
_src::pixel_t ls
= src
.lookup(vs
);
349 typename
_dest::pixel_t t
= dest
.transparent();
350 typename
_dest::pixel_t r
;
352 case PD_SRC
: r
= ls
; break;
353 case PD_ATOP
: r
= od
? (os
? ls
: ld
) : t
; break;
354 case PD_OVER
: r
= os
? ls
: ld
; break;
355 case PD_IN
: r
= (od
& os
) ? ls
: t
; break;
356 case PD_OUT
: r
= (!od
&& os
) ? ls
: t
; break;
357 case PD_DEST
: r
= ld
; break;
358 case PD_DEST_ATOP
: r
= os
? (od
? ld
: ls
) : t
; break;
359 case PD_DEST_OVER
: r
= od
? ld
: ls
; break;
360 case PD_DEST_IN
: r
= (od
& os
) ? ld
: t
; break;
361 case PD_DEST_OUT
: r
= (od
& !os
) ? ld
: t
; break;
362 case PD_CLEAR
: r
= t
; break;
363 case PD_XOR
: r
= od
? (os
? t
: ld
) : ls
; break;
367 size_t swidth
, sheight
, dwidth
, dheight
;
373 template<porterduff_oper oper
, class _src
, class _dest
> srcdest_porterduff
<oper
, _src
, _dest
>
374 mk_porterduff(_dest dest
, _src src
)
376 return srcdest_porterduff
<oper
, _src
, _dest
>(dest
, src
);
379 template<class srcdest
>
380 void xblit_copy(srcdest sd
, uint32_t dx
, uint32_t dy
, uint32_t sx
, uint32_t sy
, uint32_t w
, uint32_t h
)
382 while((dx
+ w
> sd
.dwidth
|| sx
+ w
> sd
.swidth
) && w
> 0)
384 while((dy
+ h
> sd
.dheight
|| sy
+ h
> sd
.sheight
) && h
> 0)
386 if(dx
+ w
< w
|| dy
+ h
< h
) return; //Don't do overflowing blits.
387 if(sx
+ w
< w
|| sy
+ h
< h
) return; //Don't do overflowing blits.
388 size_t sidx
= sy
* sd
.swidth
+ sx
;
389 size_t didx
= dy
* sd
.dwidth
+ dx
;
390 size_t srskip
= sd
.swidth
- w
;
391 size_t drskip
= sd
.dwidth
- w
;
392 for(uint32_t j
= 0; j
< h
; j
++) {
393 for(uint32_t i
= 0; i
< w
; i
++) {
403 template<class srcdest
>
404 void xblit_scaled(srcdest sd
, uint32_t dx
, uint32_t dy
, uint32_t sx
, uint32_t sy
, uint32_t w
, uint32_t h
,
405 uint32_t hscl
, uint32_t vscl
)
407 if(!hscl
|| !vscl
) return;
408 w
= max(static_cast<uint32_t>(sd
.dwidth
/ hscl
), w
);
409 h
= max(static_cast<uint32_t>(sd
.dheight
/ vscl
), h
);
410 while((dx
+ hscl
* w
> sd
.dwidth
|| sx
+ w
> sd
.swidth
) && w
> 0)
412 while((dy
+ vscl
* h
> sd
.dheight
|| sy
+ h
> sd
.sheight
) && h
> 0)
414 if(dx
+ hscl
* w
< dx
|| dy
+ vscl
* h
< dy
) return; //Don't do overflowing blits.
415 if(sx
+ w
< w
|| sy
+ h
< h
) return; //Don't do overflowing blits.
416 size_t sidx
= sy
* sd
.swidth
+ sx
;
417 size_t didx
= dy
* sd
.dwidth
+ dx
;
418 size_t drskip
= sd
.dwidth
- hscl
* w
;
419 uint32_t _w
= hscl
* w
;
420 for(uint32_t j
= 0; j
< vscl
* h
; j
++) {
421 uint32_t _sidx
= sidx
;
422 for(uint32_t i
= 0; i
< _w
; i
+= hscl
) {
423 for(uint32_t k
= 0; k
< hscl
; k
++)
424 sd
.copy(didx
+ k
, _sidx
);
428 if((j
% vscl
) == vscl
- 1)
434 template<bool scaled
, class srcdest
>
435 inline void xblit(srcdest sd
, uint32_t dx
, uint32_t dy
, uint32_t sx
, uint32_t sy
, uint32_t w
, uint32_t h
,
436 uint32_t hscl
, uint32_t vscl
)
439 xblit_scaled(sd
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
441 xblit_copy(sd
, dx
, dy
, sx
, sy
, w
, h
);
444 template<bool scaled
, class src
, class dest
>
445 inline void xblit_pal(dest _dest
, src _src
, uint64_t ck
, uint32_t dx
, uint32_t dy
, uint32_t sx
,
446 uint32_t sy
, uint32_t w
, uint32_t h
, uint32_t hscl
, uint32_t vscl
)
449 xblit
<scaled
>(mk_srcdest(_dest
, _src
, colorkey_none()), dx
, dy
, sx
, sy
, w
, h
,
452 xblit
<scaled
>(mk_srcdest(_dest
, _src
, colorkey_palette(ck
)), dx
, dy
, sx
, sy
, w
, h
,
456 template<bool scaled
, class src
, class dest
>
457 inline void xblit_dir(dest _dest
, src _src
, uint64_t ck
, uint32_t dx
, uint32_t dy
, uint32_t sx
,
458 uint32_t sy
, uint32_t w
, uint32_t h
, uint32_t hscl
, uint32_t vscl
)
460 if(ck
== 0x100000000ULL
)
461 xblit
<scaled
>(mk_srcdest(_dest
, _src
, colorkey_none()), dx
, dy
, sx
, sy
, w
, h
,
464 xblit
<scaled
>(mk_srcdest(_dest
, _src
, colorkey_direct(ck
)), dx
, dy
, sx
, sy
, w
, h
,
468 template<bool scaled
, porterduff_oper oper
, class src
, class dest
>
469 inline void xblit_pduff2(dest _dest
, src _src
, uint32_t dx
, uint32_t dy
, uint32_t sx
,
470 uint32_t sy
, uint32_t w
, uint32_t h
, uint32_t hscl
, uint32_t vscl
)
472 xblit
<scaled
>(mk_porterduff
<oper
>(_dest
, _src
), dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
475 template<bool scaled
, class src
, class dest
>
476 inline void xblit_pduff(dest _dest
, src _src
, uint32_t dx
, uint32_t dy
, uint32_t sx
,
477 uint32_t sy
, uint32_t w
, uint32_t h
, uint32_t hscl
, uint32_t vscl
, porterduff_oper oper
)
481 xblit_pduff2
<scaled
, PD_ATOP
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
484 xblit_pduff2
<scaled
, PD_CLEAR
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
487 xblit_pduff2
<scaled
, PD_DEST
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
490 xblit_pduff2
<scaled
, PD_DEST_ATOP
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
493 xblit_pduff2
<scaled
, PD_DEST_IN
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
496 xblit_pduff2
<scaled
, PD_DEST_OUT
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
499 xblit_pduff2
<scaled
, PD_DEST_OVER
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
502 xblit_pduff2
<scaled
, PD_IN
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
505 xblit_pduff2
<scaled
, PD_OUT
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
508 xblit_pduff2
<scaled
, PD_OVER
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
511 xblit_pduff2
<scaled
, PD_SRC
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
514 xblit_pduff2
<scaled
, PD_XOR
>(_dest
, _src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
519 int bitmap_load_fn(lua::state
& L
, std::function
<lua_loaded_bitmap()> src
)
523 lua_dbitmap
* b
= lua::_class
<lua_dbitmap
>::create(L
, bitmap
.w
, bitmap
.h
);
524 for(size_t i
= 0; i
< bitmap
.w
* bitmap
.h
; i
++)
525 b
->pixels
[i
] = framebuffer::color(bitmap
.bitmap
[i
]);
528 lua_bitmap
* b
= lua::_class
<lua_bitmap
>::create(L
, bitmap
.w
, bitmap
.h
);
529 lua_palette
* p
= lua::_class
<lua_palette
>::create(L
);
530 for(size_t i
= 0; i
< bitmap
.w
* bitmap
.h
; i
++)
531 b
->pixels
[i
] = bitmap
.bitmap
[i
];
532 p
->adjust_palette_size(bitmap
.palette
.size());
533 for(size_t i
= 0; i
< bitmap
.palette
.size(); i
++)
534 p
->colors
[i
] = framebuffer::color(bitmap
.palette
[i
]);
539 //Similar as _sample_texture(), but for the s=2^n, n integer special case.
540 template<typename pixel
>
541 inline void _sample_texture_log2(pixel
* dest
, uint32_t dwidth
, uint32_t dheight
, pixel
* source
,
542 uint32_t swidth
, uint32_t sheight
, int32_t xx
, int32_t xy
, int32_t x0
, int32_t yx
, int32_t yy
,
543 int32_t y0
, int32_t log2s
, bool wrap
, pixel transparent
)
545 uint32_t th
= (1 << log2s
) >> 1; //Two shifts, as log2s=0 should give th=0.
546 uint32_t fsmask
= (1u << log2s
) - 1;
547 uint64_t bias
= 1ull << (31 + log2s
);
549 for(int32_t i
= 0; i
< (int32_t)dheight
; i
++) {
550 uint64_t ssx
= (int64_t)xy
* i
+ (int64_t)x0
+ bias
;
551 uint64_t ssy
= (int64_t)yy
* i
+ (int64_t)y0
+ bias
;
552 for(int32_t j
= 0; j
< (int32_t)dwidth
; j
++) {
553 //Compute whole and fractional parts.
554 uint32_t _isx
= ssx
>> log2s
;
555 uint32_t fsx
= ssx
& fsmask
;
556 uint32_t _isy
= ssy
>> log2s
;
557 uint32_t fsy
= ssy
& fsmask
;
558 //The above always give positive fractional parts.
559 //Round the whole parts.
563 int32_t isx
= _isx
- (1u << 31);
564 int32_t isy
= _isy
- (1u << 31);
566 pixel p
= transparent
;
569 if(isx
< 0) isx
+= swidth
;
571 if(isy
< 0) isy
+= sheight
;
572 p
= source
[isy
* swidth
+ isx
];
573 } else if(isx
>= 0 && isx
< (int32_t)swidth
&& isy
>= 0 && isy
< (int32_t)sheight
) {
574 p
= source
[isy
* swidth
+ isx
];
577 //Update values for next pixel.
585 template<typename pixel
>
586 inline void _sample_texture(pixel
* dest
, uint32_t dwidth
, uint32_t dheight
, pixel
* source
, uint32_t swidth
,
587 uint32_t sheight
, int32_t xx
, int32_t xy
, int32_t x0
, int32_t yx
, int32_t yy
, int32_t y0
, uint32_t s
,
588 bool wrap
, pixel transparent
)
590 if((s
& (s
- 1)) == 0) {
591 //S is power of two. Compute the logarithm.
597 return _sample_texture_log2(dest
, dwidth
, dheight
, source
, swidth
, sheight
, xx
, xy
, x0
, yx
,
598 yy
, y0
, log2s
, wrap
, transparent
);
602 for(int32_t i
= 0; i
< (int32_t)dheight
; i
++) {
603 int64_t ssx
= (int64_t)xy
* i
+ (int64_t)x0
;
604 int64_t ssy
= (int64_t)yy
* i
+ (int64_t)y0
;
605 for(int32_t j
= 0; j
< (int32_t)dwidth
; j
++) {
606 //Compute whole and fractional parts.
607 int64_t isx
= ssx
/ (int32_t)s
;
608 int32_t fsx
= ssx
% (int32_t)s
;
609 int64_t isy
= ssy
/ (int32_t)s
;
610 int32_t fsy
= ssy
% (int32_t)s
;
611 //Make the fractional parts always positive.
612 if(fsx
< 0) { fsx
+= s
; isx
--; }
613 if(fsy
< 0) { fsy
+= s
; isy
--; }
614 //Round the whole parts.
618 pixel p
= transparent
;
621 if(isx
< 0) isx
+= swidth
;
623 if(isy
< 0) isy
+= sheight
;
624 p
= source
[isy
* swidth
+ isx
];
625 } else if(isx
>= 0 && isx
< (int32_t)swidth
&& isy
>= 0 && isy
< (int32_t)sheight
) {
626 p
= source
[isy
* swidth
+ isx
];
629 //Update values for next pixel.
637 template<typename pixel
>
638 inline int _hflip(pixel
* pixels
, uint32_t width
, uint32_t height
)
640 uint32_t w
= width
, h
= height
;
642 for (uint32_t x
= 0; x
< w
/2; x
++) {
643 for (uint32_t y
= 0; y
< h
; y
++) {
644 std::swap(pixels
[y
* w
+ x
], pixels
[(y
+ 1) * w
- x
- 1]);
650 template<typename pixel
>
651 inline int _vflip(pixel
* pixels
, uint32_t width
, uint32_t height
)
653 uint32_t w
= width
, h
= height
;
655 for (uint32_t x
= 0; x
< w
; x
++) {
656 for (uint32_t y
= 0; y
< h
/2; y
++) {
657 std::swap(pixels
[y
* w
+ x
], pixels
[(h
- y
- 1) * w
+ x
]);
664 inline int64_t mangle_color(uint32_t c
)
669 return ((256 - (c
>> 24) - (c
>> 31)) << 24) | (c
& 0xFFFFFF);
672 int base64val(char ch
)
674 if(ch
>= 'A' && ch
<= 'Z')
676 if(ch
>= 'a' && ch
<= 'z')
678 if(ch
>= '0' && ch
<= '9')
684 if(ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n')
691 std::string
base64_encode(const std::string
& str
)
693 std::ostringstream x
;
697 mem
= (mem
<< 8) + (unsigned char)i
;
699 uint8_t c1
= (mem
>> 18) & 0x3F;
700 uint8_t c2
= (mem
>> 12) & 0x3F;
701 uint8_t c3
= (mem
>> 6) & 0x3F;
702 uint8_t c4
= mem
& 0x3F;
703 x
<< CONST_base64chars
[c1
];
704 x
<< CONST_base64chars
[c2
];
705 x
<< CONST_base64chars
[c3
];
706 x
<< CONST_base64chars
[c4
];
712 uint8_t c1
= (mem
>> 10) & 0x3F;
713 uint8_t c2
= (mem
>> 4) & 0x3F;
714 uint8_t c3
= (mem
<< 2) & 0x3F;
715 x
<< CONST_base64chars
[c1
];
716 x
<< CONST_base64chars
[c2
];
717 x
<< CONST_base64chars
[c3
];
721 uint8_t c1
= (mem
>> 2) & 0x3F;
722 uint8_t c2
= (mem
<< 4) & 0x3F;
723 x
<< CONST_base64chars
[c1
];
724 x
<< CONST_base64chars
[c2
];
730 std::string
base64_decode(const std::string
& str
)
734 uint32_t memsize
= 1;
736 std::ostringstream x
;
738 int v
= base64val(i
);
741 posmod
= (posmod
+ 1) & 3;
742 if(v
== -2 && (posmod
== 1 || posmod
== 2))
743 throw std::runtime_error("Invalid Base64");
749 throw std::runtime_error("Invalid Base64");
750 memory
= memory
* 64 + v
;
751 memsize
= memsize
* 64;
754 x
<< static_cast<uint8_t>(memory
/ memsize
);
762 int bitmap_load_png_fn(lua::state
& L
, T
& src
)
764 png::decoder
img(src
);
765 if(img
.has_palette
) {
766 lua_bitmap
* b
= lua::_class
<lua_bitmap
>::create(L
, img
.width
, img
.height
);
767 lua_palette
* p
= lua::_class
<lua_palette
>::create(L
);
768 for(size_t i
= 0; i
< img
.width
* img
.height
; i
++)
769 b
->pixels
[i
] = img
.data
[i
];
770 p
->adjust_palette_size(img
.palette
.size());
771 for(size_t i
= 0; i
< img
.palette
.size(); i
++)
772 p
->colors
[i
] = framebuffer::color(mangle_color(img
.palette
[i
]));
775 lua_dbitmap
* b
= lua::_class
<lua_dbitmap
>::create(L
, img
.width
, img
.height
);
776 for(size_t i
= 0; i
< img
.width
* img
.height
; i
++)
777 b
->pixels
[i
] = framebuffer::color(mangle_color(img
.data
[i
]));
782 int bitmap_palette_fn(lua::state
& L
, std::istream
& s
)
784 lua_palette
* p
= lua::_class
<lua_palette
>::create(L
);
787 std::getline(s
, line
);
790 if(!regex_match("[ \t]*(#.*)?", line
)) {
792 } else if(r
= regex("[ \t]*([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]*", line
)) {
793 int64_t cr
, cg
, cb
, ca
;
794 cr
= parse_value
<uint8_t>(r
[1]);
795 cg
= parse_value
<uint8_t>(r
[2]);
796 cb
= parse_value
<uint8_t>(r
[3]);
797 ca
= 256 - parse_value
<uint16_t>(r
[4]);
799 p
->push_back(framebuffer::color(-1));
801 p
->push_back(framebuffer::color((ca
<< 24) | (cr
<< 16)
803 } else if(r
= regex("[ \t]*([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]*", line
)) {
805 cr
= parse_value
<uint8_t>(r
[1]);
806 cg
= parse_value
<uint8_t>(r
[2]);
807 cb
= parse_value
<uint8_t>(r
[3]);
808 p
->push_back(framebuffer::color((cr
<< 16) | (cg
<< 8) | cb
));
809 } else if(r
= regex("[ \t]*([^ \t]|[^ \t].*[^ \t])[ \t]*", line
)) {
810 p
->push_back(framebuffer::color(r
[1]));
812 throw std::runtime_error("Invalid line format (" + line
+ ")");
817 inline framebuffer::color
tadjust(framebuffer::color c
, uint16_t adj
)
819 uint32_t rgb
= c
.orig
;
820 uint32_t a
= c
.origa
;
825 return framebuffer::color(-1);
827 return framebuffer::color(rgb
| ((uint32_t)(256 - a
) << 24));
830 lua::_class
<lua_loaded_bitmap
> LUA_class_loaded_bitmap(lua_class_gui
, "IMAGELOADER", {
831 {"load", lua_loaded_bitmap::load
<false>},
832 {"load_str", lua_loaded_bitmap::load_str
<false>},
833 {"load_png", lua_loaded_bitmap::load
<true>},
834 {"load_png_str", lua_loaded_bitmap::load_str
<true>},
837 lua::_class
<lua_palette
> LUA_class_palette(lua_class_gui
, "PALETTE", {
838 {"new", lua_palette::create
},
839 {"load", lua_palette::load
},
840 {"load_str", lua_palette::load_str
},
842 {"set", &lua_palette::set
},
843 {"get", &lua_palette::get
},
844 {"hash", &lua_palette::hash
},
845 {"debug", &lua_palette::debug
},
846 {"adjust_transparency", &lua_palette::adjust_transparency
},
847 }, &lua_palette::print
);
849 lua::_class
<lua_bitmap
> LUA_class_bitmap(lua_class_gui
, "BITMAP", {
850 {"new", lua_bitmap::create
},
852 {"draw", &lua_bitmap::draw
<false, false>},
853 {"draw_clip", &lua_bitmap::draw
<false, true>},
854 {"draw_outside", &lua_bitmap::draw
<true, false>},
855 {"draw_clip_outside", &lua_bitmap::draw
<true, true>},
856 {"pset", &lua_bitmap::pset
},
857 {"pget", &lua_bitmap::pget
},
858 {"size", &lua_bitmap::size
},
859 {"hflip", &lua_bitmap::hflip
},
860 {"vflip", &lua_bitmap::vflip
},
861 {"hash", &lua_bitmap::hash
},
862 {"blit", &lua_bitmap::blit
<false, false>},
863 {"blit_priority", &lua_bitmap::blit_priority
<false>},
864 {"blit_scaled", &lua_bitmap::blit
<true, false>},
865 {"blit_scaled_priority", &lua_bitmap::blit_priority
<true>},
866 {"blit_porterduff", &lua_bitmap::blit
<false, true>},
867 {"blit_scaled_porterduff", &lua_bitmap::blit
<true, true>},
868 {"save_png", &lua_bitmap::save_png
},
869 {"sample_texture", &lua_bitmap::sample_texture
},
870 }, &lua_bitmap::print
);
872 lua::_class
<lua_dbitmap
> LUA_class_dbitmap(lua_class_gui
, "DBITMAP", {
873 {"new", lua_dbitmap::create
},
875 {"draw", &lua_dbitmap::draw
<false, false>},
876 {"draw_clip", &lua_dbitmap::draw
<false, true>},
877 {"draw_outside", &lua_dbitmap::draw
<true, false>},
878 {"draw_clip_outside", &lua_dbitmap::draw
<true, true>},
879 {"pset", &lua_dbitmap::pset
},
880 {"pget", &lua_dbitmap::pget
},
881 {"size", &lua_dbitmap::size
},
882 {"hflip", &lua_dbitmap::hflip
},
883 {"vflip", &lua_dbitmap::vflip
},
884 {"hash", &lua_dbitmap::hash
},
885 {"blit", &lua_dbitmap::blit
<false, false>},
886 {"blit_scaled", &lua_dbitmap::blit
<true, false>},
887 {"blit_porterduff", &lua_dbitmap::blit
<false, true>},
888 {"blit_scaled_porterduff", &lua_dbitmap::blit
<true, true>},
889 {"save_png", &lua_dbitmap::save_png
},
890 {"adjust_transparency", &lua_dbitmap::adjust_transparency
},
891 {"sample_texture", &lua_dbitmap::sample_texture
},
892 }, &lua_dbitmap::print
);
896 lua_palette::lua_palette(lua::state
& L
)
899 scolors
= colors
= lua::align_overcommit
<lua_palette
, framebuffer::color
>(this);
900 for(unsigned i
= 0; i
< reserved_colors
; i
++)
901 scolors
[i
] = framebuffer::color(-1);
904 lua_palette::~lua_palette()
906 CORE().fbuf
->render_kill_request(this);
909 std::string
lua_palette::print()
911 size_t s
= color_count
;
912 return (stringfmt() << s
<< " " << ((s
!= 1) ? "colors" : "color")).str();
915 int lua_palette::create(lua::state
& L
, lua::parameters
& P
)
917 lua::_class
<lua_palette
>::create(L
);
921 int lua_palette::load(lua::state
& L
, lua::parameters
& P
)
923 std::string name
, name2
;
925 P(name
, P
.optional(name2
, ""));
927 std::istream
& s
= zip::openrel(name
, name2
);
929 int r
= bitmap_palette_fn(L
, s
);
938 int lua_palette::load_str(lua::state
& L
, lua::parameters
& P
)
944 std::istringstream
s(content
);
945 return bitmap_palette_fn(L
, s
);
948 int lua_palette::set(lua::state
& L
, lua::parameters
& P
)
950 framebuffer::color nc
;
953 P(P
.skipped(), c
, nc
);
955 if(this->color_count
<= c
) {
956 this->adjust_palette_size(static_cast<uint32_t>(c
) + 1);
958 this->colors
[c
] = nc
;
962 int lua_palette::get(lua::state
& L
, lua::parameters
& P
)
964 framebuffer::color nc
;
970 if(this->color_count
<= c
) {
973 nc
= this->colors
[c
];
974 uint32_t rgb
= nc
.orig
;
975 uint32_t a
= nc
.origa
;
979 _nc
= ((256 - a
) << 24) | rgb
;
984 int lua_palette::hash(lua::state
& L
, lua::parameters
& P
)
987 const int buffersize
= 256;
989 char buf
[buffersize
];
990 unsigned realsize
= 0;
991 for(unsigned i
= 0; i
< this->color_count
; i
++)
992 if(this->colors
[i
].origa
) realsize
= i
+ 1;
993 for(unsigned i
= 0; i
< realsize
; i
++) {
994 if(bufferuse
+ 6 > buffersize
) {
995 h
.write(buf
, bufferuse
);
998 serialization::u32b(buf
+ bufferuse
+ 0, this->colors
[i
].orig
);
999 serialization::u16b(buf
+ bufferuse
+ 4, this->colors
[i
].origa
);
1002 if(bufferuse
> 0) h
.write(buf
, bufferuse
);
1003 L
.pushlstring(h
.read());
1007 int lua_palette::debug(lua::state
& L
, lua::parameters
& P
)
1009 for(size_t i
= 0; i
< color_count
; i
++)
1010 messages
<< "Color #" << i
<< ": " << colors
[i
].orig
<< ":" << colors
[i
].origa
<< std::endl
;
1014 int lua_palette::adjust_transparency(lua::state
& L
, lua::parameters
& P
)
1018 P(P
.skipped(), tadj
);
1020 for(size_t i
= 0; i
< color_count
; i
++)
1021 colors
[i
] = tadjust(colors
[i
], tadj
);
1025 void lua_palette::adjust_palette_size(size_t newsize
)
1027 threads::alock
h(palette_mutex
);
1028 if(newsize
> reserved_colors
) {
1029 lcolors
.resize(newsize
);
1030 if(color_count
<= reserved_colors
) {
1031 for(unsigned i
= 0; i
< color_count
; i
++)
1032 lcolors
[i
] = colors
[i
];
1034 colors
= &lcolors
[0];
1036 if(color_count
> reserved_colors
) {
1037 for(unsigned i
= 0; i
< color_count
; i
++)
1038 scolors
[i
] = lcolors
[i
];
1042 color_count
= newsize
;
1045 void lua_palette::push_back(const framebuffer::color
& cx
)
1047 size_t c
= color_count
;
1048 adjust_palette_size(c
+ 1);
1053 lua_bitmap::lua_bitmap(lua::state
& L
, uint32_t w
, uint32_t h
)
1055 if(h
> 0 && overcommit(w
, h
) / h
/ sizeof(uint16_t) < w
) throw std::bad_alloc();
1058 pixels
= lua::align_overcommit
<lua_bitmap
, uint16_t>(this);
1059 memset(pixels
, 0, 2 * width
* height
);
1062 lua_bitmap::~lua_bitmap()
1064 CORE().fbuf
->render_kill_request(this);
1067 std::string
lua_bitmap::print()
1069 return (stringfmt() << width
<< "*" << height
).str();
1072 int lua_bitmap::create(lua::state
& L
, lua::parameters
& P
)
1077 P(w
, h
, P
.optional(c
, 0));
1079 lua_bitmap
* b
= lua::_class
<lua_bitmap
>::create(L
, w
, h
);
1080 for(size_t i
= 0; i
< b
->width
* b
->height
; i
++)
1085 template<bool outside
, bool clip
>
1086 int lua_bitmap::draw(lua::state
& L
, lua::parameters
& P
)
1088 auto& core
= CORE();
1090 lua::objpin
<lua_bitmap
> b
;
1091 lua::objpin
<lua_palette
> p
;
1093 if(!core
.lua2
->render_ctx
) return 0;
1097 int32_t x0
= 0, y0
= 0, dw
= b
->width
, dh
= b
->height
;
1098 if(clip
) P(x0
, y0
, dw
, dh
);
1100 core
.lua2
->render_ctx
->queue
->create_add
<render_object_bitmap
>(x
, y
, b
, p
, x0
, y0
, dw
, dh
, outside
);
1104 int lua_bitmap::pset(lua::state
& L
, lua::parameters
& P
)
1109 P(P
.skipped(), x
, y
, c
);
1111 if(x
>= this->width
|| y
>= this->height
)
1113 this->pixels
[y
* this->width
+ x
] = c
;
1117 int lua_bitmap::pget(lua::state
& L
, lua::parameters
& P
)
1121 P(P
.skipped(), x
, y
);
1123 if(x
>= this->width
|| y
>= this->height
)
1125 L
.pushnumber(this->pixels
[y
* this->width
+ x
]);
1129 int lua_bitmap::size(lua::state
& L
, lua::parameters
& P
)
1131 L
.pushnumber(this->width
);
1132 L
.pushnumber(this->height
);
1136 int lua_bitmap::hflip(lua::state
& L
, lua::parameters
& P
)
1138 return _hflip(pixels
, width
, height
);
1141 int lua_bitmap::vflip(lua::state
& L
, lua::parameters
& P
)
1143 return _vflip(pixels
, width
, height
);
1146 int lua_bitmap::hash(lua::state
& L
, lua::parameters
& P
)
1149 const int buffersize
= 256;
1151 char buf
[buffersize
];
1152 memset(buf
, 0, buffersize
);
1153 serialization::u64b(buf
+ 0, this->width
);
1154 serialization::u64b(buf
+ 8, this->height
);
1156 for(unsigned i
= 0; i
< this->width
* this->height
; i
++) {
1157 if(bufferuse
+ 2 > buffersize
) {
1158 h
.write(buf
, bufferuse
);
1161 serialization::u16b(buf
+ bufferuse
+ 0, this->pixels
[i
]);
1164 if(bufferuse
> 0) h
.write(buf
, bufferuse
);
1165 L
.pushlstring(h
.read());
1169 template<bool scaled
, bool porterduff
> int lua_bitmap::blit(lua::state
& L
, lua::parameters
& P
)
1171 uint32_t dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
;
1174 P(P
.skipped(), dx
, dy
, src_p
, sx
, sy
, w
, h
);
1176 P(hscl
, P
.optional2(vscl
, hscl
));
1179 porterduff_oper pd_oper
= get_pd_oper(P
.arg
<std::string
>());
1180 xblit_pduff
<scaled
>(operand_bitmap(*this), operand_bitmap(*src_p
), dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
,
1183 int64_t ck
= P
.arg_opt
<uint64_t>(65536);
1184 xblit_pal
<scaled
>(operand_bitmap(*this), operand_bitmap(*src_p
), ck
, dx
, dy
, sx
, sy
, w
, h
,
1190 template<bool scaled
> int lua_bitmap::blit_priority(lua::state
& L
, lua::parameters
& P
)
1192 uint32_t dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
;
1195 P(P
.skipped(), dx
, dy
, src_p
, sx
, sy
, w
, h
);
1197 P(hscl
, P
.optional2(vscl
, hscl
));
1199 xblit
<scaled
>(srcdest_priority(*this, *src_p
), dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
1203 int lua_bitmap::save_png(lua::state
& L
, lua::parameters
& P
)
1205 std::string name
, name2
;
1210 if((was_filename
= P
.is_string())) P(name
);
1211 if(P
.is_string()) P(name2
);
1214 auto buf
= this->save_png(*p
);
1216 std::string filename
= zip::resolverel(name
, name2
);
1217 std::ofstream
strm(filename
, std::ios::binary
);
1219 throw std::runtime_error("Can't open output file");
1220 strm
.write(&buf
[0], buf
.size());
1222 throw std::runtime_error("Can't write output file");
1225 std::ostringstream strm
;
1226 strm
.write(&buf
[0], buf
.size());
1227 L
.pushlstring(base64_encode(strm
.str()));
1232 int lua_bitmap::sample_texture(lua::state
& L
, lua::parameters
& P
)
1235 int32_t xx
, xy
, yx
, yy
, x0
, y0
;
1240 P(P
.skipped(), src_p
, xx
, xy
, x0
, yx
, yy
, y0
, s
, wrap
);
1242 _sample_texture(pixels
, width
, height
, src_p
->pixels
, src_p
->width
, src_p
->height
, xx
, xy
, x0
, yx
, yy
, y0
,
1248 lua_dbitmap::lua_dbitmap(lua::state
& L
, uint32_t w
, uint32_t h
)
1250 if(h
> 0 && overcommit(w
, h
) / h
/ sizeof(framebuffer::color
) < w
) throw std::bad_alloc();
1253 pixels
= lua::align_overcommit
<lua_dbitmap
, framebuffer::color
>(this);
1254 //Initialize the bitmap data.
1255 framebuffer::color
transparent(-1);
1256 for(size_t i
= 0; i
< (size_t)width
* height
; i
++)
1257 new(pixels
+ i
) framebuffer::color(transparent
);
1260 lua_dbitmap::~lua_dbitmap()
1262 CORE().fbuf
->render_kill_request(this);
1265 std::string
lua_dbitmap::print()
1267 return (stringfmt() << width
<< "*" << height
).str();
1270 int lua_dbitmap::create(lua::state
& L
, lua::parameters
& P
)
1273 framebuffer::color c
;
1275 P(w
, h
, P
.optional(c
, -1));
1277 lua_dbitmap
* b
= lua::_class
<lua_dbitmap
>::create(L
, w
, h
);
1278 for(size_t i
= 0; i
< b
->width
* b
->height
; i
++)
1283 template<bool outside
, bool clip
>
1284 int lua_dbitmap::draw(lua::state
& L
, lua::parameters
& P
)
1286 auto& core
= CORE();
1288 lua::objpin
<lua_dbitmap
> b
;
1290 if(!core
.lua2
->render_ctx
) return 0;
1294 int32_t x0
= 0, y0
= 0, dw
= b
->width
, dh
= b
->height
;
1295 if(clip
) P(x0
, y0
, dw
, dh
);
1297 core
.lua2
->render_ctx
->queue
->create_add
<render_object_bitmap
>(x
, y
, b
, x0
, y0
, dw
, dh
, outside
);
1301 int lua_dbitmap::pset(lua::state
& L
, lua::parameters
& P
)
1304 framebuffer::color c
;
1306 P(P
.skipped(), x
, y
, c
);
1308 if(x
>= this->width
|| y
>= this->height
)
1310 this->pixels
[y
* this->width
+ x
] = c
;
1314 int lua_dbitmap::pget(lua::state
& L
, lua::parameters
& P
)
1318 P(P
.skipped(), x
, y
);
1320 if(x
>= this->width
|| y
>= this->height
)
1322 L
.pushnumber((this->pixels
[y
* this->width
+ x
]).asnumber());
1326 int lua_dbitmap::size(lua::state
& L
, lua::parameters
& P
)
1328 L
.pushnumber(this->width
);
1329 L
.pushnumber(this->height
);
1333 int lua_dbitmap::hflip(lua::state
& L
, lua::parameters
& P
)
1335 return _hflip(pixels
, width
, height
);
1338 int lua_dbitmap::vflip(lua::state
& L
, lua::parameters
& P
)
1340 return _vflip(pixels
, width
, height
);
1343 int lua_dbitmap::hash(lua::state
& L
, lua::parameters
& P
)
1346 const int buffersize
= 256;
1348 char buf
[buffersize
];
1349 memset(buf
, 0, buffersize
);
1350 serialization::u64b(buf
+ 0, this->width
);
1351 serialization::u64b(buf
+ 4, this->height
);
1353 for(unsigned i
= 0; i
< this->width
* this->height
; i
++) {
1354 if(bufferuse
+ 6 > buffersize
) {
1355 h
.write(buf
, bufferuse
);
1358 serialization::u32b(buf
+ bufferuse
+ 0, this->pixels
[i
].orig
);
1359 serialization::u16b(buf
+ bufferuse
+ 4, this->pixels
[i
].origa
);
1362 if(bufferuse
> 0) h
.write(buf
, bufferuse
);
1363 L
.pushlstring(h
.read());
1367 template<bool scaled
, bool porterduff
> int lua_dbitmap::blit(lua::state
& L
, lua::parameters
& P
)
1369 uint32_t dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
;
1371 P(P
.skipped(), dx
, dy
);
1373 //DBitmap or Bitmap+Palette.
1374 bool src_d
= P
.is
<lua_dbitmap
>();
1375 bool src_p
= P
.is
<lua_bitmap
>();
1376 int sidx
= P
.skip();
1377 if(!src_d
&& !src_p
)
1378 P
.expected("BITMAP or DBITMAP", sidx
);
1381 spal
= P
.skip(); //Reserve for palette.
1386 P(hscl
, P
.optional2(vscl
, hscl
));
1388 int64_t ckx
= 0x100000000ULL
;
1389 porterduff_oper pd_oper
;
1391 pd_oper
= get_pd_oper(P
.arg
<std::string
>());
1393 //Hack: Direct-color bitmaps should take color spec, with special NONE value.
1395 ckx
= P
.arg_opt
<int64_t>(0x10000);
1396 else if(P
.is_novalue())
1399 ckx
= P
.arg
<framebuffer::color
>().asnumber();
1402 operand_dbitmap
dest(*this);
1404 operand_dbitmap
src(*P
.arg
<lua_dbitmap
*>(sidx
));
1406 xblit_pduff
<scaled
>(dest
, src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
, pd_oper
);
1408 xblit_dir
<scaled
>(dest
, src
, ckx
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
1410 operand_bitmap_pal
src(*P
.arg
<lua_bitmap
*>(sidx
), *P
.arg
<lua_palette
*>(spal
));
1412 xblit_pduff
<scaled
>(dest
, src
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
, pd_oper
);
1414 xblit_pal
<scaled
>(dest
, src
, ckx
, dx
, dy
, sx
, sy
, w
, h
, hscl
, vscl
);
1419 int lua_dbitmap::save_png(lua::state
& L
, lua::parameters
& P
)
1421 std::string name
, name2
;
1425 if((was_filename
= P
.is_string())) P(name
);
1426 if(P
.is_string()) P(name2
);
1428 auto buf
= this->save_png();
1430 std::string filename
= zip::resolverel(name
, name2
);
1431 std::ofstream
strm(filename
, std::ios::binary
);
1433 throw std::runtime_error("Can't open output file");
1434 strm
.write(&buf
[0], buf
.size());
1436 throw std::runtime_error("Can't write output file");
1439 std::ostringstream strm
;
1440 strm
.write(&buf
[0], buf
.size());
1441 L
.pushlstring(base64_encode(strm
.str()));
1446 int lua_dbitmap::adjust_transparency(lua::state
& L
, lua::parameters
& P
)
1450 P(P
.skipped(), tadj
);
1452 for(size_t i
= 0; i
< width
* height
; i
++)
1453 pixels
[i
] = tadjust(pixels
[i
], tadj
);
1457 int lua_dbitmap::sample_texture(lua::state
& L
, lua::parameters
& P
)
1460 int32_t xx
, xy
, yx
, yy
, x0
, y0
;
1464 P(P
.skipped(), src_p
, xx
, xy
, x0
, yx
, yy
, y0
, s
, wrap
);
1466 _sample_texture(pixels
, width
, height
, src_p
->pixels
, src_p
->width
, src_p
->height
, xx
, xy
, x0
, yx
, yy
, y0
,
1467 s
, wrap
, framebuffer::color());
1471 template<bool png
> int lua_loaded_bitmap::load(lua::state
& L
, lua::parameters
& P
)
1473 std::string name
, name2
;
1475 P(name
, P
.optional(name2
, ""));
1478 std::string filename
= zip::resolverel(name
, name2
);
1479 return bitmap_load_png_fn(L
, filename
);
1481 return bitmap_load_fn(L
, [&name
, &name2
]() -> lua_loaded_bitmap
{
1482 std::string name3
= zip::resolverel(name
, name2
);
1483 return lua_loaded_bitmap::load(name3
);
1487 template<bool png
> int lua_loaded_bitmap::load_str(lua::state
& L
, lua::parameters
& P
)
1489 std::string contents
;
1494 contents
= base64_decode(contents
);
1495 std::istringstream
strm(contents
);
1496 return bitmap_load_png_fn(L
, strm
);
1498 return bitmap_load_fn(L
, [&contents
]() -> lua_loaded_bitmap
{
1499 std::istringstream
strm(contents
);
1500 return lua_loaded_bitmap::load(strm
);