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

« back to all changes in this revision

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

  • 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.w
 
2
%  
 
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>
 
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
@* Subsetting glyf, updating loca, hmtx, etc.
 
23
 
 
24
@ @c
 
25
#include "ptexlib.h"
 
26
 
 
27
#include "font/sfnt.h"
 
28
#include "font/tt_table.h"
 
29
#include "font/tt_glyf.h"
 
30
#include "font/writettf.h"
 
31
 
 
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 $";
 
35
 
 
36
@ @c
 
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 = (USHORT) (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] =
 
108
            (unsigned char) (g->used_slot[new_gid /
 
109
                                          8] | (1 << (7 - (new_gid % 8))));
 
110
        g->num_glyphs++;
 
111
    }
 
112
 
 
113
    if (new_gid > g->last_gid) {
 
114
        g->last_gid = new_gid;
 
115
    }
 
116
 
 
117
    return new_gid;
 
118
}
 
119
 
 
120
 
 
121
@ Initialization
 
122
@c
 
123
struct tt_glyphs *tt_build_init(void)
 
124
{
 
125
    struct tt_glyphs *g;
 
126
 
 
127
    g = NEW(1, struct tt_glyphs);
 
128
 
 
129
    g->num_glyphs = 0;
 
130
    g->max_glyphs = 0;
 
131
    g->last_gid = 0;
 
132
    g->emsize = 1;
 
133
    g->default_advh = 0;
 
134
    g->default_tsb = 0;
 
135
    g->gd = NULL;
 
136
    g->used_slot = NEW(8192, unsigned char);
 
137
    memset(g->used_slot, 0, 8192);
 
138
    tt_add_glyph(g, 0, 0);
 
139
 
 
140
    return g;
 
141
}
 
142
 
 
143
void tt_build_finish(struct tt_glyphs *g)
 
144
{
 
145
    if (g) {
 
146
        if (g->gd) {
 
147
            USHORT idx;
 
148
            for (idx = 0; idx < g->num_glyphs; idx++) {
 
149
                if (g->gd[idx].data)
 
150
                    RELEASE(g->gd[idx].data);
 
151
            }
 
152
            RELEASE(g->gd);
 
153
        }
 
154
        if (g->used_slot)
 
155
            RELEASE(g->used_slot);
 
156
        RELEASE(g);
 
157
    }
 
158
}
 
159
 
 
160
static int glyf_cmp(const void *v1, const void *v2)
 
161
{
 
162
    int cmp = 0;
 
163
    const struct tt_glyph_desc *sv1, *sv2;
 
164
 
 
165
    sv1 = (const struct tt_glyph_desc *) v1;
 
166
    sv2 = (const struct tt_glyph_desc *) v2;
 
167
 
 
168
    if (sv1->gid == sv2->gid)
 
169
        cmp = 0;
 
170
    else if (sv1->gid < sv2->gid)
 
171
        cmp = -1;
 
172
    else
 
173
        cmp = 1;
 
174
 
 
175
    return cmp;
 
176
}
 
177
 
 
178
@ @c
 
179
int tt_build_tables(sfnt * sfont, struct tt_glyphs *g)
 
180
{
 
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;
 
190
    /* temp */
 
191
    ULONG *location, offset;
 
192
    long i;
 
193
    USHORT *w_stat;             /* Estimate most frequently appeared width */
 
194
 
 
195
    ASSERT(g);
 
196
 
 
197
    if (sfont->type != SFNT_TYPE_TRUETYPE && sfont->type != SFNT_TYPE_TTC)
 
198
        TT_ERROR("Invalid font type");
 
199
 
 
200
    if (g->num_glyphs > NUM_GLYPH_LIMIT)
 
201
        TT_ERROR("Too many glyphs.");
 
202
 
 
203
    /*
 
204
     Read head, hhea, maxp, loca:
 
205
     
 
206
     unitsPerEm       --> head
 
207
 
 
208
     numHMetrics      --> hhea
 
209
 
 
210
     indexToLocFormat --> head
 
211
     
 
212
     numGlyphs        --> maxp
 
213
     */
 
214
    head = tt_read_head_table(sfont);
 
215
    hhea = tt_read_hhea_table(sfont);
 
216
    maxp = tt_read_maxp_table(sfont);
 
217
 
 
218
    if (hhea->metricDataFormat != 0)
 
219
        TT_ERROR("Unknown metricDataFormat.");
 
220
 
 
221
    g->emsize = head->unitsPerEm;
 
222
 
 
223
    sfnt_locate_table(sfont, "hmtx");
 
224
    hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics);
 
