Blame rdtk/librdtk/rdtk_nine_patch.c

Packit Service fa4841
/**
Packit Service fa4841
 * RdTk: Remote Desktop Toolkit
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
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 <freerdp/codec/color.h>
Packit Service fa4841
Packit Service fa4841
#include "rdtk_resources.h"
Packit Service fa4841
Packit Service fa4841
#include "rdtk_nine_patch.h"
Packit Service fa4841
Packit Service bb5c11
int rdtk_image_copy_alpha_blend(BYTE* pDstData, int nDstStep, int nXDst, int nYDst,
Packit Service bb5c11
                                int nWidth, int nHeight, BYTE* pSrcData, int nSrcStep, int nXSrc, int nYSrc)
Packit Service fa4841
{
Packit Service fa4841
	int x, y;
Packit Service fa4841
	BYTE A, R, G, B;
Packit Service fa4841
Packit Service fa4841
	for (y = 0; y < nHeight; y++)
Packit Service fa4841
	{
Packit Service fa4841
		const BYTE* pSrcPixel = &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * 4)];
Packit Service fa4841
		BYTE* pDstPixel = &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4)];
Packit Service fa4841
Packit Service fa4841
		for (x = 0; x < nWidth; x++)
Packit Service fa4841
		{
Packit Service fa4841
			B = pSrcPixel[0];
Packit Service fa4841
			G = pSrcPixel[1];
Packit Service fa4841
			R = pSrcPixel[2];
Packit Service fa4841
			A = pSrcPixel[3];
Packit Service fa4841
			pSrcPixel += 4;
Packit Service fa4841
Packit Service fa4841
			if (A == 255)
Packit Service fa4841
			{
Packit Service fa4841
				pDstPixel[0] = B;
Packit Service fa4841
				pDstPixel[1] = G;
Packit Service fa4841
				pDstPixel[2] = R;
Packit Service fa4841
			}
Packit Service fa4841
			else
Packit Service fa4841
			{
Packit Service fa4841
				R = (R * A) / 255;
Packit Service fa4841
				G = (G * A) / 255;
Packit Service fa4841
				B = (B * A) / 255;
Packit Service fa4841
				pDstPixel[0] = B + (pDstPixel[0] * (255 - A) + (255 / 2)) / 255;
Packit Service fa4841
				pDstPixel[1] = G + (pDstPixel[1] * (255 - A) + (255 / 2)) / 255;
Packit Service fa4841
				pDstPixel[2] = R + (pDstPixel[2] * (255 - A) + (255 / 2)) / 255;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			pDstPixel[3] = 0xFF;
Packit Service fa4841
			pDstPixel += 4;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return 1;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
int rdtk_nine_patch_draw(rdtkSurface* surface, int nXDst, int nYDst, int nWidth, int nHeight,
Packit Service fa4841
                         rdtkNinePatch* ninePatch)
Packit Service fa4841
{
Packit Service fa4841
	int x, y;
Packit Service fa4841
	int width;
Packit Service fa4841
	int height;
Packit Service fa4841
	int nXSrc;
Packit Service fa4841
	int nYSrc;
Packit Service fa4841
	int nSrcStep;
Packit Service fa4841
	int nDstStep;
Packit Service fa4841
	BYTE* pSrcData;
Packit Service fa4841
	BYTE* pDstData;
Packit Service fa4841
	int scaleWidth;
Packit Service fa4841
Packit Service fa4841
	if (nWidth < ninePatch->width)
Packit Service fa4841
		nWidth = ninePatch->width;
Packit Service fa4841
Packit Service fa4841
	if (nHeight < ninePatch->height)
Packit Service fa4841
		nHeight = ninePatch->height;
Packit Service fa4841
Packit Service fa4841
	scaleWidth = nWidth - (ninePatch->width - ninePatch->scaleWidth);
Packit Service fa4841
	nSrcStep = ninePatch->scanline;
Packit Service fa4841
	pSrcData = ninePatch->data;
Packit Service fa4841
	pDstData = surface->data;
Packit Service fa4841
	nDstStep = surface->scanline;
Packit Service fa4841
	/* top */
