Blame libfreerdp/codec/clear.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 * ClearCodec Bitmap Compression
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 * Copyright 2016 Armin Novak <armin.novak@thincast.com>
Packit 1fb8d4
 * Copyright 2016 Thincast Technologies GmbH
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/print.h>
Packit 1fb8d4
#include <winpr/bitstream.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/codec/color.h>
Packit 1fb8d4
#include <freerdp/codec/clear.h>
Packit 1fb8d4
#include <freerdp/log.h>
Packit 1fb8d4
Packit 1fb8d4
#define TAG FREERDP_TAG("codec.clear")
Packit 1fb8d4
Packit 1fb8d4
#define CLEARCODEC_FLAG_GLYPH_INDEX	0x01
Packit 1fb8d4
#define CLEARCODEC_FLAG_GLYPH_HIT	0x02
Packit 1fb8d4
#define CLEARCODEC_FLAG_CACHE_RESET	0x04
Packit 1fb8d4
Packit 1fb8d4
#define CLEARCODEC_VBAR_SIZE 32768
Packit 1fb8d4
#define CLEARCODEC_VBAR_SHORT_SIZE 16384
Packit 1fb8d4
Packit 1fb8d4
struct _CLEAR_GLYPH_ENTRY
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 size;
Packit 1fb8d4
	UINT32 count;
Packit 1fb8d4
	UINT32* pixels;
Packit 1fb8d4
};
Packit 1fb8d4
typedef struct _CLEAR_GLYPH_ENTRY CLEAR_GLYPH_ENTRY;
Packit 1fb8d4
Packit 1fb8d4
struct _CLEAR_VBAR_ENTRY
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 size;
Packit 1fb8d4
	UINT32 count;
Packit 1fb8d4
	BYTE* pixels;
Packit 1fb8d4
};
Packit 1fb8d4
typedef struct _CLEAR_VBAR_ENTRY CLEAR_VBAR_ENTRY;
Packit 1fb8d4
Packit 1fb8d4
struct _CLEAR_CONTEXT
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL Compressor;
Packit 1fb8d4
	NSC_CONTEXT* nsc;
Packit 1fb8d4
	UINT32 seqNumber;
Packit 1fb8d4
	BYTE* TempBuffer;
Packit 1fb8d4
	UINT32 TempSize;
Packit 1fb8d4
	UINT32 nTempStep;
Packit 1fb8d4
	UINT32 TempFormat;
Packit 1fb8d4
	UINT32 format;
Packit 1fb8d4
	CLEAR_GLYPH_ENTRY GlyphCache[4000];
Packit 1fb8d4
	UINT32 VBarStorageCursor;
Packit 1fb8d4
	CLEAR_VBAR_ENTRY VBarStorage[CLEARCODEC_VBAR_SIZE];
Packit 1fb8d4
	UINT32 ShortVBarStorageCursor;
Packit 1fb8d4
	CLEAR_VBAR_ENTRY ShortVBarStorage[CLEARCODEC_VBAR_SHORT_SIZE];
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
static const UINT32 CLEAR_LOG2_FLOOR[256] =
Packit 1fb8d4
{
Packit 1fb8d4
	0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
Packit 1fb8d4
	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
Packit 1fb8d4
	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
Packit 1fb8d4
	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
Packit 1fb8d4
	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
Packit 1fb8d4
	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
Packit 1fb8d4
	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
Packit 1fb8d4
	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
Packit 1fb8d4
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
Packit 1fb8d4
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
Packit 1fb8d4
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
Packit 1fb8d4
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
Packit 1fb8d4
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
Packit 1fb8d4
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
Packit 1fb8d4
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
Packit 1fb8d4
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
static const BYTE CLEAR_8BIT_MASKS[9] =
Packit 1fb8d4
{
Packit 1fb8d4
	0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
static BOOL convert_color(BYTE* dst, UINT32 nDstStep, UINT32 DstFormat,
Packit 1fb8d4
                          UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
Packit 1fb8d4
                          const BYTE* src, UINT32 nSrcStep, UINT32 SrcFormat,
Packit 1fb8d4
                          UINT32 nDstWidth, UINT32 nDstHeight, const gdiPalette* palette)
Packit 1fb8d4
{
Packit 1fb8d4
	if (nWidth + nXDst > nDstWidth)
Packit 1fb8d4
		nWidth = nDstWidth - nXDst;
Packit 1fb8d4
Packit 1fb8d4
	if (nHeight + nYDst > nDstHeight)
Packit 1fb8d4
		nHeight = nDstHeight - nYDst;
Packit 1fb8d4
Packit 1fb8d4
	return freerdp_image_copy(dst, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
Packit 1fb8d4
	                          src, SrcFormat, nSrcStep, 0, 0, palette, 0);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL clear_decompress_nscodec(NSC_CONTEXT* nsc, UINT32 width,
Packit 1fb8d4
                                     UINT32 height,
Packit 1fb8d4
                                     wStream* s, UINT32 bitmapDataByteCount,
Packit 1fb8d4
                                     BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
Packit 1fb8d4
                                     UINT32 nXDstRel, UINT32 nYDstRel)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL rc;
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < bitmapDataByteCount)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "stream short %"PRIuz" [%"PRIu32" expected]", Stream_GetRemainingLength(s),
Packit 1fb8d4
		         bitmapDataByteCount);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	rc = nsc_process_message(nsc, 32, width, height, Stream_Pointer(s),
Packit 1fb8d4
	                         bitmapDataByteCount, pDstData, DstFormat,
Packit 1fb8d4
	                         nDstStep, nXDstRel, nYDstRel, width, height, FREERDP_FLIP_NONE);
Packit 1fb8d4
	Stream_Seek(s, bitmapDataByteCount);
Packit 1fb8d4
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL clear_decompress_subcode_rlex(wStream* s,
Packit 1fb8d4
        UINT32 bitmapDataByteCount,
Packit 1fb8d4
        UINT32 width, UINT32 height,
Packit 1fb8d4
        BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
Packit 1fb8d4
        UINT32 nXDstRel, UINT32 nYDstRel, UINT32 nDstWidth, UINT32 nDstHeight)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 x = 0, y = 0;
Packit 1fb8d4
	UINT32 i;
Packit 1fb8d4
	UINT32 pixelCount;
Packit 1fb8d4
	UINT32 bitmapDataOffset;
Packit 1fb8d4
	UINT32 pixelIndex;
Packit 1fb8d4
	UINT32 numBits;
Packit 1fb8d4
	BYTE startIndex;
Packit 1fb8d4
	BYTE stopIndex;
Packit 1fb8d4
	BYTE suiteIndex;
Packit 1fb8d4
	BYTE suiteDepth;
Packit 1fb8d4
	BYTE paletteCount;
Packit 1fb8d4
	UINT32 palette[128] = { 0 };
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < bitmapDataByteCount)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "stream short %"PRIuz" [%"PRIu32" expected]", Stream_GetRemainingLength(s),
Packit 1fb8d4
		         bitmapDataByteCount);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read_UINT8(s, paletteCount);
