3
Copyright 2002 by Jin-Hwan Cho and Shunsaku Hirata,
4
the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
5
Copyright 2006-2008 Taco Hoekwater <taco@luatex.org>
7
This file is part of LuaTeX.
9
LuaTeX is free software; you can redistribute it and/or modify it under
10
the terms of the GNU General Public License as published by the Free
11
Software Foundation; either version 2 of the License, or (at your
12
option) any later version.
14
LuaTeX is distributed in the hope that it will be useful, but WITHOUT
15
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17
License for more details.
19
You should have received a copy of the GNU General Public License along
20
with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */
23
* Subsetting glyf, updating loca, hmtx, ...
34
static const char _svn_version[] =
35
"$Id: tt_glyf.c 2271 2009-04-12 23:42:21Z oneiros $ $URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.50.0/source/texk/web2c/luatexdir/font/tt_glyf.c $";
37
#define NUM_GLYPH_LIMIT 65534
38
#define TABLE_DATA_ALLOC_SIZE 40960
39
#define GLYPH_ARRAY_ALLOC_SIZE 256
41
static USHORT find_empty_slot(struct tt_glyphs *g)
47
for (gid = 0; gid < NUM_GLYPH_LIMIT; gid++) {
48
if (!(g->used_slot[gid / 8] & (1 << (7 - (gid % 8)))))
51
if (gid == NUM_GLYPH_LIMIT)
52
TT_ERROR("No empty glyph slot available.");
57
USHORT tt_find_glyph(struct tt_glyphs * g, USHORT gid)
59
USHORT idx, new_gid = 0;
63
for (idx = 0; idx < g->num_glyphs; idx++) {
64
if (gid == g->gd[idx].ogid) {
65
new_gid = g->gd[idx].gid;
73
USHORT tt_get_index(struct tt_glyphs * g, USHORT gid)
79
for (idx = 0; idx < g->num_glyphs; idx++) {
80
if (gid == g->gd[idx].gid)
83
if (idx == g->num_glyphs)
89
USHORT tt_add_glyph(struct tt_glyphs * g, USHORT gid, USHORT new_gid)
93
if (g->used_slot[new_gid / 8] & (1 << (7 - (new_gid % 8)))) {
94
WARN("Slot %u already used.", new_gid);
96
if (g->num_glyphs + 1 >= NUM_GLYPH_LIMIT)
97
TT_ERROR("Too many glyphs.");
99
if (g->num_glyphs >= g->max_glyphs) {
100
g->max_glyphs += GLYPH_ARRAY_ALLOC_SIZE;
101
g->gd = RENEW(g->gd, g->max_glyphs, struct tt_glyph_desc);
103
g->gd[g->num_glyphs].gid = new_gid;
104
g->gd[g->num_glyphs].ogid = gid;
105
g->gd[g->num_glyphs].length = 0;
106
g->gd[g->num_glyphs].data = NULL;
107
g->used_slot[new_gid / 8] |= (1 << (7 - (new_gid % 8)));
111
if (new_gid > g->last_gid) {
112
g->last_gid = new_gid;
121
struct tt_glyphs *tt_build_init(void)
125
g = NEW(1, struct tt_glyphs);
134
g->used_slot = NEW(8192, unsigned char);
135
memset(g->used_slot, 0, 8192);
136
tt_add_glyph(g, 0, 0);
141
void tt_build_finish(struct tt_glyphs *g)
146
for (idx = 0; idx < g->num_glyphs; idx++) {
148
RELEASE(g->gd[idx].data);
153
RELEASE(g->used_slot);
158
static int glyf_cmp(const void *v1, const void *v2)
161
struct tt_glyph_desc *sv1, *sv2;
163
sv1 = (struct tt_glyph_desc *) v1;
164
sv2 = (struct tt_glyph_desc *) v2;
166
if (sv1->gid == sv2->gid)
168
else if (sv1->gid < sv2->gid)
176
int tt_build_tables(sfnt * sfont, struct tt_glyphs *g)
178
char *hmtx_table_data = NULL, *loca_table_data = NULL;
179
char *glyf_table_data = NULL;
180
ULONG hmtx_table_size, loca_table_size, glyf_table_size;
181
/* some information available from other TrueType table */
182
struct tt_head_table *head = NULL;
183
struct tt_hhea_table *hhea = NULL;
184
struct tt_maxp_table *maxp = NULL;
185
struct tt_longMetrics *hmtx, *vmtx = NULL;
186
struct tt_os2__table *os2;
188
ULONG *location, offset;
190
USHORT *w_stat; /* Estimate most frequently appeared width */
194
if (sfont->type != SFNT_TYPE_TRUETYPE && sfont->type != SFNT_TYPE_TTC)
195
TT_ERROR("Invalid font type");
197
if (g->num_glyphs > NUM_GLYPH_LIMIT)
198
TT_ERROR("Too many glyphs.");
201
* Read head, hhea, maxp, loca:
203
* unitsPerEm --> head
204
* numHMetrics --> hhea
205
* indexToLocFormat --> head
208
head = tt_read_head_table(sfont);
209
hhea = tt_read_hhea_table(sfont);
210
maxp = tt_read_maxp_table(sfont);
212
if (hhea->metricDataFormat != 0)
213
TT_ERROR("Unknown metricDataFormat.");
215
g->emsize = head->unitsPerEm;
217
sfnt_locate_table(sfont, "hmtx");
218
hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics);
220
os2 = tt_read_os2__table(sfont);
222
g->default_advh = os2->sTypoAscender - os2->sTypoDescender;
223
g->default_tsb = g->default_advh - os2->sTypoAscender;
225
/* dvipdfmx does this elsewhere! */
226
fd_cur->font_dim[STEMV_CODE].val =
227
(os2->usWeightClass / 65) * (os2->usWeightClass / 65) + 50;
230
if (sfnt_find_table_pos(sfont, "vmtx") > 0) {
231
struct tt_vhea_table *vhea;
232
vhea = tt_read_vhea_table(sfont);
233
sfnt_locate_table(sfont, "vmtx");
235
tt_read_longMetrics(sfont, maxp->numGlyphs,
236
vhea->numOfLongVerMetrics);
242
sfnt_locate_table(sfont, "loca");
243
location = NEW(maxp->numGlyphs + 1, ULONG);
244
if (head->indexToLocFormat == 0) {
245
for (i = 0; i <= maxp->numGlyphs; i++)
246
location[i] = 2 * ((ULONG) sfnt_get_ushort(sfont));
247
} else if (head->indexToLocFormat == 1) {
248
for (i = 0; i <= maxp->numGlyphs; i++)
249
location[i] = sfnt_get_ulong(sfont);
251
TT_ERROR("Unknown IndexToLocFormat.");
254
w_stat = NEW(g->emsize + 2, USHORT);
255
memset(w_stat, 0, sizeof(USHORT) * (g->emsize + 2));
259
offset = sfnt_locate_table(sfont, "glyf");
261
* The num_glyphs may grow when composite glyph is found.
262
* A component of glyph refered by a composite glyph is appended
263
* to used_glyphs if it is not already registered in used_glyphs.
264
* Glyph programs of composite glyphs are modified so that it
265
* correctly refer to new gid of their components.
267
for (i = 0; i < NUM_GLYPH_LIMIT; i++) {
268
USHORT gid; /* old gid */
271
SHORT number_of_contours;
273
if (i >= g->num_glyphs) /* finished */
277
if (gid >= maxp->numGlyphs)
278
TT_ERROR("Invalid glyph index (gid %u)", gid);
281
len = location[gid + 1] - loc;
282
g->gd[i].advw = hmtx[gid].advance;
283
g->gd[i].lsb = hmtx[gid].sideBearing;
285
g->gd[i].advh = vmtx[gid].advance;
286
g->gd[i].tsb = vmtx[gid].sideBearing;
288
g->gd[i].advh = g->default_advh;
289
g->gd[i].tsb = g->default_tsb;
291
g->gd[i].length = len;
292
g->gd[i].data = NULL;
293
if (g->gd[i].advw <= g->emsize) {
294
w_stat[g->gd[i].advw] += 1;
296
w_stat[g->emsize + 1] += 1; /* larger than em */
299
if (len == 0) { /* Does not contains any data. */
301
} else if (len < 10) {
302
TT_ERROR("Invalid TrueType glyph data (gid %u).", gid);
305
g->gd[i].data = p = NEW(len, BYTE);
308
sfnt_seek_set(sfont, offset + loc);
309
number_of_contours = sfnt_get_short(sfont);
310
p += sfnt_put_short(p, number_of_contours);
312
/* BoundingBox: FWord x 4 */
313
g->gd[i].llx = sfnt_get_short(sfont);
314
g->gd[i].lly = sfnt_get_short(sfont);
315
g->gd[i].urx = sfnt_get_short(sfont);
316
g->gd[i].ury = sfnt_get_short(sfont);
319
if (!vmtx) /* vertOriginY == sTypeAscender */
320
g->gd[i].tsb = g->default_advh - g->default_tsb - g->gd[i].ury;
322
p += sfnt_put_short(p, g->gd[i].llx);
323
p += sfnt_put_short(p, g->gd[i].lly);
324
p += sfnt_put_short(p, g->gd[i].urx);
325
p += sfnt_put_short(p, g->gd[i].ury);
327
/* Read evrything else. */
328
sfnt_read(p, len - 10, sfont);
330
* Fix GIDs of composite glyphs.
332
if (number_of_contours < 0) {
333
USHORT flags, cgid, new_gid; /* flag, gid of a component */
336
TT_ERROR("Invalid TrueType glyph data (gid %u): %u bytes",
337
gid, (unsigned int) len);
339
* Flags and gid of component glyph are both USHORT.
341
flags = ((*p) << 8) | *(p + 1);
343
cgid = ((*p) << 8) | *(p + 1);
344
if (cgid >= maxp->numGlyphs) {
345
TT_ERROR("Invalid gid (%u > %u) in composite glyph %u.",
346
cgid, maxp->numGlyphs, gid);
348
new_gid = tt_find_glyph(g, cgid);
350
new_gid = tt_add_glyph(g, cgid, find_empty_slot(g));
352
p += sfnt_put_ushort(p, new_gid);
354
* Just skip remaining part.
356
p += (flags & ARG_1_AND_2_ARE_WORDS) ? 4 : 2;
357
if (flags & WE_HAVE_A_SCALE) /* F2Dot14 */
359
else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) /* F2Dot14 x 2 */
361
else if (flags & WE_HAVE_A_TWO_BY_TWO) /* F2Dot14 x 4 */
363
} while (flags & MORE_COMPONENTS);
365
* TrueType instructions comes here:
366
* length_of_instruction (ushort)
367
* instruction (byte * length_of_instruction)
379
g->dw = g->gd[0].advw;
380
for (i = 0; i < g->emsize + 1; i++) {
381
if (w_stat[i] > max_count) {
382
max_count = w_stat[i];
389
qsort(g->gd, g->num_glyphs, sizeof(struct tt_glyph_desc), glyf_cmp);
391
USHORT prev, last_advw;
393
int padlen, num_hm_known;
395
glyf_table_size = 0UL;
397
last_advw = g->gd[g->num_glyphs - 1].advw;
398
for (i = g->num_glyphs - 1; i >= 0; i--) {
399
padlen = (g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0;
400
glyf_table_size += g->gd[i].length + padlen;
401
if (!num_hm_known && last_advw != g->gd[i].advw) {
402
hhea->numberOfHMetrics = g->gd[i].gid + 2;
406
/* All advance widths are same. */
408
hhea->numberOfHMetrics = 1;
410
hmtx_table_size = hhea->numberOfHMetrics * 2 + (g->last_gid + 1) * 2;
413
* Choosing short format does not always give good result
414
* when compressed. Sometimes increases size.
416
if (glyf_table_size < 0x20000UL) {
417
head->indexToLocFormat = 0;
418
loca_table_size = (g->last_gid + 2) * 2;
420
head->indexToLocFormat = 1;
421
loca_table_size = (g->last_gid + 2) * 4;
424
hmtx_table_data = p = NEW(hmtx_table_size, char);
425
loca_table_data = q = NEW(loca_table_size, char);
426
glyf_table_data = NEW(glyf_table_size, char);
430
for (i = 0; i < g->num_glyphs; i++) {
432
gap = (long) g->gd[i].gid - prev - 1;
433
for (j = 1; j <= gap; j++) {
434
if (prev + j == hhea->numberOfHMetrics - 1) {
435
p += sfnt_put_ushort(p, last_advw);
436
} else if (prev + j < hhea->numberOfHMetrics) {
437
p += sfnt_put_ushort(p, 0);
439
p += sfnt_put_short(p, 0);
440
if (head->indexToLocFormat == 0) {
441
q += sfnt_put_ushort(q, (USHORT) (offset / 2));
443
q += sfnt_put_ulong(q, offset);
446
padlen = (g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0;
447
if (g->gd[i].gid < hhea->numberOfHMetrics) {
448
p += sfnt_put_ushort(p, g->gd[i].advw);
450
p += sfnt_put_short(p, g->gd[i].lsb);
451
if (head->indexToLocFormat == 0) {
452
q += sfnt_put_ushort(q, (USHORT) (offset / 2));
454
q += sfnt_put_ulong(q, offset);
456
memset(glyf_table_data + offset, 0, g->gd[i].length + padlen);
457
memcpy(glyf_table_data + offset, g->gd[i].data, g->gd[i].length);
458
offset += g->gd[i].length + padlen;
460
/* free data here since it consume much memory */
461
RELEASE(g->gd[i].data);
463
g->gd[i].data = NULL;
465
if (head->indexToLocFormat == 0) {
466
q += sfnt_put_ushort(q, (USHORT) (offset / 2));
468
q += sfnt_put_ulong(q, offset);
471
sfnt_set_table(sfont, "hmtx", (char *) hmtx_table_data,
473
sfnt_set_table(sfont, "loca", (char *) loca_table_data,
475
sfnt_set_table(sfont, "glyf", (char *) glyf_table_data,
479
head->checkSumAdjustment = 0;
480
maxp->numGlyphs = g->last_gid + 1;
483
sfnt_set_table(sfont, "maxp", tt_pack_maxp_table(maxp), TT_MAXP_TABLE_SIZE);
484
sfnt_set_table(sfont, "hhea", tt_pack_hhea_table(hhea), TT_HHEA_TABLE_SIZE);
485
sfnt_set_table(sfont, "head", tt_pack_head_table(head), TT_HEAD_TABLE_SIZE);
495
int tt_get_metrics(sfnt * sfont, struct tt_glyphs *g)
497
struct tt_head_table *head = NULL;
498
struct tt_hhea_table *hhea = NULL;
499
struct tt_maxp_table *maxp = NULL;
500
struct tt_longMetrics *hmtx, *vmtx = NULL;
501
struct tt_os2__table *os2;
503
ULONG *location, offset;
511
sfont->ft_face == NULL
512
#elif defined(pdfTeX)
513
sfont->buffer == NULL
515
sfont->stream == NULL
518
TT_ERROR("File not opened.");
520
if (sfont->type != SFNT_TYPE_TRUETYPE && sfont->type != SFNT_TYPE_TTC)
521
TT_ERROR("Invalid font type");
524
* Read head, hhea, maxp, loca:
526
* unitsPerEm --> head
527
* numHMetrics --> hhea
528
* indexToLocFormat --> head
531
head = tt_read_head_table(sfont);
532
hhea = tt_read_hhea_table(sfont);
533
maxp = tt_read_maxp_table(sfont);
535
if (hhea->metricDataFormat != 0)
536
TT_ERROR("Unknown metricDataFormat.");
538
g->emsize = head->unitsPerEm;
540
sfnt_locate_table(sfont, "hmtx");
541
hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics);
543
os2 = tt_read_os2__table(sfont);
544
g->default_advh = os2->sTypoAscender - os2->sTypoDescender;
545
g->default_tsb = g->default_advh - os2->sTypoAscender;
547
if (sfnt_find_table_pos(sfont, "vmtx") > 0) {
548
struct tt_vhea_table *vhea;
549
vhea = tt_read_vhea_table(sfont);
550
sfnt_locate_table(sfont, "vmtx");
552
tt_read_longMetrics(sfont, maxp->numGlyphs,
553
vhea->numOfLongVerMetrics);
559
sfnt_locate_table(sfont, "loca");
560
location = NEW(maxp->numGlyphs + 1, ULONG);
561
if (head->indexToLocFormat == 0) {
562
for (i = 0; i <= maxp->numGlyphs; i++)
563
location[i] = 2 * ((ULONG) sfnt_get_ushort(sfont));
564
} else if (head->indexToLocFormat == 1) {
565
for (i = 0; i <= maxp->numGlyphs; i++)
566
location[i] = sfnt_get_ulong(sfont);
568
TT_ERROR("Unknown IndexToLocFormat.");
571
w_stat = NEW(g->emsize + 2, USHORT);
572
memset(w_stat, 0, sizeof(USHORT) * (g->emsize + 2));
576
offset = sfnt_locate_table(sfont, "glyf");
577
for (i = 0; i < g->num_glyphs; i++) {
578
USHORT gid; /* old gid */
580
SHORT number_of_contours;
583
if (gid >= maxp->numGlyphs)
584
TT_ERROR("Invalid glyph index (gid %u)", gid);
587
len = location[gid + 1] - loc;
588
g->gd[i].advw = hmtx[gid].advance;
589
g->gd[i].lsb = hmtx[gid].sideBearing;
591
g->gd[i].advh = vmtx[gid].advance;
592
g->gd[i].tsb = vmtx[gid].sideBearing;
594
g->gd[i].advh = g->default_advh;
595
g->gd[i].tsb = g->default_tsb;
597
g->gd[i].length = len;
598
g->gd[i].data = NULL;
600
if (g->gd[i].advw <= g->emsize) {
601
w_stat[g->gd[i].advw] += 1;
603
w_stat[g->emsize + 1] += 1; /* larger than em */
606
if (len == 0) { /* Does not contains any data. */
608
} else if (len < 10) {
609
TT_ERROR("Invalid TrueType glyph data (gid %u).", gid);
612
sfnt_seek_set(sfont, offset + loc);
613
number_of_contours = sfnt_get_short(sfont);
615
/* BoundingBox: FWord x 4 */
616
g->gd[i].llx = sfnt_get_short(sfont);
617
g->gd[i].lly = sfnt_get_short(sfont);
618
g->gd[i].urx = sfnt_get_short(sfont);
619
g->gd[i].ury = sfnt_get_short(sfont);
622
if (!vmtx) /* vertOriginY == sTypeAscender */
623
g->gd[i].tsb = g->default_advh - g->default_tsb - g->gd[i].ury;
639
g->dw = g->gd[0].advw;
640
for (i = 0; i < g->emsize + 1; i++) {
641
if (w_stat[i] > max_count) {
642
max_count = w_stat[i];