Blame libfreerdp/gdi/test/TestGdiRop3.c

Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/winpr.h>
Packit 1fb8d4
#include <winpr/collections.h>
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Ternary Raster Operations:
Packit Service 5a9772
 * See "Windows Graphics Programming: Win32 GDI and DirectDraw", chapter 11. Advanced Bitmap
Packit Service 5a9772
 * Graphics
Packit 1fb8d4
 *
Packit 1fb8d4
 * Operators:
Packit 1fb8d4
 *
Packit 1fb8d4
 * 	AND		&		a
Packit 1fb8d4
 * 	OR		|		o
Packit 1fb8d4
 * 	NOT		~		n
Packit 1fb8d4
 * 	XOR		^		x
Packit 1fb8d4
 *
Packit 1fb8d4
 * Operands:
Packit 1fb8d4
 *
Packit 1fb8d4
 * 	Pen/Brush			P
Packit 1fb8d4
 * 	Destination			D
Packit 1fb8d4
 * 	Source				S
Packit 1fb8d4
 *
Packit 1fb8d4
 * Example:
Packit 1fb8d4
 *
Packit 1fb8d4
 * Raster operation which returns P if S is 1 or D otherwise:
Packit 1fb8d4
 * (rop_S & rop_P) | (~rop_S & rop_D); -> 0xE2 (0x00E20746)
Packit 1fb8d4
 *
Packit 1fb8d4
 * Postfix notation: DSPDxax
Packit 1fb8d4
 * Infix notation: D^(S&(P^D))), (S&P)|(~S&D)
Packit 1fb8d4
 *
Packit 1fb8d4
 * DSPDxax using D^(S&(P^D)):
Packit 1fb8d4
 *
Packit 1fb8d4
 * 	mov eax, P	// P
Packit 1fb8d4
 * 	xor eax, D	// P^D
Packit 1fb8d4
 * 	and eax, S	// S&(P^D)
Packit 1fb8d4
 * 	xor eax, D	// D^(S&(P^D))
Packit 1fb8d4
 * 	mov D, eax	// write result
Packit 1fb8d4
 *
Packit 1fb8d4
 * DSPDxax using (S&P)|(~S&D):
Packit 1fb8d4
 *
Packit 1fb8d4
 * 	mov eax, S	// S
Packit 1fb8d4
 * 	and eax, P	// S&P
Packit 1fb8d4
 * 	mov ebx, S	// S
Packit 1fb8d4
 * 	not ebx		// ~S
Packit 1fb8d4
 * 	and ebx, D	// ~D&D
Packit 1fb8d4
 * 	or eax, ebx	// (S&P)|(~S&D)
Packit 1fb8d4
 * 	mov D, eax	// write result
Packit 1fb8d4
 *
Packit 1fb8d4
 * Raster operation lower word encoding:
Packit 1fb8d4
 *
Packit 1fb8d4
 *  _______________________________________________________________________________
Packit 1fb8d4
 * |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |
Packit 1fb8d4
 * |   Op5   |   Op4   |   Op3   |   Op2   |   Op1   | Not| Parse String |  Offset |
Packit 1fb8d4
 * |____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|
Packit 1fb8d4
 *   15   14   13   12   11   10    9    8    7    6    5    4    3   2     1    0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Operator:
Packit 1fb8d4
 * 	0: NOT
Packit 1fb8d4
 * 	1: XOR
Packit 1fb8d4
 * 	2: OR
Packit 1fb8d4
 * 	3: AND
Packit 1fb8d4
 *
Packit 1fb8d4
 * Parse String:
Packit 1fb8d4
 * 	0: SPDDDDDD
Packit 1fb8d4
 * 	1: SPDSPDSP
Packit 1fb8d4
 * 	2: SDPSDPSD
Packit 1fb8d4
 * 	3: DDDDDDDD
Packit 1fb8d4
 * 	4: DDDDDDDD
Packit 1fb8d4
 * 	5: S+SP-DSS
Packit 1fb8d4
 * 	6: S+SP-PDS
Packit 1fb8d4
 * 	7: S+SD-PDS
Packit 1fb8d4
 *
Packit 1fb8d4
 * The lower word for 0x00E20746 is 0x0746 (00000111 01000110)
Packit 1fb8d4
 *
Packit 1fb8d4
 * 00		Op5 (NOT, n)
Packit 1fb8d4
 * 00		Op4 (NOT, n)
Packit 1fb8d4
 * 01		Op3 (XOR, x)
Packit 1fb8d4
 * 11		Op2 (AND, a)
Packit 1fb8d4
 * 01		Op1 (XOR, x)
Packit 1fb8d4
 * 0		Not (unused)
Packit 1fb8d4
 * 001		String (SPDSPDSP)
Packit 1fb8d4
 * 10		Offset (2)
Packit 1fb8d4
 *
Packit 1fb8d4
 * We shift SPDSPDSP to the left by 2: DSPDSPSP
Packit 1fb8d4
 *
Packit 1fb8d4
 * We have 5 operators: 3 binary operators and the last two are unary operators,
Packit 1fb8d4
 * so only four operands are needed. The parse string is truncated to reflect
Packit 1fb8d4
 * the number of operands we need: DSPD
Packit 1fb8d4
 *
Packit 1fb8d4
 * The operator string (from Op1 to Op5) is xaxnn, which can be simplified to xax
Packit 1fb8d4
 *
Packit 1fb8d4
 * The complete string representing the operation is DSPDxax
Packit 1fb8d4
 *
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
static char* gdi_convert_postfix_to_infix(const char* postfix)
Packit 1fb8d4
{
Packit Service 5a9772
	size_t i;
Packit Service 5a9772
	size_t length;
Packit 1fb8d4
	BOOL unary;
Packit 1fb8d4
	wStack* stack;
Packit Service 5a9772
	size_t al, bl, cl, dl;
Packit Service 5a9772
	char *a, *b, *c, *d;
Packit 1fb8d4
	bl = cl = dl = 0;
Packit 1fb8d4
	stack = Stack_New(FALSE);
Packit 1fb8d4
	length = strlen(postfix);
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < length; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		if ((postfix[i] == 'P') || (postfix[i] == 'D') || (postfix[i] == 'S'))
Packit 1fb8d4
		{
Packit 1fb8d4
			/* token is an operand, push on the stack */
Packit 1fb8d4
			a = malloc(2);
Packit 1fb8d4
			a[0] = postfix[i];
Packit 1fb8d4
			a[1] = '\0';
Packit Service 5a9772
			// printf("Operand: %s\n", a);
Packit 1fb8d4
			Stack_Push(stack, a);
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			/* token is an operator */
Packit 1fb8d4
			unary = FALSE;
Packit 1fb8d4
			c = malloc(2);
Packit 1fb8d4
			c[0] = postfix[i];
Packit 1fb8d4
			c[1] = '\0';
Packit 1fb8d4
Packit 1fb8d4
			if (c[0] == 'a')
Packit 1fb8d4
			{
Packit 1fb8d4
				c[0] = '&';
Packit 1fb8d4
			}
Packit 1fb8d4
			else if (c[0] == 'o')
Packit 1fb8d4
			{
Packit 1fb8d4
				c[0] = '|';
Packit 1fb8d4
			}
Packit 1fb8d4
			else if (c[0] == 'n')
Packit 1fb8d4
			{
Packit 1fb8d4
				c[0] = '~';
Packit 1fb8d4
				unary = TRUE;
Packit 1fb8d4
			}
Packit 1fb8d4
			else if (c[0] == 'x')
Packit 1fb8d4
			{
Packit 1fb8d4
				c[0] = '^';
Packit 1fb8d4
			}
Packit 1fb8d4
			else
Packit 1fb8d4
			{
Packit 1fb8d4
				printf("invalid operator: %c\n", c[0]);
Packit 1fb8d4
			}
Packit 1fb8d4
Packit Service 5a9772
			// printf("Operator: %s\n", c);
Packit Service 5a9772
			a = (char*)Stack_Pop(stack);
Packit 1fb8d4
Packit 1fb8d4
			if (unary)
Packit 1fb8d4
				b = NULL;
Packit 1fb8d4
			else
Packit Service 5a9772
				b = (char*)Stack_Pop(stack);
Packit 1fb8d4
Packit 1fb8d4
			al = strlen(a);
Packit 1fb8d4
Packit 1fb8d4
			if (b)
Packit 1fb8d4
				bl = strlen(b);
Packit 1fb8d4
Packit 1fb8d4
			cl = 1;
Packit 1fb8d4
			dl = al + bl + cl + 3;
Packit 1fb8d4
			d = malloc(dl + 1);
Packit 1fb8d4
			sprintf_s(d, dl, "(%s%s%s)", b ? b : "", c, a);
Packit 1fb8d4
			Stack_Push(stack, d);
Packit 1fb8d4
			free(a);
Packit 1fb8d4
			free(b);
Packit 1fb8d4
			free(c);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	d = (char*)Stack_Pop(stack);
Packit 1fb8d4
	Stack_Free(stack);
Packit 1fb8d4
	return d;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static const char* test_ROP3[] = { "DSPDxax",  "PSDPxax", "SPna",   "DSna",   "DPa",
Packit Service 5a9772
	                               "PDxn",     "DSxn",    "PSDnox", "PDSona", "DSPDxox",
Packit Service 5a9772
	                               "DPSDonox", "SPDSxax", "DPon",   "DPna",   "Pn",
Packit Service 5a9772
	                               "PDna",     "DPan",    "DSan",   "DSxn",   "DPa",
Packit Service 5a9772
	                               "D",        "DPno",    "SDno",   "PDno",   "DPo" };
Packit 1fb8d4
Packit 1fb8d4
int TestGdiRop3(int argc, char* argv[])
Packit 1fb8d4
{
Packit Service 5a9772
	size_t index;
Packit Service 5a9772
	WINPR_UNUSED(argc);
Packit Service 5a9772
	WINPR_UNUSED(argv);
Packit 1fb8d4
Packit 1fb8d4
	for (index = 0; index < sizeof(test_ROP3) / sizeof(test_ROP3[0]); index++)
Packit 1fb8d4
	{
Packit 1fb8d4
		const char* postfix = test_ROP3[index];
Packit 1fb8d4
		char* infix = gdi_convert_postfix_to_infix(postfix);
Packit 1fb8d4
Packit 1fb8d4
		if (!infix)
Packit 1fb8d4
			return -1;
Packit 1fb8d4
Packit 1fb8d4
		printf("%s\t\t%s\n", postfix, infix);
Packit 1fb8d4
		free(infix);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}