/src/FreeRDP/libfreerdp/codec/clear.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /**  | 
2  |  |  * FreeRDP: A Remote Desktop Protocol Implementation  | 
3  |  |  * ClearCodec Bitmap Compression  | 
4  |  |  *  | 
5  |  |  * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>  | 
6  |  |  * Copyright 2016 Armin Novak <armin.novak@thincast.com>  | 
7  |  |  * Copyright 2016 Thincast Technologies GmbH  | 
8  |  |  *  | 
9  |  |  * Licensed under the Apache License, Version 2.0 (the "License");  | 
10  |  |  * you may not use this file except in compliance with the License.  | 
11  |  |  * You may obtain a copy of the License at  | 
12  |  |  *  | 
13  |  |  *     http://www.apache.org/licenses/LICENSE-2.0  | 
14  |  |  *  | 
15  |  |  * Unless required by applicable law or agreed to in writing, software  | 
16  |  |  * distributed under the License is distributed on an "AS IS" BASIS,  | 
17  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | 
18  |  |  * See the License for the specific language governing permissions and  | 
19  |  |  * limitations under the License.  | 
20  |  |  */  | 
21  |  |  | 
22  |  | #include <freerdp/config.h>  | 
23  |  |  | 
24  |  | #include <winpr/crt.h>  | 
25  |  | #include <winpr/print.h>  | 
26  |  | #include <winpr/bitstream.h>  | 
27  |  |  | 
28  |  | #include <freerdp/codec/color.h>  | 
29  |  | #include <freerdp/codec/clear.h>  | 
30  |  | #include <freerdp/log.h>  | 
31  |  |  | 
32  |  | #define TAG FREERDP_TAG("codec.clear") | 
33  |  |  | 
34  | 23.2k  | #define CLEARCODEC_FLAG_GLYPH_INDEX 0x01  | 
35  | 22.4k  | #define CLEARCODEC_FLAG_GLYPH_HIT 0x02  | 
36  | 16.2k  | #define CLEARCODEC_FLAG_CACHE_RESET 0x04  | 
37  |  |  | 
38  | 3.80M  | #define CLEARCODEC_VBAR_SIZE 32768  | 
39  | 1.64M  | #define CLEARCODEC_VBAR_SHORT_SIZE 16384  | 
40  |  |  | 
41  |  | typedef struct  | 
42  |  | { | 
43  |  |   UINT32 size;  | 
44  |  |   UINT32 count;  | 
45  |  |   UINT32* pixels;  | 
46  |  | } CLEAR_GLYPH_ENTRY;  | 
47  |  |  | 
48  |  | typedef struct  | 
49  |  | { | 
50  |  |   UINT32 size;  | 
51  |  |   UINT32 count;  | 
52  |  |   BYTE* pixels;  | 
53  |  | } CLEAR_VBAR_ENTRY;  | 
54  |  |  | 
55  |  | struct S_CLEAR_CONTEXT  | 
56  |  | { | 
57  |  |   BOOL Compressor;  | 
58  |  |   NSC_CONTEXT* nsc;  | 
59  |  |   UINT32 seqNumber;  | 
60  |  |   BYTE* TempBuffer;  | 
61  |  |   UINT32 TempSize;  | 
62  |  |   UINT32 nTempStep;  | 
63  |  |   UINT32 TempFormat;  | 
64  |  |   UINT32 format;  | 
65  |  |   CLEAR_GLYPH_ENTRY GlyphCache[4000];  | 
66  |  |   UINT32 VBarStorageCursor;  | 
67  |  |   CLEAR_VBAR_ENTRY VBarStorage[CLEARCODEC_VBAR_SIZE];  | 
68  |  |   UINT32 ShortVBarStorageCursor;  | 
69  |  |   CLEAR_VBAR_ENTRY ShortVBarStorage[CLEARCODEC_VBAR_SHORT_SIZE];  | 
70  |  | };  | 
71  |  |  | 
72  |  | static const UINT32 CLEAR_LOG2_FLOOR[256] = { | 
73  |  |   0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,  | 
74  |  |   5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,  | 
75  |  |   6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,  | 
76  |  |   6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,  | 
77  |  |   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,  | 
78  |  |   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,  | 
79  |  |   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,  | 
80  |  |   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7  | 
81  |  | };  | 
82  |  |  | 
83  |  | static const BYTE CLEAR_8BIT_MASKS[9] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF }; | 
84  |  |  | 
85  |  | static void clear_reset_vbar_storage(CLEAR_CONTEXT* WINPR_RESTRICT clear, BOOL zero)  | 
86  | 19.3k  | { | 
87  | 19.3k  |   if (zero)  | 
88  | 16.2k  |   { | 
89  | 531M  |     for (size_t i = 0; i < ARRAYSIZE(clear->VBarStorage); i++)  | 
90  | 531M  |       winpr_aligned_free(clear->VBarStorage[i].pixels);  | 
91  |  |  | 
92  | 16.2k  |     ZeroMemory(clear->VBarStorage, sizeof(clear->VBarStorage));  | 
93  | 16.2k  |   }  | 
94  |  |  | 
95  | 19.3k  |   clear->VBarStorageCursor = 0;  | 
96  |  |  | 
97  | 19.3k  |   if (zero)  | 
98  | 16.2k  |   { | 
99  | 265M  |     for (size_t i = 0; i < ARRAYSIZE(clear->ShortVBarStorage); i++)  | 
100  | 265M  |       winpr_aligned_free(clear->ShortVBarStorage[i].pixels);  | 
101  |  |  | 
102  | 16.2k  |     ZeroMemory(clear->ShortVBarStorage, sizeof(clear->ShortVBarStorage));  | 
103  | 16.2k  |   }  | 
104  |  |  | 
105  | 19.3k  |   clear->ShortVBarStorageCursor = 0;  | 
106  | 19.3k  | }  | 
107  |  |  | 
108  |  | static void clear_reset_glyph_cache(CLEAR_CONTEXT* WINPR_RESTRICT clear)  | 
109  | 16.2k  | { | 
110  | 64.8M  |   for (size_t i = 0; i < ARRAYSIZE(clear->GlyphCache); i++)  | 
111  | 64.8M  |     winpr_aligned_free(clear->GlyphCache[i].pixels);  | 
112  |  |  | 
113  | 16.2k  |   ZeroMemory(clear->GlyphCache, sizeof(clear->GlyphCache));  | 
114  | 16.2k  | }  | 
115  |  |  | 
116  |  | static BOOL convert_color(BYTE* WINPR_RESTRICT dst, UINT32 nDstStep, UINT32 DstFormat, UINT32 nXDst,  | 
117  |  |                           UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,  | 
118  |  |                           const BYTE* WINPR_RESTRICT src, UINT32 nSrcStep, UINT32 SrcFormat,  | 
119  |  |                           UINT32 nDstWidth, UINT32 nDstHeight,  | 
120  |  |                           const gdiPalette* WINPR_RESTRICT palette)  | 
121  | 3.86k  | { | 
122  | 3.86k  |   if (nWidth + nXDst > nDstWidth)  | 
123  | 0  |     nWidth = nDstWidth - nXDst;  | 
124  |  |  | 
125  | 3.86k  |   if (nHeight + nYDst > nDstHeight)  | 
126  | 0  |     nHeight = nDstHeight - nYDst;  | 
127  |  |  | 
128  | 3.86k  |   return freerdp_image_copy_no_overlap(dst, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,  | 
129  | 3.86k  |                                        src, SrcFormat, nSrcStep, 0, 0, palette,  | 
130  | 3.86k  |                                        FREERDP_KEEP_DST_ALPHA);  | 
131  | 3.86k  | }  | 
132  |  |  | 
133  |  | static BOOL clear_decompress_nscodec(NSC_CONTEXT* WINPR_RESTRICT nsc, UINT32 width, UINT32 height,  | 
134  |  |                                      wStream* WINPR_RESTRICT s, UINT32 bitmapDataByteCount,  | 
135  |  |                                      BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,  | 
136  |  |                                      UINT32 nDstStep, UINT32 nXDstRel, UINT32 nYDstRel)  | 
137  | 524  | { | 
138  | 524  |   BOOL rc = 0;  | 
139  |  |  | 
140  | 524  |   if (!Stream_CheckAndLogRequiredLength(TAG, s, bitmapDataByteCount))  | 
141  | 0  |     return FALSE;  | 
142  |  |  | 
143  | 524  |   rc = nsc_process_message(nsc, 32, width, height, Stream_Pointer(s), bitmapDataByteCount,  | 
144  | 524  |                            pDstData, DstFormat, nDstStep, nXDstRel, nYDstRel, width, height,  | 
145  | 524  |                            FREERDP_FLIP_NONE);  | 
146  | 524  |   Stream_Seek(s, bitmapDataByteCount);  | 
147  | 524  |   return rc;  | 
148  | 524  | }  | 
149  |  |  | 
150  |  | static BOOL clear_decompress_subcode_rlex(wStream* WINPR_RESTRICT s, UINT32 bitmapDataByteCount,  | 
151  |  |                                           UINT32 width, UINT32 height,  | 
152  |  |                                           BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,  | 
153  |  |                                           UINT32 nDstStep, UINT32 nXDstRel, UINT32 nYDstRel,  | 
154  |  |                                           UINT32 nDstWidth, UINT32 nDstHeight)  | 
155  | 489  | { | 
156  | 489  |   UINT32 x = 0;  | 
157  | 489  |   UINT32 y = 0;  | 
158  | 489  |   UINT32 pixelCount = 0;  | 
159  | 489  |   UINT32 bitmapDataOffset = 0;  | 
160  | 489  |   size_t pixelIndex = 0;  | 
161  | 489  |   UINT32 numBits = 0;  | 
162  | 489  |   BYTE startIndex = 0;  | 
163  | 489  |   BYTE stopIndex = 0;  | 
164  | 489  |   BYTE suiteIndex = 0;  | 
165  | 489  |   BYTE suiteDepth = 0;  | 
166  | 489  |   BYTE paletteCount = 0;  | 
167  | 489  |   UINT32 palette[128] = { 0 }; | 
168  |  |  | 
169  | 489  |   if (!Stream_CheckAndLogRequiredLength(TAG, s, bitmapDataByteCount))  | 
170  | 0  |     return FALSE;  | 
171  |  |  | 
172  | 489  |   if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))  | 
173  | 8  |     return FALSE;  | 
174  | 481  |   Stream_Read_UINT8(s, paletteCount);  | 
175  | 481  |   bitmapDataOffset = 1 + (paletteCount * 3);  | 
176  |  |  | 
177  | 481  |   if ((paletteCount > 127) || (paletteCount < 1))  | 
178  | 14  |   { | 
179  | 14  |     WLog_ERR(TAG, "paletteCount %" PRIu8 "", paletteCount);  | 
180  | 14  |     return FALSE;  | 
181  | 14  |   }  | 
182  |  |  | 
183  | 467  |   if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, paletteCount, 3ull))  | 
184  | 12  |     return FALSE;  | 
185  |  |  | 
186  | 1.76k  |   for (UINT32 i = 0; i < paletteCount; i++)  | 
187  | 1.30k  |   { | 
188  | 1.30k  |     BYTE r = 0;  | 
189  | 1.30k  |     BYTE g = 0;  | 
190  | 1.30k  |     BYTE b = 0;  | 
191  | 1.30k  |     Stream_Read_UINT8(s, b);  | 
192  | 1.30k  |     Stream_Read_UINT8(s, g);  | 
193  | 1.30k  |     Stream_Read_UINT8(s, r);  | 
194  | 1.30k  |     palette[i] = FreeRDPGetColor(DstFormat, r, g, b, 0xFF);  | 
195  | 1.30k  |   }  | 
196  |  |  | 
197  | 455  |   pixelIndex = 0;  | 
198  | 455  |   pixelCount = width * height;  | 
199  | 455  |   numBits = CLEAR_LOG2_FLOOR[paletteCount - 1] + 1;  | 
200  |  |  | 
201  | 1.17k  |   while (bitmapDataOffset < bitmapDataByteCount)  | 
202  | 1.05k  |   { | 
203  | 1.05k  |     UINT32 tmp = 0;  | 
204  | 1.05k  |     UINT32 color = 0;  | 
205  | 1.05k  |     UINT32 runLengthFactor = 0;  | 
206  |  |  | 
207  | 1.05k  |     if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))  | 
208  | 20  |       return FALSE;  | 
209  |  |  | 
210  | 1.03k  |     Stream_Read_UINT8(s, tmp);  | 
211  | 1.03k  |     Stream_Read_UINT8(s, runLengthFactor);  | 
212  | 1.03k  |     bitmapDataOffset += 2;  | 
213  | 1.03k  |     suiteDepth = (tmp >> numBits) & CLEAR_8BIT_MASKS[(8 - numBits)];  | 
214  | 1.03k  |     stopIndex = tmp & CLEAR_8BIT_MASKS[numBits];  | 
215  | 1.03k  |     startIndex = stopIndex - suiteDepth;  | 
216  |  |  | 
217  | 1.03k  |     if (runLengthFactor >= 0xFF)  | 
218  | 259  |     { | 
219  | 259  |       if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))  | 
220  | 6  |         return FALSE;  | 
221  |  |  | 
222  | 253  |       Stream_Read_UINT16(s, runLengthFactor);  | 
223  | 253  |       bitmapDataOffset += 2;  | 
224  |  |  | 
225  | 253  |       if (runLengthFactor >= 0xFFFF)  | 
226  | 172  |       { | 
227  | 172  |         if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))  | 
228  | 9  |           return FALSE;  | 
229  |  |  | 
230  | 163  |         Stream_Read_UINT32(s, runLengthFactor);  | 
231  | 163  |         bitmapDataOffset += 4;  | 
232  | 163  |       }  | 
233  | 253  |     }  | 
234  |  |  | 
235  | 1.02k  |     if (startIndex >= paletteCount)  | 
236  | 110  |     { | 
237  | 110  |       WLog_ERR(TAG, "startIndex %" PRIu8 " > paletteCount %" PRIu8 "]", startIndex,  | 
238  | 110  |                paletteCount);  | 
239  | 110  |       return FALSE;  | 
240  | 110  |     }  | 
241  |  |  | 
242  | 911  |     if (stopIndex >= paletteCount)  | 
243  | 17  |     { | 
244  | 17  |       WLog_ERR(TAG, "stopIndex %" PRIu8 " > paletteCount %" PRIu8 "]", stopIndex,  | 
245  | 17  |                paletteCount);  | 
246  | 17  |       return FALSE;  | 
247  | 17  |     }  | 
248  |  |  | 
249  | 894  |     suiteIndex = startIndex;  | 
250  |  |  | 
251  | 894  |     if (suiteIndex > 127)  | 
252  | 0  |     { | 
253  | 0  |       WLog_ERR(TAG, "suiteIndex %" PRIu8 " > 127]", suiteIndex);  | 
254  | 0  |       return FALSE;  | 
255  | 0  |     }  | 
256  |  |  | 
257  | 894  |     color = palette[suiteIndex];  | 
258  |  |  | 
259  | 894  |     if ((pixelIndex + runLengthFactor) > pixelCount)  | 
260  | 154  |     { | 
261  | 154  |       WLog_ERR(TAG,  | 
262  | 154  |                "pixelIndex %" PRIu32 " + runLengthFactor %" PRIu32 " > pixelCount %" PRIu32  | 
263  | 154  |                "",  | 
264  | 154  |                pixelIndex, runLengthFactor, pixelCount);  | 
265  | 154  |       return FALSE;  | 
266  | 154  |     }  | 
267  |  |  | 
268  | 11.9k  |     for (UINT32 i = 0; i < runLengthFactor; i++)  | 
269  | 11.2k  |     { | 
270  | 11.2k  |       BYTE* pTmpData = &pDstData[(nXDstRel + x) * FreeRDPGetBytesPerPixel(DstFormat) +  | 
271  | 11.2k  |                                  (nYDstRel + y) * nDstStep];  | 
272  |  |  | 
273  | 11.2k  |       if ((nXDstRel + x < nDstWidth) && (nYDstRel + y < nDstHeight))  | 
274  | 11.2k  |         FreeRDPWriteColor(pTmpData, DstFormat, color);  | 
275  |  |  | 
276  | 11.2k  |       if (++x >= width)  | 
277  | 347  |       { | 
278  | 347  |         y++;  | 
279  | 347  |         x = 0;  | 
280  | 347  |       }  | 
281  | 11.2k  |     }  | 
282  |  |  | 
283  | 740  |     pixelIndex += runLengthFactor;  | 
284  |  |  | 
285  | 740  |     if ((pixelIndex + (suiteDepth + 1)) > pixelCount)  | 
286  | 17  |     { | 
287  | 17  |       WLog_ERR(TAG,  | 
288  | 17  |                "pixelIndex %" PRIu32 " + suiteDepth %" PRIu8 " + 1 > pixelCount %" PRIu32 "",  | 
289  | 17  |                pixelIndex, suiteDepth, pixelCount);  | 
290  | 17  |       return FALSE;  | 
291  | 17  |     }  | 
292  |  |  | 
293  | 1.72k  |     for (UINT32 i = 0; i <= suiteDepth; i++)  | 
294  | 1.00k  |     { | 
295  | 1.00k  |       BYTE* pTmpData = &pDstData[(nXDstRel + x) * FreeRDPGetBytesPerPixel(DstFormat) +  | 
296  | 1.00k  |                                  (nYDstRel + y) * nDstStep];  | 
297  | 1.00k  |       UINT32 ccolor = palette[suiteIndex];  | 
298  |  |  | 
299  | 1.00k  |       if (suiteIndex > 127)  | 
300  | 0  |       { | 
301  | 0  |         WLog_ERR(TAG, "suiteIndex %" PRIu8 " > 127", suiteIndex);  | 
302  | 0  |         return FALSE;  | 
303  | 0  |       }  | 
304  |  |  | 
305  | 1.00k  |       suiteIndex++;  | 
306  |  |  | 
307  | 1.00k  |       if ((nXDstRel + x < nDstWidth) && (nYDstRel + y < nDstHeight))  | 
308  | 1.00k  |         FreeRDPWriteColor(pTmpData, DstFormat, ccolor);  | 
309  |  |  | 
310  | 1.00k  |       if (++x >= width)  | 
311  | 160  |       { | 
312  | 160  |         y++;  | 
313  | 160  |         x = 0;  | 
314  | 160  |       }  | 
315  | 1.00k  |     }  | 
316  |  |  | 
317  | 723  |     pixelIndex += (suiteDepth + 1);  | 
318  | 723  |   }  | 
319  |  |  | 
320  | 122  |   if (pixelIndex != pixelCount)  | 
321  | 71  |   { | 
322  | 71  |     WLog_ERR(TAG, "pixelIndex %" PRIdz " != pixelCount %" PRIu32 "", pixelIndex, pixelCount);  | 
323  | 71  |     return FALSE;  | 
324  | 71  |   }  | 
325  |  |  | 
326  | 51  |   return TRUE;  | 
327  | 122  | }  | 
328  |  |  | 
329  |  | static BOOL clear_resize_buffer(CLEAR_CONTEXT* WINPR_RESTRICT clear, UINT32 width, UINT32 height)  | 
330  | 22.0k  | { | 
331  | 22.0k  |   UINT32 size = 0;  | 
332  |  |  | 
333  | 22.0k  |   if (!clear)  | 
334  | 0  |     return FALSE;  | 
335  |  |  | 
336  | 22.0k  |   size = ((width + 16) * (height + 16) * FreeRDPGetBytesPerPixel(clear->format));  | 
337  |  |  | 
338  | 22.0k  |   if (size > clear->TempSize)  | 
339  | 16.2k  |   { | 
340  | 16.2k  |     BYTE* tmp = (BYTE*)winpr_aligned_recalloc(clear->TempBuffer, size, sizeof(BYTE), 32);  | 
341  |  |  | 
342  | 16.2k  |     if (!tmp)  | 
343  | 0  |     { | 
344  | 0  |       WLog_ERR(TAG, "clear->TempBuffer winpr_aligned_recalloc failed for %" PRIu32 " bytes",  | 
345  | 0  |                size);  | 
346  | 0  |       return FALSE;  | 
347  | 0  |     }  | 
348  |  |  | 
349  | 16.2k  |     clear->TempSize = size;  | 
350  | 16.2k  |     clear->TempBuffer = tmp;  | 
351  | 16.2k  |   }  | 
352  |  |  | 
353  | 22.0k  |   return TRUE;  | 
354  | 22.0k  | }  | 
355  |  |  | 
356  |  | static BOOL clear_decompress_residual_data(CLEAR_CONTEXT* WINPR_RESTRICT clear,  | 
357  |  |                                            wStream* WINPR_RESTRICT s, UINT32 residualByteCount,  | 
358  |  |                                            UINT32 nWidth, UINT32 nHeight,  | 
359  |  |                                            BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,  | 
360  |  |                                            UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,  | 
361  |  |                                            UINT32 nDstWidth, UINT32 nDstHeight,  | 
362  |  |                                            const gdiPalette* WINPR_RESTRICT palette)  | 
363  | 4.90k  | { | 
364  | 4.90k  |   UINT32 nSrcStep = 0;  | 
365  | 4.90k  |   UINT32 suboffset = 0;  | 
366  | 4.90k  |   BYTE* dstBuffer = NULL;  | 
367  | 4.90k  |   UINT32 pixelIndex = 0;  | 
368  | 4.90k  |   UINT32 pixelCount = 0;  | 
369  |  |  | 
370  | 4.90k  |   if (!Stream_CheckAndLogRequiredLength(TAG, s, residualByteCount))  | 
371  | 4.03k  |     return FALSE;  | 
372  |  |  | 
373  | 870  |   suboffset = 0;  | 
374  | 870  |   pixelIndex = 0;  | 
375  | 870  |   pixelCount = nWidth * nHeight;  | 
376  |  |  | 
377  | 870  |   if (!clear_resize_buffer(clear, nWidth, nHeight))  | 
378  | 0  |     return FALSE;  | 
379  |  |  | 
380  | 870  |   dstBuffer = clear->TempBuffer;  | 
381  |  |  | 
382  | 486k  |   while (suboffset < residualByteCount)  | 
383  | 486k  |   { | 
384  | 486k  |     BYTE r = 0;  | 
385  | 486k  |     BYTE g = 0;  | 
386  | 486k  |     BYTE b = 0;  | 
387  | 486k  |     UINT32 runLengthFactor = 0;  | 
388  | 486k  |     UINT32 color = 0;  | 
389  |  |  | 
390  | 486k  |     if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))  | 
391  | 22  |       return FALSE;  | 
392  |  |  | 
393  | 486k  |     Stream_Read_UINT8(s, b);  | 
394  | 486k  |     Stream_Read_UINT8(s, g);  | 
395  | 486k  |     Stream_Read_UINT8(s, r);  | 
396  | 486k  |     Stream_Read_UINT8(s, runLengthFactor);  | 
397  | 486k  |     suboffset += 4;  | 
398  | 486k  |     color = FreeRDPGetColor(clear->format, r, g, b, 0xFF);  | 
399  |  |  | 
400  | 486k  |     if (runLengthFactor >= 0xFF)  | 
401  | 1.06k  |     { | 
402  | 1.06k  |       if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))  | 
403  | 14  |         return FALSE;  | 
404  |  |  | 
405  | 1.05k  |       Stream_Read_UINT16(s, runLengthFactor);  | 
406  | 1.05k  |       suboffset += 2;  | 
407  |  |  | 
408  | 1.05k  |       if (runLengthFactor >= 0xFFFF)  | 
409  | 412  |       { | 
410  | 412  |         if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))  | 
411  | 13  |           return FALSE;  | 
412  |  |  | 
413  | 399  |         Stream_Read_UINT32(s, runLengthFactor);  | 
414  | 399  |         suboffset += 4;  | 
415  | 399  |       }  | 
416  | 1.05k  |     }  | 
417  |  |  | 
418  | 486k  |     if ((pixelIndex >= pixelCount) || (runLengthFactor > (pixelCount - pixelIndex)))  | 
419  | 556  |     { | 
420  | 556  |       WLog_ERR(TAG,  | 
421  | 556  |                "pixelIndex %" PRIu32 " + runLengthFactor %" PRIu32 " > pixelCount %" PRIu32  | 
422  | 556  |                "",  | 
423  | 556  |                pixelIndex, runLengthFactor, pixelCount);  | 
424  | 556  |       return FALSE;  | 
425  | 556  |     }  | 
426  |  |  | 
427  | 709k  |     for (UINT32 i = 0; i < runLengthFactor; i++)  | 
428  | 224k  |     { | 
429  | 224k  |       FreeRDPWriteColor(dstBuffer, clear->format, color);  | 
430  | 224k  |       dstBuffer += FreeRDPGetBytesPerPixel(clear->format);  | 
431  | 224k  |     }  | 
432  |  |  | 
433  | 485k  |     pixelIndex += runLengthFactor;  | 
434  | 485k  |   }  | 
435  |  |  | 
436  | 265  |   nSrcStep = nWidth * FreeRDPGetBytesPerPixel(clear->format);  | 
437  |  |  | 
438  | 265  |   if (pixelIndex != pixelCount)  | 
439  | 249  |   { | 
440  | 249  |     WLog_ERR(TAG, "pixelIndex %" PRIu32 " != pixelCount %" PRIu32 "", pixelIndex, pixelCount);  | 
441  | 249  |     return FALSE;  | 
442  | 249  |   }  | 
443  |  |  | 
444  | 16  |   return convert_color(pDstData, nDstStep, DstFormat, nXDst, nYDst, nWidth, nHeight,  | 
445  | 16  |                        clear->TempBuffer, nSrcStep, clear->format, nDstWidth, nDstHeight,  | 
446  | 16  |                        palette);  | 
447  | 265  | }  | 
448  |  |  | 
449  |  | static BOOL clear_decompress_subcodecs_data(CLEAR_CONTEXT* WINPR_RESTRICT clear,  | 
450  |  |                                             wStream* WINPR_RESTRICT s, UINT32 subcodecByteCount,  | 
451  |  |                                             UINT32 nWidth, UINT32 nHeight,  | 
452  |  |                                             BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,  | 
453  |  |                                             UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,  | 
454  |  |                                             UINT32 nDstWidth, UINT32 nDstHeight,  | 
455  |  |                                             const gdiPalette* WINPR_RESTRICT palette)  | 
456  | 2.21k  | { | 
457  | 2.21k  |   UINT16 xStart = 0;  | 
458  | 2.21k  |   UINT16 yStart = 0;  | 
459  | 2.21k  |   UINT16 width = 0;  | 
460  | 2.21k  |   UINT16 height = 0;  | 
461  | 2.21k  |   UINT32 bitmapDataByteCount = 0;  | 
462  | 2.21k  |   BYTE subcodecId = 0;  | 
463  | 2.21k  |   UINT32 suboffset = 0;  | 
464  |  |  | 
465  | 2.21k  |   if (!Stream_CheckAndLogRequiredLength(TAG, s, subcodecByteCount))  | 
466  | 198  |     return FALSE;  | 
467  |  |  | 
468  | 2.01k  |   suboffset = 0;  | 
469  |  |  | 
470  | 6.19k  |   while (suboffset < subcodecByteCount)  | 
471  | 5.84k  |   { | 
472  | 5.84k  |     UINT32 nXDstRel = 0;  | 
473  | 5.84k  |     UINT32 nYDstRel = 0;  | 
474  |  |  | 
475  | 5.84k  |     if (!Stream_CheckAndLogRequiredLength(TAG, s, 13))  | 
476  | 26  |       return FALSE;  | 
477  |  |  | 
478  | 5.82k  |     Stream_Read_UINT16(s, xStart);  | 
479  | 5.82k  |     Stream_Read_UINT16(s, yStart);  | 
480  | 5.82k  |     Stream_Read_UINT16(s, width);  | 
481  | 5.82k  |     Stream_Read_UINT16(s, height);  | 
482  | 5.82k  |     Stream_Read_UINT32(s, bitmapDataByteCount);  | 
483  | 5.82k  |     Stream_Read_UINT8(s, subcodecId);  | 
484  | 5.82k  |     suboffset += 13;  | 
485  |  |  | 
486  | 5.82k  |     if (!Stream_CheckAndLogRequiredLength(TAG, s, bitmapDataByteCount))  | 
487  | 97  |       return FALSE;  | 
488  |  |  | 
489  | 5.72k  |     nXDstRel = nXDst + xStart;  | 
490  | 5.72k  |     nYDstRel = nYDst + yStart;  | 
491  |  |  | 
492  | 5.72k  |     if (1ull * xStart + width > nWidth)  | 
493  | 569  |     { | 
494  | 569  |       WLog_ERR(TAG, "xStart %" PRIu16 " + width %" PRIu16 " > nWidth %" PRIu32 "", xStart,  | 
495  | 569  |                width, nWidth);  | 
496  | 569  |       return FALSE;  | 
497  | 569  |     }  | 
498  | 5.15k  |     if (1ull * yStart + height > nHeight)  | 
499  | 225  |     { | 
500  | 225  |       WLog_ERR(TAG, "yStart %" PRIu16 " + height %" PRIu16 " > nHeight %" PRIu32 "", yStart,  | 
501  | 225  |                height, nHeight);  | 
502  | 225  |       return FALSE;  | 
503  | 225  |     }  | 
504  |  |  | 
505  | 4.93k  |     if (!clear_resize_buffer(clear, width, height))  | 
506  | 0  |       return FALSE;  | 
507  |  |  | 
508  | 4.93k  |     switch (subcodecId)  | 
509  | 4.93k  |     { | 
510  | 3.90k  |       case 0: /* Uncompressed */  | 
511  | 3.90k  |       { | 
512  | 3.90k  |         const UINT32 nSrcStep = width * FreeRDPGetBytesPerPixel(PIXEL_FORMAT_BGR24);  | 
513  | 3.90k  |         const size_t nSrcSize = 1ull * nSrcStep * height;  | 
514  |  |  | 
515  | 3.90k  |         if (bitmapDataByteCount != nSrcSize)  | 
516  | 53  |         { | 
517  | 53  |           WLog_ERR(TAG, "bitmapDataByteCount %" PRIu32 " != nSrcSize %" PRIuz "",  | 
518  | 53  |                    bitmapDataByteCount, nSrcSize);  | 
519  | 53  |           return FALSE;  | 
520  | 53  |         }  | 
521  |  |  | 
522  | 3.84k  |         if (!convert_color(pDstData, nDstStep, DstFormat, nXDstRel, nYDstRel, width, height,  | 
523  | 3.84k  |                            Stream_Pointer(s), nSrcStep, PIXEL_FORMAT_BGR24, nDstWidth,  | 
524  | 3.84k  |                            nDstHeight, palette))  | 
525  | 0  |           return FALSE;  | 
526  |  |  | 
527  | 3.84k  |         Stream_Seek(s, bitmapDataByteCount);  | 
528  | 3.84k  |       }  | 
529  | 0  |       break;  | 
530  |  |  | 
531  | 524  |       case 1: /* NSCodec */  | 
532  | 524  |         if (!clear_decompress_nscodec(clear->nsc, width, height, s, bitmapDataByteCount,  | 
533  | 524  |                                       pDstData, DstFormat, nDstStep, nXDstRel, nYDstRel))  | 
534  | 249  |           return FALSE;  | 
535  |  |  | 
536  | 275  |         break;  | 
537  |  |  | 
538  | 489  |       case 2: /* CLEARCODEC_SUBCODEC_RLEX */  | 
539  | 489  |         if (!clear_decompress_subcode_rlex(s, bitmapDataByteCount, width, height, pDstData,  | 
540  | 489  |                                            DstFormat, nDstStep, nXDstRel, nYDstRel,  | 
541  | 489  |                                            nDstWidth, nDstHeight))  | 
542  | 438  |           return FALSE;  | 
543  |  |  | 
544  | 51  |         break;  | 
545  |  |  | 
546  | 51  |       default:  | 
547  | 18  |         WLog_ERR(TAG, "Unknown subcodec ID %" PRIu8 "", subcodecId);  | 
548  | 18  |         return FALSE;  | 
549  | 4.93k  |     }  | 
550  |  |  | 
551  | 4.17k  |     suboffset += bitmapDataByteCount;  | 
552  | 4.17k  |   }  | 
553  |  |  | 
554  | 344  |   return TRUE;  | 
555  | 2.01k  | }  | 
556  |  |  | 
557  |  | static BOOL resize_vbar_entry(CLEAR_CONTEXT* WINPR_RESTRICT clear,  | 
558  |  |                               CLEAR_VBAR_ENTRY* WINPR_RESTRICT vBarEntry)  | 
559  | 2.73M  | { | 
560  | 2.73M  |   if (vBarEntry->count > vBarEntry->size)  | 
561  | 1.74M  |   { | 
562  | 1.74M  |     const UINT32 bpp = FreeRDPGetBytesPerPixel(clear->format);  | 
563  | 1.74M  |     const UINT32 oldPos = vBarEntry->size * bpp;  | 
564  | 1.74M  |     const UINT32 diffSize = (vBarEntry->count - vBarEntry->size) * bpp;  | 
565  |  |  | 
566  | 1.74M  |     vBarEntry->size = vBarEntry->count;  | 
567  | 1.74M  |     BYTE* tmp =  | 
568  | 1.74M  |         (BYTE*)winpr_aligned_recalloc(vBarEntry->pixels, vBarEntry->count, 1ull * bpp, 32);  | 
569  |  |  | 
570  | 1.74M  |     if (!tmp)  | 
571  | 0  |     { | 
572  | 0  |       WLog_ERR(TAG, "vBarEntry->pixels winpr_aligned_recalloc %" PRIu32 " failed",  | 
573  | 0  |                vBarEntry->count * bpp);  | 
574  | 0  |       return FALSE;  | 
575  | 0  |     }  | 
576  |  |  | 
577  | 1.74M  |     memset(&tmp[oldPos], 0, diffSize);  | 
578  | 1.74M  |     vBarEntry->pixels = tmp;  | 
579  | 1.74M  |   }  | 
580  |  |  | 
581  | 2.73M  |   if (!vBarEntry->pixels && vBarEntry->size)  | 
582  | 0  |   { | 
583  | 0  |     WLog_ERR(TAG, "vBarEntry->pixels is NULL but vBarEntry->size is %" PRIu32 "",  | 
584  | 0  |              vBarEntry->size);  | 
585  | 0  |     return FALSE;  | 
586  | 0  |   }  | 
587  |  |  | 
588  | 2.73M  |   return TRUE;  | 
589  | 2.73M  | }  | 
590  |  |  | 
591  |  | static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* WINPR_RESTRICT clear,  | 
592  |  |                                         wStream* WINPR_RESTRICT s, UINT32 bandsByteCount,  | 
593  |  |                                         UINT32 nWidth, UINT32 nHeight,  | 
594  |  |                                         BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,  | 
595  |  |                                         UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,  | 
596  |  |                                         UINT32 nDstWidth, UINT32 nDstHeight)  | 
597  | 2.20k  | { | 
598  | 2.20k  |   UINT32 suboffset = 0;  | 
599  |  |  | 
600  | 2.20k  |   if (!Stream_CheckAndLogRequiredLength(TAG, s, bandsByteCount))  | 
601  | 508  |     return FALSE;  | 
602  |  |  | 
603  | 90.0k  |   while (suboffset < bandsByteCount)  | 
604  | 89.8k  |   { | 
605  | 89.8k  |     BYTE cr = 0;  | 
606  | 89.8k  |     BYTE cg = 0;  | 
607  | 89.8k  |     BYTE cb = 0;  | 
608  | 89.8k  |     UINT16 xStart = 0;  | 
609  | 89.8k  |     UINT16 xEnd = 0;  | 
610  | 89.8k  |     UINT16 yStart = 0;  | 
611  | 89.8k  |     UINT16 yEnd = 0;  | 
612  | 89.8k  |     UINT32 colorBkg = 0;  | 
613  | 89.8k  |     UINT16 vBarHeader = 0;  | 
614  | 89.8k  |     UINT16 vBarYOn = 0;  | 
615  | 89.8k  |     UINT16 vBarYOff = 0;  | 
616  | 89.8k  |     UINT32 vBarCount = 0;  | 
617  | 89.8k  |     UINT32 vBarPixelCount = 0;  | 
618  | 89.8k  |     UINT32 vBarShortPixelCount = 0;  | 
619  |  |  | 
620  | 89.8k  |     if (!Stream_CheckAndLogRequiredLength(TAG, s, 11))  | 
621  | 17  |       return FALSE;  | 
622  |  |  | 
623  | 89.8k  |     Stream_Read_UINT16(s, xStart);  | 
624  | 89.8k  |     Stream_Read_UINT16(s, xEnd);  | 
625  | 89.8k  |     Stream_Read_UINT16(s, yStart);  | 
626  | 89.8k  |     Stream_Read_UINT16(s, yEnd);  | 
627  | 89.8k  |     Stream_Read_UINT8(s, cb);  | 
628  | 89.8k  |     Stream_Read_UINT8(s, cg);  | 
629  | 89.8k  |     Stream_Read_UINT8(s, cr);  | 
630  | 89.8k  |     suboffset += 11;  | 
631  | 89.8k  |     colorBkg = FreeRDPGetColor(clear->format, cr, cg, cb, 0xFF);  | 
632  |  |  | 
633  | 89.8k  |     if (xEnd < xStart)  | 
634  | 34  |     { | 
635  | 34  |       WLog_ERR(TAG, "xEnd %" PRIu16 " < xStart %" PRIu16 "", xEnd, xStart);  | 
636  | 34  |       return FALSE;  | 
637  | 34  |     }  | 
638  |  |  | 
639  | 89.8k  |     if (yEnd < yStart)  | 
640  | 81  |     { | 
641  | 81  |       WLog_ERR(TAG, "yEnd %" PRIu16 " < yStart %" PRIu16 "", yEnd, yStart);  | 
642  | 81  |       return FALSE;  | 
643  | 81  |     }  | 
644  |  |  | 
645  | 89.7k  |     vBarCount = (xEnd - xStart) + 1;  | 
646  |  |  | 
647  | 2.01M  |     for (UINT32 i = 0; i < vBarCount; i++)  | 
648  | 1.92M  |     { | 
649  | 1.92M  |       UINT32 vBarHeight = 0;  | 
650  | 1.92M  |       CLEAR_VBAR_ENTRY* vBarEntry = NULL;  | 
651  | 1.92M  |       CLEAR_VBAR_ENTRY* vBarShortEntry = NULL;  | 
652  | 1.92M  |       BOOL vBarUpdate = FALSE;  | 
653  | 1.92M  |       const BYTE* cpSrcPixel = NULL;  | 
654  |  |  | 
655  | 1.92M  |       if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))  | 
656  | 592  |         return FALSE;  | 
657  |  |  | 
658  | 1.92M  |       Stream_Read_UINT16(s, vBarHeader);  | 
659  | 1.92M  |       suboffset += 2;  | 
660  | 1.92M  |       vBarHeight = (yEnd - yStart + 1);  | 
661  |  |  | 
662  | 1.92M  |       if (vBarHeight > 52)  | 
663  | 78  |       { | 
664  | 78  |         WLog_ERR(TAG, "vBarHeight (%" PRIu32 ") > 52", vBarHeight);  | 
665  | 78  |         return FALSE;  | 
666  | 78  |       }  | 
667  |  |  | 
668  | 1.92M  |       if ((vBarHeader & 0xC000) == 0x4000) /* SHORT_VBAR_CACHE_HIT */  | 
669  | 1.08M  |       { | 
670  | 1.08M  |         const UINT16 vBarIndex = (vBarHeader & 0x3FFF);  | 
671  | 1.08M  |         vBarShortEntry = &(clear->ShortVBarStorage[vBarIndex]);  | 
672  |  |  | 
673  | 1.08M  |         if (!vBarShortEntry)  | 
674  | 0  |         { | 
675  | 0  |           WLog_ERR(TAG, "missing vBarShortEntry %" PRIu16 "", vBarIndex);  | 
676  | 0  |           return FALSE;  | 
677  | 0  |         }  | 
678  |  |  | 
679  | 1.08M  |         if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))  | 
680  | 18  |           return FALSE;  | 
681  |  |  | 
682  | 1.08M  |         Stream_Read_UINT8(s, vBarYOn);  | 
683  | 1.08M  |         suboffset += 1;  | 
684  | 1.08M  |         vBarShortPixelCount = vBarShortEntry->count;  | 
685  | 1.08M  |         vBarUpdate = TRUE;  | 
686  | 1.08M  |       }  | 
687  | 839k  |       else if ((vBarHeader & 0xC000) == 0x0000) /* SHORT_VBAR_CACHE_MISS */  | 
688  | 821k  |       { | 
689  | 821k  |         vBarYOn = (vBarHeader & 0xFF);  | 
690  | 821k  |         vBarYOff = ((vBarHeader >> 8) & 0x3F);  | 
691  |  |  | 
692  | 821k  |         if (vBarYOff < vBarYOn)  | 
693  | 316  |         { | 
694  | 316  |           WLog_ERR(TAG, "vBarYOff %" PRIu16 " < vBarYOn %" PRIu16 "", vBarYOff, vBarYOn);  | 
695  | 316  |           return FALSE;  | 
696  | 316  |         }  | 
697  |  |  | 
698  | 820k  |         vBarShortPixelCount = (vBarYOff - vBarYOn);  | 
699  |  |  | 
700  | 820k  |         if (vBarShortPixelCount > 52)  | 
701  | 8  |         { | 
702  | 8  |           WLog_ERR(TAG, "vBarShortPixelCount %" PRIu32 " > 52", vBarShortPixelCount);  | 
703  | 8  |           return FALSE;  | 
704  | 8  |         }  | 
705  |  |  | 
706  | 820k  |         if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, vBarShortPixelCount, 3ull))  | 
707  | 21  |           return FALSE;  | 
708  |  |  | 
709  | 820k  |         if (clear->ShortVBarStorageCursor >= CLEARCODEC_VBAR_SHORT_SIZE)  | 
710  | 0  |         { | 
711  | 0  |           WLog_ERR(TAG,  | 
712  | 0  |                    "clear->ShortVBarStorageCursor %" PRIu32  | 
713  | 0  |                    " >= CLEARCODEC_VBAR_SHORT_SIZE (%" PRIu32 ")",  | 
714  | 0  |                    clear->ShortVBarStorageCursor, CLEARCODEC_VBAR_SHORT_SIZE);  | 
715  | 0  |           return FALSE;  | 
716  | 0  |         }  | 
717  |  |  | 
718  | 820k  |         vBarShortEntry = &(clear->ShortVBarStorage[clear->ShortVBarStorageCursor]);  | 
719  | 820k  |         vBarShortEntry->count = vBarShortPixelCount;  | 
720  |  |  | 
721  | 820k  |         if (!resize_vbar_entry(clear, vBarShortEntry))  | 
722  | 0  |           return FALSE;  | 
723  |  |  | 
724  | 835k  |         for (size_t y = 0; y < vBarShortPixelCount; y++)  | 
725  | 14.4k  |         { | 
726  | 14.4k  |           BYTE r = 0;  | 
727  | 14.4k  |           BYTE g = 0;  | 
728  | 14.4k  |           BYTE b = 0;  | 
729  | 14.4k  |           BYTE* dstBuffer =  | 
730  | 14.4k  |               &vBarShortEntry->pixels[y * FreeRDPGetBytesPerPixel(clear->format)];  | 
731  | 14.4k  |           UINT32 color = 0;  | 
732  | 14.4k  |           Stream_Read_UINT8(s, b);  | 
733  | 14.4k  |           Stream_Read_UINT8(s, g);  | 
734  | 14.4k  |           Stream_Read_UINT8(s, r);  | 
735  | 14.4k  |           color = FreeRDPGetColor(clear->format, r, g, b, 0xFF);  | 
736  |  |  | 
737  | 14.4k  |           if (!FreeRDPWriteColor(dstBuffer, clear->format, color))  | 
738  | 0  |             return FALSE;  | 
739  | 14.4k  |         }  | 
740  |  |  | 
741  | 820k  |         suboffset += (vBarShortPixelCount * 3);  | 
742  | 820k  |         clear->ShortVBarStorageCursor =  | 
743  | 820k  |             (clear->ShortVBarStorageCursor + 1) % CLEARCODEC_VBAR_SHORT_SIZE;  | 
744  | 820k  |         vBarUpdate = TRUE;  | 
745  | 820k  |       }  | 
746  | 18.7k  |       else if ((vBarHeader & 0x8000) == 0x8000) /* VBAR_CACHE_HIT */  | 
747  | 18.7k  |       { | 
748  | 18.7k  |         const UINT16 vBarIndex = (vBarHeader & 0x7FFF);  | 
749  | 18.7k  |         vBarEntry = &(clear->VBarStorage[vBarIndex]);  | 
750  |  |  | 
751  |  |         /* If the cache was reset we need to fill in some dummy data. */  | 
752  | 18.7k  |         if (vBarEntry->size == 0)  | 
753  | 7.46k  |         { | 
754  | 7.46k  |           WLog_WARN(TAG, "Empty cache index %" PRIu16 ", filling dummy data", vBarIndex);  | 
755  | 7.46k  |           vBarEntry->count = vBarHeight;  | 
756  |  |  | 
757  | 7.46k  |           if (!resize_vbar_entry(clear, vBarEntry))  | 
758  | 0  |             return FALSE;  | 
759  | 7.46k  |         }  | 
760  | 18.7k  |       }  | 
761  | 0  |       else  | 
762  | 0  |       { | 
763  | 0  |         WLog_ERR(TAG, "invalid vBarHeader 0x%04" PRIX16 "", vBarHeader);  | 
764  | 0  |         return FALSE; /* invalid vBarHeader */  | 
765  | 0  |       }  | 
766  |  |  | 
767  | 1.92M  |       if (vBarUpdate)  | 
768  | 1.90M  |       { | 
769  | 1.90M  |         BYTE* pSrcPixel = NULL;  | 
770  | 1.90M  |         BYTE* dstBuffer = NULL;  | 
771  |  |  | 
772  | 1.90M  |         if (clear->VBarStorageCursor >= CLEARCODEC_VBAR_SIZE)  | 
773  | 0  |         { | 
774  | 0  |           WLog_ERR(TAG,  | 
775  | 0  |                    "clear->VBarStorageCursor %" PRIu32 " >= CLEARCODEC_VBAR_SIZE %" PRIu32  | 
776  | 0  |                    "",  | 
777  | 0  |                    clear->VBarStorageCursor, CLEARCODEC_VBAR_SIZE);  | 
778  | 0  |           return FALSE;  | 
779  | 0  |         }  | 
780  |  |  | 
781  | 1.90M  |         vBarEntry = &(clear->VBarStorage[clear->VBarStorageCursor]);  | 
782  | 1.90M  |         vBarPixelCount = vBarHeight;  | 
783  | 1.90M  |         vBarEntry->count = vBarPixelCount;  | 
784  |  |  | 
785  | 1.90M  |         if (!resize_vbar_entry(clear, vBarEntry))  | 
786  | 0  |           return FALSE;  | 
787  |  |  | 
788  | 1.90M  |         dstBuffer = vBarEntry->pixels;  | 
789  |  |         /* if (y < vBarYOn), use colorBkg */  | 
790  | 1.90M  |         UINT32 y = 0;  | 
791  | 1.90M  |         UINT32 count = vBarYOn;  | 
792  |  |  | 
793  | 1.90M  |         if ((y + count) > vBarPixelCount)  | 
794  | 1.61M  |           count = (vBarPixelCount > y) ? (vBarPixelCount - y) : 0;  | 
795  |  |  | 
796  | 8.36M  |         while (count--)  | 
797  | 6.46M  |         { | 
798  | 6.46M  |           FreeRDPWriteColor(dstBuffer, clear->format, colorBkg);  | 
799  | 6.46M  |           dstBuffer += FreeRDPGetBytesPerPixel(clear->format);  | 
800  | 6.46M  |         }  | 
801  |  |  | 
802  |  |         /*  | 
803  |  |          * if ((y >= vBarYOn) && (y < (vBarYOn + vBarShortPixelCount))),  | 
804  |  |          * use vBarShortPixels at index (y - shortVBarYOn)  | 
805  |  |          */  | 
806  | 1.90M  |         y = vBarYOn;  | 
807  | 1.90M  |         count = vBarShortPixelCount;  | 
808  |  |  | 
809  | 1.90M  |         if ((y + count) > vBarPixelCount)  | 
810  | 1.62M  |           count = (vBarPixelCount > y) ? (vBarPixelCount - y) : 0;  | 
811  |  |  | 
812  | 1.90M  |         if (count > 0)  | 
813  | 1.28k  |         { | 
814  | 1.28k  |           const size_t offset =  | 
815  | 1.28k  |               (1ull * y - vBarYOn) * FreeRDPGetBytesPerPixel(clear->format);  | 
816  | 1.28k  |           pSrcPixel = &vBarShortEntry->pixels[offset];  | 
817  | 1.28k  |           if (offset + count > vBarShortEntry->count)  | 
818  | 0  |           { | 
819  | 0  |             WLog_ERR(TAG, "offset + count > vBarShortEntry->count");  | 
820  | 0  |             return FALSE;  | 
821  | 0  |           }  | 
822  | 1.28k  |         }  | 
823  | 1.90M  |         for (size_t x = 0; x < count; x++)  | 
824  | 4.12k  |         { | 
825  | 4.12k  |           UINT32 color = 0;  | 
826  | 4.12k  |           color = FreeRDPReadColor(&pSrcPixel[x * FreeRDPGetBytesPerPixel(clear->format)],  | 
827  | 4.12k  |                                    clear->format);  | 
828  |  |  | 
829  | 4.12k  |           if (!FreeRDPWriteColor(dstBuffer, clear->format, color))  | 
830  | 0  |             return FALSE;  | 
831  |  |  | 
832  | 4.12k  |           dstBuffer += FreeRDPGetBytesPerPixel(clear->format);  | 
833  | 4.12k  |         }  | 
834  |  |  | 
835  |  |         /* if (y >= (vBarYOn + vBarShortPixelCount)), use colorBkg */  | 
836  | 1.90M  |         y = vBarYOn + vBarShortPixelCount;  | 
837  | 1.90M  |         count = (vBarPixelCount > y) ? (vBarPixelCount - y) : 0;  | 
838  |  |  | 
839  | 2.42M  |         while (count--)  | 
840  | 518k  |         { | 
841  | 518k  |           if (!FreeRDPWriteColor(dstBuffer, clear->format, colorBkg))  | 
842  | 0  |             return FALSE;  | 
843  |  |  | 
844  | 518k  |           dstBuffer += FreeRDPGetBytesPerPixel(clear->format);  | 
845  | 518k  |         }  | 
846  |  |  | 
847  | 1.90M  |         vBarEntry->count = vBarPixelCount;  | 
848  | 1.90M  |         clear->VBarStorageCursor = (clear->VBarStorageCursor + 1) % CLEARCODEC_VBAR_SIZE;  | 
849  | 1.90M  |       }  | 
850  |  |  | 
851  | 1.92M  |       if (vBarEntry->count != vBarHeight)  | 
852  | 146  |       { | 
853  | 146  |         WLog_ERR(TAG, "vBarEntry->count %" PRIu32 " != vBarHeight %" PRIu32 "",  | 
854  | 146  |                  vBarEntry->count, vBarHeight);  | 
855  | 146  |         vBarEntry->count = vBarHeight;  | 
856  |  |  | 
857  | 146  |         if (!resize_vbar_entry(clear, vBarEntry))  | 
858  | 0  |           return FALSE;  | 
859  | 146  |       }  | 
860  |  |  | 
861  | 1.92M  |       const UINT32 nXDstRel = nXDst + xStart;  | 
862  | 1.92M  |       const UINT32 nYDstRel = nYDst + yStart;  | 
863  | 1.92M  |       cpSrcPixel = vBarEntry->pixels;  | 
864  |  |  | 
865  | 1.92M  |       if (i < nWidth)  | 
866  | 115k  |       { | 
867  | 115k  |         UINT32 count = vBarEntry->count;  | 
868  |  |  | 
869  | 115k  |         if (count > nHeight)  | 
870  | 3.14k  |           count = nHeight;  | 
871  |  |  | 
872  | 115k  |         if (nXDstRel + i > nDstWidth)  | 
873  | 260  |           return FALSE;  | 
874  |  |  | 
875  | 308k  |         for (UINT32 y = 0; y < count; y++)  | 
876  | 193k  |         { | 
877  | 193k  |           if (nYDstRel + y > nDstHeight)  | 
878  | 73  |             return FALSE;  | 
879  |  |  | 
880  | 193k  |           BYTE* pDstPixel8 =  | 
881  | 193k  |               &pDstData[((nYDstRel + y) * nDstStep) +  | 
882  | 193k  |                         ((nXDstRel + i) * FreeRDPGetBytesPerPixel(DstFormat))];  | 
883  | 193k  |           UINT32 color = FreeRDPReadColor(cpSrcPixel, clear->format);  | 
884  | 193k  |           color = FreeRDPConvertColor(color, clear->format, DstFormat, NULL);  | 
885  |  |  | 
886  | 193k  |           if (!FreeRDPWriteColor(pDstPixel8, DstFormat, color))  | 
887  | 0  |             return FALSE;  | 
888  |  |  | 
889  | 193k  |           cpSrcPixel += FreeRDPGetBytesPerPixel(clear->format);  | 
890  | 193k  |         }  | 
891  | 115k  |       }  | 
892  | 1.92M  |     }  | 
893  | 89.7k  |   }  | 
894  |  |  | 
895  | 195  |   return TRUE;  | 
896  | 1.69k  | }  | 
897  |  |  | 
898  |  | static BOOL clear_decompress_glyph_data(CLEAR_CONTEXT* WINPR_RESTRICT clear,  | 
899  |  |                                         wStream* WINPR_RESTRICT s, UINT32 glyphFlags, UINT32 nWidth,  | 
900  |  |                                         UINT32 nHeight, BYTE* WINPR_RESTRICT pDstData,  | 
901  |  |                                         UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst,  | 
902  |  |                                         UINT32 nYDst, UINT32 nDstWidth, UINT32 nDstHeight,  | 
903  |  |                                         const gdiPalette* WINPR_RESTRICT palette,  | 
904  |  |                                         BYTE** WINPR_RESTRICT ppGlyphData)  | 
905  | 16.2k  | { | 
906  | 16.2k  |   UINT16 glyphIndex = 0;  | 
907  |  |  | 
908  | 16.2k  |   if (ppGlyphData)  | 
909  | 16.2k  |     *ppGlyphData = NULL;  | 
910  |  |  | 
911  | 16.2k  |   if ((glyphFlags & CLEARCODEC_FLAG_GLYPH_HIT) && !(glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX))  | 
912  | 1.22k  |   { | 
913  | 1.22k  |     WLog_ERR(TAG, "Invalid glyph flags %08" PRIX32 "", glyphFlags);  | 
914  | 1.22k  |     return FALSE;  | 
915  | 1.22k  |   }  | 
916  |  |  | 
917  | 14.9k  |   if ((glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX) == 0)  | 
918  | 8.90k  |     return TRUE;  | 
919  |  |  | 
920  | 6.08k  |   if ((nWidth * nHeight) > (1024 * 1024))  | 
921  | 0  |   { | 
922  | 0  |     WLog_ERR(TAG, "glyph too large: %" PRIu32 "x%" PRIu32 "", nWidth, nHeight);  | 
923  | 0  |     return FALSE;  | 
924  | 0  |   }  | 
925  |  |  | 
926  | 6.08k  |   if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))  | 
927  | 0  |     return FALSE;  | 
928  |  |  | 
929  | 6.08k  |   Stream_Read_UINT16(s, glyphIndex);  | 
930  |  |  | 
931  | 6.08k  |   if (glyphIndex >= 4000)  | 
932  | 2.41k  |   { | 
933  | 2.41k  |     WLog_ERR(TAG, "Invalid glyphIndex %" PRIu16 "", glyphIndex);  | 
934  | 2.41k  |     return FALSE;  | 
935  | 2.41k  |   }  | 
936  |  |  | 
937  | 3.67k  |   if (glyphFlags & CLEARCODEC_FLAG_GLYPH_HIT)  | 
938  | 771  |   { | 
939  | 771  |     UINT32 nSrcStep = 0;  | 
940  | 771  |     CLEAR_GLYPH_ENTRY* glyphEntry = &(clear->GlyphCache[glyphIndex]);  | 
941  | 771  |     BYTE* glyphData = NULL;  | 
942  |  |  | 
943  | 771  |     if (!glyphEntry)  | 
944  | 0  |     { | 
945  | 0  |       WLog_ERR(TAG, "clear->GlyphCache[%" PRIu16 "]=NULL", glyphIndex);  | 
946  | 0  |       return FALSE;  | 
947  | 0  |     }  | 
948  |  |  | 
949  | 771  |     glyphData = (BYTE*)glyphEntry->pixels;  | 
950  |  |  | 
951  | 771  |     if (!glyphData)  | 
952  | 771  |     { | 
953  | 771  |       WLog_ERR(TAG, "clear->GlyphCache[%" PRIu16 "]->pixels=NULL", glyphIndex);  | 
954  | 771  |       return FALSE;  | 
955  | 771  |     }  | 
956  |  |  | 
957  | 0  |     if ((nWidth * nHeight) > glyphEntry->count)  | 
958  | 0  |     { | 
959  | 0  |       WLog_ERR(TAG,  | 
960  | 0  |                "(nWidth %" PRIu32 " * nHeight %" PRIu32 ") > glyphEntry->count %" PRIu32 "",  | 
961  | 0  |                nWidth, nHeight, glyphEntry->count);  | 
962  | 0  |       return FALSE;  | 
963  | 0  |     }  | 
964  |  |  | 
965  | 0  |     nSrcStep = nWidth * FreeRDPGetBytesPerPixel(clear->format);  | 
966  | 0  |     return convert_color(pDstData, nDstStep, DstFormat, nXDst, nYDst, nWidth, nHeight,  | 
967  | 0  |                          glyphData, nSrcStep, clear->format, nDstWidth, nDstHeight, palette);  | 
968  | 0  |   }  | 
969  |  |  | 
970  | 2.90k  |   if (glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX)  | 
971  | 2.90k  |   { | 
972  | 2.90k  |     const UINT32 bpp = FreeRDPGetBytesPerPixel(clear->format);  | 
973  | 2.90k  |     CLEAR_GLYPH_ENTRY* glyphEntry = &(clear->GlyphCache[glyphIndex]);  | 
974  | 2.90k  |     glyphEntry->count = nWidth * nHeight;  | 
975  |  |  | 
976  | 2.90k  |     if (glyphEntry->count > glyphEntry->size)  | 
977  | 2.90k  |     { | 
978  | 2.90k  |       BYTE* tmp =  | 
979  | 2.90k  |           winpr_aligned_recalloc(glyphEntry->pixels, glyphEntry->count, 1ull * bpp, 32);  | 
980  |  |  | 
981  | 2.90k  |       if (!tmp)  | 
982  | 0  |       { | 
983  | 0  |         WLog_ERR(TAG, "glyphEntry->pixels winpr_aligned_recalloc %" PRIu32 " failed!",  | 
984  | 0  |                  glyphEntry->count * bpp);  | 
985  | 0  |         return FALSE;  | 
986  | 0  |       }  | 
987  |  |  | 
988  | 2.90k  |       glyphEntry->size = glyphEntry->count;  | 
989  | 2.90k  |       glyphEntry->pixels = (UINT32*)tmp;  | 
990  | 2.90k  |     }  | 
991  |  |  | 
992  | 2.90k  |     if (!glyphEntry->pixels)  | 
993  | 0  |     { | 
994  | 0  |       WLog_ERR(TAG, "glyphEntry->pixels=NULL");  | 
995  | 0  |       return FALSE;  | 
996  | 0  |     }  | 
997  |  |  | 
998  | 2.90k  |     if (ppGlyphData)  | 
999  | 2.90k  |       *ppGlyphData = (BYTE*)glyphEntry->pixels;  | 
1000  |  |  | 
1001  | 2.90k  |     return TRUE;  | 
1002  | 2.90k  |   }  | 
1003  |  |  | 
1004  | 0  |   return TRUE;  | 
1005  | 2.90k  | }  | 
1006  |  |  | 
1007  |  | static INLINE BOOL updateContextFormat(CLEAR_CONTEXT* WINPR_RESTRICT clear, UINT32 DstFormat)  | 
1008  | 32.4k  | { | 
1009  | 32.4k  |   if (!clear || !clear->nsc)  | 
1010  | 0  |     return FALSE;  | 
1011  |  |  | 
1012  | 32.4k  |   clear->format = DstFormat;  | 
1013  | 32.4k  |   return nsc_context_set_parameters(clear->nsc, NSC_COLOR_FORMAT, DstFormat);  | 
1014  | 32.4k  | }  | 
1015  |  |  | 
1016  |  | INT32 clear_decompress(CLEAR_CONTEXT* WINPR_RESTRICT clear, const BYTE* WINPR_RESTRICT pSrcData,  | 
1017  |  |                        UINT32 SrcSize, UINT32 nWidth, UINT32 nHeight, BYTE* WINPR_RESTRICT pDstData,  | 
1018  |  |                        UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,  | 
1019  |  |                        UINT32 nDstWidth, UINT32 nDstHeight,  | 
1020  |  |                        const gdiPalette* WINPR_RESTRICT palette)  | 
1021  | 16.2k  | { | 
1022  | 16.2k  |   INT32 rc = -1;  | 
1023  | 16.2k  |   BYTE seqNumber = 0;  | 
1024  | 16.2k  |   BYTE glyphFlags = 0;  | 
1025  | 16.2k  |   UINT32 residualByteCount = 0;  | 
1026  | 16.2k  |   UINT32 bandsByteCount = 0;  | 
1027  | 16.2k  |   UINT32 subcodecByteCount = 0;  | 
1028  | 16.2k  |   wStream sbuffer = { 0 }; | 
1029  | 16.2k  |   wStream* s = NULL;  | 
1030  | 16.2k  |   BYTE* glyphData = NULL;  | 
1031  |  |  | 
1032  | 16.2k  |   if (!pDstData)  | 
1033  | 0  |     return -1002;  | 
1034  |  |  | 
1035  | 16.2k  |   if ((nDstWidth == 0) || (nDstHeight == 0))  | 
1036  | 0  |     return -1022;  | 
1037  |  |  | 
1038  | 16.2k  |   if ((nWidth > 0xFFFF) || (nHeight > 0xFFFF))  | 
1039  | 0  |     return -1004;  | 
1040  |  |  | 
1041  | 16.2k  |   s = Stream_StaticConstInit(&sbuffer, pSrcData, SrcSize);  | 
1042  |  |  | 
1043  | 16.2k  |   if (!s)  | 
1044  | 0  |     return -2005;  | 
1045  |  |  | 
1046  | 16.2k  |   if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))  | 
1047  | 0  |     goto fail;  | 
1048  |  |  | 
1049  | 16.2k  |   if (!updateContextFormat(clear, DstFormat))  | 
1050  | 0  |     goto fail;  | 
1051  |  |  | 
1052  | 16.2k  |   Stream_Read_UINT8(s, glyphFlags);  | 
1053  | 16.2k  |   Stream_Read_UINT8(s, seqNumber);  | 
1054  |  |  | 
1055  | 16.2k  |   if (!clear->seqNumber && seqNumber)  | 
1056  | 12.8k  |     clear->seqNumber = seqNumber;  | 
1057  |  |  | 
1058  | 16.2k  |   if (seqNumber != clear->seqNumber)  | 
1059  | 0  |   { | 
1060  | 0  |     WLog_ERR(TAG, "Sequence number unexpected %" PRIu8 " - %" PRIu32 "", seqNumber,  | 
1061  | 0  |              clear->seqNumber);  | 
1062  | 0  |     WLog_ERR(TAG, "seqNumber %" PRIu8 " != clear->seqNumber %" PRIu32 "", seqNumber,  | 
1063  | 0  |              clear->seqNumber);  | 
1064  | 0  |     goto fail;  | 
1065  | 0  |   }  | 
1066  |  |  | 
1067  | 16.2k  |   clear->seqNumber = (seqNumber + 1) % 256;  | 
1068  |  |  | 
1069  | 16.2k  |   if (glyphFlags & CLEARCODEC_FLAG_CACHE_RESET)  | 
1070  | 3.17k  |   { | 
1071  | 3.17k  |     clear_reset_vbar_storage(clear, FALSE);  | 
1072  | 3.17k  |   }  | 
1073  |  |  | 
1074  | 16.2k  |   if (!clear_decompress_glyph_data(clear, s, glyphFlags, nWidth, nHeight, pDstData, DstFormat,  | 
1075  | 16.2k  |                                    nDstStep, nXDst, nYDst, nDstWidth, nDstHeight, palette,  | 
1076  | 16.2k  |                                    &glyphData))  | 
1077  | 4.41k  |   { | 
1078  | 4.41k  |     WLog_ERR(TAG, "clear_decompress_glyph_data failed!");  | 
1079  | 4.41k  |     goto fail;  | 
1080  | 4.41k  |   }  | 
1081  |  |  | 
1082  |  |   /* Read composition payload header parameters */  | 
1083  | 11.8k  |   if (Stream_GetRemainingLength(s) < 12)  | 
1084  | 2.60k  |   { | 
1085  | 2.60k  |     const UINT32 mask = (CLEARCODEC_FLAG_GLYPH_HIT | CLEARCODEC_FLAG_GLYPH_INDEX);  | 
1086  |  |  | 
1087  | 2.60k  |     if ((glyphFlags & mask) == mask)  | 
1088  | 0  |       goto finish;  | 
1089  |  |  | 
1090  | 2.60k  |     WLog_ERR(TAG,  | 
1091  | 2.60k  |              "invalid glyphFlags, missing flags: 0x%02" PRIx8 " & 0x%02" PRIx32  | 
1092  | 2.60k  |              " == 0x%02" PRIx32,  | 
1093  | 2.60k  |              glyphFlags, mask, glyphFlags & mask);  | 
1094  | 2.60k  |     goto fail;  | 
1095  | 2.60k  |   }  | 
1096  |  |  | 
1097  | 9.20k  |   Stream_Read_UINT32(s, residualByteCount);  | 
1098  | 9.20k  |   Stream_Read_UINT32(s, bandsByteCount);  | 
1099  | 9.20k  |   Stream_Read_UINT32(s, subcodecByteCount);  | 
1100  |  |  | 
1101  | 9.20k  |   if (residualByteCount > 0)  | 
1102  | 4.90k  |   { | 
1103  | 4.90k  |     if (!clear_decompress_residual_data(clear, s, residualByteCount, nWidth, nHeight, pDstData,  | 
1104  | 4.90k  |                                         DstFormat, nDstStep, nXDst, nYDst, nDstWidth,  | 
1105  | 4.90k  |                                         nDstHeight, palette))  | 
1106  | 4.88k  |     { | 
1107  | 4.88k  |       WLog_ERR(TAG, "clear_decompress_residual_data failed!");  | 
1108  | 4.88k  |       goto fail;  | 
1109  | 4.88k  |     }  | 
1110  | 4.90k  |   }  | 
1111  |  |  | 
1112  | 4.31k  |   if (bandsByteCount > 0)  | 
1113  | 2.20k  |   { | 
1114  | 2.20k  |     if (!clear_decompress_bands_data(clear, s, bandsByteCount, nWidth, nHeight, pDstData,  | 
1115  | 2.20k  |                                      DstFormat, nDstStep, nXDst, nYDst, nDstWidth, nDstHeight))  | 
1116  | 2.00k  |     { | 
1117  | 2.00k  |       WLog_ERR(TAG, "clear_decompress_bands_data failed!");  | 
1118  | 2.00k  |       goto fail;  | 
1119  | 2.00k  |     }  | 
1120  | 2.20k  |   }  | 
1121  |  |  | 
1122  | 2.31k  |   if (subcodecByteCount > 0)  | 
1123  | 2.21k  |   { | 
1124  | 2.21k  |     if (!clear_decompress_subcodecs_data(clear, s, subcodecByteCount, nWidth, nHeight, pDstData,  | 
1125  | 2.21k  |                                          DstFormat, nDstStep, nXDst, nYDst, nDstWidth,  | 
1126  | 2.21k  |                                          nDstHeight, palette))  | 
1127  | 1.87k  |     { | 
1128  | 1.87k  |       WLog_ERR(TAG, "clear_decompress_subcodecs_data failed!");  | 
1129  | 1.87k  |       goto fail;  | 
1130  | 1.87k  |     }  | 
1131  | 2.21k  |   }  | 
1132  |  |  | 
1133  | 439  |   if (glyphData)  | 
1134  | 130  |   { | 
1135  | 130  |     if (!freerdp_image_copy_no_overlap(glyphData, clear->format, 0, 0, 0, nWidth, nHeight,  | 
1136  | 130  |                                        pDstData, DstFormat, nDstStep, nXDst, nYDst, palette,  | 
1137  | 130  |                                        FREERDP_KEEP_DST_ALPHA))  | 
1138  | 0  |       goto fail;  | 
1139  | 130  |   }  | 
1140  |  |  | 
1141  | 439  | finish:  | 
1142  | 439  |   rc = 0;  | 
1143  | 16.2k  | fail:  | 
1144  | 16.2k  |   return rc;  | 
1145  | 439  | }  | 
1146  |  |  | 
1147  |  | int clear_compress(CLEAR_CONTEXT* WINPR_RESTRICT clear, const BYTE* WINPR_RESTRICT pSrcData,  | 
1148  |  |                    UINT32 SrcSize, BYTE** WINPR_RESTRICT ppDstData, UINT32* WINPR_RESTRICT pDstSize)  | 
1149  | 0  | { | 
1150  | 0  |   WLog_ERR(TAG, "TODO: not implemented!");  | 
1151  | 0  |   return 1;  | 
1152  | 0  | }  | 
1153  |  |  | 
1154  |  | BOOL clear_context_reset(CLEAR_CONTEXT* WINPR_RESTRICT clear)  | 
1155  | 16.2k  | { | 
1156  | 16.2k  |   if (!clear)  | 
1157  | 0  |     return FALSE;  | 
1158  |  |  | 
1159  |  |   /**  | 
1160  |  |    * The ClearCodec context is not bound to a particular surface,  | 
1161  |  |    * and its internal caches must NOT be reset on the ResetGraphics PDU.  | 
1162  |  |    */  | 
1163  | 16.2k  |   clear->seqNumber = 0;  | 
1164  | 16.2k  |   return TRUE;  | 
1165  | 16.2k  | }  | 
1166  |  |  | 
1167  |  | CLEAR_CONTEXT* clear_context_new(BOOL Compressor)  | 
1168  | 16.2k  | { | 
1169  | 16.2k  |   CLEAR_CONTEXT* clear = (CLEAR_CONTEXT*)winpr_aligned_calloc(1, sizeof(CLEAR_CONTEXT), 32);  | 
1170  |  |  | 
1171  | 16.2k  |   if (!clear)  | 
1172  | 0  |     return NULL;  | 
1173  |  |  | 
1174  | 16.2k  |   clear->Compressor = Compressor;  | 
1175  | 16.2k  |   clear->nsc = nsc_context_new();  | 
1176  |  |  | 
1177  | 16.2k  |   if (!clear->nsc)  | 
1178  | 0  |     goto error_nsc;  | 
1179  |  |  | 
1180  | 16.2k  |   if (!updateContextFormat(clear, PIXEL_FORMAT_BGRX32))  | 
1181  | 0  |     goto error_nsc;  | 
1182  |  |  | 
1183  | 16.2k  |   if (!clear_resize_buffer(clear, 512, 512))  | 
1184  | 0  |     goto error_nsc;  | 
1185  |  |  | 
1186  | 16.2k  |   if (!clear->TempBuffer)  | 
1187  | 0  |     goto error_nsc;  | 
1188  |  |  | 
1189  | 16.2k  |   if (!clear_context_reset(clear))  | 
1190  | 0  |     goto error_nsc;  | 
1191  |  |  | 
1192  | 16.2k  |   return clear;  | 
1193  | 0  | error_nsc:  | 
1194  | 0  |   WINPR_PRAGMA_DIAG_PUSH  | 
1195  | 0  |   WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC  | 
1196  | 0  |   clear_context_free(clear);  | 
1197  | 0  |   WINPR_PRAGMA_DIAG_POP  | 
1198  | 0  |   return NULL;  | 
1199  | 16.2k  | }  | 
1200  |  |  | 
1201  |  | void clear_context_free(CLEAR_CONTEXT* clear)  | 
1202  | 16.2k  | { | 
1203  | 16.2k  |   if (!clear)  | 
1204  | 0  |     return;  | 
1205  |  |  | 
1206  | 16.2k  |   nsc_context_free(clear->nsc);  | 
1207  | 16.2k  |   winpr_aligned_free(clear->TempBuffer);  | 
1208  |  |  | 
1209  | 16.2k  |   clear_reset_vbar_storage(clear, TRUE);  | 
1210  | 16.2k  |   clear_reset_glyph_cache(clear);  | 
1211  |  |  | 
1212  | 16.2k  |   winpr_aligned_free(clear);  | 
1213  | 16.2k  | }  |