Packit Service fa4841
	x = 0;
Packit Service fa4841
	y = 0;
Packit Service fa4841
	/* top left */
Packit Service fa4841
	nXSrc = 0;
Packit Service fa4841
	nYSrc = 0;
Packit Service fa4841
	width = ninePatch->scaleLeft;
Packit Service fa4841
	height = ninePatch->scaleTop;
Packit Service bb5c11
	rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y,
Packit Service bb5c11
	                            width, height, pSrcData, nSrcStep, nXSrc, nYSrc);
Packit Service fa4841
	x += width;
Packit Service fa4841
	/* top middle (scalable) */
Packit Service fa4841
	nXSrc = ninePatch->scaleLeft;
Packit Service fa4841
	nYSrc = 0;
Packit Service fa4841
	height = ninePatch->scaleTop;
Packit Service fa4841
Packit Service fa4841
	while (x < (nXSrc + scaleWidth))
Packit Service fa4841
	{
Packit Service fa4841
		width = (nXSrc + scaleWidth) - x;
Packit Service fa4841
Packit Service fa4841
		if (width > ninePatch->scaleWidth)
Packit Service fa4841
			width = ninePatch->scaleWidth;
Packit Service fa4841
Packit Service bb5c11
		rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y,
Packit Service bb5c11
		                            width, height, pSrcData, nSrcStep, nXSrc, nYSrc);
Packit Service fa4841
		x += width;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/* top right */
Packit Service fa4841
	nXSrc = ninePatch->scaleRight;
Packit Service fa4841
	nYSrc = 0;
Packit Service fa4841
	width = ninePatch->width - ninePatch->scaleRight;
Packit Service fa4841
	height = ninePatch->scaleTop;
Packit Service bb5c11
	rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y,
Packit Service bb5c11
	                            width, height, pSrcData, nSrcStep, nXSrc, nYSrc);
Packit Service fa4841
	/* middle */
Packit Service fa4841
	x = 0;
Packit Service fa4841
	y = ninePatch->scaleTop;
Packit Service fa4841
	/* middle left */
Packit Service fa4841
	nXSrc = 0;
Packit Service fa4841
	nYSrc = ninePatch->scaleTop;
Packit Service fa4841
	width = ninePatch->scaleLeft;
Packit Service fa4841
	height = ninePatch->scaleHeight;
Packit Service bb5c11
	rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y,
Packit Service bb5c11
	                            width, height, pSrcData, nSrcStep, nXSrc, nYSrc);
Packit Service fa4841
	x += width;
Packit Service fa4841
	/* middle (scalable) */
Packit Service fa4841
	nXSrc = ninePatch->scaleLeft;
Packit Service fa4841
	nYSrc = ninePatch->scaleTop;
Packit Service fa4841
	height = ninePatch->scaleHeight;
Packit Service fa4841
Packit Service fa4841
	while (x < (nXSrc + scaleWidth))
Packit Service fa4841
	{
Packit Service fa4841
		width = (nXSrc + scaleWidth) - x;
Packit Service fa4841
Packit Service fa4841
		if (width > ninePatch->scaleWidth)
Packit Service fa4841
			width = ninePatch->scaleWidth;
Packit Service fa4841
Packit Service bb5c11
		rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y,
Packit Service bb5c11
		                            width, height, pSrcData, nSrcStep, nXSrc, nYSrc);
Packit Service fa4841
		x += width;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/* middle right */
Packit Service fa4841
	nXSrc = ninePatch->scaleRight;
Packit Service fa4841
	nYSrc = ninePatch->scaleTop;
Packit Service fa4841
	width = ninePatch->width - ninePatch->scaleRight;
Packit Service fa4841
	height = ninePatch->scaleHeight;
Packit Service bb5c11
	rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y,
Packit Service bb5c11
	                            width, height, pSrcData, nSrcStep, nXSrc, nYSrc);
