Back to index

texmacs  1.0.7.15
Defines | Functions | Variables
cff_dict.c File Reference
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "error.h"
#include "mem.h"
#include "mfileio.h"
#include "cff_types.h"
#include "cff_limits.h"
#include "cff_dict.h"
#include "cff.h"

Go to the source code of this file.

Defines

#define CFF_DEBUG_STR   "CFF"
#define CFF_DEBUG   5
#define CFF_PARSE_OK   0
#define CFF_ERROR_PARSE_ERROR   -1
#define CFF_ERROR_STACK_OVERFLOW   -2
#define CFF_ERROR_STACK_UNDERFLOW   -3
#define CFF_ERROR_STACK_RANGECHECK   -4
#define DICT_ENTRY_MAX   16
#define CFF_DICT_STACK_LIMIT   64
#define CFF_LAST_DICT_OP1   22
#define CFF_LAST_DICT_OP2   39
#define CFF_LAST_DICT_OP   (CFF_LAST_DICT_OP1 + CFF_LAST_DICT_OP2)

Functions

cff_dictcff_new_dict (void)
void cff_release_dict (cff_dict *dict)
static double get_integer (card8 **data, card8 *endptr, int *status)
static double get_real (card8 **data, card8 *endptr, int *status)
static void add_dict (cff_dict *dict, card8 **data, card8 *endptr, int *status)
cff_dictcff_dict_unpack (card8 *data, card8 *endptr)
static long pack_integer (card8 *dest, long destlen, long value)
static long pack_real (card8 *dest, long destlen, double value)
static long cff_dict_put_number (double value, card8 *dest, long destlen, int type)
static long put_dict_entry (cff_dict_entry *de, card8 *dest, long destlen)
long cff_dict_pack (cff_dict *dict, card8 *dest, long destlen)
void cff_dict_add (cff_dict *dict, const char *key, int count)
void cff_dict_remove (cff_dict *dict, const char *key)
int cff_dict_known (cff_dict *dict, const char *key)
double cff_dict_get (cff_dict *dict, const char *key, int idx)
void cff_dict_set (cff_dict *dict, const char *key, int idx, double value)
void cff_dict_update (cff_dict *dict, cff_font *cff)

Variables

