9 uint8_t const *data_ptr
;
11 } sprite_column_iterator
;
13 static inline int8_t i8min( int8_t x
, int8_t y
) { return x
< y
? x
: y
; }
14 static inline int8_t i8max( int8_t x
, int8_t y
) { return x
< y
? y
: x
; }
15 static inline uint8_t u8min(uint8_t x
, uint8_t y
) { return x
< y
? x
: y
; }
16 static inline uint8_t u8max(uint8_t x
, uint8_t y
) { return x
< y
? y
: x
; }
18 static inline sprite_column_iterator
sprite_column_iterator_init(badge_sprite
const *sprite
, uint8_t xskip
) {
19 sprite_column_iterator result
= { sprite
->data
, CHAR_BIT
};
22 int skip_bits
= (xskip
* sprite
->height
);
24 result
.data_ptr
+= skip_bits
/ CHAR_BIT
;
25 result
.left_in_byte
= CHAR_BIT
- skip_bits
% 8;
31 static inline uint32_t sprite_column_iterator_pop(sprite_column_iterator
*iter
, uint8_t height
) {
34 if(iter
->left_in_byte
> height
) {
35 column
= *iter
->data_ptr
>> (CHAR_BIT
- iter
->left_in_byte
) & ((1 << height
) - 1);
36 iter
->left_in_byte
-= height
;
38 column
= *iter
->data_ptr
>> (CHAR_BIT
- iter
->left_in_byte
);
40 uint8_t shlen
= iter
->left_in_byte
;
43 for(n
= height
- shlen
; n
>= CHAR_BIT
; n
-= CHAR_BIT
) {
44 column
|= *++iter
->data_ptr
<< shlen
;
48 column
|= (*++iter
->data_ptr
& ((1 << n
) - 1)) << shlen
;
49 iter
->left_in_byte
= CHAR_BIT
- n
;
55 void badge_framebuffer_blt(badge_framebuffer
*fb
,
58 badge_sprite
const *sprite
,
61 if(y
>= BADGE_DISPLAY_HEIGHT
||
62 x
>= BADGE_DISPLAY_WIDTH
||
63 y
<= -sprite
->height
||
64 x
<= -sprite
->width
) {
69 int8_t y_major
= y
/ BADGE_DISPLAY_STRIPE_HEIGHT
- (y
< 0);
70 uint8_t y_minor
= (uint8_t) (y
- y_major
* BADGE_DISPLAY_STRIPE_HEIGHT
);
77 if(flags
& BADGE_BLT_MIRRORED
) {
79 xcursor
= i8min(x
+ sprite
->width
, BADGE_DISPLAY_WIDTH
) - 1;
80 xend
= i8max(x
, 0) - 1;
81 xskip
= x
+ sprite
->width
- xcursor
- 1;
84 xcursor
= i8max(x
, 0);
85 xend
= i8min(x
+ sprite
->width
, BADGE_DISPLAY_WIDTH
);
89 sprite_column_iterator col_iter
= sprite_column_iterator_init(sprite
, xskip
);
91 while(xcursor
!= xend
) {
92 uint32_t column
= sprite_column_iterator_pop(&col_iter
, sprite
->height
);
96 assert(xcursor < BADGE_DISPLAY_WIDTH);
100 fb
->data
[y_major
][xcursor
] |= (uint8_t) column
<< y_minor
;
103 uint8_t stripe_max
= u8min((sprite
->height
+ y_minor
- 1) / BADGE_DISPLAY_STRIPE_HEIGHT
,
104 BADGE_DISPLAY_STRIPE_COUNT
- y_major
- 1);
106 for(uint8_t stripe_ptr
= i8max(1, -y_major
); stripe_ptr
<= stripe_max
; ++stripe_ptr
) {
108 assert(y_major + stripe_ptr >= 0);
109 assert(y_major + stripe_ptr < BADGE_DISPLAY_STRIPE_COUNT);
112 fb
->data
[y_major
+ stripe_ptr
][xcursor
] |= (uint8_t) (column
>> (stripe_ptr
* BADGE_DISPLAY_STRIPE_HEIGHT
- y_minor
));