~ubuntu-branches/ubuntu/wily/luatex/wily

« back to all changes in this revision

Viewing changes to source/texk/web2c/luatexdir/font/tt_glyf.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2010-04-29 00:47:19 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20100429004719-o42etkqe90n97b9e
Tags: 0.60.1-1
* new upstream release, adapt build-script patch
* disable patch: upstream-epstopdf_cc_no_xpdf_patching, included upstream
* disable patch: libpoppler-0.12, not needed anymore

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* tt_glyf.c
2
 
    
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>
6
 
 
7
 
   This file is part of LuaTeX.
8
 
 
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.
13
 
 
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.
18
 
 
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/>. */
21
 
 
22
 
/*
23
 
 * Subsetting glyf, updating loca, hmtx, ...
24
 
 *
25
 
 */
26
 
 
27
 
#include "ptexlib.h"
28
 
 
29
 
#include "sfnt.h"
30
 
#include "tt_table.h"
31
 
#include "tt_glyf.h"
32
 
#include "writettf.h"
33
 
 
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 $";
36
 
 
37
 
#define NUM_GLYPH_LIMIT        65534
38
 
#define TABLE_DATA_ALLOC_SIZE  40960
39
 
#define GLYPH_ARRAY_ALLOC_SIZE 256
40
 
 
41
 
static USHORT find_empty_slot(struct tt_glyphs *g)
42
 
{
43
 
    USHORT gid;
44
 
 
45
 
    ASSERT(g);
46
 
 
47
 
    for (gid = 0; gid < NUM_GLYPH_LIMIT; gid++) {
48
 
        if (!(g->used_slot[gid / 8] & (1 << (7 - (gid % 8)))))
49
 
            break;
50
 
    }
51
 
    if (gid == NUM_GLYPH_LIMIT)
52
 
        TT_ERROR("No empty glyph slot available.");
53
 
 
54
 
    return gid;
55
 
}
56
 
 
57
 
USHORT tt_find_glyph(struct tt_glyphs * g, USHORT gid)
58
 
{
59
 
    USHORT idx, new_gid = 0;
60
 
 
61
 
    ASSERT(g);
62
 
 
63
 
    for (idx = 0; idx < g->num_glyphs; idx++) {
64
 
        if (gid == g->gd[idx].ogid) {
65
 
            new_gid = g->gd[idx].gid;
66
 
            break;
67
 
        }
68
 
    }
69
 
 
70
 
    return new_gid;
71
 
}
72
 
 
73
 
USHORT tt_get_index(struct tt_glyphs * g, USHORT gid)
74
 
{
75
 
    USHORT idx;
76
 
 
77
 
    ASSERT(g);
78
 
 
79
 
    for (idx = 0; idx < g->num_glyphs; idx++) {
80
 
        if (gid == g->gd[idx].gid)
81
 
            break;
82
 
    }
83
 
    if (idx == g->num_glyphs)
84
 
        idx = 0;
85
 
 
86
 
    return idx;
87
 
}
88
 
 
89
 
USHORT tt_add_glyph(struct tt_glyphs * g, USHORT gid, USHORT new_gid)
90
 
{
91
 
    ASSERT(g);
92
 
 
93
 
    if (g->used_slot[new_gid / 8] & (1 << (7 - (new_gid % 8)))) {
94
 
        WARN("Slot %u already used.", new_gid);
95
 
    } else {
96
 
        if (g->num_glyphs + 1 >= NUM_GLYPH_LIMIT)
97
 
            TT_ERROR("Too many glyphs.");
98
 
 
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);
102
 
        }
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)));
108
 
        g->num_glyphs += 1;
109
 
    }
110
 
 
111
 
    if (new_gid > g->last_gid) {
112
 
        g->last_gid = new_gid;
113
 
    }
114
 
 
115
 
    return new_gid;
116
 
}
117
 
 
118
 
/*
119
 
 * Initialization
120
 
 */
121
 
struct tt_glyphs *tt_build_init(void)
122
 
{
123
 
    struct tt_glyphs *g;
124
 
 
125
 
    g = NEW(1, struct tt_glyphs);
126
 
 
127
 
    g->num_glyphs = 0;
128
 
    g->max_glyphs = 0;
129
 
    g->last_gid = 0;
130
 
    g->emsize = 1;
131
 
    g->default_advh = 0;
132
 
    g->default_tsb = 0;
133
 
    g->gd = NULL;
134
 
    g->used_slot = NEW(8192, unsigned char);
135
 
    memset(g->used_slot, 0, 8192);
136
 
    tt_add_glyph(g, 0, 0);
137
 
 
138
 
    return g;
139
 
}
140
 
 
141
 
