aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2020-04-29 15:57:11 +0200
committerMattias Andrée <maandree@kth.se>2020-04-29 15:57:11 +0200
commit9e7d87e78531157e6a6072650cf84e59d57133fa (patch)
tree0fd6ae184a8da3c57c45d688781b2da18862691a
parentAdd support for character transformation (diff)
downloadlibskrift-9e7d87e78531157e6a6072650cf84e59d57133fa.tar.gz
libskrift-9e7d87e78531157e6a6072650cf84e59d57133fa.tar.bz2
libskrift-9e7d87e78531157e6a6072650cf84e59d57133fa.tar.xz
Add support for character mirroring and add functions for creating transformations
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--Makefile10
-rw-r--r--README6
-rw-r--r--demo.c11
-rw-r--r--libskrift.h120
-rw-r--r--libskrift_add_180_degree_rotation.c4
-rw-r--r--libskrift_add_270_degree_rotation.c4
-rw-r--r--libskrift_add_90_degree_rotation.c4
-rw-r--r--libskrift_add_rotation.c4
-rw-r--r--libskrift_add_rotation_degrees.c4
-rw-r--r--libskrift_add_scaling.c4
-rw-r--r--libskrift_add_shear.c4
-rw-r--r--libskrift_add_transformation.c4
-rw-r--r--libskrift_add_translation.c4
-rw-r--r--libskrift_add_transposition.c4
-rw-r--r--libskrift_create_context.c47
15 files changed, 192 insertions, 42 deletions
diff --git a/Makefile b/Makefile
index 4c70752..85769d0 100644
--- a/Makefile
+++ b/Makefile
@@ -4,6 +4,16 @@ CONFIGFILE = config.mk
include $(CONFIGFILE)
OBJ =\
+ libskrift_add_180_degree_rotation.o\
+ libskrift_add_270_degree_rotation.o\
+ libskrift_add_90_degree_rotation.o\
+ libskrift_add_rotation.o\
+ libskrift_add_rotation_degrees.o\
+ libskrift_add_scaling.o\
+ libskrift_add_shear.o\
+ libskrift_add_transformation.o\
+ libskrift_add_translation.o\
+ libskrift_add_transposition.o\
libskrift_apply_glyph.o\
libskrift_calculate_dpi.o\
libskrift_close_font.o\
diff --git a/README b/README
index bfa17bf..f7327d9 100644
--- a/README
+++ b/README
@@ -36,6 +36,8 @@ Currently implemented:
sRGB gamma function.
+ Affine transformations on glyphs.
+
Pending support in libschift:
@@ -44,7 +46,7 @@ Pending support in libschift:
Hinting.
(Better subpixel rendering requires subpixel aware hinting.)
- Affine transformations on glyphs, texts, part of outline.
+ Affine transformations on parts of outline.
Kerning using font information.
@@ -53,6 +55,8 @@ Pending support in libschift:
Not implemented yet
+ Affine transformations on texts.
+
Glyph caching.
Normalise text when glyphs are missing.
diff --git a/demo.c b/demo.c
index a4d998c..c6a27d2 100644
--- a/demo.c
+++ b/demo.c
@@ -11,24 +11,19 @@ main(void)
LIBSKRIFT_CONTEXT *ctx;
struct libskrift_image image = {LIBSKRIFT_R8G8B8A8, LIBSKRIFT_HOST_SUBPIXEL, 0, 800, 600, NULL, NULL, NULL};
struct libskrift_rendering rendering = LIBSKRIFT_DEFAULT_RENDERING;
- struct libskrift_colour colour = LIBSKRIFT_PREMULTIPLY(0.8f, 0.25f, .80f, .50f, .20f);
+ struct libskrift_colour colour = LIBSKRIFT_PREMULTIPLY(.80f, .50f, .80f, .50f, .20f);
double height;
size_t size, i;
rendering.smoothing = LIBSKRIFT_SUBPIXEL;
rendering.subpixel_order = LIBSKRIFT_NONE;
- rendering.flags = 0;
+ rendering.flags = LIBSKRIFT_MIRROR_CHARS;
if (libskrift_open_font_file(&font, DEMO_FONT)) {
perror("libskrift_open_font_file");
return -1;
}
- rendering.char_transformation[0] = 1;
- rendering.char_transformation[1] = 0.25;
- rendering.char_transformation[2] = 0;
- rendering.char_transformation[3] = 0;
- rendering.char_transformation[4] = 1;
- rendering.char_transformation[5] = 0;
+ libskrift_add_rotation_degrees(rendering.char_transformation, 10);
height = libskrift_points_to_pixels(72, &rendering);
if (libskrift_create_context(&ctx, &font, 1, height, &rendering, NULL)) {
perror("libskrift_create_context");
diff --git a/libskrift.h b/libskrift.h
index 843de6e..57eb4d1 100644
--- a/libskrift.h
+++ b/libskrift.h
@@ -2,6 +2,7 @@
#ifndef LIBSKRIFT_H
#define LIBSKRIFT_H 1
+#include <math.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
@@ -86,25 +87,25 @@ enum libskrift_hinting {
LIBSKRIFT_FULL = 100
};
-#define LIBSKRIFT_REMOVE_GAMMA 0x00000001L
-#define LIBSKRIFT_Y_INCREASES_UPWARDS 0x00000002L /* SFT_DOWNWARD_Y otherwise */
-#define LIBSKRIFT_FLIP_TEXT 0x00000004L
-#define LIBSKRIFT_FLIP_CHARS 0x00000008L
-#define LIBSKRIFT_MIRROR_TEXT 0x00000010L
-#define LIBSKRIFT_MIRROR_CHARS 0x00000020L
-#define LIBSKRIFT_TRANSPOSE_TEXT 0x00000040L
-#define LIBSKRIFT_TRANSPOSE_CHARS 0x00000080L
-#define LIBSKRIFT_NO_LIGATURES 0x00000100L
-#define LIBSKRIFT_ADVANCE_CHAR_TO_GRID 0x00000200L
-#define LIBSKRIFT_REGRESS_CHAR_TO_GRID 0x00000400L /* Combine with LIBSKRIFT_ADVANCE_CHAR_TO_GRID for closest alternative */
-#define LIBSKRIFT_ADVANCE_WORD_TO_GRID 0x00000800L
-#define LIBSKRIFT_REGRESS_WORD_TO_GRID 0x00001000L /* Combine with LIBSKRIFT_ADVANCE_WORD_TO_GRID for closest alternative */
-#define LIBSKRIFT_USE_SUBPIXEL_GRID 0x00002000L
-#define LIBSKRIFT_VERTICAL_TEXT 0x00004000L
-#define LIBSKRIFT_AUTOHINTING 0x00008000L /* Use autohinter even if hint information exists */
-#define LIBSKRIFT_NO_AUTOHINTING 0x00010000L /* Use autohinter if no hint information exist */
-#define LIBSKRIFT_AUTOKERNING 0x00020000L /* Use autokerner even if kerning information exists */
-#define LIBSKRIFT_NO_AUTOKERNING 0x00040000L /* Use autokerner if no kerning information exist */
+#define LIBSKRIFT_REMOVE_GAMMA UINT32_C(0x00000001)
+#define LIBSKRIFT_Y_INCREASES_UPWARDS UINT32_C(0x00000002) /* SFT_DOWNWARD_Y otherwise */
+#define LIBSKRIFT_FLIP_TEXT UINT32_C(0x00000004)
+#define LIBSKRIFT_FLIP_CHARS UINT32_C(0x00000008)
+#define LIBSKRIFT_MIRROR_TEXT UINT32_C(0x00000010)
+#define LIBSKRIFT_MIRROR_CHARS UINT32_C(0x00000020)
+#define LIBSKRIFT_TRANSPOSE_TEXT UINT32_C(0x00000040)
+#define LIBSKRIFT_TRANSPOSE_CHARS UINT32_C(0x00000080)
+#define LIBSKRIFT_NO_LIGATURES UINT32_C(0x00000100)
+#define LIBSKRIFT_ADVANCE_CHAR_TO_GRID UINT32_C(0x00000200)
+#define LIBSKRIFT_REGRESS_CHAR_TO_GRID UINT32_C(0x00000400) /* Combine with LIBSKRIFT_ADVANCE_CHAR_TO_GRID for closest alternative */
+#define LIBSKRIFT_ADVANCE_WORD_TO_GRID UINT32_C(0x00000800)
+#define LIBSKRIFT_REGRESS_WORD_TO_GRID UINT32_C(0x00001000) /* Combine with LIBSKRIFT_ADVANCE_WORD_TO_GRID for closest alternative */
+#define LIBSKRIFT_USE_SUBPIXEL_GRID UINT32_C(0x00002000)
+#define LIBSKRIFT_VERTICAL_TEXT UINT32_C(0x00004000)
+#define LIBSKRIFT_AUTOHINTING UINT32_C(0x00008000) /* Use autohinter even if hint information exists */
+#define LIBSKRIFT_NO_AUTOHINTING UINT32_C(0x00010000) /* Use autohinter if no hint information exist */
+#define LIBSKRIFT_AUTOKERNING UINT32_C(0x00020000) /* Use autokerner even if kerning information exists */
+#define LIBSKRIFT_NO_AUTOKERNING UINT32_C(0x00040000) /* Use autokerner if no kerning information exist */
struct libskrift_rendering {
int struct_version;
@@ -272,4 +273,85 @@ void libskrift_srgb_preprocess(struct libskrift_image *, size_t, size_t, size_t,
_LIBSKRIFT_GCC_ONLY(__attribute__((__nonnull__)))
void libskrift_srgb_postprocess(struct libskrift_image *, size_t, size_t, size_t, size_t);
+
+inline void
+libskrift_add_transformation(double m[restrict 6], const double tm[restrict 6])
+{
+ double a = m[0], b = m[1], c = m[2];
+ double d = m[3], e = m[4], f = m[5];
+ m[0] = tm[0] * a + tm[1] * d;
+ m[1] = tm[0] * b + tm[1] * e;
+ m[2] = tm[0] * c + tm[1] * f + tm[2];
+ m[3] = tm[3] * a + tm[4] * d;
+ m[4] = tm[3] * b + tm[4] * e;
+ m[5] = tm[3] * c + tm[4] * f + tm[5];
+}
+
+inline void
+libskrift_add_rotation(double m[6], double radians)
+{
+ double c = cos(-radians), s = sin(-radians);
+ libskrift_add_transformation(m, (double []){c, -s, 0, s, c, 0});
+}
+
+inline void
+libskrift_add_rotation_degrees(double m[6], double degrees)
+{
+ libskrift_add_rotation(m, degrees * (double)0.017453292519943295f);
+}
+
+inline void
+libskrift_add_90_degree_rotation(double m[6])
+{
+ double a = m[0], b = m[1], c = m[2];
+ m[0] = m[3], m[1] = m[4], m[2] = m[5];
+ m[3] = -a, m[4] = -b, m[5] = -c;
+}
+
+inline void
+libskrift_add_180_degree_rotation(double m[6])
+{
+ m[0] = -m[0], m[1] = -m[1], m[2] = -m[2];
+ m[3] = -m[3], m[4] = -m[4], m[5] = -m[5];
+}
+
+inline void
+libskrift_add_270_degree_rotation(double m[6])
+{
+ double a = m[0], b = m[1], c = m[2];
+ m[0] = -m[3], m[1] = -m[4], m[2] = -m[5];
+ m[3] = a, m[4] = b, m[5] = c;
+}
+
+inline void
+libskrift_add_scaling(double m[6], double x, double y)
+{
+ m[0] *= x, m[1] *= x, m[2] *= x;
+ m[3] *= y, m[4] *= y, m[5] *= y;
+}
+
+inline void
+libskrift_add_transposition(double m[6])
+{
+ double a = m[0], b = m[1], c = m[2];
+ m[0] = m[3], m[1] = m[4], m[2] = m[5];
+ m[3] = a, m[4] = b, m[5] = c;
+}
+
+inline void
+libskrift_add_shear(double m[6], double x, double y)
+{
+ double a = m[0], b = m[1], c = m[2];
+ double d = m[3], e = m[4], f = m[6];
+ m[0] += x * d, m[1] += x * e, m[2] += x * f;
+ m[3] += y * a, m[4] += y * b, m[5] += y * c;
+}
+
+inline void
+libskrift_add_translation(double m[6], double x, double y)
+{
+ m[2] += x;
+ m[5] += y;
+}
+
#endif
diff --git a/libskrift_add_180_degree_rotation.c b/libskrift_add_180_degree_rotation.c
new file mode 100644
index 0000000..776e7b4
--- /dev/null
+++ b/libskrift_add_180_degree_rotation.c
@@ -0,0 +1,4 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+extern inline void libskrift_add_180_degree_rotation(double m[6]);
diff --git a/libskrift_add_270_degree_rotation.c b/libskrift_add_270_degree_rotation.c
new file mode 100644
index 0000000..74a86ea
--- /dev/null
+++ b/libskrift_add_270_degree_rotation.c
@@ -0,0 +1,4 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+extern inline void libskrift_add_270_degree_rotation(double m[6]);
diff --git a/libskrift_add_90_degree_rotation.c b/libskrift_add_90_degree_rotation.c
new file mode 100644
index 0000000..5c920e0
--- /dev/null
+++ b/libskrift_add_90_degree_rotation.c
@@ -0,0 +1,4 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+extern inline void libskrift_add_90_degree_rotation(double m[6]);
diff --git a/libskrift_add_rotation.c b/libskrift_add_rotation.c
new file mode 100644
index 0000000..8b03e81
--- /dev/null
+++ b/libskrift_add_rotation.c
@@ -0,0 +1,4 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+extern inline void libskrift_add_rotation(double m[6], double radians);
diff --git a/libskrift_add_rotation_degrees.c b/libskrift_add_rotation_degrees.c
new file mode 100644
index 0000000..239003b
--- /dev/null
+++ b/libskrift_add_rotation_degrees.c
@@ -0,0 +1,4 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+extern inline void libskrift_add_rotation_degrees(double m[6], double degrees);
diff --git a/libskrift_add_scaling.c b/libskrift_add_scaling.c
new file mode 100644
index 0000000..f9d745a
--- /dev/null
+++ b/libskrift_add_scaling.c
@@ -0,0 +1,4 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+extern inline void libskrift_add_scaling(double m[6], double x, double y);
diff --git a/libskrift_add_shear.c b/libskrift_add_shear.c
new file mode 100644
index 0000000..f48c507
--- /dev/null
+++ b/libskrift_add_shear.c
@@ -0,0 +1,4 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+extern inline void libskrift_add_shear(double m[6], double x, double y);
diff --git a/libskrift_add_transformation.c b/libskrift_add_transformation.c
new file mode 100644
index 0000000..fa14990
--- /dev/null
+++ b/libskrift_add_transformation.c
@@ -0,0 +1,4 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+extern inline void libskrift_add_transformation(double m[restrict 6], const double tm[restrict 6]);
diff --git a/libskrift_add_translation.c b/libskrift_add_translation.c
new file mode 100644
index 0000000..f5e2c14
--- /dev/null
+++ b/libskrift_add_translation.c
@@ -0,0 +1,4 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+extern inline void libskrift_add_translation(double m[6], double x, double y);
diff --git a/libskrift_add_transposition.c b/libskrift_add_transposition.c
new file mode 100644
index 0000000..2b2e91d
--- /dev/null
+++ b/libskrift_add_transposition.c
@@ -0,0 +1,4 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+extern inline void libskrift_add_transposition(double m[6]);
diff --git a/libskrift_create_context.c b/libskrift_create_context.c
index cf67826..1500b20 100644
--- a/libskrift_create_context.c
+++ b/libskrift_create_context.c
@@ -6,30 +6,47 @@
LIBSKRIFT_NO_AUTOKERNING)
#define IMPLEMENTED_FLAGS (LIBSKRIFT_REMOVE_GAMMA |\
+ LIBSKRIFT_MIRROR_CHARS |\
FORCED_FLAGS) /* libschrift does not add gamma, so not handling is required */
+#define TRANSFORMING_FLAGS (LIBSKRIFT_MIRROR_TEXT |\
+ LIBSKRIFT_MIRROR_CHARS |\
+ LIBSKRIFT_TRANSPOSE_TEXT |\
+ LIBSKRIFT_TRANSPOSE_CHARS)
+
#define COPY_ARRAY(DEST_STRUCT, SRC_STRUCT, FIELD)\
memcpy((DEST_STRUCT).FIELD, (SRC_STRUCT).FIELD, sizeof((SRC_STRUCT).FIELD))
static const struct libskrift_rendering default_rendering = LIBSKRIFT_DEFAULT_RENDERING;
+static void
+multiply_matrices(const double a[restrict 6], const double b[restrict 6], double r[restrict 6])
+{
+ r[0] = a[0] * b[0] + a[1] * b[3];
+ r[1] = a[0] * b[1] + a[1] * b[4];
+ r[2] = a[0] * b[2] + a[1] * b[5] + a[2];
+ r[3] = a[3] * b[0] + a[4] * b[3];
+ r[4] = a[3] * b[1] + a[4] * b[4];
+ r[5] = a[3] * b[2] + a[4] * b[5] + a[5];
+}
+
static int
transformation_hook(void *hook_data, double advance, double transform[6])
{
LIBSKRIFT_CONTEXT *ctx = hook_data;
- double r1c1b = ctx->rendering.char_transformation[0], r1c1a = transform[0];
- double r1c2b = ctx->rendering.char_transformation[1], r1c2a = transform[2];
- double r1c3b = ctx->rendering.char_transformation[2], r1c3a = transform[4];
- double r2c1b = ctx->rendering.char_transformation[3], r2c1a = transform[1];
- double r2c2b = ctx->rendering.char_transformation[4], r2c2a = transform[3];
- double r2c3b = ctx->rendering.char_transformation[5], r2c3a = transform[5];
- transform[0] = r1c1a * r1c1b + r1c2a * r2c1b;
- transform[2] = r1c1a * r1c2b + r1c2a * r2c2b;
- transform[4] = r1c1a * r1c3b + r1c2a * r2c3b + r1c3a;
- transform[1] = r2c1a * r1c1b + r2c2a * r2c1b;
- transform[3] = r2c1a * r1c2b + r2c2a * r2c2b;
- transform[5] = r2c1a * r1c3b + r2c2a * r2c3b + r2c3a;
- (void) advance;
+ double schrift[6] = {transform[0], transform[2], transform[4],
+ transform[1], transform[3], transform[5]};
+ double m1[6] = {1, 0, 0, 0, 1, 0}, m2[6] = {1, 0, 0, 0, 1, 0};
+ if (((ctx->rendering.flags / LIBSKRIFT_MIRROR_CHARS) ^ (ctx->rendering.flags / LIBSKRIFT_MIRROR_TEXT)) & 1)
+ multiply_matrices((double []){-1, 0, advance / schrift[0], 0, 1, 0}, m2, m1);
+ multiply_matrices(ctx->rendering.char_transformation, m1, m2);
+ multiply_matrices(schrift, m2, m1);
+ transform[0] = m1[0];
+ transform[2] = m1[1];
+ transform[4] = m1[2];
+ transform[1] = m1[3];
+ transform[3] = m1[4];
+ transform[5] = m1[5];
return 0;
}
@@ -82,6 +99,7 @@ libskrift_create_context(LIBSKRIFT_CONTEXT **ctxp, LIBSKRIFT_FONT **fonts, size_
(*ctxp)->rendering.hinting = LIBSKRIFT_NONE;
(*ctxp)->rendering.flags &= IMPLEMENTED_FLAGS;
(*ctxp)->rendering.flags |= FORCED_FLAGS;
+ (*ctxp)->rendering.flags |= LIBSKRIFT_REMOVE_GAMMA; /* libschrift does not add gamma */
(*ctxp)->rendering.grid_fineness = 1;
(*ctxp)->rendering.kerning = 0;
(*ctxp)->rendering.interletter_spacing = 0;
@@ -92,7 +110,8 @@ libskrift_create_context(LIBSKRIFT_CONTEXT **ctxp, LIBSKRIFT_FONT **fonts, size_
(*ctxp)->schrift_ctx.xScale = (*ctxp)->schrift_ctx.yScale;
(*ctxp)->schrift_ctx.xScale *= (*ctxp)->rendering.horizontal_dpi / (*ctxp)->rendering.vertical_dpi;
(*ctxp)->schrift_ctx.hook_data = (*ctxp);
- if (fpclassify((*ctxp)->rendering.char_transformation[0] - 1) != FP_ZERO ||
+ if (((*ctxp)->rendering.flags & TRANSFORMING_FLAGS) ||
+ fpclassify((*ctxp)->rendering.char_transformation[0] - 1) != FP_ZERO ||
fpclassify((*ctxp)->rendering.char_transformation[1]) != FP_ZERO ||
fpclassify((*ctxp)->rendering.char_transformation[2]) != FP_ZERO ||
fpclassify((*ctxp)->rendering.char_transformation[3]) != FP_ZERO ||