225
 
 
226
    os2 = tt_read_os2__table(sfont);
 
227
    if (os2) {
 
228
        g->default_advh = (USHORT) (os2->sTypoAscender - os2->sTypoDescender);
 
229
        g->default_tsb = (SHORT) (g->default_advh - os2->sTypoAscender);
 
230
 
 
231
        /* dvipdfmx does this elsewhere! */
 
232
        fd_cur->font_dim[STEMV_CODE].val =
 
233
            (os2->usWeightClass / 65) * (os2->usWeightClass / 65) + 50;
 
234
    }
 
235
 
 
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");
 
240
        vmtx =
 
241
            tt_read_longMetrics(sfont, maxp->numGlyphs,
 
242
                                vhea->numOfLongVerMetrics);
 
243
        RELEASE(vhea);
 
244
    } else {
 
245
        vmtx = NULL;
 
246
    }
 
247
 
 
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);
 
256
    } else {
 
257
        TT_ERROR("Unknown IndexToLocFormat.");
 
258
    }
 
259
 
 
260
    w_stat = NEW(g->emsize + 2, USHORT);
 
261
    memset(w_stat, 0,
 
262
           (size_t) (sizeof(USHORT) * ((long unsigned) g->emsize + 2)));
 
263
    /*
 
264
     * Read glyf table.
 
265
     */
 
266
    offset = sfnt_locate_table(sfont, "glyf");
 
267
    /*
 
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.
 
273
     */
 
274
    for (i = 0; i < NUM_GLYPH_LIMIT; i++) {
 
275
        USHORT gid;             /* old gid */
 
276
        ULONG loc, len;
 
277
        BYTE *p, *endptr;
 
278
        SHORT number_of_contours;
 
279
 
 
280
        if (i >= g->num_glyphs) /* finished */
 
281
            break;
 
282
 
 
283
        gid = g->gd[i].ogid;
 
284
        if (gid >= maxp->numGlyphs)
 
285
            TT_ERROR("Invalid glyph index (gid %u)", gid);
 
286
 
 
287
        loc = location[gid];
 
288
        len = location[gid + 1] - loc;
 
289
        g->gd[i].advw = hmtx[gid].advance;
 
290
        g->gd[i].lsb = hmtx[gid].sideBearing;
 
291
        if (vmtx) {
 
292
            g->gd[i].advh = vmtx[gid].advance;
 
293
            g->gd[i].tsb = vmtx[gid].sideBearing;
 
294
        } else {
 
295
            g->gd[i].advh = g->default_advh;
 
296
            g->gd[i].tsb = g->default_tsb;
 
297
        }
 
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]++;
 
302
        } else {
 
303
            w_stat[g->emsize + 1]++;    /* larger than em */
 
304
        }
 
305
 
 
306
        if (len == 0) {         /* Does not contains any data. */
 
307
            continue;
 
308
        } else if (len < 10) {
 
309
            TT_ERROR("Invalid TrueType glyph data (gid %u).", gid);
 
310
        }
 
311
 
 
312
        g->gd[i].data = p = NEW(len, BYTE);
 
313
        endptr = p + len;
 
314
 
 
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);
 
318
 
 
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);
 
324
        /* |_FIXME_| */
 
325
#if  1
 
