summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/mfluadir/otfcc/lib/consolidate/otl/gsub-multi.c
blob: 21c9ce8b0d534008b3aecba52e04521a1bd34aa1 (plain)
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
63
64
#include "gsub-multi.h"

typedef struct {
	int fromid;
	sds fromname;
	otl_Coverage *to;
	UT_hash_handle hh;
} gsub_multi_hash;
static int by_from_id_multi(gsub_multi_hash *a, gsub_multi_hash *b) {
	return a->fromid - b->fromid;
}

bool consolidate_gsub_multi(otfcc_Font *font, table_OTL *table, otl_Subtable *_subtable,
                            const otfcc_Options *options) {
	subtable_gsub_multi *subtable = &(_subtable->gsub_multi);
	gsub_multi_hash *h = NULL;

	for (glyphid_t k = 0; k < subtable->length; k++) {
		if (!GlyphOrder.consolidateHandle(font->glyph_order, &subtable->items[k].from)) {
			logWarning("[Consolidate] Ignored missing glyph /%s.\n", subtable->items[k].from.name);
			continue;
		}
		fontop_consolidateCoverage(font, subtable->items[k].to, options);
		Coverage.shrink(subtable->items[k].to, false);
		if (!subtable->items[k].to->numGlyphs) {
			logWarning("[Consolidate] Ignoring empty one-to-many / alternative substitution for "
			           "glyph /%s.\n",
			           subtable->items[k].from.name);
			continue;
		}

		gsub_multi_hash *s;
		int fromid = subtable->items[k].from.index;
		HASH_FIND_INT(h, &fromid, s);
		if (!s) {
			NEW(s);
			s->fromid = subtable->items[k].from.index;
			s->fromname = sdsdup(subtable->items[k].from.name);
			s->to = subtable->items[k].to;
			subtable->items[k].to = NULL; // Transfer ownership
			HASH_ADD_INT(h, fromid, s);
		}
	}
	HASH_SORT(h, by_from_id_multi);
	iSubtable_gsub_multi.clear(subtable);
	{
		gsub_multi_hash *s, *tmp;
		HASH_ITER(hh, h, s, tmp) {
			iSubtable_gsub_multi.push(
			    subtable, ((otl_GsubMultiEntry){
			                  .from = Handle.fromConsolidated(s->fromid, s->fromname), .to = s->to,
			              }));
			sdsfree(s->fromname);
			HASH_DEL(h, s);
			FREE(s);
		}
	}
	return (subtable->length == 0);
}

bool consolidate_gsub_alternative(otfcc_Font *font, table_OTL *table, otl_Subtable *_subtable,
                                  const otfcc_Options *options) {
	return consolidate_gsub_multi(font, table, _subtable, options);
}