aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demo.c631
-rw-r--r--libskrift.h2
-rw-r--r--libskrift_inches_to_pixels.c2
-rw-r--r--libskrift_millimeters_to_pixels.c2
4 files changed, 609 insertions, 28 deletions
diff --git a/demo.c b/demo.c
index d86385e..c1a6488 100644
--- a/demo.c
+++ b/demo.c
@@ -1,64 +1,645 @@
/* See LICENSE file for copyright and license details. */
#include "libskrift.h"
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <libsimple-arg.h>
+
+
#define TEST_TEXT "hello world"
+
+USAGE("[-b background-colour] [-f foreground-colour] [-a opacity] [-t character-transformation] ... "
+ "[-T character-transformation] ... [-k kerning] [-i interletter-spacing] [-g grid_fineness] "
+ "[-S smoothing-method[:subpixel-order]] [-H hiniting] [-o flags] ... [-s font-size] [-F font-file] "
+ "[-D dpi-x:dpi-y | -D dpi] [-w width] [-h height] [-x x-position] [-y y-position] [text]");
+
+static uint8_t
+decode_hexbyte(char hi, char lo)
+{
+ int ret;
+ ret = ((hi & 15) + 9 * (hi > '9')) << 4;
+ ret |= ((lo & 15) + 9 * (lo > '9')) << 0;
+ return (uint8_t)ret;
+}
+
+static void
+parse_colour(const char *s, uint8_t *redp, uint8_t *greenp, uint8_t *bluep, uint8_t *alphap)
+{
+ char rh, rl, gh, gl, bh, bl, ah = 'f', al = 'f';
+
+ if (!isxdigit(s[0])) goto invalid;
+ if (!isxdigit(s[1])) goto invalid;
+ if (!isxdigit(s[2])) goto invalid;
+ if (!isxdigit(s[3])) goto invalid;
+ if (!isxdigit(s[4])) goto invalid;
+ if (!isxdigit(s[5])) goto invalid;
+
+ rh = *s++;
+ rl = *s++;
+ gh = *s++;
+ gl = *s++;
+ bh = *s++;
+ bl = *s++;
+
+ if (*s) {
+ if (!isxdigit(s[0])) goto invalid;
+ if (!isxdigit(s[1])) goto invalid;
+ if (s[2])
+ goto invalid;
+ ah = *s++;
+ al = *s++;
+ }
+
+ *redp = decode_hexbyte(rh, rl);
+ *greenp = decode_hexbyte(gh, gl);
+ *bluep = decode_hexbyte(bh, bl);
+ *alphap = decode_hexbyte(ah, al);
+ return;
+
+invalid:
+ fprintf(stderr, "%s: colours shall be encoded as rrggbb or rrggbbaa, in hexadecimal\n", argv0);
+ exit(1);
+}
+
+_LIBSKRIFT_GCC_ONLY(__attribute__((__pure__)))
+static uint16_t
+parse_uint16(const char *s)
+{
+ uint16_t ret, digit;
+ for (ret = 0; *s; s++) {
+ if (!isdigit(*s))
+ usage();
+ digit = (uint16_t)(*s & 15);
+ if (ret > (UINT16_MAX - digit) / 10)
+ usage();
+ ret *= 10;
+ ret += digit;
+ }
+ return ret;
+}
+
+_LIBSKRIFT_GCC_ONLY(__attribute__((__pure__)))
+static int16_t
+parse_int16(const char *s, const char **end)
+{
+ int16_t ret, digit;
+ int neg = 0;
+ if (*s == '+') {
+ s++;
+ } else if (*s == '-') {
+ neg = 1;
+ s++;
+ }
+ for (ret = 0; *s; s++) {
+ if (!isdigit(*s))
+ break;
+ digit = (int16_t)(*s & 15);
+ if (ret < (INT16_MIN + digit) / 10)
+ usage();
+ ret *= 10;
+ ret -= digit;
+ }
+ if (!neg)
+ ret = -ret;
+ *end = s;
+ return ret;
+}
+
+static void
+parse_transformation(char *s, double matrix[6])
+{
+#define S(T) T, n = (sizeof(T) - 1)
+#define S0(T) (n = (sizeof(T) - 1), T)
+
+ size_t n;
+ double f, x, y, m[6];
+
+ while (*s) {
+ if (*s == ',') {
+ s++;
+
+ } else if (!strncmp(s, S("rotate="))) {
+ s += n;
+ errno = 0;
+ f = strtod(s, &s);
+ if (errno)
+ goto invalid;
+ if (*s) {
+ if (s[0] == 'd' && s[1] == 'e' && s[2] == 'g') {
+ s += 3;
+ libskrift_add_rotation_degrees(matrix, f);
+ } else {
+ libskrift_add_rotation(matrix, f);
+ }
+ if (*s && *s != ',')
+ goto invalid;
+ }
+
+ } else if (!strncmp(s, S("shearx="))) {
+ s += n;
+ errno = 0;
+ f = strtod(s, &s);
+ if (errno || (*s && *s != ','))
+ goto invalid;
+ libskrift_add_shear(matrix, f, 0);
+
+ } else if (!strncmp(s, S("sheary="))) {
+ s += n;
+ errno = 0;
+ f = strtod(s, &s);
+ if (errno || (*s && *s != ','))
+ goto invalid;
+ libskrift_add_shear(matrix, 0, f);
+
+ } else if (!strncmp(s, S("shear="))) {
+ s += n;
+ errno = 0;
+ x = strtod(s, &s);
+ if (errno || *s != ':')
+ goto invalid;
+ y = strtod(&s[1], &s);
+ if (errno || (*s && *s != ','))
+ goto invalid;
+ libskrift_add_shear(matrix, x, y);
+
+ } else if (!strncmp(s, S("scalex="))) {
+ s += n;
+ errno = 0;
+ f = strtod(s, &s);
+ if (errno || (*s && *s != ','))
+ goto invalid;
+ libskrift_add_scaling(matrix, f, 1);
+
+ } else if (!strncmp(s, S("scaley="))) {
+ s += n;
+ errno = 0;
+ f = strtod(s, &s);
+ if (errno || (*s && *s != ','))
+ goto invalid;
+ libskrift_add_scaling(matrix, 1, f);
+
+ } else if (!strncmp(s, S("scale="))) {
+ s += n;
+ errno = 0;
+ x = strtod(s, &s);
+ if (errno)
+ goto invalid;
+ if (*s == ':') {
+ y = strtod(&s[1], &s);
+ if (errno || (*s && *s != ','))
+ goto invalid;
+ libskrift_add_scaling(matrix, x, y);
+ } else if (*s && *s != ',') {
+ goto invalid;
+ } else {
+ libskrift_add_scaling(matrix, x, x);
+ }
+
+ } else if (!strncmp(s, S("translate="))) {
+ s += n;
+ errno = 0;
+ x = strtod(s, &s);
+ if (errno || *s != ':')
+ goto invalid;
+ y = strtod(&s[1], &s);
+ if (errno || (*s && *s != ','))
+ goto invalid;
+ libskrift_add_translation(matrix, x, y);
+
+ } else if (!strncmp(s, S("transform="))) {
+ s += n;
+ errno = 0;
+ m[0] = strtod(s, &s);
+ if (errno || *s != ':')
+ goto invalid;
+ m[1] = strtod(&s[1], &s);
+ if (errno || *s != ':')
+ goto invalid;
+ m[2] = strtod(&s[1], &s);
+ if (errno || s[0] != ':' || s[1] != ':')
+ goto invalid;
+ m[3] = strtod(&s[2], &s);
+ if (errno || *s != ':')
+ goto invalid;
+ m[4] = strtod(&s[1], &s);
+ if (errno || *s != ':')
+ goto invalid;
+ m[5] = strtod(&s[1], &s);
+ if (errno || (*s && *s != ','))
+ goto invalid;
+ libskrift_add_transformation(matrix, m);
+
+ } else if (!strncmp(s, S("rotate90,")) || !strcmp(s, S0("rotate90"))) {
+ s += n;
+ libskrift_add_90_degree_rotation(matrix);
+
+ } else if (!strncmp(s, S("rotate180,")) || !strcmp(s, S0("rotate180"))) {
+ s += n;
+ libskrift_add_180_degree_rotation(matrix);
+
+ } else if (!strncmp(s, S("rotate270,")) || !strcmp(s, S0("rotate270"))) {
+ s += n;
+ libskrift_add_270_degree_rotation(matrix);
+
+ } else if (!strncmp(s, S("transpose,")) || !strcmp(s, S0("transpose"))) {
+ s += n;
+ libskrift_add_transposition(matrix);
+
+ } else {
+ invalid:
+ fprintf(stderr, "%s: valid transformations are:\n", argv0);
+ fprintf(stderr, "%s: rotate=<radians>\n", argv0);
+ fprintf(stderr, "%s: rotate=<degrees>deg\n", argv0);
+ fprintf(stderr, "%s: shearx=<value>\n", argv0);
+ fprintf(stderr, "%s: sheary=<value>\n", argv0);
+ fprintf(stderr, "%s: shear=<x-value>:<y-value>\n", argv0);
+ fprintf(stderr, "%s: scalex=<value>\n", argv0);
+ fprintf(stderr, "%s: scaley=<value>\n", argv0);
+ fprintf(stderr, "%s: scale=<value>\n", argv0);
+ fprintf(stderr, "%s: scale=<x-value>:<y-value>\n", argv0);
+ fprintf(stderr, "%s: translate=<x-value>:<y-value>\n", argv0);
+ fprintf(stderr, "%s: transform=<r1c1>:<r1c2>:<r1c3>::<r2c1>:<r2c2>:<r2c3>\n", argv0);
+ fprintf(stderr, "%s: rotate90\n", argv0);
+ fprintf(stderr, "%s: rotate180\n", argv0);
+ fprintf(stderr, "%s: rotate270\n", argv0);
+ fprintf(stderr, "%s: transpose\n", argv0);
+ exit(1);
+ }
+ }
+
+#undef S
+#undef S0
+}
+
int
-main(void)
+main(int argc, char *argv[])
{
LIBSKRIFT_FONT *font;
LIBSKRIFT_CONTEXT *ctx;
- struct libskrift_image image = {LIBSKRIFT_R8G8B8A8, LIBSKRIFT_HOST_SUBPIXEL, 0, 800, 600, NULL, NULL, NULL};
+ struct libskrift_image image = {LIBSKRIFT_R8G8B8A8, LIBSKRIFT_BE_SUBPIXEL, 0, 800, 600, NULL, NULL, NULL};
struct libskrift_rendering rendering = LIBSKRIFT_DEFAULT_RENDERING;
- struct libskrift_colour colour = LIBSKRIFT_PREMULTIPLY(.80f, .50f, .80f, .50f, .20f);
- double height;
+ struct libskrift_colour colour;
+ const char *font_file = DEMO_FONT;
+ double font_size = 72;
+ const char *font_size_unit = "pt";
+ const char *x_unit = "", *y_unit = "";
+ double height, opacity = .80f, xf, yf;
size_t size, i;
+ char *end, *arg;
+ const char *text = TEST_TEXT;
+ size_t text_length = sizeof(TEST_TEXT) - 1;
+ uint8_t background_red = 32U, foreground_red = 204U;
+ uint8_t background_green = 48U, foreground_green = 128U;
+ uint8_t background_blue = 64U, foreground_blue = 51U;
+ uint8_t background_alpha = 250U, foreground_alpha = 128U;
+ long int tmp_long;
+ int16_t x = 0, y = 300;
+
+ ARGBEGIN {
+ case 'b':
+ parse_colour(ARG(), &background_red, &background_green, &background_blue, &background_alpha);
+ break;
+
+ case 'f':
+ parse_colour(ARG(), &foreground_red, &foreground_green, &foreground_blue, &foreground_alpha);
+ break;
+
+ case 'F':
+ font_file = ARG();
+ break;
+
+ case 'a':
+ errno = 0;
+ opacity = strtod(ARG(), &end);
+ if (errno || *end)
+ usage();
+ break;
+
+ case 's':
+ errno = 0;
+ font_size = strtod(ARG(), &end);
+ if (errno)
+ usage();
+ font_size_unit = end;
+ break;
+
+ case 'S':
+ errno = 0;
+ arg = ARG();
+ if (!strncmp(arg, "monochrome", strlen("monochrome"))) {
+ arg += strlen("monochrome");
+ rendering.smoothing = LIBSKRIFT_MONOCHROME;
+ } else if (!strncmp(arg, "none", strlen("none"))) {
+ arg += strlen("none");
+ rendering.smoothing = LIBSKRIFT_NONE; /* = LIBSKRIFT_MONOCHROME */
+ } else if (!strncmp(arg, "greyscale", strlen("greyscale"))) {
+ arg += strlen("greyscale");
+ rendering.smoothing = LIBSKRIFT_GREYSCALE;
+ } else if (!strncmp(arg, "subpixel", strlen("subpixel"))) {
+ arg += strlen("subpixel");
+ rendering.smoothing = LIBSKRIFT_SUBPIXEL;
+ } else {
+ fprintf(stderr, "%s: valid smoothing methods are: 'monochrome', 'greyscale', 'subpixel'\n", argv0);
+ return 1;
+ }
+ if (!*arg) {
+ rendering.subpixel_order = LIBSKRIFT_RGB;
+ break;
+ }
+ if (*arg++ != ':')
+ usage();
+ if (!strcmp(arg, "other")) {
+ rendering.subpixel_order = LIBSKRIFT_OTHER;
+ } else if (!strcmp(arg, "none")) {
+ rendering.subpixel_order = LIBSKRIFT_NONE; /* = LIBSKRIFT_OTHER */
+ } else if (!strcmp(arg, "rgb")) {
+ rendering.subpixel_order = LIBSKRIFT_RGB;
+ } else if (!strcmp(arg, "bgr")) {
+ rendering.subpixel_order = LIBSKRIFT_BGR;
+ } else if (!strcmp(arg, "vrgb")) {
+ rendering.subpixel_order = LIBSKRIFT_VRGB;
+ } else if (!strcmp(arg, "vbgr")) {
+ rendering.subpixel_order = LIBSKRIFT_VBGR;
+ } else {
+ fprintf(stderr, "%s: valid subpixel orders are: 'other', 'rgb', 'bgr', 'vrgb', 'cbgr'\n", argv0);
+ return 1;
+ }
+ break;
+
+ case 'H':
+ arg = ARG();
+ if (!strcmp(arg, "none")) {
+ rendering.hinting = LIBSKRIFT_NONE;
+ } else if (!strcmp(arg, "unhinted")) {
+ rendering.hinting = LIBSKRIFT_UNHINTED; /* = LIBSKRIFT_NONE */
+ } else if (!strcmp(arg, "slight")) {
+ rendering.hinting = LIBSKRIFT_SLIGHT;
+ } else if (!strcmp(arg, "medium")) {
+ rendering.hinting = LIBSKRIFT_MEDIUM;
+ } else if (!strcmp(arg, "full")) {
+ rendering.hinting = LIBSKRIFT_FULL;
+ } else if (isdigit(*arg)) {
+ rendering.hinting = 0;
+ for (; isdigit(*arg); arg++) {
+ rendering.hinting *= 10;
+ rendering.hinting += *arg & 15;
+ }
+ if (*arg)
+ usage();
+ } else {
+ fprintf(stderr, "%s: valid hintings are: 'none', 'slight', 'medium', 'full', <integer>\n", argv0);
+ return 1;
+ }
+ break;
+
+ case 'D':
+ errno = 0;
+ rendering.horizontal_dpi = strtod(ARG(), &end);
+ if (errno)
+ usage();
+ if (!*end) {
+ rendering.vertical_dpi = rendering.horizontal_dpi;
+ } else if (*end != ':') {
+ usage();
+ } else {
+ rendering.vertical_dpi = strtod(&end[1], &end);
+ if (errno || *end)
+ usage();
+ }
+ break;
+
+ case 'w':
+ image.width = parse_uint16(ARG());
+ break;
+
+ case 'h':
+ image.height = parse_uint16(ARG());
+ break;
+
+ case 'x':
+ x = parse_int16(ARG(), &x_unit);
+ break;
+
+ case 'y':
+ y = parse_int16(ARG(), &y_unit);
+ break;
+
+ case 't':
+ parse_transformation(ARG(), rendering.char_transformation);
+ break;
+
+ case 'T':
+ parse_transformation(ARG(), rendering.text_transformation);
+ break;
+
+ case 'k':
+ errno = 0;
+ rendering.kerning = strtod(ARG(), &end);
+ if (errno || *end)
+ usage();
+ break;
+
+ case 'i':
+ errno = 0;
+ rendering.interletter_spacing = strtod(ARG(), &end);
+ if (errno || *end)
+ usage();
+ break;
+
+ case 'g':
+ errno = 0;
+ tmp_long = strtol(ARG(), &end, 10);
+ rendering.grid_fineness = (int)tmp_long;
+ if (errno || *end || tmp_long < INT_MIN || tmp_long > INT_MAX)
+ usage();
+ break;
+
+ case 'o':
+ arg = ARG();
+ while (*arg) {
+ if (*arg == ',') {
+ arg++;
+ continue;
+ }
+#define TEST(T) strncmp(arg, T, sizeof(T) - 1) ? 0 : (arg += sizeof(T) - 1, 1)
+ if (TEST("remove-gamma")) {
+ rendering.flags |= LIBSKRIFT_REMOVE_GAMMA;
+ } else if (TEST("y-increases-upwards")) {
+ rendering.flags |= LIBSKRIFT_Y_INCREASES_UPWARDS;
+ } else if (TEST("flip-text")) {
+ rendering.flags ^= LIBSKRIFT_FLIP_TEXT;
+ } else if (TEST("flip-chars")) {
+ rendering.flags ^= LIBSKRIFT_FLIP_CHARS;
+ } else if (TEST("mirror-text")) {
+ rendering.flags ^= LIBSKRIFT_MIRROR_TEXT;
+ } else if (TEST("mirror-chars")) {
+ rendering.flags ^= LIBSKRIFT_MIRROR_CHARS;
+ } else if (TEST("transpose-text")) {
+ rendering.flags ^= LIBSKRIFT_TRANSPOSE_TEXT;
+ } else if (TEST("transpose-chars")) {
+ rendering.flags ^= LIBSKRIFT_TRANSPOSE_CHARS;
+ } else if (TEST("no-ligatures")) {
+ rendering.flags |= LIBSKRIFT_NO_LIGATURES;
+ } else if (TEST("advance-char-to-grid")) {
+ rendering.flags |= LIBSKRIFT_ADVANCE_CHAR_TO_GRID;
+ } else if (TEST("regress-char-to-grid")) {
+ rendering.flags |= LIBSKRIFT_REGRESS_CHAR_TO_GRID;
+ } else if (TEST("advance-word-to-grid")) {
+ rendering.flags |= LIBSKRIFT_ADVANCE_WORD_TO_GRID;
+ } else if (TEST("regress-word-to-grid")) {
+ rendering.flags |= LIBSKRIFT_REGRESS_WORD_TO_GRID;
+ } else if (TEST("use-subpixel-grid")) {
+ rendering.flags |= LIBSKRIFT_USE_SUBPIXEL_GRID;
+ } else if (TEST("vertical-text")) {
+ rendering.flags |= LIBSKRIFT_VERTICAL_TEXT;
+ } else if (TEST("autohinting")) {
+ rendering.flags |= LIBSKRIFT_AUTOHINTING;
+ } else if (TEST("no-autohinting")) {
+ rendering.flags |= LIBSKRIFT_NO_AUTOHINTING;
+ } else if (TEST("autokerning")) {
+ rendering.flags |= LIBSKRIFT_AUTOKERNING;
+ } else if (TEST("no-autokerning")) {
+ rendering.flags |= LIBSKRIFT_NO_AUTOKERNING;
+ } else if (TEST("ignore-ignorable")) {
+ rendering.flags |= LIBSKRIFT_IGNORE_IGNORABLE;
+ } else {
+ invalid_flag:
+ fprintf(stderr, "%s: valid flags are:\n", argv0);
+ fprintf(stderr, "%s: remove-gamma\n", argv0);
+ fprintf(stderr, "%s: y-increases-upwards\n", argv0);
+ fprintf(stderr, "%s: flip-text\n", argv0);
+ fprintf(stderr, "%s: flip-chars\n", argv0);
+ fprintf(stderr, "%s: mirror-text\n", argv0);
+ fprintf(stderr, "%s: mirror-chars\n", argv0);
+ fprintf(stderr, "%s: transpose-text\n", argv0);
+ fprintf(stderr, "%s: transpose-chars\n", argv0);
+ fprintf(stderr, "%s: no-ligatures\n", argv0);
+ fprintf(stderr, "%s: advance-char-to-grid\n", argv0);
+ fprintf(stderr, "%s: regress-char-to-grid\n", argv0);
+ fprintf(stderr, "%s: advance-word-to-grid\n", argv0);
+ fprintf(stderr, "%s: regress-word-to-grid\n", argv0);
+ fprintf(stderr, "%s: use-subpixel-grid\n", argv0);
+ fprintf(stderr, "%s: vertical-text\n", argv0);
+ fprintf(stderr, "%s: autohinting\n", argv0);
+ fprintf(stderr, "%s: no-autohinting\n", argv0);
+ fprintf(stderr, "%s: autokerning\n", argv0);
+ fprintf(stderr, "%s: no-autokerning\n", argv0);
+ fprintf(stderr, "%s: ignore-ignorable\n", argv0);
+ return 1;
+ }
+#undef TEST
+ if (*arg && *arg != ',')
+ goto invalid_flag;
+ }
+ break;
+
+ default:
+ usage();
+ } ARGEND;
+
+ colour = (struct libskrift_colour)LIBSKRIFT_PREMULTIPLY((float)opacity,
+ (float)foreground_alpha / 255,
+ (float)foreground_red / 255,
+ (float)foreground_green / 255,
+ (float)foreground_blue / 255);
+
+ if (argc > 1)
+ usage();
+
+ if (argc == 1) {
+ text = argv[0];
+ text_length = strlen(text);
+ }
if (isatty(STDOUT_FILENO)) {
fprintf(stderr, "Output file is a binary PAM image file, I am not writing that to a terminal.\n");
return 1;
}
- rendering.smoothing = LIBSKRIFT_SUBPIXEL;
- rendering.subpixel_order = LIBSKRIFT_NONE;
- rendering.flags = LIBSKRIFT_MIRROR_CHARS | LIBSKRIFT_MIRROR_TEXT;
- rendering.interletter_spacing = 2;
-
- if (libskrift_open_font_file(&font, DEMO_FONT)) {
+ if (libskrift_open_font_file(&font, font_file)) {
perror("libskrift_open_font_file");
- return -1;
+ return 1;
+ }
+ if (!strcmp(font_size_unit, "pt")) {
+ height = libskrift_points_to_pixels(font_size, &rendering);
+ } else if (!strcmp(font_size_unit, "px")) {
+ height = font_size;
+ } else if (!strcmp(font_size_unit, "in")) {
+ height = libskrift_inches_to_pixels(font_size, &rendering);
+ } else if (!strcmp(font_size_unit, "mm")) {
+ height = libskrift_millimeters_to_pixels(font_size, &rendering);
+ } else if (!strcmp(font_size_unit, "cm")) {
+ height = libskrift_millimeters_to_pixels(font_size * 10, &rendering);
+ } else {
+ fprintf(stderr, "%s: valid font size units are: 'pt', 'px', 'in', 'mm', 'cm'", argv0);
+ return 1;
}
- libskrift_add_rotation_degrees(rendering.text_transformation, -10);
- libskrift_add_shear(rendering.char_transformation, .75f, 0);
- height = libskrift_points_to_pixels(72, &rendering);
if (libskrift_create_context(&ctx, &font, 1, height, &rendering, NULL)) {
perror("libskrift_create_context");
- return -1;
+ return 1;
}
libskrift_close_font(font);
+ if (*x_unit && strcmp(x_unit, "px")) {
+ xf = (double)x;
+ if (!strcmp(x_unit, "pt")) {
+ xf = (int16_t)libskrift_points_to_pixels(xf, &rendering);
+ } else if (!strcmp(x_unit, "in")) {
+ xf = (int16_t)libskrift_inches_to_pixels(xf, &rendering);
+ } else if (!strcmp(x_unit, "mm")) {
+ xf = (int16_t)libskrift_millimeters_to_pixels(xf, &rendering);
+ } else if (!strcmp(x_unit, "cm")) {
+ xf = (int16_t)libskrift_millimeters_to_pixels(xf * 10, &rendering);
+ } else {
+ fprintf(stderr, "%s: valid position units are: 'pt', 'px', 'in', 'mm', 'cm'", argv0);
+ return 1;
+ }
+ x = (int16_t)xf;
+ }
+
+ if (*y_unit && strcmp(y_unit, "px")) {
+ yf = (double)y;
+ if (!strcmp(y_unit, "pt")) {
+ yf = libskrift_points_to_pixels(yf, &rendering);
+ } else if (!strcmp(y_unit, "in")) {
+ yf = libskrift_inches_to_pixels(yf, &rendering);
+ } else if (!strcmp(y_unit, "mm")) {
+ yf = libskrift_millimeters_to_pixels(yf, &rendering);
+ } else if (!strcmp(y_unit, "cm")) {
+ yf = libskrift_millimeters_to_pixels(yf * 10, &rendering);
+ } else {
+ fprintf(stderr, "%s: valid position units are: 'pt', 'px', 'in', 'mm', 'cm'", argv0);
+ return 1;
+ }
+ y = (int16_t)yf;
+ }
+
size = 4;
size *= (size_t)image.width;
size *= (size_t)image.height;
- image.image = malloc(size);
- if (!image.image) {
- perror("malloc");
- return -1;
+ if (size) {
+ image.image = malloc(size);
+ if (!image.image) {
+ perror("malloc");
+ return 1;
+ }
}
for (i = 0; i < size; i += 4) {
- ((uint8_t *)image.image)[i + 0] = 32U;
- ((uint8_t *)image.image)[i + 1] = 48U;
- ((uint8_t *)image.image)[i + 2] = 64U;
- ((uint8_t *)image.image)[i + 3] = 250U;
+ ((uint8_t *)image.image)[i + 0] = background_red;
+ ((uint8_t *)image.image)[i + 1] = background_green;
+ ((uint8_t *)image.image)[i + 2] = background_blue;
+ ((uint8_t *)image.image)[i + 3] = background_alpha;
}
- if (libskrift_draw_text(ctx, TEST_TEXT, sizeof(TEST_TEXT) - 1, &colour, 0, 300, &image) < 0) {
+ if (libskrift_draw_text(ctx, text, text_length, &colour, x, y, &image) < 0) {
perror("libskrift_draw_text");
- return -1;
+ return 1;
}
printf("P7\n");
diff --git a/libskrift.h b/libskrift.h
index fc99142..4873d7d 100644
--- a/libskrift.h
+++ b/libskrift.h
@@ -145,7 +145,7 @@ struct libskrift_saved_grapheme {
size_t len;
};
-struct libskrift_image {
+struct libskrift_image { /* TODO need horizontal blanking */
enum libskrift_format format;
enum libskrift_endian endian;
int premultiplied;
diff --git a/libskrift_inches_to_pixels.c b/libskrift_inches_to_pixels.c
index 3901175..531a775 100644
--- a/libskrift_inches_to_pixels.c
+++ b/libskrift_inches_to_pixels.c
@@ -1,4 +1,4 @@
/* See LICENSE file for copyright and license details. */
#include "common.h"
-extern inline double libskrift_points_to_pixels(double points, const struct libskrift_rendering *rendering);
+extern inline double libskrift_inches_to_pixels(double inches, const struct libskrift_rendering *rendering);
diff --git a/libskrift_millimeters_to_pixels.c b/libskrift_millimeters_to_pixels.c
index 531a775..0c40276 100644
--- a/libskrift_millimeters_to_pixels.c
+++ b/libskrift_millimeters_to_pixels.c
@@ -1,4 +1,4 @@
/* See LICENSE file for copyright and license details. */
#include "common.h"
-extern inline double libskrift_inches_to_pixels(double inches, const struct libskrift_rendering *rendering);
+extern inline double libskrift_millimeters_to_pixels(double millimeters, const struct libskrift_rendering *rendering);