Prima

 view release on metacpan or  search on metacpan

img/rop.c  view on Meta::CPAN

		dVAL(DOWN(expr));\
		STORE;\
	}\
}

#define S (*src)
#define D (*dst)
#define SA (*src_a)
#define DA (*dst_a)
#define INVSA (255 - *src_a)
#define INVDA (255 - *dst_a)

/* sss */
static dBLEND_FUNC(blend_src_copy)
{
	if ( src_inc )
		memcpy( dst, src, bytes);
	else
		memset( dst, *src, bytes);
}

/* ddd */
static dBLEND_FUNC(blend_dst_copy)
{
}

/* 0 */
static dBLEND_FUNC(blend_clear)
{
	memset( dst, 0, bytes);
}

dBLEND_FUNCx(blend_blend,    UP(S) + UP(D) * INVSA / 255)

dBLEND_FUNCx(blend_src_over, (UP(S) * SA    + UP(D) * INVSA) / 255)
dBLEND_FUNCx(blend_xor,      (UP(S) * INVDA + UP(D) * INVSA) / 255)
dBLEND_FUNCx(blend_dst_over, (UP(D) * DA    + UP(S) * INVDA) / 255)
dBLEND_FUNCx(blend_src_in,    UP(S) * DA    / 255)
dBLEND_FUNCx(blend_dst_in,    UP(D) * SA    / 255)
dBLEND_FUNCx(blend_src_out,   UP(S) * INVDA / 255)
dBLEND_FUNCx(blend_dst_out,   UP(D) * INVSA / 255)
dBLEND_FUNCx(blend_src_atop, (UP(S) * DA    + UP(D) * INVSA) / 255)
dBLEND_FUNCx(blend_dst_atop, (UP(D) * SA    + UP(S) * INVDA) / 255)

/* sss + ddd */
static dBLEND_FUNC(blend_add)
{
	BLEND_LOOP {
		dVAL(S + D);
		STORE;
	}
}

/* SEPARABLE(S * D) */
dBLEND_FUNCx(blend_multiply, (UP(D) * (S + INVSA) + UP(S) * INVDA) / 255)

/* SEPARABLE(D * SA + S * DA - S * D) */
dBLEND_FUNCx(blend_screen,   (UP(S) * 255 + UP(D) * (255 - S)) / 255)

#define SEPARABLE(f) (UP(S) * INVDA + UP(D) * INVSA + (f))/255
dBLEND_FUNCx(blend_overlay, SEPARABLE(
	(2 * D < DA) ?
		(2 * UP(D) * S) :
		(UP(SA) * DA - UP(2) * (DA - D) * (SA - S)) 
	))

static dBLEND_FUNC(blend_darken)
{
	BLEND_LOOP {
		register int32_t ss = UP(S) * DA;
		register int32_t dd = UP(D) * SA;
		dVAL(DOWN(SEPARABLE((ss > dd) ? dd : ss)));
		STORE;
	}
}

static dBLEND_FUNC(blend_lighten)
{
	BLEND_LOOP {
		register int32_t ss = UP(S) * DA;
		register int32_t dd = UP(D) * SA;
		dVAL(DOWN(SEPARABLE((ss > dd) ? ss : dd)));
		STORE;
	}
}

static dBLEND_FUNC(blend_color_dodge)
{
	BLEND_LOOP {
		register int32_t s;
		if ( S >= SA ) {
			s = D ? UP(SA) * DA : 0;
		} else {
			register int32_t dodge = D * SA / (SA - S);
			s = UP(SA) * ((DA < dodge) ? DA : dodge);
		}
		s = DOWN(SEPARABLE(s));
		STORE;
	}
}

static dBLEND_FUNC(blend_color_burn)
{
	BLEND_LOOP {
		register int32_t s;
		if ( S == 0 ) {
			s = (D < DA) ? 0 : UP(SA) * DA;
		} else {
			register int32_t burn = (DA - D) * SA / S;
			s = (DA < burn) ? 0 : UP(SA) * (DA - burn);
		}
		s = DOWN(SEPARABLE(s));
		STORE;
	}
}

