1 #include "framebuffer.hpp"
3 #include "serialization.hpp"
11 #define SCREENSHOT_RGB_MAGIC 0x74212536U
15 std::list
<pixel_format
*>& pixel_formats()
17 static std::list
<pixel_format
*> x
;
21 template<size_t c
> void decode_words(uint8_t* target
, const uint8_t* src
, size_t srcsize
)
23 if(c
== 1 || c
== 2 || c
== 3 || c
== 4)
28 for(size_t i
= 0; i
< srcsize
; i
++)
31 uint16_t* _target
= reinterpret_cast<uint16_t*>(target
);
32 for(size_t i
= 0; i
< srcsize
; i
++) {
33 _target
[i
] = static_cast<uint16_t>(src
[2 * i
+ 0]) << 8;
34 _target
[i
] |= static_cast<uint16_t>(src
[2 * i
+ 1]);
37 for(size_t i
= 0; i
< srcsize
; i
++) {
38 target
[3 * i
+ 0] = src
[3 * i
+ 0];
39 target
[3 * i
+ 1] = src
[3 * i
+ 1];
40 target
[3 * i
+ 2] = src
[3 * i
+ 2];
43 uint32_t* _target
= reinterpret_cast<uint32_t*>(target
);
44 for(size_t i
= 0; i
< srcsize
; i
++) {
45 _target
[i
] = static_cast<uint32_t>(src
[4 * i
+ 0]) << 24;
46 _target
[i
] |= static_cast<uint32_t>(src
[4 * i
+ 1]) << 16;
47 _target
[i
] |= static_cast<uint32_t>(src
[4 * i
+ 2]) << 8;
48 _target
[i
] |= static_cast<uint32_t>(src
[4 * i
+ 3]);
51 uint32_t* _target
= reinterpret_cast<uint32_t*>(target
);
52 for(size_t i
= 0; i
< srcsize
; i
++) {
53 _target
[i
] = (static_cast<uint32_t>(src
[3 * i
+ 0]) << 16);
54 _target
[i
] |= (static_cast<uint32_t>(src
[3 * i
+ 1]) << 8);
55 _target
[i
] |= (static_cast<uint32_t>(src
[3 * i
+ 2]));
60 template<size_t c
> void encode_words(uint8_t* target
, const uint8_t* src
, size_t elts
)
63 for(size_t i
= 0; i
< elts
; i
++)
66 const uint16_t* _src
= reinterpret_cast<const uint16_t*>(src
);
67 for(size_t i
= 0; i
< elts
; i
++) {
68 target
[2 * i
+ 0] = _src
[i
] >> 8;
69 target
[2 * i
+ 1] = _src
[i
];
72 for(size_t i
= 0; i
< elts
; i
++) {
73 target
[3 * i
+ 0] = src
[3 * i
+ 0];
74 target
[3 * i
+ 1] = src
[3 * i
+ 1];
75 target
[3 * i
+ 2] = src
[3 * i
+ 2];
78 const uint32_t* _src
= reinterpret_cast<const uint32_t*>(src
);
79 for(size_t i
= 0; i
< elts
; i
++) {
80 target
[4 * i
+ 0] = _src
[i
] >> 24;
81 target
[4 * i
+ 1] = _src
[i
] >> 16;
82 target
[4 * i
+ 2] = _src
[i
] >> 8;
83 target
[4 * i
+ 3] = _src
[i
];
86 const uint32_t* _src
= reinterpret_cast<const uint32_t*>(src
);
87 for(size_t i
= 0; i
< elts
; i
++) {
88 target
[3 * i
+ 0] = _src
[i
] >> 16;
89 target
[3 * i
+ 1] = _src
[i
] >> 8;
90 target
[3 * i
+ 2] = _src
[i
];
96 pixel_format::pixel_format() throw(std::bad_alloc
)
98 pixel_formats().push_back(this);
101 pixel_format::~pixel_format() throw()
103 for(auto i
= pixel_formats().begin(); i
!= pixel_formats().end(); i
++)
105 pixel_formats().erase(i
);
110 framebuffer_raw::framebuffer_raw(const framebuffer_info
& info
) throw(std::bad_alloc
)
112 size_t unit
= info
.type
->get_bpp();
113 size_t pixel_offset
= info
.offset_y
* info
.physstride
+ unit
* info
.offset_x
;
115 addr
= info
.mem
+ pixel_offset
;
118 height
= info
.height
;
119 stride
= info
.stride
;
123 framebuffer_raw::framebuffer_raw() throw(std::bad_alloc
)
134 framebuffer_raw::framebuffer_raw(const framebuffer_raw
& f
) throw(std::bad_alloc
)
140 size_t unit
= f
.fmt
->get_bpp();
141 stride
= f
.width
* unit
;
142 allocated
= unit
* width
* height
;
143 addr
= new char[allocated
];
144 for(size_t i
= 0; i
< height
; i
++)
145 memcpy(addr
+ stride
* i
, f
.addr
+ f
.stride
* i
, unit
* width
);
148 framebuffer_raw
& framebuffer_raw::operator=(const framebuffer_raw
& f
) throw(std::bad_alloc
, std::runtime_error
)
151 throw std::runtime_error("Target framebuffer is not writable");
154 size_t unit
= f
.fmt
->get_bpp();
155 size_t newallocated
= unit
* f
.width
* f
.height
;
156 if(newallocated
> allocated
) {
157 char* newaddr
= new char[newallocated
];
160 allocated
= newallocated
;
165 stride
= f
.width
* unit
;
166 for(size_t i
= 0; i
< height
; i
++)
167 memcpy(addr
+ stride
* i
, f
.addr
+ f
.stride
* i
, unit
* width
);
171 framebuffer_raw::~framebuffer_raw()
177 void framebuffer_raw::load(const std::vector
<char>& data
) throw(std::bad_alloc
, std::runtime_error
)
180 throw std::runtime_error("Bad screenshot data");
182 throw std::runtime_error("Target framebuffer is not writable");
183 pixel_format
* nfmt
= NULL
;
184 const uint8_t* data2
= reinterpret_cast<const uint8_t*>(&data
[0]);
185 size_t legacy_width
= read16ube(data2
);
190 if(legacy_width
> 0 && data
.size() % (3 * legacy_width
) == 2) {
192 for(pixel_format
* f
: pixel_formats())
193 if(f
->get_magic() == 0)
196 throw std::runtime_error("Unknown screenshot format");
197 _width
= legacy_width
;
198 _height
= (data
.size() - 2) / (3 * legacy_width
);
203 throw std::runtime_error("Bad screenshot data");
205 uint32_t magic
= read32ube(data2
+ 2);
206 for(pixel_format
* f
: pixel_formats())
207 if(f
->get_magic() == magic
)
210 throw std::runtime_error("Unknown screenshot format");
211 _width
= read16ube(data2
+ 6);
212 _height
= (data
.size() - 8) / (nfmt
->get_ss_bpp() * _width
);
214 if(data
.size() < dataoffset
+ nfmt
->get_ss_bpp() * _width
* _height
)
215 throw std::runtime_error("Bad screenshot data");
217 size_t bpp
= nfmt
->get_bpp();
218 size_t sbpp
= nfmt
->get_ss_bpp();
219 if(allocated
< bpp
* _width
* _height
) {
220 //Allocate more memory.
221 size_t newalloc
= bpp
* _width
* _height
;
222 char* addr2
= new char[newalloc
];
225 allocated
= newalloc
;
230 stride
= _width
* bpp
;
232 decode_words
<1>(reinterpret_cast<uint8_t*>(addr
), data2
+ dataoffset
, data
.size() - dataoffset
);
234 decode_words
<2>(reinterpret_cast<uint8_t*>(addr
), data2
+ dataoffset
, data
.size() - dataoffset
);
236 decode_words
<3>(reinterpret_cast<uint8_t*>(addr
), data2
+ dataoffset
, data
.size() - dataoffset
);
237 else if(bpp
== 4 && sbpp
== 3)
238 decode_words
<5>(reinterpret_cast<uint8_t*>(addr
), data2
+ dataoffset
, data
.size() - dataoffset
);
239 else if(bpp
== 4 && sbpp
== 4)
240 decode_words
<4>(reinterpret_cast<uint8_t*>(addr
), data2
+ dataoffset
, data
.size() - dataoffset
);
243 void framebuffer_raw::save(std::vector
<char>& data
) throw(std::bad_alloc
)
245 uint8_t* memory
= reinterpret_cast<uint8_t*>(addr
);
247 size_t bpp
= fmt
->get_bpp();
248 size_t sbpp
= fmt
->get_ss_bpp();
251 uint32_t magic
= fmt
->get_magic();
254 //Save in legacy format.
256 data
.resize(offset
+ sbpp
* static_cast<size_t>(width
) * height
);
257 data2
= reinterpret_cast<uint8_t*>(&data
[0]);
258 write16ube(&data
[0], width
);
261 //Choose the first two bytes so that screenshot is bad in legacy format.
263 while(width
* height
% m
== 0)
266 data
.resize(offset
+ sbpp
* static_cast<size_t>(width
) * height
);
267 write16ube(&data
[0], m
);
268 write32ube(&data
[2], magic
);
269 write16ube(&data
[6], width
);
272 data2
= reinterpret_cast<uint8_t*>(&data
[0]);
273 for(size_t i
= 0; i
< height
; i
++) {
275 encode_words
<1>(data2
+ offset
+ sbpp
* width
* i
, memory
+ stride
* i
, width
);
277 encode_words
<2>(data2
+ offset
+ sbpp
* width
* i
, memory
+ stride
* i
, width
);
279 encode_words
<3>(data2
+ offset
+ sbpp
* width
* i
, memory
+ stride
* i
, width
);
280 else if(bpp
== 4 && sbpp
== 3)
281 encode_words
<5>(data2
+ offset
+ sbpp
* width
* i
, memory
+ stride
* i
, width
);
282 else if(bpp
== 4 && sbpp
== 4)
283 encode_words
<4>(data2
+ offset
+ sbpp
* width
* i
, memory
+ stride
* i
, width
);
287 void framebuffer_raw::save_png(const std::string
& file
) throw(std::bad_alloc
, std::runtime_error
)
289 uint8_t* memory
= reinterpret_cast<uint8_t*>(addr
);
290 uint8_t* buffer
= new uint8_t[3 * static_cast<size_t>(width
) * height
];
291 for(size_t i
= 0; i
< height
; i
++)
292 fmt
->decode(buffer
+ 3 * width
* i
, memory
+ stride
* i
, width
);
294 save_png_data(file
, buffer
, width
, height
);
303 framebuffer
<X
>::framebuffer() throw()
314 active_rshift
= (X
? 32 : 16);
315 active_gshift
= (X
? 16 : 8);
321 framebuffer
<X
>::~framebuffer() throw()
327 #define DECBUF_SIZE 1024
330 void framebuffer
<X
>::copy_from(framebuffer_raw
& scr
, size_t hscale
, size_t vscale
) throw()
332 typename framebuffer
<X
>::element_t decbuf
[DECBUF_SIZE
];
335 for(size_t y
= 0; y
< height
; y
++)
336 memset(rowptr(y
), 0, sizeof(typename framebuffer
<X
>::element_t
) * width
);
339 if(scr
.fmt
!= current_fmt
|| active_rshift
!= auxpal
.rshift
|| active_gshift
!= auxpal
.gshift
||
340 active_bshift
!= auxpal
.bshift
) {
341 scr
.fmt
->set_palette(auxpal
, active_rshift
, active_gshift
, active_bshift
);
342 current_fmt
= scr
.fmt
;
345 for(size_t y
= 0; y
< height
; y
++)
346 memset(rowptr(y
), 0, sizeof(typename framebuffer
<X
>::element_t
) * width
);
347 if(width
< offset_x
|| height
< offset_y
) {
348 //Just clear the screen.
351 size_t copyable_width
= 0, copyable_height
= 0;
353 copyable_width
= (width
- offset_x
) / hscale
;
355 copyable_height
= (height
- offset_y
) / vscale
;
356 copyable_width
= (copyable_width
> scr
.width
) ? scr
.width
: copyable_width
;
357 copyable_height
= (copyable_height
> scr
.height
) ? scr
.height
: copyable_height
;
359 for(size_t y
= 0; y
< copyable_height
; y
++) {
360 size_t line
= y
* vscale
+ offset_y
;
361 const uint8_t* sbase
= reinterpret_cast<uint8_t*>(scr
.addr
) + y
* scr
.stride
;
362 typename framebuffer
<X
>::element_t
* ptr
= rowptr(line
) + offset_x
;
363 size_t bpp
= scr
.fmt
->get_bpp();
365 while(copyable_width
> DECBUF_SIZE
) {
366 scr
.fmt
->decode(decbuf
, sbase
+ xptr
* bpp
, DECBUF_SIZE
, auxpal
);
367 for(size_t k
= 0; k
< DECBUF_SIZE
; k
++)
368 for(size_t i
= 0; i
< hscale
; i
++)
369 *(ptr
++) = decbuf
[k
];
371 copyable_width
-= DECBUF_SIZE
;
373 scr
.fmt
->decode(decbuf
, sbase
+ xptr
* bpp
, copyable_width
, auxpal
);
374 for(size_t k
= 0; k
< copyable_width
; k
++)
375 for(size_t i
= 0; i
< hscale
; i
++)
376 *(ptr
++) = decbuf
[k
];
377 for(size_t j
= 1; j
< vscale
; j
++)
378 memcpy(rowptr(line
+ j
) + offset_x
, rowptr(line
) + offset_x
,
379 sizeof(typename framebuffer
<X
>::element_t
) * hscale
* copyable_width
);
384 void framebuffer
<X
>::set_palette(uint32_t r
, uint32_t g
, uint32_t b
) throw(std::bad_alloc
)
386 typename framebuffer
<X
>::element_t R
, G
, B
;
387 if(r
== active_rshift
&& g
== active_gshift
&& b
== active_bshift
)
389 for(size_t i
= 0; i
< static_cast<size_t>(width
) * height
; i
++) {
390 typename framebuffer
<X
>::element_t word
= mem
[i
];
391 R
= (word
>> active_rshift
) & (X
? 0xFFFF : 0xFF);
392 G
= (word
>> active_gshift
) & (X
? 0xFFFF : 0xFF);
393 B
= (word
>> active_bshift
) & (X
? 0xFFFF : 0xFF);
394 mem
[i
] = (R
<< r
) | (G
<< g
) | (B
<< b
);
402 void framebuffer
<X
>::set(element_t
* _memory
, size_t _width
, size_t _height
, size_t _pitch
) throw()
415 void framebuffer
<X
>::reallocate(size_t _width
, size_t _height
, bool _upside_down
) throw(std::bad_alloc
)
417 if(width
!= _width
|| height
!= _height
) {
419 element_t
* newmem
= new element_t
[_width
* _height
];
423 mem
= new element_t
[_width
* _height
];
425 memset(mem
, 0, sizeof(element_t
) * _width
* _height
);
429 upside_down
= _upside_down
;
434 void framebuffer
<X
>::set_origin(size_t _offset_x
, size_t _offset_y
) throw()
436 offset_x
= _offset_x
;
437 offset_y
= _offset_y
;
441 size_t framebuffer
<X
>::get_width() const throw()
447 size_t framebuffer
<X
>::get_height() const throw()
453 typename framebuffer
<X
>::element_t
* framebuffer
<X
>::rowptr(size_t row
) throw()
456 row
= height
- row
- 1;
457 return mem
+ stride
* row
;
461 const typename framebuffer
<X
>::element_t
* framebuffer
<X
>::rowptr(size_t row
) const throw()
464 row
= height
- row
- 1;
465 return mem
+ stride
* row
;
468 template<bool X
> uint8_t framebuffer
<X
>::get_palette_r() const throw() { return auxpal
.rshift
; }
469 template<bool X
> uint8_t framebuffer
<X
>::get_palette_g() const throw() { return auxpal
.gshift
; }
470 template<bool X
> uint8_t framebuffer
<X
>::get_palette_b() const throw() { return auxpal
.bshift
; }
472 size_t framebuffer_raw::get_width() const throw() { return width
; }
473 size_t framebuffer_raw::get_height() const throw() { return height
; }
474 template<bool X
> size_t framebuffer
<X
>::get_origin_x() const throw() { return offset_x
; }
475 template<bool X
> size_t framebuffer
<X
>::get_origin_y() const throw() { return offset_y
; }
477 void clip_range(uint32_t origin
, uint32_t size
, int32_t base
, int32_t& minc
, int32_t& maxc
) throw()
479 int64_t _origin
= origin
;
480 int64_t _size
= size
;
481 int64_t _base
= base
;
482 int64_t _minc
= minc
;
483 int64_t _maxc
= maxc
;
484 int64_t mincoordinate
= _base
+ _origin
+ _minc
;
485 int64_t maxcoordinate
= _base
+ _origin
+ _maxc
;
486 if(mincoordinate
< 0)
487 _minc
= _minc
- mincoordinate
;
488 if(maxcoordinate
> _size
)
489 _maxc
= _maxc
- (maxcoordinate
- _size
);
499 void render_queue::add(struct render_object
& obj
) throw(std::bad_alloc
)
501 struct node
* n
= reinterpret_cast<struct node
*>(alloc(sizeof(node
)));
506 queue_tail
= queue_tail
->next
= n
;
508 queue_head
= queue_tail
= n
;
511 void render_queue::copy_from(render_queue
& q
) throw(std::bad_alloc
)
513 struct node
* tmp
= q
.queue_head
;
516 tmp
->obj
->clone(*this);
523 template<bool X
> void render_queue::run(struct framebuffer
<X
>& scr
) throw()
525 struct node
* tmp
= queue_head
;
536 void render_queue::clear() throw()
539 if(!queue_head
->killed
)
540 queue_head
->obj
->~render_object();
541 queue_head
= queue_head
->next
;
543 //Release all memory for reuse.
544 memory_allocated
= 0;
549 void* render_queue::alloc(size_t block
) throw(std::bad_alloc
)
551 block
= (block
+ 15) / 16 * 16;
552 if(block
> RENDER_PAGE_SIZE
)
553 throw std::bad_alloc();
554 if(pages
== 0 || memory_allocated
+ block
> pages
* RENDER_PAGE_SIZE
) {
555 memory_allocated
= pages
* RENDER_PAGE_SIZE
;
558 void* mem
= memory
[memory_allocated
/ RENDER_PAGE_SIZE
].content
+ (memory_allocated
% RENDER_PAGE_SIZE
);
559 memory_allocated
+= block
;
563 void render_queue::kill_request(void* obj
) throw()
565 struct node
* tmp
= queue_head
;
568 if(!tmp
->killed
&& tmp
->obj
->kill_request(obj
)) {
571 tmp
->obj
->~render_object();
579 render_queue::render_queue() throw()
583 memory_allocated
= 0;
587 render_queue::~render_queue() throw()
592 render_object::render_object() throw()
596 render_object::~render_object() throw()
600 bool render_object::kill_request_ifeq(void* myobj
, void* killobj
)
609 bool render_object::kill_request(void* obj
) throw()
614 bitmap_font::bitmap_font() throw(std::bad_alloc
)
616 bad_glyph_data
[0] = 0x018001AAU
;
617 bad_glyph_data
[1] = 0x01800180U
;
618 bad_glyph_data
[2] = 0x01800180U
;
619 bad_glyph_data
[3] = 0x55800180U
;
620 bad_glyph
.wide
= false;
621 bad_glyph
.data
= bad_glyph_data
;
624 void bitmap_font::load_hex_glyph(const char* data
, size_t size
) throw(std::bad_alloc
, std::runtime_error
)
627 std::string
line(data
, data
+ size
);
629 if(r
= regex("([0-9A-Fa-f]+):([0-9A-Fa-f]{32})", line
)) {
630 } else if(r
= regex("([0-9A-Fa-f]+):([0-9A-Fa-f]{64})", line
)) {
632 (stringfmt() << "Invalid line '" << line
<< "'").throwex();
633 std::string codepoint
= r
[1];
634 std::string cdata
= r
[2];
635 if(codepoint
.length() > 7)
636 (stringfmt() << "Invalid line '" << line
<< "'").throwex();
637 strcpy(buf2
, codepoint
.c_str());
639 unsigned long cp
= strtoul(buf2
, &end2
, 16);
640 if(*end2
|| cp
> 0x10FFFF)
641 (stringfmt() << "Invalid line '" << line
<< "'").throwex();
642 glyphs
[cp
].wide
= (cdata
.length() == 64);
643 size_t p
= memory
.size();
644 for(size_t i
= 0; i
< cdata
.length(); i
+= 8) {
647 for(size_t j
= 0; j
< 8; j
++)
648 buf
[j
] = cdata
[i
+ j
];
649 memory
.push_back(strtoul(buf
, &end
, 16));
651 glyphs
[cp
].offset
= p
;
654 void bitmap_font::load_hex(const char* data
, size_t size
) throw(std::bad_alloc
, std::runtime_error
)
656 const char* enddata
= data
+ size
;
657 while(data
!= enddata
) {
659 while(data
+ linesize
!= enddata
&& data
[linesize
] != '\n' && data
[linesize
] != '\r')
661 if(linesize
&& data
[0] != '#')
662 load_hex_glyph(data
, linesize
);
671 glyphs
[32].wide
= false;
672 glyphs
[32].offset
= memory
.size() - 4;
673 for(auto& i
: glyphs
)
674 i
.second
.data
= &memory
[i
.second
.offset
];
677 const bitmap_font::glyph
& bitmap_font::get_glyph(uint32_t glyph
) throw()
679 if(glyphs
.count(glyph
))
680 return glyphs
[glyph
];
685 std::pair
<size_t, size_t> bitmap_font::get_metrics(const std::string
& string
) throw()
687 size_t commit_width
= 0;
688 size_t commit_height
= 0;
689 int32_t lineminy
= 0;
690 int32_t linemaxy
= 0;
691 size_t linelength
= 0;
692 uint16_t utfstate
= utf8_initial_state
;
694 size_t maxitr
= string
.length();
696 int ch
= (itr
< maxitr
) ? static_cast<unsigned char>(string
[itr
++]) : -1;
697 int32_t cp
= utf8_parse_byte(ch
, utfstate
);
698 if(cp
< 0 && ch
< 0) {
700 commit_width
= (commit_width
< linelength
) ? linelength
: commit_width
;
701 commit_height
+= (linemaxy
- lineminy
+ 1);
706 const glyph
& g
= get_glyph(cp
);
709 linelength
= (linelength
+ TABSTOPS
) / TABSTOPS
* TABSTOPS
;
712 commit_width
= (commit_width
< linelength
) ? linelength
: commit_width
;
716 linelength
= linelength
+ (g
.wide
? 16 : 8);
720 return std::make_pair(commit_width
, commit_height
);
723 std::vector
<bitmap_font::layout
> bitmap_font::dolayout(const std::string
& string
) throw(std::bad_alloc
)
725 //First, calculate the number of glyphs to draw.
726 uint16_t utfstate
= utf8_initial_state
;
728 size_t maxitr
= string
.length();
731 int ch
= (itr
< maxitr
) ? static_cast<unsigned char>(string
[itr
++]) : -1;
732 int32_t cp
= utf8_parse_byte(ch
, utfstate
);
735 if(cp
!= 9 && cp
!= 10)
739 std::vector
<layout
> l
;
745 utfstate
= utf8_initial_state
;
747 int ch
= (itr
< maxitr
) ? static_cast<unsigned char>(string
[itr
++]) : -1;
748 int32_t cp
= utf8_parse_byte(ch
, utfstate
);
751 const glyph
& g
= get_glyph(cp
);
754 layout_x
= (layout_x
+ TABSTOPS
) / TABSTOPS
* TABSTOPS
;
758 layout_y
= layout_y
+ 16;
763 l
[gtr
++].dglyph
= &g
;
764 layout_x
= layout_x
+ (g
.wide
? 16 : 8);;
770 template<bool X
> void bitmap_font::render(struct framebuffer
<X
>& scr
, int32_t x
, int32_t y
, const std::string
& text
,
771 premultiplied_color fg
, premultiplied_color bg
, bool hdbl
, bool vdbl
) throw()
773 x
+= scr
.get_origin_x();
774 y
+= scr
.get_origin_y();
775 uint16_t utfstate
= utf8_initial_state
;
777 size_t maxitr
= text
.length();
780 size_t swidth
= scr
.get_width();
781 size_t sheight
= scr
.get_width();
783 int ch
= (itr
< maxitr
) ? static_cast<unsigned char>(text
[itr
++]) : -1;
784 int32_t cp
= utf8_parse_byte(ch
, utfstate
);
787 const glyph
& g
= get_glyph(cp
);
790 layout_x
= (layout_x
+ TABSTOPS
) / TABSTOPS
* TABSTOPS
;
794 layout_y
= layout_y
+ (vdbl
? 32 : 16);
797 //Render this glyph at x + layout_x, y + layout_y.
798 int32_t gx
= x
+ layout_x
;
799 int32_t gy
= y
+ layout_y
;
800 //Don't draw characters completely off-screen.
801 if(gy
<= (vdbl
? -32 : -16) || gy
>= (ssize_t
)sheight
)
803 if(gx
<= -(hdbl
? 2 : 1) * (g
.wide
? 16 : 8) || gx
>= (ssize_t
)swidth
)
805 //Compute the bounding box.
808 uint32_t xlength
= (hdbl
? 2 : 1) * (g
.wide
? 16 : 8);
809 uint32_t ylength
= (vdbl
? 32 : 16);
810 if(gx
< 0) xstart
= -gx
;
811 if(gy
< 0) ystart
= -gy
;
814 if(gx
+ xlength
> swidth
) xlength
= swidth
- gx
;
815 if(gy
+ ylength
> sheight
) ylength
= sheight
- gy
;
817 for(size_t i
= 0; i
< ylength
; i
++) {
818 typename framebuffer
<X
>::element_t
* r
= scr
.rowptr(gy
+ ystart
+ i
) +
820 uint32_t _y
= (i
+ ystart
) >> (vdbl
? 1 : 0);
821 uint32_t d
= g
.data
[_y
>> (g
.wide
? 1 : 2)];
823 d
>>= 16 - ((_y
& 1) << 4);
825 d
>>= 24 - ((_y
& 3) << 3);
827 for(size_t j
= 0; j
< xlength
; j
++) {
828 uint32_t b
= (g
.wide
? 15 : 7) - ((j
+ xstart
) >> 1);
829 if(((d
>> b
) & 1) != 0)
835 for(size_t j
= 0; j
< xlength
; j
++) {
836 uint32_t b
= (g
.wide
? 15 : 7) - (j
+ xstart
);
837 if(((d
>> b
) & 1) != 0)
844 for(size_t i
= 0; i
< ylength
; i
++) {
845 typename framebuffer
<X
>::element_t
* r
= scr
.rowptr(gy
+ ystart
+ i
) +
847 for(size_t j
= 0; j
< xlength
; j
++)
850 layout_x
+= (hdbl
? 2 : 1) * (g
.wide
? 16 : 8);
855 void premultiplied_color::set_palette(unsigned rshift
, unsigned gshift
, unsigned bshift
, bool X
) throw()
858 uint64_t r
= ((orig
>> 16) & 0xFF) * 257;
859 uint64_t g
= ((orig
>> 8) & 0xFF) * 257;
860 uint64_t b
= (orig
& 0xFF) * 257;
861 uint64_t color
= (r
<< rshift
) | (g
<< gshift
) | (b
<< bshift
);
862 hiHI
= color
& 0xFFFF0000FFFFULL
;
863 loHI
= (color
& 0xFFFF0000FFFF0000ULL
) >> 16;
864 hiHI
*= (static_cast<uint32_t>(origa
) * 256);
865 loHI
*= (static_cast<uint32_t>(origa
) * 256);
867 uint32_t r
= (orig
>> 16) & 0xFF;
868 uint32_t g
= (orig
>> 8) & 0xFF;
869 uint32_t b
= orig
& 0xFF;
870 uint32_t color
= (r
<< rshift
) | (g
<< gshift
) | (b
<< bshift
);
871 hi
= color
& 0xFF00FF;
872 lo
= (color
& 0xFF00FF00) >> 8;
878 template class framebuffer
<false>;
879 template class framebuffer
<true>;
880 template void render_queue::run(struct framebuffer
<false>&);
881 template void render_queue::run(struct framebuffer
<true>&);
882 template void bitmap_font::render(struct framebuffer
<false>& scr
, int32_t x
, int32_t y
, const std::string
& text
,
883 premultiplied_color fg
, premultiplied_color bg
, bool hdbl
, bool vdbl
) throw();
884 template void bitmap_font::render(struct framebuffer
<true>& scr
, int32_t x
, int32_t y
, const std::string
& text
,
885 premultiplied_color fg
, premultiplied_color bg
, bool hdbl
, bool vdbl
) throw();