aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2022-07-22 18:00:53 +0200
committerMattias Andrée <maandree@kth.se>2022-07-22 18:00:53 +0200
commit03dc2a75eeca1baf6d23d63c9dc74a29d84d7940 (patch)
treebdfbda04d4ad9c29c514d07ede4e3edc9e7760f0
parentFix EDID reading in libfonts_get_output_dpi and make it use the output transformation (diff)
downloadlibfonts-03dc2a75eeca1baf6d23d63c9dc74a29d84d7940.tar.gz
libfonts-03dc2a75eeca1baf6d23d63c9dc74a29d84d7940.tar.bz2
libfonts-03dc2a75eeca1baf6d23d63c9dc74a29d84d7940.tar.xz
libfonts_get_output_dpi: inversion of transformation should be used
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--libfonts.h64
-rw-r--r--libfonts_get_output_dpi.c77
2 files changed, 88 insertions, 53 deletions
diff --git a/libfonts.h b/libfonts.h
index 2c9b94d..2298c5c 100644
--- a/libfonts.h
+++ b/libfonts.h
@@ -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];