Back to index

texmacs  1.0.7.15
Classes | Functions
tt_glyf.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  tt_glyph_desc
struct  tt_glyphs

Functions

struct tt_glyphstt_build_init (void)
void tt_build_finish (struct tt_glyphs *g)
USHORT tt_add_glyph (struct tt_glyphs *g, USHORT gid, USHORT new_gid)
USHORT tt_get_index (struct tt_glyphs *g, USHORT gid)
USHORT tt_find_glyph (struct tt_glyphs *g, USHORT gid)
int tt_build_tables (sfnt *sfont, struct tt_glyphs *g)
int tt_get_metrics (sfnt *sfont, struct tt_glyphs *g)

Class Documentation

struct tt_glyph_desc

Definition at line 26 of file tt_glyf.h.

Class Members
USHORT advh
USHORT advw
BYTE * data
USHORT gid
ULONG length
SHORT llx
SHORT lly
SHORT lsb
USHORT ogid
SHORT tsb
SHORT urx
SHORT ury
struct tt_glyphs

Definition at line 37 of file tt_glyf.h.

Collaboration diagram for tt_glyphs:
Class Members
USHORT default_advh
SHORT default_tsb
USHORT dw
USHORT emsize
struct tt_glyph_desc * gd
USHORT last_gid
USHORT max_glyphs
USHORT num_glyphs
unsigned char * used_slot

Function Documentation

USHORT tt_add_glyph ( struct tt_glyphs g,
USHORT  gid,
USHORT  new_gid 
)

Definition at line 95 of file tt_glyf.c.

