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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#include "cff-charset.h"
void cff_extract_Charset(uint8_t *data, int32_t offset, uint16_t nchars, cff_Charset *charsets) {
uint32_t i;
if (offset == cff_CHARSET_ISOADOBE)
charsets->t = cff_CHARSET_ISOADOBE;
else if (offset == cff_CHARSET_EXPERT)
charsets->t = cff_CHARSET_EXPERT;
else if (offset == cff_CHARSET_EXPERTSUBSET)
charsets->t = cff_CHARSET_EXPERTSUBSET;
else {
// NOTE: gid 1 will always be named as .notdef
switch (data[offset]) {
case 0:
charsets->t = cff_CHARSET_FORMAT0;
{
charsets->s = nchars - 1;
NEW(charsets->f0.glyph, nchars - 1);
for (i = 0; i < charsets->s; i++)
charsets->f0.glyph[i] = gu2(data, offset + 1 + i * 2);
}
break;
case 1:
charsets->t = cff_CHARSET_FORMAT1;
{
uint32_t size;
uint32_t glyphsEncodedSofar = 1;
for (i = 0; glyphsEncodedSofar < nchars; i++) {
glyphsEncodedSofar += 1 + gu1(data, offset + 3 + i * 3);
}
size = i;
charsets->s = size;
NEW(charsets->f1.range1, i + 1);
for (i = 0; i < size; i++) {
charsets->f1.range1[i].first = gu2(data, offset + 1 + i * 3);
charsets->f1.range1[i].nleft = gu1(data, offset + 3 + i * 3);
}
}
break;
case 2:
charsets->t = cff_CHARSET_FORMAT2;
{
uint32_t size;
uint32_t glyphsEncodedSofar = 1;
for (i = 0; glyphsEncodedSofar < nchars; i++) {
glyphsEncodedSofar += 1 + gu2(data, offset + 3 + i * 4);
}
size = i;
charsets->s = size;
NEW(charsets->f2.range2, i + 1);
for (i = 0; i < size; i++) {
charsets->f2.range2[i].first = gu2(data, offset + 1 + i * 4);
charsets->f2.range2[i].nleft = gu2(data, offset + 3 + i * 4);
}
}
break;
}
}
}
caryll_Buffer *cff_build_Charset(cff_Charset cset) {
switch (cset.t) {
case cff_CHARSET_ISOADOBE:
case cff_CHARSET_EXPERT:
case cff_CHARSET_EXPERTSUBSET: {
return bufnew();
}
case cff_CHARSET_FORMAT0: {
caryll_Buffer *blob = bufnew();
blob->size = 1 + cset.s * 2;
NEW(blob->data, blob->size);
blob->data[0] = 0;
for (uint32_t i = 0; i < cset.s; i++)
blob->data[1 + 2 * i] = cset.f0.glyph[i] / 256, blob->data[2 + 2 * i] = cset.f0.glyph[i] % 256;
blob->cursor = blob->size;
return blob;
}
case cff_CHARSET_FORMAT1: {
caryll_Buffer *blob = bufnew();
blob->size = 1 + cset.s * 3;
NEW(blob->data, blob->size);
blob->data[0] = 1;
for (uint32_t i = 0; i < cset.s; i++)
blob->data[1 + 3 * i] = cset.f1.range1[i].first / 256,
blob->data[2 + 3 * i] = cset.f1.range1[i].first % 256,
blob->data[3 + 3 * i] = cset.f1.range1[i].nleft;
return blob;
}
case cff_CHARSET_FORMAT2: {
caryll_Buffer *blob = bufnew();
blob->size = 1 + cset.s * 4;
NEW(blob->data, blob->size);
blob->data[0] = 2;
for (uint32_t i = 0; i < cset.s; i++)
blob->data[1 + 4 * i] = cset.f2.range2[i].first / 256,
blob->data[2 + 4 * i] = cset.f2.range2[i].first % 256,
blob->data[3 + 4 * i] = cset.f2.range2[i].nleft / 256,
blob->data[4 + 4 * i] = cset.f2.range2[i].nleft % 256;
blob->cursor = blob->size;
return blob;
}
}
return NULL;
}
void cff_close_Charset(cff_Charset cset) {
switch (cset.t) {
case cff_CHARSET_EXPERT:
case cff_CHARSET_EXPERTSUBSET:
case cff_CHARSET_ISOADOBE:
break;
case cff_CHARSET_FORMAT0:
if (cset.f0.glyph != NULL) FREE(cset.f0.glyph);
break;
case cff_CHARSET_FORMAT1:
if (cset.f1.range1 != NULL) FREE(cset.f1.range1);
break;
case cff_CHARSET_FORMAT2:
if (cset.f2.range2 != NULL) FREE(cset.f2.range2);
break;
}
}
|