Packit Service fa4841
	/* bottom */
Packit Service fa4841
	x = 0;
Packit Service fa4841
	y = ninePatch->scaleBottom;
Packit Service fa4841
	/* bottom left */
Packit Service fa4841
	nXSrc = 0;
Packit Service fa4841
	nYSrc = ninePatch->scaleBottom;
Packit Service fa4841
	width = ninePatch->scaleLeft;
Packit Service fa4841
	height = ninePatch->height - ninePatch->scaleBottom;
Packit Service bb5c11
	rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y,
Packit Service bb5c11
	                            width, height, pSrcData, nSrcStep, nXSrc, nYSrc);
Packit Service fa4841
	x += width;
Packit Service fa4841
	/* bottom middle (scalable) */
Packit Service fa4841
	nXSrc = ninePatch->scaleLeft;
Packit Service fa4841
	nYSrc = ninePatch->scaleBottom;
Packit Service fa4841
	height = ninePatch->height - ninePatch->scaleBottom;
Packit Service fa4841
Packit Service fa4841
	while (x < (nXSrc + scaleWidth))
Packit Service fa4841
	{
Packit Service fa4841
		width = (nXSrc + scaleWidth) - x;
Packit Service fa4841
Packit Service fa4841
		if (width > ninePatch->scaleWidth)
Packit Service fa4841
			width = ninePatch->scaleWidth;
Packit Service fa4841
Packit Service bb5c11
		rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y,
Packit Service bb5c11
		                            width, height, pSrcData, nSrcStep, nXSrc, nYSrc);
Packit Service fa4841
		x += width;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/* bottom right */
Packit Service fa4841
	nXSrc = ninePatch->scaleRight;
Packit Service fa4841
	nYSrc = ninePatch->scaleBottom;
Packit Service fa4841
	width = ninePatch->width - ninePatch->scaleRight;
Packit Service fa4841
	height = ninePatch->height - ninePatch->scaleBottom;
Packit Service bb5c11
	rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y,
Packit Service bb5c11
	                            width, height, pSrcData, nSrcStep, nXSrc, nYSrc);
Packit Service fa4841
	return 1;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