{
  ASSERT(g);

  if (g->used_slot[new_gid/8] & (1 << (7 - (new_gid % 8)))) {
    WARN("Slot %u already used.", new_gid);
  } else {
    if (g->num_glyphs+1 >= NUM_GLYPH_LIMIT)
      ERROR("Too many glyphs.");

    if (g->num_glyphs >= g->max_glyphs) {
      g->max_glyphs += GLYPH_ARRAY_ALLOC_SIZE;
      g->gd = RENEW(g->gd, g->max_glyphs, struct tt_glyph_desc);
    }
    g->gd[g->num_glyphs].gid  = new_gid;
    g->gd[g->num_glyphs].ogid = gid;
    g->gd[g->num_glyphs].length = 0;
    g->gd[g->num_glyphs].data   = NULL;
    g->used_slot[new_gid/8] |= (1 << (7 - (new_gid % 8)));
    g->num_glyphs += 1;
  }

  if (new_gid > g->last_gid) {
    g->last_gid = new_gid;
  }

  return new_gid;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void tt_build_finish ( struct tt_glyphs g)

Definition at line 149 of file tt_glyf.c.

{
  if (g) {
    if (g->gd) {
      USHORT idx;
      for (idx = 0; idx < g->num_glyphs; idx++) {
       if (g->gd[idx].data)
         RELEASE(g->gd[idx].data);
      }
      RELEASE(g->gd);
    }
    if (g->used_slot)
      RELEASE(g->used_slot);
    RELEASE(g);
  }
}

Here is the caller graph for this function:

struct tt_glyphs* tt_build_init ( void  ) [read]

Definition at line 128 of file tt_glyf.c.

{
  struct tt_glyphs *g;

  g = NEW(1, struct tt_glyphs);

  g->num_glyphs  = 0;
  g->max_glyphs  = 0;
  g->last_gid    = 0;
  g->emsize      = 1;
  g->default_advh = 0;
  g->default_tsb  = 0;
  g->gd = NULL;
  g->used_slot = NEW(8192, unsigned char);
  memset(g->used_slot, 0, 8192);
  tt_add_glyph(g, 0, 0);

  return g;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tt_build_tables ( sfnt sfont,
struct tt_glyphs g 
)

Definition at line 200 of file tt_glyf.c.

{
  char  *hmtx_table_data = NULL, *loca_table_data = NULL;
  char  *glyf_table_data = NULL;
  ULONG  hmtx_table_size, loca_table_size, glyf_table_size;
  /* some information available from other TrueType table */
  struct tt_head_table *head = NULL;
  struct tt_hhea_table *hhea = NULL;
  struct tt_maxp_table *maxp = NULL;
  struct tt_longMetrics *hmtx, *vmtx = NULL;
  struct tt_os2__table  *os2;
  /* temp */
  ULONG  *location, offset;
  long    i;
  USHORT *w_stat; /* Estimate most frequently appeared width */

  ASSERT(g);

  if (sfont == NULL || sfont->stream == NULL)
    ERROR("File not opened.");

  if (sfont->type != SFNT_TYPE_TRUETYPE &&
      sfont->type != SFNT_TYPE_TTC &&
      sfont->type != SFNT_TYPE_DFONT)
    ERROR("Invalid font type");

  if (g->num_glyphs > NUM_GLYPH_LIMIT)
    ERROR("Too many glyphs.");

  /*
   * Read head, hhea, maxp, loca:
   *
   *   unitsPerEm       --> head
   *   numHMetrics      --> hhea
   *   indexToLocFormat --> head
   *   numGlyphs        --> maxp
   */
  head = tt_read_head_table(sfont);
  hhea = tt_read_hhea_table(sfont);
  maxp = tt_read_maxp_table(sfont);

  if (hhea->metricDataFormat != 0)
    ERROR("Unknown metricDataFormat.");

  g->emsize = head->unitsPerEm;

  sfnt_locate_table(sfont, "hmtx");
  hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numOfLongHorMetrics, hhea->numOfExSideBearings);

  os2 = tt_read_os2__table(sfont);
  g->default_advh = os2->sTypoAscender - os2->sTypoDescender;
  g->default_tsb  = g->default_advh - os2->sTypoAscender;

  if (sfnt_find_table_pos(sfont, "vmtx") > 0) {
    struct tt_vhea_table *vhea;
    vhea = tt_read_vhea_table(sfont);
    sfnt_locate_table(sfont, "vmtx");
    vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics, vhea->numOfExSideBearings);
    RELEASE(vhea);
  } else {
    vmtx = NULL;
  }

  sfnt_locate_table(sfont, "loca");
  location = NEW(maxp->numGlyphs + 1, ULONG);
  if (head->indexToLocFormat == 0) {
    for (i = 0; i <= maxp->numGlyphs; i++)
      location[i] = 2*((ULONG) sfnt_get_ushort(sfont));
  } else if (head->indexToLocFormat == 1) {
    for (i = 0; i <= maxp->numGlyphs; i++)
      location[i] = sfnt_get_ulong(sfont);
  } else {
    ERROR("Unknown IndexToLocFormat.");
  }

  w_stat = NEW(g->emsize+2, USHORT);
  memset(w_stat, 0, sizeof(USHORT)*(g->emsize+2));
  /*
   * Read glyf table.
   */
  offset = sfnt_locate_table(sfont, "glyf");
  /*
   * The num_glyphs may grow when composite glyph is found.
   * A component of glyph refered by a composite glyph is appended
   * to used_glyphs if it is not already registered in used_glyphs.
   * Glyph programs of composite glyphs are modified so that it
   * correctly refer to new gid of their components.
   */
  for (i = 0; i < NUM_GLYPH_LIMIT; i++) {
    USHORT gid;     /* old gid */
    ULONG  loc, len;
    BYTE  *p, *endptr;
    SHORT  number_of_contours;

    if (i >= g->num_glyphs) /* finished */
      break;

    gid = g->gd[i].ogid;
    if (gid >= maxp->numGlyphs)
      ERROR("Invalid glyph index (gid %u)", gid);

    loc = location[gid];
    len = location[gid+1] - loc;
    g->gd[i].advw = hmtx[gid].advance;
    g->gd[i].lsb  = hmtx[gid].sideBearing;
    if (vmtx) {
      g->gd[i].advh = vmtx[gid].advance;
      g->gd[i].tsb  = vmtx[gid].sideBearing;
    } else {
      g->gd[i].advh = g->default_advh;
      g->gd[i].tsb  = g->default_tsb;
    }
    g->gd[i].length = len;
    g->gd[i].data   = NULL;
    if (g->gd[i].advw <= g->emsize) {
      w_stat[g->gd[i].advw] += 1;
    } else {
      w_stat[g->emsize+1]   += 1; /* larger than em */
    }

    if (len == 0) { /* Does not contains any data. */
      continue;
    } else if (len < 10) {
      ERROR("Invalid TrueType glyph data (gid %u).", gid);
    }

    g->gd[i].data = p = NEW(len, BYTE);
    endptr = p + len;

    sfnt_seek_set(sfont, offset+loc);
    number_of_contours = sfnt_get_short(sfont);
    p += sfnt_put_short(p, number_of_contours);

    /* BoundingBox: FWord x 4 */
    g->gd[i].llx = sfnt_get_short(sfont);
    g->gd[i].lly = sfnt_get_short(sfont);
    g->gd[i].urx = sfnt_get_short(sfont);
    g->gd[i].ury = sfnt_get_short(sfont);
    /* _FIXME_ */
#if  1
    if (!vmtx) /* vertOriginY == sTypeAscender */
      g->gd[i].tsb = g->default_advh - g->default_tsb - g->gd[i].ury;
#endif
    p += sfnt_put_short(p, g->gd[i].llx);
    p += sfnt_put_short(p, g->gd[i].lly);
    p += sfnt_put_short(p, g->gd[i].urx);
    p += sfnt_put_short(p, g->gd[i].ury);

    /* Read evrything else. */
    sfnt_read(p, len - 10, sfont);
    /*
     * Fix GIDs of composite glyphs.
     */
    if (number_of_contours < 0) {
      USHORT flags, cgid, new_gid; /* flag, gid of a component */
      do {
       if (p >= endptr)
         ERROR("Invalid TrueType glyph data (gid %u): %u bytes", gid, len);
       /*
        * Flags and gid of component glyph are both USHORT.
        */
       flags = ((*p) << 8)| *(p+1);
       p += 2;
       cgid  = ((*p) << 8)| *(p+1);
       if (cgid >= maxp->numGlyphs) {
         ERROR("Invalid gid (%u > %u) in composite glyph %u.", cgid, maxp->numGlyphs, gid);
       }
       new_gid = tt_find_glyph(g, cgid);
       if (new_gid == 0) {
         new_gid = tt_add_glyph(g, cgid, find_empty_slot(g));
       }
       p += sfnt_put_ushort(p, new_gid);
       /*
        * Just skip remaining part.
        */
       p += (flags & ARG_1_AND_2_ARE_WORDS) ? 4 : 2;
       if (flags & WE_HAVE_A_SCALE) /* F2Dot14 */
         p += 2;
       else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) /* F2Dot14 x 2 */
         p += 4;
       else if (flags & WE_HAVE_A_TWO_BY_TWO) /* F2Dot14 x 4 */
         p += 8;
      } while (flags & MORE_COMPONENT);
      /*
       * TrueType instructions comes here:
       *  length_of_instruction (ushort)
       *  instruction (byte * length_of_instruction)
       */
    }
  }
  RELEASE(location);
  RELEASE(hmtx);
  if (vmtx)
    RELEASE(vmtx);

  {
    int max_count = -1;

    g->dw = g->gd[0].advw;
    for (i = 0; i < g->emsize + 1; i++) {
      if (w_stat[i] > max_count) {
       max_count = w_stat[i];
       g->dw = i;
      }
    }
  }
  RELEASE(w_stat);

  qsort(g->gd, g->num_glyphs, sizeof(struct tt_glyph_desc), glyf_cmp);
  {
    USHORT prev, last_advw;
    char  *p, *q;
    int    padlen, num_hm_known;

    glyf_table_size = 0UL;
    num_hm_known = 0;
    last_advw = g->gd[g->num_glyphs - 1].advw;
    for (i = g->num_glyphs - 1; i >= 0; i--) {
      padlen = (g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0;
      glyf_table_size += g->gd[i].length + padlen;
      if (!num_hm_known && last_advw != g->gd[i].advw) {
       hhea->numOfLongHorMetrics = g->gd[i].gid + 2;
       num_hm_known = 1;
      }
    }
    /* All advance widths are same. */
    if (!num_hm_known) {
      hhea->numOfLongHorMetrics = 1;
    }
    hmtx_table_size = hhea->numOfLongHorMetrics * 2 + (g->last_gid + 1) * 2;

    /*
     * Choosing short format does not always give good result
     * when compressed. Sometimes increases size.
     */
    if (glyf_table_size < 0x20000UL) {
      head->indexToLocFormat = 0;
      loca_table_size = (g->last_gid + 2)*2;
    } else {
      head->indexToLocFormat = 1;
      loca_table_size = (g->last_gid + 2)*4;
    }

    hmtx_table_data = p = NEW(hmtx_table_size, char);
    loca_table_data = q = NEW(loca_table_size, char);
    glyf_table_data = NEW(glyf_table_size, char);

    offset = 0UL; prev = 0;
    for (i = 0; i < g->num_glyphs; i++) {
      long gap, j;
      gap = (long) g->gd[i].gid - prev - 1;
      for (j = 1; j <= gap; j++) {
       if (prev + j == hhea->numOfLongHorMetrics - 1) {
         p += sfnt_put_ushort(p, last_advw);
       } else if (prev + j < hhea->numOfLongHorMetrics) {
         p += sfnt_put_ushort(p, 0);
       }
       p += sfnt_put_short (p, 0);
       if (head->indexToLocFormat == 0) {
         q += sfnt_put_ushort(q, (USHORT) (offset/2));
       } else {
         q += sfnt_put_ulong(q, offset);
       }
      }
      padlen = (g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0;
      if (g->gd[i].gid < hhea->numOfLongHorMetrics) {
       p += sfnt_put_ushort(p, g->gd[i].advw);
      }
      p += sfnt_put_short (p, g->gd[i].lsb);
      if (head->indexToLocFormat == 0) {
       q += sfnt_put_ushort(q, (USHORT) (offset/2));
      } else {
       q += sfnt_put_ulong(q, offset);
      }
      memset(glyf_table_data + offset, 0, g->gd[i].length + padlen);
      memcpy(glyf_table_data + offset, g->gd[i].data, g->gd[i].length);
      offset += g->gd[i].length + padlen;
      prev    = g->gd[i].gid;
      /* free data here since it consume much memory */
      RELEASE(g->gd[i].data);
      g->gd[i].length = 0; g->gd[i].data = NULL;
    }
    if (head->indexToLocFormat == 0) {
      q += sfnt_put_ushort(q, (USHORT) (offset/2));
    } else {
      q += sfnt_put_ulong(q, offset);
    }

    sfnt_set_table(sfont, "hmtx", (char *) hmtx_table_data, hmtx_table_size);
    sfnt_set_table(sfont, "loca", (char *) loca_table_data, loca_table_size);
    sfnt_set_table(sfont, "glyf", (char *) glyf_table_data, glyf_table_size);
  }

  head->checkSumAdjustment = 0;
  maxp->numGlyphs          = g->last_gid + 1;

  /* TODO */
  sfnt_set_table(sfont, "maxp", tt_pack_maxp_table(maxp), TT_MAXP_TABLE_SIZE);
  sfnt_set_table(sfont, "hhea", tt_pack_hhea_table(hhea), TT_HHEA_TABLE_SIZE);
  sfnt_set_table(sfont, "head", tt_pack_head_table(head), TT_HEAD_TABLE_SIZE);
  RELEASE(maxp);
  RELEASE(hhea);
  RELEASE(head);
  RELEASE(os2);

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

USHORT tt_find_glyph ( struct tt_glyphs g,
USHORT  gid 
)

Definition at line 61 of file tt_glyf.c.

{
  USHORT idx, new_gid = 0;

  ASSERT(g);

  for (idx = 0; idx < g->num_glyphs; idx++) {
    if (gid == g->gd[idx].ogid) {
      new_gid = g->gd[idx].gid;
      break;
    }
  }

  return new_gid;
}

Here is the caller graph for this function:

USHORT tt_get_index ( struct tt_glyphs g,
USHORT  gid 
)

Definition at line 78 of file tt_glyf.c.

{
  USHORT idx;

  ASSERT(g);

  for (idx = 0; idx < g->num_glyphs; idx++) {
    if (gid == g->gd[idx].gid)
      break;
  }
  if (idx == g->num_glyphs)
    idx = 0;

  return idx;
}

Here is the caller graph for this function:

int tt_get_metrics ( sfnt sfont,
struct tt_glyphs g 
)

Definition at line 509 of file tt_glyf.c.

{
  struct tt_head_table *head = NULL;
  struct tt_hhea_table *hhea = NULL;
  struct tt_maxp_table *maxp = NULL;
  struct tt_longMetrics *hmtx, *vmtx = NULL;
  struct tt_os2__table  *os2;
  /* temp */
  ULONG  *location, offset;
  long    i;
  USHORT *w_stat;

  ASSERT(g);

  if (sfont == NULL || sfont->stream == NULL)
    ERROR("File not opened.");

  if (sfont->type != SFNT_TYPE_TRUETYPE &&
      sfont->type != SFNT_TYPE_TTC &&
      sfont->type != SFNT_TYPE_DFONT)
    ERROR("Invalid font type");

  /*
   * Read head, hhea, maxp, loca:
   *
   *   unitsPerEm       --> head
   *   numHMetrics      --> hhea
   *   indexToLocFormat --> head
   *   numGlyphs        --> maxp
   */
  head = tt_read_head_table(sfont);
  hhea = tt_read_hhea_table(sfont);
  maxp = tt_read_maxp_table(sfont);

  if (hhea->metricDataFormat != 0)
    ERROR("Unknown metricDataFormat.");

  g->emsize = head->unitsPerEm;

  sfnt_locate_table(sfont, "hmtx");
  hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numOfLongHorMetrics, hhea->numOfExSideBearings);

  os2 = tt_read_os2__table(sfont);
  g->default_advh = os2->sTypoAscender - os2->sTypoDescender;
  g->default_tsb  = g->default_advh - os2->sTypoAscender;

  if (sfnt_find_table_pos(sfont, "vmtx") > 0) {
    struct tt_vhea_table *vhea;
    vhea = tt_read_vhea_table(sfont);
    sfnt_locate_table(sfont, "vmtx");
    vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics, vhea->numOfExSideBearings);
    RELEASE(vhea);
  } else {
    vmtx = NULL;
  }

  sfnt_locate_table(sfont, "loca");
  location = NEW(maxp->numGlyphs + 1, ULONG);
  if (head->indexToLocFormat == 0) {
    for (i = 0; i <= maxp->numGlyphs; i++)
      location[i] = 2*((ULONG) sfnt_get_ushort(sfont));
  } else if (head->indexToLocFormat == 1) {
    for (i = 0; i <= maxp->numGlyphs; i++)
      location[i] = sfnt_get_ulong(sfont);
  } else {
    ERROR("Unknown IndexToLocFormat.");
  }

  w_stat = NEW(g->emsize+2, USHORT);
  memset(w_stat, 0, sizeof(USHORT)*(g->emsize+2));
  /*
   * Read glyf table.
   */
  offset = sfnt_locate_table(sfont, "glyf");
  for (i = 0; i < g->num_glyphs; i++) {
    USHORT gid;     /* old gid */
    ULONG  loc, len;
    SHORT  number_of_contours;

    gid = g->gd[i].ogid;
    if (gid >= maxp->numGlyphs)
      ERROR("Invalid glyph index (gid %u)", gid);

    loc = location[gid];
    len = location[gid+1] - loc;
    g->gd[i].advw = hmtx[gid].advance;
    g->gd[i].lsb  = hmtx[gid].sideBearing;
    if (vmtx) {
      g->gd[i].advh = vmtx[gid].advance;
      g->gd[i].tsb  = vmtx[gid].sideBearing;
    } else {
      g->gd[i].advh = g->default_advh;
      g->gd[i].tsb  = g->default_tsb;
    }
    g->gd[i].length = len;
    g->gd[i].data   = NULL;

    if (g->gd[i].advw <= g->emsize) {
      w_stat[g->gd[i].advw] += 1;
    } else {
      w_stat[g->emsize+1]   += 1; /* larger than em */
    }

    if (len == 0) { /* Does not contains any data. */
      continue;
    } else if (len < 10) {
      ERROR("Invalid TrueType glyph data (gid %u).", gid);
    }

    sfnt_seek_set(sfont, offset+loc);
    number_of_contours = sfnt_get_short(sfont);

    /* BoundingBox: FWord x 4 */
    g->gd[i].llx = sfnt_get_short(sfont);
    g->gd[i].lly = sfnt_get_short(sfont);
    g->gd[i].urx = sfnt_get_short(sfont);
    g->gd[i].ury = sfnt_get_short(sfont);
    /* _FIXME_ */
#if  1
    if (!vmtx) /* vertOriginY == sTypeAscender */
      g->gd[i].tsb = g->default_advh - g->default_tsb - g->gd[i].ury;
#endif
  }
  RELEASE(location);
  RELEASE(hmtx);
  RELEASE(maxp);
  RELEASE(hhea);
  RELEASE(head);
  RELEASE(os2);

  if (vmtx)
    RELEASE(vmtx);

  {
    int max_count = -1;

    g->dw = g->gd[0].advw;
    for (i = 0; i < g->emsize + 1; i++) {
      if (w_stat[i] > max_count) {
       max_count = w_stat[i];
       g->dw = i;
      }
    }
  }
  RELEASE(w_stat);


  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function: