22#include <winpr/assert.h>
23#include <winpr/cast.h>
24#include <winpr/wtypes.h>
32static inline BYTE* WRITEFGBGIMAGE(BYTE* WINPR_RESTRICT pbDest,
33 const BYTE* WINPR_RESTRICT pbDestEnd, UINT32 rowDelta,
34 BYTE bitmask, PIXEL fgPel, UINT32 cBits)
41 WLog_ERR(TAG,
"cBits %" PRIu32
" > 8", cBits);
45 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, cBits))
50 DESTREADPIXEL(xorPixel, pbDest - rowDelta);
53 data = xorPixel ^ fgPel;
57 DESTWRITEPIXEL(pbDest, data);
58 mask = WINPR_ASSERTING_INT_CAST(BYTE, (mask << 1) & 0xFF);
68static inline BYTE* WRITEFIRSTLINEFGBGIMAGE(BYTE* WINPR_RESTRICT pbDest,
69 const BYTE* WINPR_RESTRICT pbDestEnd, BYTE bitmask,
70 PIXEL fgPel, UINT32 cBits)
76 WLog_ERR(TAG,
"cBits %" PRIu32
" > 8", cBits);
80 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, cBits))
91 DESTWRITEPIXEL(pbDest, data);
92 mask = WINPR_ASSERTING_INT_CAST(BYTE, (mask << 1) & 0xFF);
101static inline BOOL RLEDECOMPRESS(
const BYTE* WINPR_RESTRICT pbSrcBuffer, UINT32 cbSrcBuffer,
102 BYTE* WINPR_RESTRICT pbDestBuffer, UINT32 rowDelta, UINT32 width,
105 const BYTE* pbSrc = pbSrcBuffer;
106 BYTE* pbDest = pbDestBuffer;
108 PIXEL fgPel = WHITE_PIXEL;
109 BOOL fInsertFgPel = FALSE;
110 BOOL fFirstLine = TRUE;
114 UINT32 runLength = 0;
119 if ((rowDelta == 0) || (rowDelta < width))
121 WLog_ERR(TAG,
"Invalid arguments: rowDelta=%" PRIu32
" == 0 || < width=%" PRIu32, rowDelta,
126 if (!pbSrcBuffer || !pbDestBuffer)
128 WLog_ERR(TAG,
"Invalid arguments: pbSrcBuffer=%p, pbDestBuffer=%p",
129 WINPR_CXX_COMPAT_CAST(
const void*, pbSrcBuffer),
130 WINPR_CXX_COMPAT_CAST(
const void*, pbDestBuffer));
134 const BYTE* pbEnd = &pbSrcBuffer[cbSrcBuffer];
135 const BYTE* pbDestEnd = &pbDestBuffer[1ULL * rowDelta * height];
137 while (pbSrc < pbEnd)
142 if ((UINT32)(pbDest - pbDestBuffer) >= rowDelta)
145 fInsertFgPel = FALSE;
153 code = ExtractCodeId(*pbSrc);
155#if defined(WITH_DEBUG_CODECS)
156 WLog_VRB(TAG,
"pbSrc=%p code=%s, rem=%ld", (
const void*)pbSrc, rle_code_str(code),
161 if ((code == REGULAR_BG_RUN) || (code == MEGA_MEGA_BG_RUN))
163 runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
166 pbSrc = pbSrc + advance;
172 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
175 DESTWRITEPIXEL(pbDest, fgPel);
176 runLength = runLength - 1;
179 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
182 UNROLL(runLength, { DESTWRITEPIXEL(pbDest, BLACK_PIXEL); });
188 DESTREADPIXEL(temp, pbDest - rowDelta);
190 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
193 DESTWRITEPIXEL(pbDest, temp ^ fgPel);
197 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
201 DESTREADPIXEL(temp, pbDest - rowDelta);
202 DESTWRITEPIXEL(pbDest, temp);
213 fInsertFgPel = FALSE;
219 case MEGA_MEGA_FG_RUN:
220 case LITE_SET_FG_FG_RUN:
221 case MEGA_MEGA_SET_FG_RUN:
222 runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
225 pbSrc = pbSrc + advance;
227 if (code == LITE_SET_FG_FG_RUN || code == MEGA_MEGA_SET_FG_RUN)
229 if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
231 SRCREADPIXEL(fgPel, pbSrc);
234 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
239 UNROLL(runLength, { DESTWRITEPIXEL(pbDest, fgPel); });
244 DESTREADPIXEL(temp, pbDest - rowDelta);
245 DESTWRITEPIXEL(pbDest, temp ^ fgPel);
252 case LITE_DITHERED_RUN:
253 case MEGA_MEGA_DITHERED_RUN:
254 runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
257 pbSrc = pbSrc + advance;
258 if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
260 SRCREADPIXEL(pixelA, pbSrc);
261 if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
263 SRCREADPIXEL(pixelB, pbSrc);
265 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength * 2))
269 DESTWRITEPIXEL(pbDest, pixelA);
270 DESTWRITEPIXEL(pbDest, pixelB);
275 case REGULAR_COLOR_RUN:
276 case MEGA_MEGA_COLOR_RUN:
277 runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
280 pbSrc = pbSrc + advance;
281 if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
283 SRCREADPIXEL(pixelA, pbSrc);
285 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
288 UNROLL(runLength, { DESTWRITEPIXEL(pbDest, pixelA); });
292 case REGULAR_FGBG_IMAGE:
293 case MEGA_MEGA_FGBG_IMAGE:
294 case LITE_SET_FG_FGBG_IMAGE:
295 case MEGA_MEGA_SET_FGBG_IMAGE:
296 runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
299 pbSrc = pbSrc + advance;
301 if (code == LITE_SET_FG_FGBG_IMAGE || code == MEGA_MEGA_SET_FGBG_IMAGE)
303 if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
305 SRCREADPIXEL(fgPel, pbSrc);
308 if (!buffer_within_range(pbSrc, runLength / 8, pbEnd))
312 while (runLength > 8)
316 pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, bitmask, fgPel, 8);
321 runLength = runLength - 8;
326 while (runLength > 8)
330 pbDest = WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, bitmask, fgPel, 8);
335 runLength = runLength - 8;
341 if (!buffer_within_range(pbSrc, 1, pbEnd))
348 WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, bitmask, fgPel, runLength);
353 WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, bitmask, fgPel, runLength);
363 case REGULAR_COLOR_IMAGE:
364 case MEGA_MEGA_COLOR_IMAGE:
365 runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
368 pbSrc = pbSrc + advance;
369 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
371 if (!ENSURE_CAPACITY(pbSrc, pbEnd, runLength))
375 SRCREADPIXEL(temp, pbSrc);
376 DESTWRITEPIXEL(pbDest, temp);
382 if (!buffer_within_range(pbSrc, 1, pbEnd))
389 WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, g_MaskSpecialFgBg1, fgPel, 8);
394 WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, g_MaskSpecialFgBg1, fgPel, 8);
404 if (!buffer_within_range(pbSrc, 1, pbEnd))
411 WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, g_MaskSpecialFgBg2, fgPel, 8);
416 WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, g_MaskSpecialFgBg2, fgPel, 8);
426 if (!buffer_within_range(pbSrc, 1, pbEnd))
430 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
433 DESTWRITEPIXEL(pbDest, WHITE_PIXEL);
438 if (!buffer_within_range(pbSrc, 1, pbEnd))
442 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
445 DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
449 WLog_ERR(TAG,
"invalid code 0x%08" PRIx32
", pbSrcBuffer=%p, pbSrc=%p, pbEnd=%p",
450 code, WINPR_CXX_COMPAT_CAST(
const void*, pbSrcBuffer),
451 WINPR_CXX_COMPAT_CAST(
const void*, pbSrc),
452 WINPR_CXX_COMPAT_CAST(
const void*, pbEnd));