Blame libfreerdp/codec/clear.c

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