Blame libfreerdp/codec/color.c

Packit Service fa4841
/**
Packit Service fa4841
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit Service fa4841
 * Color Conversion Routines
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2010 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 <stdio.h>
Packit Service fa4841
#include <string.h>
Packit Service fa4841
#include <stdlib.h>
Packit Service fa4841
Packit Service fa4841
#include <winpr/crt.h>
Packit Service fa4841
Packit Service fa4841
#include <freerdp/log.h>
Packit Service fa4841
#include <freerdp/freerdp.h>
Packit Service fa4841
#include <freerdp/primitives.h>
Packit Service fa4841
Packit Service b1ea74
#if defined(CAIRO_FOUND)
Packit Service b1ea74
#include <cairo.h>
Packit Service b1ea74
#endif
Packit Service b1ea74
Packit Service b1ea74
#if defined(SWSCALE_FOUND)
Packit Service b1ea74
#include <libswscale/swscale.h>
Packit Service b1ea74
#endif
Packit Service b1ea74
Packit Service fa4841
#define TAG FREERDP_TAG("color")
Packit Service fa4841
Packit Service fa4841
BYTE* freerdp_glyph_convert(UINT32 width, UINT32 height, const BYTE* data)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 x, y;
Packit Service fa4841
	const BYTE* srcp;
Packit Service fa4841
	BYTE* dstp;
Packit Service fa4841
	BYTE* dstData;
Packit Service fa4841
	UINT32 scanline;
Packit Service fa4841
	/*
Packit Service fa4841
	 * converts a 1-bit-per-pixel glyph to a one-byte-per-pixel glyph:
Packit Service fa4841
	 * this approach uses a little more memory, but provides faster
Packit Service fa4841
	 * means of accessing individual pixels in blitting operations
Packit Service fa4841
	 */
Packit Service fa4841
	scanline = (width + 7) / 8;
Packit Service b1ea74
	dstData = (BYTE*)_aligned_malloc(width * height, 16);
Packit Service fa4841
Packit Service fa4841
	if (!dstData)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	ZeroMemory(dstData, width * height);
Packit Service fa4841
	dstp = dstData;
Packit Service fa4841
Packit Service fa4841
	for (y = 0; y < height; y++)