void tt_build_finish(struct tt_glyphs *g)
142
 
{
143
 
    if (g) {
144
 
        if (g->gd) {
145
 
            USHORT idx;
146
 
            for (idx = 0; idx < g->num_glyphs; idx++) {
147
 
                if (g->gd[idx].data)
148
 
                    RELEASE(g->gd[idx].data);
149
 
            }
150
 
            RELEASE(g->gd);
151
 
        }
152
 
        if (g->used_slot)
153
 
            RELEASE(g->used_slot);
154
 
        RELEASE(g);
155
 
    }
156
 
}
157
 
 
158
 
static int glyf_cmp(const void *v1, const void *v2)
159
 
{
160
 
    int cmp = 0;
161
 
    struct tt_glyph_desc *sv1, *sv2;
162
 
 
163
 
    sv1 = (struct tt_glyph_desc *) v1;
164
 
    sv2 = (struct tt_glyph_desc *) v2;
165
 
 
166
 
    if (sv1->gid == sv2->gid)
167
 
        cmp = 0;
168
 
    else if (sv1->gid < sv2->gid)
169
 
        cmp = -1;
170
 
    else
171
 
        cmp = 1;
172
 
 
173
 
    return cmp;
174
 
}
175
 
 
176
 
int tt_build_tables(sfnt * sfont, struct tt_glyphs *g)
177
 
{
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;
187
 
    /* temp */
188
 
    ULONG *location, offset;
189
 
    long i;
190
 
    USHORT *w_stat;             /* Estimate most frequently appeared width */
191
 
 
192
 
    ASSERT(g);
193
 
 
194
 
    if (sfont->type != SFNT_TYPE_TRUETYPE && sfont->type != SFNT_TYPE_TTC)
195
 
        TT_ERROR("Invalid font type");
196
 
 
197
 
    if (g->num_glyphs > NUM_GLYPH_LIMIT)
198
 
        TT_ERROR("Too many glyphs.");
199
 
 
200
 
    /*
201
 
     * Read head, hhea, maxp, loca:
202
 
     *
203
 
     *   unitsPerEm       --> head
204
 
     *   numHMetrics      --> hhea
205
 
     *   indexToLocFormat --> head
206
 
     *   numGlyphs        --> maxp
207
 
     */
208
 
    head = tt_read_head_table(sfont);
209
 
    hhea = tt_read_hhea_table(sfont);
210
 
    maxp = tt_read_maxp_table(sfont);
211
 
 
212
 
    if (hhea->metricDataFormat != 0)
213
 
        TT_ERROR("Unknown metricDataFormat.");
214
 
 
215
 
    g->emsize = head->unitsPerEm;
216
 
 
217
 
    sfnt_locate_table(sfont, "hmtx");
218
 
    hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics);
219
 
 
220
 
    os2 = tt_read_os2__table(sfont);
221
 
    if (os2) {
222
 
        g->default_advh = os2->sTypoAscender - os2->sTypoDescender;
223
 
        g->default_tsb = g->default_advh - os2->sTypoAscender;
224
 
 
225
 
        /* dvipdfmx does this elsewhere! */
226
 
        fd_cur->font_dim[STEMV_CODE].val =
227
 
            (os2->usWeightClass / 65) * (os2->usWeightClass / 65) + 50;
228
 
    }
229
 
 
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");
234
 
        vmtx =
235
 
            tt_read_longMetrics(sfont, maxp->numGlyphs,
236
 
                                vhea->numOfLongVerMetrics);
237
 
        RELEASE(vhea);
238
 
    } else {
239
 
        vmtx = NULL;
240
 
    }
241
 
 
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);
250
 
    } else {
251
 
        TT_ERROR("Unknown IndexToLocFormat.");
252
 
    }
253
 
 
254
 
    w_stat = NEW(g->emsize + 2, USHORT);
255
 
    memset(w_stat, 0, sizeof(USHORT) * (g->emsize + 2));
256
 
    /*
257
 
     * Read glyf table.
258
 
     */
259
 
    offset = sfnt_locate_table(sfont, "glyf");
260
 
    /*
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.
266
 
     */