326
        if (!vmtx)              /* |vertOriginY == sTypeAscender| */
 
327
            g->gd[i].tsb =
 
328
                (SHORT) (g->default_advh - g->default_tsb - g->gd[i].ury);
 
329
#endif
 
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);
 
334
 
 
335
        /* Read evrything else. */
 
336
        sfnt_read(p, (int) len - 10, sfont);
 
337
        /*
 
338
         Fix GIDs of composite glyphs.
 
339
         */
 
340
        if (number_of_contours < 0) {
 
341
            USHORT flags, cgid, new_gid;        /* flag, gid of a component */
 
342
            do {
 
343
                if (p >= endptr)
 
344
                    TT_ERROR("Invalid TrueType glyph data (gid %u): %u bytes",
 
345
                             gid, (unsigned int) len);
 
346
                /*
 
347
                 * Flags and gid of component glyph are both USHORT.
 
348
                 */
 
349
                flags = (USHORT) (((*p) << 8) | *(p + 1));
 
350
                p += 2;
 
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);
 
355
                }
 
356
                new_gid = tt_find_glyph(g, cgid);
 
357
                if (new_gid == 0) {
 
358
                    new_gid = tt_add_glyph(g, cgid, find_empty_slot(g));
 
359
                }
 
360
                p += sfnt_put_ushort(p, new_gid);
 
361
                /*
 
362
                 * Just skip remaining part.
 
363
                 */
 
364
                p += (flags & ARG_1_AND_2_ARE_WORDS) ? 4 : 2;
 
365
                if (flags & WE_HAVE_A_SCALE)    /* F2Dot14 */
 
366
                    p += 2;
 
367
                else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)      /* F2Dot14 x 2 */
 
368
                    p += 4;
 
369
                else if (flags & WE_HAVE_A_TWO_BY_TWO)  /* F2Dot14 x 4 */
 
370
                    p += 8;
 
371
            } while (flags & MORE_COMPONENTS);
 
372
            /*
 
373
             TrueType instructions comes here:
 
374
 
 
375
             |length_of_instruction| (|ushort|)
 
376
              
 
377
             instruction (|byte * length_of_instruction|)
 
378
             */
 
379
        }
 
380
    }
 
381
    RELEASE(location);
 
382
    RELEASE(hmtx);
 
383
    if (vmtx)
 
384
        RELEASE(vmtx);
 
385
 
 
386
    {
 
387
        int max_count = -1;
 
388
 
 
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];
 
393
                g->dw = (USHORT) i;
 
394
            }
 
395
        }
 
396
    }
 
397
    RELEASE(w_stat);
 
398
 
 
399
    qsort(g->gd, g->num_glyphs, sizeof(struct tt_glyph_desc), glyf_cmp);
 
400
    {
 
401
        USHORT prev, last_advw;
 
402
        char *p, *q;
 
403
        int padlen, num_hm_known;
 
404
 
 
405
        glyf_table_size = 0UL;
 
406
        num_hm_known = 0;
 
407
        last_advw = g->gd[g->num_glyphs - 1].advw;
 
408
        for (i = g->num_glyphs - 1; i >= 0; i--) {
 
409
            padlen =
 
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);
 
414
                num_hm_known = 1;
 
415
            }
 
416
        }
 
417
        /* All advance widths are same. */
 
418
        if (!num_hm_known) {
 
419
            hhea->numberOfHMetrics = 1;
 
420
        }
 
421
        hmtx_table_size =
 
422
            (ULONG) (hhea->numberOfHMetrics * 2 + (g->last_gid + 1) * 2);
 
423
 
 
424
        /*
 
425
         Choosing short format does not always give good result
 
426
         when compressed. Sometimes increases size.
 
427
         */
 
428
        if (glyf_table_size < 0x20000UL) {
 
429
            head->indexToLocFormat = 0;
 
430
            loca_table_size = (ULONG) ((g->last_gid + 2) * 2);
 
431
        } else {
 
432
            head->indexToLocFormat = 1;
 
433
            loca_table_size = (ULONG) ((g->last_gid + 2) * 4);
 
434
        }
 
435
 
 
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);
 
439
 
 
440
        offset = 0UL;
 
441
        prev = 0;
 
442
        for (i = 0; i < g->num_glyphs; i++) {
 
443
            long gap, j;
 
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);
 
450
                }
 
451
                p += sfnt_put_short(p, 0);
 
452
                if (head->indexToLocFormat == 0) {
 
453
                    q += sfnt_put_ushort(q, (USHORT) (offset / 2));
 
454
                } else {
 
455
                    q += sfnt_put_ulong(q, (LONG) offset);
 
456
                }
 
457
            }
 
458
            padlen =
 
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);
 
462
            }
 
463
            p += sfnt_put_short(p, g->gd[i].lsb);
 
464
            if (head->indexToLocFormat == 0) {
 
465
                q += sfnt_put_ushort(q, (USHORT) (offset / 2));
 
466
            } else {
 
467
                q += sfnt_put_ulong(q, (LONG) offset);
 
468
            }
 
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);
 
473
            prev = g->gd[i].gid;
 
474
            /* free data here since it consume much memory */
 
475
            RELEASE(g->gd[i].data);
 
476
            g->gd[i].length = 0;
 
477
            g->gd[i].data = NULL;
 
478
        }
 
479
        if (head->indexToLocFormat == 0) {
 
480
            q += sfnt_put_ushort(q, (USHORT) (offset / 2));
 
481
        } else {
 
482
            q += sfnt_put_ulong(q, (LONG) offset);
 
483
        }
 
484
 
 
485
        sfnt_set_table(sfont, "hmtx", (char *) hmtx_table_data,
 
486
                       hmtx_table_size);
 
487
        sfnt_set_table(sfont, "loca", (char *) loca_table_data,
 
488
                       loca_table_size);
 
489
        sfnt_set_table(sfont, "glyf", (char *) glyf_table_data,
 
490
                       glyf_table_size);
 
491
    }
 
492
 
 
493
    head->checkSumAdjustment = 0;
 
494
    maxp->numGlyphs = (USHORT) (g->last_gid + 1);
 
495
 
 
496
    /* TODO */
 
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);
 
500
    RELEASE(maxp);
 
501
    RELEASE(hhea);
 
502
    RELEASE(head);
 
503
    if (os2)
 
504
        RELEASE(os2);
 
505
 
 
506
    return 0;
 
507
}
 
508
 
 
509
int tt_get_metrics(sfnt * sfont, struct tt_glyphs *g)
 
510
{
 
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;
 
516
    /* temp */
 
517
    ULONG *location, offset;
 
518
    long i;
 
519
    USHORT *w_stat;
 
520
 
 
521
    ASSERT(g);
 
522
 
 
523
    if (sfont == NULL ||
 
524
#ifdef XETEX
 
525
        sfont->ft_face == NULL
 
526
#elif defined(pdfTeX)
 
527
        sfont->buffer == NULL
 
528
#else
 
529
        sfont->stream == NULL
 
530
#endif
 
531
        )
 
532
        TT_ERROR("File not opened.");
 
533
 
 
534
    if (sfont->type != SFNT_TYPE_TRUETYPE && sfont->type != SFNT_TYPE_TTC)
 
535
        TT_ERROR("Invalid font type");
 
536
 
 
537
    /*
 
538
     Read head, hhea, maxp, loca:
 
539
     
 
540
     unitsPerEm       --> head
 
541
 
 
542
     numHMetrics      --> hhea
 
543
 
 
544
     indexToLocFormat --> head
 
545
 
 
546
     numGlyphs        --> maxp
 
547
     */
 
548
    head = tt_read_head_table(sfont);
 
549
    hhea = tt_read_hhea_table(sfont);
 
550
    maxp = tt_read_maxp_table(sfont);
 
551
 
 
552
    if (hhea->metricDataFormat != 0)
 
553
        TT_ERROR("Unknown metricDataFormat.");
 
554
 
 
555
    g->emsize = head->unitsPerEm;
 
556
 
 
557
    sfnt_locate_table(sfont, "hmtx");
 
558
    hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics);
 
