Back to index

texmacs  1.0.7.15
Defines | Functions | Variables
cidtype2.c File Reference
#include "system.h"
#include "numbers.h"
#include "mem.h"
#include "error.h"
#include "dpxfile.h"
#include "pdfobj.h"
#include "pdffont.h"
#include "sfnt.h"
#include "tt_aux.h"
#include "tt_glyf.h"
#include "tt_cmap.h"
#include "tt_table.h"
#include "tt_gsub.h"
#include "cmap.h"
#include "type0.h"
#include "cid.h"
#include "cid_p.h"
#include "cidtype2.h"

Go to the source code of this file.

Defines

#define WIN_UCS_INDEX_MAX   1
#define KNOWN_ENCODINGS_MAX   9
#define PDFUNIT(v)   ((double) (ROUND(1000.0*(v)/(g->emsize), 1)))
#define FIX_CJK_UNIOCDE_SYMBOLS   1
#define NUM_CJK_SYMBOLS   (sizeof(CJK_Uni_symbols)/sizeof(CJK_Uni_symbols[0]))

Functions

void CIDFont_type2_set_verbose (void)
void CIDFont_type2_set_flags (long flags)
static void validate_name (char *fontname, int len)
static CMapfind_tocode_cmap (const char *reg, const char *ord, int select)
static void add_TTCIDHMetrics (pdf_obj *fontdict, struct tt_glyphs *g, char *used_chars, unsigned char *cidtogidmap, unsigned short last_cid)
static void add_TTCIDVMetrics (pdf_obj *fontdict, struct tt_glyphs *g, char *used_chars, unsigned char *cidtogidmap, unsigned short last_cid)
static unsigned short fix_CJK_symbols (unsigned short code)
static long cid_to_code (CMap *cmap, CID cid)
void CIDFont_type2_dofont (CIDFont *font)
int CIDFont_type2_open (CIDFont *font, const char *name, CIDSysInfo *cmap_csi, cid_opt *opt)
void CIDFont_type2_release (CIDFont *font)

Variables

static int verbose = 0
static int opt_flags = 0
struct {
const char * name
int must_exist
required_table []
struct {
unsigned short platform
unsigned short encoding
const char * pdfnames [5]
known_encodings []

Define Documentation

#define FIX_CJK_UNIOCDE_SYMBOLS   1

Definition at line 406 of file cidtype2.c.

#define KNOWN_ENCODINGS_MAX   9

Definition at line 162 of file cidtype2.c.

#define NUM_CJK_SYMBOLS   (sizeof(CJK_Uni_symbols)/sizeof(CJK_Uni_symbols[0]))
#define PDFUNIT (   v)    ((double) (ROUND(1000.0*(v)/(g->emsize), 1)))

Definition at line 227 of file cidtype2.c.

#define WIN_UCS_INDEX_MAX   1

Definition at line 161 of file cidtype2.c.


Function Documentation

static void add_TTCIDHMetrics ( pdf_obj fontdict,
struct tt_glyphs g,
char *  used_chars,
unsigned char *  cidtogidmap,
unsigned short  last_cid 
) [static]

Definition at line 230 of file cidtype2.c.

{
  long cid, start = 0, prev = 0;
  pdf_obj *w_array, *an_array = NULL;
  double   dw;
  int      empty = 1;

  w_array = pdf_new_array();
  if (g->dw != 0 && g->dw <= g->emsize) {
    dw = PDFUNIT(g->dw);
  } else {
    dw = PDFUNIT(g->gd[0].advw);
  }
  for (cid = 0; cid <= last_cid; cid++) {
    USHORT idx, gid;
    double width;

    if (!is_used_char2(used_chars, cid))
      continue;
    gid = (cidtogidmap) ? ((cidtogidmap[2*cid] << 8)|cidtogidmap[2*cid+1]) : cid;
    idx = tt_get_index(g, gid);
    if (cid != 0 && idx == 0)
      continue;
    width = PDFUNIT((g->gd)[idx].advw);
    if (width == dw) {
      if (an_array) {
       pdf_add_array(w_array, pdf_new_number(start));
       pdf_add_array(w_array, an_array);
       an_array = NULL;
       empty = 0;
      }
    } else {
      if (cid != prev + 1) {
       if (an_array) {
         pdf_add_array(w_array, pdf_new_number(start));
         pdf_add_array(w_array, an_array);
         an_array = NULL;
         empty = 0;
       }
      }
      if (an_array == NULL) {
       an_array = pdf_new_array();
       start = cid;
      }
      pdf_add_array(an_array, pdf_new_number(width));
      prev = cid;
    }
  }

  if (an_array) {
    pdf_add_array(w_array, pdf_new_number(start));
    pdf_add_array(w_array, an_array);
    empty = 0;
  }

  pdf_add_dict(fontdict,
              pdf_new_name("DW"),
              pdf_new_number(dw));
  if (!empty) {
    pdf_add_dict(fontdict,
               pdf_new_name("W"),
               pdf_ref_obj(w_array));
  }
  pdf_release_obj(w_array);

  return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void add_TTCIDVMetrics ( pdf_obj fontdict,
struct tt_glyphs g,
char *  used_chars,
unsigned char *  cidtogidmap,
unsigned short  last_cid 
) [static]

Definition at line 300 of file cidtype2.c.

{
  pdf_obj *w2_array, *an_array = NULL;
  long cid, prev, start;
  double defaultVertOriginY, defaultAdvanceHeight;
  int    empty = 1;

  defaultVertOriginY   = PDFUNIT(g->default_advh - g->default_tsb);
  defaultAdvanceHeight = PDFUNIT(g->default_advh);

  w2_array = pdf_new_array();
  start = prev = 0;
  for (cid = 0; cid <= last_cid; cid++) {
    USHORT idx, gid;
    double vertOriginX, vertOriginY, advanceHeight;

    if (!is_used_char2(used_chars, cid))
      continue;
    gid = (cidtogidmap) ? ((cidtogidmap[2*cid] << 8)|cidtogidmap[2*cid+1]) : cid;
    idx = tt_get_index(g, cid);
    if (cid != 0 && idx == 0)
      continue;
    advanceHeight = PDFUNIT(g->gd[idx].advh);
    vertOriginX   = PDFUNIT(0.5*(g->gd[idx].advw));
    vertOriginY   = PDFUNIT(g->gd[idx].tsb + g->gd[idx].ury);
#if 0
    /*
     * c [w1_1y v_1x v_1y w1_2y v_2x v_2y ...]
     * Not working... Why?
     * Acrobat Reader:
     *  Wrong rendering, interpretation of position vector is wrong.
     * Xpdf and gs: ignores W2?
     */
    if (vertOriginY == defaultVertOriginY &&
       advanceHeight == defaultAdvanceHeight) {
      if (an_array) {
       pdf_add_array(w2_array, pdf_new_number(start));
       pdf_add_array(w2_array, an_array);
       an_array = NULL;
       empty = 0;
      }
    } else {
      if (cid != prev + 1 && an_array) {
       pdf_add_array(w2_array, pdf_new_number(start));
       pdf_add_array(w2_array, an_array);
       an_array = NULL;
       empty = 0;
      }
      if (an_array == NULL) {
       an_array = pdf_new_array();
       start = cid;
      }
      pdf_add_array(an_array, pdf_new_number(-advanceHeight));
      pdf_add_array(an_array, pdf_new_number(vertOriginX));
      pdf_add_array(an_array, pdf_new_number(vertOriginY));
      prev = cid;
    }
#else
    /*
     * c_first c_last w1_y v_x v_y
     * This form may hit Acrobat's implementation limit of array element size,
     * 8192. AFPL GhostScript 8.11 stops with rangecheck error with this.
     * Maybe GS's bug?
     */
    if (vertOriginY != defaultVertOriginY ||
       advanceHeight != defaultAdvanceHeight) {
      pdf_add_array(w2_array, pdf_new_number(cid));
      pdf_add_array(w2_array, pdf_new_number(cid));
      pdf_add_array(w2_array, pdf_new_number(-advanceHeight));
      pdf_add_array(w2_array, pdf_new_number(vertOriginX));
      pdf_add_array(w2_array, pdf_new_number(vertOriginY));
      empty = 0;
    }
#endif
  }

#if 0
  if (an_array) {
    pdf_add_array(w2_array, pdf_new_number(start));
    pdf_add_array(w2_array, an_array);
    empty = 0;
  }
#endif

  if (defaultVertOriginY != 880 || defaultAdvanceHeight != 1000) {
    an_array = pdf_new_array();
    pdf_add_array(an_array, pdf_new_number(defaultVertOriginY));
    pdf_add_array(an_array, pdf_new_number(-defaultAdvanceHeight));
    pdf_add_dict(fontdict, pdf_new_name ("DW2"), an_array);
  }
  if (!empty) {
    pdf_add_dict(fontdict,
               pdf_new_name("W2"),
               pdf_ref_obj(w2_array));
  }
  pdf_release_obj(w2_array);

  return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static long cid_to_code ( CMap cmap,
CID  cid 
) [static]

Definition at line 451 of file cidtype2.c.

{
  unsigned char  inbuf[2], outbuf[32];
  long           inbytesleft = 2, outbytesleft = 32;
  unsigned char *p, *q;

  if (!cmap)
    return cid;

  inbuf[0] = (cid >> 8) & 0xff;
  inbuf[1] = cid & 0xff;
  p = inbuf; q = outbuf;

  CMap_decode_char(cmap, (const unsigned char **) &p, &inbytesleft, &q, &outbytesleft);

  if (inbytesleft != 0)
    return 0;
  else if (outbytesleft == 31)
    return (long) outbuf[0];
  else if (outbytesleft == 30)
    return (long) (outbuf[0] << 8|outbuf[1]);
  else if (outbytesleft == 28) { /* We assume the output encoding is UTF-16. */
    CID hi, lo;
    hi = outbuf[0] << 8|outbuf[1];
    lo = outbuf[2] << 8|outbuf[3];
    if (hi >= 0xd800 && hi <= 0xdbff && lo >= 0xdc00 && lo <= 0xdfff)
      return (long) ((hi - 0xd800) * 0x400 + 0x10000 + lo - 0xdc00);
    else
      return (long) (hi << 16|lo);
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void CIDFont_type2_dofont ( CIDFont font)

Definition at line 488 of file cidtype2.c.

{
  pdf_obj *fontfile;
  sfnt    *sfont;
  char    *h_used_chars, *v_used_chars, *used_chars;
  struct tt_glyphs *glyphs;
  CMap    *cmap = NULL;
  tt_cmap *ttcmap = NULL;
  unsigned long offset = 0;
  CID      cid, last_cid;
  unsigned char *cidtogidmap;
  USHORT   num_glyphs;
  int      i, glyph_ordering = 0, unicode_cmap = 0;
  FILE    *fp;

  if (!font->indirect)
    return;

  pdf_add_dict(font->fontdict, 
              pdf_new_name("FontDescriptor"), pdf_ref_obj(font->descriptor));

  if (CIDFont_is_BaseFont(font))
    return;

  /*
   * CIDSystemInfo comes here since Supplement can be increased.
   */
  {
    pdf_obj *tmp;

    tmp = pdf_new_dict ();
    pdf_add_dict(tmp,
               pdf_new_name("Registry"),
               pdf_new_string(font->csi->registry, strlen(font->csi->registry)));
    pdf_add_dict(tmp,
               pdf_new_name("Ordering"),
               pdf_new_string(font->csi->ordering, strlen(font->csi->ordering)));
    pdf_add_dict(tmp,
               pdf_new_name("Supplement"),
               pdf_new_number(font->csi->supplement));
    pdf_add_dict(font->fontdict, pdf_new_name("CIDSystemInfo"), tmp);
  }

  /* Quick exit for non-embedded & fixed-pitch font. */
  if (!CIDFont_get_embedding(font) &&
      (opt_flags & CIDFONT_FORCE_FIXEDPITCH)) {
    pdf_add_dict(font->fontdict,
               pdf_new_name("DW"), pdf_new_number(1000.0));
    return;
  }

  fp = DPXFOPEN(font->ident, DPX_RES_TYPE_TTFONT);
  if (!fp) {
    fp = DPXFOPEN(font->ident, DPX_RES_TYPE_DFONT);
    if (!fp) ERROR("Could not open TTF/dfont file: %s", font->ident);
    sfont = dfont_open(fp, font->options->index);
  } else {
    sfont = sfnt_open(fp);
  }

  if (!sfont) {
    ERROR("Could not open TTF file: %s", font->ident);
  }

  switch (sfont->type) {
  case SFNT_TYPE_TTC:
    offset = ttc_read_offset(sfont, font->options->index);
    if (offset == 0)
      ERROR("Invalid TTC index in %s.", font->ident);
    break;
  case SFNT_TYPE_TRUETYPE:
    if (font->options->index > 0)
      ERROR("Found TrueType font file while expecting TTC file (%s).", font->ident);
    offset = 0;
    break;
  case SFNT_TYPE_DFONT:
    offset = sfont->offset;
    break;
  default:
    ERROR("Not a TrueType/TTC font (%s)?", font->ident);
    break;
  }

  if (sfnt_read_table_directory(sfont, offset) < 0)
    ERROR("Could not read TrueType table directory (%s).", font->ident);

  /*
   * Adobe-Identity means font's internal glyph ordering here.
   */
  if (!strcmp(font->csi->registry, "Adobe") &&
      !strcmp(font->csi->ordering, "Identity")) {
    glyph_ordering = 1;
  } else {
    glyph_ordering = 0;
  }

  /*
   * Select TrueType cmap table, find ToCode CMap for each TrueType encodings.
   */
  if (glyph_ordering) {
    ttcmap = NULL;
    cmap   = NULL;
  } else {
    /*
     * This part contains a bug. It may choose SJIS encoding TrueType cmap
     * table for Adobe-GB1.
     */
    for (i = 0; i <= KNOWN_ENCODINGS_MAX; i++) {
      ttcmap = tt_cmap_read(sfont,
                         known_encodings[i].platform,
                         known_encodings[i].encoding);
      if (ttcmap)
       break;
    }
    if (!ttcmap) {
      WARN("No usable TrueType cmap table found for font \"%s\".", font->ident);
      WARN("CID character collection for this font is set to \"%s-%s\"",
          font->csi->registry, font->csi->ordering);
      ERROR("Cannot continue without this...");
    } else if (i <= WIN_UCS_INDEX_MAX) {
      unicode_cmap = 1;
    } else {
      unicode_cmap = 0;
    }

    /*
     * NULL is returned if CMap is Identity CMap.
     */
    cmap = find_tocode_cmap(font->csi->registry,
                         font->csi->ordering, i);
  }

  glyphs = tt_build_init();

  last_cid   = 0;
  num_glyphs = 1; /* .notdef */
  used_chars = h_used_chars = v_used_chars = NULL;
  {
    Type0Font *parent;
    int        parent_id, c;

    if ((parent_id = CIDFont_get_parent_id(font, 0)) >= 0) {
      parent = Type0Font_cache_get(parent_id);
      h_used_chars = Type0Font_get_usedchars(parent);
    }
    if ((parent_id = CIDFont_get_parent_id(font, 1)) >= 0) {
      parent = Type0Font_cache_get(parent_id);
      v_used_chars = Type0Font_get_usedchars(parent);
    }
    if (!h_used_chars && !v_used_chars)
      ERROR("Unexpected error.");

    /*
     * Quick check of max CID.
     */
    c = 0;
    for (i = 8191; i >= 0; i--) {
      if (h_used_chars && h_used_chars[i] != 0) {
       last_cid = i * 8 + 7;
       c = h_used_chars[i];
       break;
      }
      if (v_used_chars && v_used_chars[i] != 0) {
       last_cid = i * 8 + 7;
       c = v_used_chars[i];
       break;
      }
    }
    if (last_cid > 0) {
      for (i = 0; i < 8; i++) {
       if ((c >> i) & 1)
         break;
       last_cid--;
      }
    }
    if (last_cid >= 0xFFFFu) {
      ERROR("CID count > 65535");
    }
  }

#ifndef NO_GHOSTSCRIPT_BUG
  cidtogidmap = NULL;
#else
  cidtogidmap = NEW((last_cid + 1) * 2, unsigned char);
  memset(cidtogidmap, 0, (last_cid + 1) * 2);
#endif /* !NO_GHOSTSCRIPT_BUG */

  /*
   * Map CIDs to GIDs.
   * Horizontal and vertical used_chars are merged.
   */

  /*
   * Horizontal
   */
  if (h_used_chars) {
    used_chars = h_used_chars;
    for (cid = 1; cid <= last_cid; cid++) {
      long           code;
      unsigned short gid;

      if (!is_used_char2(h_used_chars, cid))
       continue;

      if (glyph_ordering) {
       gid  = cid;
       code = cid;
      } else {
       code = cid_to_code(cmap, cid);
       gid  = tt_cmap_lookup(ttcmap, code);
#ifdef FIX_CJK_UNIOCDE_SYMBOLS
       if (gid == 0 && unicode_cmap) {
         long alt_code;

         alt_code = fix_CJK_symbols(code);
         if (alt_code != code) {
           gid = tt_cmap_lookup(ttcmap, alt_code);
           if (gid != 0) {
             WARN("Unicode char U+%04x replaced with U+%04x.",
                 code, alt_code);
           }
         }
       }
#endif /* FIX_CJK_UNIOCDE_SYMBOLS */
      }

      if (gid == 0) {
       WARN("Glyph missing in font. (CID=%u, code=0x%04x)", cid, code);
      }

      /* TODO: duplicated glyph */
#ifndef NO_GHOSTSCRIPT_BUG
      gid = tt_add_glyph(glyphs, gid, cid);
#else
      gid = tt_add_glyph(glyphs, gid, num_glyphs);
      cidtogidmap[2*cid  ] = gid >> 8;
      cidtogidmap[2*cid+1] = gid & 0xff;
#endif /* !NO_GHOSTSCRIPT_BUG */

      num_glyphs++;
    }
  }

  /*
   * Vertical
   */
  if (v_used_chars) {
    otl_gsub *gsub_list = NULL;

    /*
     * Require `vrt2' or `vert'.
     */
    if (glyph_ordering) {
      gsub_list = NULL;
    } else {
      gsub_list = otl_gsub_new();
      if (otl_gsub_add_feat(gsub_list,
                         "*", "*", "vrt2", sfont) < 0) {
       if (otl_gsub_add_feat(gsub_list,
                           "*", "*", "vert", sfont) < 0) {
         WARN("GSUB feature vrt2/vert not found.");
         otl_gsub_release(gsub_list);
         gsub_list = NULL;
       } else {
         otl_gsub_select(gsub_list, "*", "*", "vert");
       }
      } else {
       otl_gsub_select(gsub_list, "*", "*", "vrt2");
      }
    }

    for (cid = 1; cid <= last_cid; cid++) {
      long           code;
      unsigned short gid;

      if (!is_used_char2(v_used_chars, cid))
       continue;

      /* There may be conflict of horizontal and vertical glyphs
       * when font is used with /UCS. However, we simply ignore
       * that...
       */
      if (h_used_chars && is_used_char2(h_used_chars, cid)) {
       continue;
      }

      if (glyph_ordering) {
       gid  = cid;
       code = cid;
      } else {
       code = cid_to_code(cmap, cid);
       gid  = tt_cmap_lookup(ttcmap, code);
#ifdef FIX_CJK_UNIOCDE_SYMBOLS
       if (gid == 0 && unicode_cmap) {
         long alt_code;

         alt_code = fix_CJK_symbols(code);
         if (alt_code != code) {
           gid = tt_cmap_lookup(ttcmap, alt_code);
           if (gid != 0) {
             WARN("Unicode char U+%04x replaced with U+%04x.",
                 code, alt_code);
           }
         }
       }
#endif /* FIX_CJK_UNIOCDE_SYMBOLS */
      }
      if (gid == 0) {
       WARN("Glyph missing in font. (CID=%u, code=0x%04x)", cid, code);
      } else if (gsub_list) {
       otl_gsub_apply(gsub_list, &gid);
      }

#ifndef NO_GHOSTSCRIPT_BUG
      gid = tt_add_glyph(glyphs, gid, cid);
#else
      gid = tt_add_glyph(glyphs, gid, num_glyphs);
      cidtogidmap[2*cid  ] = gid >> 8;
      cidtogidmap[2*cid+1] = gid & 0xff;
#endif /* !NO_GHOSTSCRIPT_BUG */

      if (used_chars) /* merge vertical used_chars to horizontal */
       add_to_used_chars2(used_chars, cid);

      num_glyphs++;
    }

    if (gsub_list)
      otl_gsub_release(gsub_list);

    if (!used_chars) /* We have no horizontal. */
      used_chars = v_used_chars;
  }

  if (!used_chars)
    ERROR("Unexpected error.");

  tt_cmap_release(ttcmap);

  if (CIDFont_get_embedding(font)) {
    if (tt_build_tables(sfont, glyphs) < 0)
      ERROR("Could not created FontFile stream.");
    if (verbose > 1)
      MESG("[%u glyphs (Max CID: %u)]", glyphs->num_glyphs, last_cid);
  } else {
    if (tt_get_metrics(sfont, glyphs) < 0)
      ERROR("Reading glyph metrics failed...");
  }

  /*
   * DW, W, DW2, and W2
   */
  if (opt_flags & CIDFONT_FORCE_FIXEDPITCH) {
    pdf_add_dict(font->fontdict,
               pdf_new_name("DW"), pdf_new_number(1000.0));
  } else {
    add_TTCIDHMetrics(font->fontdict, glyphs, used_chars, cidtogidmap, last_cid);
    if (v_used_chars)
      add_TTCIDVMetrics(font->fontdict, glyphs, used_chars, cidtogidmap, last_cid);
  }

  tt_build_finish(glyphs);

  /* Finish here if not embedded. */
  if (!CIDFont_get_embedding(font)) {
    if (cidtogidmap)
      RELEASE(cidtogidmap);
    sfnt_close(sfont);
    DPXFCLOSE(fp);

    return;
  }

  /* Create font file */
  for (i = 0; required_table[i].name; i++) {
    if (sfnt_require_table(sfont,
                        required_table[i].name,
                        required_table[i].must_exist) < 0) {
      ERROR("Some required TrueType table (%s) does not exist.", required_table[i].name);
    }
  }

  /*
   * FontFile2
   */
  fontfile = sfnt_create_FontFile_stream(sfont);

  sfnt_close(sfont);
  DPXFCLOSE(fp);

  if (!fontfile)
    ERROR("Could not created FontFile stream for \"%s\".", font->ident);

  if (verbose > 1) {
    MESG("[%ld bytes]", pdf_stream_length(fontfile));
  }

  pdf_add_dict(font->descriptor,
              pdf_new_name("FontFile2"),
              pdf_ref_obj (fontfile));
  pdf_release_obj(fontfile);

  /*
   * CIDSet
   */
  {
    pdf_obj *cidset;

    cidset = pdf_new_stream(STREAM_COMPRESS);
    pdf_add_stream(cidset, used_chars, last_cid/8 + 1);
    pdf_add_dict(font->descriptor,
               pdf_new_name("CIDSet"),
               pdf_ref_obj(cidset));
    pdf_release_obj(cidset);
  }

  /*
   * CIDToGIDMap
   */
  if (cidtogidmap) {
    pdf_obj *c2gmstream;

    c2gmstream = pdf_new_stream(STREAM_COMPRESS);
    pdf_add_stream(c2gmstream, cidtogidmap, (last_cid + 1) * 2);
    pdf_add_dict(font->fontdict,
                 pdf_new_name("CIDToGIDMap"),
                 pdf_ref_obj (c2gmstream));
    pdf_release_obj(c2gmstream);
    RELEASE(cidtogidmap);
  }
  
  return;
}

Here is the caller graph for this function:

int CIDFont_type2_open ( CIDFont font,
const char *  name,
CIDSysInfo cmap_csi,
cid_opt opt 
)

Definition at line 923 of file cidtype2.c.

{
  char    *fontname;
  sfnt    *sfont;
  unsigned long offset = 0;
  FILE    *fp;

  ASSERT(font && opt);

  fp = DPXFOPEN(name, DPX_RES_TYPE_TTFONT);
  if (!fp) {
    fp = DPXFOPEN(name, DPX_RES_TYPE_DFONT);
    if (!fp) return -1;
    sfont = dfont_open(fp, opt->index);
  } else {
    sfont = sfnt_open(fp);
  }

  if (!sfont) {
    DPXFCLOSE(fp);
    return -1;
  }

  switch (sfont->type) {
  case SFNT_TYPE_TTC:
    offset = ttc_read_offset(sfont, opt->index);
    break;
  case SFNT_TYPE_TRUETYPE:
    if (opt->index > 0) {
      ERROR("Invalid TTC index (not TTC font): %s", name);
    } else {
      offset = 0;
    }
    break;
  case SFNT_TYPE_DFONT:
    offset = sfont->offset;
    break;
  default:
    sfnt_close(sfont);
    DPXFCLOSE(fp);
    return -1;
    break;
  }

  if (sfnt_read_table_directory(sfont, offset) < 0) {
    ERROR("Reading TrueType table directory failed.");
  }

  {
    char *shortname;
    long  namelen;

    /* MAC-ROMAN-EN-POSTSCRIPT or WIN-UNICODE-EN(US)-POSTSCRIPT */
    shortname = NEW(PDF_NAME_LEN_MAX, char);
    namelen   = tt_get_ps_fontname(sfont, shortname, PDF_NAME_LEN_MAX);
    if (namelen == 0) {
      memset(shortname, 0, PDF_NAME_LEN_MAX);
      strncpy(shortname, name, PDF_NAME_LEN_MAX);
      namelen = strlen(shortname);
    }
    validate_name(shortname, namelen); /* for SJIS, UTF-16, ... string */
    /*
     * Strlen works, after validate_named string.
     * Mangled name requires more 7 bytes.
     * Style requires more 11 bytes.
     */
    fontname = NEW(strlen(shortname)+19, char);
    strcpy(fontname, shortname);
    RELEASE(shortname);
  }

  if (opt->embed && opt->style != FONT_STYLE_NONE) {
    WARN("Embedding disabled due to style option for %s.", name);
    opt->embed = 0;
  }
  switch (opt->style) {
  case FONT_STYLE_BOLD:
    strcat(fontname, ",Bold");
    break;
  case FONT_STYLE_ITALIC:
    strcat(fontname, ",Italic");
    break;
  case FONT_STYLE_BOLDITALIC:
    strcat(fontname, ",BoldItalic");
    break;
  }
  /*
   * CIDSystemInfo is determined from CMap or from map record option.
   */
  font->fontname = fontname;
  font->subtype  = CIDFONT_TYPE2;
  font->csi      = NEW(1, CIDSysInfo);
  if (opt->csi) {
    if (cmap_csi) {
      if (strcmp(opt->csi->registry, cmap_csi->registry) ||
         strcmp(opt->csi->ordering, cmap_csi->ordering)) {
       WARN("CID character collection mismatched:\n");
       MESG("\tFont: %s-%s-%d\n",
            opt->csi->registry, opt->csi->ordering, opt->csi->supplement);
       MESG("\tCMap: %s-%s-%d\n",
            cmap_csi->registry, cmap_csi->ordering, cmap_csi->supplement);
       ERROR("Incompatible CMap specified for this font.");
      }
      if (opt->csi->supplement < cmap_csi->supplement) {
       WARN("Supplmement value in CIDSystemInfo increased.");
       WARN("Some characters may not shown.");
       opt->csi->supplement = cmap_csi->supplement;
      }
    }
    font->csi->registry   = NEW(strlen(opt->csi->registry)+1, char);
    strcpy(font->csi->registry, opt->csi->registry);
    font->csi->ordering   = NEW(strlen(opt->csi->ordering)+1, char);
    strcpy(font->csi->ordering, opt->csi->ordering);
    font->csi->supplement = opt->csi->supplement;
  } else if (cmap_csi) {
    font->csi->registry   = NEW(strlen(cmap_csi->registry)+1, char);
    strcpy(font->csi->registry, cmap_csi->registry);
    font->csi->ordering   = NEW(strlen(cmap_csi->ordering)+1, char);
    strcpy(font->csi->ordering, cmap_csi->ordering);
    font->csi->supplement = cmap_csi->supplement;
  } else { /* This means font's internal glyph ordering. */
    font->csi->registry   = NEW(strlen("Adobe")+1, char);
    strcpy(font->csi->registry, "Adobe");
    font->csi->ordering   = NEW(strlen("Identity")+1, char);
    strcpy(font->csi->ordering, "Identity");
    font->csi->supplement = 0;
  }

  font->fontdict = pdf_new_dict();
  pdf_add_dict(font->fontdict,
              pdf_new_name("Type"),
              pdf_new_name("Font"));
  pdf_add_dict(font->fontdict,
              pdf_new_name("Subtype"),
              pdf_new_name("CIDFontType2"));

  font->descriptor = tt_get_fontdesc(sfont, &(opt->embed), opt->stemv, 0);
  if (!font->descriptor) {
    ERROR("Could not obtain neccesary font info.");
  }

  if (opt->embed) {
    memmove(fontname + 7, fontname, strlen(fontname) + 1);
    pdf_font_make_uniqueTag(fontname);
    fontname[6] = '+';
  }

  pdf_add_dict(font->descriptor,
              pdf_new_name("FontName"),
              pdf_new_name(fontname));
  pdf_add_dict(font->fontdict, 
              pdf_new_name("BaseFont"),
              pdf_new_name(fontname));

  sfnt_close(sfont);
  DPXFCLOSE(fp);

  /*
   * Don't write fontdict here.
   * /Supplement in /CIDSystemInfo may change.
   */

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void CIDFont_type2_release ( CIDFont font)

Definition at line 1090 of file cidtype2.c.

{
  return;
}

Here is the caller graph for this function:

void CIDFont_type2_set_flags ( long  flags)

Definition at line 72 of file cidtype2.c.

{
  opt_flags = flags;
}

Here is the caller graph for this function:

void CIDFont_type2_set_verbose ( void  )

Definition at line 66 of file cidtype2.c.

{
  verbose++;
}

Here is the caller graph for this function:

static CMap* find_tocode_cmap ( const char *  reg,
const char *  ord,
int  select 
) [static]

Definition at line 183 of file cidtype2.c.

{
  int   cmap_id = -1, i;
  char *cmap_name;
  char *append;

  if (!reg || !ord ||
      select < 0 || select > KNOWN_ENCODINGS_MAX)
    ERROR("Character set unknown.");

  if (!strcmp(ord, "UCS") &&
      select <= WIN_UCS_INDEX_MAX)
    return NULL;

  for (i = 0; cmap_id < 0 && i < 5; i++) {
    append = (char *) known_encodings[select].pdfnames[i];
    if (!append)
      break;
    cmap_name = NEW(strlen(reg) + strlen(ord) + strlen(append) + 3, char);
    sprintf(cmap_name, "%s-%s-%s", reg, ord, append);
    cmap_id = CMap_cache_find(cmap_name);
    RELEASE(cmap_name);
  }
  if (cmap_id < 0) {
    WARN("Could not find CID-to-Code mapping for \"%s-%s\".", reg, ord);
    WARN("I tried to load (one of) the following file(s):");
    for (i = 0; i < 5; i++) {
      append = (char *) known_encodings[select].pdfnames[i];
      if (!append)
       break;
      MESG(" %s-%s-%s", reg, ord, append);
    }
    WARN("Please check if this file exists.");
    ERROR("Cannot continue...");
  }

  return CMap_cache_get(cmap_id);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned short fix_CJK_symbols ( unsigned short  code) [static]

Definition at line 409 of file cidtype2.c.

{
  unsigned short alt_code;
  static struct
  {
    unsigned short alt1;
    unsigned short alt2;
  } CJK_Uni_symbols[] = {
    /*
     * Microsoft/Apple Unicode mapping difference:
     * They are taken from SJIS-Unicode mapping difference but nearly
     * same thing might be applied to Chinese (e.g., Big5) too.
     */
    {0x2014, 0x2015}, /* EM DASH <-> HORIZONTAL BAR */
    {0x2016, 0x2225}, /* DOUBLE VERTICAL LINE <-> PARALLEL TO */
    {0x203E, 0xFFE3}, /* OVERLINE <-> FULLWIDTH MACRON */
    {0x2026, 0x22EF}, /* HORIZONTAL ELLIPSIS <-> MIDLINE HORIZONTAL ELLIPSIS */
    {0x2212, 0xFF0D}, /* MINUS SIGN <-> FULLWIDTH HYPHEN-MINUS */
    {0x301C, 0xFF5E}, /* WAVE DASH <-> FULLWIDTH TILDE */
    {0xFFE0, 0x00A2}, /* FULLWIDTH CENT SIGN <-> CENT SIGN */
    {0xFFE1, 0x00A3}, /* FULLWIDTH POUND SIGN <-> POUND SIGN */
    {0xFFE2, 0x00AC}, /* FULLWIDTH NOT SIGN <-> NOT SIGN */
    {0xFFFF, 0xFFFF}, /* EOD */
  };
#define NUM_CJK_SYMBOLS (sizeof(CJK_Uni_symbols)/sizeof(CJK_Uni_symbols[0]))
  int i;

  alt_code = code;
  for (i = 0; i < NUM_CJK_SYMBOLS; i++) {
    if (CJK_Uni_symbols[i].alt1 == code) {
      alt_code = CJK_Uni_symbols[i].alt2;
      break;
    } else if (CJK_Uni_symbols[i].alt2 == code) {
      alt_code = CJK_Uni_symbols[i].alt1;
      break;
    }
  }

  return alt_code;
}

Here is the caller graph for this function:

static void validate_name ( char *  fontname,
int  len 
) [static]

Definition at line 110 of file cidtype2.c.

{
  int    i, count;
  char  *p;
  static const char *badstrlist[] = {
    "-WIN-RKSJ-H",
    "-WINP-RKSJ-H",
    "-WING-RKSJ-H",
    "-90pv-RKSJ-H",
    NULL
  };

  for (count = 0, i = 0; i < len; i++) {
    if (fontname[i] == 0) {
      memmove(fontname + i, fontname + i + 1, len - i);
      count++;
      len--;
    }
  }
  if (count > 0) {
    WARN("Removed %d null character(s) from fontname --> %s",
        count, fontname);
  }
  fontname[len] = '\0';

  /* For some fonts that have bad PS name. ad hoc. remove me. */
  for (i = 0; badstrlist[i] != NULL; i++) {
    p = strstr(fontname, badstrlist[i]);
    if (p && p > fontname) {
      WARN("Removed string \"%s\" from fontname \"%s\".",
          badstrlist[i], fontname);
      p[0] = '\0';
      len  = (int) (p - fontname);
      break;
    }
  }

  if (len < 1) {
    ERROR("No valid character found in fontname string.");
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

struct { ... } known_encodings[] [static]
int opt_flags = 0 [static]

Definition at line 63 of file cidtype2.c.

struct { ... } required_table[] [static]
int verbose = 0 [static]

Definition at line 62 of file cidtype2.c.