Back to index

texmacs  1.0.7.15
Classes | Defines | Functions
cmap_write.c File Reference
#include <string.h>
#include "system.h"
#include "mem.h"
#include "error.h"
#include "dpxutil.h"
#include "pdfobj.h"
#include "pdfresource.h"
#include "cmap_p.h"
#include "cmap.h"
#include "cmap_write.h"

Go to the source code of this file.

Classes

struct  sbuf

Defines

#define BLOCK_LEN_MIN   2
#define CMAP_BEGIN   "\/CIDInit /ProcSet findresource begin\n\12 dict begin\n\begincmap\n\"
#define CMAP_END   "\endcmap\n\CMapName currentdict /CMap defineresource pop\n\end\n\end\n\"
#define WBUF_SIZE   4096
#define CMAP_CSI_FMT   "/CIDSystemInfo <<\n\ /Registry (%s)\n\ /Ordering (%s)\n\ /Supplement %d\n\>> def\n"

Functions

static int write_map (mapDef *mtab, int count, unsigned char *codestr, int depth, struct sbuf *wbuf, pdf_obj *stream)
static int block_count (mapDef *mtab, int c)
pdf_objCMap_create_stream (CMap *cmap, int flags)

Class Documentation

struct sbuf

Definition at line 57 of file cmap_write.c.

Class Members
char * buf
char * curptr
char * limptr

Define Documentation

#define BLOCK_LEN_MIN   2
#define CMAP_BEGIN   "\/CIDInit /ProcSet findresource begin\n\12 dict begin\n\begincmap\n\"

Definition at line 229 of file cmap_write.c.

#define CMAP_CSI_FMT   "/CIDSystemInfo <<\n\ /Registry (%s)\n\ /Ordering (%s)\n\ /Supplement %d\n\>> def\n"
#define CMAP_END   "\endcmap\n\CMapName currentdict /CMap defineresource pop\n\end\n\end\n\"

Definition at line 235 of file cmap_write.c.

#define WBUF_SIZE   4096

Function Documentation

static int block_count ( mapDef mtab,
int  c 
) [static]

Definition at line 84 of file cmap_write.c.

{
  int count = 0, n;

  n  = mtab[c].len - 1;
  c += 1;
  for (; c < 256; c++) {
    if (LOOKUP_CONTINUE(mtab[c].flag) ||
       !MAP_DEFINED(mtab[c].flag)     ||
       (MAP_TYPE(mtab[c].flag) != MAP_IS_CID &&
        MAP_TYPE(mtab[c].flag) != MAP_IS_CODE) ||
       mtab[c-1].len != mtab[c].len)
      break;
    else if (!memcmp(mtab[c-1].code, mtab[c].code, n) &&
            mtab[c-1].code[n] < 255 &&
            mtab[c-1].code[n] + 1 == mtab[c].code[n])
      count++;
    else {
      break;
    }
  }

  return count;
}

Here is the caller graph for this function:

pdf_obj* CMap_create_stream ( CMap cmap,
int  flags 
)

Definition at line 243 of file cmap_write.c.

{
  pdf_obj         *stream;
  pdf_obj         *stream_dict;
  CIDSysInfo      *csi;
  struct sbuf      wbuf;
  struct rangeDef *ranges;
  unsigned char   *codestr;
  int              i, j, count = 0;

  if (!cmap || !CMap_is_valid(cmap)) {
    WARN("Invalid CMap");
    return NULL;
  }

  if (cmap->type == CMAP_TYPE_IDENTITY)
    return NULL;

  stream      = pdf_new_stream(STREAM_COMPRESS);
  stream_dict = pdf_stream_dict(stream);

  csi = CMap_get_CIDSysInfo(cmap);
  if (!csi) {
    csi = (cmap->type != CMAP_TYPE_TO_UNICODE) ?
      &CSI_IDENTITY : &CSI_UNICODE;
  }

  if (cmap->type != CMAP_TYPE_TO_UNICODE) {
    pdf_obj *csi_dict;

    csi_dict = pdf_new_dict();
    pdf_add_dict(csi_dict,
               pdf_new_name("Registry"),
               pdf_new_string(csi->registry, strlen(csi->registry)));
    pdf_add_dict(csi_dict,
               pdf_new_name("Ordering"),
               pdf_new_string(csi->ordering, strlen(csi->ordering)));
    pdf_add_dict(csi_dict,
               pdf_new_name("Supplement"),
               pdf_new_number(csi->supplement));

    pdf_add_dict(stream_dict,
               pdf_new_name("Type"),
               pdf_new_name("CMap"));
    pdf_add_dict(stream_dict,
               pdf_new_name("CMapName"),
               pdf_new_name(cmap->name));
    pdf_add_dict(stream_dict,
               pdf_new_name("CIDSystemInfo"), csi_dict);
    if (cmap->wmode != 0)
      pdf_add_dict(stream_dict,
                 pdf_new_name("WMode"),
                 pdf_new_number(cmap->wmode));
  }

  /* TODO:
   * Predefined CMaps need not to be embedded.
   */
  if (cmap->useCMap) {
    ERROR("UseCMap found (not supported yet)...");
    if (CMap_is_Identity(cmap->useCMap)) { /* not sure */
      if (CMap_get_wmode(cmap) == 1) {
       pdf_add_dict(stream_dict,
                   pdf_new_name("UseCMap"),
                   pdf_new_name("Identity-V"));
      } else {
       pdf_add_dict(stream_dict,
                   pdf_new_name("UseCMap"),
                   pdf_new_name("Identity-H"));
      }
    } else {
      long     res_id;
      pdf_obj *ucmap_ref;

      res_id = pdf_findresource("CMap", CMap_get_name(cmap->useCMap));
      if (res_id >= 0) {
       ucmap_ref = pdf_get_resource_reference(res_id);
      } else {
       pdf_obj *ucmap_obj;

       ucmap_obj = CMap_create_stream(cmap->useCMap, 0);
       if (!ucmap_obj) {
         ERROR("Uh ah. I cannot continue...");
       }

       res_id = pdf_defineresource("CMap",
                                CMap_get_name(cmap->useCMap),
                                ucmap_obj, PDF_RES_FLUSH_IMMEDIATE);
       ucmap_ref = pdf_get_resource_reference(res_id);
      }
      pdf_add_dict(stream_dict, pdf_new_name("UseCMap"), ucmap_ref);
    }
  }

#define WBUF_SIZE 4096
  wbuf.buf = NEW(WBUF_SIZE, char);
  codestr  = NEW(cmap->profile.maxBytesIn, unsigned char);
  memset(codestr, 0, cmap->profile.maxBytesIn);

  wbuf.curptr = wbuf.buf;
  wbuf.limptr = wbuf.buf + WBUF_SIZE -
    2 * (cmap->profile.maxBytesIn + cmap->profile.maxBytesOut) + 16;

  /* Start CMap */
  pdf_add_stream(stream, (void *) CMAP_BEGIN, strlen(CMAP_BEGIN));

  wbuf.curptr += sprintf(wbuf.curptr, "/CMapName /%s def\n", cmap->name);
  wbuf.curptr += sprintf(wbuf.curptr, "/CMapType %d def\n" , cmap->type);
  if (cmap->wmode != 0 &&
      cmap->type != CMAP_TYPE_TO_UNICODE)
    wbuf.curptr += sprintf(wbuf.curptr, "/WMode %d def\n", cmap->wmode);

#define CMAP_CSI_FMT "/CIDSystemInfo <<\n\
  /Registry (%s)\n\
  /Ordering (%s)\n\
  /Supplement %d\n\
>> def\n"
  wbuf.curptr += sprintf(wbuf.curptr, CMAP_CSI_FMT,
                      csi->registry, csi->ordering, csi->supplement);
  pdf_add_stream(stream, wbuf.buf, (long)(wbuf.curptr - wbuf.buf));
  wbuf.curptr = wbuf.buf;

  /* codespacerange */
  ranges = cmap->codespace.ranges;
  wbuf.curptr += sprintf(wbuf.curptr,
                      "%d begincodespacerange\n", cmap->codespace.num);
  for (i = 0; i < cmap->codespace.num; i++) {
    *(wbuf.curptr)++ = '<';
    for (j = 0; j < ranges[i].dim; j++) {
      sputx(ranges[i].codeLo[j], &(wbuf.curptr), wbuf.limptr);
    }
    *(wbuf.curptr)++ = '>';
    *(wbuf.curptr)++ = ' ';
    *(wbuf.curptr)++ = '<';
    for (j = 0; j < ranges[i].dim; j++) {
      sputx(ranges[i].codeHi[j], &(wbuf.curptr), wbuf.limptr);
    }
    *(wbuf.curptr)++ = '>';
    *(wbuf.curptr)++ = '\n';
  }
  pdf_add_stream(stream, wbuf.buf, (long)(wbuf.curptr - wbuf.buf));
  wbuf.curptr = wbuf.buf;
  pdf_add_stream(stream,
               "endcodespacerange\n", strlen("endcodespacerange\n"));

  /* CMap body */
  if (cmap->mapTbl) {
    count = write_map(cmap->mapTbl,
                    0, codestr, 0, &wbuf, stream); /* Top node */
    if (count > 0) { /* Flush */
      char fmt_buf[32];
      if (count > 100)
       ERROR("Unexpected error....: %d", count);
      sprintf(fmt_buf, "%d beginbfchar\n", count);
      pdf_add_stream(stream, fmt_buf,  strlen(fmt_buf));
      pdf_add_stream(stream,
                   wbuf.buf, (long) (wbuf.curptr - wbuf.buf));
      pdf_add_stream(stream,
                   "endbfchar\n", strlen("endbfchar\n"));
      count = 0;
      wbuf.curptr = wbuf.buf;
    }
  }
  /* End CMap */
  pdf_add_stream(stream, CMAP_END, strlen(CMAP_END));

  RELEASE(codestr);
  RELEASE(wbuf.buf);

  return stream;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int write_map ( mapDef mtab,
int  count,
unsigned char *  codestr,
int  depth,
struct sbuf wbuf,
pdf_obj stream 
) [static]

Definition at line 110 of file cmap_write.c.

{
  int     c, i, block_length;
  mapDef *mtab1;
  /* Must be greater than 1 */
#define BLOCK_LEN_MIN 2
  struct {
    int start, count;
  } blocks[256/BLOCK_LEN_MIN+1];
  int num_blocks = 0;

  for (c = 0; c < 256; c++) {
    codestr[depth] = (unsigned char) (c & 0xff);
    if (LOOKUP_CONTINUE(mtab[c].flag)) {
      mtab1 = mtab[c].next;
      count = write_map(mtab1, count,
                     codestr, depth + 1, wbuf, stream);
    } else {
      if (MAP_DEFINED(mtab[c].flag)) {
       switch (MAP_TYPE(mtab[c].flag)) {
       case MAP_IS_CID: case MAP_IS_CODE:
         block_length = block_count(mtab, c);
         if (block_length >= BLOCK_LEN_MIN) {
           blocks[num_blocks].start = c;
           blocks[num_blocks].count = block_length;
           num_blocks++;
           c += block_length;
         } else {
           *(wbuf->curptr)++ = '<';
           for (i = 0; i <= depth; i++)
             sputx(codestr[i], &(wbuf->curptr), wbuf->limptr);
           *(wbuf->curptr)++ = '>';
           *(wbuf->curptr)++ = ' ';
           *(wbuf->curptr)++ = '<';
           for (i = 0; i < mtab[c].len; i++)
             sputx(mtab[c].code[i], &(wbuf->curptr), wbuf->limptr);
           *(wbuf->curptr)++ = '>';
           *(wbuf->curptr)++ = '\n';
           count++;
         }
         break;
       case MAP_IS_NAME:
         ERROR("%s: Unexpected error...", CMAP_DEBUG_STR);
         break;
       case MAP_IS_NOTDEF:
         break;
       default:
         ERROR("%s: Unknown mapping type: %d",
              CMAP_DEBUG_STR, MAP_TYPE(mtab[c].flag));
       }
      }
    }

    /* Flush if necessary */
    if (count >= 100 ||
       wbuf->curptr >= wbuf->limptr ) {
      char fmt_buf[32];
      if (count > 100)
       ERROR("Unexpected error....: %d", count);
      sprintf(fmt_buf, "%d beginbfchar\n", count);
      pdf_add_stream(stream, fmt_buf,  strlen(fmt_buf));
      pdf_add_stream(stream,
                   wbuf->buf, (long) (wbuf->curptr - wbuf->buf));
      wbuf->curptr = wbuf->buf;
      pdf_add_stream(stream,
                   "endbfchar\n", strlen("endbfchar\n"));
      count = 0;
    }
  }

  if (num_blocks > 0) {
    char fmt_buf[32];

    if (count > 0) {
      sprintf(fmt_buf, "%d beginbfchar\n", count);
      pdf_add_stream(stream, fmt_buf,  strlen(fmt_buf));
      pdf_add_stream(stream,
                   wbuf->buf, (long) (wbuf->curptr - wbuf->buf));
      wbuf->curptr = wbuf->buf;
      pdf_add_stream(stream,
                   "endbfchar\n", strlen("endbfchar\n"));
      count = 0;
    }
    sprintf(fmt_buf, "%d beginbfrange\n", num_blocks);
    pdf_add_stream(stream, fmt_buf, strlen(fmt_buf));
    for (i = 0; i < num_blocks; i++) {
      int j;

      c = blocks[i].start;
      *(wbuf->curptr)++ = '<';
      for (j = 0; j < depth; j++)
       sputx(codestr[j], &(wbuf->curptr), wbuf->limptr);
      sputx(c, &(wbuf->curptr), wbuf->limptr);
      *(wbuf->curptr)++ = '>';
      *(wbuf->curptr)++ = ' ';
      *(wbuf->curptr)++ = '<';
      for (j = 0; j < depth; j++)
       sputx(codestr[j], &(wbuf->curptr), wbuf->limptr);
      sputx(c + blocks[i].count, &(wbuf->curptr), wbuf->limptr);
      *(wbuf->curptr)++ = '>';
      *(wbuf->curptr)++ = ' ';
      *(wbuf->curptr)++ = '<';
      for (j = 0; j < mtab[c].len; j++)
       sputx(mtab[c].code[j], &(wbuf->curptr), wbuf->limptr);
      *(wbuf->curptr)++ = '>';
      *(wbuf->curptr)++ = '\n';
    }
    pdf_add_stream(stream,
                 wbuf->buf, (long) (wbuf->curptr - wbuf->buf));
    wbuf->curptr = wbuf->buf;
    pdf_add_stream(stream,
                 "endbfrange\n", strlen("endbfrange\n"));
  }

  return count;
}

Here is the call graph for this function:

Here is the caller graph for this function: