Back to index

texmacs  1.0.7.15
tt_glyf.c
Go to the documentation of this file.
00001 /*  $Header: /home/cvsroot/dvipdfmx/src/tt_glyf.c,v 1.4 2008/05/08 18:51:59 chofchof Exp $
00002     
00003     This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
00004 
00005     Copyright (C) 2007 by Jin-Hwan Cho and Shunsaku Hirata,
00006     the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
00007     
00008     This program is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012     
00013     This program is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017     
00018     You should have received a copy of the GNU General Public License
00019     along with this program; if not, write to the Free Software
00020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00021 */
00022 
00023 /*
00024  * Subsetting glyf, updating loca, hmtx, ...
00025  *
00026  */
00027 
00028 #include "config.h"
00029 
00030 #include "system.h"
00031 #include "mem.h"
00032 #include "error.h"
00033 #include "dpxutil.h"
00034 
00035 #include "sfnt.h"
00036 #include "tt_table.h"
00037 #include "tt_glyf.h"
00038 
00039 #define NUM_GLYPH_LIMIT        65534
00040 #define TABLE_DATA_ALLOC_SIZE  40960
00041 #define GLYPH_ARRAY_ALLOC_SIZE 256
00042 
00043 static USHORT
00044 find_empty_slot (struct tt_glyphs *g)
00045 {
00046   USHORT gid;
00047 
00048   ASSERT(g);
00049 
00050   for (gid = 0; gid < NUM_GLYPH_LIMIT; gid++) {
00051     if (!(g->used_slot[gid/8] & (1 << (7 - (gid % 8)))))
00052       break;
00053   }
00054   if (gid == NUM_GLYPH_LIMIT)
00055     ERROR("No empty glyph slot available.");
00056 
00057   return gid;
00058 }
00059 
00060 USHORT
00061 tt_find_glyph (struct tt_glyphs *g, USHORT gid)
00062 {
00063   USHORT idx, new_gid = 0;
00064 
00065   ASSERT(g);
00066 
00067   for (idx = 0; idx < g->num_glyphs; idx++) {
00068     if (gid == g->gd[idx].ogid) {
00069       new_gid = g->gd[idx].gid;
00070       break;
00071     }
00072   }
00073 
00074   return new_gid;
00075 }
00076 
00077 USHORT
00078 tt_get_index (struct tt_glyphs *g, USHORT gid)
00079 {
00080   USHORT idx;
00081 
00082   ASSERT(g);
00083 
00084   for (idx = 0; idx < g->num_glyphs; idx++) {
00085     if (gid == g->gd[idx].gid)
00086       break;
00087   }
00088   if (idx == g->num_glyphs)
00089     idx = 0;
00090 
00091   return idx;
00092 }
00093 
00094 USHORT
00095 tt_add_glyph (struct tt_glyphs *g, USHORT gid, USHORT new_gid)
00096 {
00097   ASSERT(g);
00098 
00099   if (g->used_slot[new_gid/8] & (1 << (7 - (new_gid % 8)))) {
00100     WARN("Slot %u already used.", new_gid);
00101   } else {
00102     if (g->num_glyphs+1 >= NUM_GLYPH_LIMIT)
00103       ERROR("Too many glyphs.");
00104 
00105     if (g->num_glyphs >= g->max_glyphs) {
00106       g->max_glyphs += GLYPH_ARRAY_ALLOC_SIZE;
00107       g->gd = RENEW(g->gd, g->max_glyphs, struct tt_glyph_desc);
00108     }
00109     g->gd[g->num_glyphs].gid  = new_gid;
00110     g->gd[g->num_glyphs].ogid = gid;
00111     g->gd[g->num_glyphs].length = 0;
00112     g->gd[g->num_glyphs].data   = NULL;
00113     g->used_slot[new_gid/8] |= (1 << (7 - (new_gid % 8)));
00114     g->num_glyphs += 1;
00115   }
00116 
00117   if (new_gid > g->last_gid) {
00118     g->last_gid = new_gid;
00119   }
00120 
00121   return new_gid;
00122 }
00123 
00124 /*
00125  * Initialization
00126  */
00127 struct tt_glyphs *
00128 tt_build_init (void)
00129 {
00130   struct tt_glyphs *g;
00131 
00132   g = NEW(1, struct tt_glyphs);
00133 
00134   g->num_glyphs  = 0;
00135   g->max_glyphs  = 0;
00136   g->last_gid    = 0;
00137   g->emsize      = 1;
00138   g->default_advh = 0;
00139   g->default_tsb  = 0;
00140   g->gd = NULL;
00141   g->used_slot = NEW(8192, unsigned char);
00142   memset(g->used_slot, 0, 8192);
00143   tt_add_glyph(g, 0, 0);
00144 
00145   return g;
00146 }
00147 
00148 void
00149 tt_build_finish (struct tt_glyphs *g)
00150 {
00151   if (g) {
00152     if (g->gd) {
00153       USHORT idx;
00154       for (idx = 0; idx < g->num_glyphs; idx++) {
00155        if (g->gd[idx].data)
00156          RELEASE(g->gd[idx].data);
00157       }
00158       RELEASE(g->gd);
00159     }
00160     if (g->used_slot)
00161       RELEASE(g->used_slot);
00162     RELEASE(g);
00163   }
00164 }
00165 
00166 static int CDECL 
00167 glyf_cmp (const void *v1, const void *v2)
00168 {
00169   int cmp = 0;
00170   struct tt_glyph_desc *sv1, *sv2;
00171 
00172   sv1 = (struct tt_glyph_desc *) v1;
00173   sv2 = (struct tt_glyph_desc *) v2;
00174 
00175   if (sv1->gid == sv2->gid)
00176     cmp = 0;
00177   else if (sv1->gid < sv2->gid)
00178     cmp = -1;
00179   else
00180     cmp = 1;
00181     
00182   return cmp;
00183 }
00184 
00185 /*
00186  * TrueType outline data.
00187  */
00188 #define ARG_1_AND_2_ARE_WORDS     (1 << 0)
00189 #define ARGS_ARE_XY_VALUES        (1 << 1)
00190 #define ROUND_XY_TO_GRID          (1 << 2)
00191 #define WE_HAVE_A_SCALE           (1 << 3)
00192 #define RESERVED                  (1 << 4)
00193 #define MORE_COMPONENT            (1 << 5)
00194 #define WE_HAVE_AN_X_AND_Y_SCALE  (1 << 6)
00195 #define WE_HAVE_A_TWO_BY_TWO      (1 << 7)
00196 #define WE_HAVE_INSTRUCTIONS      (1 << 8)
00197 #define USE_MY_METRICS            (1 << 9)
00198 
00199 int
00200 tt_build_tables (sfnt *sfont, struct tt_glyphs *g)
00201 {
00202   char  *hmtx_table_data = NULL, *loca_table_data = NULL;
00203   char  *glyf_table_data = NULL;
00204   ULONG  hmtx_table_size, loca_table_size, glyf_table_size;
00205   /* some information available from other TrueType table */
00206   struct tt_head_table *head = NULL;
00207   struct tt_hhea_table *hhea = NULL;
00208   struct tt_maxp_table *maxp = NULL;
00209   struct tt_longMetrics *hmtx, *vmtx = NULL;
00210   struct tt_os2__table  *os2;
00211   /* temp */
00212   ULONG  *location, offset;
00213   long    i;
00214   USHORT *w_stat; /* Estimate most frequently appeared width */
00215 
00216   ASSERT(g);
00217 
00218   if (sfont == NULL || sfont->stream == NULL)
00219     ERROR("File not opened.");
00220 
00221   if (sfont->type != SFNT_TYPE_TRUETYPE &&
00222       sfont->type != SFNT_TYPE_TTC &&
00223       sfont->type != SFNT_TYPE_DFONT)
00224     ERROR("Invalid font type");
00225 
00226   if (g->num_glyphs > NUM_GLYPH_LIMIT)
00227     ERROR("Too many glyphs.");
00228 
00229   /*
00230    * Read head, hhea, maxp, loca:
00231    *
00232    *   unitsPerEm       --> head
00233    *   numHMetrics      --> hhea
00234    *   indexToLocFormat --> head
00235    *   numGlyphs        --> maxp
00236    */
00237   head = tt_read_head_table(sfont);
00238   hhea = tt_read_hhea_table(sfont);
00239   maxp = tt_read_maxp_table(sfont);
00240 
00241   if (hhea->metricDataFormat != 0)
00242     ERROR("Unknown metricDataFormat.");
00243 
00244   g->emsize = head->unitsPerEm;
00245 
00246   sfnt_locate_table(sfont, "hmtx");
00247   hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numOfLongHorMetrics, hhea->numOfExSideBearings);
00248 
00249   os2 = tt_read_os2__table(sfont);
00250   g->default_advh = os2->sTypoAscender - os2->sTypoDescender;
00251   g->default_tsb  = g->default_advh - os2->sTypoAscender;
00252 
00253   if (sfnt_find_table_pos(sfont, "vmtx") > 0) {
00254     struct tt_vhea_table *vhea;
00255     vhea = tt_read_vhea_table(sfont);
00256     sfnt_locate_table(sfont, "vmtx");
00257     vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics, vhea->numOfExSideBearings);
00258     RELEASE(vhea);
00259   } else {
00260     vmtx = NULL;
00261   }
00262 
00263   sfnt_locate_table(sfont, "loca");
00264   location = NEW(maxp->numGlyphs + 1, ULONG);
00265   if (head->indexToLocFormat == 0) {
00266     for (i = 0; i <= maxp->numGlyphs; i++)
00267       location[i] = 2*((ULONG) sfnt_get_ushort(sfont));
00268   } else if (head->indexToLocFormat == 1) {
00269     for (i = 0; i <= maxp->numGlyphs; i++)
00270       location[i] = sfnt_get_ulong(sfont);
00271   } else {
00272     ERROR("Unknown IndexToLocFormat.");
00273   }
00274 
00275   w_stat = NEW(g->emsize+2, USHORT);
00276   memset(w_stat, 0, sizeof(USHORT)*(g->emsize+2));
00277   /*
00278    * Read glyf table.
00279    */
00280   offset = sfnt_locate_table(sfont, "glyf");
00281   /*
00282    * The num_glyphs may grow when composite glyph is found.
00283    * A component of glyph refered by a composite glyph is appended
00284    * to used_glyphs if it is not already registered in used_glyphs.
00285    * Glyph programs of composite glyphs are modified so that it
00286    * correctly refer to new gid of their components.
00287    */
00288   for (i = 0; i < NUM_GLYPH_LIMIT; i++) {
00289     USHORT gid;     /* old gid */
00290     ULONG  loc, len;
00291     BYTE  *p, *endptr;
00292     SHORT  number_of_contours;
00293 
00294     if (i >= g->num_glyphs) /* finished */
00295       break;
00296 
00297     gid = g->gd[i].ogid;
00298     if (gid >= maxp->numGlyphs)
00299       ERROR("Invalid glyph index (gid %u)", gid);
00300 
00301     loc = location[gid];
00302     len = location[gid+1] - loc;
00303     g->gd[i].advw = hmtx[gid].advance;
00304     g->gd[i].lsb  = hmtx[gid].sideBearing;
00305     if (vmtx) {
00306       g->gd[i].advh = vmtx[gid].advance;
00307       g->gd[i].tsb  = vmtx[gid].sideBearing;
00308     } else {
00309       g->gd[i].advh = g->default_advh;
00310       g->gd[i].tsb  = g->default_tsb;
00311     }
00312     g->gd[i].length = len;
00313     g->gd[i].data   = NULL;
00314     if (g->gd[i].advw <= g->emsize) {
00315       w_stat[g->gd[i].advw] += 1;
00316     } else {
00317       w_stat[g->emsize+1]   += 1; /* larger than em */
00318     }
00319 
00320     if (len == 0) { /* Does not contains any data. */
00321       continue;
00322     } else if (len < 10) {
00323       ERROR("Invalid TrueType glyph data (gid %u).", gid);
00324     }
00325 
00326     g->gd[i].data = p = NEW(len, BYTE);
00327     endptr = p + len;
00328 
00329     sfnt_seek_set(sfont, offset+loc);
00330     number_of_contours = sfnt_get_short(sfont);
00331     p += sfnt_put_short(p, number_of_contours);
00332 
00333     /* BoundingBox: FWord x 4 */
00334     g->gd[i].llx = sfnt_get_short(sfont);
00335     g->gd[i].lly = sfnt_get_short(sfont);
00336     g->gd[i].urx = sfnt_get_short(sfont);
00337     g->gd[i].ury = sfnt_get_short(sfont);
00338     /* _FIXME_ */
00339 #if  1
00340     if (!vmtx) /* vertOriginY == sTypeAscender */
00341       g->gd[i].tsb = g->default_advh - g->default_tsb - g->gd[i].ury;
00342 #endif
00343     p += sfnt_put_short(p, g->gd[i].llx);
00344     p += sfnt_put_short(p, g->gd[i].lly);
00345     p += sfnt_put_short(p, g->gd[i].urx);
00346     p += sfnt_put_short(p, g->gd[i].ury);
00347 
00348     /* Read evrything else. */
00349     sfnt_read(p, len - 10, sfont);
00350     /*
00351      * Fix GIDs of composite glyphs.
00352      */
00353     if (number_of_contours < 0) {
00354       USHORT flags, cgid, new_gid; /* flag, gid of a component */
00355       do {
00356        if (p >= endptr)
00357          ERROR("Invalid TrueType glyph data (gid %u): %u bytes", gid, len);
00358        /*
00359         * Flags and gid of component glyph are both USHORT.
00360         */
00361        flags = ((*p) << 8)| *(p+1);
00362        p += 2;
00363        cgid  = ((*p) << 8)| *(p+1);
00364        if (cgid >= maxp->numGlyphs) {
00365          ERROR("Invalid gid (%u > %u) in composite glyph %u.", cgid, maxp->numGlyphs, gid);
00366        }
00367        new_gid = tt_find_glyph(g, cgid);
00368        if (new_gid == 0) {
00369          new_gid = tt_add_glyph(g, cgid, find_empty_slot(g));
00370        }
00371        p += sfnt_put_ushort(p, new_gid);
00372        /*
00373         * Just skip remaining part.
00374         */
00375        p += (flags & ARG_1_AND_2_ARE_WORDS) ? 4 : 2;
00376        if (flags & WE_HAVE_A_SCALE) /* F2Dot14 */
00377          p += 2;
00378        else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) /* F2Dot14 x 2 */
00379          p += 4;
00380        else if (flags & WE_HAVE_A_TWO_BY_TWO) /* F2Dot14 x 4 */
00381          p += 8;
00382       } while (flags & MORE_COMPONENT);
00383       /*
00384        * TrueType instructions comes here:
00385        *  length_of_instruction (ushort)
00386        *  instruction (byte * length_of_instruction)
00387        */
00388     }
00389   }
00390   RELEASE(location);
00391   RELEASE(hmtx);
00392   if (vmtx)
00393     RELEASE(vmtx);
00394 
00395   {
00396     int max_count = -1;
00397 
00398     g->dw = g->gd[0].advw;
00399     for (i = 0; i < g->emsize + 1; i++) {
00400       if (w_stat[i] > max_count) {
00401        max_count = w_stat[i];
00402        g->dw = i;
00403       }
00404     }
00405   }
00406   RELEASE(w_stat);
00407 
00408   qsort(g->gd, g->num_glyphs, sizeof(struct tt_glyph_desc), glyf_cmp);
00409   {
00410     USHORT prev, last_advw;
00411     char  *p, *q;
00412     int    padlen, num_hm_known;
00413 
00414     glyf_table_size = 0UL;
00415     num_hm_known = 0;
00416     last_advw = g->gd[g->num_glyphs - 1].advw;
00417     for (i = g->num_glyphs - 1; i >= 0; i--) {
00418       padlen = (g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0;
00419       glyf_table_size += g->gd[i].length + padlen;
00420       if (!num_hm_known && last_advw != g->gd[i].advw) {
00421        hhea->numOfLongHorMetrics = g->gd[i].gid + 2;
00422        num_hm_known = 1;
00423       }
00424     }
00425     /* All advance widths are same. */
00426     if (!num_hm_known) {
00427       hhea->numOfLongHorMetrics = 1;
00428     }
00429     hmtx_table_size = hhea->numOfLongHorMetrics * 2 + (g->last_gid + 1) * 2;
00430 
00431     /*
00432      * Choosing short format does not always give good result
00433      * when compressed. Sometimes increases size.
00434      */
00435     if (glyf_table_size < 0x20000UL) {
00436       head->indexToLocFormat = 0;
00437       loca_table_size = (g->last_gid + 2)*2;
00438     } else {
00439       head->indexToLocFormat = 1;
00440       loca_table_size = (g->last_gid + 2)*4;
00441     }
00442 
00443     hmtx_table_data = p = NEW(hmtx_table_size, char);
00444     loca_table_data = q = NEW(loca_table_size, char);
00445     glyf_table_data = NEW(glyf_table_size, char);
00446 
00447     offset = 0UL; prev = 0;
00448     for (i = 0; i < g->num_glyphs; i++) {
00449       long gap, j;
00450       gap = (long) g->gd[i].gid - prev - 1;
00451       for (j = 1; j <= gap; j++) {
00452        if (prev + j == hhea->numOfLongHorMetrics - 1) {
00453          p += sfnt_put_ushort(p, last_advw);
00454        } else if (prev + j < hhea->numOfLongHorMetrics) {
00455          p += sfnt_put_ushort(p, 0);
00456        }
00457        p += sfnt_put_short (p, 0);
00458        if (head->indexToLocFormat == 0) {
00459          q += sfnt_put_ushort(q, (USHORT) (offset/2));
00460        } else {
00461          q += sfnt_put_ulong(q, offset);
00462        }
00463       }
00464       padlen = (g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0;
00465       if (g->gd[i].gid < hhea->numOfLongHorMetrics) {
00466        p += sfnt_put_ushort(p, g->gd[i].advw);
00467       }
00468       p += sfnt_put_short (p, g->gd[i].lsb);
00469       if (head->indexToLocFormat == 0) {
00470        q += sfnt_put_ushort(q, (USHORT) (offset/2));
00471       } else {
00472        q += sfnt_put_ulong(q, offset);
00473       }
00474       memset(glyf_table_data + offset, 0, g->gd[i].length + padlen);
00475       memcpy(glyf_table_data + offset, g->gd[i].data, g->gd[i].length);
00476       offset += g->gd[i].length + padlen;
00477       prev    = g->gd[i].gid;
00478       /* free data here since it consume much memory */
00479       RELEASE(g->gd[i].data);
00480       g->gd[i].length = 0; g->gd[i].data = NULL;
00481     }
00482     if (head->indexToLocFormat == 0) {
00483       q += sfnt_put_ushort(q, (USHORT) (offset/2));
00484     } else {
00485       q += sfnt_put_ulong(q, offset);
00486     }
00487 
00488     sfnt_set_table(sfont, "hmtx", (char *) hmtx_table_data, hmtx_table_size);
00489     sfnt_set_table(sfont, "loca", (char *) loca_table_data, loca_table_size);
00490     sfnt_set_table(sfont, "glyf", (char *) glyf_table_data, glyf_table_size);
00491   }
00492 
00493   head->checkSumAdjustment = 0;
00494   maxp->numGlyphs          = g->last_gid + 1;
00495 
00496   /* TODO */
00497   sfnt_set_table(sfont, "maxp", tt_pack_maxp_table(maxp), TT_MAXP_TABLE_SIZE);
00498   sfnt_set_table(sfont, "hhea", tt_pack_hhea_table(hhea), TT_HHEA_TABLE_SIZE);
00499   sfnt_set_table(sfont, "head", tt_pack_head_table(head), TT_HEAD_TABLE_SIZE);
00500   RELEASE(maxp);
00501   RELEASE(hhea);
00502   RELEASE(head);
00503   RELEASE(os2);
00504 
00505   return 0;
00506 }
00507 
00508 int
00509 tt_get_metrics (sfnt *sfont, struct tt_glyphs *g)
00510 {
00511   struct tt_head_table *head = NULL;
00512   struct tt_hhea_table *hhea = NULL;
00513   struct tt_maxp_table *maxp = NULL;
00514   struct tt_longMetrics *hmtx, *vmtx = NULL;
00515   struct tt_os2__table  *os2;
00516   /* temp */
00517   ULONG  *location, offset;
00518   long    i;
00519   USHORT *w_stat;
00520 
00521   ASSERT(g);
00522 
00523   if (sfont == NULL || sfont->stream == NULL)
00524     ERROR("File not opened.");
00525 
00526   if (sfont->type != SFNT_TYPE_TRUETYPE &&
00527       sfont->type != SFNT_TYPE_TTC &&
00528       sfont->type != SFNT_TYPE_DFONT)
00529     ERROR("Invalid font type");
00530 
00531   /*
00532    * Read head, hhea, maxp, loca:
00533    *
00534    *   unitsPerEm       --> head
00535    *   numHMetrics      --> hhea
00536    *   indexToLocFormat --> head
00537    *   numGlyphs        --> maxp
00538    */
00539   head = tt_read_head_table(sfont);
00540   hhea = tt_read_hhea_table(sfont);
00541   maxp = tt_read_maxp_table(sfont);
00542 
00543   if (hhea->metricDataFormat != 0)
00544     ERROR("Unknown metricDataFormat.");
00545 
00546   g->emsize = head->unitsPerEm;
00547 
00548   sfnt_locate_table(sfont, "hmtx");
00549   hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numOfLongHorMetrics, hhea->numOfExSideBearings);
00550 
00551   os2 = tt_read_os2__table(sfont);
00552   g->default_advh = os2->sTypoAscender - os2->sTypoDescender;
00553   g->default_tsb  = g->default_advh - os2->sTypoAscender;
00554 
00555   if (sfnt_find_table_pos(sfont, "vmtx") > 0) {
00556     struct tt_vhea_table *vhea;
00557     vhea = tt_read_vhea_table(sfont);
00558     sfnt_locate_table(sfont, "vmtx");
00559     vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics, vhea->numOfExSideBearings);
00560     RELEASE(vhea);
00561   } else {
00562     vmtx = NULL;
00563   }
00564 
00565   sfnt_locate_table(sfont, "loca");
00566   location = NEW(maxp->numGlyphs + 1, ULONG);
00567   if (head->indexToLocFormat == 0) {
00568     for (i = 0; i <= maxp->numGlyphs; i++)
00569       location[i] = 2*((ULONG) sfnt_get_ushort(sfont));
00570   } else if (head->indexToLocFormat == 1) {
00571     for (i = 0; i <= maxp->numGlyphs; i++)
00572       location[i] = sfnt_get_ulong(sfont);
00573   } else {
00574     ERROR("Unknown IndexToLocFormat.");
00575   }
00576 
00577   w_stat = NEW(g->emsize+2, USHORT);
00578   memset(w_stat, 0, sizeof(USHORT)*(g->emsize+2));
00579   /*
00580    * Read glyf table.
00581    */
00582   offset = sfnt_locate_table(sfont, "glyf");
00583   for (i = 0; i < g->num_glyphs; i++) {
00584     USHORT gid;     /* old gid */
00585     ULONG  loc, len;
00586     SHORT  number_of_contours;
00587 
00588     gid = g->gd[i].ogid;
00589     if (gid >= maxp->numGlyphs)
00590       ERROR("Invalid glyph index (gid %u)", gid);
00591 
00592     loc = location[gid];
00593     len = location[gid+1] - loc;
00594     g->gd[i].advw = hmtx[gid].advance;
00595     g->gd[i].lsb  = hmtx[gid].sideBearing;
00596     if (vmtx) {
00597       g->gd[i].advh = vmtx[gid].advance;
00598       g->gd[i].tsb  = vmtx[gid].sideBearing;
00599     } else {
00600       g->gd[i].advh = g->default_advh;
00601       g->gd[i].tsb  = g->default_tsb;
00602     }
00603     g->gd[i].length = len;
00604     g->gd[i].data   = NULL;
00605 
00606     if (g->gd[i].advw <= g->emsize) {
00607       w_stat[g->gd[i].advw] += 1;
00608     } else {
00609       w_stat[g->emsize+1]   += 1; /* larger than em */
00610     }
00611 
00612     if (len == 0) { /* Does not contains any data. */
00613       continue;
00614     } else if (len < 10) {
00615       ERROR("Invalid TrueType glyph data (gid %u).", gid);
00616     }
00617 
00618     sfnt_seek_set(sfont, offset+loc);
00619     number_of_contours = sfnt_get_short(sfont);
00620 
00621     /* BoundingBox: FWord x 4 */
00622     g->gd[i].llx = sfnt_get_short(sfont);
00623     g->gd[i].lly = sfnt_get_short(sfont);
00624     g->gd[i].urx = sfnt_get_short(sfont);
00625     g->gd[i].ury = sfnt_get_short(sfont);
00626     /* _FIXME_ */
00627 #if  1
00628     if (!vmtx) /* vertOriginY == sTypeAscender */
00629       g->gd[i].tsb = g->default_advh - g->default_tsb - g->gd[i].ury;
00630 #endif
00631   }
00632   RELEASE(location);
00633   RELEASE(hmtx);
00634   RELEASE(maxp);
00635   RELEASE(hhea);
00636   RELEASE(head);
00637   RELEASE(os2);
00638 
00639   if (vmtx)
00640     RELEASE(vmtx);
00641 
00642   {
00643     int max_count = -1;
00644 
00645     g->dw = g->gd[0].advw;
00646     for (i = 0; i < g->emsize + 1; i++) {
00647       if (w_stat[i] > max_count) {
00648        max_count = w_stat[i];
00649        g->dw = i;
00650       }
00651     }
00652   }
00653   RELEASE(w_stat);
00654 
00655 
00656   return 0;
00657 }