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
)));
505 queue_tail
= queue_tail
->next
= n
;
507 queue_head
= queue_tail
= n
;
510 template<bool X
> void render_queue::run(struct framebuffer
<X
>& scr
) throw()
512 struct node
* tmp
= queue_head
;
522 void render_queue::clear() throw()
525 queue_head
->obj
->~render_object();
526 queue_head
= queue_head
->next
;
528 //Release all memory for reuse.
529 memory_allocated
= 0;
534 void* render_queue::alloc(size_t block
) throw(std::bad_alloc
)
536 block
= (block
+ 15) / 16 * 16;
537 if(block
> RENDER_PAGE_SIZE
)
538 throw std::bad_alloc();
539 if(pages
== 0 || memory_allocated
+ block
> pages
* RENDER_PAGE_SIZE
) {
540 memory_allocated
= pages
* RENDER_PAGE_SIZE
;
543 void* mem
= memory
[memory_allocated
/ RENDER_PAGE_SIZE
].content
+ (memory_allocated
% RENDER_PAGE_SIZE
);
544 memory_allocated
+= block
;
548 render_queue::render_queue() throw()
552 memory_allocated
= 0;
556 render_queue::~render_queue() throw()
561 render_object::~render_object() throw()
565 bitmap_font::bitmap_font() throw(std::bad_alloc
)
567 bad_glyph_data
[0] = 0x018001AAU
;
568 bad_glyph_data
[1] = 0x01800180U
;
569 bad_glyph_data
[2] = 0x01800180U
;
570 bad_glyph_data
[3] = 0x55800180U
;
571 bad_glyph
.wide
= false;
572 bad_glyph
.data
= bad_glyph_data
;
575 void bitmap_font::load_hex_glyph(const char* data
, size_t size
) throw(std::bad_alloc
, std::runtime_error
)
578 std::string
line(data
, data
+ size
);
580 if(r
= regex("([0-9A-Fa-f]+):([0-9A-Fa-f]{32})", line
)) {
581 } else if(r
= regex("([0-9A-Fa-f]+):([0-9A-Fa-f]{64})", line
)) {
583 (stringfmt() << "Invalid line '" << line
<< "'").throwex();
584 std::string codepoint
= r
[1];
585 std::string cdata
= r
[2];
586 if(codepoint
.length() > 7)
587 (stringfmt() << "Invalid line '" << line
<< "'").throwex();
588 strcpy(buf2
, codepoint
.c_str());
590 unsigned long cp
= strtoul(buf2
, &end2
, 16);
591 if(*end2
|| cp
> 0x10FFFF)
592 (stringfmt() << "Invalid line '" << line
<< "'").throwex();
593 glyphs
[cp
].wide
= (cdata
.length() == 64);
594 size_t p
= memory
.size();
595 for(size_t i
= 0; i
< cdata
.length(); i
+= 8) {
598 for(size_t j
= 0; j
< 8; j
++)
599 buf
[j
] = cdata
[i
+ j
];
600 memory
.push_back(strtoul(buf
, &end
, 16));
602 glyphs
[cp
].offset
= p
;
605 void bitmap_font::load_hex(const char* data
, size_t size
) throw(std::bad_alloc
, std::runtime_error
)
607 const char* enddata
= data
+ size
;
609 while(data
!= enddata
) {
611 while(data
+ linesize
!= enddata
&& data
[linesize
] != '\n' && data
[linesize
] != '\r')
613 if(linesize
&& data
[0] != '#')
614 load_hex_glyph(data
, linesize
);
623 glyphs
[32].wide
= false;
624 glyphs
[32].offset
= memory
.size() - 4;
625 for(auto& i
: glyphs
)
626 i
.second
.data
= &memory
[i
.second
.offset
];
629 const bitmap_font::glyph
& bitmap_font::get_glyph(uint32_t glyph
) throw()
631 if(glyphs
.count(glyph
))
632 return glyphs
[glyph
];
637 std::pair
<size_t, size_t> bitmap_font::get_metrics(const std::string
& string
) throw()
639 size_t commit_width
= 0;
640 size_t commit_height
= 0;
641 int32_t lineminy
= 0;
642 int32_t linemaxy
= 0;
643 size_t linelength
= 0;
644 uint16_t utfstate
= utf8_initial_state
;
646 size_t maxitr
= string
.length();
648 int ch
= (itr
< maxitr
) ? static_cast<unsigned char>(string
[itr
++]) : -1;
649 int32_t cp
= utf8_parse_byte(ch
, utfstate
);
650 if(cp
< 0 && ch
< 0) {
652 commit_width
= (commit_width
< linelength
) ? linelength
: commit_width
;
653 commit_height
+= (linemaxy
- lineminy
+ 1);
658 const glyph
& g
= get_glyph(cp
);
661 linelength
= (linelength
+ TABSTOPS
) / TABSTOPS
* TABSTOPS
;
664 commit_width
= (commit_width
< linelength
) ? linelength
: commit_width
;
668 linelength
= linelength
+ (g
.wide
? 16 : 8);
672 return std::make_pair(commit_width
, commit_height
);
675 std::vector
<bitmap_font::layout
> bitmap_font::dolayout(const std::string
& string
) throw(std::bad_alloc
)
677 //First, calculate the number of glyphs to draw.
678 uint16_t utfstate
= utf8_initial_state
;
680 size_t maxitr
= string
.length();
683 int ch
= (itr
< maxitr
) ? static_cast<unsigned char>(string
[itr
++]) : -1;
684 int32_t cp
= utf8_parse_byte(ch
, utfstate
);
687 if(cp
!= 9 && cp
!= 10)
691 std::vector
<layout
> l
;
697 utfstate
= utf8_initial_state
;
699 int ch
= (itr
< maxitr
) ? static_cast<unsigned char>(string
[itr
++]) : -1;
700 int32_t cp
= utf8_parse_byte(ch
, utfstate
);
703 const glyph
& g
= get_glyph(cp
);
706 layout_x
= (layout_x
+ TABSTOPS
) / TABSTOPS
* TABSTOPS
;
710 layout_y
= layout_y
+ 16;
715 l
[gtr
++].dglyph
= &g
;
716 layout_x
= layout_x
+ (g
.wide
? 16 : 8);;
722 template<bool X
> void bitmap_font::render(struct framebuffer
<X
>& scr
, int32_t x
, int32_t y
, const std::string
& text
,
723 premultiplied_color fg
, premultiplied_color bg
, bool hdbl
, bool vdbl
) throw()
725 x
+= scr
.get_origin_x();
726 y
+= scr
.get_origin_y();
727 uint16_t utfstate
= utf8_initial_state
;
729 size_t maxitr
= text
.length();
732 size_t swidth
= scr
.get_width();
733 size_t sheight
= scr
.get_width();
735 int ch
= (itr
< maxitr
) ? static_cast<unsigned char>(text
[itr
++]) : -1;
736 int32_t cp
= utf8_parse_byte(ch
, utfstate
);
739 const glyph
& g
= get_glyph(cp
);
742 layout_x
= (layout_x
+ TABSTOPS
) / TABSTOPS
* TABSTOPS
;
746 layout_y
= layout_y
+ (vdbl
? 32 : 16);
749 //Render this glyph at x + layout_x, y + layout_y.
750 int32_t gx
= x
+ layout_x
;
751 int32_t gy
= y
+ layout_y
;
752 //Don't draw characters completely off-screen.
753 if(gy
<= (vdbl
? -32 : -16) || gy
>= sheight
)
755 if(gx
<= -(hdbl
? 2 : 1) * (g
.wide
? 16 : 8) || gx
>= swidth
)
757 //Compute the bounding box.
760 uint32_t xlength
= (hdbl
? 2 : 1) * (g
.wide
? 16 : 8);
761 uint32_t ylength
= (vdbl
? 32 : 16);
762 if(gx
< 0) xstart
= -gx
;
763 if(gy
< 0) ystart
= -gy
;
766 if(gx
+ xlength
> swidth
) xlength
= swidth
- gx
;
767 if(gy
+ ylength
> sheight
) ylength
= sheight
- gy
;
769 for(size_t i
= 0; i
< ylength
; i
++) {
770 typename framebuffer
<X
>::element_t
* r
= scr
.rowptr(gy
+ ystart
+ i
) +
772 uint32_t _y
= (i
+ ystart
) >> (vdbl
? 1 : 0);
773 uint32_t d
= g
.data
[_y
>> (g
.wide
? 1 : 2)];
775 d
>>= 16 - ((_y
& 1) << 4);
777 d
>>= 24 - ((_y
& 3) << 3);
779 for(size_t j
= 0; j
< xlength
; j
++) {
780 uint32_t b
= (g
.wide
? 15 : 7) - ((j
+ xstart
) >> 1);
781 if(((d
>> b
) & 1) != 0)
787 for(size_t j
= 0; j
< xlength
; j
++) {
788 uint32_t b
= (g
.wide
? 15 : 7) - (j
+ xstart
);
789 if(((d
>> b
) & 1) != 0)
796 for(size_t i
= 0; i
< ylength
; i
++) {
797 typename framebuffer
<X
>::element_t
* r
= scr
.rowptr(gy
+ ystart
+ i
) +
799 for(size_t j
= 0; j
< xlength
; j
++)
802 layout_x
+= (hdbl
? 2 : 1) * (g
.wide
? 16 : 8);
807 void premultiplied_color::set_palette(unsigned rshift
, unsigned gshift
, unsigned bshift
, bool X
) throw()
810 uint64_t r
= ((orig
>> 16) & 0xFF) * 257;
811 uint64_t g
= ((orig
>> 8) & 0xFF) * 257;
812 uint64_t b
= (orig
& 0xFF) * 257;
813 uint64_t color
= (r
<< rshift
) | (g
<< gshift
) | (b
<< bshift
);
814 hiHI
= color
& 0xFFFF0000FFFFULL
;
815 loHI
= (color
& 0xFFFF0000FFFF0000ULL
) >> 16;
816 hiHI
*= (static_cast<uint32_t>(origa
) * 256);
817 loHI
*= (static_cast<uint32_t>(origa
) * 256);
819 uint32_t r
= (orig
>> 16) & 0xFF;
820 uint32_t g
= (orig
>> 8) & 0xFF;
821 uint32_t b
= orig
& 0xFF;
822 uint32_t color
= (r
<< rshift
) | (g
<< gshift
) | (b
<< bshift
);
823 hi
= color
& 0xFF00FF;
824 lo
= (color
& 0xFF00FF00) >> 8;
830 template class framebuffer
<false>;
831 template class framebuffer
<true>;
832 template void render_queue::run(struct framebuffer
<false>&);
833 template void render_queue::run(struct framebuffer
<true>&);
834 template void bitmap_font::render(struct framebuffer
<false>& scr
, int32_t x
, int32_t y
, const std::string
& text
,
835 premultiplied_color fg
, premultiplied_color bg
, bool hdbl
, bool vdbl
) throw();
836 template void bitmap_font::render(struct framebuffer
<true>& scr
, int32_t x
, int32_t y
, const std::string
& text
,
837 premultiplied_color fg
, premultiplied_color bg
, bool hdbl
, bool vdbl
) throw();