diff --git a/libfreerdp/codec/bitmap.c b/libfreerdp/codec/bitmap.c index 0bba3ad46..c0d25653b 100644 --- a/libfreerdp/codec/bitmap.c +++ b/libfreerdp/codec/bitmap.c @@ -25,6 +25,24 @@ #include #include +struct count +{ + ALIGN64 UINT16 bicolor_count; + ALIGN64 UINT16 fill_count; + ALIGN64 UINT16 color_count; + ALIGN64 UINT16 mix_count; + ALIGN64 UINT16 fom_count; + ALIGN64 size_t fom_mask_len; + ALIGN64 BOOL bicolor_spin; +}; + +static inline void reset_counts(struct count* counts) +{ + const struct count empty = { 0 }; + WINPR_ASSERT(counts); + *counts = empty; +} + static inline UINT16 GETPIXEL16(const void* WINPR_RESTRICT d, UINT32 x, UINT32 y, UINT32 w) { const BYTE* WINPR_RESTRICT src = (const BYTE*)d + ((y * w + x) * sizeof(UINT16)); @@ -91,8 +109,6 @@ static inline UINT16 out_color_count_2(UINT16 in_count, wStream* WINPR_RESTRICT return 0; } -#define OUT_COLOR_COUNT2(in_count, in_s, in_data) \ - in_count = out_color_count_2(in_count, in_s, in_data) /*****************************************************************************/ /* color */ @@ -127,9 +143,6 @@ static inline UINT16 out_color_count_3(UINT16 in_count, wStream* WINPR_RESTRICT return 0; } -#define OUT_COLOR_COUNT3(in_count, in_s, in_data) \ - in_count = out_color_count_3(in_count, in_s, in_data) - /*****************************************************************************/ /* copy */ static inline UINT16 out_copy_count_2(UINT16 in_count, wStream* WINPR_RESTRICT in_s, @@ -161,8 +174,7 @@ static inline UINT16 out_copy_count_2(UINT16 in_count, wStream* WINPR_RESTRICT i Stream_SetPosition(in_data, 0); return 0; } -#define OUT_COPY_COUNT2(in_count, in_s, in_data) \ - in_count = out_copy_count_2(in_count, in_s, in_data) + /*****************************************************************************/ /* copy */ static inline UINT16 out_copy_count_3(UINT16 in_count, wStream* WINPR_RESTRICT in_s, @@ -193,8 +205,6 @@ static inline UINT16 out_copy_count_3(UINT16 in_count, wStream* WINPR_RESTRICT i Stream_SetPosition(in_data, 0); return 0; } -#define OUT_COPY_COUNT3(in_count, in_s, in_data) \ - in_count = out_copy_count_3(in_count, in_s, in_data) /*****************************************************************************/ /* bicolor */ @@ -227,9 +237,6 @@ static inline UINT16 out_bicolor_count_2(UINT16 in_count, wStream* WINPR_RESTRIC return 0; } -#define OUT_BICOLOR_COUNT2(in_count, in_s, in_color1, in_color2) \ - in_count = out_bicolor_count_2(in_count, in_s, in_color1, in_color2) - /*****************************************************************************/ /* bicolor */ static inline UINT16 out_bicolor_count_3(UINT16 in_count, wStream* WINPR_RESTRICT in_s, @@ -265,9 +272,6 @@ static inline UINT16 out_bicolor_count_3(UINT16 in_count, wStream* WINPR_RESTRIC return 0; } -#define OUT_BICOLOR_COUNT3(in_count, in_s, in_color1, in_color2) \ - in_count = out_bicolor_count_3(in_count, in_s, in_color1, in_color2) - /*****************************************************************************/ /* fill */ static inline UINT16 out_fill_count_2(UINT16 in_count, wStream* WINPR_RESTRICT in_s) @@ -294,8 +298,6 @@ static inline UINT16 out_fill_count_2(UINT16 in_count, wStream* WINPR_RESTRICT i return 0; } -#define OUT_FILL_COUNT2(in_count, in_s) in_count = out_fill_count_2(in_count, in_s) - /*****************************************************************************/ /* fill */ static inline UINT16 out_fill_count_3(UINT16 in_count, wStream* WINPR_RESTRICT in_s) @@ -321,39 +323,10 @@ static inline UINT16 out_fill_count_3(UINT16 in_count, wStream* WINPR_RESTRICT i return 0; } -#define OUT_FILL_COUNT3(in_count, in_s) in_count = out_fill_count_3(in_count, in_s) /*****************************************************************************/ /* mix */ -static inline UINT16 out_mix_count_2(UINT16 in_count, wStream* WINPR_RESTRICT in_s) -{ - if (in_count > 0) - { - if (in_count < 32) - { - const BYTE temp = ((0x1 << 5) | in_count) & 0xFF; - Stream_Write_UINT8(in_s, temp); - } - else if (in_count < 256 + 32) - { - const BYTE temp = (in_count - 32) & 0xFF; - Stream_Write_UINT8(in_s, 0x20); - Stream_Write_UINT8(in_s, temp); - } - else - { - Stream_Write_UINT8(in_s, 0xf1); - Stream_Write_UINT16(in_s, in_count); - } - } - - return 0; -} -#define OUT_MIX_COUNT2(in_count, in_s) in_count = out_mix_count_2(in_count, in_s) - -/*****************************************************************************/ -/* mix */ -static inline UINT16 out_mix_count_3(UINT16 in_count, wStream* WINPR_RESTRICT in_s) +static inline UINT16 out_counts_mix_count_2(UINT16 in_count, wStream* WINPR_RESTRICT in_s) { if (in_count > 0) { @@ -378,12 +351,37 @@ static inline UINT16 out_mix_count_3(UINT16 in_count, wStream* WINPR_RESTRICT in return 0; } -#define OUT_MIX_COUNT3(in_count, in_s) in_count = out_mix_count_3(in_count, in_s) +/*****************************************************************************/ +/* mix */ +static inline UINT16 out_counts_mix_count_3(UINT16 in_count, wStream* WINPR_RESTRICT in_s) +{ + if (in_count > 0) + { + if (in_count < 32) + { + const BYTE temp = ((0x1 << 5) | in_count) & 0xFF; + Stream_Write_UINT8(in_s, temp); + } + else if (in_count < 256 + 32) + { + const BYTE temp = (in_count - 32) & 0xFF; + Stream_Write_UINT8(in_s, 0x20); + Stream_Write_UINT8(in_s, temp); + } + else + { + Stream_Write_UINT8(in_s, 0xf1); + Stream_Write_UINT16(in_s, in_count); + } + } + + return 0; +} /*****************************************************************************/ /* fom */ static inline UINT16 out_from_count_2(UINT16 in_count, wStream* WINPR_RESTRICT in_s, - const int8_t* WINPR_RESTRICT in_mask, size_t in_mask_len) + const uint8_t* WINPR_RESTRICT in_mask, size_t in_mask_len) { if (in_count > 0) { @@ -409,13 +407,11 @@ static inline UINT16 out_from_count_2(UINT16 in_count, wStream* WINPR_RESTRICT i return 0; } -#define OUT_FOM_COUNT2(in_count, in_s, in_mask, in_mask_len) \ - in_count = out_from_count_2(in_count, in_s, in_mask, in_mask_len) /*****************************************************************************/ /* fill or mix (fom) */ static inline UINT16 out_from_count_3(UINT16 in_count, wStream* WINPR_RESTRICT in_s, - const int8_t* WINPR_RESTRICT in_mask, size_t in_mask_len) + const uint8_t* WINPR_RESTRICT in_mask, size_t in_mask_len) { if (in_count > 0) { @@ -441,28 +437,16 @@ static inline UINT16 out_from_count_3(UINT16 in_count, wStream* WINPR_RESTRICT i return 0; } -#define OUT_FOM_COUNT3(in_count, in_s, in_mask, in_mask_len) \ - in_count = out_from_count_3(in_count, in_s, in_mask, in_mask_len) #define TEST_FILL ((last_line == 0 && pixel == 0) || (last_line != 0 && pixel == ypixel)) #define TEST_MIX ((last_line == 0 && pixel == mix) || (last_line != 0 && pixel == (ypixel ^ mix))) #define TEST_FOM TEST_FILL || TEST_MIX #define TEST_COLOR pixel == last_pixel -#define TEST_BICOLOR \ - ((pixel != last_pixel) && \ - ((!bicolor_spin && (pixel == bicolor1) && (last_pixel == bicolor2)) || \ - (bicolor_spin && (pixel == bicolor2) && (last_pixel == bicolor1)))) -#define RESET_COUNTS \ - do \ - { \ - bicolor_count = 0; \ - fill_count = 0; \ - color_count = 0; \ - mix_count = 0; \ - fom_count = 0; \ - fom_mask_len = 0; \ - bicolor_spin = FALSE; \ - } while (0) + +#define test_bicolor(counts) \ + ((pixel != last_pixel) && \ + ((!(counts)->bicolor_spin && (pixel == bicolor1) && (last_pixel == bicolor2)) || \ + ((counts)->bicolor_spin && (pixel == bicolor2) && (last_pixel == bicolor1)))) static inline SSIZE_T freerdp_bitmap_compress_24(const void* WINPR_RESTRICT srcData, UINT32 width, WINPR_ATTR_UNUSED UINT32 height, @@ -470,23 +454,17 @@ static inline SSIZE_T freerdp_bitmap_compress_24(const void* WINPR_RESTRICT srcD UINT32 start_line, wStream* WINPR_RESTRICT temp_s, UINT32 e) { - int8_t fom_mask[8192] = { 0 }; /* good for up to 64K bitmap */ + uint8_t fom_mask[8192] = { 0 }; /* good for up to 64K bitmap */ SSIZE_T lines_sent = 0; UINT16 count = 0; - UINT16 color_count = 0; UINT32 last_pixel = 0; UINT32 last_ypixel = 0; - UINT16 bicolor_count = 0; + struct count counts = { 0 }; UINT32 bicolor1 = 0; UINT32 bicolor2 = 0; - BOOL bicolor_spin = FALSE; UINT32 end = width + e; UINT32 out_count = end * 3; - UINT16 fill_count = 0; - UINT16 mix_count = 0; const UINT32 mix = 0xFFFFFF; - UINT16 fom_count = 0; - size_t fom_mask_len = 0; const char* start = (const char*)srcData; const char* line = start + 4ULL * width * start_line; const char* last_line = NULL; @@ -495,9 +473,11 @@ static inline SSIZE_T freerdp_bitmap_compress_24(const void* WINPR_RESTRICT srcD { size_t i = Stream_GetPosition(s) + 3ULL * count; - if ((i - (3ULL * color_count) >= byte_limit) && - (i - (3ULL * bicolor_count) >= byte_limit) && (i - (3ULL * fill_count) >= byte_limit) && - (i - (3ULL * mix_count) >= byte_limit) && (i - (3ULL * fom_count) >= byte_limit)) + if ((i - (3ULL * counts.color_count) >= byte_limit) && + (i - (3ULL * counts.bicolor_count) >= byte_limit) && + (i - (3ULL * counts.fill_count) >= byte_limit) && + (i - (3ULL * counts.mix_count) >= byte_limit) && + (i - (3ULL * counts.fom_count) >= byte_limit)) { break; } @@ -512,135 +492,143 @@ static inline SSIZE_T freerdp_bitmap_compress_24(const void* WINPR_RESTRICT srcD if (!TEST_FILL) { - if (fill_count > 3 && fill_count >= color_count && fill_count >= bicolor_count && - fill_count >= mix_count && fill_count >= fom_count) + if (counts.fill_count > 3 && counts.fill_count >= counts.color_count && + counts.fill_count >= counts.bicolor_count && + counts.fill_count >= counts.mix_count && counts.fill_count >= counts.fom_count) { - if (fill_count > count) + if (counts.fill_count > count) return -1; - count -= fill_count; - OUT_COPY_COUNT3(count, s, temp_s); - OUT_FILL_COUNT3(fill_count, s); - RESET_COUNTS; + count -= counts.fill_count; + count = out_copy_count_3(count, s, temp_s); + counts.fill_count = out_fill_count_3(counts.fill_count, s); + reset_counts(&counts); } - fill_count = 0; + counts.fill_count = 0; } if (!TEST_MIX) { - if (mix_count > 3 && mix_count >= fill_count && mix_count >= bicolor_count && - mix_count >= color_count && mix_count >= fom_count) + if (counts.mix_count > 3 && counts.mix_count >= counts.fill_count && + counts.mix_count >= counts.bicolor_count && + counts.mix_count >= counts.color_count && counts.mix_count >= counts.fom_count) { - if (mix_count > count) + if (counts.mix_count > count) return -1; - count -= mix_count; - OUT_COPY_COUNT3(count, s, temp_s); - OUT_MIX_COUNT3(mix_count, s); - RESET_COUNTS; + count -= counts.mix_count; + count = out_copy_count_3(count, s, temp_s); + counts.mix_count = out_counts_mix_count_3(counts.mix_count, s); + reset_counts(&counts); } - mix_count = 0; + counts.mix_count = 0; } if (!(TEST_COLOR)) { - if (color_count > 3 && color_count >= fill_count && color_count >= bicolor_count && - color_count >= mix_count && color_count >= fom_count) + if (counts.color_count > 3 && counts.color_count >= counts.fill_count && + counts.color_count >= counts.bicolor_count && + counts.color_count >= counts.mix_count && + counts.color_count >= counts.fom_count) { - if (color_count > count) + if (counts.color_count > count) return -1; - count -= color_count; - OUT_COPY_COUNT3(count, s, temp_s); - OUT_COLOR_COUNT3(color_count, s, last_pixel); - RESET_COUNTS; + count -= counts.color_count; + count = out_copy_count_3(count, s, temp_s); + counts.color_count = out_color_count_3(counts.color_count, s, last_pixel); + reset_counts(&counts); } - color_count = 0; + counts.color_count = 0; } - if (!TEST_BICOLOR) + if (!test_bicolor(&counts)) { - if (bicolor_count > 3 && bicolor_count >= fill_count && - bicolor_count >= color_count && bicolor_count >= mix_count && - bicolor_count >= fom_count) + if (counts.bicolor_count > 3 && counts.bicolor_count >= counts.fill_count && + counts.bicolor_count >= counts.color_count && + counts.bicolor_count >= counts.mix_count && + counts.bicolor_count >= counts.fom_count) { - if ((bicolor_count % 2) != 0) - bicolor_count--; + if ((counts.bicolor_count % 2) != 0) + counts.bicolor_count--; - if (bicolor_count > count) + if (counts.bicolor_count > count) return -1; - count -= bicolor_count; - OUT_COPY_COUNT3(count, s, temp_s); - OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor2, bicolor1); - RESET_COUNTS; + count -= counts.bicolor_count; + count = out_copy_count_3(count, s, temp_s); + counts.bicolor_count = + out_bicolor_count_3(counts.bicolor_count, s, bicolor2, bicolor1); + reset_counts(&counts); } - bicolor_count = 0; + counts.bicolor_count = 0; bicolor1 = last_pixel; bicolor2 = pixel; - bicolor_spin = FALSE; + counts.bicolor_spin = FALSE; } if (!(TEST_FOM)) { - if (fom_count > 3 && fom_count >= fill_count && fom_count >= color_count && - fom_count >= mix_count && fom_count >= bicolor_count) + if (counts.fom_count > 3 && counts.fom_count >= counts.fill_count && + counts.fom_count >= counts.color_count && + counts.fom_count >= counts.mix_count && + counts.fom_count >= counts.bicolor_count) { - if (fom_count > count) + if (counts.fom_count > count) return -1; - count -= fom_count; - OUT_COPY_COUNT3(count, s, temp_s); - OUT_FOM_COUNT3(fom_count, s, fom_mask, fom_mask_len); - RESET_COUNTS; + count -= counts.fom_count; + count = out_copy_count_3(count, s, temp_s); + counts.fom_count = + out_from_count_3(counts.fom_count, s, fom_mask, counts.fom_mask_len); + reset_counts(&counts); } - fom_count = 0; - fom_mask_len = 0; + counts.fom_count = 0; + counts.fom_mask_len = 0; } if (TEST_FILL) { - fill_count++; + counts.fill_count++; } if (TEST_MIX) { - mix_count++; + counts.mix_count++; } if (TEST_COLOR) { - color_count++; + counts.color_count++; } - if (TEST_BICOLOR) + if (test_bicolor(&counts)) { - bicolor_spin = !bicolor_spin; - bicolor_count++; + counts.bicolor_spin = !counts.bicolor_spin; + counts.bicolor_count++; } if (TEST_FOM) { - if ((fom_count % 8) == 0) + if ((counts.fom_count % 8) == 0) { - fom_mask[fom_mask_len] = 0; - fom_mask_len++; + fom_mask[counts.fom_mask_len] = 0; + counts.fom_mask_len++; } if (pixel == (ypixel ^ mix)) { - const int tmp = (1 << (fom_count % 8)); - const int val = fom_mask[fom_mask_len - 1] | tmp; - const int8_t ival = WINPR_ASSERTING_INT_CAST(int8_t, val); - fom_mask[fom_mask_len - 1] = ival; + const uint8_t tmp = (1 << (counts.fom_count % 8)) & 0xFF; + const uint8_t val = fom_mask[counts.fom_mask_len - 1] | tmp; + fom_mask[counts.fom_mask_len - 1] = val; } - fom_count++; + counts.fom_count++; } Stream_Write_UINT8(temp_s, pixel & 0xff); @@ -654,48 +642,52 @@ static inline SSIZE_T freerdp_bitmap_compress_24(const void* WINPR_RESTRICT srcD /* can't take fix, mix, or fom past first line */ if (last_line == 0) { - if (fill_count > 3 && fill_count >= color_count && fill_count >= bicolor_count && - fill_count >= mix_count && fill_count >= fom_count) + if (counts.fill_count > 3 && counts.fill_count >= counts.color_count && + counts.fill_count >= counts.bicolor_count && + counts.fill_count >= counts.mix_count && counts.fill_count >= counts.fom_count) { - if (fill_count > count) + if (counts.fill_count > count) return -1; - count -= fill_count; - OUT_COPY_COUNT3(count, s, temp_s); - OUT_FILL_COUNT3(fill_count, s); - RESET_COUNTS; + count -= counts.fill_count; + count = out_copy_count_3(count, s, temp_s); + counts.fill_count = out_fill_count_3(counts.fill_count, s); + reset_counts(&counts); } - fill_count = 0; + counts.fill_count = 0; - if (mix_count > 3 && mix_count >= fill_count && mix_count >= bicolor_count && - mix_count >= color_count && mix_count >= fom_count) + if (counts.mix_count > 3 && counts.mix_count >= counts.fill_count && + counts.mix_count >= counts.bicolor_count && + counts.mix_count >= counts.color_count && counts.mix_count >= counts.fom_count) { - if (mix_count > count) + if (counts.mix_count > count) return -1; - count -= mix_count; - OUT_COPY_COUNT3(count, s, temp_s); - OUT_MIX_COUNT3(mix_count, s); - RESET_COUNTS; + count -= counts.mix_count; + count = out_copy_count_3(count, s, temp_s); + counts.mix_count = out_counts_mix_count_3(counts.mix_count, s); + reset_counts(&counts); } - mix_count = 0; + counts.mix_count = 0; - if (fom_count > 3 && fom_count >= fill_count && fom_count >= color_count && - fom_count >= mix_count && fom_count >= bicolor_count) + if (counts.fom_count > 3 && counts.fom_count >= counts.fill_count && + counts.fom_count >= counts.color_count && counts.fom_count >= counts.mix_count && + counts.fom_count >= counts.bicolor_count) { - if (fom_count > count) + if (counts.fom_count > count) return -1; - count -= fom_count; - OUT_COPY_COUNT3(count, s, temp_s); - OUT_FOM_COUNT3(fom_count, s, fom_mask, fom_mask_len); - RESET_COUNTS; + count -= counts.fom_count; + count = out_copy_count_3(count, s, temp_s); + counts.fom_count = + out_from_count_3(counts.fom_count, s, fom_mask, counts.fom_mask_len); + reset_counts(&counts); } - fom_count = 0; - fom_mask_len = 0; + counts.fom_count = 0; + counts.fom_mask_len = 0; } last_line = line; @@ -706,69 +698,74 @@ static inline SSIZE_T freerdp_bitmap_compress_24(const void* WINPR_RESTRICT srcD Stream_SetPosition(temp_s, 0); - if (fill_count > 3 && fill_count >= color_count && fill_count >= bicolor_count && - fill_count >= mix_count && fill_count >= fom_count) + if (counts.fill_count > 3 && counts.fill_count >= counts.color_count && + counts.fill_count >= counts.bicolor_count && counts.fill_count >= counts.mix_count && + counts.fill_count >= counts.fom_count) { - if (fill_count > count) + if (counts.fill_count > count) return -1; - count -= fill_count; - OUT_COPY_COUNT3(count, s, temp_s); - OUT_FILL_COUNT3(fill_count, s); + count -= counts.fill_count; + (void)out_copy_count_3(count, s, temp_s); + counts.fill_count = out_fill_count_3(counts.fill_count, s); } - else if (mix_count > 3 && mix_count >= color_count && mix_count >= bicolor_count && - mix_count >= fill_count && mix_count >= fom_count) + else if (counts.mix_count > 3 && counts.mix_count >= counts.color_count && + counts.mix_count >= counts.bicolor_count && counts.mix_count >= counts.fill_count && + counts.mix_count >= counts.fom_count) { - if (mix_count > count) + if (counts.mix_count > count) return -1; - count -= mix_count; - OUT_COPY_COUNT3(count, s, temp_s); - OUT_MIX_COUNT3(mix_count, s); + count -= counts.mix_count; + (void)out_copy_count_3(count, s, temp_s); + counts.mix_count = out_counts_mix_count_3(counts.mix_count, s); } - else if (color_count > 3 && color_count >= mix_count && color_count >= bicolor_count && - color_count >= fill_count && color_count >= fom_count) + else if (counts.color_count > 3 && counts.color_count >= counts.mix_count && + counts.color_count >= counts.bicolor_count && + counts.color_count >= counts.fill_count && counts.color_count >= counts.fom_count) { - if (color_count > count) + if (counts.color_count > count) return -1; - count -= color_count; - OUT_COPY_COUNT3(count, s, temp_s); - OUT_COLOR_COUNT3(color_count, s, last_pixel); + count -= counts.color_count; + (void)out_copy_count_3(count, s, temp_s); + counts.color_count = out_color_count_3(counts.color_count, s, last_pixel); } - else if (bicolor_count > 3 && bicolor_count >= mix_count && bicolor_count >= color_count && - bicolor_count >= fill_count && bicolor_count >= fom_count) + else if (counts.bicolor_count > 3 && counts.bicolor_count >= counts.mix_count && + counts.bicolor_count >= counts.color_count && + counts.bicolor_count >= counts.fill_count && counts.bicolor_count >= counts.fom_count) { - if ((bicolor_count % 2) != 0) - bicolor_count--; + if ((counts.bicolor_count % 2) != 0) + counts.bicolor_count--; - if (bicolor_count > count) + if (counts.bicolor_count > count) return -1; - count -= bicolor_count; - OUT_COPY_COUNT3(count, s, temp_s); - OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor2, bicolor1); + count -= counts.bicolor_count; + count = out_copy_count_3(count, s, temp_s); + counts.bicolor_count = out_bicolor_count_3(counts.bicolor_count, s, bicolor2, bicolor1); - if (bicolor_count > count) + if (counts.bicolor_count > count) return -1; - count -= bicolor_count; - OUT_COPY_COUNT3(count, s, temp_s); - OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor1, bicolor2); + count -= counts.bicolor_count; + (void)out_copy_count_3(count, s, temp_s); + counts.bicolor_count = out_bicolor_count_3(counts.bicolor_count, s, bicolor1, bicolor2); } - else if (fom_count > 3 && fom_count >= mix_count && fom_count >= color_count && - fom_count >= fill_count && fom_count >= bicolor_count) + else if (counts.fom_count > 3 && counts.fom_count >= counts.mix_count && + counts.fom_count >= counts.color_count && counts.fom_count >= counts.fill_count && + counts.fom_count >= counts.bicolor_count) { - if (fom_count > count) + if (counts.fom_count > count) return -1; - count -= fom_count; - OUT_COPY_COUNT3(count, s, temp_s); - OUT_FOM_COUNT3(fom_count, s, fom_mask, fom_mask_len); + count -= counts.fom_count; + (void)out_copy_count_3(count, s, temp_s); + counts.fom_count = out_from_count_3(counts.fom_count, s, fom_mask, counts.fom_mask_len); } else { - OUT_COPY_COUNT3(count, s, temp_s); + (void)out_copy_count_3(count, s, temp_s); } return lines_sent; @@ -780,23 +777,17 @@ static inline SSIZE_T freerdp_bitmap_compress_16(const void* WINPR_RESTRICT srcD UINT32 byte_limit, UINT32 start_line, wStream* WINPR_RESTRICT temp_s, UINT32 e) { - int8_t fom_mask[8192] = { 0 }; /* good for up to 64K bitmap */ + uint8_t fom_mask[8192] = { 0 }; /* good for up to 64K bitmap */ SSIZE_T lines_sent = 0; UINT16 count = 0; - UINT16 color_count = 0; UINT16 last_pixel = 0; UINT16 last_ypixel = 0; - UINT16 bicolor_count = 0; + struct count counts = { 0 }; UINT16 bicolor1 = 0; UINT16 bicolor2 = 0; - BOOL bicolor_spin = FALSE; UINT32 end = width + e; UINT32 out_count = end * 2; - UINT16 fill_count = 0; - UINT16 mix_count = 0; const UINT32 mix = (bpp == 15) ? 0xBA1F : 0xFFFF; - UINT16 fom_count = 0; - size_t fom_mask_len = 0; const char* start = (const char*)srcData; const char* line = start + 2ULL * width * start_line; const char* last_line = NULL; @@ -805,9 +796,11 @@ static inline SSIZE_T freerdp_bitmap_compress_16(const void* WINPR_RESTRICT srcD { size_t i = Stream_GetPosition(s) + 2ULL * count; - if ((i - (2ULL * color_count) >= byte_limit) && - (i - (2ULL * bicolor_count) >= byte_limit) && (i - (2ULL * fill_count) >= byte_limit) && - (i - (2ULL * mix_count) >= byte_limit) && (i - (2ULL * fom_count) >= byte_limit)) + if ((i - (2ULL * counts.color_count) >= byte_limit) && + (i - (2ULL * counts.bicolor_count) >= byte_limit) && + (i - (2ULL * counts.fill_count) >= byte_limit) && + (i - (2ULL * counts.mix_count) >= byte_limit) && + (i - (2ULL * counts.fom_count) >= byte_limit)) { break; } @@ -822,135 +815,143 @@ static inline SSIZE_T freerdp_bitmap_compress_16(const void* WINPR_RESTRICT srcD if (!TEST_FILL) { - if (fill_count > 3 && fill_count >= color_count && fill_count >= bicolor_count && - fill_count >= mix_count && fill_count >= fom_count) + if (counts.fill_count > 3 && counts.fill_count >= counts.color_count && + counts.fill_count >= counts.bicolor_count && + counts.fill_count >= counts.mix_count && counts.fill_count >= counts.fom_count) { - if (fill_count > count) + if (counts.fill_count > count) return -1; - count -= fill_count; - OUT_COPY_COUNT2(count, s, temp_s); - OUT_FILL_COUNT2(fill_count, s); - RESET_COUNTS; + count -= counts.fill_count; + count = out_copy_count_2(count, s, temp_s); + counts.fill_count = out_fill_count_2(counts.fill_count, s); + reset_counts(&counts); } - fill_count = 0; + counts.fill_count = 0; } if (!TEST_MIX) { - if (mix_count > 3 && mix_count >= fill_count && mix_count >= bicolor_count && - mix_count >= color_count && mix_count >= fom_count) + if (counts.mix_count > 3 && counts.mix_count >= counts.fill_count && + counts.mix_count >= counts.bicolor_count && + counts.mix_count >= counts.color_count && counts.mix_count >= counts.fom_count) { - if (mix_count > count) + if (counts.mix_count > count) return -1; - count -= mix_count; - OUT_COPY_COUNT2(count, s, temp_s); - OUT_MIX_COUNT2(mix_count, s); - RESET_COUNTS; + count -= counts.mix_count; + count = out_copy_count_2(count, s, temp_s); + counts.mix_count = out_counts_mix_count_2(counts.mix_count, s); + reset_counts(&counts); } - mix_count = 0; + counts.mix_count = 0; } if (!(TEST_COLOR)) { - if (color_count > 3 && color_count >= fill_count && color_count >= bicolor_count && - color_count >= mix_count && color_count >= fom_count) + if (counts.color_count > 3 && counts.color_count >= counts.fill_count && + counts.color_count >= counts.bicolor_count && + counts.color_count >= counts.mix_count && + counts.color_count >= counts.fom_count) { - if (color_count > count) + if (counts.color_count > count) return -1; - count -= color_count; - OUT_COPY_COUNT2(count, s, temp_s); - OUT_COLOR_COUNT2(color_count, s, last_pixel); - RESET_COUNTS; + count -= counts.color_count; + count = out_copy_count_2(count, s, temp_s); + counts.color_count = out_color_count_2(counts.color_count, s, last_pixel); + reset_counts(&counts); } - color_count = 0; + counts.color_count = 0; } - if (!TEST_BICOLOR) + if (!test_bicolor(&counts)) { - if ((bicolor_count > 3) && (bicolor_count >= fill_count) && - (bicolor_count >= color_count) && (bicolor_count >= mix_count) && - (bicolor_count >= fom_count)) + if ((counts.bicolor_count > 3) && (counts.bicolor_count >= counts.fill_count) && + (counts.bicolor_count >= counts.color_count) && + (counts.bicolor_count >= counts.mix_count) && + (counts.bicolor_count >= counts.fom_count)) { - if ((bicolor_count % 2) != 0) - bicolor_count--; + if ((counts.bicolor_count % 2) != 0) + counts.bicolor_count--; - if (bicolor_count > count) + if (counts.bicolor_count > count) return -1; - count -= bicolor_count; - OUT_COPY_COUNT2(count, s, temp_s); - OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor2, bicolor1); - RESET_COUNTS; + count -= counts.bicolor_count; + count = out_copy_count_2(count, s, temp_s); + counts.bicolor_count = + out_bicolor_count_2(counts.bicolor_count, s, bicolor2, bicolor1); + reset_counts(&counts); } - bicolor_count = 0; + counts.bicolor_count = 0; bicolor1 = last_pixel; bicolor2 = pixel; - bicolor_spin = FALSE; + counts.bicolor_spin = FALSE; } if (!(TEST_FOM)) { - if (fom_count > 3 && fom_count >= fill_count && fom_count >= color_count && - fom_count >= mix_count && fom_count >= bicolor_count) + if (counts.fom_count > 3 && counts.fom_count >= counts.fill_count && + counts.fom_count >= counts.color_count && + counts.fom_count >= counts.mix_count && + counts.fom_count >= counts.bicolor_count) { - if (fom_count > count) + if (counts.fom_count > count) return -1; - count -= fom_count; - OUT_COPY_COUNT2(count, s, temp_s); - OUT_FOM_COUNT2(fom_count, s, fom_mask, fom_mask_len); - RESET_COUNTS; + count -= counts.fom_count; + count = out_copy_count_2(count, s, temp_s); + counts.fom_count = + out_from_count_2(counts.fom_count, s, fom_mask, counts.fom_mask_len); + reset_counts(&counts); } - fom_count = 0; - fom_mask_len = 0; + counts.fom_count = 0; + counts.fom_mask_len = 0; } if (TEST_FILL) { - fill_count++; + counts.fill_count++; } if (TEST_MIX) { - mix_count++; + counts.mix_count++; } if (TEST_COLOR) { - color_count++; + counts.color_count++; } - if (TEST_BICOLOR) + if (test_bicolor(&counts)) { - bicolor_spin = !bicolor_spin; - bicolor_count++; + counts.bicolor_spin = !counts.bicolor_spin; + counts.bicolor_count++; } if (TEST_FOM) { - if ((fom_count % 8) == 0) + if ((counts.fom_count % 8) == 0) { - fom_mask[fom_mask_len] = 0; - fom_mask_len++; + fom_mask[counts.fom_mask_len] = 0; + counts.fom_mask_len++; } if (pixel == (ypixel ^ mix)) { - const int tmp = (1 << (fom_count % 8)); - const int val = fom_mask[fom_mask_len - 1] | tmp; - const int8_t ival = WINPR_ASSERTING_INT_CAST(int8_t, val); - fom_mask[fom_mask_len - 1] = ival; + const uint8_t tmp = (1 << (counts.fom_count % 8)) & 0xFF; + const uint8_t val = fom_mask[counts.fom_mask_len - 1] | tmp; + fom_mask[counts.fom_mask_len - 1] = val; } - fom_count++; + counts.fom_count++; } Stream_Write_UINT16(temp_s, pixel); @@ -962,48 +963,52 @@ static inline SSIZE_T freerdp_bitmap_compress_16(const void* WINPR_RESTRICT srcD /* can't take fix, mix, or fom past first line */ if (last_line == 0) { - if (fill_count > 3 && fill_count >= color_count && fill_count >= bicolor_count && - fill_count >= mix_count && fill_count >= fom_count) + if (counts.fill_count > 3 && counts.fill_count >= counts.color_count && + counts.fill_count >= counts.bicolor_count && + counts.fill_count >= counts.mix_count && counts.fill_count >= counts.fom_count) { - if (fill_count > count) + if (counts.fill_count > count) return -1; - count -= fill_count; - OUT_COPY_COUNT2(count, s, temp_s); - OUT_FILL_COUNT2(fill_count, s); - RESET_COUNTS; + count -= counts.fill_count; + count = out_copy_count_2(count, s, temp_s); + counts.fill_count = out_fill_count_2(counts.fill_count, s); + reset_counts(&counts); } - fill_count = 0; + counts.fill_count = 0; - if (mix_count > 3 && mix_count >= fill_count && mix_count >= bicolor_count && - mix_count >= color_count && mix_count >= fom_count) + if (counts.mix_count > 3 && counts.mix_count >= counts.fill_count && + counts.mix_count >= counts.bicolor_count && + counts.mix_count >= counts.color_count && counts.mix_count >= counts.fom_count) { - if (mix_count > count) + if (counts.mix_count > count) return -1; - count -= mix_count; - OUT_COPY_COUNT2(count, s, temp_s); - OUT_MIX_COUNT2(mix_count, s); - RESET_COUNTS; + count -= counts.mix_count; + count = out_copy_count_2(count, s, temp_s); + counts.mix_count = out_counts_mix_count_2(counts.mix_count, s); + reset_counts(&counts); } - mix_count = 0; + counts.mix_count = 0; - if (fom_count > 3 && fom_count >= fill_count && fom_count >= color_count && - fom_count >= mix_count && fom_count >= bicolor_count) + if (counts.fom_count > 3 && counts.fom_count >= counts.fill_count && + counts.fom_count >= counts.color_count && counts.fom_count >= counts.mix_count && + counts.fom_count >= counts.bicolor_count) { - if (fom_count > count) + if (counts.fom_count > count) return -1; - count -= fom_count; - OUT_COPY_COUNT2(count, s, temp_s); - OUT_FOM_COUNT2(fom_count, s, fom_mask, fom_mask_len); - RESET_COUNTS; + count -= counts.fom_count; + count = out_copy_count_2(count, s, temp_s); + counts.fom_count = + out_from_count_2(counts.fom_count, s, fom_mask, counts.fom_mask_len); + reset_counts(&counts); } - fom_count = 0; - fom_mask_len = 0; + counts.fom_count = 0; + counts.fom_mask_len = 0; } last_line = line; @@ -1014,69 +1019,74 @@ static inline SSIZE_T freerdp_bitmap_compress_16(const void* WINPR_RESTRICT srcD Stream_SetPosition(temp_s, 0); - if (fill_count > 3 && fill_count >= color_count && fill_count >= bicolor_count && - fill_count >= mix_count && fill_count >= fom_count) + if (counts.fill_count > 3 && counts.fill_count >= counts.color_count && + counts.fill_count >= counts.bicolor_count && counts.fill_count >= counts.mix_count && + counts.fill_count >= counts.fom_count) { - if (fill_count > count) + if (counts.fill_count > count) return -1; - count -= fill_count; - OUT_COPY_COUNT2(count, s, temp_s); - OUT_FILL_COUNT2(fill_count, s); + count -= counts.fill_count; + (void)out_copy_count_2(count, s, temp_s); + counts.fill_count = out_fill_count_2(counts.fill_count, s); } - else if (mix_count > 3 && mix_count >= color_count && mix_count >= bicolor_count && - mix_count >= fill_count && mix_count >= fom_count) + else if (counts.mix_count > 3 && counts.mix_count >= counts.color_count && + counts.mix_count >= counts.bicolor_count && counts.mix_count >= counts.fill_count && + counts.mix_count >= counts.fom_count) { - if (mix_count > count) + if (counts.mix_count > count) return -1; - count -= mix_count; - OUT_COPY_COUNT2(count, s, temp_s); - OUT_MIX_COUNT2(mix_count, s); + count -= counts.mix_count; + (void)out_copy_count_2(count, s, temp_s); + counts.mix_count = out_counts_mix_count_2(counts.mix_count, s); } - else if (color_count > 3 && color_count >= mix_count && color_count >= bicolor_count && - color_count >= fill_count && color_count >= fom_count) + else if (counts.color_count > 3 && counts.color_count >= counts.mix_count && + counts.color_count >= counts.bicolor_count && + counts.color_count >= counts.fill_count && counts.color_count >= counts.fom_count) { - if (color_count > count) + if (counts.color_count > count) return -1; - count -= color_count; - OUT_COPY_COUNT2(count, s, temp_s); - OUT_COLOR_COUNT2(color_count, s, last_pixel); + count -= counts.color_count; + (void)out_copy_count_2(count, s, temp_s); + counts.color_count = out_color_count_2(counts.color_count, s, last_pixel); } - else if (bicolor_count > 3 && bicolor_count >= mix_count && bicolor_count >= color_count && - bicolor_count >= fill_count && bicolor_count >= fom_count) + else if (counts.bicolor_count > 3 && counts.bicolor_count >= counts.mix_count && + counts.bicolor_count >= counts.color_count && + counts.bicolor_count >= counts.fill_count && counts.bicolor_count >= counts.fom_count) { - if ((bicolor_count % 2) != 0) - bicolor_count--; + if ((counts.bicolor_count % 2) != 0) + counts.bicolor_count--; - if (bicolor_count > count) + if (counts.bicolor_count > count) return -1; - count -= bicolor_count; - OUT_COPY_COUNT2(count, s, temp_s); - OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor2, bicolor1); + count -= counts.bicolor_count; + count = out_copy_count_2(count, s, temp_s); + counts.bicolor_count = out_bicolor_count_2(counts.bicolor_count, s, bicolor2, bicolor1); - if (bicolor_count > count) + if (counts.bicolor_count > count) return -1; - count -= bicolor_count; - OUT_COPY_COUNT2(count, s, temp_s); - OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor1, bicolor2); + count -= counts.bicolor_count; + (void)out_copy_count_2(count, s, temp_s); + counts.bicolor_count = out_bicolor_count_2(counts.bicolor_count, s, bicolor1, bicolor2); } - else if (fom_count > 3 && fom_count >= mix_count && fom_count >= color_count && - fom_count >= fill_count && fom_count >= bicolor_count) + else if (counts.fom_count > 3 && counts.fom_count >= counts.mix_count && + counts.fom_count >= counts.color_count && counts.fom_count >= counts.fill_count && + counts.fom_count >= counts.bicolor_count) { - if (fom_count > count) + if (counts.fom_count > count) return -1; - count -= fom_count; - OUT_COPY_COUNT2(count, s, temp_s); - OUT_FOM_COUNT2(fom_count, s, fom_mask, fom_mask_len); + count -= counts.fom_count; + (void)out_copy_count_2(count, s, temp_s); + counts.fom_count = out_from_count_2(counts.fom_count, s, fom_mask, counts.fom_mask_len); } else { - OUT_COPY_COUNT2(count, s, temp_s); + (void)out_copy_count_2(count, s, temp_s); } return lines_sent;