diff options
-rw-r--r-- | LICENSE | 2 | ||||
-rw-r--r-- | README | 6 | ||||
-rw-r--r-- | common.h | 3 | ||||
-rw-r--r-- | demo.c | 2 | ||||
-rw-r--r-- | libskrift.h | 11 | ||||
-rw-r--r-- | libskrift_apply_glyph.c | 2 | ||||
-rw-r--r-- | libskrift_create_context.c | 32 | ||||
-rw-r--r-- | libskrift_draw_text.c | 29 | ||||
-rw-r--r-- | libskrift_format_settings.c | 1 | ||||
-rw-r--r-- | libskrift_get_cluster_glyph.c | 37 | ||||
-rw-r--r-- | libskrift_merge_glyphs.c | 4 | ||||
-rw-r--r-- | libskrift_open_font.c | 4 | ||||
-rw-r--r-- | libskrift_open_font_at.c | 4 | ||||
-rw-r--r-- | libskrift_open_font_fd.c | 3 |
14 files changed, 74 insertions, 66 deletions
@@ -1,6 +1,6 @@ ISC License -© 2020 Mattias Andrée <maandree@kth.se> +© 2020, 2021 Mattias Andrée <maandree@kth.se> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -13,7 +13,7 @@ Currently implemented: Subpixel rendering (RGB, BGR, both horizontal and vertical). DPI support. (Points, inches, and millimeters can be - exactly converted pixels.) + exactly converted to pixels.) (Both horizonal and vertical resolution can be specified.) Drawing coloured text with 3 primaries, alpha and opacity, @@ -78,7 +78,7 @@ Things that require new features in libschrift Out of scope: - Bidirection text. + Bidirectional text. Text justification. @@ -89,3 +89,5 @@ Out of scope: Underline, overline, strike-thought, ... Superscript and subscript. + + Mathematical formulae formating. @@ -19,6 +19,9 @@ #define LEN(ARR) (sizeof(ARR) / sizeof(*(ARR))) +#define FLEXSTRUCTSIZE(STRUCT, FLEXARRAY, FLEXARRAY_LENGTH)\ + (offsetof(STRUCT, FLEXARRAY) + (FLEXARRAY_LENGTH) * sizeof(*((STRUCT *)NULL)->FLEXARRAY)) + struct libskrift_font { SFT_Font *font; void *memory_free; @@ -54,7 +54,7 @@ main(void) ((uint8_t *)image.image)[i + 3] = 250U; } - if (libskrift_draw_text(ctx, "hello world", &colour, 0, 300, &image) < 0) { + if (libskrift_draw_text(ctx, "hello world", strlen("hello world"), &colour, 0, 300, &image) < 0) { perror("libskrift_draw_text"); return -1; } diff --git a/libskrift.h b/libskrift.h index d587294..fc99142 100644 --- a/libskrift.h +++ b/libskrift.h @@ -140,6 +140,7 @@ struct libskrift_glyph { }; struct libskrift_saved_grapheme { + int have_saved; libskrift_codepoint_t cp; size_t len; }; @@ -185,7 +186,7 @@ struct libskrift_colour { .text_transformation = {1, 0, 0, 0, 1, 0},\ } -#define LIBSKRIFT_NO_SAVED_GRAPHEME {0, 0} +#define LIBSKRIFT_NO_SAVED_GRAPHEME {0, 0, 0} #define LIBSKRIFT_PREMULTIPLY(OPACITY, ALPHA, RED, GREEN, BLUE)\ {(OPACITY),\ @@ -254,8 +255,8 @@ const struct libskrift_rendering *libskrift_get_rendering_settings(LIBSKRIFT_CON _LIBSKRIFT_GCC_ONLY(__attribute__((__nonnull__))) int libskrift_get_grapheme_glyph(LIBSKRIFT_CONTEXT *, libskrift_codepoint_t, double, double, struct libskrift_glyph **); -_LIBSKRIFT_GCC_ONLY(__attribute__((__nonnull__(1, 2, 6)))) -ssize_t libskrift_get_cluster_glyph(LIBSKRIFT_CONTEXT *, const char *, struct libskrift_saved_grapheme *, +_LIBSKRIFT_GCC_ONLY(__attribute__((__nonnull__(1, 2, 7)))) +ssize_t libskrift_get_cluster_glyph(LIBSKRIFT_CONTEXT *, const char *, size_t, struct libskrift_saved_grapheme *, double, double, struct libskrift_glyph **); _LIBSKRIFT_GCC_ONLY(__attribute__((__nonnull__))) @@ -266,8 +267,8 @@ _LIBSKRIFT_GCC_ONLY(__attribute__((__nonnull__(1, 2, 6)))) int libskrift_apply_glyph(LIBSKRIFT_CONTEXT *, const struct libskrift_glyph *, const struct libskrift_colour *, int16_t, int16_t, struct libskrift_image *); -_LIBSKRIFT_GCC_ONLY(__attribute__((__nonnull__(1, 2, 6)))) -int libskrift_draw_text(LIBSKRIFT_CONTEXT *, const char *, const struct libskrift_colour *, +_LIBSKRIFT_GCC_ONLY(__attribute__((__nonnull__(1, 2, 7)))) +int libskrift_draw_text(LIBSKRIFT_CONTEXT *, const char *, size_t, const struct libskrift_colour *, int16_t, int16_t, struct libskrift_image *); diff --git a/libskrift_apply_glyph.c b/libskrift_apply_glyph.c index 85e4bd2..3fc3fc5 100644 --- a/libskrift_apply_glyph.c +++ b/libskrift_apply_glyph.c @@ -95,7 +95,7 @@ libskrift_apply_glyph(LIBSKRIFT_CONTEXT *ctx, const struct libskrift_glyph *glyp startc = (uint16_t)((int16_t)x1 - sx1); startr = (uint16_t)((int16_t)y1 - sy1); - /* Post-last pixel in glyph to draw*/ + /* Post-last pixel in glyph to draw */ endc = (uint16_t)((int16_t)x2 - sx1); endr = (uint16_t)((int16_t)y2 - sy1); diff --git a/libskrift_create_context.c b/libskrift_create_context.c index 18cf961..db6f8a4 100644 --- a/libskrift_create_context.c +++ b/libskrift_create_context.c @@ -71,7 +71,7 @@ libskrift_create_context(LIBSKRIFT_CONTEXT **ctxp, LIBSKRIFT_FONT **fonts, size_ } } - *ctxp = calloc(1, offsetof(LIBSKRIFT_CONTEXT, fonts) + nfonts * sizeof(*(*ctxp)->fonts)); + *ctxp = calloc(1, FLEXSTRUCTSIZE(LIBSKRIFT_CONTEXT, fonts, nfonts)); if (!*ctxp) return -1; @@ -97,13 +97,13 @@ libskrift_create_context(LIBSKRIFT_CONTEXT **ctxp, LIBSKRIFT_FONT **fonts, size_ memcpy(&(*ctxp)->rendering, &default_rendering, sizeof(default_rendering)); } - (*ctxp)->rendering.struct_version = LIBSKRIFT_RENDERING_STRUCT_VERSION; - (*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.struct_version = LIBSKRIFT_RENDERING_STRUCT_VERSION; + (*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; if (!(*ctxp)->rendering.smoothing) (*ctxp)->rendering.smoothing = LIBSKRIFT_GREYSCALE; @@ -113,17 +113,17 @@ libskrift_create_context(LIBSKRIFT_CONTEXT **ctxp, LIBSKRIFT_FONT **fonts, size_ (*ctxp)->schrift_ctx.hook_data = (*ctxp); 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 || + fpclassify((*ctxp)->rendering.char_transformation[1]) != FP_ZERO || + fpclassify((*ctxp)->rendering.char_transformation[2]) != FP_ZERO || + fpclassify((*ctxp)->rendering.char_transformation[3]) != FP_ZERO || fpclassify((*ctxp)->rendering.char_transformation[4] - 1) != FP_ZERO || - fpclassify((*ctxp)->rendering.char_transformation[5]) != FP_ZERO || + fpclassify((*ctxp)->rendering.char_transformation[5]) != FP_ZERO || fpclassify((*ctxp)->rendering.text_transformation[0] - 1) != FP_ZERO || - fpclassify((*ctxp)->rendering.text_transformation[1]) != FP_ZERO || - fpclassify((*ctxp)->rendering.text_transformation[2]) != FP_ZERO || - fpclassify((*ctxp)->rendering.text_transformation[3]) != FP_ZERO || + fpclassify((*ctxp)->rendering.text_transformation[1]) != FP_ZERO || + fpclassify((*ctxp)->rendering.text_transformation[2]) != FP_ZERO || + fpclassify((*ctxp)->rendering.text_transformation[3]) != FP_ZERO || fpclassify((*ctxp)->rendering.text_transformation[4] - 1) != FP_ZERO || - fpclassify((*ctxp)->rendering.text_transformation[5]) != FP_ZERO) { + 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]; diff --git a/libskrift_draw_text.c b/libskrift_draw_text.c index 356468d..75645ba 100644 --- a/libskrift_draw_text.c +++ b/libskrift_draw_text.c @@ -2,45 +2,42 @@ #include "common.h" static void -reverse_text(const char *restrict text, char *restrict s, size_t off) +reverse_text(const char *restrict text, size_t text_length, char *restrict s) { - size_t n; - s[off] = '\0'; - for (; *text; text += n) { - off -= n = grapheme_len(text); + size_t n, off = text_length; + for (; text_length; text += n, text_length -= n) { + off -= n = grapheme_bytelen(text); memcpy(&s[off], text, n); } } int -libskrift_draw_text(LIBSKRIFT_CONTEXT *ctx, const char *text, const struct libskrift_colour *colour, - int16_t x, int16_t y, struct libskrift_image *image) +libskrift_draw_text(LIBSKRIFT_CONTEXT *ctx, const char *text, size_t text_length, + const struct libskrift_colour *colour, int16_t x, int16_t y, struct libskrift_image *image) { struct libskrift_saved_grapheme saved = LIBSKRIFT_NO_SAVED_GRAPHEME; struct libskrift_glyph *glyph; char *buffer = NULL; double xpos = 0, ypos = 0; ssize_t len; - size_t n; int r; if (ctx->rendering.flags & LIBSKRIFT_MIRROR_TEXT) { - n = strlen(text); - if (n < 1024) { - buffer = alloca(n + 1); + if (text_length < 1024) { + buffer = alloca(text_length + 1); } else { - buffer = malloc(n + 1); + buffer = malloc(text_length + 1); if (!buffer) return -1; } - reverse_text(text, buffer, n); + reverse_text(text, text_length, buffer); text = buffer; - if (n < 1024) + if (text_length < 1024) buffer = NULL; } - for (; *text; text += len) { - len = libskrift_get_cluster_glyph(ctx, text, &saved, xpos, ypos, &glyph); + for (; text_length; text += len, text_length -= (size_t)len) { + len = libskrift_get_cluster_glyph(ctx, text, text_length, &saved, xpos, ypos, &glyph); if (len < 0) { free(buffer); return -1; diff --git a/libskrift_format_settings.c b/libskrift_format_settings.c index aaa8255..fba2eed 100644 --- a/libskrift_format_settings.c +++ b/libskrift_format_settings.c @@ -32,5 +32,4 @@ const struct format_settings libskrift_format_settings[] = { [LIBSKRIFT_RGB_LONG_DOUBLE] = {3, RGB, sizeof(long double)}, [LIBSKRIFT_ARGB_LONG_DOUBLE] = {3, ARGB, sizeof(long double)}, [LIBSKRIFT_RGBA_LONG_DOUBLE] = {3, RGBA, sizeof(long double)} - /* REMEMBER that element count is specified in common.h */ }; diff --git a/libskrift_get_cluster_glyph.c b/libskrift_get_cluster_glyph.c index e8d5724..fbc3a18 100644 --- a/libskrift_get_cluster_glyph.c +++ b/libskrift_get_cluster_glyph.c @@ -4,8 +4,8 @@ /* TODO try normalisation if not found, then try fallback fonts */ ssize_t -libskrift_get_cluster_glyph(LIBSKRIFT_CONTEXT *ctx, const char *text, struct libskrift_saved_grapheme *saved, - double x, double y, struct libskrift_glyph **glyphp) +libskrift_get_cluster_glyph(LIBSKRIFT_CONTEXT *ctx, const char *text, size_t text_length, + struct libskrift_saved_grapheme *saved, double x, double y, struct libskrift_glyph **glyphp) { struct libskrift_glyph *glyph0, *glyph1, *glyph2; uint32_t cp0, cp1; @@ -14,36 +14,31 @@ libskrift_get_cluster_glyph(LIBSKRIFT_CONTEXT *ctx, const char *text, struct lib *glyphp = NULL; - if (saved && saved->cp) { + if (!text_length) { + errno = EINVAL; + return -1; + } + + if (saved && saved->have_saved) { cp0 = saved->cp; len = saved->len; } else { - len = grapheme_decode(text, &cp0); - if (!len) { - errno = EINVAL; - return -1; - } + len = grapheme_cp_decode(&cp0, (const void *)text, text_length); } if (libskrift_get_grapheme_glyph(ctx, cp0, x, y, &glyph0)) return -1; x += glyph0->advance; - for (; cp0; cp0 = cp1, len += r) { - r = grapheme_decode(&text[len], &cp1); - if (!r) { - if (saved) { - saved->cp = 0; - saved->len = 0; - } - break; - } + 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)) { if (saved) { + saved->have_saved = 1; saved->cp = cp1; saved->len = r; } - break; + goto out; } if (libskrift_get_grapheme_glyph(ctx, cp1, x, y, &glyph1)) { @@ -62,7 +57,13 @@ libskrift_get_cluster_glyph(LIBSKRIFT_CONTEXT *ctx, const char *text, struct lib free(glyph1); glyph0 = glyph2; } + if (saved) { + saved->have_saved = 0; + saved->cp = 0; + saved->len = 0; + } +out: *glyphp = glyph0; return (ssize_t)len; diff --git a/libskrift_merge_glyphs.c b/libskrift_merge_glyphs.c index 4df6f7a..820d0d4 100644 --- a/libskrift_merge_glyphs.c +++ b/libskrift_merge_glyphs.c @@ -20,7 +20,7 @@ libskrift_merge_glyphs(LIBSKRIFT_CONTEXT *ctx, const struct libskrift_glyph *gly glyph2 = t; } if (!(glyph2->width | glyph2->height)) { - size = offsetof(struct libskrift_glyph, image) + glyph1->size; + size = FLEXSTRUCTSIZE(struct libskrift_glyph, image, glyph1->size); *glyphp = calloc(1, size); if (!*glyphp) return -1; @@ -47,7 +47,7 @@ libskrift_merge_glyphs(LIBSKRIFT_CONTEXT *ctx, const struct libskrift_glyph *gly size *= width = (uint16_t)(x2 - x1); size *= height = (uint16_t)(y2 - y1); - *glyphp = calloc(1, offsetof(struct libskrift_glyph, image) + size); + *glyphp = calloc(1, FLEXSTRUCTSIZE(struct libskrift_glyph, image, size)); if (!*glyphp) return -1; diff --git a/libskrift_open_font.c b/libskrift_open_font.c index 1eb8ff9..d829a66 100644 --- a/libskrift_open_font.c +++ b/libskrift_open_font.c @@ -43,8 +43,8 @@ libskrift_open_font(LIBSKRIFT_FONT **fontp, FILE *fp) return -1; } - (*fontp)->memory_free = mem; - (*fontp)->memory_size = size; + (*fontp)->memory_free = mem; + (*fontp)->memory_size = size; return 0; } diff --git a/libskrift_open_font_at.c b/libskrift_open_font_at.c index 2927dea..8745991 100644 --- a/libskrift_open_font_at.c +++ b/libskrift_open_font_at.c @@ -4,7 +4,7 @@ int libskrift_open_font_at(LIBSKRIFT_FONT **fontp, int dirfd, const char *path) { - int fd, ret; + int fd, ret, saved_errno; if (!*path) { return libskrift_open_font_fd(fontp, dirfd); } else { @@ -12,7 +12,9 @@ libskrift_open_font_at(LIBSKRIFT_FONT **fontp, int dirfd, const char *path) if (fd < 0) return -1; ret = libskrift_open_font_fd(fontp, fd); + saved_errno = errno; close(fd); + errno = saved_errno; return ret; } } diff --git a/libskrift_open_font_fd.c b/libskrift_open_font_fd.c index c00422e..e134cd8 100644 --- a/libskrift_open_font_fd.c +++ b/libskrift_open_font_fd.c @@ -13,6 +13,7 @@ libskrift_open_font_fd(LIBSKRIFT_FONT **fontp, int fd) saved_errno = errno; if (fstat(fd, &st) < 0 || !st.st_size || !S_ISREG(st.st_mode)) { + fallback: for (;;) { if (off + 2048 > size) { size += 8192; @@ -39,6 +40,8 @@ libskrift_open_font_fd(LIBSKRIFT_FONT **fontp, int fd) errno = saved_errno; } else { mem = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mem == MAP_FAILED || !mem) + goto fallback; size = (size_t)st.st_size; mmapped = 1; } |