267
 
    for (i = 0; i < NUM_GLYPH_LIMIT; i++) {
268
 
        USHORT gid;             /* old gid */
269
 
        ULONG loc, len;
270
 
        BYTE *p, *endptr;
271
 
        SHORT number_of_contours;
272
 
 
273
 
        if (i >= g->num_glyphs) /* finished */
274
 
            break;
275
 
 
276
 
        gid = g->gd[i].ogid;
277
 
        if (gid >= maxp->numGlyphs)
278
 
            TT_ERROR("Invalid glyph index (gid %u)", gid);
279
 
 
280
 
        loc = location[gid];
281
 
        len = location[gid + 1] - loc;
282
 
        g->gd[i].advw = hmtx[gid].advance;
283
 
        g->gd[i].lsb = hmtx[gid].sideBearing;
284
 
        if (vmtx) {
285
 
            g->gd[i].advh = vmtx[gid].advance;
286
 
            g->gd[i].tsb = vmtx[gid].sideBearing;
287
 
        } else {
288
 
            g->gd[i].advh = g->default_advh;
289
 
            g->gd[i].tsb = g->default_tsb;
290
 
        }
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;
295
 
        } else {
296
 
            w_stat[g->emsize + 1] += 1; /* larger than em */
297
 
        }
298
 
 
299
 
        if (len == 0) {         /* Does not contains any data. */
300
 
            continue;
301
 
        } else if (len < 10) {
302
 
            TT_ERROR("Invalid TrueType glyph data (gid %u).", gid);
303
 
        }
304
 
 
305
 
        g->gd[i].data = p = NEW(len, BYTE);
306
 
        endptr = p + len;
307
 
 
308
 
        sfnt_seek_set(sfont, offset + loc);
309
 
        number_of_contours = sfnt_get_short(sfont);
310
 
        p += sfnt_put_short(p, number_of_contours);
311
 
 
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);
317
 
        /* _FIXME_ */
318
 
#if  1
319
 
        if (!vmtx)              /* vertOriginY == sTypeAscender */
320
 
            g->gd[i].tsb = g->default_advh - g->default_tsb - g->gd[i].ury;
321
 
#endif
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);
326
 
 
327
 
        /* Read evrything else. */
328
 
        sfnt_read(p, len - 10, sfont);
329
 
        /*
330
 
         * Fix GIDs of composite glyphs.
331
 
         */
332
 
        if (number_of_contours < 0) {
333
 
            USHORT flags, cgid, new_gid;        /* flag, gid of a component */
334
 
            do {
335
 
                if (p >= endptr)
336
 
                    TT_ERROR("Invalid TrueType glyph data (gid %u): %u bytes",
337
 
                             gid, (unsigned int) len);
338
 
                /*
339
 
                 * Flags and gid of component glyph are both USHORT.
340
 
                 */
341
 
                flags = ((*p) << 8) | *(p + 1);
342
 
                p += 2;
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);
347
 
                }
348
 
                new_gid = tt_find_glyph(g, cgid);
349
 
                if (new_gid == 0) {
350
 
                    new_gid = tt_add_glyph(g, cgid, find_empty_slot(g));
351
 
                }
352
 
                p += sfnt_put_ushort(p, new_gid);
353
 
                /*
354
 
                 * Just skip remaining part.
355
 
                 */
356
 
                p += (flags & ARG_1_AND_2_ARE_WORDS) ? 4 : 2;
357
 
                if (flags & WE_HAVE_A_SCALE)    /* F2Dot14 */
358
 
                    p += 2;
359
 
                else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)      /* F2Dot14 x 2 */
360
 
                    p += 4;
361
 
                else if (flags & WE_HAVE_A_TWO_BY_TWO)  /* F2Dot14 x 4 */
362
 
                    p += 8;
363
 
            } while (flags & MORE_COMPONENTS);
364
 
            /*
365
 
             * TrueType instructions comes here:
366
 
             *  length_of_instruction (ushort)
367
 
             *  instruction (byte * length_of_instruction)
368
 
             */
369
 
        }
370
 
    }
371
 
    RELEASE(location);
372
 
    RELEASE(hmtx);
373
 
    if (vmtx)
374
 
        RELEASE(vmtx);
375
 
 
376
 
    {
377
 
        int max_count = -1;
378
 
 
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];
383
 
                g->dw = i;
384
 
            }
385
 
        }
386
 
    }
387
 
    RELEASE(w_stat);
