Back to index

texmacs  1.0.7.15
tt_table.c
Go to the documentation of this file.
00001 /*  $Header: /home/cvsroot/dvipdfmx/src/tt_table.c,v 1.11 2009/05/02 12:16:32 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 #include <stdio.h>
00024 
00025 #include "system.h"
00026 #include "error.h"
00027 #include "mem.h"
00028 #include "mfileio.h"
00029 
00030 #include "sfnt.h"
00031 #include "tt_table.h"
00032 
00033 /*
00034   tables contains information refered by other tables
00035   maxp->numGlyphs, etc --> loca, etc
00036   hhea->numOfLongHorMetrics --> hmtx
00037   head->indexToLocFormat --> loca
00038   head->glyphDataFormat --> glyf
00039 */
00040 
00041 char *tt_pack_head_table (struct tt_head_table *table)
00042 {
00043   int i;
00044   char *p, *data;
00045 
00046   if (table == NULL)
00047     ERROR("passed NULL pointer\n");
00048 
00049   p = data = NEW(TT_HEAD_TABLE_SIZE, char);
00050   p += sfnt_put_ulong(p, table->version);
00051   p += sfnt_put_ulong(p, table->fontRevision);
00052   p += sfnt_put_ulong(p, table->checkSumAdjustment);
00053   p += sfnt_put_ulong(p, table->magicNumber);
00054   p += sfnt_put_ushort(p, table->flags);
00055   p += sfnt_put_ushort(p, table->unitsPerEm);
00056   for (i=0; i<8; i++) {
00057     *(p++) = (table->created)[i];
00058   }
00059   for (i=0; i<8; i++) {
00060     *(p++) = (table->modified)[i];
00061   }
00062   p += sfnt_put_short(p, table->xMin);
00063   p += sfnt_put_short(p, table->yMin);
00064   p += sfnt_put_short(p, table->xMax);
00065   p += sfnt_put_short(p, table->yMax);
00066   p += sfnt_put_ushort(p, table->macStyle);
00067   p += sfnt_put_ushort(p, table->lowestRecPPEM);
00068   p += sfnt_put_short(p, table->fontDirectionHint);
00069   p += sfnt_put_short(p, table->indexToLocFormat);
00070   p += sfnt_put_short(p, table->glyphDataFormat);
00071 
00072   return data;
00073 }
00074 
00075 struct tt_head_table *tt_read_head_table (sfnt *sfont)
00076 {
00077   int i;
00078   struct tt_head_table *table = NULL;
00079 
00080   sfnt_locate_table(sfont, "head");
00081 
00082   table = NEW(1, struct tt_head_table);
00083   table->version = sfnt_get_ulong(sfont);
00084   table->fontRevision = sfnt_get_ulong(sfont);
00085   table->checkSumAdjustment = sfnt_get_ulong(sfont);
00086   table->magicNumber = sfnt_get_ulong(sfont);
00087   table->flags = sfnt_get_ushort(sfont);
00088   table->unitsPerEm = sfnt_get_ushort(sfont);
00089   for (i=0; i<8; i++) {
00090     (table->created)[i] = sfnt_get_byte (sfont);
00091   }
00092   for (i=0; i<8; i++) {
00093     (table->modified)[i] = sfnt_get_byte (sfont);
00094   }
00095   table->xMin = sfnt_get_short(sfont);
00096   table->yMin = sfnt_get_short(sfont);
00097   table->xMax = sfnt_get_short(sfont);
00098   table->yMax = sfnt_get_short(sfont);
00099   table->macStyle = sfnt_get_short(sfont);
00100   table->lowestRecPPEM = sfnt_get_short(sfont);
00101   table->fontDirectionHint = sfnt_get_short(sfont);
00102   table->indexToLocFormat = sfnt_get_short(sfont);
00103   table->glyphDataFormat = sfnt_get_short(sfont);
00104 
00105   return table;
00106 }
00107 
00108 char *tt_pack_maxp_table (struct tt_maxp_table *table)
00109 {
00110   char *p, *data;
00111 
00112   p = data = NEW(TT_MAXP_TABLE_SIZE, char);
00113   p += sfnt_put_ulong(p, table->version);
00114   p += sfnt_put_ushort(p, table->numGlyphs);
00115   p += sfnt_put_ushort(p, table->maxPoints);
00116   p += sfnt_put_ushort(p, table->maxContours);
00117   p += sfnt_put_ushort(p, table->maxComponentPoints);
00118   p += sfnt_put_ushort(p, table->maxComponentContours);
00119   p += sfnt_put_ushort(p, table->maxZones);
00120   p += sfnt_put_ushort(p, table->maxTwilightPoints);
00121   p += sfnt_put_ushort(p, table->maxStorage);
00122   p += sfnt_put_ushort(p, table->maxFunctionDefs);
00123   p += sfnt_put_ushort(p, table->maxInstructionDefs);
00124   p += sfnt_put_ushort(p, table->maxStackElements);
00125   p += sfnt_put_ushort(p, table->maxSizeOfInstructions);
00126   p += sfnt_put_ushort(p, table->maxComponentElements);
00127   p += sfnt_put_ushort(p, table->maxComponentDepth);
00128 
00129   return data;
00130 }
00131 
00132 struct tt_maxp_table *tt_read_maxp_table (sfnt *sfont)
00133 {
00134   struct tt_maxp_table *table = NULL;
00135 
00136   sfnt_locate_table(sfont, "maxp");
00137 
00138   table = NEW(1, struct tt_maxp_table);
00139   table->version = sfnt_get_ulong(sfont);
00140   table->numGlyphs = sfnt_get_ushort(sfont);
00141   table->maxPoints = sfnt_get_ushort(sfont);
00142   table->maxContours = sfnt_get_ushort(sfont);
00143   table->maxComponentPoints = sfnt_get_ushort(sfont);
00144   table->maxComponentContours = sfnt_get_ushort(sfont);
00145   table->maxZones = sfnt_get_ushort(sfont);
00146   table->maxTwilightPoints = sfnt_get_ushort(sfont);
00147   table->maxStorage = sfnt_get_ushort(sfont);
00148   table->maxFunctionDefs = sfnt_get_ushort(sfont);
00149   table->maxInstructionDefs = sfnt_get_ushort(sfont);
00150   table->maxStackElements = sfnt_get_ushort(sfont);
00151   table->maxSizeOfInstructions = sfnt_get_ushort(sfont);
00152   table->maxComponentElements = sfnt_get_ushort(sfont);
00153   table->maxComponentDepth = sfnt_get_ushort(sfont);
00154 
00155   return table;
00156 }
00157 
00158 char *tt_pack_hhea_table (struct tt_hhea_table *table)
00159 {
00160   int   i;
00161   char *p, *data;
00162 
00163   p  = data = NEW(TT_HHEA_TABLE_SIZE, char);
00164   p += sfnt_put_ulong(p, table->version);
00165   p += sfnt_put_short(p, table->ascent);
00166   p += sfnt_put_short(p, table->descent);
00167   p += sfnt_put_short(p, table->lineGap);
00168   p += sfnt_put_ushort(p, table->advanceWidthMax);
00169   p += sfnt_put_short(p, table->minLeftSideBearing);
00170   p += sfnt_put_short(p, table->minRightSideBearing);
00171   p += sfnt_put_short(p, table->xMaxExtent);
00172   p += sfnt_put_short(p, table->caretSlopeRise);
00173   p += sfnt_put_short(p, table->caretSlopeRun);
00174   p += sfnt_put_short(p, table->caretOffset);
00175   for (i = 0; i < 4; i++) {
00176     p += sfnt_put_short(p, table->reserved[i]);
00177   }
00178   p += sfnt_put_short(p, table->metricDataFormat);
00179   p += sfnt_put_ushort(p, table->numOfLongHorMetrics);
00180 
00181   return data;
00182 }
00183 
00184 struct tt_hhea_table *
00185 tt_read_hhea_table (sfnt *sfont)
00186 {
00187   int    i;
00188   ULONG  len;
00189   struct tt_hhea_table *table = NULL;
00190 
00191   sfnt_locate_table(sfont, "hhea");
00192 
00193   table = NEW(1, struct tt_hhea_table);
00194   table->version = sfnt_get_ulong(sfont);
00195   table->ascent  = sfnt_get_short (sfont);
00196   table->descent = sfnt_get_short(sfont);
00197   table->lineGap = sfnt_get_short(sfont);
00198   table->advanceWidthMax     = sfnt_get_ushort(sfont);
00199   table->minLeftSideBearing  = sfnt_get_short(sfont);
00200   table->minRightSideBearing = sfnt_get_short(sfont);
00201   table->xMaxExtent     = sfnt_get_short(sfont);
00202   table->caretSlopeRise = sfnt_get_short(sfont);
00203   table->caretSlopeRun  = sfnt_get_short(sfont);
00204   table->caretOffset    = sfnt_get_short(sfont);
00205   for(i = 0; i < 4; i++) {
00206     table->reserved[i] = sfnt_get_short(sfont);
00207   }
00208   table->metricDataFormat = sfnt_get_short(sfont);
00209   if (table->metricDataFormat != 0)
00210     ERROR("unknown metricDaraFormat");
00211   table->numOfLongHorMetrics = sfnt_get_ushort(sfont);
00212 
00213   len = sfnt_find_table_len(sfont, "hmtx");
00214   table->numOfExSideBearings = (USHORT)((len - table->numOfLongHorMetrics * 4) / 2);
00215 
00216   return table;
00217 }
00218 
00219 /* vhea */
00220 #if 0
00221 char *
00222 tt_pack_vhea_table (struct tt_vhea_table *table)
00223 {
00224   int   i;
00225   char *p, *data;
00226 
00227   p  = data = NEW(TT_VHEA_TABLE_SIZE, char);
00228   p += sfnt_put_ulong(p, table->version);
00229   p += sfnt_put_short(p, table->vertTypoAscender);
00230   p += sfnt_put_short(p, table->vertTypoDescender);
00231   p += sfnt_put_short(p, table->vertTypoLineGap);
00232   p += sfnt_put_short(p, table->advanceHeightMax);  /* ushort ? */
00233   p += sfnt_put_short(p, table->minTopSideBearing);
00234   p += sfnt_put_short(p, table->minBottomSideBearing);
00235   p += sfnt_put_short(p, table->yMaxExtent);
00236   p += sfnt_put_short(p, table->caretSlopeRise);
00237   p += sfnt_put_short(p, table->caretSlopeRun);
00238   p += sfnt_put_short(p, table->caretOffset);
00239   for(i = 0; i < 4; i++) {
00240     p += sfnt_put_short(p, table->reserved[i]);
00241   }
00242   p += sfnt_put_short(p, table->metricDataFormat);
00243   p += sfnt_put_ushort(p, table->numOfLongVerMetrics);
00244 
00245   return data;
00246 }
00247 #endif
00248 
00249 struct tt_vhea_table *tt_read_vhea_table (sfnt *sfont)
00250 {
00251   int   i;
00252   ULONG len;
00253   struct tt_vhea_table *table = NULL;
00254 
00255   sfnt_locate_table(sfont, "vhea");
00256 
00257   table = NEW(1, struct tt_vhea_table);
00258   table->version = sfnt_get_ulong(sfont);
00259   table->vertTypoAscender = sfnt_get_short (sfont);
00260   table->vertTypoDescender = sfnt_get_short(sfont);
00261   table->vertTypoLineGap = sfnt_get_short(sfont);
00262   table->advanceHeightMax = sfnt_get_short(sfont); /* ushort ? */
00263   table->minTopSideBearing = sfnt_get_short(sfont);
00264   table->minBottomSideBearing = sfnt_get_short(sfont);
00265   table->yMaxExtent = sfnt_get_short(sfont);
00266   table->caretSlopeRise = sfnt_get_short(sfont);
00267   table->caretSlopeRun = sfnt_get_short(sfont);
00268   table->caretOffset = sfnt_get_short(sfont);
00269   for(i = 0; i < 4; i++) {
00270     (table->reserved)[i] = sfnt_get_short(sfont);
00271   }
00272   table->metricDataFormat = sfnt_get_short(sfont);
00273   table->numOfLongVerMetrics = sfnt_get_ushort(sfont);
00274 
00275   len = sfnt_find_table_len(sfont, "vmtx");
00276   table->numOfExSideBearings = (USHORT)((len - table->numOfLongVerMetrics * 4) / 2);
00277 
00278   return table;
00279 }
00280 
00281 
00282 struct tt_VORG_table *
00283 tt_read_VORG_table (sfnt *sfont)
00284 {
00285   struct tt_VORG_table *vorg;
00286   ULONG  offset;
00287   USHORT i;
00288 
00289   offset = sfnt_find_table_pos(sfont, "VORG");
00290 
00291   if (offset > 0) {
00292     vorg = NEW(1, struct tt_VORG_table);
00293 
00294     sfnt_locate_table(sfont, "VORG");
00295     if (sfnt_get_ushort(sfont) != 1 ||
00296        sfnt_get_ushort(sfont) != 0)
00297       ERROR("Unsupported VORG version.");
00298 
00299     vorg->defaultVertOriginY    = sfnt_get_short(sfont);
00300     vorg->numVertOriginYMetrics = sfnt_get_ushort(sfont);
00301     vorg->vertOriginYMetrics    = NEW(vorg->numVertOriginYMetrics,
00302                                   struct tt_vertOriginYMetrics);
00303     /*
00304      * The vertOriginYMetrics array must be sorted in increasing
00305      * glyphIndex order.
00306      */
00307     for (i = 0;
00308         i < vorg->numVertOriginYMetrics; i++) {
00309       vorg->vertOriginYMetrics[i].glyphIndex  = sfnt_get_ushort(sfont);
00310       vorg->vertOriginYMetrics[i].vertOriginY = sfnt_get_short(sfont);
00311     }
00312   } else {
00313     vorg = NULL;
00314   }
00315 
00316   return vorg;
00317 }
00318 
00319 /*
00320  * hmtx and vmtx
00321  *
00322  *  Reading/writing hmtx and vmtx depend on other tables, maxp and hhea/vhea.
00323  */
00324 
00325 struct tt_longMetrics *
00326 tt_read_longMetrics (sfnt *sfont, USHORT numGlyphs, USHORT numLongMetrics, USHORT numExSideBearings)
00327 {
00328   struct tt_longMetrics *m;
00329   USHORT gid, last_adv = 0;
00330   SHORT  last_esb = 0;
00331 
00332   m = NEW(numGlyphs, struct tt_longMetrics);
00333   for (gid = 0; gid < numGlyphs; gid++) {
00334     if (gid < numLongMetrics)
00335       last_adv = sfnt_get_ushort(sfont);
00336     if (gid < numLongMetrics + numExSideBearings)
00337       last_esb = sfnt_get_short(sfont);
00338     m[gid].advance     = last_adv;
00339     m[gid].sideBearing = last_esb;
00340   }
00341 
00342   return m;
00343 }
00344 
00345 /* OS/2 table */
00346 /* this table may not exist */
00347 struct tt_os2__table *
00348 tt_read_os2__table (sfnt *sfont)
00349 {
00350   struct tt_os2__table *table = NULL;
00351   int    i;
00352 
00353   table = NEW(1, struct tt_os2__table);
00354 
00355   if (sfnt_find_table_pos(sfont, "OS/2") > 0) {
00356     sfnt_locate_table(sfont, "OS/2");
00357     table->version       = sfnt_get_ushort(sfont);
00358     table->xAvgCharWidth = sfnt_get_short(sfont);
00359     table->usWeightClass = sfnt_get_ushort(sfont);
00360     table->usWidthClass  = sfnt_get_ushort(sfont);
00361     table->fsType        = sfnt_get_short(sfont);
00362     table->ySubscriptXSize   = sfnt_get_short(sfont);
00363     table->ySubscriptYSize   = sfnt_get_short(sfont);
00364     table->ySubscriptXOffset = sfnt_get_short(sfont);
00365     table->ySubscriptYOffset = sfnt_get_short(sfont);
00366     table->ySuperscriptXSize = sfnt_get_short(sfont);
00367     table->ySuperscriptYSize = sfnt_get_short(sfont);
00368     table->ySuperscriptXOffset = sfnt_get_short(sfont);
00369     table->ySuperscriptYOffset = sfnt_get_short(sfont);
00370     table->yStrikeoutSize      = sfnt_get_short(sfont);
00371     table->yStrikeoutPosition  = sfnt_get_short(sfont);
00372     table->sFamilyClass        = sfnt_get_short(sfont);
00373     for (i = 0; i < 10; i++) {
00374       table->panose[i] = sfnt_get_byte(sfont);
00375     }
00376     table->ulUnicodeRange1 = sfnt_get_ulong(sfont);
00377     table->ulUnicodeRange2 = sfnt_get_ulong(sfont);
00378     table->ulUnicodeRange3 = sfnt_get_ulong(sfont);
00379     table->ulUnicodeRange4 = sfnt_get_ulong(sfont);
00380     for (i = 0; i < 4; i++) {
00381       table->achVendID[i] = sfnt_get_char(sfont);
00382     }
00383     table->fsSelection      = sfnt_get_ushort(sfont);
00384     table->usFirstCharIndex = sfnt_get_ushort(sfont);
00385     table->usLastCharIndex  = sfnt_get_ushort(sfont);
00386     table->sTypoAscender    = sfnt_get_short(sfont);
00387     table->sTypoDescender   = sfnt_get_short(sfont);
00388     table->sTypoLineGap     = sfnt_get_short(sfont);
00389     table->usWinAscent      = sfnt_get_ushort(sfont);
00390     table->usWinDescent     = sfnt_get_ushort(sfont);
00391     table->ulCodePageRange1 = sfnt_get_ulong(sfont);
00392     table->ulCodePageRange2 = sfnt_get_ulong(sfont);
00393     if (table->version == 0x0002) {
00394       table->sxHeight      = sfnt_get_short(sfont);
00395       table->sCapHeight    = sfnt_get_short(sfont);
00396       table->usDefaultChar = sfnt_get_ushort(sfont);
00397       table->usBreakChar   = sfnt_get_ushort(sfont);
00398       table->usMaxContext  = sfnt_get_ushort(sfont);
00399     }
00400   } else {
00401     /* used in add_CIDVMetrics() of cidtype0.c */
00402     table->sTypoAscender  = 880;
00403     table->sTypoDescender = -120;
00404     /* used in tt_get_fontdesc() of tt_aux.c */
00405     table->usWeightClass = 400U; /* Normal(Regular) */
00406     table->xAvgCharWidth = 0; /* ignore */
00407     table->version = 0; /* TrueType rev 1.5 */
00408     table->fsType = 0; /* Installable Embedding */
00409     table->fsSelection = 0U; /* All undefined */
00410     table->sFamilyClass = 0; /* No Classification */
00411     for (i = 0; i < 10; i++) {
00412       table->panose[i] = 0; /* All Any */
00413     }
00414   }
00415 
00416   return table;
00417 }
00418 
00419 USHORT
00420 tt_get_name (sfnt *sfont, char *dest, USHORT destlen,
00421             USHORT plat_id, USHORT enco_id,
00422             USHORT lang_id, USHORT name_id)
00423 {
00424   USHORT length = 0;
00425   USHORT num_names, string_offset;
00426   ULONG  name_offset;
00427   int    i;
00428 
00429   name_offset = sfnt_locate_table (sfont, "name");
00430 
00431   if (sfnt_get_ushort(sfont)) 
00432     ERROR ("Expecting zero");
00433 
00434   num_names = sfnt_get_ushort(sfont);
00435   string_offset = sfnt_get_ushort(sfont);
00436   for (i=0;i<num_names;i++) {
00437     USHORT p_id, e_id, n_id, l_id;
00438     USHORT offset;
00439 
00440     p_id = sfnt_get_ushort(sfont);
00441     e_id = sfnt_get_ushort(sfont);
00442     l_id = sfnt_get_ushort(sfont);
00443     n_id = sfnt_get_ushort(sfont);
00444     length = sfnt_get_ushort(sfont);
00445     offset = sfnt_get_ushort(sfont);
00446     /* language ID value 0xffffu for `accept any language ID' */
00447     if ((p_id == plat_id) && (e_id == enco_id) &&
00448        (lang_id == 0xffffu || l_id == lang_id) && (n_id == name_id)) {
00449       if (length > destlen - 1) {
00450        fprintf(stderr, "\n** Notice: Name string too long. Truncating **\n");
00451        length = destlen - 1;
00452       }
00453       sfnt_seek_set (sfont, name_offset+string_offset+offset);
00454       sfnt_read(dest, length, sfont);
00455       dest[length] = '\0';
00456       break;
00457     }
00458   }
00459   if (i == num_names) {
00460     length = 0;
00461   }
00462 
00463   return length;
00464 }
00465 
00466 USHORT
00467 tt_get_ps_fontname (sfnt *sfont, char *dest, USHORT destlen)
00468 {
00469   USHORT namelen = 0;
00470 
00471   /* First try Mac-Roman PS name and then Win-Unicode PS name */
00472   if ((namelen = tt_get_name(sfont, dest, destlen, 1, 0, 0, 6)) != 0 ||
00473       (namelen = tt_get_name(sfont, dest, destlen, 3, 1, 0x409u, 6)) != 0 ||
00474       (namelen = tt_get_name(sfont, dest, destlen, 3, 5, 0x412u, 6)) != 0)
00475     return namelen;
00476 
00477   fprintf(stderr, "\n** Warning: No valid PostScript name available **\n");
00478   /*
00479     Wrokaround for some bad TTfonts:
00480     Language ID value 0xffffu for `accept any language ID'
00481   */
00482   if ((namelen = tt_get_name(sfont, dest, destlen, 1, 0, 0xffffu, 6)) == 0) {
00483     /*
00484       Finally falling back to Mac Roman name field.
00485       Warning: Some bad Japanese TTfonts using SJIS encoded string in the
00486       Mac Roman name field. 
00487     */
00488     namelen = tt_get_name(sfont, dest, destlen, 1, 0, 0, 1);
00489   }
00490 
00491   return namelen;
00492 }