Back to index

texmacs  1.0.7.15
type0.c
Go to the documentation of this file.
00001 /*  $Header: /home/cvsroot/dvipdfmx/src/type0.c,v 1.24 2008/11/30 21:12:27 matthias 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  * Type0 font support:
00025  * 
00026  * TODO:
00027  *
00028  *  Composite font (multiple descendants) - not supported in PDF
00029  */
00030 
00031 #if HAVE_CONFIG_H
00032 #include "config.h"
00033 #endif
00034 
00035 #include <string.h>
00036 
00037 #include "system.h"
00038 #include "mem.h"
00039 #include "error.h"
00040 #include "dpxfile.h"
00041 
00042 #include "pdfobj.h"
00043 #include "fontmap.h"
00044 
00045 #include "cmap.h"
00046 #include "cid.h"
00047 
00048 #include "type0.h"
00049 
00050 
00051 #define TYPE0FONT_DEBUG_STR "Type0"
00052 #define TYPE0FONT_DEBUG     3
00053 
00054 static int __verbose = 0;
00055 
00056 static pdf_obj *pdf_read_ToUnicode_file (const char *cmap_name);
00057 
00058 void
00059 Type0Font_set_verbose(void)
00060 {
00061   __verbose++;
00062 }
00063 
00064 /*
00065  * used_chars:
00066  *
00067  *  Single bit is used for each CIDs since used_chars can be reused as a
00068  *  stream content of CIDSet by doing so. See, cid.h for add_to_used() and
00069  *  is_used().
00070  */
00071 
00072 static char *
00073 new_used_chars2(void)
00074 {
00075   char *used_chars;
00076 
00077   used_chars = NEW(8192, char);
00078   memset(used_chars, 0, 8192);
00079 
00080   return used_chars;
00081 }
00082 
00083 #define FLAG_NONE              0
00084 #define FLAG_USED_CHARS_SHARED (1 << 0)
00085 
00086 struct Type0Font {
00087   char    *fontname;   /* BaseFont */
00088   char    *encoding;   /* "Identity-H" or "Identity-V" (not ID) */
00089   char    *used_chars; /* Used chars (CIDs) */
00090 
00091   /*
00092    * Type0 only
00093    */
00094   CIDFont *descendant; /* Only single descendant is allowed. */
00095   int      flags;
00096   int      wmode;
00097 
00098   /*
00099    * PDF Font Resource
00100    */
00101   pdf_obj *indirect;
00102   pdf_obj *fontdict;
00103   pdf_obj *descriptor; /* MUST BE NULL */
00104 };
00105 
00106 static void
00107 Type0Font_init_font_struct (Type0Font *font)
00108 {
00109   ASSERT(font);
00110 
00111   font->fontname   = NULL;
00112   font->fontdict   = NULL;
00113   font->indirect   = NULL;
00114   font->descriptor = NULL;
00115   font->encoding   = NULL;
00116   font->used_chars = NULL;
00117   font->descendant = NULL;
00118   font->wmode      = -1;
00119   font->flags      = FLAG_NONE;
00120 
00121   return;
00122 }
00123 
00124 static void
00125 Type0Font_clean (Type0Font *font)
00126 {
00127   if (font) {
00128     if (font->fontdict)
00129       ERROR("%s: Object not flushed.", TYPE0FONT_DEBUG_STR);
00130     if (font->indirect)
00131       ERROR("%s: Object not flushed.", TYPE0FONT_DEBUG_STR);
00132     if (font->descriptor)
00133       ERROR("%s: FontDescriptor unexpected for Type0 font.", TYPE0FONT_DEBUG_STR);
00134     if (!(font->flags & FLAG_USED_CHARS_SHARED) && font->used_chars)
00135       RELEASE(font->used_chars);
00136     if (font->encoding)
00137       RELEASE(font->encoding);
00138     if (font->fontname)
00139       RELEASE(font->fontname);
00140     font->fontdict   = NULL;
00141     font->indirect   = NULL;
00142     font->descriptor = NULL;
00143     font->used_chars = NULL;
00144     font->encoding   = NULL;
00145     font->fontname   = NULL;
00146   }
00147 }
00148 
00149 /* PLEASE FIX THIS */
00150 #include "tt_cmap.h"
00151 
00152 static void
00153 add_ToUnicode (Type0Font *font)
00154 {
00155   pdf_obj    *tounicode;
00156   CIDFont    *cidfont;
00157   CIDSysInfo *csi;
00158   char       *cmap_name, *fontname;
00159 
00160   /*
00161    * ToUnicode CMap:
00162    *
00163    *  ToUnicode CMaps are usually not required for standard character
00164    *  collections such as Adobe-Japan1. Identity-H is used for UCS
00165    *  ordering CID-keyed fonts. External resource must be loaded for
00166    *  others.
00167    */
00168 
00169   cidfont = font->descendant;
00170   if (!cidfont) {
00171     ERROR("%s: No descendant CID-keyed font.", TYPE0FONT_DEBUG_STR);
00172     return;
00173   }
00174 
00175   if (CIDFont_is_ACCFont(cidfont)) {
00176     /* No need to embed ToUnicode */
00177     return;
00178   } else if (CIDFont_is_UCSFont(cidfont)) {
00179     /*
00180      * Old version of dvipdfmx mistakenly used Adobe-Identity as Unicode.
00181      */
00182     tounicode = pdf_read_ToUnicode_file("Adobe-Identity-UCS2");
00183     if (!tounicode) { /* This should work */
00184       tounicode = pdf_new_name("Identity-H");
00185     }
00186     pdf_add_dict(font->fontdict, pdf_new_name("ToUnicode"), tounicode);
00187     return;
00188   }
00189 
00190   tounicode = NULL;
00191   csi       = CIDFont_get_CIDSysInfo(cidfont);
00192   fontname  = CIDFont_get_fontname(cidfont);
00193   if (CIDFont_get_embedding(cidfont)) {
00194     fontname += 7; /* FIXME */
00195   }
00196 
00197   if (!strcmp(csi->registry, "Adobe")    &&
00198       !strcmp(csi->ordering, "Identity")) {
00199     switch (CIDFont_get_subtype(cidfont)) {
00200     case CIDFONT_TYPE2:
00201       /* PLEASE FIX THIS */
00202       tounicode = otf_create_ToUnicode_stream(CIDFont_get_ident(cidfont),
00203                                          CIDFont_get_opt_index(cidfont),
00204                                          Type0Font_get_usedchars(font));
00205       break;
00206     default:
00207       if (CIDFont_get_flag(cidfont, CIDFONT_FLAG_TYPE1C)) { /* FIXME */
00208        tounicode = otf_create_ToUnicode_stream(CIDFont_get_ident(cidfont),
00209                                           CIDFont_get_opt_index(cidfont),
00210                                           Type0Font_get_usedchars(font));
00211       } else if (CIDFont_get_flag(cidfont, CIDFONT_FLAG_TYPE1)) { /* FIXME */
00212        /* Font loader will create ToUnicode and set. */
00213        return;
00214       } else {
00215        cmap_name = NEW(strlen(fontname) + 7, char);
00216        sprintf(cmap_name, "%s-UTF16", fontname);
00217        tounicode = pdf_read_ToUnicode_file(cmap_name);
00218        if (!tounicode) {
00219          sprintf(cmap_name, "%s-UCS2", fontname);
00220          tounicode = pdf_read_ToUnicode_file(cmap_name);
00221        }
00222        RELEASE(cmap_name);
00223       }
00224       break;
00225     }
00226   } else {
00227     cmap_name = NEW(strlen(csi->registry)+strlen(csi->ordering)+8, char);
00228     sprintf(cmap_name, "%s-%s-UTF16", csi->registry, csi->ordering);
00229     tounicode = pdf_read_ToUnicode_file(cmap_name);
00230     if (!tounicode) {
00231       sprintf(cmap_name, "%s-%s-UCS2", csi->registry, csi->ordering);
00232       tounicode = pdf_read_ToUnicode_file(cmap_name);
00233     }
00234     RELEASE(cmap_name);
00235   }
00236 
00237   if (tounicode) {
00238     pdf_add_dict(font->fontdict,
00239                pdf_new_name("ToUnicode"), tounicode);
00240   } else {
00241     WARN("Failed to load ToUnicode CMap for font \"%s\"", fontname);
00242   }
00243 
00244   return;
00245 }
00246 
00247 void
00248 Type0Font_set_ToUnicode (Type0Font *font, pdf_obj *cmap_ref)
00249 {
00250   ASSERT(font);
00251 
00252   pdf_add_dict(font->fontdict,
00253               pdf_new_name("ToUnicode"), cmap_ref);
00254 }
00255 
00256 static void
00257 Type0Font_dofont (Type0Font *font)
00258 {
00259   if (!font || !font->indirect)
00260     return;
00261 
00262   if (!pdf_lookup_dict(font->fontdict, "ToUnicode")) { /* FIXME */
00263     add_ToUnicode(font);
00264   }
00265 }
00266 
00267 static void
00268 Type0Font_flush (Type0Font *font)
00269 {
00270   if (font) {
00271     if (font->fontdict)
00272       pdf_release_obj(font->fontdict);
00273     font->fontdict = NULL;
00274     if (font->indirect)
00275       pdf_release_obj(font->indirect);
00276     font->indirect = NULL;
00277     if (font->descriptor)
00278       ERROR("%s: FontDescriptor unexpected for Type0 font.", TYPE0FONT_DEBUG_STR);
00279     font->descriptor = NULL;
00280   }
00281 }
00282 
00283 int
00284 Type0Font_get_wmode (Type0Font *font)
00285 {
00286   ASSERT(font);
00287 
00288   return font->wmode;
00289 }
00290 
00291 #if 0
00292 char *
00293 Type0Font_get_encoding (Type0Font *font)
00294 {
00295   ASSERT(font);
00296 
00297   return font->encoding;
00298 }
00299 #endif
00300 
00301 char *
00302 Type0Font_get_usedchars (Type0Font *font)
00303 {
00304   ASSERT(font);
00305 
00306   return font->used_chars;
00307 }
00308 
00309 pdf_obj *
00310 Type0Font_get_resource (Type0Font *font)
00311 {
00312   ASSERT(font);
00313 
00314   /*
00315    * This looks somewhat strange.
00316    */
00317   if (!font->indirect) {
00318     pdf_obj *array;
00319 
00320     array = pdf_new_array();
00321     pdf_add_array(array, CIDFont_get_resource(font->descendant));
00322     pdf_add_dict(font->fontdict, pdf_new_name("DescendantFonts"), array);
00323     font->indirect = pdf_ref_obj(font->fontdict);
00324   }
00325 
00326   return pdf_link_obj(font->indirect);
00327 }
00328 
00329 /******************************** CACHE ********************************/
00330 
00331 #define CHECK_ID(n) do {\
00332   if ((n) < 0 || (n) >= __cache.count)\
00333     ERROR("%s: Invalid ID %d", TYPE0FONT_DEBUG_STR, (n));\
00334 } while (0)
00335 
00336 #define CACHE_ALLOC_SIZE 16u
00337 
00338 static struct font_cache {
00339   int        count;
00340   int        capacity;
00341   Type0Font *fonts;
00342 } __cache = {
00343   0, 0, NULL
00344 };
00345 
00346 void
00347 Type0Font_cache_init (void)
00348 {
00349   if (__cache.fonts)
00350     ERROR("%s: Already initialized.", TYPE0FONT_DEBUG_STR);
00351   __cache.count    = 0;
00352   __cache.capacity = 0;
00353   __cache.fonts    = NULL;
00354 }
00355 
00356 Type0Font *
00357 Type0Font_cache_get (int id)
00358 {
00359   CHECK_ID(id);
00360 
00361   return &__cache.fonts[id];
00362 }
00363 
00364 int
00365 Type0Font_cache_find (const char *map_name, int cmap_id, fontmap_opt *fmap_opt)
00366 {
00367   int         font_id = -1;
00368   Type0Font  *font;
00369   CIDFont    *cidfont;
00370   CMap       *cmap;
00371   CIDSysInfo *csi;
00372   char       *fontname = NULL;
00373   int         cid_id = -1, parent_id = -1, wmode = 0;
00374   int         pdf_ver;
00375 
00376   pdf_ver = pdf_get_version();
00377   if (!map_name || cmap_id < 0 || pdf_ver < 2)
00378     return -1;
00379 
00380   /*
00381    * Encoding is Identity-H or Identity-V according as thier WMode value.
00382    * 
00383    * We do not use match against the map_name since fonts (TrueType) covers
00384    * characters across multiple character collection (eg, Adobe-Japan1 and
00385    * Adobe-Japan2) must be splited into multiple CID-keyed fonts.
00386    */
00387 
00388   cmap = CMap_cache_get(cmap_id);
00389   csi  = (CMap_is_Identity(cmap)) ? NULL : CMap_get_CIDSysInfo(cmap) ;
00390 
00391   cid_id = CIDFont_cache_find(map_name, csi, fmap_opt);
00392 
00393   if (cid_id < 0) 
00394     return -1;
00395 
00396   /*
00397    * The descendant CID-keyed font has already been registerd.
00398    * If CID-keyed font with ID = cid_id is new font, then create new parent
00399    * Type 0 font. Otherwise, there already exists parent Type 0 font and
00400    * then we find him and return his ID. We must check against their WMode.
00401    */
00402 
00403   cidfont = CIDFont_cache_get(cid_id);
00404   wmode   = CMap_get_wmode(cmap);
00405 
00406   /* Does CID-keyed font already have parent ? */
00407   parent_id = CIDFont_get_parent_id(cidfont, wmode);
00408   if (parent_id >= 0)
00409     return parent_id; /* If so, we don't need new one. */
00410 
00411   /*
00412    * CIDFont does not have parent or his parent's WMode does not matched with
00413    * wmode. Create new Type0 font.
00414    */
00415 
00416   if (__cache.count >= __cache.capacity) {
00417     __cache.capacity += CACHE_ALLOC_SIZE;
00418     __cache.fonts     = RENEW(__cache.fonts, __cache.capacity, struct Type0Font);
00419   }
00420   font_id =  __cache.count;
00421   font    = &__cache.fonts[font_id];
00422 
00423   Type0Font_init_font_struct(font);
00424 
00425   /*
00426    * All CJK double-byte characters are mapped so that resulting
00427    * character codes coincide with CIDs of given character collection.
00428    * So, the Encoding is always Identity-H for horizontal fonts or
00429    * Identity-V for vertical fonts.
00430    */
00431   if (wmode) {
00432     font->encoding = NEW(strlen("Identity-V")+1, char);
00433     strcpy(font->encoding, "Identity-V");
00434   } else {
00435     font->encoding = NEW(strlen("Identity-H")+1, char);
00436     strcpy(font->encoding, "Identity-H");
00437   }
00438   font->wmode = wmode;
00439 
00440   /*
00441    * Now we start font dictionary.
00442    */
00443   font->fontdict = pdf_new_dict();
00444   pdf_add_dict(font->fontdict, pdf_new_name ("Type"),    pdf_new_name ("Font"));
00445   pdf_add_dict(font->fontdict, pdf_new_name ("Subtype"), pdf_new_name ("Type0"));
00446 
00447   /*
00448    * Type0 font does not have FontDescriptor because it is not a simple font.
00449    * Instead, DescendantFonts appears here.
00450    *
00451    * Up to PDF version 1.5, Type0 font must have single descendant font which
00452    * is a CID-keyed font. Future PDF spec. will allow multiple desecendant
00453    * fonts.
00454    */
00455   font->descendant = cidfont;
00456   CIDFont_attach_parent(cidfont, font_id, wmode);
00457 
00458   /*
00459    * PostScript Font name:
00460    *
00461    *  Type0 font's fontname is usually descendant CID-keyed font's font name 
00462    *  appended by -ENCODING.
00463    */
00464   fontname = CIDFont_get_fontname(cidfont);
00465 
00466   if (__verbose) {
00467     if (CIDFont_get_embedding(cidfont) && strlen(fontname) > 7)
00468       MESG("(CID:%s)", fontname+7); /* skip XXXXXX+ */
00469     else
00470       MESG("(CID:%s)", fontname);
00471   }
00472 
00473   /*
00474    * The difference between CID-keyed font and TrueType font appears here.
00475    *
00476    * Glyph substitution for vertical writing is done in CMap mapping process
00477    * for CID-keyed fonts. But we must rely on OpenType layout table in the
00478    * case of TrueType fonts. So, we must use different used_chars for each
00479    * horizontal and vertical fonts in that case.
00480    *
00481    * In most PDF file, encoding name is not appended to fontname for Type0
00482    * fonts having CIDFontType 2 font as their descendant.
00483    */
00484 
00485   font->used_chars = NULL;
00486   font->flags      = FLAG_NONE;
00487 
00488   switch (CIDFont_get_subtype(cidfont)) {
00489   case CIDFONT_TYPE0:
00490     font->fontname = NEW(strlen(fontname)+strlen(font->encoding)+2, char);
00491     sprintf(font->fontname, "%s-%s", fontname, font->encoding);
00492     pdf_add_dict(font->fontdict,
00493                  pdf_new_name("BaseFont"), pdf_new_name(font->fontname));
00494     /*
00495      * Need used_chars to write W, W2.
00496      */
00497     if ((parent_id = CIDFont_get_parent_id(cidfont, wmode ? 0 : 1)) < 0)
00498       font->used_chars = new_used_chars2();
00499     else {
00500       /* Don't allocate new one. */
00501       font->used_chars = Type0Font_get_usedchars(Type0Font_cache_get(parent_id));
00502       font->flags     |= FLAG_USED_CHARS_SHARED;
00503     }
00504     break;
00505   case CIDFONT_TYPE2:
00506     /*
00507      * TrueType:
00508      *
00509      *  Use different used_chars for H and V.
00510      */
00511     pdf_add_dict(font->fontdict,
00512                  pdf_new_name("BaseFont"), pdf_new_name(fontname));
00513     font->used_chars = new_used_chars2();
00514     break;
00515   default:
00516     ERROR("Unrecognized CIDFont Type");
00517     break;
00518   }
00519 
00520   pdf_add_dict(font->fontdict,
00521                pdf_new_name("Encoding"), pdf_new_name(font->encoding));
00522 
00523   __cache.count++;
00524 
00525   return font_id;
00526 }
00527 
00528 void
00529 Type0Font_cache_close (void)
00530 {
00531   int   font_id;
00532 
00533   /*
00534    * This need to be fixed.
00535    *
00536    * CIDFont_cache_close() before Type0Font_release because of used_chars.
00537    * ToUnicode support want descendant CIDFont's CSI and fontname.
00538    */
00539   if (__cache.fonts) {
00540     for (font_id = 0; font_id < __cache.count; font_id++)
00541       Type0Font_dofont(&__cache.fonts[font_id]);
00542   }
00543   CIDFont_cache_close();
00544   if (__cache.fonts) {
00545     for (font_id = 0; font_id < __cache.count; font_id++) {
00546       Type0Font_flush(&__cache.fonts[font_id]);
00547       Type0Font_clean(&__cache.fonts[font_id]);
00548     }
00549     RELEASE(__cache.fonts);
00550   }
00551   __cache.fonts    = NULL;
00552   __cache.count    = 0;
00553   __cache.capacity = 0;
00554 }
00555 
00556 
00557 /************************************************************************/
00558 
00559 int
00560 pdf_font_findfont0 (const char *font_name, int cmap_id, fontmap_opt *fmap_opt)
00561 {
00562   return Type0Font_cache_find(font_name, cmap_id, fmap_opt);
00563 }
00564 
00565 /******************************** COMPAT ********************************/
00566 
00567 #ifndef WITHOUT_COMPAT
00568 
00569 #include "cmap_read.h"
00570 #include "cmap_write.h"
00571 #include "pdfresource.h"
00572 #include "pdfencoding.h"
00573 
00574 static pdf_obj *
00575 create_dummy_CMap (void)
00576 {
00577   pdf_obj *stream;
00578   char     buf[32];
00579   int      i, n;
00580 
00581 #define CMAP_PART0 "\
00582 %!PS-Adobe-3.0 Resource-CMap\n\
00583 %%DocumentNeededResources: ProcSet (CIDInit)\n\
00584 %%IncludeResource: ProcSet (CIDInit)\n\
00585 %%BeginResource: CMap (Adobe-Identity-UCS2)\n\
00586 %%Title: (Adobe-Identity-UCS2 Adobe UCS2 0)\n\
00587 %%Version: 1.0\n\
00588 %%Copyright:\n\
00589 %% ---\n\
00590 %%EndComments\n\n\
00591 "
00592 #define CMAP_PART1 "\
00593 /CIDInit /ProcSet findresource begin\n\
00594 \n\
00595 12 dict begin\n\nbegincmap\n\n\
00596 /CIDSystemInfo 3 dict dup begin\n\
00597   /Registry (Adobe) def\n\
00598   /Ordering (UCS2) def\n\
00599   /Supplement 0 def\n\
00600 end def\n\n\
00601 /CMapName /Adobe-Identity-UCS2 def\n\
00602 /CMapVersion 1.0 def\n\
00603 /CMapType 2 def\n\n\
00604 2 begincodespacerange\n\
00605 <0000> <FFFF>\n\
00606 endcodespacerange\n\
00607 "
00608 #define CMAP_PART3 "\
00609 endcmap\n\n\
00610 CMapName currentdict /CMap defineresource pop\n\n\
00611 end\nend\n\n\
00612 %%EndResource\n\
00613 %%EOF\n\
00614 "
00615 
00616   stream = pdf_new_stream(STREAM_COMPRESS);
00617   pdf_add_stream(stream, CMAP_PART0, strlen(CMAP_PART0));
00618   pdf_add_stream(stream, CMAP_PART1, strlen(CMAP_PART1));
00619   pdf_add_stream(stream, "\n100 beginbfrange\n", strlen("\n100 beginbfrange\n"));
00620   for (i = 0; i < 0x64; i++) {
00621     n = sprintf(buf,
00622                 "<%02X00> <%02XFF> <%02X00>\n", i, i, i);
00623     pdf_add_stream(stream, buf, n);
00624   }
00625   pdf_add_stream(stream, "endbfrange\n\n", strlen("endbfrange\n\n"));
00626 
00627   pdf_add_stream(stream, "\n100 beginbfrange\n", strlen("\n100 beginbfrange\n"));
00628   for (i = 0x64; i < 0xc8; i++) {
00629     n = sprintf(buf,
00630                 "<%02X00> <%02XFF> <%02X00>\n", i, i, i);
00631     pdf_add_stream(stream, buf, n);
00632   }
00633   pdf_add_stream(stream, "endbfrange\n\n", strlen("endbfrange\n\n"));
00634 
00635   pdf_add_stream(stream, "\n48 beginbfrange\n", strlen("\n48 beginbfrange\n"));
00636   for (i = 0xc8; i <= 0xd7; i++) {
00637     n = sprintf(buf,
00638                 "<%02X00> <%02XFF> <%02X00>\n", i, i, i);
00639     pdf_add_stream(stream, buf, n);
00640   }
00641   for (i = 0xe0; i <= 0xff; i++) {
00642     n = sprintf(buf,
00643                 "<%02X00> <%02XFF> <%02X00>\n", i, i, i);
00644     pdf_add_stream(stream, buf, n);
00645   }
00646   pdf_add_stream(stream, "endbfrange\n\n", strlen("endbfrange\n\n"));
00647 
00648   pdf_add_stream(stream, CMAP_PART3, strlen(CMAP_PART3));
00649 
00650   return  stream;
00651 }
00652 
00653 static pdf_obj *
00654 pdf_read_ToUnicode_file (const char *cmap_name)
00655 {
00656   pdf_obj *stream;
00657   long     res_id = -1;
00658 
00659   ASSERT(cmap_name);
00660 
00661   res_id = pdf_findresource("CMap", cmap_name);
00662   if (res_id < 0) {
00663     if (!strcmp(cmap_name, "Adobe-Identity-UCS2"))
00664       stream = create_dummy_CMap();
00665     else {
00666       stream = pdf_load_ToUnicode_stream(cmap_name);
00667     }
00668     if (stream) {
00669       res_id   = pdf_defineresource("CMap",
00670                                     cmap_name,
00671                                     stream, PDF_RES_FLUSH_IMMEDIATE);
00672     }
00673   }
00674 
00675   return  (res_id < 0 ? NULL : pdf_get_resource_reference(res_id));
00676 }
00677 #endif /* !WITHOUT_COMPAT */