aboutsummaryrefslogblamecommitdiffstats
path: root/libfonts_calculate_subpixel_order.c
blob: 493b9e71fe9dec9712e661bf636a4dfadc0c2dac (plain) (tree)
1
2
3
4
                                                         
                   
 
 














                                                                                                                               







                                               




































































































                                                                                    

         
/* See LICENSE file for copyright and license details. */
#include "common.h"


enum libfonts_subpixel_order
libfonts_calculate_subpixel_order(enum libfonts_subpixel_order unrotated, const struct libfonts_transformation *transformation)
{
#define ASIS 0
#define ROTATED_90_DEG_CLOCKWISE 1
#define ROTATED_180_DEG_CLOCKWISE 2
#define ROTATED_270_DEG_CLOCKWISE 3
#define FLIPPED -1
#define FLOPPED -2
#define TRANSPOSED -3
#define ANTITRANSPOSED -4
#define OTHER -5

	double x[4], y[4], xmin, ymin, xmax, ymax, t1, t2;
	int trans, i, j;

	switch (unrotated) {
	case LIBFONTS_SUBPIXEL_ORDER_UNKNOWN:
	case LIBFONTS_SUBPIXEL_ORDER_NONRGB:
	case LIBFONTS_SUBPIXEL_ORDER_NONLINEAR:
	case LIBFONTS_SUBPIXEL_ORDER_OTHER:
		return unrotated;
	default:
		break;
	}

	for (i = 0; i < 3; i++)
		for (j = 0; j < 3; j++)
			if (!eq(transformation->m[i][j], 0))
				goto known;
	return LIBFONTS_SUBPIXEL_ORDER_UNKNOWN;
known:

	transform(&x[0], &y[0], 0, 0, transformation);
	transform(&x[1], &y[1], 1, 0, transformation);
	transform(&x[2], &y[2], 0, 1, transformation);
	transform(&x[3], &y[3], 1, 1, transformation);

	t1 = x[0] < x[1] ? x[0] : x[1];
	t2 = x[2] < x[3] ? x[2] : x[3];
	xmin = t1 < t2 ? t1 : t2;

	t1 = y[0] < y[1] ? y[0] : y[1];
	t2 = y[2] < y[3] ? y[2] : y[3];
	ymin = t1 < t2 ? t1 : t2;

	for (i = 0; i < 4; i++) {
		x[i] -= xmin;
		y[i] -= ymin;
	}

	t1 = x[0] > x[1] ? x[0] : x[1];
	t2 = x[2] > x[3] ? x[2] : x[3];
	xmax = t1 > t2 ? t1 : t2;

	t1 = y[0] > y[1] ? y[0] : y[1];
	t2 = y[2] > y[3] ? y[2] : y[3];
	ymax = t1 > t2 ? t1 : t2;

	for (i = 0; i < 4; i++) {
		x[i] /= xmax;
		y[i] /= ymax;
	}

	/* Here we select the inverse transformation from what `transformation`
	 * applies, as `transformation` applies to the image on the output and
	 * we want to know how the output is physically configured, which is
	 * the inverse */
	trans = OTHER;
	if (eq(x[0], 0) && eq(y[0], 0)  &&  eq(x[3], 1) && eq(y[3], 1)) {
		if (eq(x[1], 1) && eq(y[1], 0)  &&  eq(x[2], 0) && eq(y[2], 1))
			trans = ASIS;
		else if (eq(x[2], 1) && eq(y[2], 0)  &&  eq(x[1], 0) && eq(y[1], 1))
			trans = TRANSPOSED;
	} else if (eq(x[1], 0) && eq(y[1], 0)  &&  eq(x[2], 1) && eq(y[2], 1)) {
		if (eq(x[0], 1) && eq(y[0], 0)  &&  eq(x[3], 0) && eq(y[3], 1))
			trans = FLOPPED;
		else if (eq(x[3], 1) && eq(y[3], 0)  &&  eq(x[0], 0) && eq(y[0], 1))
			trans = ROTATED_90_DEG_CLOCKWISE;
	} else if (eq(x[2], 0) && eq(y[2], 0)  &&  eq(x[1], 1) && eq(y[1], 1)) {
		if (eq(x[0], 1) && eq(y[0], 0)  &&  eq(x[3], 0) && eq(y[3], 1))
			trans = ROTATED_270_DEG_CLOCKWISE;
		else if (eq(x[3], 1) && eq(y[3], 0)  &&  eq(x[0], 0) && eq(y[0], 1))
			trans = FLIPPED;
	} else if (eq(x[3], 0) && eq(y[3], 0)  &&  eq(x[0], 1) && eq(y[0], 1)) {
		if (eq(x[1], 1) && eq(y[1], 0)  &&  eq(x[2], 0) && eq(y[2], 1))
			trans = ANTITRANSPOSED;
		else if (eq(x[2], 1) && eq(y[2], 0)  &&  eq(x[1], 0) && eq(y[1], 1))
			trans = ROTATED_180_DEG_CLOCKWISE;
	}

	switch (trans) {
	case OTHER:
		return LIBFONTS_SUBPIXEL_ORDER_NONLINEAR;

	case ANTITRANSPOSED:
		if (unrotated <= LIBFONTS_SUBPIXEL_ORDER_G_R_B)
			return unrotated ^ 1;
		else
			return unrotated ^ 5;

	case TRANSPOSED:
		if (unrotated <= LIBFONTS_SUBPIXEL_ORDER_G_R_B)
			return unrotated ^ 1;
		else
			return 8 - (unrotated & 7) + (unrotated & ~7);

	case FLOPPED:
		if (unrotated <= LIBFONTS_SUBPIXEL_ORDER_G_R_B)
			return unrotated ^ ((~unrotated << 1) & 2);
		else
			return unrotated ^ 4 ^ ((unrotated << 1) & 2);

	case FLIPPED:
		if (unrotated <= LIBFONTS_SUBPIXEL_ORDER_G_R_B)
			return unrotated ^ ((unrotated << 1) & 2);
		else
			return unrotated ^ 4 ^ ((~unrotated << 1) & 2);

	case ASIS:
		return unrotated;

	default:
		return ((unrotated + trans) & 3) + (unrotated & ~3);
	}
}