aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libfonts_get_output_dpi.c328
1 files changed, 303 insertions, 25 deletions
diff --git a/libfonts_get_output_dpi.c b/libfonts_get_output_dpi.c
index 47fcb70..03f73cc 100644
--- a/libfonts_get_output_dpi.c
+++ b/libfonts_get_output_dpi.c
@@ -6,7 +6,7 @@
static int
invert(struct libfonts_transformation *out, const struct libfonts_transformation *in)
{
- double m[3][3], t;
+ double m[3][6], t;
int i, j;
#define SWAP_ROWS(A, B)\
@@ -18,6 +18,7 @@ invert(struct libfonts_transformation *out, const struct libfonts_transformation
}\
} while (0)
+ /* Copy in-matrix and augment with identity-matrix */
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
m[i][j] = in->m[i][j];
@@ -26,6 +27,7 @@ invert(struct libfonts_transformation *out, const struct libfonts_transformation
m[i][i + 3] = 1;
}
+ /* Set m[0][0] ≠ 0 */
if (eq(m[0][0], 0)) {
if (!eq(m[1][0], 0))
SWAP_ROWS(0, 1);
@@ -34,34 +36,34 @@ invert(struct libfonts_transformation *out, const struct libfonts_transformation
else
return 0;
}
- for (i = 0; i < 6; i++)
- m[0][i] /= m[0][0];
- for (i = 0; i < 6; i++)
- m[1][i] -= m[1][0] * m[0][i];
- for (i = 0; i < 6; i++)
- m[2][i] -= m[2][0] * m[0][i];
+ /* Set m[0][0] = 1 */ for (t = m[0][0], i = 0; i < 6; i++) m[0][i] /= t;
+ /* Set m[1][0] = 0 */ for (t = m[1][0], i = 0; i < 6; i++) m[1][i] -= t * m[0][i];
+ /* Set m[2][0] = 0 */ for (t = m[2][0], i = 0; i < 6; i++) m[2][i] -= t * m[0][i];
+ /* Set m[1][1] ≠ 0 */
if (eq(m[1][1], 0)) {
if (!eq(m[2][1], 0))
SWAP_ROWS(1, 2);
else
return 0;
}
- for (i = 1; i < 6; i++)
- m[1][i] /= m[1][1];
- for (i = 1; i < 6; i++)
- m[2][i] -= m[2][1] * m[1][i];
- for (i = 1; i < 6; i++)
- m[0][i] -= m[0][1] * m[1][i];
+ /* Set m[1][1] = 1 */ for (t = m[1][1], i = 1; i < 6; i++) m[1][i] /= t;
+ /* Set m[2][1] = 0 */ for (t = m[2][1], i = 1; i < 6; i++) m[2][i] -= t * m[1][i];
+ /* Set m[0][1] = 0 */ for (t = m[0][1], i = 1; i < 6; i++) m[0][i] -= t * m[1][i];
+ /* Set m[2][2] ≠ 0 */
if (eq(m[2][2], 0))
return 0;
- for (i = 2; i < 6; i++)
- m[2][i] /= m[2][2];
- for (i = 2; i < 6; i++)
- m[1][i] -= m[1][1] * m[2][i];
- for (i = 2; i < 6; i++)
- m[0][i] -= m[0][1] * m[2][i];
+ /* Set m[2][2] = 1 */ for (t = m[2][2], i = 2; i < 6; i++) m[2][i] /= t;
+ /* Set m[1][2] = 0 */ for (t = m[1][2], i = 2; i < 6; i++) m[1][i] -= t * m[2][i];
+ /* Set m[0][2] = 0 */ for (t = m[0][2], i = 2; i < 6; i++) m[0][i] -= t * m[2][i];
+
+ /* Output augment */
+ for (i = 0; i < 3; i++) {
+ out->m[i][0] = m[i][3];
+ out->m[i][1] = m[i][4];
+ out->m[i][2] = m[i][5];
+ }
return 1;
}
@@ -73,13 +75,13 @@ libfonts_get_output_dpi(struct libfonts_output *output, const char *edid)
struct libfonts_transformation invtrans;
int width, height;
char width1, width2, height1, height2;
- double x[2], y[2];
+ double x[4], y[4], c1, c2, c3, c4;
if (edid) {
output->dpi_x = 0;
output->dpi_y = 0;
- if (strncasecmp(edid, "00""FF""FF""FF""FF""FF""FF""00", 2 * 8) || strlen(edid) < 256)
+ if (strncasecmp(edid, "00""FF""FF""FF""FF""FF""FF""00", 8 * 2) || strlen(edid) < 256)
return 0;
width1 = edid[21 * 2 + 0];
@@ -109,10 +111,25 @@ libfonts_get_output_dpi(struct libfonts_output *output, const char *edid)
}
transform(&x[0], &y[0], 0, 0, &invtrans);
- transform(&x[1], &y[1], output->dpi_x, output->dpi_y, &invtrans);
+ transform(&x[1], &y[1], output->dpi_x, 0, &invtrans);
+ transform(&x[2], &y[2], 0, output->dpi_y, &invtrans);
+ transform(&x[3], &y[3], output->dpi_x, output->dpi_y, &invtrans);
+
+ c1 = x[0] > x[1] ? x[0] - x[1] : x[1] - x[0];
+ c2 = x[0] > x[2] ? x[0] - x[2] : x[2] - x[0];
+ c3 = x[3] > x[1] ? x[3] - x[1] : x[1] - x[3];
+ c4 = x[3] > x[2] ? x[3] - x[2] : x[2] - x[3];
+ c1 = c1 > c2 ? c1 : c2;
+ c3 = c3 > c4 ? c3 : c4;
+ output->dpi_x = c1 > c3 ? c1 : c3;
- output->dpi_x = x[1] > x[0] ? x[1] - x[0] : x[0] - x[1];
- output->dpi_y = y[1] > y[0] ? y[1] - y[0] : y[0] - y[1];
+ c1 = y[0] > y[1] ? y[0] - y[1] : y[1] - y[0];
+ c2 = y[0] > y[2] ? y[0] - y[2] : y[2] - y[0];
+ c3 = y[3] > y[1] ? y[3] - y[1] : y[1] - y[3];
+ c4 = y[3] > y[2] ? y[3] - y[2] : y[2] - y[3];
+ c1 = c1 > c2 ? c1 : c2;
+ c3 = c3 > c4 ? c3 : c4;
+ output->dpi_y = c1 > c3 ? c1 : c3;
return 1;
}
@@ -122,8 +139,269 @@ libfonts_get_output_dpi(struct libfonts_output *output, const char *edid)
int
-main(void) /* TODO add test */
+main(void)
{
+#define T_(MAT, XOUT, YOUT, RET)\
+ do {\
+ output.dpi_x = 100;\
+ output.dpi_y = 150;\
+ memcpy(&output.output_transformation, &MAT, sizeof(struct libfonts_transformation));\
+ ASSERT(libfonts_get_output_dpi(&output, NULL) == RET);\
+ ASSERT(eq(output.dpi_x, XOUT));\
+ ASSERT(eq(output.dpi_y, YOUT));\
+ } while (0)
+
+#define T(MAT, XOUT, YOUT) T_(MAT, XOUT, YOUT, 1)
+#define ASIS(MAT) T(MAT, 100, 150)
+#define SWAPS(MAT) T(MAT, 150, 100)
+
+ char edid[512];
+ struct libfonts_output output;
+ struct libfonts_transformation asis_matrix = {.m = {
+ {+1, 0, 0},
+ { 0, +1, 0},
+ { 0, 0, 1}}};
+ struct libfonts_transformation rot90cw_matrix = {.m = {
+ { 0, -1, 0},
+ {+1, 0, 0},
+ { 0, 0, 1}}};
+ struct libfonts_transformation rot180cw_matrix = {.m = {
+ {-1, 0, 0},
+ { 0, -1, 0},
+ { 0, 0, 1}}};
+ struct libfonts_transformation rot270cw_matrix = {.m = {
+ { 0, +1, 0},
+ {-1, 0, 0},
+ { 0, 0, 1}}};
+ struct libfonts_transformation flip_matrix = {.m = {
+ {+1, 0, 0},
+ { 0, -1, 0},
+ { 0, 0, 1}}};
+ struct libfonts_transformation flop_matrix = {.m = {
+ {-1, 0, 0},
+ { 0, +1, 0},
+ { 0, 0, 1}}};
+ struct libfonts_transformation transpose_matrix = {.m = {
+ { 0, +1, 0},
+ {+1, 0, 0},
+ { 0, 0, 1}}};
+ struct libfonts_transformation antitranspose_matrix = {.m = {
+ { 0, -1, 0},
+ {-1, 0, 0},
+ { 0, 0, 1}}};
+ struct libfonts_transformation xdouble_matrix = {.m = {
+ {+2, 0, 0},
+ { 0, +1, 0},
+ { 0, 0, 1}}};
+ struct libfonts_transformation ydouble_matrix = {.m = {
+ {+1, 0, 0},
+ { 0, +2, 0},
+ { 0, 0, 1}}};
+ struct libfonts_transformation xydouble_matrix = {.m = {
+ {+2, 0, 0},
+ { 0, +2, 0},
+ { 0, 0, 1}}};
+ struct libfonts_transformation xtranslate_matrix = {.m = {
+ {+1, 0, 1},
+ { 0, +1, 0},
+ { 0, 0, 1}}};
+ struct libfonts_transformation ytranslate_matrix = {.m = {
+ {+1, 0, 0},
+ { 0, +1, 1},
+ { 0, 0, 1}}};
+ struct libfonts_transformation xytranslate_matrix = {.m = {
+ {+1, 0, 1},
+ { 0, +1, 1},
+ { 0, 0, 1}}};
+ struct libfonts_transformation xshear_matrix = {.m = {
+ {+1, +1, 0},
+ { 0, +1, 0},
+ { 0, 0, 1}}};
+ struct libfonts_transformation yshear_matrix = {.m = {
+ {+1, 0, 0},
+ {+1, +1, 0},
+ { 0, 0, 1}}};
+ struct libfonts_transformation rot45cw_matrix = {.m = {
+ {+0.7071067811865475, -0.7071067811865475, 0},
+ {+0.7071067811865475, +0.7071067811865475, 0},
+ { 0, 0, 1}}};
+ struct libfonts_transformation uninvertable_matrix = {.m = {
+ {1, 1, 0},
+ {1, 1, 0},
+ {0, 0, 1}}};
+ struct libfonts_transformation null_matrix = {.m = {
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}}};
+
+ ASIS(asis_matrix);
+ ASIS(rot180cw_matrix);
+ ASIS(flip_matrix);
+ ASIS(flop_matrix);
+ ASIS(xtranslate_matrix);
+ ASIS(ytranslate_matrix);
+ ASIS(xytranslate_matrix);
+
+ SWAPS(rot90cw_matrix);
+ SWAPS(rot270cw_matrix);
+ SWAPS(transpose_matrix);
+ SWAPS(antitranspose_matrix);
+
+ T(xdouble_matrix, 50, 150);
+ T(ydouble_matrix, 100, 75);
+ T(xydouble_matrix, 50, 75);
+
+ T(xshear_matrix, 150, 150); /* not important */
+ T(yshear_matrix, 100, 150); /* not important */
+
+ T(rot45cw_matrix, 150 * 0.7071067811865475, 150 * 0.7071067811865475); /* not important */
+
+ T_(uninvertable_matrix, 0, 0, 0);
+ T_(null_matrix, 0, 0, 0);
+
+ output.unrotated_output_width = 400;
+ output.unrotated_output_height = 500;
+
+ output.dpi_x = 100;
+ output.dpi_y = 150;
+ strcpy(edid, "00""FF""FF""FF""FF""FF""FF""00");
+ memcpy(&output.output_transformation, &asis_matrix, sizeof(struct libfonts_transformation));
+ ASSERT(libfonts_get_output_dpi(&output, edid) == 0);
+ ASSERT(eq(output.dpi_x, 0));
+ ASSERT(eq(output.dpi_y, 0));
+
+ output.dpi_x = 100;
+ output.dpi_y = 150;
+ memset(edid, '0', sizeof(edid));
+ memcpy(edid, "00""FF""FF""FF""FF""FF""FF""00", 8 * 2);
+ edid[21 * 2 + 0] = 'A';
+ edid[21 * 2 + 1] = 'A';
+ edid[22 * 2 + 0] = 'A';
+ edid[22 * 2 + 1] = 'A';
+ edid[255] = '\0';
+ memcpy(&output.output_transformation, &asis_matrix, sizeof(struct libfonts_transformation));
+ ASSERT(libfonts_get_output_dpi(&output, edid) == 0);
+ ASSERT(eq(output.dpi_x, 0));
+ ASSERT(eq(output.dpi_y, 0));
+
+ output.dpi_x = 100;
+ output.dpi_y = 150;
+ memset(edid, '0', sizeof(edid));
+ memcpy(edid, "00""FF""FF""FF""FF""FF""FF""00", 8 * 2);
+ edid[21 * 2 + 0] = 'A';
+ edid[21 * 2 + 1] = 'A';
+ edid[22 * 2 + 0] = 'A';
+ edid[22 * 2 + 1] = 'A';
+ edid[254] = '\0';
+ memcpy(&output.output_transformation, &asis_matrix, sizeof(struct libfonts_transformation));
+ ASSERT(libfonts_get_output_dpi(&output, edid) == 0);
+ ASSERT(eq(output.dpi_x, 0));
+ ASSERT(eq(output.dpi_y, 0));
+
+ output.dpi_x = 100;
+ output.dpi_y = 150;
+ memset(edid, '0', sizeof(edid));
+ memcpy(edid, "00""FF""FF""FF""FF""FF""FF""00", 8 * 2);
+ edid[21 * 2 + 0] = 'X';
+ edid[21 * 2 + 1] = 'X';
+ edid[22 * 2 + 0] = 'X';
+ edid[22 * 2 + 1] = 'X';
+ edid[256] = '\0';
+ memcpy(&output.output_transformation, &asis_matrix, sizeof(struct libfonts_transformation));
+ ASSERT(libfonts_get_output_dpi(&output, edid) == 0);
+ ASSERT(eq(output.dpi_x, 0));
+ ASSERT(eq(output.dpi_y, 0));
+
+ output.dpi_x = 100;
+ output.dpi_y = 150;
+ memset(edid, '0', sizeof(edid));
+ memcpy(edid, "00""FF""FF""FF""FF""FF""FF""00", 8 * 2);
+ edid[21 * 2 + 0] = 'A';
+ edid[21 * 2 + 1] = 'A';
+ edid[22 * 2 + 0] = '0';
+ edid[22 * 2 + 1] = '0';
+ edid[256] = '\0';
+ memcpy(&output.output_transformation, &asis_matrix, sizeof(struct libfonts_transformation));
+ ASSERT(libfonts_get_output_dpi(&output, edid) == 0);
+ ASSERT(eq(output.dpi_x, 0));
+ ASSERT(eq(output.dpi_y, 0));
+
+ output.dpi_x = 100;
+ output.dpi_y = 150;
+ memset(edid, '0', sizeof(edid));
+ memcpy(edid, "00""FF""FF""FF""FF""FF""FF""00", 8 * 2);
+ edid[21 * 2 + 0] = '0';
+ edid[21 * 2 + 1] = '0';
+ edid[22 * 2 + 0] = 'A';
+ edid[22 * 2 + 1] = 'A';
+ edid[256] = '\0';
+ memcpy(&output.output_transformation, &asis_matrix, sizeof(struct libfonts_transformation));
+ ASSERT(libfonts_get_output_dpi(&output, edid) == 0);
+ ASSERT(eq(output.dpi_x, 0));
+ ASSERT(eq(output.dpi_y, 0));
+
+ output.dpi_x = 100;
+ output.dpi_y = 150;
+ memset(edid, '0', sizeof(edid));
+ memcpy(edid, "00""FF""FF""FF""FF""FF""FF""00", 8 * 2);
+ edid[21 * 2 + 0] = '0';
+ edid[21 * 2 + 1] = '0';
+ edid[22 * 2 + 0] = '0';
+ edid[22 * 2 + 1] = '0';
+ edid[256] = '\0';
+ memcpy(&output.output_transformation, &asis_matrix, sizeof(struct libfonts_transformation));
+ ASSERT(libfonts_get_output_dpi(&output, edid) == 0);
+ ASSERT(eq(output.dpi_x, 0));
+ ASSERT(eq(output.dpi_y, 0));
+
+ output.unrotated_output_width = 400;
+ output.unrotated_output_height = 500;
+ output.dpi_x = 100;
+ output.dpi_y = 150;
+ memset(edid, '0', sizeof(edid));
+ memcpy(edid, "00""FF""FF""FF""FF""FF""FF""00", 8 * 2);
+ edid[21 * 2 + 0] = 'A';
+ edid[21 * 2 + 1] = 'A';
+ edid[22 * 2 + 0] = 'A';
+ edid[22 * 2 + 1] = 'A';
+ edid[256] = '\0';
+ memcpy(&output.output_transformation, &asis_matrix, sizeof(struct libfonts_transformation));
+ ASSERT(libfonts_get_output_dpi(&output, edid) == 1);
+ ASSERT(eq(output.dpi_x, 2.54 * 400 / 0xAA));
+ ASSERT(eq(output.dpi_y, 2.54 * 500 / 0xAA));
+
+ output.unrotated_output_width = 400;
+ output.unrotated_output_height = 500;
+ output.dpi_x = 100;
+ output.dpi_y = 150;
+ memset(edid, '0', sizeof(edid));
+ memcpy(edid, "00""FF""FF""FF""FF""FF""FF""00", 8 * 2);
+ edid[21 * 2 + 0] = '9';
+ edid[21 * 2 + 1] = '9';
+ edid[22 * 2 + 0] = '8';
+ edid[22 * 2 + 1] = '8';
+ edid[256] = '\0';
+ memcpy(&output.output_transformation, &asis_matrix, sizeof(struct libfonts_transformation));
+ ASSERT(libfonts_get_output_dpi(&output, edid) == 1);
+ ASSERT(eq(output.dpi_x, 2.54 * 400 / 0x99));
+ ASSERT(eq(output.dpi_y, 2.54 * 500 / 0x88));
+
+ output.unrotated_output_width = 400;
+ output.unrotated_output_height = 500;
+ output.dpi_x = 100;
+ output.dpi_y = 150;
+ memset(edid, '0', sizeof(edid));
+ memcpy(edid, "00""FF""FF""FF""FF""FF""FF""00", 8 * 2);
+ edid[21 * 2 + 0] = '9';
+ edid[21 * 2 + 1] = '9';
+ edid[22 * 2 + 0] = '8';
+ edid[22 * 2 + 1] = '8';
+ edid[256] = '\0';
+ memcpy(&output.output_transformation, &rot90cw_matrix, sizeof(struct libfonts_transformation));
+ ASSERT(libfonts_get_output_dpi(&output, edid) == 1);
+ ASSERT(eq(output.dpi_y, 2.54 * 400 / 0x99));
+ ASSERT(eq(output.dpi_x, 2.54 * 500 / 0x88));
+
return 0;
}