22#include <winpr/assert.h>
23#include <winpr/cast.h>
24#include <winpr/wtypes.h>
31static inline BYTE* WRITEFGBGIMAGE(BYTE* WINPR_RESTRICT pbDest,
32 const BYTE* WINPR_RESTRICT pbDestEnd, UINT32 rowDelta,
33 BYTE bitmask, PIXEL fgPel, UINT32 cBits)
40 WLog_ERR(TAG,
"cBits %d > 8", cBits);
44 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, cBits))
49 DESTREADPIXEL(xorPixel, pbDest - rowDelta);
52 data = xorPixel ^ fgPel;
56 DESTWRITEPIXEL(pbDest, data);
57 mask = WINPR_ASSERTING_INT_CAST(BYTE, (mask << 1) & 0xFF);
66static inline BYTE* WRITEFIRSTLINEFGBGIMAGE(BYTE* WINPR_RESTRICT pbDest,
67 const BYTE* WINPR_RESTRICT pbDestEnd, BYTE bitmask,
68 PIXEL fgPel, UINT32 cBits)
74 WLog_ERR(TAG,
"cBits %d > 8", cBits);
78 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, cBits))
89 DESTWRITEPIXEL(pbDest, data);
90 mask = WINPR_ASSERTING_INT_CAST(BYTE, (mask << 1) & 0xFF);
98static inline BOOL RLEDECOMPRESS(
const BYTE* WINPR_RESTRICT pbSrcBuffer, UINT32 cbSrcBuffer,
99 BYTE* WINPR_RESTRICT pbDestBuffer, UINT32 rowDelta, UINT32 width,
102 const BYTE* pbSrc = pbSrcBuffer;
103 BYTE* pbDest = pbDestBuffer;
105 PIXEL fgPel = WHITE_PIXEL;
106 BOOL fInsertFgPel = FALSE;
107 BOOL fFirstLine = TRUE;
111 UINT32 runLength = 0;
116 if ((rowDelta == 0) || (rowDelta < width))
118 WLog_ERR(TAG,
"Invalid arguments: rowDelta=%" PRIu32
" == 0 || < width=%" PRIu32, rowDelta,
123 if (!pbSrcBuffer || !pbDestBuffer)
125 WLog_ERR(TAG,
"Invalid arguments: pbSrcBuffer=%p, pbDestBuffer=%p", pbSrcBuffer,
130 const BYTE* pbEnd = &pbSrcBuffer[cbSrcBuffer];
131 const BYTE* pbDestEnd = &pbDestBuffer[1ULL * rowDelta * height];
133 while (pbSrc < pbEnd)
138 if ((UINT32)(pbDest - pbDestBuffer) >= rowDelta)
141 fInsertFgPel = FALSE;
149 code = ExtractCodeId(*pbSrc);
151#if defined(WITH_DEBUG_CODECS)
152 WLog_VRB(TAG,
"pbSrc=%p code=%s, rem=%" PRIuz, pbSrc, rle_code_str(code), pbEnd - pbSrc);
156 if ((code == REGULAR_BG_RUN) || (code == MEGA_MEGA_BG_RUN))
158 runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
161 pbSrc = pbSrc + advance;
167 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
170 DESTWRITEPIXEL(pbDest, fgPel);
171 runLength = runLength - 1;
174 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
177 UNROLL(runLength, { DESTWRITEPIXEL(pbDest, BLACK_PIXEL); });
183 DESTREADPIXEL(temp, pbDest - rowDelta);
185 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
188 DESTWRITEPIXEL(pbDest, temp ^ fgPel);
192 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
196 DESTREADPIXEL(temp, pbDest - rowDelta);
197 DESTWRITEPIXEL(pbDest, temp);
208 fInsertFgPel = FALSE;
214 case MEGA_MEGA_FG_RUN:
215 case LITE_SET_FG_FG_RUN:
216 case MEGA_MEGA_SET_FG_RUN:
217 runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
220 pbSrc = pbSrc + advance;
222 if (code == LITE_SET_FG_FG_RUN || code == MEGA_MEGA_SET_FG_RUN)
224 if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
226 SRCREADPIXEL(fgPel, pbSrc);
229 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
234 UNROLL(runLength, { DESTWRITEPIXEL(pbDest, fgPel); });
239 DESTREADPIXEL(temp, pbDest - rowDelta);
240 DESTWRITEPIXEL(pbDest, temp ^ fgPel);
247 case LITE_DITHERED_RUN:
248 case MEGA_MEGA_DITHERED_RUN:
249 runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
252 pbSrc = pbSrc + advance;
253 if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
255 SRCREADPIXEL(pixelA, pbSrc);
256 if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
258 SRCREADPIXEL(pixelB, pbSrc);
260 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength * 2))
264 DESTWRITEPIXEL(pbDest, pixelA);
265 DESTWRITEPIXEL(pbDest, pixelB);
270 case REGULAR_COLOR_RUN:
271 case MEGA_MEGA_COLOR_RUN:
272 runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
275 pbSrc = pbSrc + advance;
276 if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
278 SRCREADPIXEL(pixelA, pbSrc);
280 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
283 UNROLL(runLength, { DESTWRITEPIXEL(pbDest, pixelA); });
287 case REGULAR_FGBG_IMAGE:
288 case MEGA_MEGA_FGBG_IMAGE:
289 case LITE_SET_FG_FGBG_IMAGE:
290 case MEGA_MEGA_SET_FGBG_IMAGE:
291 runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
294 pbSrc = pbSrc + advance;
296 if (code == LITE_SET_FG_FGBG_IMAGE || code == MEGA_MEGA_SET_FGBG_IMAGE)
298 if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
300 SRCREADPIXEL(fgPel, pbSrc);
303 if (!buffer_within_range(pbSrc, runLength / 8, pbEnd))
307 while (runLength > 8)
311 pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, bitmask, fgPel, 8);
316 runLength = runLength - 8;
321 while (runLength > 8)
325 pbDest = WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, bitmask, fgPel, 8);
330 runLength = runLength - 8;
336 if (!buffer_within_range(pbSrc, 1, pbEnd))
343 WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, bitmask, fgPel, runLength);
348 WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, bitmask, fgPel, runLength);
358 case REGULAR_COLOR_IMAGE:
359 case MEGA_MEGA_COLOR_IMAGE:
360 runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
363 pbSrc = pbSrc + advance;
364 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
366 if (!ENSURE_CAPACITY(pbSrc, pbEnd, runLength))
370 SRCREADPIXEL(temp, pbSrc);
371 DESTWRITEPIXEL(pbDest, temp);
377 if (!buffer_within_range(pbSrc, 1, pbEnd))
384 WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, g_MaskSpecialFgBg1, fgPel, 8);
389 WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, g_MaskSpecialFgBg1, fgPel, 8);
399 if (!buffer_within_range(pbSrc, 1, pbEnd))
406 WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, g_MaskSpecialFgBg2, fgPel, 8);
411 WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, g_MaskSpecialFgBg2, fgPel, 8);
421 if (!buffer_within_range(pbSrc, 1, pbEnd))
425 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
428 DESTWRITEPIXEL(pbDest, WHITE_PIXEL);
433 if (!buffer_within_range(pbSrc, 1, pbEnd))
437 if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
440 DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
444 WLog_ERR(TAG,
"invalid code 0x%08" PRIx32
", pbSrcBuffer=%p, pbSrc=%p, pbEnd=%p",
445 code, pbSrcBuffer, pbSrc, pbEnd);