int rdtk_nine_patch_set_image(rdtkNinePatch* ninePatch, wImage* image)
Packit Service fa4841
{
Packit Service fa4841
	int x, y;
Packit Service fa4841
	BYTE* data;
Packit Service fa4841
	int beg, end;
Packit Service fa4841
	int scanline;
Packit Service fa4841
	UINT32* pixel;
Packit Service fa4841
	int width, height;
Packit Service fa4841
	ninePatch->image = image;
Packit Service fa4841
	width = image->width;
Packit Service fa4841
	height = image->height;
Packit Service fa4841
	scanline = image->scanline;
Packit Service fa4841
	data = image->data;
Packit Service fa4841
	/* parse scalable area */
Packit Service fa4841
	beg = end = -1;
Packit Service bb5c11
	pixel = (UINT32*) &data[4]; /* (1, 0) */
Packit Service fa4841
Packit Service fa4841
	for (x = 1; x < width - 1; x++)
Packit Service fa4841
	{
Packit Service fa4841
		if (beg < 0)
Packit Service fa4841
		{
Packit Service fa4841
			if (*pixel)
Packit Service fa4841
			{
Packit Service fa4841
				beg = x;
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
		else if (end < 0)
Packit Service fa4841
		{
Packit Service fa4841
			if (!(*pixel))
Packit Service fa4841
			{
Packit Service fa4841
				end = x;
Packit Service fa4841
				break;
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		pixel++;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	ninePatch->scaleLeft = beg - 1;
Packit Service fa4841
	ninePatch->scaleRight = end - 1;
Packit Service fa4841
	ninePatch->scaleWidth = ninePatch->scaleRight - ninePatch->scaleLeft;
Packit Service fa4841
	beg = end = -1;
Packit Service bb5c11
	pixel = (UINT32*) &data[scanline]; /* (0, 1) */
Packit Service fa4841
Packit Service fa4841
	for (y = 1; y < height - 1; y++)
Packit Service fa4841
	{
Packit Service fa4841
		if (beg < 0)
Packit Service fa4841
		{
Packit Service fa4841
			if (*pixel)
Packit Service fa4841
			{
Packit Service fa4841
				beg = y;
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
		else if (end < 0)
Packit Service fa4841
		{
Packit Service fa4841
			if (!(*pixel))
Packit Service fa4841
			{
Packit Service fa4841
				end = y;
Packit Service fa4841
				break;
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
Packit Service bb5c11
		pixel = (UINT32*) & ((BYTE*) pixel)[scanline];
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	ninePatch->scaleTop = beg - 1;
Packit Service fa4841
	ninePatch->scaleBottom = end - 1;
Packit Service fa4841
	ninePatch->scaleHeight = ninePatch->scaleBottom - ninePatch->scaleTop;
Packit Service fa4841
	/* parse fillable area */
Packit Service fa4841
	beg = end = -1;
Packit Service bb5c11
	pixel = (UINT32*) &data[((height - 1) * scanline) + 4]; /* (1, height - 1) */
Packit Service fa4841
Packit Service fa4841
	for (x = 1; x < width - 1; x++)
Packit Service fa4841
	{
Packit Service fa4841
		if (beg < 0)
Packit Service fa4841
		{
Packit Service fa4841
			if (*pixel)
Packit Service fa4841
			{
Packit Service fa4841
				beg = x;
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
		else if (end < 0)
Packit Service fa4841
		{
Packit Service fa4841
			if (!(*pixel))
Packit Service fa4841
			{
Packit Service fa4841
				end = x;
Packit Service fa4841
				break;
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		pixel++;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	ninePatch->fillLeft = beg - 1;
Packit Service fa4841
	ninePatch->fillRight = end - 1;
Packit Service fa4841
	ninePatch->fillWidth = ninePatch->fillRight - ninePatch->fillLeft;
Packit Service fa4841
	beg = end = -1;
Packit Service bb5c11
	pixel = (UINT32*) &data[((width - 1) * 4) + scanline]; /* (width - 1, 1) */
Packit Service fa4841
Packit Service fa4841
	for (y = 1; y < height - 1; y++)
Packit Service fa4841
	{
Packit Service fa4841
		if (beg < 0)
Packit Service fa4841
		{
Packit Service fa4841
			if (*pixel)
Packit Service fa4841
			{
Packit Service fa4841
				beg = y;
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
		else if (end < 0)
Packit Service fa4841
		{
Packit Service fa4841
			if (!(*pixel))
Packit Service fa4841
			{
Packit Service fa4841
				end = y;
Packit Service fa4841
				break;
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
Packit Service bb5c11
		pixel = (UINT32*) & ((BYTE*) pixel)[scanline];
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	ninePatch->fillTop = beg - 1;
Packit Service fa4841
	ninePatch->fillBottom = end - 1;
Packit Service fa4841
	ninePatch->fillHeight = ninePatch->fillBottom - ninePatch->fillTop;
Packit Service fa4841
	/* cut out borders from image */
Packit Service fa4841
	ninePatch->width = width - 2;
Packit Service fa4841
	ninePatch->height = height - 2;
Packit Service fa4841
	ninePatch->data = &data[scanline + 4]; /* (1, 1) */
Packit Service fa4841
	ninePatch->scanline = scanline;
Packit Service fa4841
#if 0
Packit Service fa4841
	printf("width: %d height: %d\n", ninePatch->width, ninePatch->height);
Packit Service fa4841
	printf("scale: left: %d right: %d top: %d bottom: %d\n",
Packit Service fa4841
	       ninePatch->scaleLeft, ninePatch->scaleRight,
Packit Service fa4841
	       ninePatch->scaleTop, ninePatch->scaleBottom);
Packit Service fa4841
	printf("fill:  left: %d right: %d top: %d bottom: %d\n",
Packit Service fa4841
	       ninePatch->fillLeft, ninePatch->fillRight,
Packit Service fa4841
	       ninePatch->fillTop, ninePatch->fillBottom);
Packit Service fa4841
#endif
Packit Service fa4841
	return 1;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
rdtkNinePatch* rdtk_nine_patch_new(rdtkEngine* engine)
Packit Service fa4841
{
Packit Service fa4841
	rdtkNinePatch* ninePatch;
Packit Service bb5c11
	ninePatch = (rdtkNinePatch*) calloc(1, sizeof(rdtkNinePatch));
Packit Service fa4841
Packit Service fa4841
	if (!ninePatch)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	ninePatch->engine = engine;
Packit Service fa4841
	return ninePatch;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void rdtk_nine_patch_free(rdtkNinePatch* ninePatch)
Packit Service fa4841
{
Packit Service fa4841
	if (!ninePatch)
Packit Service fa4841
		return;
Packit Service fa4841
Packit Service fa4841
	winpr_image_free(ninePatch->image, TRUE);
Packit Service fa4841
	free(ninePatch);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
int rdtk_nine_patch_engine_init(rdtkEngine* engine)
Packit Service fa4841
{
Packit Service fa4841
	int status;
Packit Service fa4841
	wImage* image = NULL;
Packit Service fa4841
	rdtkNinePatch* ninePatch;
Packit Service fa4841
Packit Service fa4841
	if (!engine->button9patch)
Packit Service fa4841
	{
Packit Service fa4841
		int size;
Packit Service fa4841
		BYTE* data;
Packit Service fa4841
		status = -1;
Packit Service fa4841
		size = rdtk_get_embedded_resource_file("btn_default_normal.9.png", &data);
Packit Service fa4841
Packit Service fa4841
		if (size > 0)
Packit Service fa4841
		{
Packit Service fa4841
			image = winpr_image_new();
Packit Service fa4841
Packit Service fa4841
			if (image)
Packit Service fa4841
				status = winpr_image_read_buffer(image, data, size);
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (status > 0)
Packit Service fa4841
		{
Packit Service fa4841
			ninePatch = engine->button9patch = rdtk_nine_patch_new(engine);
Packit Service fa4841
Packit Service fa4841
			if (ninePatch)
Packit Service fa4841
				rdtk_nine_patch_set_image(ninePatch, image);
Packit Service fa4841
			else
Packit Service fa4841
				winpr_image_free(image, TRUE);
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (!engine->textField9patch)
Packit Service fa4841
	{
Packit Service fa4841
		int size;
Packit Service fa4841
		BYTE* data;
Packit Service fa4841
		status = -1;
Packit Service fa4841
		size = rdtk_get_embedded_resource_file("textfield_default.9.png", &data);
Packit Service fa4841
Packit Service fa4841
		if (size > 0)
Packit Service fa4841
		{
Packit Service fa4841
			image = winpr_image_new();
Packit Service fa4841
Packit Service fa4841
			if (image)
Packit Service fa4841
				status = winpr_image_read_buffer(image, data, size);
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (status > 0)
Packit Service fa4841
		{
Packit Service fa4841
			ninePatch = engine->textField9patch = rdtk_nine_patch_new(engine);
Packit Service fa4841
Packit Service fa4841
			if (ninePatch)
Packit Service fa4841
				rdtk_nine_patch_set_image(ninePatch, image);
Packit Service fa4841
			else
Packit Service fa4841
				winpr_image_free(image, TRUE);
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return 1;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
int rdtk_nine_patch_engine_uninit(rdtkEngine* engine)
Packit Service fa4841
{
Packit Service fa4841
	if (engine->button9patch)
Packit Service fa4841
	{
Packit Service fa4841
		rdtk_nine_patch_free(engine->button9patch);
Packit Service fa4841
		engine->button9patch = NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (engine->textField9patch)
Packit Service fa4841
	{
Packit Service fa4841
		rdtk_nine_patch_free(engine->textField9patch);
Packit Service fa4841
		engine->textField9patch = NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return 1;
Packit Service fa4841
}