Back to index

texmacs  1.0.7.15
cidtype2.c
Go to the documentation of this file.
00001 /*  $Header: /home/cvsroot/dvipdfmx/src/cidtype2.c,v 1.37 2010/03/21 13:16:12 chofchof Exp $
00002     
00003     This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
00004 
00005     Copyright (C) 2002 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  * TrueType glyf table is sorted by CID and no CIDToGIDMap is used here.
00025  * GhostScript can't handle CIDToGIDMap correctly.
00026  */
00027 
00028 #if HAVE_CONFIG_H
00029 #include "config.h"
00030 #endif
00031 
00032 #include "system.h"
00033 #include "numbers.h"
00034 #include "mem.h"
00035 #include "error.h"
00036 #include "dpxfile.h"
00037 
00038 #include "pdfobj.h"
00039 /* pseudo unique tag */
00040 #include "pdffont.h"
00041 
00042 #ifndef PDF_NAME_LEN_MAX
00043 #  define PDF_NAME_LEN_MAX 255
00044 #endif
00045 
00046 /* TrueType */
00047 #include "sfnt.h"
00048 #include "tt_aux.h"
00049 #include "tt_glyf.h"
00050 #include "tt_cmap.h"
00051 #include "tt_table.h"
00052 
00053 #include "tt_gsub.h"
00054 
00055 /* CID font */
00056 #include "cmap.h"
00057 #include "type0.h"
00058 #include "cid.h"
00059 #include "cid_p.h"
00060 #include "cidtype2.h"
00061 
00062 static int verbose   = 0;
00063 static int opt_flags = 0;
00064 
00065 void
00066 CIDFont_type2_set_verbose (void)
00067 {
00068   verbose++;
00069 }
00070 
00071 void
00072 CIDFont_type2_set_flags (long flags)
00073 {
00074   opt_flags = flags;
00075 }
00076 
00077 /*
00078  * PDF viewer applications use following tables (CIDFontType 2)
00079  *
00080  *  head, hhea, loca, maxp, glyf, hmtx, fpgm, cvt_, prep
00081  *
00082  *                                         - from PDF Ref. v.1.3, 2nd ed.
00083  *
00084  * The fpgm, cvt_, and prep tables appears only when TrueType instructions
00085  * requires them. Those tables must be preserved if they exist.
00086  * We use must_exist flag to indicate `preserve it if present'
00087  * and to make sure not to cause an error when it does not exist.
00088  *
00089  * post and name table must exist in ordinary TrueType font file,
00090  * but when a TrueType font is converted to CIDFontType 2 font, those tables
00091  * are no longer required.
00092  *
00093  * The OS/2 table (required for TrueType font for Windows and OS/2) contains
00094  * liscencing information, but PDF viewers seems not using them.
00095  *
00096  * The 'name' table added. See comments in ttf.c.
00097  */
00098 
00099 static struct
00100 {
00101   const char *name;
00102   int         must_exist;
00103 } required_table[] = {
00104   {"OS/2", 0}, {"head", 1}, {"hhea", 1}, {"loca", 1}, {"maxp", 1},
00105   {"name", 1}, {"glyf", 1}, {"hmtx", 1}, {"fpgm", 0}, {"cvt ", 0},
00106   {"prep", 0}, {NULL, 0}
00107 };
00108 
00109 static void
00110 validate_name (char *fontname, int len)
00111 {
00112   int    i, count;
00113   char  *p;
00114   static const char *badstrlist[] = {
00115     "-WIN-RKSJ-H",
00116     "-WINP-RKSJ-H",
00117     "-WING-RKSJ-H",
00118     "-90pv-RKSJ-H",
00119     NULL
00120   };
00121 
00122   for (count = 0, i = 0; i < len; i++) {
00123     if (fontname[i] == 0) {
00124       memmove(fontname + i, fontname + i + 1, len - i);
00125       count++;
00126       len--;
00127     }
00128   }
00129   if (count > 0) {
00130     WARN("Removed %d null character(s) from fontname --> %s",
00131         count, fontname);
00132   }
00133   fontname[len] = '\0';
00134 
00135   /* For some fonts that have bad PS name. ad hoc. remove me. */
00136   for (i = 0; badstrlist[i] != NULL; i++) {
00137     p = strstr(fontname, badstrlist[i]);
00138     if (p && p > fontname) {
00139       WARN("Removed string \"%s\" from fontname \"%s\".",
00140           badstrlist[i], fontname);
00141       p[0] = '\0';
00142       len  = (int) (p - fontname);
00143       break;
00144     }
00145   }
00146 
00147   if (len < 1) {
00148     ERROR("No valid character found in fontname string.");
00149   }
00150 }
00151 
00152 /*
00153  * We will follow the convension for finding ToUnicode CMap described in PDF
00154  * Reference 4th ed., page 432. The name of "ToCode" (not limited to Unicode
00155  * here) CMap is obtained by concatenating the registry, ordering, and the
00156  * name of encoding.
00157  *
00158  * UCSms-UCS4, UCSms-UCS2, UCS4 added...
00159  */
00160 
00161 #define WIN_UCS_INDEX_MAX   1
00162 #define KNOWN_ENCODINGS_MAX 9
00163 static struct
00164 {
00165   unsigned short  platform;
00166   unsigned short  encoding;
00167   const char     *pdfnames[5];
00168 } known_encodings[] = {
00169   {TT_WIN, TT_WIN_UCS4,     {"UCSms-UCS4", "UCSms-UCS2", "UCS4", "UCS2", NULL}},
00170   {TT_WIN, TT_WIN_UNICODE,  {"UCSms-UCS4", "UCSms-UCS2", "UCS4", "UCS2", NULL}},
00171   {TT_WIN, TT_WIN_SJIS,     {"90ms-RKSJ", NULL}},
00172   {TT_WIN, TT_WIN_RPC,      {"GBK-EUC",   NULL}},
00173   {TT_WIN, TT_WIN_BIG5,     {"ETen-B5",   NULL}},
00174   {TT_WIN, TT_WIN_WANSUNG,  {"KSCms-UHC", NULL}},
00175   {TT_MAC, TT_MAC_JAPANESE, {"90pv-RKSJ", NULL}},
00176   {TT_MAC, TT_MAC_TRADITIONAL_CHINESE, {"B5pc",     NULL}},
00177   {TT_MAC, TT_MAC_SIMPLIFIED_CHINESE,  {"GBpc-EUC", NULL}},
00178   {TT_MAC, TT_MAC_KOREAN,   {"KSCpc-EUC", NULL}},
00179   {0, 0, {NULL}}
00180 };
00181 
00182 static CMap *
00183 find_tocode_cmap (const char *reg, const char *ord, int select)
00184 {
00185   int   cmap_id = -1, i;
00186   char *cmap_name;
00187   char *append;
00188 
00189   if (!reg || !ord ||
00190       select < 0 || select > KNOWN_ENCODINGS_MAX)
00191     ERROR("Character set unknown.");
00192 
00193   if (!strcmp(ord, "UCS") &&
00194       select <= WIN_UCS_INDEX_MAX)
00195     return NULL;
00196 
00197   for (i = 0; cmap_id < 0 && i < 5; i++) {
00198     append = (char *) known_encodings[select].pdfnames[i];
00199     if (!append)
00200       break;
00201     cmap_name = NEW(strlen(reg) + strlen(ord) + strlen(append) + 3, char);
00202     sprintf(cmap_name, "%s-%s-%s", reg, ord, append);
00203     cmap_id = CMap_cache_find(cmap_name);
00204     RELEASE(cmap_name);
00205   }
00206   if (cmap_id < 0) {
00207     WARN("Could not find CID-to-Code mapping for \"%s-%s\".", reg, ord);
00208     WARN("I tried to load (one of) the following file(s):");
00209     for (i = 0; i < 5; i++) {
00210       append = (char *) known_encodings[select].pdfnames[i];
00211       if (!append)
00212        break;
00213       MESG(" %s-%s-%s", reg, ord, append);
00214     }
00215     WARN("Please check if this file exists.");
00216     ERROR("Cannot continue...");
00217   }
00218 
00219   return CMap_cache_get(cmap_id);
00220 }
00221 
00222 
00223 /*
00224  * CIDFont glyph metrics:
00225  * Mostly same as add_CID[HV]Metrics in cidtype0.c.
00226  */
00227 #define PDFUNIT(v) ((double) (ROUND(1000.0*(v)/(g->emsize), 1)))
00228 
00229 static void
00230 add_TTCIDHMetrics (pdf_obj *fontdict, struct tt_glyphs *g,
00231                  char *used_chars, unsigned char *cidtogidmap, unsigned short last_cid)
00232 {
00233   long cid, start = 0, prev = 0;
00234   pdf_obj *w_array, *an_array = NULL;
00235   double   dw;
00236   int      empty = 1;
00237 
00238   w_array = pdf_new_array();
00239   if (g->dw != 0 && g->dw <= g->emsize) {
00240     dw = PDFUNIT(g->dw);
00241   } else {
00242     dw = PDFUNIT(g->gd[0].advw);
00243   }
00244   for (cid = 0; cid <= last_cid; cid++) {
00245     USHORT idx, gid;
00246     double width;
00247 
00248     if (!is_used_char2(used_chars, cid))
00249       continue;
00250     gid = (cidtogidmap) ? ((cidtogidmap[2*cid] << 8)|cidtogidmap[2*cid+1]) : cid;
00251     idx = tt_get_index(g, gid);
00252     if (cid != 0 && idx == 0)
00253       continue;
00254     width = PDFUNIT((g->gd)[idx].advw);
00255     if (width == dw) {
00256       if (an_array) {
00257        pdf_add_array(w_array, pdf_new_number(start));
00258        pdf_add_array(w_array, an_array);
00259        an_array = NULL;
00260        empty = 0;
00261       }
00262     } else {
00263       if (cid != prev + 1) {
00264        if (an_array) {
00265          pdf_add_array(w_array, pdf_new_number(start));
00266          pdf_add_array(w_array, an_array);
00267          an_array = NULL;
00268          empty = 0;
00269        }
00270       }
00271       if (an_array == NULL) {
00272        an_array = pdf_new_array();
00273        start = cid;
00274       }
00275       pdf_add_array(an_array, pdf_new_number(width));
00276       prev = cid;
00277     }
00278   }
00279 
00280   if (an_array) {
00281     pdf_add_array(w_array, pdf_new_number(start));
00282     pdf_add_array(w_array, an_array);
00283     empty = 0;
00284   }
00285 
00286   pdf_add_dict(fontdict,
00287               pdf_new_name("DW"),
00288               pdf_new_number(dw));
00289   if (!empty) {
00290     pdf_add_dict(fontdict,
00291                pdf_new_name("W"),
00292                pdf_ref_obj(w_array));
00293   }
00294   pdf_release_obj(w_array);
00295 
00296   return;
00297 }
00298 
00299 static void
00300 add_TTCIDVMetrics (pdf_obj *fontdict, struct tt_glyphs *g,
00301                  char *used_chars, unsigned char *cidtogidmap, unsigned short last_cid)
00302 {
00303   pdf_obj *w2_array, *an_array = NULL;
00304   long cid, prev, start;
00305   double defaultVertOriginY, defaultAdvanceHeight;
00306   int    empty = 1;
00307 
00308   defaultVertOriginY   = PDFUNIT(g->default_advh - g->default_tsb);
00309   defaultAdvanceHeight = PDFUNIT(g->default_advh);
00310 
00311   w2_array = pdf_new_array();
00312   start = prev = 0;
00313   for (cid = 0; cid <= last_cid; cid++) {
00314     USHORT idx, gid;
00315     double vertOriginX, vertOriginY, advanceHeight;
00316 
00317     if (!is_used_char2(used_chars, cid))
00318       continue;
00319     gid = (cidtogidmap) ? ((cidtogidmap[2*cid] << 8)|cidtogidmap[2*cid+1]) : cid;
00320     idx = tt_get_index(g, cid);
00321     if (cid != 0 && idx == 0)
00322       continue;
00323     advanceHeight = PDFUNIT(g->gd[idx].advh);
00324     vertOriginX   = PDFUNIT(0.5*(g->gd[idx].advw));
00325     vertOriginY   = PDFUNIT(g->gd[idx].tsb + g->gd[idx].ury);
00326 #if 0
00327     /*
00328      * c [w1_1y v_1x v_1y w1_2y v_2x v_2y ...]
00329      * Not working... Why?
00330      * Acrobat Reader:
00331      *  Wrong rendering, interpretation of position vector is wrong.
00332      * Xpdf and gs: ignores W2?
00333      */
00334     if (vertOriginY == defaultVertOriginY &&
00335        advanceHeight == defaultAdvanceHeight) {
00336       if (an_array) {
00337        pdf_add_array(w2_array, pdf_new_number(start));
00338        pdf_add_array(w2_array, an_array);
00339        an_array = NULL;
00340        empty = 0;
00341       }
00342     } else {
00343       if (cid != prev + 1 && an_array) {
00344        pdf_add_array(w2_array, pdf_new_number(start));
00345        pdf_add_array(w2_array, an_array);
00346        an_array = NULL;
00347        empty = 0;
00348       }
00349       if (an_array == NULL) {
00350        an_array = pdf_new_array();
00351        start = cid;
00352       }
00353       pdf_add_array(an_array, pdf_new_number(-advanceHeight));
00354       pdf_add_array(an_array, pdf_new_number(vertOriginX));
00355       pdf_add_array(an_array, pdf_new_number(vertOriginY));
00356       prev = cid;
00357     }
00358 #else
00359     /*
00360      * c_first c_last w1_y v_x v_y
00361      * This form may hit Acrobat's implementation limit of array element size,
00362      * 8192. AFPL GhostScript 8.11 stops with rangecheck error with this.
00363      * Maybe GS's bug?
00364      */
00365     if (vertOriginY != defaultVertOriginY ||
00366        advanceHeight != defaultAdvanceHeight) {
00367       pdf_add_array(w2_array, pdf_new_number(cid));
00368       pdf_add_array(w2_array, pdf_new_number(cid));
00369       pdf_add_array(w2_array, pdf_new_number(-advanceHeight));
00370       pdf_add_array(w2_array, pdf_new_number(vertOriginX));
00371       pdf_add_array(w2_array, pdf_new_number(vertOriginY));
00372       empty = 0;
00373     }
00374 #endif
00375   }
00376 
00377 #if 0
00378   if (an_array) {
00379     pdf_add_array(w2_array, pdf_new_number(start));
00380     pdf_add_array(w2_array, an_array);
00381     empty = 0;
00382   }
00383 #endif
00384 
00385   if (defaultVertOriginY != 880 || defaultAdvanceHeight != 1000) {
00386     an_array = pdf_new_array();
00387     pdf_add_array(an_array, pdf_new_number(defaultVertOriginY));
00388     pdf_add_array(an_array, pdf_new_number(-defaultAdvanceHeight));
00389     pdf_add_dict(fontdict, pdf_new_name ("DW2"), an_array);
00390   }
00391   if (!empty) {
00392     pdf_add_dict(fontdict,
00393                pdf_new_name("W2"),
00394                pdf_ref_obj(w2_array));
00395   }
00396   pdf_release_obj(w2_array);
00397 
00398   return;
00399 }
00400 
00401 /*
00402  * The following routine fixes few problems caused by vendor specific
00403  * Unicode mappings.
00404  */
00405 
00406 #define FIX_CJK_UNIOCDE_SYMBOLS 1
00407 
00408 static unsigned short
00409 fix_CJK_symbols (unsigned short code)
00410 {
00411   unsigned short alt_code;
00412   static struct
00413   {
00414     unsigned short alt1;
00415     unsigned short alt2;
00416   } CJK_Uni_symbols[] = {
00417     /*
00418      * Microsoft/Apple Unicode mapping difference:
00419      * They are taken from SJIS-Unicode mapping difference but nearly
00420      * same thing might be applied to Chinese (e.g., Big5) too.
00421      */
00422     {0x2014, 0x2015}, /* EM DASH <-> HORIZONTAL BAR */
00423     {0x2016, 0x2225}, /* DOUBLE VERTICAL LINE <-> PARALLEL TO */
00424     {0x203E, 0xFFE3}, /* OVERLINE <-> FULLWIDTH MACRON */
00425     {0x2026, 0x22EF}, /* HORIZONTAL ELLIPSIS <-> MIDLINE HORIZONTAL ELLIPSIS */
00426     {0x2212, 0xFF0D}, /* MINUS SIGN <-> FULLWIDTH HYPHEN-MINUS */
00427     {0x301C, 0xFF5E}, /* WAVE DASH <-> FULLWIDTH TILDE */
00428     {0xFFE0, 0x00A2}, /* FULLWIDTH CENT SIGN <-> CENT SIGN */
00429     {0xFFE1, 0x00A3}, /* FULLWIDTH POUND SIGN <-> POUND SIGN */
00430     {0xFFE2, 0x00AC}, /* FULLWIDTH NOT SIGN <-> NOT SIGN */
00431     {0xFFFF, 0xFFFF}, /* EOD */
00432   };
00433 #define NUM_CJK_SYMBOLS (sizeof(CJK_Uni_symbols)/sizeof(CJK_Uni_symbols[0]))
00434   int i;
00435 
00436   alt_code = code;
00437   for (i = 0; i < NUM_CJK_SYMBOLS; i++) {
00438     if (CJK_Uni_symbols[i].alt1 == code) {
00439       alt_code = CJK_Uni_symbols[i].alt2;
00440       break;
00441     } else if (CJK_Uni_symbols[i].alt2 == code) {
00442       alt_code = CJK_Uni_symbols[i].alt1;
00443       break;
00444     }
00445   }
00446 
00447   return alt_code;
00448 }
00449 
00450 static long
00451 cid_to_code (CMap *cmap, CID cid)
00452 {
00453   unsigned char  inbuf[2], outbuf[32];
00454   long           inbytesleft = 2, outbytesleft = 32;
00455   unsigned char *p, *q;
00456 
00457   if (!cmap)
00458     return cid;
00459 
00460   inbuf[0] = (cid >> 8) & 0xff;
00461   inbuf[1] = cid & 0xff;
00462   p = inbuf; q = outbuf;
00463 
00464   CMap_decode_char(cmap, (const unsigned char **) &p, &inbytesleft, &q, &outbytesleft);
00465 
00466   if (inbytesleft != 0)
00467     return 0;
00468   else if (outbytesleft == 31)
00469     return (long) outbuf[0];
00470   else if (outbytesleft == 30)
00471     return (long) (outbuf[0] << 8|outbuf[1]);
00472   else if (outbytesleft == 28) { /* We assume the output encoding is UTF-16. */
00473     CID hi, lo;
00474     hi = outbuf[0] << 8|outbuf[1];
00475     lo = outbuf[2] << 8|outbuf[3];
00476     if (hi >= 0xd800 && hi <= 0xdbff && lo >= 0xdc00 && lo <= 0xdfff)
00477       return (long) ((hi - 0xd800) * 0x400 + 0x10000 + lo - 0xdc00);
00478     else
00479       return (long) (hi << 16|lo);
00480   }
00481 
00482   return 0;
00483 }
00484 
00485 /* #define NO_GHOSTSCRIPT_BUG 1 */
00486 
00487 void
00488 CIDFont_type2_dofont (CIDFont *font)
00489 {
00490   pdf_obj *fontfile;
00491   sfnt    *sfont;
00492   char    *h_used_chars, *v_used_chars, *used_chars;
00493   struct tt_glyphs *glyphs;
00494   CMap    *cmap = NULL;
00495   tt_cmap *ttcmap = NULL;
00496   unsigned long offset = 0;
00497   CID      cid, last_cid;
00498   unsigned char *cidtogidmap;
00499   USHORT   num_glyphs;
00500   int      i, glyph_ordering = 0, unicode_cmap = 0;
00501   FILE    *fp;
00502 
00503   if (!font->indirect)
00504     return;
00505 
00506   pdf_add_dict(font->fontdict, 
00507               pdf_new_name("FontDescriptor"), pdf_ref_obj(font->descriptor));
00508 
00509   if (CIDFont_is_BaseFont(font))
00510     return;
00511 
00512   /*
00513    * CIDSystemInfo comes here since Supplement can be increased.
00514    */
00515   {
00516     pdf_obj *tmp;
00517 
00518     tmp = pdf_new_dict ();
00519     pdf_add_dict(tmp,
00520                pdf_new_name("Registry"),
00521                pdf_new_string(font->csi->registry, strlen(font->csi->registry)));
00522     pdf_add_dict(tmp,
00523                pdf_new_name("Ordering"),
00524                pdf_new_string(font->csi->ordering, strlen(font->csi->ordering)));
00525     pdf_add_dict(tmp,
00526                pdf_new_name("Supplement"),
00527                pdf_new_number(font->csi->supplement));
00528     pdf_add_dict(font->fontdict, pdf_new_name("CIDSystemInfo"), tmp);
00529   }
00530 
00531   /* Quick exit for non-embedded & fixed-pitch font. */
00532   if (!CIDFont_get_embedding(font) &&
00533       (opt_flags & CIDFONT_FORCE_FIXEDPITCH)) {
00534     pdf_add_dict(font->fontdict,
00535                pdf_new_name("DW"), pdf_new_number(1000.0));
00536     return;
00537   }
00538 
00539   fp = DPXFOPEN(font->ident, DPX_RES_TYPE_TTFONT);
00540   if (!fp) {
00541     fp = DPXFOPEN(font->ident, DPX_RES_TYPE_DFONT);
00542     if (!fp) ERROR("Could not open TTF/dfont file: %s", font->ident);
00543     sfont = dfont_open(fp, font->options->index);
00544   } else {
00545     sfont = sfnt_open(fp);
00546   }
00547 
00548   if (!sfont) {
00549     ERROR("Could not open TTF file: %s", font->ident);
00550   }
00551 
00552   switch (sfont->type) {
00553   case SFNT_TYPE_TTC:
00554     offset = ttc_read_offset(sfont, font->options->index);
00555     if (offset == 0)
00556       ERROR("Invalid TTC index in %s.", font->ident);
00557     break;
00558   case SFNT_TYPE_TRUETYPE:
00559     if (font->options->index > 0)
00560       ERROR("Found TrueType font file while expecting TTC file (%s).", font->ident);
00561     offset = 0;
00562     break;
00563   case SFNT_TYPE_DFONT:
00564     offset = sfont->offset;
00565     break;
00566   default:
00567     ERROR("Not a TrueType/TTC font (%s)?", font->ident);
00568     break;
00569   }
00570 
00571   if (sfnt_read_table_directory(sfont, offset) < 0)
00572     ERROR("Could not read TrueType table directory (%s).", font->ident);
00573 
00574   /*
00575    * Adobe-Identity means font's internal glyph ordering here.
00576    */
00577   if (!strcmp(font->csi->registry, "Adobe") &&
00578       !strcmp(font->csi->ordering, "Identity")) {
00579     glyph_ordering = 1;
00580   } else {
00581     glyph_ordering = 0;
00582   }
00583 
00584   /*
00585    * Select TrueType cmap table, find ToCode CMap for each TrueType encodings.
00586    */
00587   if (glyph_ordering) {
00588     ttcmap = NULL;
00589     cmap   = NULL;
00590   } else {
00591     /*
00592      * This part contains a bug. It may choose SJIS encoding TrueType cmap
00593      * table for Adobe-GB1.
00594      */
00595     for (i = 0; i <= KNOWN_ENCODINGS_MAX; i++) {
00596       ttcmap = tt_cmap_read(sfont,
00597                          known_encodings[i].platform,
00598                          known_encodings[i].encoding);
00599       if (ttcmap)
00600        break;
00601     }
00602     if (!ttcmap) {
00603       WARN("No usable TrueType cmap table found for font \"%s\".", font->ident);
00604       WARN("CID character collection for this font is set to \"%s-%s\"",
00605           font->csi->registry, font->csi->ordering);
00606       ERROR("Cannot continue without this...");
00607     } else if (i <= WIN_UCS_INDEX_MAX) {
00608       unicode_cmap = 1;
00609     } else {
00610       unicode_cmap = 0;
00611     }
00612 
00613     /*
00614      * NULL is returned if CMap is Identity CMap.
00615      */
00616     cmap = find_tocode_cmap(font->csi->registry,
00617                          font->csi->ordering, i);
00618   }
00619 
00620   glyphs = tt_build_init();
00621 
00622   last_cid   = 0;
00623   num_glyphs = 1; /* .notdef */
00624   used_chars = h_used_chars = v_used_chars = NULL;
00625   {
00626     Type0Font *parent;
00627     int        parent_id, c;
00628 
00629     if ((parent_id = CIDFont_get_parent_id(font, 0)) >= 0) {
00630       parent = Type0Font_cache_get(parent_id);
00631       h_used_chars = Type0Font_get_usedchars(parent);
00632     }
00633     if ((parent_id = CIDFont_get_parent_id(font, 1)) >= 0) {
00634       parent = Type0Font_cache_get(parent_id);
00635       v_used_chars = Type0Font_get_usedchars(parent);
00636     }
00637     if (!h_used_chars && !v_used_chars)
00638       ERROR("Unexpected error.");
00639 
00640     /*
00641      * Quick check of max CID.
00642      */
00643     c = 0;
00644     for (i = 8191; i >= 0; i--) {
00645       if (h_used_chars && h_used_chars[i] != 0) {
00646        last_cid = i * 8 + 7;
00647        c = h_used_chars[i];
00648        break;
00649       }
00650       if (v_used_chars && v_used_chars[i] != 0) {
00651        last_cid = i * 8 + 7;
00652        c = v_used_chars[i];
00653        break;
00654       }
00655     }
00656     if (last_cid > 0) {
00657       for (i = 0; i < 8; i++) {
00658        if ((c >> i) & 1)
00659          break;
00660        last_cid--;
00661       }
00662     }
00663     if (last_cid >= 0xFFFFu) {
00664       ERROR("CID count > 65535");
00665     }
00666   }
00667 
00668 #ifndef NO_GHOSTSCRIPT_BUG
00669   cidtogidmap = NULL;
00670 #else
00671   cidtogidmap = NEW((last_cid + 1) * 2, unsigned char);
00672   memset(cidtogidmap, 0, (last_cid + 1) * 2);
00673 #endif /* !NO_GHOSTSCRIPT_BUG */
00674 
00675   /*
00676    * Map CIDs to GIDs.
00677    * Horizontal and vertical used_chars are merged.
00678    */
00679 
00680   /*
00681    * Horizontal
00682    */
00683   if (h_used_chars) {
00684     used_chars = h_used_chars;
00685     for (cid = 1; cid <= last_cid; cid++) {
00686       long           code;
00687       unsigned short gid;
00688 
00689       if (!is_used_char2(h_used_chars, cid))
00690        continue;
00691 
00692       if (glyph_ordering) {
00693        gid  = cid;
00694        code = cid;
00695       } else {
00696        code = cid_to_code(cmap, cid);
00697        gid  = tt_cmap_lookup(ttcmap, code);
00698 #ifdef FIX_CJK_UNIOCDE_SYMBOLS
00699        if (gid == 0 && unicode_cmap) {
00700          long alt_code;
00701 
00702          alt_code = fix_CJK_symbols(code);
00703          if (alt_code != code) {
00704            gid = tt_cmap_lookup(ttcmap, alt_code);
00705            if (gid != 0) {
00706              WARN("Unicode char U+%04x replaced with U+%04x.",
00707                  code, alt_code);
00708            }
00709          }
00710        }
00711 #endif /* FIX_CJK_UNIOCDE_SYMBOLS */
00712       }
00713 
00714       if (gid == 0) {
00715        WARN("Glyph missing in font. (CID=%u, code=0x%04x)", cid, code);
00716       }
00717 
00718       /* TODO: duplicated glyph */
00719 #ifndef NO_GHOSTSCRIPT_BUG
00720       gid = tt_add_glyph(glyphs, gid, cid);
00721 #else
00722       gid = tt_add_glyph(glyphs, gid, num_glyphs);
00723       cidtogidmap[2*cid  ] = gid >> 8;
00724       cidtogidmap[2*cid+1] = gid & 0xff;
00725 #endif /* !NO_GHOSTSCRIPT_BUG */
00726 
00727       num_glyphs++;
00728     }
00729   }
00730 
00731   /*
00732    * Vertical
00733    */
00734   if (v_used_chars) {
00735     otl_gsub *gsub_list = NULL;
00736 
00737     /*
00738      * Require `vrt2' or `vert'.
00739      */
00740     if (glyph_ordering) {
00741       gsub_list = NULL;
00742     } else {
00743       gsub_list = otl_gsub_new();
00744       if (otl_gsub_add_feat(gsub_list,
00745                          "*", "*", "vrt2", sfont) < 0) {
00746        if (otl_gsub_add_feat(gsub_list,
00747                            "*", "*", "vert", sfont) < 0) {
00748          WARN("GSUB feature vrt2/vert not found.");
00749          otl_gsub_release(gsub_list);
00750          gsub_list = NULL;
00751        } else {
00752          otl_gsub_select(gsub_list, "*", "*", "vert");
00753        }
00754       } else {
00755        otl_gsub_select(gsub_list, "*", "*", "vrt2");
00756       }
00757     }
00758 
00759     for (cid = 1; cid <= last_cid; cid++) {
00760       long           code;
00761       unsigned short gid;
00762 
00763       if (!is_used_char2(v_used_chars, cid))
00764        continue;
00765 
00766       /* There may be conflict of horizontal and vertical glyphs
00767        * when font is used with /UCS. However, we simply ignore
00768        * that...
00769        */
00770       if (h_used_chars && is_used_char2(h_used_chars, cid)) {
00771        continue;
00772       }
00773 
00774       if (glyph_ordering) {
00775        gid  = cid;
00776        code = cid;
00777       } else {
00778        code = cid_to_code(cmap, cid);
00779        gid  = tt_cmap_lookup(ttcmap, code);
00780 #ifdef FIX_CJK_UNIOCDE_SYMBOLS
00781        if (gid == 0 && unicode_cmap) {
00782          long alt_code;
00783 
00784          alt_code = fix_CJK_symbols(code);
00785          if (alt_code != code) {
00786            gid = tt_cmap_lookup(ttcmap, alt_code);
00787            if (gid != 0) {
00788              WARN("Unicode char U+%04x replaced with U+%04x.",
00789                  code, alt_code);
00790            }
00791          }
00792        }
00793 #endif /* FIX_CJK_UNIOCDE_SYMBOLS */
00794       }
00795       if (gid == 0) {
00796        WARN("Glyph missing in font. (CID=%u, code=0x%04x)", cid, code);
00797       } else if (gsub_list) {
00798        otl_gsub_apply(gsub_list, &gid);
00799       }
00800 
00801 #ifndef NO_GHOSTSCRIPT_BUG
00802       gid = tt_add_glyph(glyphs, gid, cid);
00803 #else
00804       gid = tt_add_glyph(glyphs, gid, num_glyphs);
00805       cidtogidmap[2*cid  ] = gid >> 8;
00806       cidtogidmap[2*cid+1] = gid & 0xff;
00807 #endif /* !NO_GHOSTSCRIPT_BUG */
00808 
00809       if (used_chars) /* merge vertical used_chars to horizontal */
00810        add_to_used_chars2(used_chars, cid);
00811 
00812       num_glyphs++;
00813     }
00814 
00815     if (gsub_list)
00816       otl_gsub_release(gsub_list);
00817 
00818     if (!used_chars) /* We have no horizontal. */
00819       used_chars = v_used_chars;
00820   }
00821 
00822   if (!used_chars)
00823     ERROR("Unexpected error.");
00824 
00825   tt_cmap_release(ttcmap);
00826 
00827   if (CIDFont_get_embedding(font)) {
00828     if (tt_build_tables(sfont, glyphs) < 0)
00829       ERROR("Could not created FontFile stream.");
00830     if (verbose > 1)
00831       MESG("[%u glyphs (Max CID: %u)]", glyphs->num_glyphs, last_cid);
00832   } else {
00833     if (tt_get_metrics(sfont, glyphs) < 0)
00834       ERROR("Reading glyph metrics failed...");
00835   }
00836 
00837   /*
00838    * DW, W, DW2, and W2
00839    */
00840   if (opt_flags & CIDFONT_FORCE_FIXEDPITCH) {
00841     pdf_add_dict(font->fontdict,
00842                pdf_new_name("DW"), pdf_new_number(1000.0));
00843   } else {
00844     add_TTCIDHMetrics(font->fontdict, glyphs, used_chars, cidtogidmap, last_cid);
00845     if (v_used_chars)
00846       add_TTCIDVMetrics(font->fontdict, glyphs, used_chars, cidtogidmap, last_cid);
00847   }
00848 
00849   tt_build_finish(glyphs);
00850 
00851   /* Finish here if not embedded. */
00852   if (!CIDFont_get_embedding(font)) {
00853     if (cidtogidmap)
00854       RELEASE(cidtogidmap);
00855     sfnt_close(sfont);
00856     DPXFCLOSE(fp);
00857 
00858     return;
00859   }
00860 
00861   /* Create font file */
00862   for (i = 0; required_table[i].name; i++) {
00863     if (sfnt_require_table(sfont,
00864                         required_table[i].name,
00865                         required_table[i].must_exist) < 0) {
00866       ERROR("Some required TrueType table (%s) does not exist.", required_table[i].name);
00867     }
00868   }
00869 
00870   /*
00871    * FontFile2
00872    */
00873   fontfile = sfnt_create_FontFile_stream(sfont);
00874 
00875   sfnt_close(sfont);
00876   DPXFCLOSE(fp);
00877 
00878   if (!fontfile)
00879     ERROR("Could not created FontFile stream for \"%s\".", font->ident);
00880 
00881   if (verbose > 1) {
00882     MESG("[%ld bytes]", pdf_stream_length(fontfile));
00883   }
00884 
00885   pdf_add_dict(font->descriptor,
00886               pdf_new_name("FontFile2"),
00887               pdf_ref_obj (fontfile));
00888   pdf_release_obj(fontfile);
00889 
00890   /*
00891    * CIDSet
00892    */
00893   {
00894     pdf_obj *cidset;
00895 
00896     cidset = pdf_new_stream(STREAM_COMPRESS);
00897     pdf_add_stream(cidset, used_chars, last_cid/8 + 1);
00898     pdf_add_dict(font->descriptor,
00899                pdf_new_name("CIDSet"),
00900                pdf_ref_obj(cidset));
00901     pdf_release_obj(cidset);
00902   }
00903 
00904   /*
00905    * CIDToGIDMap
00906    */
00907   if (cidtogidmap) {
00908     pdf_obj *c2gmstream;
00909 
00910     c2gmstream = pdf_new_stream(STREAM_COMPRESS);
00911     pdf_add_stream(c2gmstream, cidtogidmap, (last_cid + 1) * 2);
00912     pdf_add_dict(font->fontdict,
00913                  pdf_new_name("CIDToGIDMap"),
00914                  pdf_ref_obj (c2gmstream));
00915     pdf_release_obj(c2gmstream);
00916     RELEASE(cidtogidmap);
00917   }
00918   
00919   return;
00920 }
00921 
00922 int
00923 CIDFont_type2_open (CIDFont *font, const char *name,
00924                   CIDSysInfo *cmap_csi, cid_opt *opt)
00925 {
00926   char    *fontname;
00927   sfnt    *sfont;
00928   unsigned long offset = 0;
00929   FILE    *fp;
00930 
00931   ASSERT(font && opt);
00932 
00933   fp = DPXFOPEN(name, DPX_RES_TYPE_TTFONT);
00934   if (!fp) {
00935     fp = DPXFOPEN(name, DPX_RES_TYPE_DFONT);
00936     if (!fp) return -1;
00937     sfont = dfont_open(fp, opt->index);
00938   } else {
00939     sfont = sfnt_open(fp);
00940   }
00941 
00942   if (!sfont) {
00943     DPXFCLOSE(fp);
00944     return -1;
00945   }
00946 
00947   switch (sfont->type) {
00948   case SFNT_TYPE_TTC:
00949     offset = ttc_read_offset(sfont, opt->index);
00950     break;
00951   case SFNT_TYPE_TRUETYPE:
00952     if (opt->index > 0) {
00953       ERROR("Invalid TTC index (not TTC font): %s", name);
00954     } else {
00955       offset = 0;
00956     }
00957     break;
00958   case SFNT_TYPE_DFONT:
00959     offset = sfont->offset;
00960     break;
00961   default:
00962     sfnt_close(sfont);
00963     DPXFCLOSE(fp);
00964     return -1;
00965     break;
00966   }
00967 
00968   if (sfnt_read_table_directory(sfont, offset) < 0) {
00969     ERROR("Reading TrueType table directory failed.");
00970   }
00971 
00972   {
00973     char *shortname;
00974     long  namelen;
00975 
00976     /* MAC-ROMAN-EN-POSTSCRIPT or WIN-UNICODE-EN(US)-POSTSCRIPT */
00977     shortname = NEW(PDF_NAME_LEN_MAX, char);
00978     namelen   = tt_get_ps_fontname(sfont, shortname, PDF_NAME_LEN_MAX);
00979     if (namelen == 0) {
00980       memset(shortname, 0, PDF_NAME_LEN_MAX);
00981       strncpy(shortname, name, PDF_NAME_LEN_MAX);
00982       namelen = strlen(shortname);
00983     }
00984     validate_name(shortname, namelen); /* for SJIS, UTF-16, ... string */
00985     /*
00986      * Strlen works, after validate_named string.
00987      * Mangled name requires more 7 bytes.
00988      * Style requires more 11 bytes.
00989      */
00990     fontname = NEW(strlen(shortname)+19, char);
00991     strcpy(fontname, shortname);
00992     RELEASE(shortname);
00993   }
00994 
00995   if (opt->embed && opt->style != FONT_STYLE_NONE) {
00996     WARN("Embedding disabled due to style option for %s.", name);
00997     opt->embed = 0;
00998   }
00999   switch (opt->style) {
01000   case FONT_STYLE_BOLD:
01001     strcat(fontname, ",Bold");
01002     break;
01003   case FONT_STYLE_ITALIC:
01004     strcat(fontname, ",Italic");
01005     break;
01006   case FONT_STYLE_BOLDITALIC:
01007     strcat(fontname, ",BoldItalic");
01008     break;
01009   }
01010   /*
01011    * CIDSystemInfo is determined from CMap or from map record option.
01012    */
01013   font->fontname = fontname;
01014   font->subtype  = CIDFONT_TYPE2;
01015   font->csi      = NEW(1, CIDSysInfo);
01016   if (opt->csi) {
01017     if (cmap_csi) {
01018       if (strcmp(opt->csi->registry, cmap_csi->registry) ||
01019          strcmp(opt->csi->ordering, cmap_csi->ordering)) {
01020        WARN("CID character collection mismatched:\n");
01021        MESG("\tFont: %s-%s-%d\n",
01022             opt->csi->registry, opt->csi->ordering, opt->csi->supplement);
01023        MESG("\tCMap: %s-%s-%d\n",
01024             cmap_csi->registry, cmap_csi->ordering, cmap_csi->supplement);
01025        ERROR("Incompatible CMap specified for this font.");
01026       }
01027       if (opt->csi->supplement < cmap_csi->supplement) {
01028        WARN("Supplmement value in CIDSystemInfo increased.");
01029        WARN("Some characters may not shown.");
01030        opt->csi->supplement = cmap_csi->supplement;
01031       }
01032     }
01033     font->csi->registry   = NEW(strlen(opt->csi->registry)+1, char);
01034     strcpy(font->csi->registry, opt->csi->registry);
01035     font->csi->ordering   = NEW(strlen(opt->csi->ordering)+1, char);
01036     strcpy(font->csi->ordering, opt->csi->ordering);
01037     font->csi->supplement = opt->csi->supplement;
01038   } else if (cmap_csi) {
01039     font->csi->registry   = NEW(strlen(cmap_csi->registry)+1, char);
01040     strcpy(font->csi->registry, cmap_csi->registry);
01041     font->csi->ordering   = NEW(strlen(cmap_csi->ordering)+1, char);
01042     strcpy(font->csi->ordering, cmap_csi->ordering);
01043     font->csi->supplement = cmap_csi->supplement;
01044   } else { /* This means font's internal glyph ordering. */
01045     font->csi->registry   = NEW(strlen("Adobe")+1, char);
01046     strcpy(font->csi->registry, "Adobe");
01047     font->csi->ordering   = NEW(strlen("Identity")+1, char);
01048     strcpy(font->csi->ordering, "Identity");
01049     font->csi->supplement = 0;
01050   }
01051 
01052   font->fontdict = pdf_new_dict();
01053   pdf_add_dict(font->fontdict,
01054               pdf_new_name("Type"),
01055               pdf_new_name("Font"));
01056   pdf_add_dict(font->fontdict,
01057               pdf_new_name("Subtype"),
01058               pdf_new_name("CIDFontType2"));
01059 
01060   font->descriptor = tt_get_fontdesc(sfont, &(opt->embed), opt->stemv, 0);
01061   if (!font->descriptor) {
01062     ERROR("Could not obtain neccesary font info.");
01063   }
01064 
01065   if (opt->embed) {
01066     memmove(fontname + 7, fontname, strlen(fontname) + 1);
01067     pdf_font_make_uniqueTag(fontname);
01068     fontname[6] = '+';
01069   }
01070 
01071   pdf_add_dict(font->descriptor,
01072               pdf_new_name("FontName"),
01073               pdf_new_name(fontname));
01074   pdf_add_dict(font->fontdict, 
01075               pdf_new_name("BaseFont"),
01076               pdf_new_name(fontname));
01077 
01078   sfnt_close(sfont);
01079   DPXFCLOSE(fp);
01080 
01081   /*
01082    * Don't write fontdict here.
01083    * /Supplement in /CIDSystemInfo may change.
01084    */
01085 
01086   return 0;
01087 }
01088 
01089 void
01090 CIDFont_type2_release (CIDFont *font)
01091 {
01092   return;
01093 }