Packit 1fb8d4
	bitmapDataOffset = 1 + (paletteCount * 3);
Packit 1fb8d4
Packit 1fb8d4
	if (paletteCount > 127)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "paletteCount %"PRIu8"", paletteCount);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < paletteCount; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		BYTE r, g, b;
Packit 1fb8d4
		Stream_Read_UINT8(s, b);
Packit 1fb8d4
		Stream_Read_UINT8(s, g);
Packit 1fb8d4
		Stream_Read_UINT8(s, r);
Packit 1fb8d4
		palette[i] = FreeRDPGetColor(DstFormat, r, g, b, 0xFF);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	pixelIndex = 0;
Packit 1fb8d4
	pixelCount = width * height;
Packit 1fb8d4
	numBits = CLEAR_LOG2_FLOOR[paletteCount - 1] + 1;
Packit 1fb8d4
Packit 1fb8d4
	while (bitmapDataOffset < bitmapDataByteCount)
Packit 1fb8d4
	{
Packit 1fb8d4
		UINT32 tmp;
Packit 1fb8d4
		UINT32 color;
Packit 1fb8d4
		UINT32 runLengthFactor;
Packit 1fb8d4
Packit 1fb8d4
		if (Stream_GetRemainingLength(s) < 2)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "stream short %"PRIuz" [2 expected]", Stream_GetRemainingLength(s));
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		Stream_Read_UINT8(s, tmp);
Packit 1fb8d4
		Stream_Read_UINT8(s, runLengthFactor);
Packit 1fb8d4
		bitmapDataOffset += 2;
Packit 1fb8d4
		suiteDepth = (tmp >> numBits) & CLEAR_8BIT_MASKS[(8 - numBits)];
Packit 1fb8d4
		stopIndex = tmp & CLEAR_8BIT_MASKS[numBits];
Packit 1fb8d4
		startIndex = stopIndex - suiteDepth;
Packit 1fb8d4
Packit 1fb8d4
		if (runLengthFactor >= 0xFF)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (Stream_GetRemainingLength(s) < 2)
Packit 1fb8d4
			{
Packit 1fb8d4
				WLog_ERR(TAG, "stream short %"PRIuz" [2 expected]", Stream_GetRemainingLength(s));
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			Stream_Read_UINT16(s, runLengthFactor);
Packit 1fb8d4
			bitmapDataOffset += 2;
Packit 1fb8d4
Packit 1fb8d4
			if (runLengthFactor >= 0xFFFF)
Packit 1fb8d4
			{
Packit 1fb8d4
				if (Stream_GetRemainingLength(s) < 4)
Packit 1fb8d4
				{
Packit 1fb8d4
					WLog_ERR(TAG, "stream short %"PRIuz" [4 expected]", Stream_GetRemainingLength(s));
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				Stream_Read_UINT32(s, runLengthFactor);
Packit 1fb8d4
				bitmapDataOffset += 4;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (startIndex >= paletteCount)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "startIndex %"PRIu8" > paletteCount %"PRIu8"]", startIndex, paletteCount);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (stopIndex >= paletteCount)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "stopIndex %"PRIu8" > paletteCount %"PRIu8"]", stopIndex, paletteCount);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		suiteIndex = startIndex;
Packit 1fb8d4
Packit 1fb8d4
		if (suiteIndex > 127)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "suiteIndex %"PRIu8" > 127]", suiteIndex);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		color = palette[suiteIndex];
Packit 1fb8d4
Packit 1fb8d4
		if ((pixelIndex + runLengthFactor) > pixelCount)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "pixelIndex %"PRIu32" + runLengthFactor %"PRIu32" > pixelCount %"PRIu32"",
Packit 1fb8d4
			         pixelIndex, runLengthFactor,
Packit 1fb8d4
			         pixelCount);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		for (i = 0; i < runLengthFactor; i++)
Packit 1fb8d4
		{
Packit 1fb8d4
			BYTE* pTmpData = &pDstData[(nXDstRel + x) * GetBytesPerPixel(DstFormat) +
Packit 1fb8d4
			                                          (nYDstRel + y) * nDstStep];
Packit 1fb8d4
Packit 1fb8d4
			if ((nXDstRel + x < nDstWidth) && (nYDstRel + y < nDstHeight))
Packit 1fb8d4
				WriteColor(pTmpData, DstFormat, color);
Packit 1fb8d4
Packit 1fb8d4
			if (++x >= width)
Packit 1fb8d4
			{
Packit 1fb8d4
				y++;
Packit 1fb8d4
				x = 0;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		pixelIndex += runLengthFactor;
Packit 1fb8d4
Packit 1fb8d4
		if ((pixelIndex + (suiteDepth + 1)) > pixelCount)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "pixelIndex %"PRIu32" + suiteDepth %"PRIu8" + 1 > pixelCount %"PRIu32"",
Packit 1fb8d4
			         pixelIndex, suiteDepth,
Packit 1fb8d4
			         pixelCount);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		for (i = 0; i <= suiteDepth; i++)
Packit 1fb8d4
		{
Packit 1fb8d4
			BYTE* pTmpData = &pDstData[(nXDstRel + x) * GetBytesPerPixel(DstFormat) +
Packit 1fb8d4
			                                          (nYDstRel + y) * nDstStep];
Packit 1fb8d4
			UINT32 color = palette[suiteIndex];
Packit 1fb8d4
Packit 1fb8d4
			if (suiteIndex > 127)
Packit 1fb8d4
			{
Packit 1fb8d4
				WLog_ERR(TAG, "suiteIndex %"PRIu8" > 127", suiteIndex);
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			suiteIndex++;
Packit 1fb8d4
Packit 1fb8d4
			if ((nXDstRel + x < nDstWidth) && (nYDstRel + y < nDstHeight))
Packit 1fb8d4
				WriteColor(pTmpData, DstFormat, color);
Packit 1fb8d4
Packit 1fb8d4
			if (++x >= width)
Packit 1fb8d4
			{
Packit 1fb8d4
				y++;
Packit 1fb8d4
				x = 0;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		pixelIndex += (suiteDepth + 1);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (pixelIndex != pixelCount)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "pixelIndex %"PRIu32" != pixelCount %"PRIu32"", pixelIndex, pixelCount);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL clear_resize_buffer(CLEAR_CONTEXT* clear, UINT32 width, UINT32 height)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 size;
Packit 1fb8d4
Packit 1fb8d4
	if (!clear)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	size = ((width + 16) * (height + 16) * GetBytesPerPixel(clear->format));
Packit 1fb8d4
Packit 1fb8d4
	if (size > clear->TempSize)
Packit 1fb8d4
	{
Packit 1fb8d4
		BYTE* tmp = (BYTE*) realloc(clear->TempBuffer, size);
Packit 1fb8d4
Packit 1fb8d4
		if (!tmp)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "clear->TempBuffer realloc failed for %"PRIu32" bytes",
Packit 1fb8d4
			         size);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		clear->TempSize = size;
Packit 1fb8d4
		clear->TempBuffer = tmp;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL clear_decompress_residual_data(CLEAR_CONTEXT* clear,
Packit 1fb8d4
        wStream* s,
Packit 1fb8d4
        UINT32 residualByteCount,
Packit 1fb8d4
        UINT32 nWidth, UINT32 nHeight,
Packit 1fb8d4
        BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
Packit 1fb8d4
        UINT32 nXDst, UINT32 nYDst,
Packit 1fb8d4
        UINT32 nDstWidth, UINT32 nDstHeight,
Packit 1fb8d4
        const gdiPalette* palette)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 i;
Packit 1fb8d4
	UINT32 nSrcStep;
Packit 1fb8d4
	UINT32 suboffset;
Packit 1fb8d4
	BYTE* dstBuffer;
Packit 1fb8d4
	UINT32 pixelIndex;
Packit 1fb8d4
	UINT32 pixelCount;
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < residualByteCount)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "stream short %"PRIuz" [%"PRIu32" expected]", Stream_GetRemainingLength(s),
Packit 1fb8d4
		         residualByteCount);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	suboffset = 0;
Packit 1fb8d4
	pixelIndex = 0;
Packit 1fb8d4
	pixelCount = nWidth * nHeight;
Packit 1fb8d4
Packit 1fb8d4
	if (!clear_resize_buffer(clear, nWidth, nHeight))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	dstBuffer = clear->TempBuffer;
Packit 1fb8d4
Packit 1fb8d4
	while (suboffset < residualByteCount)
Packit 1fb8d4
	{
Packit 1fb8d4
		BYTE r, g, b;
Packit 1fb8d4
		UINT32 runLengthFactor;
Packit 1fb8d4
		UINT32 color;
Packit 1fb8d4
Packit 1fb8d4
		if (Stream_GetRemainingLength(s) < 4)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "stream short %"PRIuz" [4 expected]", Stream_GetRemainingLength(s));
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		Stream_Read_UINT8(s, b);
Packit 1fb8d4
		Stream_Read_UINT8(s, g);
Packit 1fb8d4
		Stream_Read_UINT8(s, r);
Packit 1fb8d4
		Stream_Read_UINT8(s, runLengthFactor);
Packit 1fb8d4
		suboffset += 4;
Packit 1fb8d4
		color = FreeRDPGetColor(clear->format, r, g, b, 0xFF);
Packit 1fb8d4
Packit 1fb8d4
		if (runLengthFactor >= 0xFF)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (Stream_GetRemainingLength(s) < 2)
Packit 1fb8d4
			{
Packit 1fb8d4
				WLog_ERR(TAG, "stream short %"PRIuz" [2 expected]", Stream_GetRemainingLength(s));
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			Stream_Read_UINT16(s, runLengthFactor);
Packit 1fb8d4
			suboffset += 2;
Packit 1fb8d4
Packit 1fb8d4
			if (runLengthFactor >= 0xFFFF)
Packit 1fb8d4
			{
Packit 1fb8d4
				if (Stream_GetRemainingLength(s) < 4)
Packit 1fb8d4
				{
Packit 1fb8d4
					WLog_ERR(TAG, "stream short %"PRIuz" [4 expected]", Stream_GetRemainingLength(s));
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				Stream_Read_UINT32(s, runLengthFactor);
Packit 1fb8d4
				suboffset += 4;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if ((pixelIndex + runLengthFactor) > pixelCount)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "pixelIndex %"PRIu32" + runLengthFactor %"PRIu32" > pixelCount %"PRIu32"",
Packit 1fb8d4
			         pixelIndex, runLengthFactor,
Packit 1fb8d4
			         pixelCount);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		for (i = 0; i < runLengthFactor; i++)
Packit 1fb8d4
		{
Packit 1fb8d4
			WriteColor(dstBuffer, clear->format, color);
Packit 1fb8d4
			dstBuffer += GetBytesPerPixel(clear->format);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		pixelIndex += runLengthFactor;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	nSrcStep = nWidth * GetBytesPerPixel(clear->format);
Packit 1fb8d4
Packit 1fb8d4
	if (pixelIndex != pixelCount)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "pixelIndex %"PRIu32" != pixelCount %"PRIu32"", pixelIndex, pixelCount);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return convert_color(pDstData, nDstStep, DstFormat,
Packit 1fb8d4
	                     nXDst, nYDst, nWidth, nHeight,
Packit 1fb8d4
	                     clear->TempBuffer, nSrcStep, clear->format,
Packit 1fb8d4
	                     nDstWidth, nDstHeight, palette);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL clear_decompress_subcodecs_data(CLEAR_CONTEXT* clear, wStream* s,
Packit 1fb8d4
        UINT32 subcodecByteCount, UINT32 nWidth, UINT32 nHeight,
Packit 1fb8d4
        BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
Packit 1fb8d4
        UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth, UINT32 nDstHeight,
Packit 1fb8d4
        const gdiPalette* palette)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT16 xStart;
Packit 1fb8d4
	UINT16 yStart;
Packit 1fb8d4
	UINT16 width;
Packit 1fb8d4
	UINT16 height;
Packit 1fb8d4
	UINT32 bitmapDataByteCount;
Packit 1fb8d4
	BYTE subcodecId;
Packit 1fb8d4
	UINT32 suboffset;
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < subcodecByteCount)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "stream short %"PRIuz" [%"PRIu32" expected]", Stream_GetRemainingLength(s),
Packit 1fb8d4
		         subcodecByteCount);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	suboffset = 0;
Packit 1fb8d4
Packit 1fb8d4
	while (suboffset < subcodecByteCount)
Packit 1fb8d4
	{
Packit 1fb8d4
		UINT32 nXDstRel;
Packit 1fb8d4
		UINT32 nYDstRel;
Packit 1fb8d4
Packit 1fb8d4
		if (Stream_GetRemainingLength(s) < 13)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "stream short %"PRIuz" [13 expected]", Stream_GetRemainingLength(s));
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		Stream_Read_UINT16(s, xStart);
Packit 1fb8d4
		Stream_Read_UINT16(s, yStart);
Packit 1fb8d4
		Stream_Read_UINT16(s, width);
Packit 1fb8d4
		Stream_Read_UINT16(s, height);
Packit 1fb8d4
		Stream_Read_UINT32(s, bitmapDataByteCount);
Packit 1fb8d4
		Stream_Read_UINT8(s, subcodecId);
Packit 1fb8d4
		suboffset += 13;
Packit 1fb8d4
Packit 1fb8d4
		if (Stream_GetRemainingLength(s) < bitmapDataByteCount)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "stream short %"PRIuz" [%"PRIu32" expected]", Stream_GetRemainingLength(s),
Packit 1fb8d4
			         bitmapDataByteCount);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		nXDstRel = nXDst + xStart;
Packit 1fb8d4
		nYDstRel = nYDst + yStart;
Packit 1fb8d4
Packit 1fb8d4
		if (width > nWidth)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "width %"PRIu16" > nWidth %"PRIu32"", width, nWidth);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (height > nHeight)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "height %"PRIu16" > nHeight %"PRIu32"", height, nHeight);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (!clear_resize_buffer(clear, width, height))
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		switch (subcodecId)
Packit 1fb8d4
		{
Packit 1fb8d4
			case 0: /* Uncompressed */
Packit 1fb8d4
				{
Packit 1fb8d4
					UINT32 nSrcStep = width * GetBytesPerPixel(PIXEL_FORMAT_BGR24);
Packit 1fb8d4
					UINT32 nSrcSize = nSrcStep * height;
Packit 1fb8d4
Packit 1fb8d4
					if (bitmapDataByteCount != nSrcSize)
Packit 1fb8d4
					{
Packit 1fb8d4
						WLog_ERR(TAG, "bitmapDataByteCount %"PRIu32" != nSrcSize %"PRIu32"", bitmapDataByteCount,
Packit 1fb8d4
						         nSrcSize);
Packit 1fb8d4
						return FALSE;
Packit 1fb8d4
					}
Packit 1fb8d4
Packit 1fb8d4
					if (!convert_color(pDstData, nDstStep, DstFormat,
Packit 1fb8d4
					                   nXDstRel, nYDstRel, width, height,
Packit 1fb8d4
					                   Stream_Pointer(s), nSrcStep,
Packit 1fb8d4
					                   PIXEL_FORMAT_BGR24,
Packit 1fb8d4
					                   nDstWidth, nDstHeight, palette))
Packit 1fb8d4
						return FALSE;
Packit 1fb8d4
Packit 1fb8d4
					Stream_Seek(s, bitmapDataByteCount);
Packit 1fb8d4
				}
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 1: /* NSCodec */
Packit 1fb8d4
				if (!clear_decompress_nscodec(clear->nsc, width, height,
Packit 1fb8d4
				                              s, bitmapDataByteCount,
Packit 1fb8d4
				                              pDstData, DstFormat, nDstStep,
Packit 1fb8d4
				                              nXDstRel, nYDstRel))
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 2: /* CLEARCODEC_SUBCODEC_RLEX */
Packit 1fb8d4
				if (!clear_decompress_subcode_rlex(s,
Packit 1fb8d4
				                                   bitmapDataByteCount,
Packit 1fb8d4
				                                   width, height,
Packit 1fb8d4
				                                   pDstData, DstFormat, nDstStep,
Packit 1fb8d4
				                                   nXDstRel, nYDstRel,
Packit 1fb8d4
				                                   nDstWidth, nDstHeight))
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			default:
Packit 1fb8d4
				WLog_ERR(TAG, "Unknown subcodec ID %"PRIu8"", subcodecId);
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		suboffset += bitmapDataByteCount;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL resize_vbar_entry(CLEAR_CONTEXT* clear, CLEAR_VBAR_ENTRY* vBarEntry)
Packit 1fb8d4
{
Packit 1fb8d4
	if (vBarEntry->count > vBarEntry->size)
Packit 1fb8d4
	{
Packit 1fb8d4
		const UINT32 bpp = GetBytesPerPixel(clear->format);
Packit 1fb8d4
		const UINT32 oldPos = vBarEntry->size * bpp;
Packit 1fb8d4
		const UINT32 diffSize = (vBarEntry->count - vBarEntry->size) * bpp;
Packit 1fb8d4
		BYTE* tmp;
Packit 1fb8d4
		vBarEntry->size = vBarEntry->count;
Packit 1fb8d4
		tmp = (BYTE*) realloc(vBarEntry->pixels,
Packit 1fb8d4
		                      vBarEntry->count * bpp);
Packit 1fb8d4
Packit 1fb8d4
		if (!tmp)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "vBarEntry->pixels realloc %"PRIu32" failed", vBarEntry->count * bpp);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		memset(&tmp[oldPos], 0, diffSize);
Packit 1fb8d4
		vBarEntry->pixels = tmp;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!vBarEntry->pixels && vBarEntry->size)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "vBarEntry->pixels is NULL but vBarEntry->size is %"PRIu32"",
Packit 1fb8d4
		         vBarEntry->size);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear,
Packit 1fb8d4
                                        wStream* s, UINT32 bandsByteCount,
Packit 1fb8d4
                                        UINT32 nWidth, UINT32 nHeight,
Packit 1fb8d4
                                        BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
Packit 1fb8d4
                                        UINT32 nXDst, UINT32 nYDst)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 i, y;
Packit 1fb8d4
	UINT32 count;
Packit 1fb8d4
	UINT32 suboffset;
Packit 1fb8d4
	UINT32 nXDstRel;
Packit 1fb8d4
	UINT32 nYDstRel;
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < bandsByteCount)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "stream short %"PRIuz" [11 expected]", Stream_GetRemainingLength(s));
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	suboffset = 0;
Packit 1fb8d4
Packit 1fb8d4
	while (suboffset < bandsByteCount)
Packit 1fb8d4
	{
Packit 1fb8d4
		BYTE r, g, b;
Packit 1fb8d4
		UINT16 xStart;
Packit 1fb8d4
		UINT16 xEnd;
Packit 1fb8d4
		UINT16 yStart;
Packit 1fb8d4
		UINT16 yEnd;
Packit 1fb8d4
		UINT32 colorBkg;
Packit 1fb8d4
		UINT16 vBarHeader;
Packit 1fb8d4
		UINT16 vBarYOn;
Packit 1fb8d4
		UINT16 vBarYOff;
Packit 1fb8d4
		UINT32 vBarCount;
Packit 1fb8d4
		UINT32 vBarPixelCount;
Packit 1fb8d4
		UINT32 vBarShortPixelCount;
Packit 1fb8d4
Packit 1fb8d4
		if (Stream_GetRemainingLength(s) < 11)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "stream short %"PRIuz" [11 expected]", Stream_GetRemainingLength(s));
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		Stream_Read_UINT16(s, xStart);
Packit 1fb8d4
		Stream_Read_UINT16(s, xEnd);
Packit 1fb8d4
		Stream_Read_UINT16(s, yStart);
Packit 1fb8d4
		Stream_Read_UINT16(s, yEnd);