559
 
 
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);
 
563
 
 
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");
 
568
        vmtx =
 
569
            tt_read_longMetrics(sfont, maxp->numGlyphs,
 
570
                                vhea->numOfLongVerMetrics);
 
571
        RELEASE(vhea);
 
572
    } else {
 
573
        vmtx = NULL;
 
574
    }
 
575
 
 
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);
 
584
    } else {
 
585
        TT_ERROR("Unknown IndexToLocFormat.");
 
586
    }
 
587
 
 
588
    w_stat = NEW(g->emsize + 2, USHORT);
 
589
    memset(w_stat, 0, (size_t) ((int) sizeof(USHORT) * (g->emsize + 2)));
 
590
    /*
 
591
     Read glyf table.
 
592
     */
 
593
    offset = sfnt_locate_table(sfont, "glyf");
 
594
    for (i = 0; i < g->num_glyphs; i++) {
 
595
        USHORT gid;             /* old gid */
 
596
        ULONG loc, len;
 
597
        SHORT number_of_contours;
 
598
 
 
599
        gid = g->gd[i].ogid;
 
600
        if (gid >= maxp->numGlyphs)
 
601
            TT_ERROR("Invalid glyph index (gid %u)", gid);
 
602
 
 
603
        loc = location[gid];
 
604
        len = location[gid + 1] - loc;
 
605
        g->gd[i].advw = hmtx[gid].advance;
 
606
        g->gd[i].lsb = hmtx[gid].sideBearing;
 
607
        if (vmtx) {
 
608
            g->gd[i].advh = vmtx[gid].advance;
 
609
            g->gd[i].tsb = vmtx[gid].sideBearing;
 
610
        } else {
 
611
            g->gd[i].advh = g->default_advh;
 
612
            g->gd[i].tsb = g->default_tsb;
 
613
        }
 
614
        g->gd[i].length = len;
 
615
        g->gd[i].data = NULL;
 
616
 
 
617
        if (g->gd[i].advw <= g->emsize) {
 
618
            w_stat[g->gd[i].advw]++;
 
619
        } else {
 
620
            w_stat[g->emsize + 1]++;    /* larger than em */
 
621
        }
 
622
 
 
623
        if (len == 0) {         /* Does not contains any data. */
 
624
            continue;
 
625
        } else if (len < 10) {
 
626
            TT_ERROR("Invalid TrueType glyph data (gid %u).", gid);
 
627
        }
 
628
 
 
629
        sfnt_seek_set(sfont, (long) (offset + loc));
 
630
        number_of_contours = sfnt_get_short(sfont);
 
631
 
 
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);
 
637
        /* |_FIXME_| */
 
638
#if  1
 
639
        if (!vmtx)              /* |vertOriginY == sTypeAscender| */
 
640
            g->gd[i].tsb =
 
641
                (SHORT) (g->default_advh - g->default_tsb - g->gd[i].ury);
 
642
#endif
 
643
    }
 
644
    RELEASE(location);
 
645
    RELEASE(hmtx);
 
646
    RELEASE(maxp);
 
647
    RELEASE(hhea);
 
648
    RELEASE(head);
 
649
    RELEASE(os2);
 
650
 
 
651
    if (vmtx)
 
652
        RELEASE(vmtx);
 
653
 
 
654
    {
 
655
        int max_count = -1;
 
656
 
 
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];
 
661
                g->dw = (USHORT) i;
 
662
            }
 
663
        }
 
664
    }
 
665
    RELEASE(w_stat);
 
666
 
 
667
 
 
668
    return 0;
 
669
}