1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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;
}
|