Packit 1fb8d4
		Stream_Read_UINT8(s, b);
Packit 1fb8d4
		Stream_Read_UINT8(s, g);
Packit 1fb8d4
		Stream_Read_UINT8(s, r);
Packit 1fb8d4
		suboffset += 11;
Packit 1fb8d4
		colorBkg = FreeRDPGetColor(clear->format, r, g, b, 0xFF);
Packit 1fb8d4
Packit 1fb8d4
		if (xEnd < xStart)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "xEnd %"PRIu16" < xStart %"PRIu16"", xEnd, xStart);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (yEnd < yStart)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "yEnd %"PRIu16" < yStart %"PRIu16"", yEnd, yStart);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		vBarCount = (xEnd - xStart) + 1;
Packit 1fb8d4
Packit 1fb8d4
		for (i = 0; i < vBarCount; i++)
Packit 1fb8d4
		{
Packit 1fb8d4
			UINT32 vBarHeight;
Packit 1fb8d4
			CLEAR_VBAR_ENTRY* vBarEntry = NULL;
Packit 1fb8d4
			CLEAR_VBAR_ENTRY* vBarShortEntry;
Packit 1fb8d4
			BOOL vBarUpdate = FALSE;
Packit 1fb8d4
			const BYTE* pSrcPixel;
Packit 1fb8d4
Packit 1fb8d4
			if (Stream_GetRemainingLength(s) < 2)
Packit 1fb8d4
			{
Packit 1fb8d4
				WLog_ERR(TAG, "stream short %"PRIuz" [2 expected]", Stream_GetRemainingLength(s));
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			Stream_Read_UINT16(s, vBarHeader);
Packit 1fb8d4
			suboffset += 2;
Packit 1fb8d4
			vBarHeight = (yEnd - yStart + 1);
Packit 1fb8d4
Packit 1fb8d4
			if (vBarHeight > 52)
Packit 1fb8d4
			{
Packit 1fb8d4
				WLog_ERR(TAG, "vBarHeight (%"PRIu32") > 52", vBarHeight);
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			if ((vBarHeader & 0xC000) == 0x4000) /* SHORT_VBAR_CACHE_HIT */
Packit 1fb8d4
			{
Packit 1fb8d4
				const UINT16 vBarIndex = (vBarHeader & 0x3FFF);
Packit 1fb8d4
				vBarShortEntry = &(clear->ShortVBarStorage[vBarIndex]);
Packit 1fb8d4
Packit 1fb8d4
				if (!vBarShortEntry)
Packit 1fb8d4
				{
Packit 1fb8d4
					WLog_ERR(TAG, "missing vBarShortEntry %"PRIu16"", vBarIndex);
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				if (Stream_GetRemainingLength(s) < 1)
Packit 1fb8d4
				{
Packit 1fb8d4
					WLog_ERR(TAG, "stream short %"PRIuz" [1 expected]", Stream_GetRemainingLength(s));
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				Stream_Read_UINT8(s, vBarYOn);
Packit 1fb8d4
				suboffset += 1;
Packit 1fb8d4
				vBarShortPixelCount = vBarShortEntry->count;
Packit 1fb8d4
				vBarUpdate = TRUE;
Packit 1fb8d4
			}
Packit 1fb8d4
			else if ((vBarHeader & 0xC000) == 0x0000) /* SHORT_VBAR_CACHE_MISS */
Packit 1fb8d4
			{
Packit 1fb8d4
				vBarYOn = (vBarHeader & 0xFF);
Packit 1fb8d4
				vBarYOff = ((vBarHeader >> 8) & 0x3F);
Packit 1fb8d4
Packit 1fb8d4
				if (vBarYOff < vBarYOn)
Packit 1fb8d4
				{
Packit 1fb8d4
					WLog_ERR(TAG, "vBarYOff %"PRIu16" < vBarYOn %"PRIu16"", vBarYOff, vBarYOn);
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				vBarShortPixelCount = (vBarYOff - vBarYOn);
Packit 1fb8d4
Packit 1fb8d4
				if (vBarShortPixelCount > 52)
Packit 1fb8d4
				{
Packit 1fb8d4
					WLog_ERR(TAG, "vBarShortPixelCount %"PRIu32" > 52", vBarShortPixelCount);
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				if (Stream_GetRemainingLength(s) < (vBarShortPixelCount * 3))
Packit 1fb8d4
				{
Packit 1fb8d4
					WLog_ERR(TAG, "stream short %"PRIuz" [%"PRIu32" expected]", Stream_GetRemainingLength(s),
Packit 1fb8d4
					         (vBarShortPixelCount * 3));
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				if (clear->ShortVBarStorageCursor >= CLEARCODEC_VBAR_SHORT_SIZE)
Packit 1fb8d4
				{
Packit 1fb8d4
					WLog_ERR(TAG,
Packit 1fb8d4
					         "clear->ShortVBarStorageCursor %"PRIu32" >= CLEARCODEC_VBAR_SHORT_SIZE (%"PRIu32")",
Packit 1fb8d4
					         clear->ShortVBarStorageCursor, CLEARCODEC_VBAR_SHORT_SIZE);
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				vBarShortEntry = &(clear->ShortVBarStorage[clear->ShortVBarStorageCursor]);
Packit 1fb8d4
				vBarShortEntry->count = vBarShortPixelCount;
Packit 1fb8d4
Packit 1fb8d4
				if (!resize_vbar_entry(clear, vBarShortEntry))
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
Packit 1fb8d4
				for (y = 0; y < vBarShortPixelCount; y++)
Packit 1fb8d4
				{
Packit 1fb8d4
					BYTE r, g, b;
Packit 1fb8d4
					BYTE* dstBuffer =
Packit 1fb8d4
					    &vBarShortEntry->pixels[y * GetBytesPerPixel(clear->format)];
Packit 1fb8d4
					UINT32 color;
Packit 1fb8d4
					Stream_Read_UINT8(s, b);
Packit 1fb8d4
					Stream_Read_UINT8(s, g);
Packit 1fb8d4
					Stream_Read_UINT8(s, r);
Packit 1fb8d4
					color = FreeRDPGetColor(clear->format, r, g, b, 0xFF);
Packit 1fb8d4
Packit 1fb8d4
					if (!WriteColor(dstBuffer, clear->format, color))
Packit 1fb8d4
						return FALSE;
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				suboffset += (vBarShortPixelCount * 3);
Packit 1fb8d4
				clear->ShortVBarStorageCursor =
Packit 1fb8d4
				    (clear->ShortVBarStorageCursor + 1) % CLEARCODEC_VBAR_SHORT_SIZE;
Packit 1fb8d4
				vBarUpdate = TRUE;
Packit 1fb8d4
			}
Packit 1fb8d4
			else if ((vBarHeader & 0x8000) == 0x8000) /* VBAR_CACHE_HIT */
Packit 1fb8d4
			{
Packit 1fb8d4
				const UINT16 vBarIndex = (vBarHeader & 0x7FFF);
Packit 1fb8d4
				vBarEntry = &(clear->VBarStorage[vBarIndex]);
Packit 1fb8d4
Packit 1fb8d4
				/* If the cache was reset we need to fill in some dummy data. */
Packit 1fb8d4
				if (vBarEntry->size == 0)
Packit 1fb8d4
				{
Packit 1fb8d4
					WLog_WARN(TAG, "Empty cache index %"PRIu16", filling dummy data", vBarIndex);
Packit 1fb8d4
					vBarEntry->count = vBarHeight;
Packit 1fb8d4
Packit 1fb8d4
					if (!resize_vbar_entry(clear, vBarEntry))
Packit 1fb8d4
						return FALSE;
Packit 1fb8d4
				}
Packit 1fb8d4
			}
Packit 1fb8d4
			else
Packit 1fb8d4
			{
Packit 1fb8d4
				WLog_ERR(TAG, "invalid vBarHeader 0x%04"PRIX16"", vBarHeader);
Packit 1fb8d4
				return FALSE; /* invalid vBarHeader */
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			if (vBarUpdate)
Packit 1fb8d4
			{
Packit 1fb8d4
				UINT32 x;
Packit 1fb8d4
				BYTE* pSrcPixel;
Packit 1fb8d4
				BYTE* dstBuffer;
Packit 1fb8d4
Packit 1fb8d4
				if (clear->VBarStorageCursor >= CLEARCODEC_VBAR_SIZE)
Packit 1fb8d4
				{
Packit 1fb8d4
					WLog_ERR(TAG, "clear->VBarStorageCursor %"PRIu32" >= CLEARCODEC_VBAR_SIZE %"PRIu32"",
Packit 1fb8d4
					         clear->VBarStorageCursor,
Packit 1fb8d4
					         CLEARCODEC_VBAR_SIZE);
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				vBarEntry = &(clear->VBarStorage[clear->VBarStorageCursor]);
Packit 1fb8d4
				vBarPixelCount = vBarHeight;
Packit 1fb8d4
				vBarEntry->count = vBarPixelCount;
Packit 1fb8d4
Packit 1fb8d4
				if (!resize_vbar_entry(clear, vBarEntry))
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
Packit 1fb8d4
				dstBuffer = vBarEntry->pixels;
Packit 1fb8d4
				/* if (y < vBarYOn), use colorBkg */
Packit 1fb8d4
				y = 0;
Packit 1fb8d4
				count = vBarYOn;
Packit 1fb8d4
Packit 1fb8d4
				if ((y + count) > vBarPixelCount)
Packit 1fb8d4
					count = (vBarPixelCount > y) ? (vBarPixelCount - y) : 0;
Packit 1fb8d4
Packit 1fb8d4
				while (count--)
Packit 1fb8d4
				{
Packit 1fb8d4
					WriteColor(dstBuffer, clear->format, colorBkg);
Packit 1fb8d4
					dstBuffer += GetBytesPerPixel(clear->format);
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				/*
Packit 1fb8d4
				 * if ((y >= vBarYOn) && (y < (vBarYOn + vBarShortPixelCount))),
Packit 1fb8d4
				 * use vBarShortPixels at index (y - shortVBarYOn)
Packit 1fb8d4
				 */
Packit 1fb8d4
				y = vBarYOn;
Packit 1fb8d4
				count = vBarShortPixelCount;
Packit 1fb8d4
Packit 1fb8d4
				if ((y + count) > vBarPixelCount)
Packit 1fb8d4
					count = (vBarPixelCount > y) ? (vBarPixelCount - y) : 0;
Packit 1fb8d4
Packit 1fb8d4
				pSrcPixel = &vBarShortEntry->pixels[(y - vBarYOn) * GetBytesPerPixel(
Packit 1fb8d4
				                                                      clear->format)];
Packit 1fb8d4
Packit 1fb8d4
				for (x = 0; x < count; x++)
Packit 1fb8d4
				{
Packit 1fb8d4
					UINT32 color;
Packit 1fb8d4
					color =	ReadColor(&pSrcPixel[x * GetBytesPerPixel(clear->format)],
Packit 1fb8d4
					                  clear->format);
Packit 1fb8d4
Packit 1fb8d4
					if (!WriteColor(dstBuffer, clear->format, color))
Packit 1fb8d4
						return FALSE;
Packit 1fb8d4
Packit 1fb8d4
					dstBuffer += GetBytesPerPixel(clear->format);
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				/* if (y >= (vBarYOn + vBarShortPixelCount)), use colorBkg */
Packit 1fb8d4
				y = vBarYOn + vBarShortPixelCount;
Packit 1fb8d4
				count = (vBarPixelCount > y) ? (vBarPixelCount - y) : 0;
Packit 1fb8d4
Packit 1fb8d4
				while (count--)
Packit 1fb8d4
				{
Packit 1fb8d4
					if (!WriteColor(dstBuffer, clear->format, colorBkg))
Packit 1fb8d4
						return FALSE;
Packit 1fb8d4
Packit 1fb8d4
					dstBuffer += GetBytesPerPixel(clear->format);
Packit 1fb8d4
				}
Packit 1fb8d4
Packit 1fb8d4
				vBarEntry->count = vBarPixelCount;
Packit 1fb8d4
				clear->VBarStorageCursor = (clear->VBarStorageCursor + 1) %
Packit 1fb8d4
				                           CLEARCODEC_VBAR_SIZE;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			if (vBarEntry->count != vBarHeight)
Packit 1fb8d4
			{
Packit 1fb8d4
				WLog_ERR(TAG, "vBarEntry->count %"PRIu32" != vBarHeight %"PRIu32"", vBarEntry->count,
Packit 1fb8d4
				         vBarHeight);
Packit 1fb8d4
				vBarEntry->count = vBarHeight;
Packit 1fb8d4
Packit 1fb8d4
				if (!resize_vbar_entry(clear, vBarEntry))
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			nXDstRel = nXDst + xStart;
Packit 1fb8d4
			nYDstRel = nYDst + yStart;
Packit 1fb8d4
			pSrcPixel = vBarEntry->pixels;
Packit 1fb8d4
Packit 1fb8d4
			if (i < nWidth)
Packit 1fb8d4
			{
Packit 1fb8d4
				count = vBarEntry->count;
Packit 1fb8d4
Packit 1fb8d4
				if (count > nHeight)
Packit 1fb8d4
					count = nHeight;
Packit 1fb8d4
Packit 1fb8d4
				for (y = 0; y < count; y++)
Packit 1fb8d4
				{
Packit 1fb8d4
					BYTE* pDstPixel8 = &pDstData[((nYDstRel + y) * nDstStep) +
Packit 1fb8d4
					                                             ((nXDstRel + i) * GetBytesPerPixel(DstFormat))];
Packit 1fb8d4
					UINT32 color = ReadColor(pSrcPixel, clear->format);
Packit 1fb8d4
					color = FreeRDPConvertColor(color, clear->format,
Packit 1fb8d4
					                            DstFormat, NULL);
Packit 1fb8d4
Packit 1fb8d4
					if (!WriteColor(pDstPixel8, DstFormat, color))
Packit 1fb8d4
						return FALSE;
Packit 1fb8d4
Packit 1fb8d4
					pSrcPixel += GetBytesPerPixel(clear->format);
Packit 1fb8d4
				}
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL clear_decompress_glyph_data(CLEAR_CONTEXT* clear,
Packit 1fb8d4
                                        wStream* s, UINT32 glyphFlags,
Packit 1fb8d4
                                        UINT32 nWidth, UINT32 nHeight,
Packit 1fb8d4
                                        BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
Packit 1fb8d4
                                        UINT32 nXDst, UINT32 nYDst,
Packit 1fb8d4
                                        UINT32 nDstWidth, UINT32 nDstHeight,
Packit 1fb8d4
                                        const gdiPalette* palette, BYTE** ppGlyphData)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT16 glyphIndex = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (ppGlyphData)
Packit 1fb8d4
		*ppGlyphData = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if ((glyphFlags & CLEARCODEC_FLAG_GLYPH_HIT) &&
Packit 1fb8d4
	    !(glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX))
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "Invalid glyph flags %08"PRIX32"", glyphFlags);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if ((glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX) == 0)
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if ((nWidth * nHeight) > (1024 * 1024))
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "glyph too large: %"PRIu32"x%"PRIu32"", nWidth, nHeight);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 2)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "stream short %"PRIuz" [2 expected]", Stream_GetRemainingLength(s));
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read_UINT16(s, glyphIndex);
Packit 1fb8d4
Packit 1fb8d4
	if (glyphIndex >= 4000)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "Invalid glyphIndex %"PRIu16"", glyphIndex);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (glyphFlags & CLEARCODEC_FLAG_GLYPH_HIT)
Packit 1fb8d4
	{
Packit 1fb8d4
		UINT32 nSrcStep;
Packit 1fb8d4
		CLEAR_GLYPH_ENTRY* glyphEntry = &(clear->GlyphCache[glyphIndex]);
Packit 1fb8d4
		BYTE* glyphData;
Packit 1fb8d4
Packit 1fb8d4
		if (!glyphEntry)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "clear->GlyphCache[%"PRIu16"]=NULL", glyphIndex);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		glyphData = (BYTE*) glyphEntry->pixels;
Packit 1fb8d4
Packit 1fb8d4
		if (!glyphData)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "clear->GlyphCache[%"PRIu16"]->pixels=NULL", glyphIndex);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if ((nWidth * nHeight) > glyphEntry->count)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "(nWidth %"PRIu32" * nHeight %"PRIu32") > glyphEntry->count %"PRIu32"", nWidth,
Packit 1fb8d4
			         nHeight,
Packit 1fb8d4
			         glyphEntry->count);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		nSrcStep = nWidth * GetBytesPerPixel(clear->format);
Packit 1fb8d4
		return convert_color(pDstData, nDstStep, DstFormat,
Packit 1fb8d4
		                     nXDst, nYDst, nWidth, nHeight,
Packit 1fb8d4
		                     glyphData, nSrcStep, clear->format,
Packit 1fb8d4
		                     nDstWidth, nDstHeight, palette);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX)
Packit 1fb8d4
	{
Packit 1fb8d4
		const UINT32 bpp = GetBytesPerPixel(clear->format);
Packit 1fb8d4
		CLEAR_GLYPH_ENTRY* glyphEntry = &(clear->GlyphCache[glyphIndex]);
Packit 1fb8d4
		glyphEntry->count = nWidth * nHeight;
Packit 1fb8d4
Packit 1fb8d4
		if (glyphEntry->count > glyphEntry->size)
Packit 1fb8d4
		{
Packit 1fb8d4
			BYTE* tmp;
Packit 1fb8d4
			tmp = realloc(glyphEntry->pixels, glyphEntry->count * bpp);
Packit 1fb8d4
Packit 1fb8d4
			if (!tmp)
Packit 1fb8d4
			{
Packit 1fb8d4
				WLog_ERR(TAG, "glyphEntry->pixels realloc %"PRIu32" failed!", glyphEntry->count * bpp);
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			glyphEntry->size = glyphEntry->count;
Packit 1fb8d4
			glyphEntry->pixels = (UINT32*)tmp;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (!glyphEntry->pixels)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "glyphEntry->pixels=NULL");
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (ppGlyphData)
Packit 1fb8d4
			*ppGlyphData = (BYTE*)glyphEntry->pixels;
Packit 1fb8d4
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static INLINE BOOL updateContextFormat(CLEAR_CONTEXT* clear, UINT32 DstFormat)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!clear || !clear->nsc)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	clear->format = DstFormat;
Packit 1fb8d4
	return nsc_context_set_pixel_format(clear->nsc, DstFormat);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
INT32 clear_decompress(CLEAR_CONTEXT* clear, const BYTE* pSrcData,
Packit 1fb8d4
                       UINT32 SrcSize, UINT32 nWidth, UINT32 nHeight,
Packit 1fb8d4
                       BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
Packit 1fb8d4
                       UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth,
Packit 1fb8d4
                       UINT32 nDstHeight, const gdiPalette* palette)
Packit 1fb8d4
{
Packit 1fb8d4
	INT32 rc = -1;
Packit 1fb8d4
	BYTE seqNumber;
Packit 1fb8d4
	BYTE glyphFlags;
Packit 1fb8d4
	UINT32 residualByteCount;
Packit 1fb8d4
	UINT32 bandsByteCount;
Packit 1fb8d4
	UINT32 subcodecByteCount;
Packit 1fb8d4
	wStream* s;
Packit 1fb8d4
	BYTE* glyphData = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (!pDstData)
Packit 1fb8d4
		return -1002;
Packit 1fb8d4
Packit 1fb8d4
	if ((nDstWidth == 0) || (nDstHeight == 0))
Packit 1fb8d4
		return -1022;
Packit 1fb8d4
Packit 1fb8d4
	if ((nWidth > 0xFFFF) || (nHeight > 0xFFFF))
Packit 1fb8d4
		return -1004;
Packit 1fb8d4
Packit 1fb8d4
	s = Stream_New((BYTE*)pSrcData, SrcSize);
Packit 1fb8d4
Packit 1fb8d4
	if (!s)
Packit 1fb8d4
		return -2005;
Packit 1fb8d4
Packit 1fb8d4
	Stream_SetLength(s, SrcSize);
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 2)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "stream short %"PRIuz" [2 expected]", Stream_GetRemainingLength(s));
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!updateContextFormat(clear, DstFormat))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read_UINT8(s, glyphFlags);
Packit 1fb8d4
	Stream_Read_UINT8(s, seqNumber);
Packit 1fb8d4
Packit 1fb8d4
	if (!clear->seqNumber && seqNumber)
Packit 1fb8d4
		clear->seqNumber = seqNumber;
Packit 1fb8d4
Packit 1fb8d4
	if (seqNumber != clear->seqNumber)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "Sequence number unexpected %"PRIu8" - %"PRIu32"",
Packit 1fb8d4
		         seqNumber, clear->seqNumber);
Packit 1fb8d4
		WLog_ERR(TAG, "seqNumber %"PRIu8" != clear->seqNumber %"PRIu32"", seqNumber, clear->seqNumber);
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	clear->seqNumber = (seqNumber + 1) % 256;
Packit 1fb8d4
Packit 1fb8d4
	if (glyphFlags & CLEARCODEC_FLAG_CACHE_RESET)
Packit 1fb8d4
	{
Packit 1fb8d4
		clear->VBarStorageCursor = 0;
Packit 1fb8d4
		clear->ShortVBarStorageCursor = 0;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!clear_decompress_glyph_data(clear, s, glyphFlags, nWidth,
Packit 1fb8d4
	                                 nHeight, pDstData, DstFormat,
Packit 1fb8d4
	                                 nDstStep, nXDst, nYDst,
Packit 1fb8d4
	                                 nDstWidth, nDstHeight, palette, &glyphData))
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "clear_decompress_glyph_data failed!");
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* Read composition payload header parameters */
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 12)
Packit 1fb8d4
	{
Packit 1fb8d4
		const UINT32 mask = (CLEARCODEC_FLAG_GLYPH_HIT | CLEARCODEC_FLAG_GLYPH_INDEX);
Packit 1fb8d4
Packit 1fb8d4
		if ((glyphFlags & mask) == mask)
Packit 1fb8d4
			goto finish;
Packit 1fb8d4
Packit 1fb8d4
		WLog_ERR(TAG, "stream short %"PRIuz" [12 expected]", Stream_GetRemainingLength(s));
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read_UINT32(s, residualByteCount);
Packit 1fb8d4
	Stream_Read_UINT32(s, bandsByteCount);
Packit 1fb8d4
	Stream_Read_UINT32(s, subcodecByteCount);
Packit 1fb8d4
Packit 1fb8d4
	if (residualByteCount > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!clear_decompress_residual_data(clear, s, residualByteCount, nWidth,
Packit 1fb8d4
		                                    nHeight, pDstData, DstFormat, nDstStep, nXDst, nYDst,
Packit 1fb8d4
		                                    nDstWidth, nDstHeight, palette))
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "clear_decompress_residual_data failed!");
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (bandsByteCount > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!clear_decompress_bands_data(clear, s, bandsByteCount, nWidth, nHeight,
Packit 1fb8d4
		                                 pDstData, DstFormat, nDstStep, nXDst, nYDst))
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "clear_decompress_bands_data failed!");
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (subcodecByteCount > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!clear_decompress_subcodecs_data(clear, s, subcodecByteCount, nWidth,
Packit 1fb8d4
		                                     nHeight, pDstData, DstFormat,
Packit 1fb8d4
		                                     nDstStep, nXDst, nYDst,
Packit 1fb8d4
		                                     nDstWidth, nDstHeight, palette))
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "clear_decompress_subcodecs_data failed!");
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (glyphData)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!freerdp_image_copy(glyphData, clear->format, 0, 0, 0, nWidth, nHeight,
Packit 1fb8d4
		                        pDstData, DstFormat, nDstStep, nXDst, nYDst, palette,
Packit 1fb8d4
		                        FREERDP_FLIP_NONE))
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
finish:
Packit 1fb8d4
	rc = 0;
Packit 1fb8d4
fail:
Packit 1fb8d4
	Stream_Free(s, FALSE);
Packit 1fb8d4
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int clear_compress(CLEAR_CONTEXT* clear, const BYTE* pSrcData, UINT32 SrcSize,
Packit 1fb8d4
                   BYTE** ppDstData, UINT32* pDstSize)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_ERR(TAG, "TODO: %s not implemented!", __FUNCTION__);
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
BOOL clear_context_reset(CLEAR_CONTEXT* clear)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!clear)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	clear->seqNumber = 0;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
CLEAR_CONTEXT* clear_context_new(BOOL Compressor)
Packit 1fb8d4
{
Packit 1fb8d4
	CLEAR_CONTEXT* clear;
Packit 1fb8d4
	clear = (CLEAR_CONTEXT*) calloc(1, sizeof(CLEAR_CONTEXT));
Packit 1fb8d4
Packit 1fb8d4
	if (!clear)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	clear->Compressor = Compressor;
Packit 1fb8d4
	clear->nsc = nsc_context_new();
Packit 1fb8d4
Packit 1fb8d4
	if (!clear->nsc)
Packit 1fb8d4
		goto error_nsc;
Packit 1fb8d4
Packit 1fb8d4
	if (!updateContextFormat(clear, PIXEL_FORMAT_BGRX32))
Packit 1fb8d4
		goto error_nsc;
Packit 1fb8d4
Packit 1fb8d4
	if (!clear_resize_buffer(clear, 512, 512))
Packit 1fb8d4
		goto error_nsc;
Packit 1fb8d4
Packit 1fb8d4
	if (!clear->TempBuffer)
Packit 1fb8d4
		goto error_nsc;
Packit 1fb8d4
Packit 1fb8d4
	if (!clear_context_reset(clear))
Packit 1fb8d4
		goto error_nsc;
Packit 1fb8d4
Packit 1fb8d4
	return clear;
Packit 1fb8d4
error_nsc:
Packit 1fb8d4
	clear_context_free(clear);
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}
Packit 1fb8d4
void clear_context_free(CLEAR_CONTEXT* clear)
Packit 1fb8d4
{
Packit 1fb8d4
	int i;
Packit 1fb8d4
Packit 1fb8d4
	if (!clear)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	nsc_context_free(clear->nsc);
Packit 1fb8d4
	free(clear->TempBuffer);
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < 4000; i++)
Packit 1fb8d4
		free(clear->GlyphCache[i].pixels);
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < 32768; i++)
Packit 1fb8d4
		free(clear->VBarStorage[i].pixels);
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < 16384; i++)
Packit 1fb8d4
		free(clear->ShortVBarStorage[i].pixels);
Packit 1fb8d4
Packit 1fb8d4
	free(clear);
Packit 1fb8d4
}