388
 
 
389
 
    qsort(g->gd, g->num_glyphs, sizeof(struct tt_glyph_desc), glyf_cmp);
390
 
    {
391
 
        USHORT prev, last_advw;
392
 
        char *p, *q;
393
 
        int padlen, num_hm_known;
394
 
 
395
 
        glyf_table_size = 0UL;
396
 
        num_hm_known = 0;
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;
403
 
                num_hm_known = 1;
404
 
            }
405
 
        }
406
 
        /* All advance widths are same. */
407
 
        if (!num_hm_known) {
408
 
            hhea->numberOfHMetrics = 1;
409
 
        }
410
 
        hmtx_table_size = hhea->numberOfHMetrics * 2 + (g->last_gid + 1) * 2;
411
 
 
412
 
        /*
413
 
         * Choosing short format does not always give good result
414
 
         * when compressed. Sometimes increases size.
415
 
         */
416
 
        if (glyf_table_size < 0x20000UL) {
417
 
            head->indexToLocFormat = 0;
418
 
            loca_table_size = (g->last_gid + 2) * 2;
419
 
        } else {
420
 
            head->indexToLocFormat = 1;
421
 
            loca_table_size = (g->last_gid + 2) * 4;
422
 
        }
423
 
 
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);
427
 
 
428
 
        offset = 0UL;
429
 
        prev = 0;
430
 
        for (i = 0; i < g->num_glyphs; i++) {
431
 
            long gap, j;
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);
438
 
                }
439
 
                p += sfnt_put_short(p, 0);
440
 
                if (head->indexToLocFormat == 0) {
441
 
                    q += sfnt_put_ushort(q, (USHORT) (offset / 2));
442
 
                } else {
443
 
                    q += sfnt_put_ulong(q, offset);
444
 
                }
445
 
            }
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);
449
 
            }
450
 
            p += sfnt_put_short(p, g->gd[i].lsb);
451
 
            if (head->indexToLocFormat == 0) {
452
 
                q += sfnt_put_ushort(q, (USHORT) (offset / 2));
453
 
            } else {
454
 
                q += sfnt_put_ulong(q, offset);
455
 
            }
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;
459
 
            prev = g->gd[i].gid;
460
 
            /* free data here since it consume much memory */
461
 
            RELEASE(g->gd[i].data);
462
 
            g->gd[i].length = 0;
463
 
            g->gd[i].data = NULL;
464
 
        }
465
 
        if (head->indexToLocFormat == 0) {
466
 
            q += sfnt_put_ushort(q, (USHORT) (offset / 2));
467
 
        } else {
468
 
            q += sfnt_put_ulong(q, offset);
469
 
        }
470
 
 
471
 
        sfnt_set_table(sfont, "hmtx", (char *) hmtx_table_data,
472
 
                       hmtx_table_size);
473
 
        sfnt_set_table(sfont, "loca", (char *) loca_table_data,
474
 
                       loca_table_size);
475
 
        sfnt_set_table(sfont, "glyf", (char *) glyf_table_data,
476
 
                       glyf_table_size);
477
 
    }
478
 
 
479
 
    head->checkSumAdjustment = 0;
480
 
    maxp->numGlyphs = g->last_gid + 1;
481
 
 
482
 
    /* TODO */
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);
486
 
    RELEASE(maxp);
487
 
    RELEASE(hhea);
488
 
    RELEASE(head);
489
 
    if (os2)
490
 
        RELEASE(os2);
491
 
 
492
 
    return 0;
493
 
}
494
 
 
495
 
int tt_get_metrics(sfnt * sfont, struct tt_glyphs *g)
496
 
{
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;
502
 
    /* temp */
503
 
    ULONG *location, offset;
504
 
    long i;
505
 
    USHORT *w_stat;
506
 
 
507
 
    ASSERT(g);
508
 
 
509
 
    if (sfont == NULL ||
510
 
#ifdef XETEX
511
 
        sfont->ft_face == NULL
512
 
#elif defined(pdfTeX)
513
 
        sfont->buffer == NULL
514
 
#else
515
 
        sfont->stream == NULL
516
 
#endif
517
 
        )
518
 
        TT_ERROR("File not opened.");
519
 
 
520
 
    if (sfont->type != SFNT_TYPE_TRUETYPE && sfont->type != SFNT_TYPE_TTC)
521
 
        TT_ERROR("Invalid font type");
522
 
 
523
 
    /*
524
 
     * Read head, hhea, maxp, loca:
525
 
     *
526
 
     *   unitsPerEm       --> head
527
 
     *   numHMetrics      --> hhea
528
 
     *   indexToLocFormat --> head
529
 
     *   numGlyphs        --> maxp
530
 
     */
531
 
    head = tt_read_head_table(sfont);
532
 
    hhea = tt_read_hhea_table(sfont);
533
 
    maxp = tt_read_maxp_table(sfont);
534
 
 
535
 
    if (hhea->metricDataFormat != 0)
536
 
        TT_ERROR("Unknown metricDataFormat.");
537
 
 
538
 
    g->emsize = head->unitsPerEm;
539
 
 
540
 
    sfnt_locate_table(sfont, "hmtx");
541
 
    hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics);
