aboutsummaryrefslogtreecommitdiffstats
path: root/libskrift_merge_glyphs.c
diff options
context:
space:
mode:
Diffstat (limited to 'libskrift_merge_glyphs.c')
-rw-r--r--libskrift_merge_glyphs.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/libskrift_merge_glyphs.c b/libskrift_merge_glyphs.c
new file mode 100644
index 0000000..548e8fb
--- /dev/null
+++ b/libskrift_merge_glyphs.c
@@ -0,0 +1,62 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+/* TODO How common are grapheme clusters with more than two glyphs? Should we need a variadic version? */
+
+int
+libskrift_merge_glyphs(LIBSKRIFT_CONTEXT *ctx, struct libskrift_glyph *glyph1,
+ struct libskrift_glyph *glyph2, struct libskrift_glyph **glyphp)
+{
+ int16_t x1a, x1b, x2a, x2b, y1a, y1b, y2a, y2b, x1, x2, y1, y2;
+ size_t width, height, r, c, size = 1, psize = 1;
+ size_t src_off, dest_off, src_linesize, dest_linesize;
+
+ if (ctx->rendering.smoothing == LIBSKRIFT_SUBPIXEL)
+ size = psize = 3;
+
+ x1a = glyph1->x;
+ x1b = glyph2->x;
+ y1a = glyph1->y;
+ y1b = glyph2->y;
+
+ x2a = (int16_t)(x1a + (int16_t)glyph1->width);
+ x2b = (int16_t)(x1b + (int16_t)glyph2->width);
+ y2a = (int16_t)(y1a + (int16_t)glyph1->height);
+ y2b = (int16_t)(y1b + (int16_t)glyph2->height);
+
+ x1 = MIN(x1a, x1b);
+ y1 = MIN(y1a, y1b);
+ x2 = MAX(x2a, x2b);
+ y2 = MAX(y2a, y2b);
+
+ size *= width = (uint16_t)(x2 - x1);
+ size *= height = (uint16_t)(y2 - y1);
+
+ *glyphp = calloc(1, offsetof(struct libskrift_glyph, image) + size);
+ if (!*glyphp)
+ return -1;
+
+ (*glyphp)->advance = glyph1->advance + glyph2->advance;
+ (*glyphp)->x = x1;
+ (*glyphp)->y = y1;
+ (*glyphp)->width = (uint16_t)width;
+ (*glyphp)->height = (uint16_t)height;
+ (*glyphp)->size = size;
+
+ dest_linesize = width * psize;
+
+ src_linesize = glyph1->width * psize;
+ dest_off = (size_t)(glyph1->y - y1) * dest_linesize;
+ dest_off += (size_t)(glyph1->x - x1) * psize;
+ for (r = src_off = 0; r < glyph1->height; r++, dest_off += dest_linesize, src_off += src_linesize)
+ memcpy(&(*glyphp)->image[dest_off], &glyph1->image[src_off], src_linesize);
+
+ src_linesize = glyph2->width * psize;
+ dest_off = (size_t)(glyph2->y - y1) * dest_linesize;
+ dest_off += (size_t)(glyph2->x - x1) * psize;
+ for (r = src_off = 0; r < glyph2->height; r++, dest_off += dest_linesize, src_off += src_linesize)
+ for (c = 0; c < src_linesize; c++)
+ (*glyphp)->image[dest_off + c] = MAX((*glyphp)->image[dest_off + c], glyph2->image[src_off + c]);
+
+ return 0;
+}