diff options
-rw-r--r-- | libfonts.h | 64 | ||||
-rw-r--r-- | libfonts_get_output_dpi.c | 77 |
2 files changed, 88 insertions, 53 deletions
@@ -90,43 +90,6 @@ enum libfonts_subpixel_order { /** - * Device rotation - */ -enum libfonts_orientation { - /** - * Unknown rotation - */ - LIBFONTS_ORIENTATION_UNKNOWN, - - /** - * Not rotated - */ - LIBFONTS_ORIENTATION_0_DEGREES_CLOCKWISE, - - /** - * Rotated 90 degrees clockwise - */ - LIBFONTS_ORIENTATION_90_DEGREES_CLOCKWISE, - - /** - * Rotated 180 degrees - */ - LIBFONTS_ORIENTATION_180_DEGREES_CLOCKWISE, - - /** - * Rotated 90 degrees counter-clockwise - */ - LIBFONTS_ORIENTATION_270_DEGREES_CLOCKWISE, - - /** - * Not rotated by a multiple of 90 degrees - */ - LIBFONTS_ORIENTATION_OTHER -}; -/* TODO use affine transformations instead to account for scaling and mirroring */ - - -/** * Output transformation structure */ struct libfonts_transformation { @@ -149,17 +112,17 @@ struct libfonts_transformation { struct libfonts_rendering_settings { /** * The output device's horizontal pixel density, - * in pixels (not dots) per inch, without output - * transformations applied, zero if not applicable - * or unknown + * in pixels (not dots) per inch, for the reference + * width, without output transformations applied, + * zero if not applicable or unknown */ double dpi_x; /** * The output device's vertical pixel density, - * in pixels (not dots) per inch, without output - * transformations applied, zero if not applicable - * or unknown + * in pixels (not dots) per inch, for the reference + * height, without output transformations applied, + * zero if not applicable or unknown */ double dpi_y; @@ -265,8 +228,8 @@ struct libfonts_output { * is applied * * This `.unrotated_output_width` divided by the output's - * physical width in inches, with `.output_transformation` - * than applied + * physical width in inches, with inverse of + * `.output_transformation` than applied */ double dpi_x; @@ -276,8 +239,8 @@ struct libfonts_output { * is applied * * This `.unrotated_output_height` divided by the output's - * physical height in inches, with `.output_transformation` - * than applied + * physical height in inches, with inverse of + * `.output_transformation` than applied */ double dpi_y; @@ -510,11 +473,12 @@ int libfonts_get_output_rendering_settings(struct libfonts_rendering_settings *, * @param edid The output device's EDID, in hexadecimal representation; * if `NULL`, `output->unrotated_output_width` and * `output->unrotated_output_height` need not be set, instead - * `output->dpi_x` and `output->dpi_y` must be set to the - * pixel density before the `output->output_transformation` + * `output->dpi_x` and `output->dpi_y` must be set to the pixel + * density before the inverse of `output->output_transformation` * is applied * @return 1 if a pixel density was calculated, - * 0 otherwise (projector or unsupported EDID) + * 0 otherwise (projector, unsupported EDID, or + * non-invertable output transformation) */ int libfonts_get_output_dpi(struct libfonts_output *, const char *); diff --git a/libfonts_get_output_dpi.c b/libfonts_get_output_dpi.c index 8e698e2..17ae837 100644 --- a/libfonts_get_output_dpi.c +++ b/libfonts_get_output_dpi.c @@ -2,9 +2,74 @@ #include "common.h" +static int +invert(struct libfonts_transformation *out, const struct libfonts_transformation *in) +{ + double m[3][3], t; + int i, j; + +#define SWAP_ROWS(A, B)\ + do {\ + for (i = 0; i < 6; i++) {\ + t = m[A][i];\ + m[A][i] = m[B][i];\ + m[B][i] = t;\ + }\ + } while (0) + + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + m[i][j] = in->m[i][j]; + m[i][j + 3] = 0; + } + m[i][i + 3] = 1; + } + + if (eq(m[0][0], 0)) { + if (!eq(m[1][0], 0)) + SWAP_ROWS(0, 1); + else if (!eq(m[2][0], 0)) + SWAP_ROWS(0, 2); + 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]; + + 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]; + + 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]; + + return 1; +} + + int 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]; @@ -12,7 +77,7 @@ libfonts_get_output_dpi(struct libfonts_output *output, const char *edid) 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) return 0; @@ -36,8 +101,14 @@ libfonts_get_output_dpi(struct libfonts_output *output, const char *edid) output->dpi_y = (double)output->unrotated_output_height / (double)height * 2.54; } - transform(&x[0], &y[0], 0, 0, &output->output_transformation); - transform(&x[1], &y[1], output->dpi_x, output->dpi_y, &output->output_transformation); + if (!invert(&invtrans, &output->output_transformation)) { + output->dpi_x = 0; + output->dpi_y = 0; + return 0; + } + + transform(&x[0], &y[0], 0, 0, &invtrans); + transform(&x[1], &y[1], output->dpi_x, output->dpi_y, &invtrans); 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]; |