From 9761455b328c86d8caedbf2f8ebd1bec8936e749 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Tue, 28 Apr 2020 18:47:10 +0200 Subject: Fix drawing issues (there is still some left) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- Makefile | 1 + demo.c | 63 ++++++++++++++++++++++-------------------------- libskrift.h | 11 +++++++++ libskrift_apply_glyph.c | 48 +++++++++++++++++++++++------------- libskrift_draw_text.c | 27 +++++++++++++++++++++ libskrift_merge_glyphs.c | 15 ++++++++++++ 6 files changed, 114 insertions(+), 51 deletions(-) create mode 100644 libskrift_draw_text.c diff --git a/Makefile b/Makefile index dd440d0..4c70752 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,7 @@ OBJ =\ libskrift_calculate_dpi.o\ libskrift_close_font.o\ libskrift_create_context.o\ + libskrift_draw_text.o\ libskrift_format_settings.o\ libskrift_free_context.o\ libskrift_get_grapheme_glyph.o\ diff --git a/demo.c b/demo.c index 9157a5c..062f515 100644 --- a/demo.c +++ b/demo.c @@ -11,13 +11,14 @@ main(void) { LIBSKRIFT_FONT *font; LIBSKRIFT_CONTEXT *ctx; - struct libskrift_glyph *glyph; + struct libskrift_image image = {LIBSKRIFT_R8G8B8A8, LIBSKRIFT_HOST_SUBPIXEL, 0, 800, 600, NULL, NULL, NULL}; struct libskrift_rendering rendering = LIBSKRIFT_DEFAULT_RENDERING; - uint16_t i, x, y; + struct libskrift_colour colour = LIBSKRIFT_PREMULTIPLY(1, 1, .80f, .50f, .20f); double height; + size_t size, i; rendering.smoothing = LIBSKRIFT_SUBPIXEL; - rendering.subpixel_order = LIBSKRIFT_RGB; + rendering.subpixel_order = LIBSKRIFT_NONE; rendering.flags = 0; if (libskrift_open_font_file(&font, DEMO_FONT)) { @@ -31,43 +32,37 @@ main(void) } libskrift_close_font(font); -#if 1 - if (libskrift_get_cluster_glyph(ctx, "x̴̑", NULL, 0, 0, &glyph) < 0) { - perror("libskrift_get_cluster_glyph"); + size = 4; + size *= (size_t)image.width; + size *= (size_t)image.height; + image.image = malloc(size); + if (!image.image) { + perror("malloc"); return -1; } -#else - if (libskrift_get_grapheme_glyph(ctx, 197 /* Å */, 0, 0, &glyph)) { - perror("libskrift_get_grapheme_glyph"); - 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] = 192U; } -#endif - if (rendering.smoothing == LIBSKRIFT_GREYSCALE) { - printf("P2\n%u %u\n255\n", glyph->width, glyph->height); - printf("# x-position: %i\n", glyph->x); - printf("# y-position: %i\n", glyph->y); - printf("# advance: %lf\n", glyph->advance); - for (i = y = 0; y < glyph->height; y++) { - for (x = 0; x < glyph->width; x++, i++) - printf("%3u ", glyph->image[i]); - printf("\n\n"); - } - fflush(stdout); - } else { - printf("P3\n%u %u\n255\n", glyph->width, glyph->height); - printf("# x-position: %i\n", glyph->x); - printf("# y-position: %i\n", glyph->y); - printf("# advance: %lf\n", glyph->advance); - for (i = y = 0; y < glyph->height; y++) { - for (x = 0; x < glyph->width * 3; x++, i++) - printf("%3u ", glyph->image[i]); - printf("\n\n"); - } - fflush(stdout); + if (libskrift_draw_text(ctx, "hello world", &colour, 0, 300, &image) < 0) { + perror("libskrift_draw_text"); + return -1; } - free(glyph); + printf("P7\n"); + printf("WIDTH %u\n", image.width); + printf("HEIGHT %u\n", image.height); + printf("DEPTH 4\n"); + printf("MAXVAL 255\n"); + printf("TUPLTYPE RGB_ALPHA\n"); + printf("ENDHDR\n"); + fwrite(image.image, 1, size, stdout); + fflush(stdout); + + free(image.image); libskrift_free_context(ctx); return 0; } diff --git a/libskrift.h b/libskrift.h index 93adb79..aeeaad2 100644 --- a/libskrift.h +++ b/libskrift.h @@ -184,6 +184,13 @@ struct libskrift_colour { #define LIBSKRIFT_NO_SAVED_GRAPHEME {0, 0} +#define LIBSKRIFT_PREMULTIPLY(OPACITY, ALPHA, RED, GREEN, BLUE)\ + {(OPACITY),\ + (ALPHA) * (OPACITY),\ + (RED) * (ALPHA) * (OPACITY),\ + (GREEN) * (ALPHA) * (OPACITY),\ + (BLUE) * (ALPHA) * (OPACITY)} + _LIBSKRIFT_GCC_ONLY(__attribute__((__const__, __warn_unused_result__))) inline double @@ -253,6 +260,10 @@ _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 *, + int16_t, int16_t, struct libskrift_image *); + _LIBSKRIFT_GCC_ONLY(__attribute__((__nonnull__))) void libskrift_srgb_preprocess(struct libskrift_image *, size_t, size_t, size_t, size_t); diff --git a/libskrift_apply_glyph.c b/libskrift_apply_glyph.c index 05770ce..85e4bd2 100644 --- a/libskrift_apply_glyph.c +++ b/libskrift_apply_glyph.c @@ -45,10 +45,10 @@ libskrift_apply_glyph(LIBSKRIFT_CONTEXT *ctx, const struct libskrift_glyph *glyp size_t img_linesize, gly_linesize, i, gly_psize, usize; size_t ri, gi, bi, rj, gj, bj; uint16_t x1, y1, x2, y2; - int16_t sx2, sy2; + int16_t sx1, sy1, sx2, sy2; uint8_t high; uint8_t *img, *img_start = image->image; - const uint8_t *gly = glyph->image; + const uint8_t *gly = glyph->image, *gly_start; const uint16_t u16 = 0x0102; const uint32_t u32 = 0x01020304L; const uint64_t u64 = 0x0102030405060708LL; @@ -69,30 +69,42 @@ libskrift_apply_glyph(LIBSKRIFT_CONTEXT *ctx, const struct libskrift_glyph *glyp return -1; } - /* Drawing area on image */ - sx2 = (int16_t)(x + (int16_t)glyph->width); - sy2 = (int16_t)(y + (int16_t)glyph->height); - x1 = x < 0 ? 0 : (uint16_t)x; - y1 = y < 0 ? 0 : (uint16_t)y; - if (sx2 <= 0 || sy2 <= 0 || x1 >= image->width || y1 >= image->height) + /* Top left corner of glyph on image */ + sx1 = (int16_t)(x + glyph->x); + sy1 = (int16_t)(y + glyph->y); + + /* Post-bottom right corner of glyph on image */ + sx2 = (int16_t)(sx1 + (int16_t)glyph->width); + sy2 = (int16_t)(sy1 + (int16_t)glyph->height); + if (sx2 <= 0 || sy2 <= 0) + return 0; + + /* First pixel in image to draw on */ + x1 = sx1 < 0 ? 0 : (uint16_t)sx1; + y1 = sy1 < 0 ? 0 : (uint16_t)sy1; + if (x1 >= image->width || y1 >= image->height) return 0; + + /* Post-last pixel in image to draw on */ + sx2 = (int16_t)(sx1 + (int16_t)glyph->width); + sy2 = (int16_t)(sy1 + (int16_t)glyph->height); x2 = (uint16_t)sx2 < image->width ? (uint16_t)sx2 : image->width; y2 = (uint16_t)sy2 < image->height ? (uint16_t)sy2 : image->height; - sx2 = (int16_t)x2; - sy2 = (int16_t)y2; - /* Drawing area on glyph */ - startc = x <= 0 ? 0 : (size_t)-x; - startr = y <= 0 ? 0 : (size_t)-y; - endc = x2 < image->width ? glyph->width : (uint16_t)(sx2 - x); - endr = y2 < image->height ? glyph->height : (uint16_t)(sy2 - y); + /* First pixel in glyph to draw */ + startc = (uint16_t)((int16_t)x1 - sx1); + startr = (uint16_t)((int16_t)y1 - sy1); + + /* Post-last pixel in glyph to draw*/ + endc = (uint16_t)((int16_t)x2 - sx1); + endr = (uint16_t)((int16_t)y2 - sy1); img_linesize = (size_t)image->width * psize; img_start += (size_t)y1 * img_linesize; img_start += (size_t)x1 * psize; - gly_psize = ctx->rendering.smoothing ? 3 : 1; - gly_linesize = (size_t)image->width * gly_psize; + gly_psize = (ctx->rendering.smoothing == LIBSKRIFT_SUBPIXEL) ? 3 : 1; + gly_linesize = (size_t)glyph->width * gly_psize; gly += startr * gly_linesize; usize = image->endian >= LIBSKRIFT_HOST_SUBPIXEL ? settings.spsize : psize; @@ -180,6 +192,7 @@ libskrift_apply_glyph(LIBSKRIFT_CONTEXT *ctx, const struct libskrift_glyph *glyp rj = (size_t)settings.rpos * settings.spsize; gj = (size_t)settings.gpos * settings.spsize; bj = (size_t)settings.bpos * settings.spsize; + gly_start = gly; for (img = img_start, r = startr; r < endr; r++, img += img_linesize, gly += gly_linesize) { for (c = startc, i = 0; c < endc; c += gly_psize, i += psize) { img[i + rj] ^= gly[c + ri]; @@ -191,6 +204,7 @@ libskrift_apply_glyph(LIBSKRIFT_CONTEXT *ctx, const struct libskrift_glyph *glyp ri = rj + j; gi = gj + j; bi = bj + j; + gly = gly_start; for (img = img_start, r = startr; r < endr; r++, img += img_linesize, gly += gly_linesize) { for (c = startc, i = 0; c < endc; c += gly_psize, i += psize) { img[i + ri] = img[i + rj]; diff --git a/libskrift_draw_text.c b/libskrift_draw_text.c new file mode 100644 index 0000000..8f46df4 --- /dev/null +++ b/libskrift_draw_text.c @@ -0,0 +1,27 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +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) +{ + struct libskrift_saved_grapheme saved = LIBSKRIFT_NO_SAVED_GRAPHEME; + struct libskrift_glyph *glyph; + double xpos = 0; + ssize_t len; + int r; + + for (; *text; text += len) { + len = libskrift_get_cluster_glyph(ctx, text, &saved, xpos, 0, &glyph); + if (len < 0) + return -1; + + r = libskrift_apply_glyph(ctx, glyph, colour, x, y, image); + xpos += glyph->advance; + free(glyph); + if (r) + return -1; + } + + return 0; +} diff --git a/libskrift_merge_glyphs.c b/libskrift_merge_glyphs.c index 6c62fc8..4df6f7a 100644 --- a/libskrift_merge_glyphs.c +++ b/libskrift_merge_glyphs.c @@ -10,9 +10,24 @@ libskrift_merge_glyphs(LIBSKRIFT_CONTEXT *ctx, const struct libskrift_glyph *gly int16_t x1a, x1b, x2a, x2b, y1a, y1b, y2a, y2b, x1, x2, y1, y2; size_t width, height, r, c, size, psize; size_t src_off, dest_off, src_linesize, dest_linesize; + const struct libskrift_glyph *t; psize = ctx->rendering.smoothing ? 3 : 1; + if (!(glyph1->width | glyph1->height)) { + t = glyph1; + glyph1 = glyph2; + glyph2 = t; + } + if (!(glyph2->width | glyph2->height)) { + size = offsetof(struct libskrift_glyph, image) + glyph1->size; + *glyphp = calloc(1, size); + if (!*glyphp) + return -1; + memcpy(*glyphp, glyph1, size); + return 0; + } + x1a = glyph1->x; x1b = glyph2->x; y1a = glyph1->y; -- cgit v1.2.3-70-g09d2