542
 
 
543
 
    os2 = tt_read_os2__table(sfont);
544
 
    g->default_advh = os2->sTypoAscender - os2->sTypoDescender;
545
 
    g->default_tsb = g->default_advh - os2->sTypoAscender;
546
 
 
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");
551
 
        vmtx =
552
 
            tt_read_longMetrics(sfont, maxp->numGlyphs,
553
 
                                vhea->numOfLongVerMetrics);
554
 
        RELEASE(vhea);
555
 
    } else {
556
 
        vmtx = NULL;
557
 
    }
558
 
 
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);
567
 
    } else {
568
 
        TT_ERROR("Unknown IndexToLocFormat.");
569
 
    }
570
 
 
571
 
    w_stat = NEW(g->emsize + 2, USHORT);
572
 
    memset(w_stat, 0, sizeof(USHORT) * (g->emsize + 2));
573
 
    /*
574
 
     * Read glyf table.
575
 
     */
576
 
    offset = sfnt_locate_table(sfont, "glyf");
577
 
    for (i = 0; i < g->num_glyphs; i++) {
578
 
        USHORT gid;             /* old gid */
579
 
        ULONG loc, len;
580
 
        SHORT number_of_contours;
581
 
 
582
 
        gid = g->gd[i].ogid;
583
 
        if (gid >= maxp->numGlyphs)
584
 
            TT_ERROR("Invalid glyph index (gid %u)", gid);
585
 
 
586
 
        loc = location[gid];
587
 
        len = location[gid + 1] - loc;
588
 
        g->gd[i].advw = hmtx[gid].advance;
589
 
        g->gd[i].lsb = hmtx[gid].sideBearing;
590
 
        if (vmtx) {
591
 
            g->gd[i].advh = vmtx[gid].advance;
592
 
            g->gd[i].tsb = vmtx[gid].sideBearing;
593
 
        } else {
594
 
            g->gd[i].advh = g->default_advh;
595
 
            g->gd[i].tsb = g->default_tsb;
596
 
        }
597
 
        g->gd[i].length = len;
598
 
        g->gd[i].data = NULL;
599
 
 
600
 
        if (g->gd[i].advw <= g->emsize) {
601
 
            w_stat[g->gd[i].advw] += 1;
602
 
        } else {
603
 
            w_stat[g->emsize + 1] += 1; /* larger than em */
604
 
        }
605
 
 
606
 
        if (len == 0) {         /* Does not contains any data. */
607
 
            continue;
608
 
        } else if (len < 10) {
609
 
            TT_ERROR("Invalid TrueType glyph data (gid %u).", gid);
610
 
        }
611
 
 
612
 
        sfnt_seek_set(sfont, offset + loc);
613
 
        number_of_contours = sfnt_get_short(sfont);
614
 
 
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);
620
 
        /* _FIXME_ */
621
 
#if  1
622
 
        if (!vmtx)              /* vertOriginY == sTypeAscender */
623
 
            g->gd[i].tsb = g->default_advh - g->default_tsb - g->gd[i].ury;
624
 
#endif
625
 
    }
626
 
    RELEASE(location);
627
 
    RELEASE(hmtx);
628
 
    RELEASE(maxp);
629
 
    RELEASE(hhea);
630
 
    RELEASE(head);
631
 
    RELEASE(os2);
632
 
 
633
 
    if (vmtx)
634
 
        RELEASE(vmtx);
635
 
 
636
 
    {
637
 
        int max_count = -1;
638
 
 
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];
643
 
                g->dw = i;
644
 
            }
645
 
        }
646
 
    }
647
 
    RELEASE(w_stat);
648
 
 
649
 
 
650
 
    return 0;
651
 
}