From a5fe9dab3f68668e3bc31326447139b7446edbc7 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Thu, 5 Aug 2021 20:53:28 +0200 Subject: Improvements for character transformations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- common.h | 6 ++- demo.c | 107 +++++++++++++++++++++-------------------- libskrift_create_context.c | 12 +++-- libskrift_draw_text.c | 8 +-- libskrift_get_cluster_glyph.c | 6 ++- libskrift_get_grapheme_glyph.c | 2 +- 6 files changed, 78 insertions(+), 63 deletions(-) diff --git a/common.h b/common.h index 787ec68..d8c4a56 100644 --- a/common.h +++ b/common.h @@ -36,8 +36,10 @@ struct libskrift_context { char subpixel_horizontally; char subpixel_vertically; char subpixel_bgr; - double x_advancement; - double y_advancement; + double char_x_advancement; + double char_y_advancement; + double text_x_advancement; + double text_y_advancement; double transformation[6]; size_t nfonts; LIBSKRIFT_FONT *fonts[]; diff --git a/demo.c b/demo.c index c1a6488..e7d4eec 100644 --- a/demo.c +++ b/demo.c @@ -19,6 +19,7 @@ USAGE("[-b background-colour] [-f foreground-colour] [-a opacity] [-t character- "[-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) { @@ -28,6 +29,7 @@ decode_hexbyte(char hi, char lo) return (uint8_t)ret; } + static void parse_colour(const char *s, uint8_t *redp, uint8_t *greenp, uint8_t *bluep, uint8_t *alphap) { @@ -67,6 +69,7 @@ invalid: exit(1); } + _LIBSKRIFT_GCC_ONLY(__attribute__((__pure__))) static uint16_t parse_uint16(const char *s) @@ -84,6 +87,7 @@ parse_uint16(const char *s) return ret; } + _LIBSKRIFT_GCC_ONLY(__attribute__((__pure__))) static int16_t parse_int16(const char *s, const char **end) @@ -111,6 +115,7 @@ parse_int16(const char *s, const char **end) return ret; } + static void parse_transformation(char *s, double matrix[6]) { @@ -277,6 +282,26 @@ parse_transformation(char *s, double matrix[6]) #undef S0 } + +static double +apply_unit(double size, const char *unit, const struct libskrift_rendering *rendering, const char *unit_for) +{ + if (!strcmp(unit, "px")) + return size; + if (!strcmp(unit, "pt")) + return libskrift_points_to_pixels(size, rendering); + if (!strcmp(unit, "in")) + return libskrift_inches_to_pixels(size, rendering); + if (!strcmp(unit, "mm")) + return libskrift_millimeters_to_pixels(size, rendering); + if (!strcmp(unit, "cm")) + return libskrift_millimeters_to_pixels(size * 10, rendering); + + fprintf(stderr, "%s: valid %s units are: 'px', 'pt', 'in', 'mm', 'cm'", argv0, unit_for); + exit(1); +} + + int main(int argc, char *argv[]) { @@ -289,7 +314,8 @@ main(int argc, char *argv[]) double font_size = 72; const char *font_size_unit = "pt"; const char *x_unit = "", *y_unit = ""; - double height, opacity = .80f, xf, yf; + const char *kerning_unit = "", *interletter_spacing_unit = ""; + double height, opacity = .80f, f; size_t size, i; char *end, *arg; const char *text = TEST_TEXT; @@ -441,15 +467,17 @@ main(int argc, char *argv[]) case 'k': errno = 0; rendering.kerning = strtod(ARG(), &end); - if (errno || *end) + if (errno) usage(); + kerning_unit = end; break; case 'i': errno = 0; rendering.interletter_spacing = strtod(ARG(), &end); - if (errno || *end) + if (errno) usage(); + interletter_spacing_unit = end; break; case 'g': @@ -562,64 +590,41 @@ main(int argc, char *argv[]) return 1; } + if (*x_unit && strcmp(x_unit, "px")) { + f = (double)x; + f = apply_unit(f, x_unit, &rendering, "position"); + x = (int16_t)f; + } + + if (*y_unit && strcmp(y_unit, "px")) { + f = (double)y; + f = apply_unit(f, y_unit, &rendering, "position"); + y = (int16_t)f; + } + + if (*kerning_unit && strcmp(kerning_unit, "px")) { + f = rendering.kerning; + f = apply_unit(f, kerning_unit, &rendering, "spacing"); + rendering.kerning = f; + } + + if (*interletter_spacing_unit && strcmp(interletter_spacing_unit, "px")) { + f = rendering.interletter_spacing; + f = apply_unit(f, interletter_spacing_unit, &rendering, "spacing"); + rendering.interletter_spacing = f; + } + if (libskrift_open_font_file(&font, font_file)) { perror("libskrift_open_font_file"); 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; - } + height = apply_unit(font_size, font_size_unit, &rendering, "font size"); if (libskrift_create_context(&ctx, &font, 1, height, &rendering, NULL)) { perror("libskrift_create_context"); 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; diff --git a/libskrift_create_context.c b/libskrift_create_context.c index db6f8a4..a1d01e0 100644 --- a/libskrift_create_context.c +++ b/libskrift_create_context.c @@ -77,8 +77,10 @@ libskrift_create_context(LIBSKRIFT_CONTEXT **ctxp, LIBSKRIFT_FONT **fonts, size_ (*ctxp)->schrift_ctx.font = fonts[0]->font; (*ctxp)->schrift_ctx.yScale = height; - (*ctxp)->x_advancement = 1; - (*ctxp)->y_advancement = 0; + (*ctxp)->char_x_advancement = 1; + (*ctxp)->char_y_advancement = 0; + (*ctxp)->text_x_advancement = 1; + (*ctxp)->text_y_advancement = 0; (*ctxp)->nfonts = nfonts; for (i = 0; i < nfonts; i++) { (*ctxp)->fonts[i] = fonts[i]; @@ -126,8 +128,10 @@ libskrift_create_context(LIBSKRIFT_CONTEXT **ctxp, LIBSKRIFT_FONT **fonts, size_ fpclassify((*ctxp)->rendering.text_transformation[5]) != FP_ZERO) { memcpy((*ctxp)->transformation, (*ctxp)->rendering.char_transformation, sizeof((*ctxp)->transformation)); libskrift_add_transformation((*ctxp)->transformation, (*ctxp)->rendering.text_transformation); - (*ctxp)->x_advancement = (*ctxp)->rendering.text_transformation[0]; - (*ctxp)->y_advancement = (*ctxp)->rendering.text_transformation[3]; + (*ctxp)->char_x_advancement = (*ctxp)->rendering.char_transformation[0]; + (*ctxp)->char_y_advancement = (*ctxp)->rendering.char_transformation[3]; + (*ctxp)->text_x_advancement = (*ctxp)->rendering.text_transformation[0]; + (*ctxp)->text_y_advancement = (*ctxp)->rendering.text_transformation[3]; (*ctxp)->schrift_ctx.transformation_hook = transformation_hook; } diff --git a/libskrift_draw_text.c b/libskrift_draw_text.c index 75645ba..e827159 100644 --- a/libskrift_draw_text.c +++ b/libskrift_draw_text.c @@ -18,7 +18,7 @@ libskrift_draw_text(LIBSKRIFT_CONTEXT *ctx, const char *text, size_t text_length struct libskrift_saved_grapheme saved = LIBSKRIFT_NO_SAVED_GRAPHEME; struct libskrift_glyph *glyph; char *buffer = NULL; - double xpos = 0, ypos = 0; + double xpos = 0, ypos = 0, advance; ssize_t len; int r; @@ -44,8 +44,10 @@ libskrift_draw_text(LIBSKRIFT_CONTEXT *ctx, const char *text, size_t text_length } r = libskrift_apply_glyph(ctx, glyph, colour, x, y, image); - xpos += (glyph->advance + ctx->rendering.interletter_spacing) * ctx->x_advancement; - ypos += (glyph->advance + ctx->rendering.interletter_spacing) * ctx->y_advancement; + advance = glyph->advance * ctx->char_x_advancement; + advance += ctx->rendering.interletter_spacing; + xpos += advance * ctx->text_x_advancement; + ypos += advance * ctx->text_y_advancement; free(glyph); if (r) { free(buffer); diff --git a/libskrift_get_cluster_glyph.c b/libskrift_get_cluster_glyph.c index fbc3a18..6b3abaa 100644 --- a/libskrift_get_cluster_glyph.c +++ b/libskrift_get_cluster_glyph.c @@ -29,7 +29,8 @@ libskrift_get_cluster_glyph(LIBSKRIFT_CONTEXT *ctx, const char *text, size_t tex if (libskrift_get_grapheme_glyph(ctx, cp0, x, y, &glyph0)) return -1; - x += glyph0->advance; + x += glyph0->advance * ctx->char_x_advancement; + y += glyph0->advance * ctx->char_y_advancement; for (; len < text_length; cp0 = cp1, len += r) { r = grapheme_cp_decode(&cp1, (const void *)&text[len], text_length - len); if (grapheme_boundary(cp0, cp1, &state)) { @@ -45,7 +46,8 @@ libskrift_get_cluster_glyph(LIBSKRIFT_CONTEXT *ctx, const char *text, size_t tex free(glyph0); return -1; } - x += glyph1->advance; + x += glyph1->advance * ctx->char_x_advancement; + y += glyph1->advance * ctx->char_y_advancement; if (libskrift_merge_glyphs(ctx, glyph0, glyph1, &glyph2)) { free(glyph0); diff --git a/libskrift_get_grapheme_glyph.c b/libskrift_get_grapheme_glyph.c index fa7a8c5..515e81d 100644 --- a/libskrift_get_grapheme_glyph.c +++ b/libskrift_get_grapheme_glyph.c @@ -38,7 +38,7 @@ libskrift_get_grapheme_glyph(LIBSKRIFT_CONTEXT *ctx, libskrift_codepoint_t codep height = (uint16_t)(sft_chr.height + top + bottom) / vmul; size *= (size_t)width * (size_t)height; - *glyphp = malloc(offsetof(struct libskrift_glyph, image) + size); + *glyphp = malloc(FLEXSTRUCTSIZE(struct libskrift_glyph, image, size)); if (!*glyphp) { free(sft_chr.image); return -1; -- cgit v1.2.3-70-g09d2