dBLEND_FUNCx(blend_hard_light, SEPARABLE(
	(2 * S < SA) ?
		(2 * UP(D) * S) :
		(UP(SA) * DA - UP(2) * (DA - D) * (SA - S)) 
	))

static dBLEND_FUNC(blend_soft_light)
{
	BLEND_LOOP {
		register int32_t s;
		if ( 2 * S < SA ) {
			s = DA ? D * (UP(SA) - UP(DA - D) * (SA - 2 * S) / DA ) : 0;
		} else if (DA == 0) {
			s = 0;
		} else if (4 * D <= DA) {
			s = D * (UP(SA) + (2 * S - SA) * ((UP(16) * D / DA - UP(12)) * D / DA + UP(3)));
		} else {
			s = 256 * (D * SA + (sqrt(D * DA) - D) * (2 * SA - S));
		}
		s = DOWN(SEPARABLE(s));
		STORE;
	}
}

static dBLEND_FUNC(blend_difference)
{
	BLEND_LOOP {
		dVAL(UP(D) * SA - UP(S) * DA);
		if ( s < 0 ) s = -s;
		s = DOWN(SEPARABLE(s));
		STORE;
	}
}

dBLEND_FUNCx(blend_exclusion, SEPARABLE( UP(S) * (DA - 2 * D) + UP(D) * SA ))

static BlendFunc* blend_functions[] = {
	blend_blend,
	blend_xor,
	blend_src_over,
	blend_dst_over,
	blend_src_copy,
	blend_dst_copy,
	blend_clear,
	blend_src_in,
	blend_dst_in,
	blend_src_out,
	blend_dst_out,
	blend_src_atop,
	blend_dst_atop,
	blend_add,
	blend_multiply,
	blend_screen,
	blend_dst_copy,
	blend_overlay,
	blend_darken,
	blend_lighten,
	blend_color_dodge,
	blend_color_burn,
	blend_hard_light,
	blend_soft_light,
	blend_difference,
	blend_exclusion
};

void
img_find_blend_proc( int rop, BlendFunc ** blend1, BlendFunc ** blend2 )
{
	*blend1 = blend_functions[rop];
	*blend2 = (rop >= ropMultiply) ? blend_functions[ropScreen] : blend_functions[rop];
}

Byte
rop_1bit_transform(Byte fore, Byte back, Byte rop)
{
	/*
	Special case with current foreground and background colors for 1-bit bitmaps/pixmaps, see also
	L<pod/Prima/Drawable.pod | Monochrome bitmaps>.

	Raster ops can be identified by a fingerprint.  For example, Or's is 14
	and Noop's is 10:

        0 | 0 =    0                      0 | 0 =    0
        0 | 1 =   1                       0 | 1 =   1
        1 | 0 =  1                        1 | 0 =  0
        1 | 1 = 1                         1 | 1 = 1
        ---     ----                      ---     ----
                1110 = 14                         1010 = 10

	when this special case uses not actual 0s and 1s, but bit values of
	foreground and background color instead, the resulting operation can
	still be expressed in rops, but these needs to be adjusted. Let's
	consider a case where both colors are 0, and rop = OrPut:

        0 | 0 =    0
        0 | 1 =   1
        0 | 0 =  0
        0 | 1 = 1
        ---     ----
                1010 = 10

	this means that in these conditions, Or (as well as Xor and AndInverted) becomes Noop.

	*/
	if ( fore == 0 && back == 0 ) {
		switch( rop) {
			case ropAndPut:
			case ropNotDestAnd:
			case ropBlackness:
			case ropCopyPut:       return ropBlackness;
			case ropNotXor:
			case ropInvert:
			case ropNotOr:
			case ropNotDestOr:     return ropInvert;
			case ropNotSrcAnd:



( run in 2.173 seconds using v1.01-cache-2.11-cpan-75ffa21a3d4 )