Back to index

texmacs  1.0.7.15
tt_cmap.c
Go to the documentation of this file.
00001 /*  $Header: /home/cvsroot/dvipdfmx/src/tt_cmap.c,v 1.27 2009/09/18 23:56:02 matthias 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  * A large part of codes are brought from ttfdump-0.5.5.
00025  */
00026 
00027 #ifdef HAVE_CONFIG_H
00028 #include "config.h"
00029 #endif
00030 
00031 #include "system.h"
00032 #include "mem.h"
00033 #include "error.h"
00034 
00035 #include "sfnt.h"
00036 
00037 
00038 /* Sorry for placing this here.
00039  * We need to rewrite TrueType font support code...
00040  */
00041 #include "cmap.h"
00042 #include "cmap_write.h"
00043 
00044 #include "tt_aux.h"
00045 #include "tt_gsub.h"
00046 
00047 #include "unicode.h"
00048 #include "agl.h"
00049 #include "pdfparse.h"
00050 #include "pdfresource.h"
00051 #include "otl_conf.h"
00052 
00053 #include "dpxfile.h"
00054 
00055 /* Hash */
00056 #include "dpxutil.h"
00057 
00058 #include "tt_cmap.h"
00059 
00060 #define VERBOSE_LEVEL_MIN 0
00061 static int verbose = 0;
00062 void
00063 otf_cmap_set_verbose (void)
00064 {
00065   otl_gsub_set_verbose();
00066   verbose++;
00067 }
00068 
00069 /* format 0: byte encoding table */
00070 struct cmap0
00071 {
00072   BYTE glyphIndexArray[256];
00073 };
00074 
00075 static struct cmap0 *
00076 read_cmap0 (sfnt *sfont, ULONG len)
00077 {
00078   struct cmap0 *map;
00079   int    i;
00080 
00081   if (len < 256)
00082     ERROR("invalid cmap subtable");
00083 
00084   map = NEW(1, struct cmap0);
00085 
00086   for (i = 0; i < 256; i++)
00087     map->glyphIndexArray[i] = sfnt_get_byte(sfont);
00088 
00089   return map;
00090 }
00091 
00092 static void
00093 release_cmap0(struct cmap0 *map)
00094 {
00095   if (map)
00096     RELEASE(map);
00097 }
00098 
00099 static USHORT
00100 lookup_cmap0 (struct cmap0 *map, USHORT cc)
00101 {
00102   return ((cc > 255) ? 0 : map->glyphIndexArray[cc]);
00103 }
00104 
00105 /* format 2: high-byte mapping through table */
00106 struct SubHeader
00107 {
00108   USHORT firstCode;
00109   USHORT entryCount;
00110   SHORT  idDelta;
00111   USHORT idRangeOffset;
00112 };
00113 
00114 struct cmap2
00115 {
00116   USHORT  subHeaderKeys[256];
00117   struct SubHeader *subHeaders;
00118   USHORT *glyphIndexArray;
00119 };
00120 
00121 static struct cmap2 *
00122 read_cmap2 (sfnt *sfont, ULONG len)
00123 {
00124   struct cmap2 *map;
00125   USHORT i, n;
00126 
00127   if (len < 512)
00128     ERROR("invalid cmap subtable");
00129     
00130   map = NEW(1, struct cmap2);
00131 
00132   for (i = 0; i < 256; i++)
00133     map->subHeaderKeys[i] = sfnt_get_ushort(sfont);
00134 
00135   for (n = 0, i = 0; i < 256; i++) {
00136     map->subHeaderKeys[i] /= 8;
00137     if (n < map->subHeaderKeys[i])
00138       n = map->subHeaderKeys[i];
00139   }
00140   n += 1; /* the number of subHeaders is one plus the max of subHeaderKeys */
00141 
00142   map->subHeaders = NEW(n, struct SubHeader); 
00143   for (i = 0; i < n; i++) {
00144     map->subHeaders[i].firstCode     = sfnt_get_ushort(sfont);
00145     map->subHeaders[i].entryCount    = sfnt_get_ushort(sfont);
00146     map->subHeaders[i].idDelta       = sfnt_get_short(sfont);
00147     map->subHeaders[i].idRangeOffset = sfnt_get_ushort(sfont);
00148 
00149     /* It makes things easier to let the offset starts from
00150      * the beginning of glyphIndexArray.
00151      */
00152     if (map->subHeaders[i].idRangeOffset != 0)
00153       map->subHeaders[i].idRangeOffset -= (2 + (n - i - 1) * 8);
00154   }
00155 
00156   /* Caculate the length of glyphIndexArray, this is ugly,
00157    * there should be a better way to get this information.
00158    */
00159   n = (USHORT) (len - 518 - n * 8) / 2;
00160 
00161   map->glyphIndexArray = NEW(n, USHORT);
00162   for (i = 0; i < n; i++)
00163     map->glyphIndexArray[i] = sfnt_get_ushort(sfont);
00164 
00165   return map;
00166 }
00167 
00168 static void
00169 release_cmap2 (struct cmap2 *map)
00170 {
00171   if (map) {
00172     if (map->subHeaders)
00173       RELEASE(map->subHeaders);
00174     if (map->glyphIndexArray)
00175       RELEASE(map->glyphIndexArray);
00176     RELEASE(map);
00177   }
00178 }
00179 
00180 static USHORT
00181 lookup_cmap2 (struct cmap2 *map, USHORT cc)
00182 {
00183   USHORT  idx = 0;
00184   SHORT   idDelta;
00185   USHORT  firstCode, entryCount, idRangeOffset;
00186   int     hi, lo;
00187   USHORT  i;
00188    
00189   hi = (cc >> 8) & 0xff;
00190   lo = cc & 0xff;
00191 
00192   /* select which subHeader to use */
00193   i = map->subHeaderKeys[hi];
00194 
00195   firstCode     = map->subHeaders[i].firstCode;
00196   entryCount    = map->subHeaders[i].entryCount;
00197   idDelta       = map->subHeaders[i].idDelta;
00198   idRangeOffset = map->subHeaders[i].idRangeOffset / 2;
00199 
00200   if (lo >= firstCode &&
00201       lo < firstCode + entryCount) {
00202     idRangeOffset += lo - firstCode;
00203     idx = map->glyphIndexArray[idRangeOffset];
00204     if (idx != 0)
00205       idx = (idx + idDelta) & 0xffff;
00206   }
00207 
00208   return idx;
00209 }
00210 
00211 /*
00212  * format 4: segment mapping to delta values
00213  * - Microsoft standard character to glyph index mapping table
00214  */
00215 struct cmap4
00216 {
00217   USHORT  segCountX2;
00218   USHORT  searchRange;
00219   USHORT  entrySelector;
00220   USHORT  rangeShift;
00221   USHORT *endCount;
00222   USHORT  reservedPad;
00223   USHORT *startCount;
00224   USHORT *idDelta;
00225   USHORT *idRangeOffset;
00226   USHORT *glyphIndexArray;
00227 };
00228 
00229 static struct cmap4 *
00230 read_cmap4(sfnt *sfont, ULONG len)
00231 {
00232   struct cmap4 *map;
00233   USHORT i, n, segCount;
00234 
00235   if (len < 8)
00236     ERROR("invalid cmap subtable");
00237 
00238   map = NEW(1, struct cmap4);
00239 
00240   map->segCountX2    = segCount = sfnt_get_ushort(sfont);
00241   map->searchRange   = sfnt_get_ushort(sfont);
00242   map->entrySelector = sfnt_get_ushort(sfont);
00243   map->rangeShift    = sfnt_get_ushort(sfont);
00244   
00245   segCount /= 2;
00246 
00247   map->endCount = NEW(segCount, USHORT);
00248   for (i = 0; i < segCount; i++)
00249     map->endCount[i] = sfnt_get_ushort(sfont);
00250 
00251   map->reservedPad = sfnt_get_ushort(sfont);
00252 
00253   map->startCount  = NEW(segCount, USHORT);
00254   for (i = 0; i < segCount; i++)
00255     map->startCount[i] = sfnt_get_ushort(sfont);
00256 
00257   map->idDelta = NEW(segCount, USHORT);
00258   for (i = 0; i < segCount; i++)
00259     map->idDelta[i] = sfnt_get_ushort(sfont);
00260 
00261   map->idRangeOffset = NEW(segCount, USHORT);
00262   for (i = 0; i < segCount; i++)
00263     map->idRangeOffset[i] = sfnt_get_ushort(sfont);
00264 
00265   n = (len - 16 - 8 * segCount) / 2;
00266   if (n == 0)
00267     map->glyphIndexArray = NULL;
00268   else {
00269     map->glyphIndexArray = NEW(n, USHORT);
00270     for (i = 0; i < n; i++)
00271       map->glyphIndexArray[i] = sfnt_get_ushort(sfont);
00272   }
00273 
00274   return map;
00275 }
00276 
00277 static void
00278 release_cmap4 (struct cmap4 *map)
00279 {
00280   if (map) {
00281     if (map->endCount)   RELEASE(map->endCount);
00282     if (map->startCount) RELEASE(map->startCount);
00283     if (map->idDelta)    RELEASE(map->idDelta);
00284     if (map->idRangeOffset)   RELEASE(map->idRangeOffset);
00285     if (map->glyphIndexArray) RELEASE(map->glyphIndexArray);
00286     RELEASE(map);
00287   }
00288 }
00289 
00290 static USHORT
00291 lookup_cmap4 (struct cmap4 *map, USHORT cc)
00292 {
00293   USHORT gid = 0;
00294   USHORT i, j, segCount;
00295 
00296   /*
00297    * Segments are sorted in order of increasing endCode values.
00298    * Last segment maps 0xffff to gid 0 (?)
00299   */
00300   i = segCount = map->segCountX2 / 2;
00301   while (i-- > 0 &&  cc <= map->endCount[i]) {
00302     if (cc >= map->startCount[i]) {
00303       if (map->idRangeOffset[i] == 0) {
00304        gid = (cc + map->idDelta[i]) & 0xffff;
00305       } else {
00306        j  = map->idRangeOffset[i] - (segCount - i) * 2;
00307        j  = (cc - map->startCount[i]) + (j / 2);
00308        gid = map->glyphIndexArray[j];
00309        if (gid != 0)
00310          gid = (gid + map->idDelta[i]) & 0xffff;
00311       }
00312       break;
00313     }
00314   }
00315 
00316   return gid;
00317 }
00318 
00319 /* format 6: trimmed table mapping */
00320 struct cmap6
00321 {
00322   USHORT  firstCode;
00323   USHORT  entryCount;
00324   USHORT *glyphIndexArray;
00325 };
00326 
00327 static struct cmap6 *
00328 read_cmap6 (sfnt *sfont, ULONG len)
00329 {
00330   struct cmap6 *map;
00331   USHORT i;
00332   
00333   if (len < 4)
00334     ERROR("invalid cmap subtable");
00335 
00336   map =  NEW(1, struct cmap6);
00337   map->firstCode       = sfnt_get_ushort(sfont);
00338   map->entryCount      = sfnt_get_ushort(sfont);
00339   map->glyphIndexArray = NEW(map->entryCount, USHORT);
00340   
00341   for (i = 0; i < map->entryCount; i++)
00342     map->glyphIndexArray[i] = sfnt_get_ushort(sfont);
00343 
00344   return map;
00345 }
00346 
00347 static void
00348 release_cmap6 (struct cmap6 *map)
00349 {
00350   if (map) {
00351     if (map->glyphIndexArray)
00352       RELEASE(map->glyphIndexArray);
00353     RELEASE(map);
00354   }
00355 }
00356 
00357 static USHORT
00358 lookup_cmap6 (struct cmap6 *map, USHORT cc)
00359 {
00360   USHORT idx;
00361 
00362   idx = cc - map->firstCode; 
00363   if (idx < map->entryCount)
00364     return map->glyphIndexArray[idx];
00365   else
00366     return 0;
00367 
00368   return 0;
00369 }
00370 
00371 /* Format 8 and 10 not supported...
00372  *
00373  *  format  8: mixed 16-bit and 32-bit coverage
00374  *  format 10: trimmed array
00375  */
00376 
00377 /*
00378  * format 12: segmented coverage
00379  *
00380  * startGlyphID is 32-bit long, however, GlyphID is still 16-bit long !
00381  */
00382 
00383 struct charGroup
00384 {
00385   ULONG startCharCode;
00386   ULONG endCharCode;
00387   ULONG startGlyphID;
00388 };
00389 
00390 struct cmap12
00391 {
00392   ULONG  nGroups;
00393   struct charGroup *groups;
00394 };
00395 
00396 /* ULONG length */
00397 static struct cmap12 *
00398 read_cmap12 (sfnt *sfont, ULONG len)
00399 {
00400   struct cmap12 *map;
00401   ULONG  i;
00402   
00403   if (len < 4)
00404     ERROR("invalid cmap subtable");
00405 
00406   map =  NEW(1, struct cmap12);
00407   map->nGroups = sfnt_get_ulong(sfont);
00408   map->groups  = NEW(map->nGroups, struct charGroup);
00409 
00410   for (i = 0; i < map->nGroups; i++) {
00411     map->groups[i].startCharCode = sfnt_get_ulong(sfont);
00412     map->groups[i].endCharCode   = sfnt_get_ulong(sfont);
00413     map->groups[i].startGlyphID  = sfnt_get_ulong(sfont);
00414   }
00415 
00416   return map;
00417 }
00418 
00419 static void
00420 release_cmap12 (struct cmap12 *map)
00421 {
00422   if (map) {
00423     if (map->groups)
00424       RELEASE(map->groups);
00425     RELEASE(map);
00426   }
00427 }
00428 
00429 static USHORT
00430 lookup_cmap12 (struct cmap12 *map, ULONG cccc)
00431 {
00432   USHORT gid = 0;
00433   ULONG  i;
00434 
00435   i = map->nGroups;
00436   while (i-- >= 0 &&
00437         cccc <= map->groups[i].endCharCode) {
00438     if (cccc >= map->groups[i].startCharCode) {
00439       gid = (USHORT) ((cccc -
00440                      map->groups[i].startCharCode +
00441                      map->groups[i].startGlyphID) & 0xffff);
00442       break;
00443     }
00444   }
00445 
00446   return gid;
00447 }
00448 
00449 /* read cmap */
00450 tt_cmap *
00451 tt_cmap_read (sfnt *sfont, USHORT platform, USHORT encoding)
00452 {
00453   tt_cmap *cmap = NULL;
00454   ULONG    offset, length = 0;
00455   USHORT   version, p_id, e_id;
00456   USHORT   i, n_subtabs;
00457 
00458   ASSERT(sfont);
00459 
00460   offset    = sfnt_locate_table(sfont, "cmap");
00461   version   = sfnt_get_ushort(sfont);
00462   n_subtabs = sfnt_get_ushort(sfont);
00463 
00464   for (i = 0; i < n_subtabs; i++) {
00465     p_id = sfnt_get_ushort(sfont);
00466     e_id = sfnt_get_ushort(sfont);
00467     if (p_id != platform || e_id != encoding)
00468       sfnt_get_ulong(sfont);
00469     else {
00470       offset += sfnt_get_ulong(sfont);
00471       break;
00472     }
00473   }
00474 
00475   if (i == n_subtabs)
00476     return NULL;
00477 
00478   cmap = NEW(1, tt_cmap);
00479   cmap->map      = NULL;
00480   cmap->platform = platform;
00481   cmap->encoding = encoding;
00482 
00483   sfnt_seek_set(sfont, offset);
00484   cmap->format = sfnt_get_ushort(sfont);
00485   /* Length and version (language) is ULONG for
00486    * format 8, 10, 12 !
00487    */
00488   if (cmap->format <= 6) {
00489     length         = sfnt_get_ushort(sfont);
00490     cmap->language = sfnt_get_ushort(sfont); /* language (Mac) */
00491   } else {
00492     if (sfnt_get_ushort(sfont) != 0) { /* reverved - 0 */
00493       WARN("Unrecognized cmap subtable format.");
00494       tt_cmap_release(cmap);
00495       return NULL;
00496     } else {
00497       length         = sfnt_get_ulong(sfont);
00498       cmap->language = sfnt_get_ulong(sfont);
00499     }
00500   }
00501   
00502   switch(cmap->format) {
00503   case 0:
00504     cmap->map = read_cmap0(sfont, length);
00505     break;
00506   case 2:
00507     cmap->map = read_cmap2(sfont, length);
00508     break;
00509   case 4:
00510     cmap->map = read_cmap4(sfont, length);
00511     break;
00512   case 6:
00513     cmap->map = read_cmap6(sfont, length);
00514     break;
00515   case 12:
00516     WARN("UCS-4 TrueType cmap table...");
00517     cmap->map = read_cmap12(sfont, length);
00518     break;
00519   default:
00520     WARN("Unrecognized TrueType cmap format.");
00521     tt_cmap_release(cmap);
00522     return NULL;
00523   }
00524 
00525   if (!cmap->map) {
00526     tt_cmap_release(cmap);
00527     cmap = NULL;
00528   }
00529 
00530   return cmap;
00531 }
00532 
00533 void
00534 tt_cmap_release (tt_cmap *cmap)
00535 {
00536 
00537   if (cmap) {
00538     if (cmap->map) {
00539       switch(cmap->format) {
00540       case 0:
00541        release_cmap0(cmap->map);
00542        break;
00543       case 2:
00544        release_cmap2(cmap->map);
00545        break;
00546       case 4:
00547        release_cmap4(cmap->map);
00548        break;
00549       case 6:
00550        release_cmap6(cmap->map);
00551        break;
00552       case 12:
00553        release_cmap12(cmap->map);
00554        break;
00555       default:
00556        ERROR("Unrecognized TrueType cmap format.");
00557       }
00558     }
00559     RELEASE(cmap);
00560   }
00561 
00562   return;
00563 }
00564 
00565 
00566 USHORT
00567 tt_cmap_lookup (tt_cmap *cmap, long cc)
00568 {
00569   USHORT gid = 0;
00570 
00571   ASSERT(cmap);
00572 
00573   if (cc > 0xffffL && cmap->format < 12) {
00574     WARN("Four bytes charcode not supported in TrueType cmap format 0...6.");
00575     return 0;
00576   }
00577 
00578   switch (cmap->format) {
00579   case 0:
00580     gid = lookup_cmap0(cmap->map,  (USHORT) cc);
00581     break;
00582   case 2:
00583     gid = lookup_cmap2(cmap->map,  (USHORT) cc);
00584     break;
00585   case 4:
00586     gid = lookup_cmap4(cmap->map,  (USHORT) cc);
00587     break;
00588   case 6:
00589     gid = lookup_cmap6(cmap->map,  (USHORT) cc);
00590     break;
00591   case 12:
00592     gid = lookup_cmap12(cmap->map, (ULONG) cc);
00593     break;
00594   default:
00595     ERROR("Unrecognized TrueType cmap subtable format");
00596     break;
00597   }
00598 
00599   return gid;
00600 }
00601 
00602 /* Sorry for placing this here.
00603  * We need to rewrite TrueType font support code...
00604  */
00605 
00606 #define WBUF_SIZE 1024
00607 static unsigned char wbuf[WBUF_SIZE];
00608 
00609 static unsigned char srange_min[2] = {0x00, 0x00};
00610 static unsigned char srange_max[2] = {0xff, 0xff};
00611 static unsigned char lrange_min[4] = {0x00, 0x00, 0x00, 0x00};
00612 static unsigned char lrange_max[4] = {0x7f, 0xff, 0xff, 0xff};
00613 
00614 static void
00615 load_cmap4 (struct cmap4 *map,
00616            unsigned char *GIDToCIDMap, CMap *cmap)
00617 {
00618   USHORT  c0, c1, gid, cid;
00619   USHORT  j, d, segCount;
00620   USHORT  ch;
00621   long    i;
00622 
00623   segCount = map->segCountX2 / 2;
00624   for (i = segCount - 1; i >= 0 ; i--) {
00625     c0 = map->startCount[i];
00626     c1 = map->endCount[i];
00627     d  = map->idRangeOffset[i] / 2 - (segCount - i);
00628     for (j = 0; j <= c1 - c0; j++) {
00629       ch = c0 + j;
00630       if (map->idRangeOffset[i] == 0) {
00631        gid = (ch + map->idDelta[i]) & 0xffff;
00632       } else {
00633        gid = (map->glyphIndexArray[j+d] +
00634               map->idDelta[i]) & 0xffff;
00635       }
00636       if (gid != 0 && gid != 0xffff) {
00637        if (GIDToCIDMap) {
00638          cid = ((GIDToCIDMap[2*gid] << 8)|GIDToCIDMap[2*gid+1]);
00639          if (cid == 0)
00640            WARN("GID %u does not have corresponding CID %u.",
00641                gid, cid);
00642        } else {
00643          cid = gid;
00644        }
00645        wbuf[0] = 0;
00646        wbuf[1] = 0;
00647        wbuf[2] = (ch >> 8) & 0xff;
00648        wbuf[3] =  ch & 0xff;
00649        CMap_add_cidchar(cmap, wbuf, 4, cid);
00650       }
00651     }
00652   }
00653 
00654   return;
00655 }
00656 
00657 static void
00658 load_cmap12 (struct cmap12 *map,
00659             unsigned char *GIDToCIDMap, CMap *cmap)
00660 {
00661   ULONG   i, ch;  /* LONG ? */
00662   USHORT  gid, cid;
00663 
00664   for (i = 0; i < map->nGroups; i++) {
00665     for (ch  = map->groups[i].startCharCode;
00666         ch <= map->groups[i].endCharCode;
00667         ch++) {
00668       long  d = ch - map->groups[i].startCharCode;
00669       gid = (USHORT) ((map->groups[i].startGlyphID + d) & 0xffff);
00670       if (GIDToCIDMap) {
00671        cid = ((GIDToCIDMap[2*gid] << 8)|GIDToCIDMap[2*gid+1]);
00672        if (cid == 0)
00673          WARN("GID %u does not have corresponding CID %u.", gid, cid);
00674       } else {
00675        cid = gid;
00676       }
00677       wbuf[0] = (ch >> 24) & 0xff;
00678       wbuf[1] = (ch >> 16) & 0xff;
00679       wbuf[2] = (ch >>  8) & 0xff;
00680       wbuf[3] = ch & 0xff;
00681       CMap_add_cidchar(cmap, wbuf, 4, cid);
00682     }
00683   }
00684 
00685   return;
00686 }
00687 
00688 /* OpenType CIDFont:
00689  *
00690  *  We don't use GID for them. OpenType cmap table is for
00691  *  charcode to GID mapping rather than to-CID mapping.
00692  */
00693 #include "cid.h"
00694 
00695 #include "tt_table.h"
00696 #include "cff_types.h"
00697 #include "cff_dict.h"
00698 #include "cff.h"
00699 
00700 static int
00701 handle_CIDFont (sfnt *sfont,
00702               unsigned char **GIDToCIDMap, CIDSysInfo *csi)
00703 {
00704   cff_font *cffont;
00705   long      offset, i;
00706   card16    num_glyphs, gid;
00707   cff_charsets  *charset;
00708   unsigned char *map;
00709   struct tt_maxp_table *maxp;
00710 
00711   ASSERT(csi);
00712 
00713   offset = sfnt_find_table_pos(sfont, "CFF ");
00714   if (offset == 0) {
00715     csi->registry = NULL;
00716     csi->ordering = NULL;
00717     *GIDToCIDMap  = NULL;
00718     return 0;
00719   }
00720 
00721   maxp       = tt_read_maxp_table(sfont);
00722   num_glyphs = (card16) maxp->numGlyphs;
00723   RELEASE(maxp);
00724   if (num_glyphs < 1)
00725     ERROR("No glyph contained in this font...");
00726 
00727   cffont = cff_open(sfont->stream, offset, 0);
00728   if (!cffont)
00729     ERROR("Could not open CFF font...");
00730 
00731   
00732   if (!(cffont->flag & FONTTYPE_CIDFONT)) {
00733     cff_close(cffont);
00734     csi->registry = NULL;
00735     csi->ordering = NULL;
00736     *GIDToCIDMap  = NULL;
00737     return 0;
00738   }
00739 
00740   if (!cff_dict_known(cffont->topdict, "ROS")) {
00741     ERROR("No CIDSystemInfo???");
00742   } else {
00743     card16 reg, ord;
00744 
00745     reg = (card16) cff_dict_get(cffont->topdict, "ROS", 0);
00746     ord = (card16) cff_dict_get(cffont->topdict, "ROS", 1);
00747 
00748     csi->registry = cff_get_string(cffont, reg);
00749     csi->ordering = cff_get_string(cffont, ord);
00750     csi->supplement = (int) cff_dict_get(cffont->topdict, "ROS", 2);
00751   }
00752 
00753   cff_read_charsets(cffont);
00754   charset = cffont->charsets;
00755   if (!charset) {
00756     ERROR("No CFF charset data???");
00757   }
00758 
00759   map     = NEW(num_glyphs * 2, unsigned char);
00760   memset(map, 0, num_glyphs * 2);
00761   switch (charset->format) {
00762   case 0:
00763     {
00764       s_SID   *cids; /* CID... */
00765 
00766       cids = charset->data.glyphs;
00767       for (gid = 1, i = 0;
00768           i < charset->num_entries; i++) {
00769        map[2*gid  ] = (cids[i] >> 8) & 0xff;
00770        map[2*gid+1] = cids[i] & 0xff;
00771        gid++;
00772       }
00773     }
00774     break;
00775   case 1:
00776     {
00777       cff_range1 *ranges;
00778       card16      cid, count;
00779 
00780       ranges = charset->data.range1;
00781       for (gid = 1, i = 0;
00782           i < charset->num_entries; i++) {
00783        cid   = ranges[i].first;
00784        count = ranges[i].n_left + 1; /* card8 */
00785        while (count-- > 0 &&
00786               gid <= num_glyphs) {
00787          map[2*gid    ] = (cid >> 8) & 0xff;
00788          map[2*gid + 1] = cid & 0xff;
00789          gid++;
00790        }
00791       }
00792     }
00793     break;
00794   case 2:
00795     {
00796       cff_range2 *ranges;
00797       card16      cid, count;
00798 
00799       ranges = charset->data.range2;
00800       if (charset->num_entries == 1 &&
00801          ranges[0].first == 1) {
00802        /* "Complete" CIDFont */
00803        RELEASE(map); map = NULL;
00804       } else {
00805        /* Not trivial mapping */
00806        for (gid = 1, i = 0;
00807             i < charset->num_entries; i++) {
00808          cid   = ranges[i].first;
00809          count = ranges[i].n_left + 1;
00810          while (count-- > 0 &&
00811                gid <= num_glyphs) {
00812            map[gid] = (cid >> 8) & 0xff;
00813            map[gid] = cid & 0xff;
00814            gid++;
00815          }
00816        }
00817        
00818       }
00819     }
00820     break;
00821   default:
00822     RELEASE(map); map = NULL;
00823     ERROR("Unknown CFF charset format...: %d", charset->format);
00824     break;
00825   }
00826   cff_close(cffont);
00827 
00828   *GIDToCIDMap = map;
00829   return 1;
00830 }
00831 
00832 /*
00833  * Substituted glyphs:
00834  *
00835  *  Mapping information stored in cmap_add.
00836  */
00837 #ifndef is_used_char2
00838 #define is_used_char2(b,c) (((b)[(c)/8]) & (1 << (7-((c)%8))))
00839 #endif
00840 
00841 static USHORT
00842 handle_subst_glyphs (CMap *cmap,
00843                    CMap *cmap_add, const char *used_glyphs)
00844 {
00845   USHORT count;
00846   USHORT i, gid;
00847 
00848   for (count = 0, i = 0; i < 8192; i++) {
00849     int   j;
00850     long  len, inbytesleft, outbytesleft;
00851     unsigned char *inbuf, *outbuf;
00852 
00853     if (used_glyphs[i] == 0)
00854       continue;
00855 
00856     for (j = 0; j < 8; j++) {
00857       gid = 8 * i + j;
00858 
00859       if (!is_used_char2(used_glyphs, gid))
00860        continue;
00861 
00862       if (!cmap_add)
00863        WARN("No Unicode mapping available: GID=%u", gid);
00864       else {
00865        wbuf[0] = (gid >> 8) & 0xff;
00866        wbuf[1] =  gid & 0xff;
00867        inbuf        = wbuf;
00868        inbytesleft  = 2;
00869        outbuf       = inbuf + 2;
00870        outbytesleft = WBUF_SIZE - 2;
00871        CMap_decode(cmap_add,
00872                   (const unsigned char **) &inbuf , &inbytesleft,
00873                   &outbuf, &outbytesleft);
00874        if (inbytesleft != 0) {
00875          WARN("CMap conversion failed...");
00876        } else {
00877          len = WBUF_SIZE - 2 - outbytesleft;
00878          CMap_add_bfchar(cmap, wbuf, 2, wbuf + 2, len);
00879          count++;
00880 
00881          if (verbose > VERBOSE_LEVEL_MIN) {
00882            long _i;
00883 
00884            MESG("otf_cmap>> Additional ToUnicode mapping: <%04X> <", gid);
00885            for (_i = 0; _i < len; _i++) {
00886              MESG("%02X", wbuf[2 + _i]);
00887            }
00888            MESG(">\n");
00889          }
00890 
00891        }
00892       }
00893 
00894     }
00895   }
00896 
00897   return count;
00898 }
00899 
00900 static pdf_obj *
00901 create_ToUnicode_cmap4 (struct cmap4 *map,
00902                      const char *cmap_name, CMap *cmap_add,
00903                      const char *used_glyphs)
00904 {
00905   pdf_obj  *stream = NULL;
00906   CMap     *cmap;
00907   USHORT    c0, c1, gid, count, ch;
00908   USHORT    i, j, d, segCount;
00909   char      used_glyphs_copy[8192];
00910 
00911   cmap = CMap_new();
00912   CMap_set_name (cmap, cmap_name);
00913   CMap_set_wmode(cmap, 0);
00914   CMap_set_type (cmap, CMAP_TYPE_TO_UNICODE);
00915   CMap_set_CIDSysInfo(cmap, &CSI_UNICODE);
00916   CMap_add_codespacerange(cmap, srange_min, srange_max, 2);
00917 
00918   memcpy(used_glyphs_copy, used_glyphs, 8192);
00919 
00920   segCount = map->segCountX2 / 2;
00921   for (count = 0, i = 0; i < segCount; i++) {
00922     c0 = map->startCount[i];
00923     c1 = map->endCount[i];
00924     d  = map->idRangeOffset[i] / 2 - (segCount - i);
00925     for (j = 0; j <= c1 - c0; j++) {
00926       ch = c0 + j;
00927       if (map->idRangeOffset[i] == 0) {
00928        gid = (ch + map->idDelta[i]) & 0xffff;
00929       } else {
00930        gid = (map->glyphIndexArray[j+d] +
00931               map->idDelta[i]) & 0xffff;
00932       }
00933       if (is_used_char2(used_glyphs_copy, gid)) {
00934        count++;
00935 
00936        wbuf[0] = (gid >> 8) & 0xff;
00937        wbuf[1] = (gid & 0xff);
00938 
00939        wbuf[2] = (ch >> 8) & 0xff;
00940        wbuf[3] =  ch & 0xff;
00941 
00942        CMap_add_bfchar(cmap, wbuf, 2, wbuf+2, 2);
00943 
00944        /* Avoid duplicate entry
00945         * There are problem when two Unicode code is mapped to
00946         * single glyph...
00947         */
00948        used_glyphs_copy[gid/8] &= ~(1 << (7 - (gid % 8)));
00949        count++;
00950       }
00951     }
00952   }
00953 
00954   count += handle_subst_glyphs(cmap, cmap_add, used_glyphs_copy);
00955 
00956   if (count < 1)
00957     stream = NULL;
00958   else {
00959     stream = CMap_create_stream(cmap, 0);
00960   }
00961   CMap_release(cmap);
00962 
00963   return stream;
00964 }
00965 
00966 
00967 static pdf_obj *
00968 create_ToUnicode_cmap12 (struct cmap12 *map,
00969                       const char *cmap_name, CMap *cmap_add,
00970                       const char *used_glyphs)
00971 {
00972   pdf_obj  *stream = NULL;
00973   CMap     *cmap;
00974   ULONG     i, ch;
00975   USHORT    gid, count;
00976   char      used_glyphs_copy[8192];
00977 
00978   cmap = CMap_new();
00979   CMap_set_name (cmap, cmap_name);
00980   CMap_set_wmode(cmap, 0);
00981   CMap_set_type (cmap, CMAP_TYPE_TO_UNICODE);
00982   CMap_set_CIDSysInfo(cmap, &CSI_UNICODE);
00983   CMap_add_codespacerange(cmap, srange_min, srange_max, 2);
00984 
00985   memcpy(used_glyphs_copy, used_glyphs, 8192);
00986   for (count = 0, i = 0; i < map->nGroups; i++) {
00987     for (ch  = map->groups[i].startCharCode;
00988          ch <= map->groups[i].endCharCode; ch++) {
00989       unsigned char *p;
00990       int      len;
00991       long     d;
00992 
00993       p   = wbuf + 2;
00994       d   = ch - map->groups[i].startCharCode;
00995       gid = (USHORT) ((map->groups[i].startGlyphID + d) & 0xffff);
00996       if (is_used_char2(used_glyphs_copy, gid)) {
00997         count++;
00998         wbuf[0] = (gid >> 8) & 0xff;
00999         wbuf[1] = (gid & 0xff);
01000         len = UC_sput_UTF16BE((long)ch, &p, wbuf+WBUF_SIZE);
01001 
01002         used_glyphs_copy[gid/8] &= ~(1 << (7 - (gid % 8)));
01003         CMap_add_bfchar(cmap, wbuf, 2, wbuf+2, len);
01004       }
01005     }
01006   }
01007 
01008   count += handle_subst_glyphs(cmap, cmap_add, used_glyphs_copy);
01009 
01010   if (count < 1)
01011     stream = NULL;
01012   else {
01013     stream = CMap_create_stream(cmap, 0);
01014   }
01015   CMap_release(cmap);
01016 
01017   return stream;
01018 }
01019 
01020 pdf_obj *
01021 otf_create_ToUnicode_stream (const char *font_name,
01022                           int ttc_index, /* 0 for non-TTC */
01023                           const char *used_glyphs)
01024 {
01025   pdf_obj    *cmap_ref = NULL;
01026   long        res_id;
01027   pdf_obj    *cmap_obj = NULL;
01028   CMap       *cmap_add;
01029   int         cmap_add_id;
01030   tt_cmap    *ttcmap;
01031   char       *cmap_name;
01032   FILE       *fp;
01033   sfnt       *sfont;
01034   long        offset = 0;
01035 
01036 
01037   cmap_name = NEW(strlen(font_name)+strlen("-UTF16")+5, char);
01038   sprintf(cmap_name, "%s,%03d-UTF16", font_name, ttc_index);
01039 
01040   res_id = pdf_findresource("CMap", cmap_name);
01041   if (res_id >= 0) {
01042     RELEASE(cmap_name);
01043     cmap_ref = pdf_get_resource_reference(res_id);
01044     return cmap_ref;
01045   }
01046 
01047   if (verbose > VERBOSE_LEVEL_MIN) {
01048     MESG("\n");
01049     MESG("otf_cmap>> Creating ToUnicode CMap for \"%s\"...\n", font_name);
01050   }
01051 
01052   fp = DPXFOPEN(font_name, DPX_RES_TYPE_TTFONT);
01053   if (!fp) {
01054     fp = DPXFOPEN(font_name, DPX_RES_TYPE_OTFONT);
01055   }
01056 
01057   if (!fp) {
01058     RELEASE(cmap_name);
01059     return NULL;
01060   }
01061 
01062   sfont = sfnt_open(fp);
01063   if (!sfont) {
01064     ERROR("Could not open TrueType font file \"%s\"", font_name);
01065   }
01066 
01067   switch (sfont->type) {
01068   case SFNT_TYPE_TTC:
01069     offset = ttc_read_offset(sfont, ttc_index);
01070     if (offset == 0) {
01071       ERROR("Invalid TTC index");
01072     }
01073     break;
01074   default:
01075     offset = 0;
01076     break;
01077   }
01078 
01079   if (sfnt_read_table_directory(sfont, offset) < 0) {
01080     ERROR("Could not read TrueType table directory.");
01081   }
01082 
01083   cmap_add_id = CMap_cache_find(cmap_name);
01084   if (cmap_add_id < 0) {
01085     cmap_add = NULL;
01086   } else {
01087     cmap_add = CMap_cache_get(cmap_add_id);
01088   }
01089 
01090   CMap_set_silent(1); /* many warnings without this... */
01091   ttcmap = tt_cmap_read(sfont, 3, 10); /* Microsoft UCS4 */
01092   if (ttcmap &&
01093       ttcmap->format == 12) {
01094     WARN("Format 12 cmap table ... untested");
01095     cmap_obj = create_ToUnicode_cmap12(ttcmap->map,
01096                                    cmap_name, cmap_add, used_glyphs);
01097   } else {
01098     ttcmap = tt_cmap_read(sfont, 3, 1); /* Microsoft UCS2 */
01099     if (ttcmap &&
01100        ttcmap->format == 4) {
01101       cmap_obj = create_ToUnicode_cmap4(ttcmap->map,
01102                                    cmap_name, cmap_add, used_glyphs);
01103     } else {
01104       ttcmap = tt_cmap_read(sfont, 0, 3); /* Unicode 2.0 or later */
01105       if (ttcmap &&
01106          ttcmap->format == 4) {
01107         cmap_obj = create_ToUnicode_cmap4(ttcmap->map,
01108                                      cmap_name, cmap_add, used_glyphs);
01109       } else {
01110         ERROR("Unable to read OpenType/TrueType Unicode cmap table.");
01111       }
01112     }
01113   }
01114   tt_cmap_release(ttcmap);
01115   CMap_set_silent(0);
01116 
01117   if (cmap_obj) {
01118     res_id   = pdf_defineresource("CMap", cmap_name,
01119                               cmap_obj, PDF_RES_FLUSH_IMMEDIATE);
01120     cmap_ref = pdf_get_resource_reference(res_id);
01121   } else {
01122     cmap_ref = NULL;
01123   }
01124   RELEASE(cmap_name);
01125 
01126   sfnt_close(sfont);
01127   DPXFCLOSE(fp);
01128 
01129   return cmap_ref;
01130 }
01131 
01132 /* Must be smaller than (WBUF_SIZE-2)/8 */
01133 #define MAX_UNICODES 16
01134 
01135 struct gent
01136 {
01137   USHORT gid;
01138   long   ucv; /* assigned PUA unicode */
01139 
01140   int    num_unicodes;
01141   long   unicodes[MAX_UNICODES];
01142 };
01143 
01144 static void
01145 create_cmaps (CMap *cmap, CMap *tounicode,
01146              struct ht_table *unencoded, unsigned char *GIDToCIDMap)
01147 {
01148   struct ht_iter iter;
01149 
01150   ASSERT(cmap && unencoded);
01151 
01152   if (ht_set_iter(unencoded, &iter) < 0)
01153     return;
01154 
01155   CMap_set_silent(1); /* many warnings without this... */
01156 
01157   do {
01158     struct gent   *glyph;
01159     unsigned char *ucv;
01160     int            i, len;
01161     unsigned char  *p, *endptr;
01162     CID            cid;
01163 
01164     glyph = (struct gent *)   ht_iter_getval(&iter);
01165     ucv   = (unsigned char *) ht_iter_getkey(&iter, &len);
01166 
01167     if (GIDToCIDMap) {
01168       cid = ((GIDToCIDMap[2 * glyph->gid] << 8)|GIDToCIDMap[2 * glyph->gid + 1]);
01169       if (cid == 0)
01170        WARN("Glyph gid=%u does not have corresponding CID.", glyph->gid);
01171     } else {
01172       cid = glyph->gid;
01173     }
01174 
01175     CMap_add_cidchar(cmap, ucv, 4, cid);
01176 
01177     if (tounicode) {
01178       wbuf[0] = (cid >> 8) & 0xff;
01179       wbuf[1] = cid & 0xff;
01180       p       = wbuf + 2;
01181       endptr  = wbuf + WBUF_SIZE;
01182       len     = 0;
01183       for (i = 0; i < glyph->num_unicodes; i++) {
01184        len += UC_sput_UTF16BE(glyph->unicodes[i], &p, endptr);
01185       }
01186       CMap_add_bfchar(tounicode, wbuf, 2, wbuf + 2, len);
01187     }
01188   } while (ht_iter_next(&iter) >= 0);
01189 
01190   CMap_set_silent(0);
01191 
01192   ht_clear_iter(&iter);
01193 }
01194 
01195 static void
01196 add_glyph (struct ht_table *unencoded,
01197           USHORT gid, long ucv, int num_unicodes, long *unicodes)
01198 {
01199   struct gent *glyph;
01200   int i;
01201 
01202   ASSERT(unencoded);
01203 
01204   if (gid == 0 || num_unicodes < 1) {
01205     return;
01206   }
01207 
01208   wbuf[0] = (ucv >> 24) & 0xff;
01209   wbuf[1] = (ucv >> 16) & 0xff;
01210   wbuf[2] = (ucv >>  8) & 0xff;
01211   wbuf[3] =  ucv & 0xff;
01212 
01213   glyph = NEW(1, struct gent);
01214   glyph->gid = gid;
01215   glyph->num_unicodes = num_unicodes;
01216   for (i = 0;
01217        i < num_unicodes && i < MAX_UNICODES; i++) {
01218     glyph->unicodes[i] = unicodes[i];
01219   }
01220 
01221   ht_append_table(unencoded, wbuf, 4, glyph);
01222 }
01223 
01224 /* This seriously affects speed... */
01225 static struct gent *
01226 find_glyph (struct ht_table *unencoded, long ucv)
01227 {
01228   ASSERT(unencoded);
01229 
01230   wbuf[0] = (ucv >> 24) & 0xff;
01231   wbuf[1] = (ucv >> 16) & 0xff;
01232   wbuf[2] = (ucv >>  8) & 0xff;
01233   wbuf[3] =  ucv & 0xff;
01234 
01235   return (struct gent *) ht_lookup_table(unencoded, wbuf, 4);
01236 }
01237 
01238 static void
01239 handle_subst (pdf_obj *dst_obj, pdf_obj *src_obj, int flag,
01240              otl_gsub *gsub_list, tt_cmap *ttcmap,
01241              struct ht_table *unencoded)
01242 {
01243   pdf_obj *tmp;
01244   long     i, j, src_size, dst_size;
01245   long     src, dst;
01246   long     src_start, src_end, dst_start, dst_end;
01247 
01248   src_size = pdf_array_length(src_obj);
01249   dst_size = pdf_array_length(dst_obj);
01250 
01251   dst_start = dst_end = -1; dst = 0;
01252   src_start = src_end = -1; src = 0;
01253   for (i = 0, j = 0;
01254        i < src_size && j < dst_size; i++) {
01255     USHORT       gid;
01256     int          rv;
01257     struct gent *glyph;
01258 
01259     tmp = pdf_get_array(src_obj, i);
01260     if (PDF_OBJ_ARRAYTYPE(tmp)) {
01261       src_start = (long) pdf_number_value(pdf_get_array(tmp, 0));
01262       src_end   = (long) pdf_number_value(pdf_get_array(tmp, 1));
01263     } else {
01264       src_start = src_end = (long) pdf_number_value(tmp);
01265     }
01266     for (src = src_start; src <= src_end; src++) {
01267       glyph = find_glyph(unencoded, src);
01268       if (glyph)
01269        gid = glyph->gid;
01270       else {
01271        gid = tt_cmap_lookup(ttcmap, src);
01272       }
01273       dst++;
01274       if (dst > dst_end) {
01275        tmp = pdf_get_array(dst_obj, j++);
01276        if (PDF_OBJ_ARRAYTYPE(tmp)) {
01277          dst_start = (long) pdf_number_value(pdf_get_array(tmp, 0));
01278          dst_end   = (long) pdf_number_value(pdf_get_array(tmp, 1));
01279        } else {
01280          dst_start = dst_end = (long) pdf_number_value(tmp);
01281        }
01282        dst = dst_start;
01283       }
01284       if (gid == 0) {
01285        if (flag == 'r' || flag == 'p') {
01286          if (src < 0x10000) {
01287            WARN("Font does not have glyph for U+%04X.", src);
01288          } else {
01289            WARN("Font does not have glyph for U+%06X.", src);
01290          }
01291        }
01292        if (flag == 'r') {
01293          ERROR("Missing glyph found...");
01294        }
01295        continue;
01296       }
01297       rv = otl_gsub_apply(gsub_list, &gid);
01298       if (rv < 0) {
01299        if (flag == 'p' || flag == 'r') {
01300          if (src < 0x10000) {
01301            WARN("No substituted glyph for U+%04X.", src);
01302          } else {
01303            WARN("No substituted glyph for U+%06X.", src);
01304          }
01305        }
01306        if (flag == 'r') {
01307          ERROR("Missing glyph found...");
01308        }
01309        continue;
01310       }
01311 
01312       if (glyph) {
01313        glyph->gid = gid;
01314       } else {
01315        add_glyph(unencoded, gid, dst, 1, &src);
01316       }
01317 
01318       if (verbose > VERBOSE_LEVEL_MIN) {
01319        if (dst < 0x10000) {
01320          MESG("otf_cmap>> Substituted glyph gid=%u assigned to U+%04X\n",
01321               gid, dst);
01322        } else {
01323          MESG("otf_cmap>> Substituted glyph gid=%u assigned to U+%06X\n",
01324               gid, dst);
01325        }
01326       }
01327 
01328     }
01329   }
01330 
01331   if (dst < dst_end || src < src_end ||
01332       i < src_size  || j < dst_size) {
01333     WARN("Number of glyphs in left-side and right-side not equal...");
01334     WARN("Please check .otl file...");
01335   }
01336 }
01337 
01338 static void
01339 handle_assign (pdf_obj *dst, pdf_obj *src, int flag,
01340               otl_gsub *gsub_list, tt_cmap *ttcmap,
01341               struct ht_table *unencoded)
01342 {
01343   long     unicodes[MAX_UNICODES], ucv;
01344   int      i, n_unicodes, rv;
01345   USHORT   gid_in[MAX_UNICODES], lig;
01346 
01347   n_unicodes = pdf_array_length(src); /* FIXME */
01348   ucv = (long) pdf_number_value(pdf_get_array(dst, 0)); /* FIXME */
01349   if (!UC_is_valid(ucv)) {
01350     if (flag == 'r' || flag == 'p') {
01351       if (ucv < 0x10000) {
01352        WARN("Invalid Unicode in: %04X", ucv);
01353       } else {
01354        WARN("Invalid Unicode in: %06X", ucv);
01355       }
01356     }
01357     if (flag == 'r') {
01358       ERROR("Invalid Unicode code specified.", ucv);
01359     }
01360     return;
01361   }
01362 
01363   if (verbose > VERBOSE_LEVEL_MIN) {
01364     MESG("otf_cmap>> Ligature component:");
01365   }
01366 
01367   for (i = 0; i < n_unicodes; i++) {
01368     unicodes[i] =
01369       (long) pdf_number_value(pdf_get_array(src, i));
01370     gid_in[i] = tt_cmap_lookup(ttcmap, unicodes[i]);
01371 
01372     if (verbose > VERBOSE_LEVEL_MIN) {
01373       if (unicodes[i] < 0x10000) {
01374        MESG(" U+%04X (gid=%u)", unicodes[i], gid_in[i]);
01375       } else {
01376        MESG(" U+%06X (gid=%u)", unicodes[i], gid_in[i]);
01377       }
01378     }
01379 
01380     if (gid_in[i] == 0) {
01381       if (flag == 'r' || flag == 'p') {
01382        if (unicodes[i] < 0x10000) {
01383          WARN("Unicode char U+%04X not exist in font...", unicodes[i]);
01384        } else {
01385          WARN("Unicode char U+%06X not exist in font...", unicodes[i]);
01386        }
01387       }
01388       if (flag == 'r') {
01389        ERROR("Missing glyph found...");
01390       }
01391       return;
01392     }
01393 
01394   }
01395  
01396   if (verbose > VERBOSE_LEVEL_MIN) {
01397     MESG("\n");
01398   }
01399 
01400   rv = otl_gsub_apply_lig(gsub_list,
01401                        gid_in, n_unicodes, &lig);
01402   if (rv < 0) {
01403     if (flag == 'p')
01404       WARN("No ligature found...");
01405     else if (flag == 'r')
01406       ERROR("No ligature found...");
01407     return;
01408   }
01409 
01410   add_glyph(unencoded, lig, ucv, n_unicodes, unicodes);
01411 
01412   if (verbose > VERBOSE_LEVEL_MIN) {
01413     if (ucv < 0x10000) {
01414       MESG("otf_cmap>> Ligature glyph gid=%u assigned to U+%04X\n", lig, ucv);
01415     } else {
01416       MESG("otf_cmap>> Ligature glyph gid=%u assigned to U+%06X\n", lig, ucv);
01417     }
01418   }
01419 
01420   return;
01421 }
01422 
01423 static int
01424 load_base_CMap (const char *cmap_name, int wmode,
01425               CIDSysInfo *csi, unsigned char *GIDToCIDMap,
01426               tt_cmap *ttcmap)
01427 {
01428   int cmap_id;
01429 
01430   cmap_id = CMap_cache_find(cmap_name);
01431   if (cmap_id < 0) {
01432     CMap  *cmap;
01433 
01434     cmap = CMap_new();
01435     CMap_set_name (cmap, cmap_name);
01436     CMap_set_type (cmap, CMAP_TYPE_CODE_TO_CID);
01437     CMap_set_wmode(cmap, wmode);
01438     CMap_add_codespacerange(cmap, lrange_min, lrange_max, 4);
01439 
01440     if (csi) { /* CID */
01441       CMap_set_CIDSysInfo(cmap, csi);
01442     } else {
01443       CMap_set_CIDSysInfo(cmap, &CSI_IDENTITY);
01444     }
01445 
01446     if (ttcmap->format == 12) {
01447       load_cmap12(ttcmap->map, GIDToCIDMap, cmap);
01448     } else if (ttcmap->format == 4) {
01449       load_cmap4(ttcmap->map, GIDToCIDMap, cmap);
01450     }
01451 
01452     cmap_id = CMap_cache_add(cmap);
01453   }
01454 
01455   return cmap_id;
01456 }
01457 
01458 static void
01459 load_gsub (pdf_obj *conf, otl_gsub *gsub_list, sfnt *sfont)
01460 {
01461   pdf_obj  *rule;
01462   char     *script, *language, *feature;
01463   long      i, size;
01464 
01465   rule = otl_conf_get_rule(conf);
01466   if (!rule)
01467     return;
01468 
01469   script   = otl_conf_get_script  (conf);
01470   language = otl_conf_get_language(conf);
01471 
01472   size     = pdf_array_length(rule);
01473   for (i = 0; i < size; i += 2) {
01474     pdf_obj   *tmp, *commands;
01475     int        flag;
01476     long       j, num_comms;
01477 
01478     tmp  = pdf_get_array(rule, i);
01479     flag = (int) pdf_number_value(tmp);
01480 
01481     commands  = pdf_get_array(rule, i+1);
01482     num_comms = pdf_array_length(commands);
01483 
01484     /* (assign|substitute) tag dst src */
01485     for (j = 0 ; j < num_comms; j += 4) {
01486       tmp = pdf_get_array(commands, 1);
01487       if (PDF_OBJ_STRINGTYPE(tmp)) {
01488        feature = pdf_string_value(tmp);
01489        if (otl_gsub_add_feat(gsub_list,
01490                            script, language, feature, sfont) < 0) {
01491          if (flag == 'p')
01492            WARN("No OTL feature matches \"%s.%s.%s\" found.",
01493                script, language, feature);
01494          else if (flag == 'r')
01495            ERROR("No OTL feature matches \"%s.%s.%s\" found.",
01496                 script, language, feature);
01497        }
01498       }
01499 
01500     }
01501   }
01502 
01503 }
01504 
01505 static void
01506 handle_gsub (pdf_obj *conf,
01507             tt_cmap *ttcmap, otl_gsub *gsub_list,
01508             struct ht_table *unencoded)
01509 {
01510   pdf_obj *rule;
01511   char    *script, *language, *feature;
01512   long     i, size;
01513 
01514   if (!conf)
01515     return;
01516 
01517   rule = otl_conf_get_rule(conf);
01518   if (!rule) {
01519     return;
01520   }
01521 
01522   if (!PDF_OBJ_ARRAYTYPE(rule)) {
01523     WARN("Not arraytype?");
01524     return;
01525   }
01526   script   = otl_conf_get_script  (conf);
01527   language = otl_conf_get_language(conf);
01528 
01529   size = pdf_array_length(rule);
01530   for (i = 0; i < size; i += 2) {
01531     pdf_obj  *tmp, *commands;
01532     long      j, num_comms;
01533     int       flag;
01534 
01535     tmp  = pdf_get_array(rule, i);
01536     flag = (int) pdf_number_value(tmp);
01537 
01538     commands  = pdf_get_array   (rule, i+1);
01539     num_comms = pdf_array_length(commands);
01540 
01541     for (j = 0; j < num_comms; j += 4) {
01542       pdf_obj *operator;
01543       pdf_obj *src, *dst, *feat;
01544       int      rv;
01545 
01546       /* (assing|substitute) tag dst src */
01547       operator = pdf_get_array(commands, j);
01548 
01549       feat     = pdf_get_array(commands, j+1);
01550       if (PDF_OBJ_STRINGTYPE(feat))
01551        feature = pdf_string_value(feat);
01552       else
01553        feature = NULL;
01554 
01555       dst  = pdf_get_array(commands, j+2);
01556       src  = pdf_get_array(commands, j+3);
01557 
01558       rv = otl_gsub_select(gsub_list, script, language, feature);
01559       if (rv < 0) {
01560        if (flag == 'p') {
01561          WARN("No GSUB featre %s.%s.%s loaded...",
01562               script, language, feature);
01563        } else if (flag == 'r') {
01564          ERROR("No GSUB featre %s.%s.%s loaded...",
01565               script, language, feature);
01566        }
01567       } else {
01568 
01569        if (verbose > VERBOSE_LEVEL_MIN) {
01570          MESG("otf_cmap>> %s:\n", pdf_name_value(operator));
01571        }
01572 
01573        if (!strcmp(pdf_name_value(operator), "assign")) {
01574          handle_assign(dst, src, flag,
01575                      gsub_list, ttcmap, unencoded);
01576        } else if (!strcmp(pdf_name_value(operator), "substitute")) {
01577          handle_subst(dst, src, flag,
01578                      gsub_list, ttcmap, unencoded);
01579        }
01580       }
01581 
01582     }
01583 
01584   }
01585 
01586 }
01587 
01588 static void CDECL
01589 hval_free (void *hval)
01590 {
01591   RELEASE(hval);
01592 }
01593 
01594 int
01595 otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC font */
01596                      const char *otl_tags, int wmode)
01597 {
01598   int    cmap_id = -1;
01599   int    tounicode_id = -1, is_cidfont = 0;
01600   sfnt  *sfont;
01601   unsigned long   offset = 0;
01602   char  *base_name = NULL, *cmap_name = NULL;
01603   char  *tounicode_name = NULL;
01604   FILE  *fp;
01605   otl_gsub      *gsub_list = NULL;
01606   tt_cmap       *ttcmap;
01607   CMap          *cmap, *base, *tounicode = NULL;
01608   CIDSysInfo     csi = {NULL, NULL, 0};
01609   unsigned char *GIDToCIDMap = NULL;
01610 
01611   if (!map_name)
01612     return -1;
01613 
01614   if (ttc_index > 999 || ttc_index < 0) {
01615     return -1; /* Sorry for this... */
01616   }
01617 
01618   fp = DPXFOPEN(map_name, DPX_RES_TYPE_TTFONT);
01619   if (!fp) {
01620     fp = DPXFOPEN(map_name, DPX_RES_TYPE_OTFONT);
01621   }
01622   if (!fp) {
01623     fp = DPXFOPEN(map_name, DPX_RES_TYPE_DFONT);
01624     if (!fp) return -1;
01625     sfont = dfont_open(fp, ttc_index);
01626   } else {
01627     sfont = sfnt_open(fp);
01628   }
01629 
01630   if (!sfont) {
01631     ERROR("Could not open OpenType/TrueType/dfont font file \"%s\"", map_name);
01632   }
01633   switch (sfont->type) {
01634   case SFNT_TYPE_TTC:
01635     offset = ttc_read_offset(sfont, ttc_index);
01636     if (offset == 0) {
01637       ERROR("Invalid TTC index");
01638     }
01639     break;
01640   case SFNT_TYPE_TRUETYPE:
01641   case SFNT_TYPE_POSTSCRIPT:
01642     offset = 0;
01643     break;
01644   case SFNT_TYPE_DFONT:
01645     offset = sfont->offset;
01646     break;
01647   default:
01648     ERROR("Not a OpenType/TrueType/TTC font?: %s", map_name);
01649     break;
01650   }
01651 
01652   if (sfnt_read_table_directory(sfont, offset) < 0)
01653     ERROR("Could not read OpenType/TrueType table directory.");
01654 
01655   base_name = NEW(strlen(map_name)+strlen("-UCS4-H")+5, char);
01656   if (wmode)
01657     sprintf(base_name, "%s,%03d-UCS4-V", map_name, ttc_index);
01658   else {
01659     sprintf(base_name, "%s,%03d-UCS4-H", map_name, ttc_index);
01660   }
01661 
01662   if (otl_tags) {
01663     cmap_name = NEW(strlen(map_name)+strlen(otl_tags)+strlen("-UCS4-H")+6, char);
01664     if (wmode)
01665       sprintf(cmap_name, "%s,%03d,%s-UCS4-V", map_name, ttc_index, otl_tags);
01666     else
01667       sprintf(cmap_name, "%s,%03d,%s-UCS4-H", map_name, ttc_index, otl_tags);
01668   } else {
01669     cmap_name = NEW(strlen(base_name)+1, char);
01670     strcpy(cmap_name, base_name);
01671   }
01672 
01673   if (sfont->type == SFNT_TYPE_POSTSCRIPT) {
01674     is_cidfont = handle_CIDFont(sfont, &GIDToCIDMap, &csi);
01675   } else {
01676     is_cidfont = 0;
01677   }
01678 
01679   if (is_cidfont) {
01680     tounicode_name = NULL;
01681   } else {
01682     tounicode_name = NEW(strlen(map_name)+strlen("-UTF16")+5, char);
01683     sprintf(tounicode_name, "%s,%03d-UTF16", map_name, ttc_index);
01684   }
01685 
01686   if (verbose > VERBOSE_LEVEL_MIN) {
01687     MESG("\n");
01688     MESG("otf_cmap>> Unicode charmap for font=\"%s\" layout=\"%s\"\n",
01689         map_name, (otl_tags ? otl_tags : "none"));
01690   }
01691 
01692   cmap_id = CMap_cache_find(cmap_name);
01693   if (cmap_id >= 0) {
01694     RELEASE(cmap_name);
01695     RELEASE(base_name);
01696     if (GIDToCIDMap)
01697       RELEASE(GIDToCIDMap);
01698     if (tounicode_name)
01699       RELEASE(tounicode_name);
01700 
01701     sfnt_close(sfont);
01702     DPXFCLOSE(fp);
01703 
01704     if (verbose > VERBOSE_LEVEL_MIN)
01705       MESG("otf_cmap>> Found at cmap_id=%d.\n", cmap_id);
01706 
01707     return cmap_id;
01708   }
01709 
01710   ttcmap = tt_cmap_read(sfont, 3, 10); /* Microsoft UCS4 */
01711   if (!ttcmap) {
01712     ttcmap = tt_cmap_read(sfont, 3, 1); /* Microsoft UCS2 */
01713     if (!ttcmap) {
01714       ttcmap = tt_cmap_read(sfont, 0, 3); /* Unicode 2.0 or later */
01715       if (!ttcmap) {
01716         ERROR("Unable to read OpenType/TrueType Unicode cmap table.");
01717       }
01718     }
01719   }
01720   cmap_id = load_base_CMap(base_name, wmode,
01721                         (is_cidfont ? &csi : NULL),
01722                         GIDToCIDMap, ttcmap);
01723   if (cmap_id < 0)
01724     ERROR("Failed to read OpenType/TrueType cmap table.");
01725 
01726   if (!otl_tags) {
01727     RELEASE(cmap_name);
01728     RELEASE(base_name);
01729     if (GIDToCIDMap)
01730       RELEASE(GIDToCIDMap);
01731     if (tounicode_name)
01732       RELEASE(tounicode_name);
01733     if (is_cidfont) {
01734       if (csi.registry)
01735        RELEASE(csi.registry);
01736       if (csi.ordering)
01737        RELEASE(csi.ordering);
01738     }
01739     tt_cmap_release(ttcmap);
01740     sfnt_close(sfont);
01741     DPXFCLOSE(fp);
01742 
01743     return cmap_id;
01744   }
01745 
01746   base = CMap_cache_get(cmap_id);
01747 
01748   cmap = CMap_new();
01749   CMap_set_name (cmap, cmap_name);
01750   CMap_set_type (cmap, CMAP_TYPE_CODE_TO_CID);
01751   CMap_set_wmode(cmap, wmode);
01752   /* CMap_add_codespacerange(cmap, lrange_min, lrange_max, 4); */
01753   CMap_set_usecmap(cmap, base);
01754   CMap_add_cidchar(cmap, lrange_max, 4, 0); /* FIXME */
01755 
01756   if (is_cidfont) {
01757     CMap_set_CIDSysInfo(cmap, &csi);
01758     if (csi.registry)
01759       RELEASE(csi.registry);
01760     if (csi.ordering)
01761       RELEASE(csi.ordering);
01762   } else {
01763     CMap_set_CIDSysInfo(cmap, &CSI_IDENTITY);
01764   }
01765 
01766   gsub_list = otl_gsub_new();
01767 
01768   {
01769     struct ht_table unencoded;
01770     char    *conf_name, *opt_tag;
01771     pdf_obj *conf, *opt_conf;
01772 
01773     conf_name = NEW(strlen(otl_tags)+1, char);
01774     memset (conf_name, 0, strlen(otl_tags)+1);
01775     opt_tag  = strchr(otl_tags, ':');
01776     if (opt_tag) {
01777       opt_tag++;
01778       strncpy(conf_name, otl_tags,
01779              strlen(otl_tags) - strlen(opt_tag) - 1);
01780     } else {
01781       strcpy(conf_name, otl_tags);
01782     }
01783 
01784     if (verbose > VERBOSE_LEVEL_MIN) {
01785       MESG("otf_cmap>> Read layout config. \"%s\"\n", conf_name);
01786     }
01787 
01788     conf = otl_find_conf(conf_name);
01789     if (!conf)
01790       ERROR("Layout file \"%s\" not found...", conf_name);
01791 
01792     load_gsub(conf, gsub_list, sfont);
01793     if (opt_tag) {
01794       if (verbose > VERBOSE_LEVEL_MIN) {
01795        MESG("otf_cmap>> Layout option \"%s\" enabled\n", opt_tag);
01796       }
01797       opt_conf = otl_conf_find_opt(conf, opt_tag);
01798       if (!opt_conf)
01799        ERROR("There are no option \"%s\" in \"%s\".",
01800              opt_tag, conf_name);
01801       load_gsub(opt_conf, gsub_list, sfont);
01802     }
01803 
01804     ht_init_table(&unencoded, hval_free);
01805 
01806     handle_gsub(conf, ttcmap, gsub_list, &unencoded);
01807     if (opt_tag) {
01808       opt_conf = otl_conf_find_opt(conf, opt_tag);
01809       if (!opt_conf)
01810        ERROR("There are no option \"%s\" in \"%s\".",
01811              opt_tag, conf_name);
01812       handle_gsub(opt_conf, ttcmap, gsub_list, &unencoded);
01813     }
01814     if (is_cidfont) {
01815       tounicode_id = -1;
01816       tounicode    = NULL;
01817     } else {
01818       tounicode_id = CMap_cache_find(tounicode_name);
01819       if (tounicode_id >= 0)
01820        tounicode  = CMap_cache_get(tounicode_id);
01821       else {
01822        tounicode = CMap_new();
01823        CMap_set_name (tounicode, tounicode_name);
01824        CMap_set_type (tounicode, CMAP_TYPE_TO_UNICODE);
01825        CMap_set_wmode(tounicode, 0);
01826        CMap_add_codespacerange(tounicode, srange_min, srange_max, 2);
01827        CMap_set_CIDSysInfo(tounicode, &CSI_UNICODE);
01828        /* FIXME */
01829        CMap_add_bfchar(tounicode, srange_min, 2, srange_max, 2);
01830       }
01831     }
01832     create_cmaps(cmap, tounicode, &unencoded, GIDToCIDMap);
01833 
01834     ht_clear_table(&unencoded);
01835     RELEASE(conf_name);
01836   }
01837 
01838   cmap_id = CMap_cache_add(cmap);
01839   if (!is_cidfont && tounicode_id < 0) /* New */
01840     CMap_cache_add(tounicode);
01841 
01842   tt_cmap_release(ttcmap);
01843   if (gsub_list)
01844     otl_gsub_release(gsub_list);
01845 
01846   if (verbose > VERBOSE_LEVEL_MIN) {
01847     MESG("otf_cmap>> Overwrite CMap \"%s\" by \"%s\" with usecmap\n",
01848         base_name, cmap_name);
01849   }
01850 
01851   if (GIDToCIDMap)
01852     RELEASE(GIDToCIDMap);
01853   if (base_name)
01854     RELEASE(base_name);
01855   if (cmap_name)
01856     RELEASE(cmap_name);
01857   if (tounicode_name)
01858     RELEASE(tounicode_name);
01859 
01860   sfnt_close(sfont);
01861   DPXFCLOSE(fp);
01862 
01863   return cmap_id;
01864 }