static int stack_top = 0
static double arg_stack [CFF_DICT_STACK_LIMIT]
struct {
const char * opname
int argtype
dict_operator [CFF_LAST_DICT_OP]

Define Documentation

#define CFF_DEBUG   5

Definition at line 39 of file cff_dict.c.

#define CFF_DEBUG_STR   "CFF"

Definition at line 38 of file cff_dict.c.

#define CFF_DICT_STACK_LIMIT   64

Definition at line 100 of file cff_dict.c.

#define CFF_ERROR_PARSE_ERROR   -1

Definition at line 54 of file cff_dict.c.

#define CFF_ERROR_STACK_OVERFLOW   -2

Definition at line 55 of file cff_dict.c.

#define CFF_ERROR_STACK_RANGECHECK   -4

Definition at line 57 of file cff_dict.c.

#define CFF_ERROR_STACK_UNDERFLOW   -3

Definition at line 56 of file cff_dict.c.

Definition at line 111 of file cff_dict.c.

#define CFF_LAST_DICT_OP1   22

Definition at line 109 of file cff_dict.c.

#define CFF_LAST_DICT_OP2   39

Definition at line 110 of file cff_dict.c.

#define CFF_PARSE_OK   0

Definition at line 53 of file cff_dict.c.

#define DICT_ENTRY_MAX   16

Definition at line 59 of file cff_dict.c.


Function Documentation

static void add_dict ( cff_dict dict,
card8 **  data,
card8 endptr,
int *  status 
) [static]

Definition at line 283 of file cff_dict.c.

{
  int id, argtype;

  id = **data;
  if (id == 0x0c) {
    *data += 1;
    if (*data >= endptr ||
       (id = **data + CFF_LAST_DICT_OP1) >= CFF_LAST_DICT_OP) {
      *status = CFF_ERROR_PARSE_ERROR;
      return;
    }
  } else if (id >= CFF_LAST_DICT_OP1) {
    *status = CFF_ERROR_PARSE_ERROR;
    return;
  }

  argtype = dict_operator[id].argtype;
  if (dict_operator[id].opname == NULL || argtype < 0) {
    *status = CFF_ERROR_PARSE_ERROR;
    return;
  } else if (stack_top < 1) {
    *status = CFF_ERROR_STACK_UNDERFLOW;
    return;
  }

  if (dict->count >= dict->max) {
    dict->max += DICT_ENTRY_MAX;
    dict->entries = RENEW(dict->entries, dict->max, cff_dict_entry);
  }

  (dict->entries)[dict->count].id = id;
  (dict->entries)[dict->count].key = (char *) dict_operator[id].opname;
  if (argtype == CFF_TYPE_NUMBER ||
      argtype == CFF_TYPE_BOOLEAN ||
      argtype == CFF_TYPE_SID ||
      argtype == CFF_TYPE_OFFSET) {
    stack_top--;
    (dict->entries)[dict->count].count  = 1;
    (dict->entries)[dict->count].values = NEW(1, double);
    (dict->entries)[dict->count].values[0] = arg_stack[stack_top];
  } else {
    (dict->entries)[dict->count].count  = stack_top;
    (dict->entries)[dict->count].values = NEW(stack_top, double);
    while (stack_top > 0) {
      stack_top--;
      (dict->entries)[dict->count].values[stack_top] = arg_stack[stack_top];
    }
  }

  dict->count += 1;
  *data += 1;

  return;
}

Here is the caller graph for this function:

void cff_dict_add ( cff_dict dict,
const char *  key,
int  count 
)

Definition at line 580 of file cff_dict.c.

{
  int id, i;

  for (id=0;id<CFF_LAST_DICT_OP;id++) {
    if (key && dict_operator[id].opname &&
       strcmp(dict_operator[id].opname, key) == 0)
      break;
  }

  if (id == CFF_LAST_DICT_OP)
    ERROR("%s: Unknown CFF DICT operator.", CFF_DEBUG_STR);

  for (i=0;i<dict->count;i++) {
    if ((dict->entries)[i].id == id) {
      if ((dict->entries)[i].count != count)
       ERROR("%s: Inconsistent DICT argument number.", CFF_DEBUG_STR);
      return;
    }
  }

  if (dict->count + 1 >= dict->max) {
    dict->max += 8;
    dict->entries = RENEW(dict->entries, dict->max, cff_dict_entry);
  }

  (dict->entries)[dict->count].id    = id;
  (dict->entries)[dict->count].key   = (char *) dict_operator[id].opname;
  (dict->entries)[dict->count].count = count;
  if (count > 0) {
    (dict->entries)[dict->count].values = NEW(count, double);
    memset((dict->entries)[dict->count].values,
          0, sizeof(double)*count);
  } else {
    (dict->entries)[dict->count].values = NULL;
  }
  dict->count += 1;

  return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

double cff_dict_get ( cff_dict dict,
const char *  key,
int  idx 
)

Definition at line 647 of file cff_dict.c.

{
  double value = 0.0;
  int    i;

  ASSERT(key && dict);

  for (i = 0; i < dict->count; i++) {
    if (strcmp(key, (dict->entries)[i].key) == 0) {
      if ((dict->entries)[i].count > idx)
       value = (dict->entries)[i].values[idx];
      else
       ERROR("%s: Invalid index number.", CFF_DEBUG_STR);
      break;
    }
  }

  if (i == dict->count)
    ERROR("%s: DICT entry \"%s\" not found.", CFF_DEBUG_STR, key);

  return value;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int cff_dict_known ( cff_dict dict,
const char *  key 
)

Definition at line 634 of file cff_dict.c.

{
  int i;

  for (i = 0; i < dict->count; i++) {
    if (key && strcmp(key, (dict->entries)[i].key) == 0
       && (dict->entries)[i].count > 0)
      return 1;
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

long cff_dict_pack ( cff_dict dict,
card8 dest,
long  destlen 
)

Definition at line 560 of file cff_dict.c.

{
  long len = 0;
  int  i;

  for (i = 0; i < dict->count; i++) {
    if (!strcmp(dict->entries[i].key, "ROS")) {
      len += put_dict_entry(&dict->entries[i], dest, destlen);
      break;
    }
  }
  for (i = 0; i < dict->count; i++) {
    if (strcmp(dict->entries[i].key, "ROS")) {
      len += put_dict_entry(&dict->entries[i], dest+len, destlen-len);
    }
  }

  return len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static long cff_dict_put_number ( double  value,
card8 dest,
long  destlen,
int  type 
) [static]

Definition at line 492 of file cff_dict.c.

{
  long   len = 0;
  double nearint;

  nearint = floor(value+0.5);
  /* set offset to longint */
  if (type == CFF_TYPE_OFFSET) {
    long lvalue;

    lvalue = (long) value;
    if (destlen < 5)
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
    dest[0] = 29;
    dest[1] = (lvalue >> 24) & 0xff;
    dest[2] = (lvalue >> 16) & 0xff;
    dest[3] = (lvalue >>  8) & 0xff;
    dest[4] = lvalue         & 0xff;
    len = 5;
  } else if (value > CFF_INT_MAX || value < CFF_INT_MIN ||
            (fabs(value - nearint) > 1.0e-5)) { /* real */
    len = pack_real(dest, destlen, value);
  } else { /* integer */
    len = pack_integer(dest, destlen, (long) nearint);
  }

  return len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cff_dict_remove ( cff_dict dict,
const char *  key 
)

Definition at line 621 of file cff_dict.c.

{
  int i;
  for (i = 0; i < dict->count; i++) {
    if (key && strcmp(key, (dict->entries)[i].key) == 0) {
      (dict->entries)[i].count = 0;
      if ((dict->entries)[i].values)
       RELEASE((dict->entries)[i].values);
      (dict->entries)[i].values = NULL;
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cff_dict_set ( cff_dict dict,
const char *  key,
int  idx,
double  value 
)

Definition at line 670 of file cff_dict.c.

{
  int i;

  ASSERT(dict && key);

  for (i = 0 ; i < dict->count; i++) {
    if (strcmp(key, (dict->entries)[i].key) == 0) {
      if ((dict->entries)[i].count > idx)
       (dict->entries)[i].values[idx] = value;
      else
       ERROR("%s: Invalid index number.", CFF_DEBUG_STR);
      break;
    }
  }

  if (i == dict->count)
    ERROR("%s: DICT entry \"%s\" not found.", CFF_DEBUG_STR, key);
}

Here is the call graph for this function:

Here is the caller graph for this function:

cff_dict* cff_dict_unpack ( card8 data,
card8 endptr 
)

Definition at line 345 of file cff_dict.c.

{
  cff_dict *dict;
  int status = CFF_PARSE_OK;

  stack_top = 0;

  dict = cff_new_dict();
  while (data < endptr && status == CFF_PARSE_OK) {
    if (*data < 22) { /* operator */
      add_dict(dict, &data, endptr, &status);
    } else if (*data == 30) { /* real - First byte of a sequence (variable) */
      if (stack_top < CFF_DICT_STACK_LIMIT) {
       arg_stack[stack_top] = get_real(&data, endptr, &status);
       stack_top++;
      } else {
       status = CFF_ERROR_STACK_OVERFLOW;
      }
    } else if (*data == 255 || (*data >= 22 && *data <= 27)) { /* reserved */
      data++;
    } else { /* everything else are integer */
      if (stack_top < CFF_DICT_STACK_LIMIT) {
       arg_stack[stack_top] = get_integer(&data, endptr, &status);
       stack_top++;
      } else {
       status = CFF_ERROR_STACK_OVERFLOW;
      }
    }
  }

  if (status != CFF_PARSE_OK) {
    ERROR("%s: Parsing CFF DICT failed. (error=%d)", CFF_DEBUG_STR, status);
  } else if (stack_top != 0) {
    WARN("%s: Garbage in CFF DICT data.", CFF_DEBUG_STR);
    stack_top = 0;
  }

  return dict;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cff_dict_update ( cff_dict dict,
cff_font cff 
)

Definition at line 690 of file cff_dict.c.

{
  int i;

  for (i = 0;i < dict->count; i++) {
    if ((dict->entries)[i].count > 0) {
      char *str;
      int   id;

      id = (dict->entries)[i].id;
      if (dict_operator[id].argtype == CFF_TYPE_SID) {
       str = cff_get_string(cff, (dict->entries)[i].values[0]);
       (dict->entries)[i].values[0] = cff_add_string(cff, str, 1);
       RELEASE(str);
      } else if (dict_operator[id].argtype == CFF_TYPE_ROS) {
       str = cff_get_string(cff, (dict->entries)[i].values[0]);
       (dict->entries)[i].values[0] = cff_add_string(cff, str, 1);
       RELEASE(str);
       str = cff_get_string(cff, (dict->entries)[i].values[1]);
       (dict->entries)[i].values[1] = cff_add_string(cff, str, 1);
       RELEASE(str);
      }
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

cff_dict* cff_new_dict ( void  )

Definition at line 60 of file cff_dict.c.

{
  cff_dict *dict;

  dict = NEW(1, cff_dict);
  dict->max     = DICT_ENTRY_MAX;
  dict->count   = 0;
  dict->entries = NEW(dict->max, cff_dict_entry);

  return dict;
}

Here is the caller graph for this function:

void cff_release_dict ( cff_dict dict)

Definition at line 72 of file cff_dict.c.

{
  if (dict) {
    if (dict->entries) {
      int i;
      for (i=0;i<dict->count;i++) {
       if ((dict->entries)[i].values)
         RELEASE((dict->entries)[i].values);
      }
      RELEASE(dict->entries);
    }
  RELEASE(dict);
  }
}

Here is the caller graph for this function:

static double get_integer ( card8 **  data,
card8 endptr,
int *  status 
) [static]

Definition at line 185 of file cff_dict.c.

{
  long result = 0;
  card8 b0, b1, b2;

  b0 = *(*data)++;
  if (b0 == 28 && *data < endptr - 2) { /* shortint */
    b1 = *(*data)++;
    b2 = *(*data)++;
    result = b1*256+b2;
    if (result > 0x7fffL)
      result -= 0x10000L;
  } else if (b0 == 29 && *data < endptr - 4) { /* longint */
    int i;
    result = *(*data)++;
    if (result > 0x7f)
      result -= 0x100;
    for (i=0;i<3;i++) {
      result = result*256+(**data);
      *data += 1;
    }
  } else if (b0 >= 32 && b0 <= 246) { /* int (1) */
    result = b0 - 139;
  } else if (b0 >= 247 && b0 <= 250) { /* int (2) */
    b1 = *(*data)++;
    result = (b0-247)*256+b1+108;
  } else if (b0 >= 251 && b0 <= 254) {
    b1 = *(*data)++;
    result = -(b0-251)*256-b1-108;
  } else {
    *status = CFF_ERROR_PARSE_ERROR;
  }

  return (double) result;
}

Here is the caller graph for this function:

static double get_real ( card8 **  data,
card8 endptr,
int *  status 
) [static]

Definition at line 222 of file cff_dict.c.

{
  double result = 0.0;
  int nibble = 0, pos = 0;
  int len = 0, fail = 0;

  if (**data != 30 || *data >= endptr -1) {
    *status = CFF_ERROR_PARSE_ERROR;
    return 0.0;
  }

  *data += 1; /* skip first byte (30) */

  pos = 0;
  while ((! fail) && len < WORK_BUFFER_SIZE - 2 && *data < endptr) {
    /* get nibble */
    if (pos % 2) {
      nibble = **data & 0x0f;
      *data += 1;
    } else {
      nibble = (**data >> 4) & 0x0f;
    }
    if (nibble >= 0x00 && nibble <= 0x09) {
      work_buffer[len++] = nibble + '0';
    } else if (nibble == 0x0a) { /* . */
      work_buffer[len++] = '.';
    } else if (nibble == 0x0b || nibble == 0x0c) { /* E, E- */
      work_buffer[len++] = 'e';
      if (nibble == 0x0c)
       work_buffer[len++] = '-';
    } else if (nibble == 0x0e) { /* `-' */
      work_buffer[len++] = '-';
    } else if (nibble == 0x0d) { /* skip */
      /* do nothing */
    } else if (nibble == 0x0f) { /* end */
      work_buffer[len++] = '\0';
      if (((pos % 2) == 0) && (**data != 0xff)) {
       fail = 1;
      }
      break;
    } else { /* invalid */
      fail = 1;
    }
    pos++;
  }

  /* returned values */
  if (fail || nibble != 0x0f) {
    *status = CFF_ERROR_PARSE_ERROR;
  } else {
    char *s;
    result = strtod(work_buffer, &s);
    if (*s != 0 || errno == ERANGE) {
      *status = CFF_ERROR_PARSE_ERROR;
    }
  }

  return result;
}

Here is the caller graph for this function:

static long pack_integer ( card8 dest,
long  destlen,
long  value 
) [static]

Definition at line 386 of file cff_dict.c.

{
  long len = 0;

  if (value >= -107 && value <= 107) {
    if (destlen < 1)
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
    dest[0] = (value + 139) & 0xff;
    len = 1;
  } else if (value >= 108 && value <= 1131) {
    if (destlen < 2)
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
    value = 0xf700u + value - 108;
    dest[0] = (value >> 8) & 0xff;
    dest[1] = value & 0xff;
    len = 2;
  } else if (value >= -1131 && value <= -108) {
    if (destlen < 2)
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
    value = 0xfb00u - value - 108;
    dest[0] = (value >> 8) & 0xff;
    dest[1] = value & 0xff;
    len = 2;
  } else if (value >= -32768 && value <= 32767) { /* shortint */
    if (destlen < 3)
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
    dest[0] = 28;
    dest[1] = (value >> 8) & 0xff;
    dest[2] = value & 0xff;
    len = 3;
  } else { /* longint */
    if (destlen < 5)
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
    dest[0] = 29;
    dest[1] = (value >> 24) & 0xff;
    dest[2] = (value >> 16) & 0xff;
    dest[3] = (value >> 8) & 0xff;
    dest[4] = value & 0xff;
    len = 5;
  }

  return len;
}

Here is the caller graph for this function:

static long pack_real ( card8 dest,
long  destlen,
double  value 
) [static]

Definition at line 430 of file cff_dict.c.

{
  int i = 0, pos = 2;
  char buffer[32];

  if (destlen < 2)
    ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);

  dest[0] = 30;

  if (value == 0.0) {
    dest[1] = 0x0f;
    return 2;
  }

  if (value < 0.0) {
    dest[1] = 0xe0;
    value *= -1.0;
    pos++;
  }

  /* To avoid the problem with Mac OS X 10.4 Quartz,
   * change the presion of the real numbers
   * on June 27, 2007 for musix20.pfb */
  sprintf(buffer, "%.13g", value);

  for (i = 0; buffer[i] != '\0'; i++) {
    unsigned char ch = 0;
    if (buffer[i] == '.') {
      ch = 0x0a;
    } else if (buffer[i] >= '0' && buffer[i] <= '9') {
      ch = buffer[i] - '0';
    } else if (buffer[i] == 'e') {
      ch = (buffer[++i] == '-' ? 0x0c : 0x0b);
    } else {
      ERROR("%s: Invalid character.", CFF_DEBUG_STR);
    }

    if (destlen < pos/2 + 1)
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);

    if (pos % 2) {
      dest[pos/2] += ch;
    } else {
      dest[pos/2] = (ch << 4);
    }
    pos++;
  }

  if (pos % 2) {
    dest[pos/2] += 0x0f;
    pos++;
  } else {
    if (destlen < pos/2 + 1)
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
    dest[pos/2] = 0xff;
    pos += 2;
  }

  return pos/2;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static long put_dict_entry ( cff_dict_entry de,
card8 dest,
long  destlen 
) [static]

Definition at line 524 of file cff_dict.c.

{
  long len = 0;
  int  i, type, id;

  if (de->count > 0) {
    id = de->id;
    if (dict_operator[id].argtype == CFF_TYPE_OFFSET ||
       dict_operator[id].argtype == CFF_TYPE_SZOFF) {
      type = CFF_TYPE_OFFSET;
    } else {
      type = CFF_TYPE_NUMBER;
    }
    for (i = 0; i < de->count; i++) {
      len += cff_dict_put_number(de->values[i],
                             dest+len,
                             destlen-len, type);
    }
    if (id >= 0 && id < CFF_LAST_DICT_OP1) {
      if (len + 1 > destlen)
       ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
      dest[len++] = id;
    } else if (id >= 0 && id < CFF_LAST_DICT_OP) {
      if (len + 2 > destlen)
       ERROR("in cff_dict_pack(): Buffer overflow");
      dest[len++] = 12;
      dest[len++] = id - CFF_LAST_DICT_OP1;
    } else {
      ERROR("%s: Invalid CFF DICT operator ID.", CFF_DEBUG_STR);
    }
  }

  return len;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

double arg_stack[CFF_DICT_STACK_LIMIT] [static]

Definition at line 102 of file cff_dict.c.

struct { ... } dict_operator[CFF_LAST_DICT_OP] [static]
int stack_top = 0 [static]

Definition at line 101 of file cff_dict.c.