3
% Copyright 2002 by Jin-Hwan Cho and Shunsaku Hirata,
4
% the dvipdfmx project team <dvipdfmx@@project.ktug.or.kr>
5
% Copyright 2006-2010 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/>.
22
@* Subsetting glyf, updating loca, hmtx, etc.
27
#include "font/sfnt.h"
28
#include "font/tt_table.h"
29
#include "font/tt_glyf.h"
30
#include "font/writettf.h"
32
static const char _svn_version[] =
33
"$Id: tt_glyf.w 3584 2010-04-02 17:45:55Z hhenkel $ "
34
"$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.1/source/texk/web2c/luatexdir/font/tt_glyf.w $";
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 = (USHORT) (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] =
108
(unsigned char) (g->used_slot[new_gid /
109
8] | (1 << (7 - (new_gid % 8))));
113
if (new_gid > g->last_gid) {
114
g->last_gid = new_gid;
123
struct tt_glyphs *tt_build_init(void)
127
g = NEW(1, struct tt_glyphs);
136
g->used_slot = NEW(8192, unsigned char);
137
memset(g->used_slot, 0, 8192);
138
tt_add_glyph(g, 0, 0);
143
void tt_build_finish(struct tt_glyphs *g)
148
for (idx = 0; idx < g->num_glyphs; idx++) {
150
RELEASE(g->gd[idx].data);
155
RELEASE(g->used_slot);
160
static int glyf_cmp(const void *v1, const void *v2)
163
const struct tt_glyph_desc *sv1, *sv2;
165
sv1 = (const struct tt_glyph_desc *) v1;
166
sv2 = (const struct tt_glyph_desc *) v2;
168
if (sv1->gid == sv2->gid)
170
else if (sv1->gid < sv2->gid)
179
int tt_build_tables(sfnt * sfont, struct tt_glyphs *g)
181
char *hmtx_table_data = NULL, *loca_table_data = NULL;
182
char *glyf_table_data = NULL;
183
ULONG hmtx_table_size, loca_table_size, glyf_table_size;
184
/* some information available from other TrueType table */
185
struct tt_head_table *head = NULL;
186
struct tt_hhea_table *hhea = NULL;
187
struct tt_maxp_table *maxp = NULL;
188
struct tt_longMetrics *hmtx, *vmtx = NULL;
189
struct tt_os2__table *os2;
191
ULONG *location, offset;
193
USHORT *w_stat; /* Estimate most frequently appeared width */
197
if (sfont->type != SFNT_TYPE_TRUETYPE && sfont->type != SFNT_TYPE_TTC)
198
TT_ERROR("Invalid font type");
200
if (g->num_glyphs > NUM_GLYPH_LIMIT)
201
TT_ERROR("Too many glyphs.");
204
Read head, hhea, maxp, loca:
210
indexToLocFormat --> head
214
head = tt_read_head_table(sfont);
215
hhea = tt_read_hhea_table(sfont);
216
maxp = tt_read_maxp_table(sfont);
218
if (hhea->metricDataFormat != 0)
219
TT_ERROR("Unknown metricDataFormat.");
221
g->emsize = head->unitsPerEm;
223
sfnt_locate_table(sfont, "hmtx");
224
hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics);
226
os2 = tt_read_os2__table(sfont);
228
g->default_advh = (USHORT) (os2->sTypoAscender - os2->sTypoDescender);
229
g->default_tsb = (SHORT) (g->default_advh - os2->sTypoAscender);
231
/* dvipdfmx does this elsewhere! */
232
fd_cur->font_dim[STEMV_CODE].val =
233
(os2->usWeightClass / 65) * (os2->usWeightClass / 65) + 50;
236
if (sfnt_find_table_pos(sfont, "vmtx") > 0) {
237
struct tt_vhea_table *vhea;
238
vhea = tt_read_vhea_table(sfont);
239
sfnt_locate_table(sfont, "vmtx");
241
tt_read_longMetrics(sfont, maxp->numGlyphs,
242
vhea->numOfLongVerMetrics);
248
sfnt_locate_table(sfont, "loca");
249
location = NEW(maxp->numGlyphs + 1, ULONG);
250
if (head->indexToLocFormat == 0) {
251
for (i = 0; i <= maxp->numGlyphs; i++)
252
location[i] = 2 * ((ULONG) sfnt_get_ushort(sfont));
253
} else if (head->indexToLocFormat == 1) {
254
for (i = 0; i <= maxp->numGlyphs; i++)
255
location[i] = sfnt_get_ulong(sfont);
257
TT_ERROR("Unknown IndexToLocFormat.");
260
w_stat = NEW(g->emsize + 2, USHORT);
262
(size_t) (sizeof(USHORT) * ((long unsigned) g->emsize + 2)));
266
offset = sfnt_locate_table(sfont, "glyf");
268
The |num_glyphs| may grow when composite glyph is found.
269
A component of glyph refered by a composite glyph is appended
270
to |used_glyphs| if it is not already registered in |used_glyphs|.
271
Glyph programs of composite glyphs are modified so that it
272
correctly refer to new gid of their components.
274
for (i = 0; i < NUM_GLYPH_LIMIT; i++) {
275
USHORT gid; /* old gid */
278
SHORT number_of_contours;
280
if (i >= g->num_glyphs) /* finished */
284
if (gid >= maxp->numGlyphs)
285
TT_ERROR("Invalid glyph index (gid %u)", gid);
288
len = location[gid + 1] - loc;
289
g->gd[i].advw = hmtx[gid].advance;
290
g->gd[i].lsb = hmtx[gid].sideBearing;
292
g->gd[i].advh = vmtx[gid].advance;
293
g->gd[i].tsb = vmtx[gid].sideBearing;
295
g->gd[i].advh = g->default_advh;
296
g->gd[i].tsb = g->default_tsb;
298
g->gd[i].length = len;
299
g->gd[i].data = NULL;
300
if (g->gd[i].advw <= g->emsize) {
301
w_stat[g->gd[i].advw]++;
303
w_stat[g->emsize + 1]++; /* larger than em */
306
if (len == 0) { /* Does not contains any data. */
308
} else if (len < 10) {
309
TT_ERROR("Invalid TrueType glyph data (gid %u).", gid);
312
g->gd[i].data = p = NEW(len, BYTE);
315
sfnt_seek_set(sfont, (long) (offset + loc));
316
number_of_contours = sfnt_get_short(sfont);
317
p += sfnt_put_short(p, number_of_contours);
319
/* BoundingBox: FWord x 4 */
320
g->gd[i].llx = sfnt_get_short(sfont);
321
g->gd[i].lly = sfnt_get_short(sfont);
322
g->gd[i].urx = sfnt_get_short(sfont);
323
g->gd[i].ury = sfnt_get_short(sfont);
326
if (!vmtx) /* |vertOriginY == sTypeAscender| */
328
(SHORT) (g->default_advh - g->default_tsb - g->gd[i].ury);
330
p += sfnt_put_short(p, g->gd[i].llx);
331
p += sfnt_put_short(p, g->gd[i].lly);
332
p += sfnt_put_short(p, g->gd[i].urx);
333
p += sfnt_put_short(p, g->gd[i].ury);
335
/* Read evrything else. */
336
sfnt_read(p, (int) len - 10, sfont);
338
Fix GIDs of composite glyphs.
340
if (number_of_contours < 0) {
341
USHORT flags, cgid, new_gid; /* flag, gid of a component */
344
TT_ERROR("Invalid TrueType glyph data (gid %u): %u bytes",
345
gid, (unsigned int) len);
347
* Flags and gid of component glyph are both USHORT.
349
flags = (USHORT) (((*p) << 8) | *(p + 1));
351
cgid = (USHORT) (((*p) << 8) | *(p + 1));
352
if (cgid >= maxp->numGlyphs) {
353
TT_ERROR("Invalid gid (%u > %u) in composite glyph %u.",
354
cgid, maxp->numGlyphs, gid);
356
new_gid = tt_find_glyph(g, cgid);
358
new_gid = tt_add_glyph(g, cgid, find_empty_slot(g));
360
p += sfnt_put_ushort(p, new_gid);
362
* Just skip remaining part.
364
p += (flags & ARG_1_AND_2_ARE_WORDS) ? 4 : 2;
365
if (flags & WE_HAVE_A_SCALE) /* F2Dot14 */
367
else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) /* F2Dot14 x 2 */
369
else if (flags & WE_HAVE_A_TWO_BY_TWO) /* F2Dot14 x 4 */
371
} while (flags & MORE_COMPONENTS);
373
TrueType instructions comes here:
375
|length_of_instruction| (|ushort|)
377
instruction (|byte * length_of_instruction|)
389
g->dw = g->gd[0].advw;
390
for (i = 0; i < g->emsize + 1; i++) {
391
if (w_stat[i] > max_count) {
392
max_count = w_stat[i];
399
qsort(g->gd, g->num_glyphs, sizeof(struct tt_glyph_desc), glyf_cmp);
401
USHORT prev, last_advw;
403
int padlen, num_hm_known;
405
glyf_table_size = 0UL;
407
last_advw = g->gd[g->num_glyphs - 1].advw;
408
for (i = g->num_glyphs - 1; i >= 0; i--) {
410
(int) ((g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0);
411
glyf_table_size += (ULONG) (g->gd[i].length + (ULONG) padlen);
412
if (!num_hm_known && last_advw != g->gd[i].advw) {
413
hhea->numberOfHMetrics = (USHORT) (g->gd[i].gid + 2);
417
/* All advance widths are same. */
419
hhea->numberOfHMetrics = 1;
422
(ULONG) (hhea->numberOfHMetrics * 2 + (g->last_gid + 1) * 2);
425
Choosing short format does not always give good result
426
when compressed. Sometimes increases size.
428
if (glyf_table_size < 0x20000UL) {
429
head->indexToLocFormat = 0;
430
loca_table_size = (ULONG) ((g->last_gid + 2) * 2);
432
head->indexToLocFormat = 1;
433
loca_table_size = (ULONG) ((g->last_gid + 2) * 4);
436
hmtx_table_data = p = NEW(hmtx_table_size, char);
437
loca_table_data = q = NEW(loca_table_size, char);
438
glyf_table_data = NEW(glyf_table_size, char);
442
for (i = 0; i < g->num_glyphs; i++) {
444
gap = (long) g->gd[i].gid - prev - 1;
445
for (j = 1; j <= gap; j++) {
446
if (prev + j == hhea->numberOfHMetrics - 1) {
447
p += sfnt_put_ushort(p, last_advw);
448
} else if (prev + j < hhea->numberOfHMetrics) {
449
p += sfnt_put_ushort(p, 0);
451
p += sfnt_put_short(p, 0);
452
if (head->indexToLocFormat == 0) {
453
q += sfnt_put_ushort(q, (USHORT) (offset / 2));
455
q += sfnt_put_ulong(q, (LONG) offset);
459
(int) ((g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0);
460
if (g->gd[i].gid < hhea->numberOfHMetrics) {
461
p += sfnt_put_ushort(p, g->gd[i].advw);
463
p += sfnt_put_short(p, g->gd[i].lsb);
464
if (head->indexToLocFormat == 0) {
465
q += sfnt_put_ushort(q, (USHORT) (offset / 2));
467
q += sfnt_put_ulong(q, (LONG) offset);
469
memset(glyf_table_data + offset, 0,
470
(size_t) (g->gd[i].length + (ULONG) padlen));
471
memcpy(glyf_table_data + offset, g->gd[i].data, g->gd[i].length);
472
offset += (g->gd[i].length + (ULONG) padlen);
474
/* free data here since it consume much memory */
475
RELEASE(g->gd[i].data);
477
g->gd[i].data = NULL;
479
if (head->indexToLocFormat == 0) {
480
q += sfnt_put_ushort(q, (USHORT) (offset / 2));
482
q += sfnt_put_ulong(q, (LONG) offset);
485
sfnt_set_table(sfont, "hmtx", (char *) hmtx_table_data,
487
sfnt_set_table(sfont, "loca", (char *) loca_table_data,
489
sfnt_set_table(sfont, "glyf", (char *) glyf_table_data,
493
head->checkSumAdjustment = 0;
494
maxp->numGlyphs = (USHORT) (g->last_gid + 1);
497
sfnt_set_table(sfont, "maxp", tt_pack_maxp_table(maxp), TT_MAXP_TABLE_SIZE);
498
sfnt_set_table(sfont, "hhea", tt_pack_hhea_table(hhea), TT_HHEA_TABLE_SIZE);
499
sfnt_set_table(sfont, "head", tt_pack_head_table(head), TT_HEAD_TABLE_SIZE);
509
int tt_get_metrics(sfnt * sfont, struct tt_glyphs *g)
511
struct tt_head_table *head = NULL;
512
struct tt_hhea_table *hhea = NULL;
513
struct tt_maxp_table *maxp = NULL;
514
struct tt_longMetrics *hmtx, *vmtx = NULL;
515
struct tt_os2__table *os2;
517
ULONG *location, offset;
525
sfont->ft_face == NULL
526
#elif defined(pdfTeX)
527
sfont->buffer == NULL
529
sfont->stream == NULL
532
TT_ERROR("File not opened.");
534
if (sfont->type != SFNT_TYPE_TRUETYPE && sfont->type != SFNT_TYPE_TTC)
535
TT_ERROR("Invalid font type");
538
Read head, hhea, maxp, loca:
544
indexToLocFormat --> head
548
head = tt_read_head_table(sfont);
549
hhea = tt_read_hhea_table(sfont);
550
maxp = tt_read_maxp_table(sfont);
552
if (hhea->metricDataFormat != 0)
553
TT_ERROR("Unknown metricDataFormat.");
555
g->emsize = head->unitsPerEm;
557
sfnt_locate_table(sfont, "hmtx");
558
hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics);
560
os2 = tt_read_os2__table(sfont);
561
g->default_advh = (USHORT) (os2->sTypoAscender - os2->sTypoDescender);
562
g->default_tsb = (SHORT) (g->default_advh - os2->sTypoAscender);
564
if (sfnt_find_table_pos(sfont, "vmtx") > 0) {
565
struct tt_vhea_table *vhea;
566
vhea = tt_read_vhea_table(sfont);
567
sfnt_locate_table(sfont, "vmtx");
569
tt_read_longMetrics(sfont, maxp->numGlyphs,
570
vhea->numOfLongVerMetrics);
576
sfnt_locate_table(sfont, "loca");
577
location = NEW(maxp->numGlyphs + 1, ULONG);
578
if (head->indexToLocFormat == 0) {
579
for (i = 0; i <= maxp->numGlyphs; i++)
580
location[i] = 2 * ((ULONG) sfnt_get_ushort(sfont));
581
} else if (head->indexToLocFormat == 1) {
582
for (i = 0; i <= maxp->numGlyphs; i++)
583
location[i] = sfnt_get_ulong(sfont);
585
TT_ERROR("Unknown IndexToLocFormat.");
588
w_stat = NEW(g->emsize + 2, USHORT);
589
memset(w_stat, 0, (size_t) ((int) sizeof(USHORT) * (g->emsize + 2)));
593
offset = sfnt_locate_table(sfont, "glyf");
594
for (i = 0; i < g->num_glyphs; i++) {
595
USHORT gid; /* old gid */
597
SHORT number_of_contours;
600
if (gid >= maxp->numGlyphs)
601
TT_ERROR("Invalid glyph index (gid %u)", gid);
604
len = location[gid + 1] - loc;
605
g->gd[i].advw = hmtx[gid].advance;
606
g->gd[i].lsb = hmtx[gid].sideBearing;
608
g->gd[i].advh = vmtx[gid].advance;
609
g->gd[i].tsb = vmtx[gid].sideBearing;
611
g->gd[i].advh = g->default_advh;
612
g->gd[i].tsb = g->default_tsb;
614
g->gd[i].length = len;
615
g->gd[i].data = NULL;
617
if (g->gd[i].advw <= g->emsize) {
618
w_stat[g->gd[i].advw]++;
620
w_stat[g->emsize + 1]++; /* larger than em */
623
if (len == 0) { /* Does not contains any data. */
625
} else if (len < 10) {
626
TT_ERROR("Invalid TrueType glyph data (gid %u).", gid);
629
sfnt_seek_set(sfont, (long) (offset + loc));
630
number_of_contours = sfnt_get_short(sfont);
632
/* BoundingBox: FWord x 4 */
633
g->gd[i].llx = sfnt_get_short(sfont);
634
g->gd[i].lly = sfnt_get_short(sfont);
635
g->gd[i].urx = sfnt_get_short(sfont);
636
g->gd[i].ury = sfnt_get_short(sfont);
639
if (!vmtx) /* |vertOriginY == sTypeAscender| */
641
(SHORT) (g->default_advh - g->default_tsb - g->gd[i].ury);
657
g->dw = g->gd[0].advw;
658
for (i = 0; i < g->emsize + 1; i++) {
659
if (w_stat[i] > max_count) {
660
max_count = w_stat[i];