Packit Service fa4841
	{
Packit Service fa4841
		srcp = data + (y * scanline);
Packit Service fa4841
Packit Service fa4841
		for (x = 0; x < width; x++)
Packit Service fa4841
		{
Packit Service fa4841
			if ((*srcp & (0x80 >> (x % 8))) != 0)
Packit Service fa4841
				*dstp = 0xFF;
Packit Service fa4841
Packit Service fa4841
			dstp++;
Packit Service fa4841
Packit Service fa4841
			if (((x + 1) % 8 == 0) && x != 0)
Packit Service fa4841
				srcp++;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return dstData;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
BOOL freerdp_image_copy_from_monochrome(BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
Packit Service b1ea74
                                        UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
Packit Service b1ea74
                                        const BYTE* pSrcData, UINT32 backColor, UINT32 foreColor,
Packit Service fa4841
                                        const gdiPalette* palette)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 x, y;
Packit Service fa4841
	BOOL vFlip;
Packit Service fa4841
	UINT32 monoStep;
Packit Service fa4841
	const UINT32 dstBytesPerPixel = GetBytesPerPixel(DstFormat);
Packit Service fa4841
Packit Service fa4841
	if (!pDstData || !pSrcData || !palette)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (nDstStep == 0)
Packit Service fa4841
		nDstStep = dstBytesPerPixel * nWidth;
Packit Service fa4841
Packit Service fa4841
	vFlip = FALSE;
Packit Service fa4841
	monoStep = (nWidth + 7) / 8;
Packit Service fa4841
Packit Service fa4841
	for (y = 0; y < nHeight; y++)
Packit Service fa4841
	{
Packit Service fa4841
		const BYTE* monoBits;
Packit Service fa4841
		BYTE* pDstLine = &pDstData[((nYDst + y) * nDstStep)];
Packit Service fa4841
		UINT32 monoBit = 0x80;
Packit Service fa4841
Packit Service fa4841
		if (!vFlip)
Packit Service fa4841
			monoBits = &pSrcData[monoStep * y];
Packit Service fa4841
		else
Packit Service fa4841
			monoBits = &pSrcData[monoStep * (nHeight - y - 1)];
Packit Service fa4841
Packit Service fa4841
		for (x = 0; x < nWidth; x++)
Packit Service fa4841
		{
Packit Service fa4841
			BYTE* pDstPixel = &pDstLine[((nXDst + x) * GetBytesPerPixel(DstFormat))];
Packit Service fa4841
			BOOL monoPixel = (*monoBits & monoBit) ? TRUE : FALSE;
Packit Service fa4841
Packit Service fa4841
			if (!(monoBit >>= 1))
Packit Service fa4841
			{
Packit Service fa4841
				monoBits++;
Packit Service fa4841
				monoBit = 0x80;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			if (monoPixel)
Packit Service fa4841
				WriteColor(pDstPixel, DstFormat, backColor);
Packit Service fa4841
			else
Packit Service fa4841
				WriteColor(pDstPixel, DstFormat, foreColor);
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static INLINE UINT32 freerdp_image_inverted_pointer_color(UINT32 x, UINT32 y, UINT32 format)
Packit Service fa4841
{
Packit Service fa4841
#if 1
Packit Service fa4841
	/**
Packit Service fa4841
	 * Inverted pointer colors (where individual pixels can change their
Packit Service fa4841
	 * color to accommodate the background behind them) only seem to be
Packit Service fa4841
	 * supported on Windows.
Packit Service fa4841
	 * Using a static replacement color for these pixels (e.g. black)
Packit Service fa4841
	 * might result in invisible pointers depending on the background.
Packit Service fa4841
	 * This function returns either black or white, depending on the
Packit Service fa4841
	 * pixel's position.
Packit Service fa4841
	 */
Packit Service fa4841
	BYTE fill = (x + y) & 1 ? 0x00 : 0xFF;
Packit Service fa4841
#else
Packit Service fa4841
	BYTE fill = 0x00;
Packit Service fa4841
#endif
Packit Service fa4841
	return FreeRDPGetColor(format, fill, fill, fill, 0xFF);
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
/*
Packit Service b1ea74
 * DIB color palettes are arrays of RGBQUAD structs with colors in BGRX format.
Packit Service b1ea74
 * They are used only by 1, 2, 4, and 8-bit bitmaps.
Packit Service fa4841
 */
Packit Service b1ea74
static void fill_gdi_palette_for_icon(const BYTE* colorTable, UINT16 cbColorTable,
Packit Service b1ea74
                                      gdiPalette* palette)
Packit Service b1ea74
{
Packit Service b1ea74
	UINT16 i;
Packit Service b1ea74
	palette->format = PIXEL_FORMAT_BGRX32;
Packit Service b1ea74
	ZeroMemory(palette->palette, sizeof(palette->palette));
Packit Service b1ea74
Packit Service b1ea74
	if (!cbColorTable)
Packit Service b1ea74
		return;
Packit Service b1ea74
Packit Service b1ea74
	if ((cbColorTable % 4 != 0) || (cbColorTable / 4 > 256))
Packit Service b1ea74
	{
Packit Service b1ea74
		WLog_WARN(TAG, "weird palette size: %u", cbColorTable);
Packit Service b1ea74
		return;
Packit Service b1ea74
	}
Packit Service b1ea74
Packit Service b1ea74
	for (i = 0; i < cbColorTable / 4; i++)
Packit Service b1ea74
	{
Packit Service b1ea74
		palette->palette[i] = ReadColor(&colorTable[4 * i], palette->format);
Packit Service b1ea74
	}
Packit Service b1ea74
}
Packit Service b1ea74
Packit Service b1ea74
static INLINE UINT32 div_ceil(UINT32 a, UINT32 b)
Packit Service b1ea74
{
Packit Service b1ea74
	return (a + (b - 1)) / b;
Packit Service b1ea74
}
Packit Service b1ea74
Packit Service b1ea74
static INLINE UINT32 round_up(UINT32 a, UINT32 b)
Packit Service b1ea74
{
Packit Service b1ea74
	return b * div_ceil(a, b);
Packit Service b1ea74
}
Packit Service b1ea74
Packit Service b1ea74
BOOL freerdp_image_copy_from_icon_data(BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
Packit Service b1ea74
                                       UINT32 nXDst, UINT32 nYDst, UINT16 nWidth, UINT16 nHeight,
Packit Service b1ea74
                                       const BYTE* bitsColor, UINT16 cbBitsColor,
Packit Service b1ea74
                                       const BYTE* bitsMask, UINT16 cbBitsMask,
Packit Service b1ea74
                                       const BYTE* colorTable, UINT16 cbColorTable, UINT32 bpp)
Packit Service b1ea74
{
Packit Service b1ea74
	DWORD format;
Packit Service b1ea74
	gdiPalette palette;
Packit Service b1ea74
Packit Service b1ea74
	if (!pDstData || !bitsColor)
Packit Service b1ea74
		return FALSE;
Packit Service b1ea74
Packit Service b1ea74
	/*
Packit Service b1ea74
	 * Color formats used by icons are DIB bitmap formats (2-bit format
Packit Service b1ea74
	 * is not used by MS-RDPERP). Note that 16-bit is RGB555, not RGB565,
Packit Service b1ea74
	 * and that 32-bit format uses BGRA order.
Packit Service b1ea74
	 */
Packit Service b1ea74
	switch (bpp)
Packit Service b1ea74
	{
Packit Service b1ea74
		case 1:
Packit Service b1ea74
		case 4:
Packit Service b1ea74
			/*
Packit Service b1ea74
			 * These formats are not supported by freerdp_image_copy().
Packit Service b1ea74
			 * PIXEL_FORMAT_MONO and PIXEL_FORMAT_A4 are *not* correct
Packit Service b1ea74
			 * color formats for this. Please fix freerdp_image_copy()
Packit Service b1ea74
			 * if you came here to fix a broken icon of some weird app
Packit Service b1ea74
			 * that still uses 1 or 4bpp format in the 21st century.
Packit Service b1ea74
			 */
Packit Service b1ea74
			WLog_WARN(TAG, "1bpp and 4bpp icons are not supported");
Packit Service b1ea74
			return FALSE;
Packit Service b1ea74
Packit Service b1ea74
		case 8:
Packit Service b1ea74
			format = PIXEL_FORMAT_RGB8;
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case 16:
Packit Service b1ea74
			format = PIXEL_FORMAT_RGB15;
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case 24:
Packit Service b1ea74
			format = PIXEL_FORMAT_RGB24;
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case 32:
Packit Service b1ea74
			format = PIXEL_FORMAT_BGRA32;
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		default:
Packit Service b1ea74
			WLog_WARN(TAG, "invalid icon bpp: %d", bpp);
Packit Service b1ea74
			return FALSE;
Packit Service b1ea74
	}
Packit Service b1ea74
Packit Service b1ea74
	fill_gdi_palette_for_icon(colorTable, cbColorTable, &palette);
Packit Service b1ea74
	if (!freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, bitsColor,
Packit Service b1ea74
	                        format, 0, 0, 0, &palette, FREERDP_FLIP_VERTICAL))
Packit Service b1ea74
		return FALSE;
Packit Service b1ea74
Packit Service b1ea74
	/* apply alpha mask */
Packit Service b1ea74
	if (ColorHasAlpha(DstFormat) && cbBitsMask)
Packit Service b1ea74
	{
Packit Service b1ea74
		BYTE nextBit;
Packit Service b1ea74
		const BYTE* maskByte;
Packit Service b1ea74
		UINT32 x, y;
Packit Service b1ea74
		UINT32 stride;
Packit Service b1ea74
		BYTE r, g, b;
Packit Service b1ea74
		BYTE* dstBuf = pDstData;
Packit Service b1ea74
		UINT32 dstBpp = GetBytesPerPixel(DstFormat);
Packit Service b1ea74
Packit Service b1ea74
		/*
Packit Service b1ea74
		 * Each byte encodes 8 adjacent pixels (with LSB padding as needed).
Packit Service b1ea74
		 * And due to hysterical raisins, stride of DIB bitmaps must be
Packit Service b1ea74
		 * a multiple of 4 bytes.
Packit Service b1ea74
		 */
Packit Service b1ea74
		stride = round_up(div_ceil(nWidth, 8), 4);
Packit Service b1ea74
Packit Service b1ea74
		for (y = 0; y < nHeight; y++)
Packit Service b1ea74
		{
Packit Service b1ea74
			maskByte = &bitsMask[stride * (nHeight - 1 - y)];
Packit Service b1ea74
			nextBit = 0x80;
Packit Service b1ea74
Packit Service b1ea74
			for (x = 0; x < nWidth; x++)
Packit Service b1ea74
			{
Packit Service b1ea74
				UINT32 color;
Packit Service b1ea74
				BYTE alpha = (*maskByte & nextBit) ? 0x00 : 0xFF;
Packit Service b1ea74
Packit Service b1ea74
				/* read color back, add alpha and write it back */
Packit Service b1ea74
				color = ReadColor(dstBuf, DstFormat);
Packit Service b1ea74
				SplitColor(color, DstFormat, &r, &g, &b, NULL, &palette);
Packit Service b1ea74
				color = FreeRDPGetColor(DstFormat, r, g, b, alpha);
Packit Service b1ea74
				WriteColor(dstBuf, DstFormat, color);
Packit Service b1ea74
Packit Service b1ea74
				nextBit >>= 1;
Packit Service b1ea74
				dstBuf += dstBpp;
Packit Service b1ea74
				if (!nextBit)
Packit Service b1ea74
				{
Packit Service b1ea74
					nextBit = 0x80;
Packit Service b1ea74
					maskByte++;
Packit Service b1ea74
				}
Packit Service b1ea74
			}
Packit Service b1ea74
		}
Packit Service b1ea74
	}
Packit Service b1ea74
Packit Service b1ea74
	return TRUE;
Packit Service b1ea74
}
Packit Service fa4841
Packit Service b1ea74
static BOOL freerdp_image_copy_from_pointer_data_1bpp(BYTE* pDstData, UINT32 DstFormat,
Packit Service b1ea74
                                                      UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
Packit Service b1ea74
                                                      UINT32 nWidth, UINT32 nHeight,
Packit Service b1ea74
                                                      const BYTE* xorMask, UINT32 xorMaskLength,
Packit Service b1ea74
                                                      const BYTE* andMask, UINT32 andMaskLength,
Packit Service b1ea74
                                                      UINT32 xorBpp)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 x, y;
Packit Service fa4841
	BOOL vFlip;
Packit Service fa4841
	UINT32 xorStep;
Packit Service fa4841
	UINT32 andStep;
Packit Service fa4841
	UINT32 xorBit;
Packit Service fa4841
	UINT32 andBit;
Packit Service fa4841
	UINT32 xorPixel;
Packit Service fa4841
	UINT32 andPixel;
Packit Service fa4841
	UINT32 dstBitsPerPixel;
Packit Service fa4841
	UINT32 dstBytesPerPixel;
Packit Service fa4841
	dstBitsPerPixel = GetBitsPerPixel(DstFormat);
Packit Service fa4841
	dstBytesPerPixel = GetBytesPerPixel(DstFormat);
Packit Service fa4841
Packit Service fa4841
	vFlip = (xorBpp == 1) ? FALSE : TRUE;
Packit Service fa4841
	andStep = (nWidth + 7) / 8;
Packit Service fa4841
	andStep += (andStep % 2);
Packit Service fa4841
Packit Service fa4841
	if (!xorMask || (xorMaskLength == 0))
Packit Service fa4841
		return FALSE;
Packit Service b1ea74
	if (!andMask || (andMaskLength == 0))
Packit Service b1ea74
		return FALSE;
Packit Service fa4841
Packit Service b1ea74
	xorStep = (nWidth + 7) / 8;
Packit Service b1ea74
	xorStep += (xorStep % 2);
Packit Service b1ea74
Packit Service b1ea74
	if (xorStep * nHeight > xorMaskLength)
Packit Service b1ea74
		return FALSE;
Packit Service b1ea74
Packit Service b1ea74
	if (andStep * nHeight > andMaskLength)
Packit Service b1ea74
		return FALSE;
Packit Service b1ea74
Packit Service b1ea74
	for (y = 0; y < nHeight; y++)
Packit Service fa4841
	{
Packit Service b1ea74
		const BYTE* andBits;
Packit Service b1ea74
		const BYTE* xorBits;
Packit Service b1ea74
		BYTE* pDstPixel =
Packit Service b1ea74
		    &pDstData[((nYDst + y) * nDstStep) + (nXDst * GetBytesPerPixel(DstFormat))];
Packit Service b1ea74
		xorBit = andBit = 0x80;
Packit Service fa4841
Packit Service b1ea74
		if (!vFlip)
Packit Service b1ea74
		{
Packit Service b1ea74
			xorBits = &xorMask[xorStep * y];
Packit Service b1ea74
			andBits = &andMask[andStep * y];
Packit Service b1ea74
		}
Packit Service b1ea74
		else
Packit Service b1ea74
		{
Packit Service b1ea74
			xorBits = &xorMask[xorStep * (nHeight - y - 1)];
Packit Service b1ea74
			andBits = &andMask[andStep * (nHeight - y - 1)];
Packit Service b1ea74
		}
Packit Service fa4841
Packit Service b1ea74
		for (x = 0; x < nWidth; x++)
Packit Service b1ea74
		{
Packit Service b1ea74
			UINT32 color = 0;
Packit Service b1ea74
			xorPixel = (*xorBits & xorBit) ? 1 : 0;
Packit Service fa4841
Packit Service b1ea74
			if (!(xorBit >>= 1))
Packit Service b1ea74
			{
Packit Service b1ea74
				xorBits++;
Packit Service b1ea74
				xorBit = 0x80;
Packit Service b1ea74
			}
Packit Service fa4841
Packit Service b1ea74
			andPixel = (*andBits & andBit) ? 1 : 0;
Packit Service b1ea74
Packit Service b1ea74
			if (!(andBit >>= 1))
Packit Service fa4841
			{
Packit Service b1ea74
				andBits++;
Packit Service b1ea74
				andBit = 0x80;
Packit Service b1ea74
			}
Packit Service fa4841
Packit Service b1ea74
			if (!andPixel && !xorPixel)
Packit Service b1ea74
				color = FreeRDPGetColor(DstFormat, 0, 0, 0, 0xFF); /* black */
Packit Service b1ea74
			else if (!andPixel && xorPixel)
Packit Service b1ea74
				color = FreeRDPGetColor(DstFormat, 0xFF, 0xFF, 0xFF, 0xFF); /* white */
Packit Service b1ea74
			else if (andPixel && !xorPixel)
Packit Service b1ea74
				color = FreeRDPGetColor(DstFormat, 0, 0, 0, 0); /* transparent */
Packit Service b1ea74
			else if (andPixel && xorPixel)
Packit Service b1ea74
				color = freerdp_image_inverted_pointer_color(x, y, DstFormat); /* inverted */
Packit Service b1ea74
Packit Service b1ea74
			WriteColor(pDstPixel, DstFormat, color);
Packit Service b1ea74
			pDstPixel += GetBytesPerPixel(DstFormat);
Packit Service b1ea74
		}
Packit Service b1ea74
	}
Packit Service fa4841
Packit Service b1ea74
	return TRUE;
Packit Service b1ea74
}
Packit Service b1ea74
Packit Service b1ea74
static BOOL freerdp_image_copy_from_pointer_data_xbpp(BYTE* pDstData, UINT32 DstFormat,
Packit Service b1ea74
                                                      UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
Packit Service b1ea74
                                                      UINT32 nWidth, UINT32 nHeight,
Packit Service b1ea74
                                                      const BYTE* xorMask, UINT32 xorMaskLength,
Packit Service b1ea74
                                                      const BYTE* andMask, UINT32 andMaskLength,
Packit Service b1ea74
                                                      UINT32 xorBpp, const gdiPalette* palette)
Packit Service b1ea74
{
Packit Service b1ea74
	UINT32 x, y;
Packit Service b1ea74
	BOOL vFlip;
Packit Service b1ea74
	UINT32 xorStep;
Packit Service b1ea74
	UINT32 andStep;
Packit Service b1ea74
	UINT32 andBit;
Packit Service b1ea74
	UINT32 xorPixel;
Packit Service b1ea74
	UINT32 andPixel;
Packit Service b1ea74
	UINT32 dstBitsPerPixel;
Packit Service b1ea74
	UINT32 dstBytesPerPixel;
Packit Service b1ea74
	UINT32 xorBytesPerPixel;
Packit Service b1ea74
	dstBitsPerPixel = GetBitsPerPixel(DstFormat);
Packit Service b1ea74
	dstBytesPerPixel = GetBytesPerPixel(DstFormat);
Packit Service b1ea74
Packit Service b1ea74
	vFlip = (xorBpp == 1) ? FALSE : TRUE;
Packit Service b1ea74
	andStep = (nWidth + 7) / 8;
Packit Service b1ea74
	andStep += (andStep % 2);
Packit Service b1ea74
Packit Service b1ea74
	if (!xorMask || (xorMaskLength == 0))
Packit Service b1ea74
		return FALSE;
Packit Service b1ea74
Packit Service b1ea74
	xorBytesPerPixel = xorBpp >> 3;
Packit Service b1ea74
	xorStep = nWidth * xorBytesPerPixel;
Packit Service b1ea74
	xorStep += (xorStep % 2);
Packit Service b1ea74
Packit Service b1ea74
	if (xorBpp == 8 && !palette)
Packit Service b1ea74
	{
Packit Service b1ea74
		WLog_ERR(TAG, "null palette in conversion from %" PRIu32 " bpp to %" PRIu32 " bpp", xorBpp,
Packit Service b1ea74
		         dstBitsPerPixel);
Packit Service b1ea74
		return FALSE;
Packit Service b1ea74
	}
Packit Service b1ea74
Packit Service b1ea74
	if (xorStep * nHeight > xorMaskLength)
Packit Service b1ea74
		return FALSE;
Packit Service b1ea74
Packit Service b1ea74
	if (andMask)
Packit Service b1ea74
	{
Packit Service b1ea74
		if (andStep * nHeight > andMaskLength)
Packit Service b1ea74
			return FALSE;
Packit Service b1ea74
	}
Packit Service b1ea74
Packit Service b1ea74
	for (y = 0; y < nHeight; y++)
Packit Service b1ea74
	{
Packit Service b1ea74
		const BYTE* xorBits;
Packit Service b1ea74
		const BYTE* andBits = NULL;
Packit Service b1ea74
		BYTE* pDstPixel =
Packit Service b1ea74
		    &pDstData[((nYDst + y) * nDstStep) + (nXDst * GetBytesPerPixel(DstFormat))];
Packit Service b1ea74
		andBit = 0x80;
Packit Service b1ea74
Packit Service b1ea74
		if (!vFlip)
Packit Service b1ea74
		{
Packit Service b1ea74
			if (andMask)
Packit Service b1ea74
				andBits = &andMask[andStep * y];
Packit Service b1ea74
Packit Service b1ea74
			xorBits = &xorMask[xorStep * y];
Packit Service b1ea74
		}
Packit Service b1ea74
		else
Packit Service b1ea74
		{
Packit Service b1ea74
			if (andMask)
Packit Service b1ea74
				andBits = &andMask[andStep * (nHeight - y - 1)];
Packit Service b1ea74
Packit Service b1ea74
			xorBits = &xorMask[xorStep * (nHeight - y - 1)];
Packit Service b1ea74
		}
Packit Service b1ea74
Packit Service b1ea74
		for (x = 0; x < nWidth; x++)
Packit Service b1ea74
		{
Packit Service b1ea74
			UINT32 pixelFormat;
Packit Service b1ea74
			UINT32 color;
Packit Service b1ea74
Packit Service b1ea74
			if (xorBpp == 32)
Packit Service b1ea74
			{
Packit Service b1ea74
				pixelFormat = PIXEL_FORMAT_BGRA32;
Packit Service b1ea74
				xorPixel = ReadColor(xorBits, pixelFormat);
Packit Service b1ea74
			}
Packit Service b1ea74
			else if (xorBpp == 16)
Packit Service b1ea74
			{
Packit Service b1ea74
				pixelFormat = PIXEL_FORMAT_RGB15;
Packit Service b1ea74
				xorPixel = ReadColor(xorBits, pixelFormat);
Packit Service b1ea74
			}
Packit Service b1ea74
			else if (xorBpp == 8)
Packit Service b1ea74
			{
Packit Service b1ea74
				pixelFormat = palette->format;
Packit Service b1ea74
				xorPixel = palette->palette[xorBits[0]];
Packit Service b1ea74
			}
Packit Service b1ea74
			else
Packit Service b1ea74
			{
Packit Service b1ea74
				pixelFormat = PIXEL_FORMAT_BGR24;
Packit Service b1ea74
				xorPixel = ReadColor(xorBits, pixelFormat);
Packit Service fa4841
			}
Packit Service fa4841
Packit Service b1ea74
			xorPixel = FreeRDPConvertColor(xorPixel, pixelFormat, PIXEL_FORMAT_ARGB32, palette);
Packit Service b1ea74
			xorBits += xorBytesPerPixel;
Packit Service b1ea74
			andPixel = 0;
Packit Service fa4841
Packit Service b1ea74
			if (andMask)
Packit Service bb5c11
			{
Packit Service b1ea74
				andPixel = (*andBits & andBit) ? 1 : 0;
Packit Service fa4841
Packit Service b1ea74
				if (!(andBit >>= 1))
Packit Service bb5c11
				{
Packit Service b1ea74
					andBits++;
Packit Service b1ea74
					andBit = 0x80;
Packit Service bb5c11
				}
Packit Service b1ea74
			}
Packit Service fa4841
Packit Service b1ea74
			if (andPixel)
Packit Service b1ea74
			{
Packit Service b1ea74
				if (xorPixel == 0xFF000000) /* black -> transparent */
Packit Service b1ea74
					xorPixel = 0x00000000;
Packit Service b1ea74
				else if (xorPixel == 0xFFFFFFFF) /* white -> inverted */
Packit Service b1ea74
					xorPixel = freerdp_image_inverted_pointer_color(x, y, PIXEL_FORMAT_ARGB32);
Packit Service b1ea74
			}
Packit Service fa4841
Packit Service b1ea74
			color = FreeRDPConvertColor(xorPixel, PIXEL_FORMAT_ARGB32, DstFormat, palette);
Packit Service b1ea74
			WriteColor(pDstPixel, DstFormat, color);
Packit Service b1ea74
			pDstPixel += GetBytesPerPixel(DstFormat);
Packit Service b1ea74
		}
Packit Service b1ea74
	}
Packit Service fa4841
Packit Service b1ea74
	return TRUE;
Packit Service b1ea74
}
Packit Service fa4841
Packit Service b1ea74
/**
Packit Service b1ea74
 * Drawing Monochrome Pointers:
Packit Service b1ea74
 * http://msdn.microsoft.com/en-us/library/windows/hardware/ff556143/
Packit Service b1ea74
 *
Packit Service b1ea74
 * Drawing Color Pointers:
Packit Service b1ea74
 * http://msdn.microsoft.com/en-us/library/windows/hardware/ff556138/
Packit Service b1ea74
 */
Packit Service fa4841
Packit Service b1ea74
BOOL freerdp_image_copy_from_pointer_data(BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
Packit Service b1ea74
                                          UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
Packit Service b1ea74
                                          const BYTE* xorMask, UINT32 xorMaskLength,
Packit Service b1ea74
                                          const BYTE* andMask, UINT32 andMaskLength, UINT32 xorBpp,
Packit Service b1ea74
                                          const gdiPalette* palette)
Packit Service b1ea74
{
Packit Service b1ea74
	UINT32 y;
Packit Service b1ea74
	UINT32 dstBitsPerPixel;
Packit Service b1ea74
	UINT32 dstBytesPerPixel;
Packit Service b1ea74
	dstBitsPerPixel = GetBitsPerPixel(DstFormat);
Packit Service b1ea74
	dstBytesPerPixel = GetBytesPerPixel(DstFormat);
Packit Service b1ea74
Packit Service b1ea74
	if (nDstStep <= 0)
Packit Service b1ea74
		nDstStep = dstBytesPerPixel * nWidth;
Packit Service b1ea74
Packit Service b1ea74
	for (y = nYDst; y < nHeight; y++)
Packit Service b1ea74
	{
Packit Service b1ea74
		BYTE* pDstLine = &pDstData[y * nDstStep + nXDst * dstBytesPerPixel];
Packit Service b1ea74
		memset(pDstLine, 0, dstBytesPerPixel * (nWidth - nXDst));
Packit Service b1ea74
	}
Packit Service b1ea74
Packit Service b1ea74
	switch (xorBpp)
Packit Service b1ea74
	{
Packit Service b1ea74
		case 1:
Packit Service b1ea74
			return freerdp_image_copy_from_pointer_data_1bpp(
Packit Service b1ea74
			    pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, xorMask,
Packit Service b1ea74
			    xorMaskLength, andMask, andMaskLength, xorBpp);
Packit Service b1ea74
Packit Service b1ea74
		case 8:
Packit Service b1ea74
		case 16:
Packit Service b1ea74
		case 24:
Packit Service b1ea74
		case 32:
Packit Service b1ea74
			return freerdp_image_copy_from_pointer_data_xbpp(
Packit Service b1ea74
			    pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, xorMask,
Packit Service b1ea74
			    xorMaskLength, andMask, andMaskLength, xorBpp, palette);
Packit Service fa4841
Packit Service fa4841
		default:
Packit Service b1ea74
			WLog_ERR(TAG, "failed to convert from %" PRIu32 " bpp to %" PRIu32 " bpp", xorBpp,
Packit Service b1ea74
			         dstBitsPerPixel);
Packit Service fa4841
			return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
static INLINE BOOL overlapping(const BYTE* pDstData, UINT32 nXDst, UINT32 nYDst, UINT32 nDstStep,
Packit Service b1ea74
                               UINT32 dstBytesPerPixel, const BYTE* pSrcData, UINT32 nXSrc,
Packit Service b1ea74
                               UINT32 nYSrc, UINT32 nSrcStep, UINT32 srcBytesPerPixel,
Packit Service fa4841
                               UINT32 nWidth, UINT32 nHeight)
Packit Service fa4841
{
Packit Service fa4841
	const BYTE* pDstStart = &pDstData[nXDst * dstBytesPerPixel + nYDst * nDstStep];
Packit Service fa4841
	const BYTE* pDstEnd = pDstStart + nHeight * nDstStep;
Packit Service fa4841
	const BYTE* pSrcStart = &pSrcData[nXSrc * srcBytesPerPixel + nYSrc * nSrcStep];
Packit Service fa4841
	const BYTE* pSrcEnd = pSrcStart + nHeight * nSrcStep;
Packit Service fa4841
Packit Service fa4841
	if ((pDstStart >= pSrcStart) && (pDstStart <= pSrcEnd))
Packit Service fa4841
		return TRUE;
Packit Service fa4841
Packit Service fa4841
	if ((pDstEnd >= pSrcStart) && (pDstEnd <= pSrcEnd))
Packit Service fa4841
		return TRUE;
Packit Service fa4841
Packit Service fa4841
	return FALSE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst,
Packit Service b1ea74
                        UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, const BYTE* pSrcData,
Packit Service b1ea74
                        DWORD SrcFormat, UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
Packit Service fa4841
                        const gdiPalette* palette, UINT32 flags)
Packit Service fa4841
{
Packit Service fa4841
	const UINT32 dstByte = GetBytesPerPixel(DstFormat);
Packit Service fa4841
	const UINT32 srcByte = GetBytesPerPixel(SrcFormat);
Packit Service fa4841
	const UINT32 copyDstWidth = nWidth * dstByte;
Packit Service fa4841
	const UINT32 xSrcOffset = nXSrc * srcByte;
Packit Service fa4841
	const UINT32 xDstOffset = nXDst * dstByte;
Packit Service fa4841
	const BOOL vSrcVFlip = flags & FREERDP_FLIP_VERTICAL;
Packit Service fa4841
	UINT32 srcVOffset = 0;
Packit Service fa4841
	INT32 srcVMultiplier = 1;
Packit Service fa4841
	UINT32 dstVOffset = 0;
Packit Service fa4841
	INT32 dstVMultiplier = 1;
Packit Service fa4841
Packit Service b1ea74
	if ((nHeight > INT32_MAX) || (nWidth > INT32_MAX))
Packit Service b1ea74
		return FALSE;
Packit Service b1ea74
Packit Service fa4841
	if (!pDstData || !pSrcData)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (nDstStep == 0)
Packit Service fa4841
		nDstStep = nWidth * GetBytesPerPixel(DstFormat);
Packit Service fa4841
Packit Service fa4841
	if (nSrcStep == 0)
Packit Service fa4841
		nSrcStep = nWidth * GetBytesPerPixel(SrcFormat);
Packit Service fa4841
Packit Service fa4841
	if (vSrcVFlip)
Packit Service fa4841
	{
Packit Service fa4841
		srcVOffset = (nHeight - 1) * nSrcStep;
Packit Service fa4841
		srcVMultiplier = -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (AreColorFormatsEqualNoAlpha(SrcFormat, DstFormat))
Packit Service fa4841
	{
Packit Service fa4841
		INT32 y;
Packit Service fa4841
Packit Service b1ea74
		if (overlapping(pDstData, nXDst, nYDst, nDstStep, dstByte, pSrcData, nXSrc, nYSrc, nSrcStep,
Packit Service b1ea74
		                srcByte, nWidth, nHeight))
Packit Service fa4841
		{
Packit Service fa4841
			/* Copy down */
Packit Service fa4841
			if (nYDst < nYSrc)
Packit Service fa4841
			{
Packit Service b1ea74
				for (y = 0; y < (INT32)nHeight; y++)
Packit Service fa4841
				{
Packit Service b1ea74
					const BYTE* srcLine =
Packit Service b1ea74
					    &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset];
Packit Service b1ea74
					BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset];
Packit Service b1ea74
					memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
Packit Service fa4841
				}
Packit Service fa4841
			}
Packit Service fa4841
			/* Copy up */
Packit Service fa4841
			else if (nYDst > nYSrc)
Packit Service fa4841
			{
Packit Service fa4841
				for (y = nHeight - 1; y >= 0; y--)
Packit Service fa4841
				{
Packit Service b1ea74
					const BYTE* srcLine =
Packit Service b1ea74
					    &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset];
Packit Service b1ea74
					BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset];
Packit Service b1ea74
					memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
Packit Service fa4841
				}
Packit Service fa4841
			}
Packit Service fa4841
			/* Copy left */
Packit Service fa4841
			else if (nXSrc > nXDst)
Packit Service fa4841
			{
Packit Service b1ea74
				for (y = 0; y < (INT32)nHeight; y++)
Packit Service fa4841
				{
Packit Service b1ea74
					const BYTE* srcLine =
Packit Service b1ea74
					    &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset];
Packit Service b1ea74
					BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset];
Packit Service b1ea74
					memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
Packit Service fa4841
				}
Packit Service fa4841
			}
Packit Service fa4841
			/* Copy right */
Packit Service fa4841
			else if (nXSrc < nXDst)
Packit Service fa4841
			{
Packit Service b1ea74
				for (y = (INT32)nHeight - 1; y >= 0; y--)
Packit Service fa4841
				{
Packit Service b1ea74
					const BYTE* srcLine =
Packit Service b1ea74
					    &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset];
Packit Service b1ea74
					BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset];
Packit Service b1ea74
					memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
Packit Service fa4841
				}
Packit Service fa4841
			}
Packit Service fa4841
			/* Source and destination are equal... */
Packit Service fa4841
			else
Packit Service fa4841
			{
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
		{
Packit Service b1ea74
			for (y = 0; y < (INT32)nHeight; y++)
Packit Service fa4841
			{
Packit Service b1ea74
				const BYTE* srcLine =
Packit Service b1ea74
				    &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset];
Packit Service b1ea74
				BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset];
Packit Service b1ea74
				memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		UINT32 x, y;
Packit Service fa4841
Packit Service fa4841
		for (y = 0; y < nHeight; y++)
Packit Service fa4841
		{
Packit Service b1ea74
			const BYTE* srcLine = &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset];
Packit Service b1ea74
			BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset];
Packit Service b1ea74
Packit Service b1ea74
			UINT32 color = ReadColor(&srcLine[nXSrc * srcByte], SrcFormat);
Packit Service b1ea74
			UINT32 oldColor = color;
Packit Service b1ea74
			UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
Packit Service b1ea74
			WriteColor(&dstLine[nXDst * dstByte], DstFormat, dstColor);
Packit Service b1ea74
			for (x = 1; x < nWidth; x++)
Packit Service fa4841
			{
Packit Service b1ea74
				color = ReadColor(&srcLine[(x + nXSrc) * srcByte], SrcFormat);
Packit Service b1ea74
				if (color == oldColor)
Packit Service b1ea74
				{
Packit Service b1ea74
					WriteColor(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor);
Packit Service b1ea74
				}
Packit Service b1ea74
				else
Packit Service b1ea74
				{
Packit Service b1ea74
					oldColor = color;
Packit Service b1ea74
					dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
Packit Service b1ea74
					WriteColor(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor);
Packit Service b1ea74
				}
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 b1ea74
BOOL freerdp_image_fill(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst,
Packit Service b1ea74
                        UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, UINT32 color)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 x, y;
Packit Service fa4841
	const UINT32 bpp = GetBytesPerPixel(DstFormat);
Packit Service fa4841
	BYTE* pFirstDstLine = &pDstData[nYDst * nDstStep];
Packit Service fa4841
	BYTE* pFirstDstLineXOffset = &pFirstDstLine[nXDst * bpp];
Packit Service fa4841
Packit Service fa4841
	for (x = 0; x < nWidth; x++)
Packit Service fa4841
	{
Packit Service fa4841
		BYTE* pDst = &pFirstDstLine[(x + nXDst) * bpp];
Packit Service fa4841
		WriteColor(pDst, DstFormat, color);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	for (y = 1; y < nHeight; y++)
Packit Service fa4841
	{
Packit Service fa4841
		BYTE* pDstLine = &pDstData[(y + nYDst) * nDstStep + nXDst * bpp];
Packit Service fa4841
		memcpy(pDstLine, pFirstDstLineXOffset, nWidth * bpp);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service b1ea74
Packit Service b1ea74
#if defined(SWSCALE_FOUND)
Packit Service b1ea74
static int av_format_for_buffer(UINT32 format)
Packit Service b1ea74
{
Packit Service b1ea74
	switch (format)
Packit Service b1ea74
	{
Packit Service b1ea74
		case PIXEL_FORMAT_ARGB32:
Packit Service b1ea74
			return AV_PIX_FMT_BGRA;
Packit Service b1ea74
Packit Service b1ea74
		case PIXEL_FORMAT_XRGB32:
Packit Service b1ea74
			return AV_PIX_FMT_BGR0;
Packit Service b1ea74
Packit Service b1ea74
		case PIXEL_FORMAT_BGRA32:
Packit Service b1ea74
			return AV_PIX_FMT_RGBA;
Packit Service b1ea74
Packit Service b1ea74
		case PIXEL_FORMAT_BGRX32:
Packit Service b1ea74
			return AV_PIX_FMT_RGB0;
Packit Service b1ea74
Packit Service b1ea74
		default:
Packit Service b1ea74
			return AV_PIX_FMT_NONE;
Packit Service b1ea74
	}
Packit Service b1ea74
}
Packit Service b1ea74
#endif
Packit Service b1ea74
Packit Service b1ea74
BOOL freerdp_image_scale(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst,
Packit Service b1ea74
                         UINT32 nYDst, UINT32 nDstWidth, UINT32 nDstHeight, const BYTE* pSrcData,
Packit Service b1ea74
                         DWORD SrcFormat, UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
Packit Service b1ea74
                         UINT32 nSrcWidth, UINT32 nSrcHeight)
Packit Service b1ea74
{
Packit Service b1ea74
	BOOL rc = FALSE;
Packit Service b1ea74
	const BYTE* src = &pSrcData[nXSrc * GetBytesPerPixel(SrcFormat) + nYSrc * nSrcStep];
Packit Service b1ea74
	BYTE* dst = &pDstData[nXDst * GetBytesPerPixel(DstFormat) + nYDst * nDstStep];
Packit Service b1ea74
Packit Service b1ea74
	/* direct copy is much faster than scaling, so check if we can simply copy... */
Packit Service b1ea74
	if ((nDstWidth == nSrcWidth) && (nDstHeight == nSrcHeight))
Packit Service b1ea74
	{
Packit Service b1ea74
		return freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth,
Packit Service b1ea74
		                          nDstHeight, pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, NULL,
Packit Service b1ea74
		                          FREERDP_FLIP_NONE);
Packit Service b1ea74
	}
Packit Service b1ea74
	else
Packit Service b1ea74
#if defined(SWSCALE_FOUND)
Packit Service b1ea74
	{
Packit Service b1ea74
		int res;
Packit Service b1ea74
		struct SwsContext* resize;
Packit Service b1ea74
		int srcFormat = av_format_for_buffer(SrcFormat);
Packit Service b1ea74
		int dstFormat = av_format_for_buffer(DstFormat);
Packit Service b1ea74
		const int srcStep[1] = { (int)nSrcStep };
Packit Service b1ea74
		const int dstStep[1] = { (int)nDstStep };
Packit Service b1ea74
Packit Service b1ea74
		if ((srcFormat == AV_PIX_FMT_NONE) || (dstFormat == AV_PIX_FMT_NONE))
Packit Service b1ea74
			return FALSE;
Packit Service b1ea74
Packit Service b1ea74
		resize = sws_getContext((int)nSrcWidth, (int)nSrcHeight, srcFormat, (int)nDstWidth,
Packit Service b1ea74
		                        (int)nDstHeight, dstFormat, SWS_BILINEAR, NULL, NULL, NULL);
Packit Service b1ea74
Packit Service b1ea74
		if (!resize)
Packit Service b1ea74
			goto fail;
Packit Service b1ea74
Packit Service b1ea74
		res = sws_scale(resize, &src, srcStep, 0, (int)nSrcHeight, &dst, dstStep);
Packit Service b1ea74
		rc = (res == ((int)nDstHeight));
Packit Service b1ea74
	fail:
Packit Service b1ea74
		sws_freeContext(resize);
Packit Service b1ea74
	}
Packit Service b1ea74
Packit Service b1ea74
#elif defined(CAIRO_FOUND)
Packit Service b1ea74
	{
Packit Service b1ea74
		const double sx = (double)nDstWidth / (double)nSrcWidth;
Packit Service b1ea74
		const double sy = (double)nDstHeight / (double)nSrcHeight;
Packit Service b1ea74
		cairo_t* cairo_context;
Packit Service b1ea74
		cairo_surface_t *csrc, *cdst;
Packit Service b1ea74
Packit Service b1ea74
		if ((nSrcWidth > INT_MAX) || (nSrcHeight > INT_MAX) || (nSrcStep > INT_MAX))
Packit Service b1ea74
			return FALSE;
Packit Service b1ea74
Packit Service b1ea74
		if ((nDstWidth > INT_MAX) || (nDstHeight > INT_MAX) || (nDstStep > INT_MAX))
Packit Service b1ea74
			return FALSE;
Packit Service b1ea74
Packit Service b1ea74
		csrc = cairo_image_surface_create_for_data((void*)src, CAIRO_FORMAT_ARGB32, (int)nSrcWidth,
Packit Service b1ea74
		                                           (int)nSrcHeight, (int)nSrcStep);
Packit Service b1ea74
		cdst = cairo_image_surface_create_for_data(dst, CAIRO_FORMAT_ARGB32, (int)nDstWidth,
Packit Service b1ea74
		                                           (int)nDstHeight, (int)nDstStep);
Packit Service b1ea74
Packit Service b1ea74
		if (!csrc || !cdst)
Packit Service b1ea74
			goto fail;
Packit Service b1ea74
Packit Service b1ea74
		cairo_context = cairo_create(cdst);
Packit Service b1ea74
Packit Service b1ea74
		if (!cairo_context)
Packit Service b1ea74
			goto fail2;
Packit Service b1ea74
Packit Service b1ea74
		cairo_scale(cairo_context, sx, sy);
Packit Service b1ea74
		cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
Packit Service b1ea74
		cairo_set_source_surface(cairo_context, csrc, 0, 0);
Packit Service b1ea74
		cairo_paint(cairo_context);
Packit Service b1ea74
		rc = TRUE;
Packit Service b1ea74
	fail2:
Packit Service b1ea74
		cairo_destroy(cairo_context);
Packit Service b1ea74
	fail:
Packit Service b1ea74
		cairo_surface_destroy(csrc);
Packit Service b1ea74
		cairo_surface_destroy(cdst);
Packit Service b1ea74
	}
Packit Service b1ea74
#else
Packit Service b1ea74
	{
Packit Service b1ea74
		WLog_WARN(TAG, "SmartScaling requested but compiled without libcairo support!");
Packit Service b1ea74
	}
Packit Service b1ea74
#endif
Packit Service b1ea74
	return rc;
Packit Service b1ea74
}