Back to index

texmacs  1.0.7.15
Functions
cidtype2.h File Reference
#include "cid.h"
#include "cid_p.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void CIDFont_type2_set_verbose (void)
void CIDFont_type2_set_flags (long flags)
int CIDFont_type2_open (CIDFont *font, const char *name, CIDSysInfo *cmap_csi, cid_opt *opt)
void CIDFont_type2_dofont (CIDFont *font)
void CIDFont_type2_release (CIDFont *font)

Function Documentation

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: