Back to index

texmacs  1.0.7.15
Classes | Defines | Typedefs | Functions | Variables
tt_gsub.c File Reference
#include "system.h"
#include "error.h"
#include "mem.h"
#include "mfileio.h"
#include "sfnt.h"
#include "otl_opt.h"
#include "tt_gsub.h"

Go to the source code of this file.

Classes

struct  clt_record
struct  clt_range
struct  clt_record_list
struct  clt_number_list
struct  clt_coverage
struct  otl_gsub_header
struct  otl_gsub_single1
struct  otl_gsub_single2
struct  otl_gsub_altset
struct  otl_gsub_alternate1
struct  otl_gsub_ligtab
struct  otl_gsub_ligset
struct  otl_gsub_ligature1
struct  otl_gsub_subtab
struct  clt_script_table
struct  clt_langsys_table
struct  clt_feature_table
struct  clt_lookup_table
struct  otl_gsub_tab
struct  otl_gsub
union  otl_gsub_subtab.table

Defines

#define VERBOSE_LEVEL_MIN   0
#define SET_BIT(b, p)
#define BIT_SET(b, p)   (((b)[(p)/8]) & (1 << (7-((p)%8))))
#define GSUB_LIST_MAX   32

Typedefs

typedef USHORT Offset
typedef USHORT GlyphID

Functions

void otl_gsub_set_verbose (void)
static long clt_read_record (struct clt_record *rec, sfnt *sfont)
static long clt_read_range (struct clt_range *rec, sfnt *sfont)
static long clt_read_record_list (struct clt_record_list *list, sfnt *sfont)
static void clt_release_record_list (struct clt_record_list *list)
static long clt_read_number_list (struct clt_number_list *list, sfnt *sfont)
static void clt_release_number_list (struct clt_number_list *list)
static long clt_read_script_table (struct clt_script_table *tab, sfnt *sfont)
static void clt_release_script_table (struct clt_script_table *tab)
static long clt_read_langsys_table (struct clt_langsys_table *tab, sfnt *sfont)
static void clt_release_langsys_table (struct clt_langsys_table *tab)
static long clt_read_feature_table (struct clt_feature_table *tab, sfnt *sfont)
static void clt_release_feature_table (struct clt_feature_table *tab)
static long clt_read_lookup_table (struct clt_lookup_table *tab, sfnt *sfont)
static void clt_release_lookup_table (struct clt_lookup_table *tab)
static long clt_read_coverage (struct clt_coverage *cov, sfnt *sfont)
static void clt_release_coverage (struct clt_coverage *cov)
static long clt_lookup_coverage (struct clt_coverage *cov, USHORT gid)
static long otl_gsub_read_single (struct otl_gsub_subtab *subtab, sfnt *sfont)
static long otl_gsub_read_alternate (struct otl_gsub_subtab *subtab, sfnt *sfont)
static long otl_gsub_read_ligature (struct otl_gsub_subtab *subtab, sfnt *sfont)
static void otl_gsub_release_single (struct otl_gsub_subtab *subtab)
static void otl_gsub_release_ligature (struct otl_gsub_subtab *subtab)
static void otl_gsub_release_alternate (struct otl_gsub_subtab *subtab)
static long otl_gsub_read_header (struct otl_gsub_header *head, sfnt *sfont)
static int otl_gsub_read_feat (struct otl_gsub_tab *gsub, sfnt *sfont)
static int otl_gsub_apply_single (struct otl_gsub_subtab *subtab, USHORT *gid)
static int otl_gsub_apply_alternate (struct otl_gsub_subtab *subtab, USHORT alt_idx, USHORT *gid)
static int glyph_seq_cmp (GlyphID *glyph_seq0, USHORT n_glyphs0, GlyphID *glyph_seq1, USHORT n_glyphs1)
static int otl_gsub_apply_ligature (struct otl_gsub_subtab *subtab, USHORT *gid_in, USHORT num_gids, USHORT *gid_out)
otl_gsubotl_gsub_new (void)
int otl_gsub_add_feat (otl_gsub *gsub_list, const char *script, const char *language, const char *feature, sfnt *sfont)
void otl_gsub_release (otl_gsub *gsub_list)
int otl_gsub_apply (otl_gsub *gsub_list, USHORT *gid)
int otl_gsub_apply_alt (otl_gsub *gsub_list, USHORT alt_idx, USHORT *gid)
int otl_gsub_apply_lig (otl_gsub *gsub_list, USHORT *gid_in, USHORT num_gids, USHORT *gid_out)
int otl_gsub_select (otl_gsub *gsub_list, const char *script, const char *language, const char *feature)

Variables

static int verbose = 0

Class Documentation

struct clt_record

Definition at line 51 of file tt_gsub.c.

Class Members
Offset offset
char tag
struct clt_range

Definition at line 59 of file tt_gsub.c.

Class Members
GlyphID End
GlyphID Start
USHORT StartCoverageIndex
struct clt_record_list

Definition at line 99 of file tt_gsub.c.

Collaboration diagram for clt_record_list:
Class Members
USHORT count
struct clt_record * record
struct clt_number_list

Definition at line 106 of file tt_gsub.c.

Class Members
USHORT count
USHORT * value
struct clt_coverage

Definition at line 183 of file tt_gsub.c.

Collaboration diagram for clt_coverage:
Class Members
USHORT count
USHORT format
GlyphID * list
struct clt_range * range
struct otl_gsub_header

Definition at line 194 of file tt_gsub.c.

Class Members
Offset FeatureList
Offset LookupList
Offset ScriptList
Fixed version
struct otl_gsub_single1

Definition at line 203 of file tt_gsub.c.

Class Members
SHORT DeltaGlyphID
struct otl_gsub_single2

Definition at line 211 of file tt_gsub.c.

Class Members
USHORT GlyphCount
GlyphID * Substitute
struct otl_gsub_altset

Definition at line 220 of file tt_gsub.c.

Class Members
GlyphID * Alternate
USHORT GlyphCount
struct otl_gsub_alternate1

Definition at line 228 of file tt_gsub.c.

Collaboration diagram for otl_gsub_alternate1:
Class Members
struct otl_gsub_altset * AlternateSet
USHORT AlternateSetCount
struct otl_gsub_ligtab

Definition at line 237 of file tt_gsub.c.

Class Members
USHORT CompCount
GlyphID * Component
GlyphID LigGlyph
struct otl_gsub_ligset

Definition at line 247 of file tt_gsub.c.

Collaboration diagram for otl_gsub_ligset:
Class Members
struct otl_gsub_ligtab * Ligature
USHORT LigatureCount
struct otl_gsub_ligature1

Definition at line 253 of file tt_gsub.c.

Collaboration diagram for otl_gsub_ligature1:
Class Members
struct otl_gsub_ligset * LigatureSet
USHORT LigSetCount
struct otl_gsub_subtab

Definition at line 262 of file tt_gsub.c.

Class Members
USHORT LookupType
USHORT SubstFormat
union otl_gsub_subtab table
struct clt_script_table

Definition at line 276 of file tt_gsub.c.

Class Members
Offset DefaultLangSys
struct clt_langsys_table

Definition at line 304 of file tt_gsub.c.

Class Members
Offset LookupOrder
USHORT ReqFeatureIndex
struct clt_feature_table

Definition at line 337 of file tt_gsub.c.

Class Members
Offset FeatureParams
struct clt_lookup_table

Definition at line 368 of file tt_gsub.c.

Class Members
USHORT LookupFlag
USHORT LookupType
struct otl_gsub_tab

Definition at line 819 of file tt_gsub.c.

Collaboration diagram for otl_gsub_tab:
Class Members
char * feature
char * language
int num_subtables
char * script
struct otl_gsub_subtab * subtables
struct otl_gsub

Definition at line 1270 of file tt_gsub.c.

Class Members
int num_gsubs
int select
union otl_gsub_subtab.table

Definition at line 267 of file tt_gsub.c.

Class Members
struct otl_gsub_alternate1 * alternate1
struct otl_gsub_ligature1 * ligature1
struct otl_gsub_single1 * single1
struct otl_gsub_single2 * single2

Define Documentation

#define BIT_SET (   b,
 
)    (((b)[(p)/8]) & (1 << (7-((p)%8))))
#define GSUB_LIST_MAX   32

Definition at line 1269 of file tt_gsub.c.

#define SET_BIT (   b,
 
)
Value:
do {\
  (b)[(p)/8] |= (1<<(7-((p) % 8)));\
} while (0)
#define VERBOSE_LEVEL_MIN   0

Definition at line 38 of file tt_gsub.c.


Typedef Documentation

typedef USHORT GlyphID

Definition at line 47 of file tt_gsub.c.

typedef USHORT Offset

Definition at line 46 of file tt_gsub.c.


Function Documentation

static long clt_lookup_coverage ( struct clt_coverage cov,
USHORT  gid 
) [static]

Definition at line 464 of file tt_gsub.c.

{
  long i;

  ASSERT(cov);

  switch (cov->format) {
  case 1: /* list */
    for (i = 0; i < cov->count; i++) {
      if (cov->list[i] > gid) {
        break;
      } else if (cov->list[i] == gid) {
        return i; /* found */
      }
    }
    break;
  case 2: /* range */
    for (i = 0; i < cov->count; i++) {
      if (gid < cov->range[i].Start) {
        break;
      } else if (gid <= cov->range[i].End) { /* found */
        return (cov->range[i].StartCoverageIndex +
                gid - cov->range[i].Start);
      }
    }
    break;
  default:
    ERROR("Unknown coverage format");
  }

  return -1; /* not found */
}

Here is the call graph for this function:

Here is the caller graph for this function:

static long clt_read_coverage ( struct clt_coverage cov,
sfnt sfont 
) [static]

Definition at line 399 of file tt_gsub.c.

{
  long len, i;

  ASSERT(cov && sfont);

  cov->format = sfnt_get_ushort(sfont);
  cov->count  = sfnt_get_ushort(sfont);
  len = 4;

  switch (cov->format) {
  case 1: /* list */
    if (cov->count == 0)
      cov->list = NULL;
    else {
      cov->list = NEW(cov->count, USHORT);
      for (i = 0; i < cov->count; i++) {
        cov->list[i] = sfnt_get_ushort(sfont);
      }
    }
    cov->range = NULL;
    len += 2 * cov->count;
    break;
  case 2: /* range */
    if (cov->count == 0)
      cov->range = NULL;
    else {
      cov->range = NEW(cov->count, struct clt_range);
      for (i = 0; i < cov->count; i++) {
        len += clt_read_range(&(cov->range[i]), sfont);
      }
    }
    cov->list = NULL;
    break;
  default:
    ERROR("Unknown coverage format");
  }

  return len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static long clt_read_feature_table ( struct clt_feature_table tab,
sfnt sfont 
) [static]

Definition at line 344 of file tt_gsub.c.

{
  long len;

  ASSERT(tab && sfont);

  tab->FeatureParams = sfnt_get_ushort(sfont);
  len  = 2;
  len += clt_read_number_list(&tab->LookupListIndex, sfont);

  return len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static long clt_read_langsys_table ( struct clt_langsys_table tab,
sfnt sfont 
) [static]

Definition at line 314 of file tt_gsub.c.

{
  long len;

  ASSERT(tab && sfont);

  tab->LookupOrder     = sfnt_get_ushort(sfont);
  tab->ReqFeatureIndex = sfnt_get_ushort(sfont);
  len  = 4;
  len += clt_read_number_list(&tab->FeatureIndex, sfont);

  return len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static long clt_read_lookup_table ( struct clt_lookup_table tab,
sfnt sfont 
) [static]

Definition at line 377 of file tt_gsub.c.

{
  long len;

  ASSERT(tab && sfont);

  tab->LookupType = sfnt_get_ushort(sfont);
  tab->LookupFlag = sfnt_get_ushort(sfont);
  len  = 4;
  len += clt_read_number_list(&tab->SubTableList, sfont);

  return len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static long clt_read_number_list ( struct clt_number_list list,
sfnt sfont 
) [static]

Definition at line 146 of file tt_gsub.c.

{
  long i;

  ASSERT(list && sfont);

  list->count = sfnt_get_ushort(sfont);

  if (list->count == 0)
    list->value = NULL;
  else {
    list->value = NEW(list->count, USHORT);
    for (i = 0; i < list->count; i++) {
      list->value[i] = sfnt_get_ushort(sfont);
    }
  }

  return (2 + 2 * list->count);
}

Here is the caller graph for this function:

static long clt_read_range ( struct clt_range rec,
sfnt sfont 
) [static]

Definition at line 83 of file tt_gsub.c.

{
  ASSERT(rec && sfont);

  rec->Start = sfnt_get_ushort(sfont);
  rec->End   = sfnt_get_ushort(sfont);
  rec->StartCoverageIndex = sfnt_get_ushort(sfont);

  return 6;
}

Here is the caller graph for this function:

static long clt_read_record ( struct clt_record rec,
sfnt sfont 
) [static]

Definition at line 67 of file tt_gsub.c.

{
  int i;

  ASSERT(rec && sfont);

  for (i = 0; i < 4; i++) {
    rec->tag[i] = sfnt_get_char(sfont);
  }
  rec->tag[4] = '\0';
  rec->offset = sfnt_get_ushort(sfont);

  return 6;
}

Here is the caller graph for this function:

static long clt_read_record_list ( struct clt_record_list list,
sfnt sfont 
) [static]

Definition at line 113 of file tt_gsub.c.

{
  long len, i;

  ASSERT(list && sfont);

  list->count = sfnt_get_ushort(sfont);
  len = 2;

  if (list->count == 0)
    list->record = NULL;
  else {
    list->record = NEW(list->count, struct clt_record);
    for (i = 0; i < list->count; i++) {
      len += clt_read_record(&(list->record[i]), sfont);
    }
  }

  return len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static long clt_read_script_table ( struct clt_script_table tab,
sfnt sfont 
) [static]

Definition at line 283 of file tt_gsub.c.

{
  long len;

  ASSERT(tab && sfont);

  tab->DefaultLangSys = sfnt_get_ushort(sfont);
  len  = 2;
  len += clt_read_record_list(&tab->LangSysRecord, sfont);

  return len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void clt_release_coverage ( struct clt_coverage cov) [static]

Definition at line 441 of file tt_gsub.c.

{
  if (cov) {
    switch (cov->format) {
    case 1: /* list */
      if (cov->list)
        RELEASE(cov->list);
      cov->list = NULL;
      break;
    case 2: /* range */
      if (cov->range)
        RELEASE(cov->range);
      cov->range = NULL;
      break;
    default:
      ERROR("Unknown coverage format");
    }
  }
  cov->count = 0;
}

Here is the caller graph for this function:

static void clt_release_feature_table ( struct clt_feature_table tab) [static]

Definition at line 358 of file tt_gsub.c.

{
  if (tab)
    clt_release_number_list(&tab->LookupListIndex);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void clt_release_langsys_table ( struct clt_langsys_table tab) [static]

Definition at line 329 of file tt_gsub.c.

{
  if (tab)
    clt_release_number_list(&tab->FeatureIndex);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void clt_release_lookup_table ( struct clt_lookup_table tab) [static]

Definition at line 392 of file tt_gsub.c.

{
  if (tab)
    clt_release_number_list(&tab->SubTableList);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void clt_release_number_list ( struct clt_number_list list) [static]

Definition at line 167 of file tt_gsub.c.

{
  if (list) {
    if (list->value)
      RELEASE(list->value);
    list->value = NULL;
    list->count = 0;
  }
}

Here is the caller graph for this function:

static void clt_release_record_list ( struct clt_record_list list) [static]

Definition at line 135 of file tt_gsub.c.

{
  if (list) {
    if (list->record)
      RELEASE(list->record);
    list->record = NULL;
    list->count  = 0;
  }
}

Here is the caller graph for this function:

static void clt_release_script_table ( struct clt_script_table tab) [static]

Definition at line 297 of file tt_gsub.c.

{
  if (tab)
    clt_release_record_list(&tab->LangSysRecord);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int glyph_seq_cmp ( GlyphID glyph_seq0,
USHORT  n_glyphs0,
GlyphID glyph_seq1,
USHORT  n_glyphs1 
) [static]

Definition at line 1217 of file tt_gsub.c.

{
  USHORT i;

  if (n_glyphs0 != n_glyphs1)
    return n_glyphs0 - n_glyphs1;

  for (i = 0; i < n_glyphs0; i++) {
    if (glyph_seq0[i] != glyph_seq1[i])
      return glyph_seq0[i] - glyph_seq1[i];
  }

  return 0;
}

Here is the caller graph for this function:

int otl_gsub_add_feat ( otl_gsub gsub_list,
const char *  script,
const char *  language,
const char *  feature,
sfnt sfont 
)

Definition at line 1290 of file tt_gsub.c.

{
  int    retval = -1;
  int    i;
  struct otl_gsub_tab *gsub;

  if (gsub_list->num_gsubs > GSUB_LIST_MAX) {
    ERROR("Too many GSUB features...");
    return -1;
  }
  for (i = 0; i < gsub_list->num_gsubs; i++) {
    gsub = &(gsub_list->gsubs[i]);
    if (!strcmp(script,   gsub->script)   &&
        !strcmp(language, gsub->language) &&
        !strcmp(feature,  gsub->feature)) {
      gsub_list->select = i;
      return 0;
    }
  }
  gsub = &gsub_list->gsubs[i];

  gsub->script   = NEW(strlen(script)  +1, char);
  strcpy(gsub->script,   script);
  gsub->language = NEW(strlen(language)+1, char);
  strcpy(gsub->language, language);
  gsub->feature  = NEW(strlen(feature) +1, char);
  strcpy(gsub->feature,  feature);

  if(verbose > VERBOSE_LEVEL_MIN) {
    MESG("\n");
    MESG("otl_gsub>> Reading \"%s.%s.%s\"...\n", script, language, feature);
  }

  retval = otl_gsub_read_feat(gsub, sfont);
  if (retval >= 0) {
    gsub_list->select = i;
    gsub_list->num_gsubs++;
  } else {
    if(verbose > VERBOSE_LEVEL_MIN) {
      MESG("otl_gsub>> Failed\n");
    }
    RELEASE(gsub->script);
    RELEASE(gsub->language);
    RELEASE(gsub->feature);
  }
  
  return retval;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int otl_gsub_apply ( otl_gsub gsub_list,
USHORT gid 
)

Definition at line 1387 of file tt_gsub.c.

{
  int    retval = -1;
  struct otl_gsub_tab    *gsub;
  struct otl_gsub_subtab *subtab;
  int    i, j;

  if (!gsub_list || !gid)
    return retval;

  i = gsub_list->select;
  if (i < 0 || i >= gsub_list->num_gsubs) {
    ERROR("GSUB not selected...");
    return -1;
  }
  gsub = &(gsub_list->gsubs[i]);

  for (j = 0;
       retval < 0 && j < gsub->num_subtables; j++) {
    subtab = &(gsub->subtables[j]);
    switch ((int) subtab->LookupType){
    case OTL_GSUB_TYPE_SINGLE:
      retval = otl_gsub_apply_single(subtab, gid);
      break;
    default:
      break;
    }
  }

  return retval;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int otl_gsub_apply_alt ( otl_gsub gsub_list,
USHORT  alt_idx,
USHORT gid 
)

Definition at line 1420 of file tt_gsub.c.

{
  int    retval = -1;
  struct otl_gsub_tab    *gsub;
  struct otl_gsub_subtab *subtab;
  int    i, j;

  if (!gsub_list || !gid)
    return retval;

  i = gsub_list->select;
  if (i < 0 || i >= gsub_list->num_gsubs) {
    ERROR("GSUB not selected...");
    return -1;
  }
  gsub = &(gsub_list->gsubs[i]);

  for (j = 0;
       retval < 0 && j < gsub->num_subtables; j++) {
    subtab = &(gsub->subtables[j]);
    switch ((int) subtab->LookupType){
    case OTL_GSUB_TYPE_ALTERNATE:
      retval = otl_gsub_apply_alternate(subtab, alt_idx, gid);
      break;
    default:
      break;
    }
  }

  return retval;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int otl_gsub_apply_alternate ( struct otl_gsub_subtab subtab,
USHORT  alt_idx,
USHORT gid 
) [static]

Definition at line 1186 of file tt_gsub.c.

{
  long  idx;

  ASSERT(subtab && gid);

  if (subtab->SubstFormat == 1) {
    struct otl_gsub_alternate1 *data;

    data = subtab->table.alternate1;
    idx  = clt_lookup_coverage(&data->coverage, *gid);
    if (idx < 0 || idx >= data->AlternateSetCount)
      return  -1;
    else {
      struct otl_gsub_altset *altset;
      altset = &(data->AlternateSet[idx]);
      if (alt_idx >= altset->GlyphCount)
        return  -1;
      else {
        *gid = altset->Alternate[alt_idx];
        return  0;
      }
    }
  }

  return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int otl_gsub_apply_lig ( otl_gsub gsub_list,
USHORT gid_in,
USHORT  num_gids,
USHORT gid_out 
)

Definition at line 1453 of file tt_gsub.c.

{
  int    retval = -1;
  struct otl_gsub_tab    *gsub;
  struct otl_gsub_subtab *subtab;
  int    i, j;

  if (!gsub_list || !gid_out)
    return retval;

  i = gsub_list->select;
  if (i < 0 || i >= gsub_list->num_gsubs) {
    ERROR("GSUB not selected...");
    return -1;
  }
  gsub = &(gsub_list->gsubs[i]);

  for (j = 0;
       retval < 0 && j < gsub->num_subtables; j++) {
    subtab = &(gsub->subtables[j]);
    switch ((int) subtab->LookupType){
    case OTL_GSUB_TYPE_LIGATURE:
      retval = otl_gsub_apply_ligature(subtab,
                                       gid_in, num_gids, gid_out);
      break;
    default:
      break;
    }
  }

  return retval;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int otl_gsub_apply_ligature ( struct otl_gsub_subtab subtab,
USHORT gid_in,
USHORT  num_gids,
USHORT gid_out 
) [static]

Definition at line 1234 of file tt_gsub.c.

{
  long idx;

  ASSERT(subtab && gid_out);

  if (!gid_in || num_gids < 1)
    return -1;

  if (subtab->SubstFormat == 1) {
    struct otl_gsub_ligature1 *data;

    data = subtab->table.ligature1;
    idx  = clt_lookup_coverage(&data->coverage, gid_in[0]);
    if (idx >= 0 && idx < data->LigSetCount) {
      struct otl_gsub_ligset *ligset;
      USHORT j;

      ligset = &(data->LigatureSet[idx]);
      for (j = 0; j < ligset->LigatureCount; j++) {
        if (!glyph_seq_cmp(&gid_in[1], num_gids - 1,
                           ligset->Ligature[j].Component,
                           ligset->Ligature[j].CompCount - 1)) {
          *gid_out = ligset->Ligature[j].LigGlyph;
          return 0; /* found */
        }
      }
    }
  }

  return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int otl_gsub_apply_single ( struct otl_gsub_subtab subtab,
USHORT gid 
) [static]

Definition at line 1155 of file tt_gsub.c.

{
  long idx;

  ASSERT(subtab && gid);

  if (subtab->SubstFormat == 1) {
    struct otl_gsub_single1 *data;

    data = (subtab->table).single1;
    idx  = clt_lookup_coverage(&data->coverage, *gid);
    if (idx >= 0) {
      *gid += data->DeltaGlyphID;
      return 0; /* found */
    }
  } else if (subtab->SubstFormat == 2) {
    struct otl_gsub_single2 *data;

    data = (subtab->table).single2;
    idx  = clt_lookup_coverage(&data->coverage, *gid);
    if (idx >= 0 &&
        idx < data->GlyphCount) {
      *gid = (data->Substitute)[idx];
      return 0; /* found */
    }
  }

  return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

otl_gsub* otl_gsub_new ( void  )

Definition at line 1278 of file tt_gsub.c.

{
  struct otl_gsub *gsub_list;

  gsub_list = NEW(1, struct otl_gsub);
  gsub_list->num_gsubs = 0;
  gsub_list->select    = -1;

  return (otl_gsub *) gsub_list;
}

Here is the caller graph for this function:

static long otl_gsub_read_alternate ( struct otl_gsub_subtab subtab,
sfnt sfont 
) [static]

Definition at line 554 of file tt_gsub.c.

{
  long   len;
  USHORT i, j;
  ULONG  offset;     /* not Offset which is USHORT */
  Offset cov_offset; /* subtable offset, offset to Coverage table */
  struct clt_number_list      altset_offsets;
  struct otl_gsub_alternate1 *data;

  ASSERT(subtab && sfont);

  offset = tell_position(sfont->stream);

  subtab->LookupType  = OTL_GSUB_TYPE_ALTERNATE;
  subtab->SubstFormat = sfnt_get_ushort(sfont); /* Must be 1 */
  if (subtab->SubstFormat != 1) {
    WARN("Unknown GSUB SubstFormat for Alternate: %u",
         subtab->SubstFormat);
    return -1;
  }

  len  = 2;
  subtab->table.alternate1 =
    data = NEW(1, struct otl_gsub_alternate1);

  cov_offset        = sfnt_get_ushort(sfont);
  len += 2;
  len += clt_read_number_list(&altset_offsets, sfont);
  data->AlternateSetCount = altset_offsets.count;
  if (data->AlternateSetCount == 0) {
    data->AlternateSet    = NULL;
    data->coverage.count  = 0;
    data->coverage.format = 0;
    data->coverage.list   = NULL;
    return  len;
  }
  data->AlternateSet = NEW(data->AlternateSetCount,
                           struct otl_gsub_altset);
  for (i = 0; i < data->AlternateSetCount; i++) {
    struct otl_gsub_altset *altset;
    ULONG  altset_offset;

    altset = &(data->AlternateSet[i]);

    altset_offset = offset + altset_offsets.value[i];
    sfnt_seek_set(sfont, altset_offset);
    altset->GlyphCount = sfnt_get_ushort(sfont);
    len += 2;
    if (altset->GlyphCount == 0) {
      altset->Alternate = NULL;
      break;
    }
    altset->Alternate = NEW(altset->GlyphCount, GlyphID);
    for (j = 0; j < altset->GlyphCount; j++) {
      altset->Alternate[j] = sfnt_get_ushort(sfont);
      len += 2;
    }
  }
  clt_release_number_list(&altset_offsets);

  sfnt_seek_set(sfont, offset + cov_offset);
  len += clt_read_coverage(&data->coverage, sfont);

  return  len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int otl_gsub_read_feat ( struct otl_gsub_tab gsub,
sfnt sfont 
) [static]

Definition at line 831 of file tt_gsub.c.

{
  long   feat_idx, script_idx;
  ULONG  gsub_offset, offset;
  struct otl_gsub_header  head;
  struct otl_gsub_subtab *subtab = NULL;
  USHORT num_subtabs = 0;
  unsigned char feat_bits[8192];
  struct clt_record_list feature_list;
  struct clt_record_list script_list;
  struct clt_number_list lookup_list ;
  otl_opt *script, *language, *feature;

  ASSERT(gsub && sfont);

  gsub_offset = sfnt_find_table_pos(sfont, "GSUB");
  if (gsub_offset == 0)
    return -1; /* not found */

  script   = otl_new_opt();
  otl_parse_optstring(script,   gsub->script);
  language = otl_new_opt();
  otl_parse_optstring(language, gsub->language);
  feature  = otl_new_opt();
  otl_parse_optstring(feature,  gsub->feature);

  memset(feat_bits, 0, 8192);

  /* GSUB header */
  sfnt_seek_set(sfont, gsub_offset);
  otl_gsub_read_header(&head, sfont);

  /* Script */
  offset = gsub_offset + head.ScriptList;
  sfnt_seek_set(sfont, offset);
  clt_read_record_list(&script_list, sfont);

#define SET_BIT(b,p) do {\
  (b)[(p)/8] |= (1<<(7-((p) % 8)));\
} while (0)
#define BIT_SET(b,p) (((b)[(p)/8]) & (1 << (7-((p)%8))))

  for (script_idx = 0;
       script_idx < script_list.count; script_idx++) {
    if (otl_match_optrule(script,
                          script_list.record[script_idx].tag)) {
      struct clt_script_table script_tab;
      long   langsys_idx;

      offset = gsub_offset +
        head.ScriptList + script_list.record[script_idx].offset;
      sfnt_seek_set(sfont, offset);
      clt_read_script_table(&script_tab, sfont);

      if (otl_match_optrule(language, "dflt") &&
          script_tab.DefaultLangSys != 0) { 
        struct clt_langsys_table langsys_tab;

        if(verbose > VERBOSE_LEVEL_MIN) {
          MESG("otl_gsub>> OTL script-language enabled: %c%c%c%c.dflt\n",
               script_list.record[script_idx].tag[0],
               script_list.record[script_idx].tag[1],
               script_list.record[script_idx].tag[2],
               script_list.record[script_idx].tag[3]);
        }

        sfnt_seek_set(sfont, offset + script_tab.DefaultLangSys);
        clt_read_langsys_table(&langsys_tab, sfont);
        if (otl_match_optrule(feature, "____") && /* _FIXME_ */
            langsys_tab.ReqFeatureIndex != 0xFFFF)
          SET_BIT(feat_bits, langsys_tab.ReqFeatureIndex);
        for (feat_idx = 0;
             feat_idx < langsys_tab.FeatureIndex.count;
             feat_idx++) {
          SET_BIT(feat_bits,
                  langsys_tab.FeatureIndex.value[feat_idx]);
        }
        clt_release_langsys_table(&langsys_tab);
      }
      for (langsys_idx = 0;
           langsys_idx < script_tab.LangSysRecord.count;
           langsys_idx++) {
        struct clt_record  *langsys_rec;

        langsys_rec = &(script_tab.LangSysRecord.record[langsys_idx]);
        if (otl_match_optrule(language, langsys_rec->tag)) {
          struct clt_langsys_table langsys_tab;

          if(verbose > VERBOSE_LEVEL_MIN) {
            MESG("otl_gsub>> OTL script-language enabled: %c%c%c%c.%c%c%c%c\n",
                 script_list.record[script_idx].tag[0],
                 script_list.record[script_idx].tag[1],
                 script_list.record[script_idx].tag[2],
                 script_list.record[script_idx].tag[3],
                 langsys_rec->tag[0], langsys_rec->tag[1],
                 langsys_rec->tag[2], langsys_rec->tag[3]);
          }

          sfnt_seek_set(sfont, offset + langsys_rec->offset);
          clt_read_langsys_table(&langsys_tab, sfont);
          if (otl_match_optrule(feature, "____") || /* _FIXME_ */
              langsys_tab.ReqFeatureIndex != 0xFFFF)
            SET_BIT(feat_bits, langsys_tab.ReqFeatureIndex);
          for (feat_idx = 0;
               feat_idx < langsys_tab.FeatureIndex.count;
               feat_idx++) {
            SET_BIT(feat_bits,
                    langsys_tab.FeatureIndex.value[feat_idx]);
          }
          clt_release_langsys_table(&langsys_tab);
        }
      }
      clt_release_script_table(&script_tab);
    }
  }

  /* Feature List */
  offset = gsub_offset + head.FeatureList;
  sfnt_seek_set(sfont, offset);
  clt_read_record_list(&feature_list, sfont);

  /* Lookup List */
  offset = gsub_offset + head.LookupList;
  sfnt_seek_set(sfont, offset);
  clt_read_number_list(&lookup_list, sfont);

  if(verbose > VERBOSE_LEVEL_MIN) {
    MESG("otl_gsub>> Reading OTL feature(s):");
  }

  for (feat_idx = 0;
       feat_idx < feature_list.count; feat_idx++) {
    if (BIT_SET(feat_bits, feat_idx)  &&
        (otl_match_optrule(feature,
                           feature_list.record[feat_idx].tag))) {
      struct clt_feature_table feature_table;
      long   i;

      if(verbose > VERBOSE_LEVEL_MIN) {
        MESG(" %c%c%c%c",
             feature_list.record[feat_idx].tag[0],
             feature_list.record[feat_idx].tag[1],
             feature_list.record[feat_idx].tag[2],
             feature_list.record[feat_idx].tag[3]);
      }

      /* Feature Table */
      offset = gsub_offset +
        head.FeatureList + feature_list.record[feat_idx].offset;

      sfnt_seek_set(sfont, offset);
      clt_read_feature_table(&feature_table, sfont);
      if (feature_table.FeatureParams != 0) {
        ERROR("unrecognized FeatureParams");
      }

      /* Lookup table */
      for (i = 0; i < feature_table.LookupListIndex.count; i++) {
        struct clt_lookup_table lookup_table;
        long ll_idx, st_idx, r, n_st;

        ll_idx = feature_table.LookupListIndex.value[i];
        if (ll_idx >= lookup_list.count)
          ERROR("invalid Lookup index.");

        offset = gsub_offset +
          head.LookupList + (lookup_list.value)[ll_idx];
        sfnt_seek_set(sfont, offset);
        clt_read_lookup_table(&lookup_table, sfont);

        if (lookup_table.LookupType != OTL_GSUB_TYPE_SINGLE    &&
            lookup_table.LookupType != OTL_GSUB_TYPE_ALTERNATE &&
            lookup_table.LookupType != OTL_GSUB_TYPE_LIGATURE  &&
            lookup_table.LookupType != OTL_GSUB_TYPE_ESUBST) {
          if (verbose > VERBOSE_LEVEL_MIN)
            WARN("Skipping unsupported GSUB subtable: LookupType=%d", lookup_table.LookupType);
          continue;
        }

        subtab = RENEW(subtab,
                       num_subtabs + lookup_table.SubTableList.count,
                       struct otl_gsub_subtab);
        for (n_st = 0, st_idx = 0;
             st_idx < lookup_table.SubTableList.count; st_idx++) {

          offset = gsub_offset + head.LookupList +
            lookup_list.value[ll_idx] +
            (lookup_table.SubTableList.value)[st_idx];

          sfnt_seek_set(sfont, offset);

          switch ((int) lookup_table.LookupType) {
          case OTL_GSUB_TYPE_SINGLE:
            r = otl_gsub_read_single(&subtab[num_subtabs + n_st],
                                     sfont);
            if (r <= 0)
              WARN("Reading GSUB subtable (single) failed...");
            else {
              if(verbose > VERBOSE_LEVEL_MIN) {
                MESG("(single)");
              }
              n_st++;
            }
            break;

          case OTL_GSUB_TYPE_ALTERNATE:
            r = otl_gsub_read_alternate(&subtab[num_subtabs + n_st],
                                        sfont);
            if (r <= 0)
              WARN("Reading GSUB subtable (alternate) failed...");
            else {
              if(verbose > VERBOSE_LEVEL_MIN) {
                MESG("(alternate)");
              }
              n_st++;
            }
            break;

          case OTL_GSUB_TYPE_LIGATURE:
            r = otl_gsub_read_ligature(&subtab[num_subtabs + n_st],
                                       sfont);
            if (r <= 0)
              WARN("Reading GSUB subtable (ligature) failed...");
            else {
              if(verbose > VERBOSE_LEVEL_MIN) {
                MESG("(ligature)");
              }
              n_st++;
            }
            break;

          case OTL_GSUB_TYPE_ESUBST:
            {
              USHORT  SubstFormat;
              USHORT  ExtensionLookupType;
              ULONG   ExtensionOffset;

              SubstFormat = sfnt_get_ushort(sfont);
              if (SubstFormat != 1)
                break;
              ExtensionLookupType = sfnt_get_ushort(sfont);
              ExtensionOffset     = sfnt_get_ulong (sfont);

              sfnt_seek_set(sfont, offset + ExtensionOffset);
              switch (ExtensionLookupType) {
              case OTL_GSUB_TYPE_SINGLE:
                r = otl_gsub_read_single(&subtab[num_subtabs + n_st],
                                         sfont);
                if (r <= 0)
                  WARN("Reading GSUB subtable (ext:single) failed...");
                else {
                  if(verbose > VERBOSE_LEVEL_MIN) {
                    MESG("(ext:single)");
                  }
                  n_st++;
                }
                break;

              case OTL_GSUB_TYPE_ALTERNATE:
                r = otl_gsub_read_alternate(&subtab[num_subtabs + n_st],
                                            sfont);
                if (r <= 0)
                  WARN("Reading GSUB subtable (alternate) failed...");
                else {
                  if(verbose > VERBOSE_LEVEL_MIN) {
                    MESG("(alternate)");
                  }
                  n_st++;
                }
              break;

              case OTL_GSUB_TYPE_LIGATURE:
                r = otl_gsub_read_ligature(&subtab[num_subtabs + n_st],
                                           sfont);
                if (r <= 0)
                  WARN("Reading GSUB subtable (ext:ligature) failed...");
                else {
                  if(verbose > VERBOSE_LEVEL_MIN) {
                    MESG("(ext:ligature)");
                  }
                  n_st++;
                }
                break;

              }
            }
            break;

          default:
            break;
          }
        }
        num_subtabs += n_st; /* lookup_table.SubTableList.count; */
        clt_release_lookup_table(&lookup_table);
      }
      clt_release_feature_table(&feature_table);
    }
  }

  if(verbose > VERBOSE_LEVEL_MIN) {
    MESG("\n");
    MESG("otl_gsub>> %ld subtable(s) read.\n", num_subtabs);
  }

  clt_release_number_list(&lookup_list);
  clt_release_record_list(&feature_list);
  clt_release_record_list(&script_list);

  otl_release_opt(script);
  otl_release_opt(language);
  otl_release_opt(feature);

  if (subtab != NULL) {
    gsub->num_subtables = num_subtabs;
    gsub->subtables     = subtab;
  } else {
    return -1;
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static long otl_gsub_read_header ( struct otl_gsub_header head,
sfnt sfont 
) [static]

Definition at line 799 of file tt_gsub.c.

{
  ASSERT(head && sfont);

  head->version     = sfnt_get_ulong (sfont);
  head->ScriptList  = sfnt_get_ushort(sfont);
  head->FeatureList = sfnt_get_ushort(sfont);
  head->LookupList  = sfnt_get_ushort(sfont);

  return 10;
}

Here is the caller graph for this function:

static long otl_gsub_read_ligature ( struct otl_gsub_subtab subtab,
sfnt sfont 
) [static]

Definition at line 621 of file tt_gsub.c.

{
  long   len;
  USHORT i, j;
  ULONG  offset;     /* not Offset which is USHORT */
  Offset cov_offset; /* subtable offset, offset to Coverage table */
  struct clt_number_list     ligset_offsets;
  struct otl_gsub_ligature1 *data;

  ASSERT(subtab && sfont);

  offset = tell_position(sfont->stream);

  subtab->LookupType  = OTL_GSUB_TYPE_LIGATURE;
  subtab->SubstFormat = sfnt_get_ushort(sfont); /* Must be 1 */
  if (subtab->SubstFormat != 1) {
    WARN("Unknown GSUB SubstFormat for Ligature: %u",
         subtab->SubstFormat);
    return -1;
  }

  len  = 2;
  subtab->table.ligature1 =
    data = NEW(1, struct otl_gsub_ligature1);

  cov_offset        = sfnt_get_ushort(sfont);
  len += 2;
  len += clt_read_number_list(&ligset_offsets, sfont);
  data->LigSetCount = ligset_offsets.count;
  if (data->LigSetCount == 0) {
    data->LigatureSet    = NULL;
    data->coverage.count  = 0;
    data->coverage.format = 0;
    data->coverage.list   = NULL;
    return len;
  }
  data->LigatureSet = NEW(data->LigSetCount,
                          struct otl_gsub_ligset);
  for (i = 0; i < data->LigSetCount; i++) {
    struct clt_number_list  ligset_tab;
    struct otl_gsub_ligset *ligset;
    ULONG  ligset_offset;
    USHORT count;

    ligset = &(data->LigatureSet[i]);

    ligset_offset = offset + ligset_offsets.value[i];
    sfnt_seek_set(sfont, ligset_offset);
    len += clt_read_number_list(&ligset_tab, sfont);

    ligset->LigatureCount = ligset_tab.count;
    if (ligset_tab.count == 0) {
      ligset->Ligature = NULL;
      break;
    }
    ligset->Ligature = NEW(ligset_tab.count,
                           struct otl_gsub_ligtab);
    for (j = 0; j < ligset_tab.count; j++) {
      sfnt_seek_set(sfont, ligset_offset + ligset_tab.value[j]);
      ligset->Ligature[j].LigGlyph = sfnt_get_ushort(sfont);
      ligset->Ligature[j].CompCount = sfnt_get_ushort(sfont);
      if (ligset->Ligature[j].CompCount == 0) {
        ligset->Ligature[j].Component = NULL;
        break;
      }
      ligset->Ligature[j].Component =
        NEW(ligset->Ligature[j].CompCount - 1, GlyphID);
      for (count = 0;
           count < ligset->Ligature[j].CompCount - 1; count++) {
        ligset->Ligature[j].Component[count] = sfnt_get_ushort(sfont);
      }
      len += 4 + count * 2;
    }
    clt_release_number_list(&ligset_tab);
  }
  clt_release_number_list(&ligset_offsets);

  sfnt_seek_set(sfont, offset + cov_offset);
  len += clt_read_coverage(&data->coverage, sfont);

  return len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static long otl_gsub_read_single ( struct otl_gsub_subtab subtab,
sfnt sfont 
) [static]

Definition at line 498 of file tt_gsub.c.

{
  long   len;
  ULONG  offset;     /* not Offset which is USHORT */
  Offset cov_offset; /* subtable offset, offset to Coverage table */

  ASSERT(subtab && sfont);

  offset = tell_position(sfont->stream);

  subtab->LookupType  = OTL_GSUB_TYPE_SINGLE;
  subtab->SubstFormat = sfnt_get_ushort(sfont);
  len = 2;

  if (subtab->SubstFormat == 1) {
    struct otl_gsub_single1 *data;

    subtab->table.single1 = data = NEW(1, struct otl_gsub_single1);
    cov_offset         = sfnt_get_ushort(sfont);
    data->DeltaGlyphID = sfnt_get_short(sfont);
    len += 4;

    sfnt_seek_set(sfont, offset + cov_offset);
    len += clt_read_coverage(&data->coverage, sfont);

  } else if (subtab->SubstFormat == 2) {
    struct otl_gsub_single2 *data;
    USHORT count;

    subtab->table.single2 = data = NEW(1, struct otl_gsub_single2);
    cov_offset       = sfnt_get_ushort(sfont);
    data->GlyphCount = sfnt_get_ushort(sfont);
    len += 4;

    if (data->GlyphCount == 0)
      data->Substitute = NULL;
    else {
      data->Substitute = NEW(data->GlyphCount, GlyphID);
      for (count = 0; count < data->GlyphCount; count++) {
        data->Substitute[count] = sfnt_get_ushort(sfont);
      }
      len += 2 * data->GlyphCount;
    }

    sfnt_seek_set(sfont, offset + cov_offset);
    len += clt_read_coverage(&data->coverage, sfont);

  } else {
    ERROR("unexpected SubstFormat");
  }
  /* not implemented yet */

  return len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void otl_gsub_release ( otl_gsub gsub_list)

Definition at line 1344 of file tt_gsub.c.

{
  struct otl_gsub_tab    *gsub;
  struct otl_gsub_subtab *subtab;
  int    i, j;

  if (!gsub_list)
    return;

  for (i = 0; i < gsub_list->num_gsubs; i++) {
    gsub = &(gsub_list->gsubs[i]);

    if (gsub->script)
      RELEASE(gsub->script);
    if (gsub->language)
      RELEASE(gsub->language);
    if (gsub->feature)
      RELEASE(gsub->feature);

    for (j = 0; j < gsub->num_subtables; j++) {
      subtab = &(gsub->subtables[j]);
      switch ((int) subtab->LookupType) {
      case OTL_GSUB_TYPE_SINGLE:
        otl_gsub_release_single(subtab);
        break;
      case OTL_GSUB_TYPE_ALTERNATE:
        otl_gsub_release_alternate(subtab);
        break;
      case OTL_GSUB_TYPE_LIGATURE:
        otl_gsub_release_ligature(subtab);
        break;
      default:
        ERROR("???");
        break;
      }
    }
    RELEASE(gsub->subtables);
  }

  RELEASE(gsub_list);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void otl_gsub_release_alternate ( struct otl_gsub_subtab subtab) [static]

Definition at line 773 of file tt_gsub.c.

{
  if (subtab) {
    struct otl_gsub_alternate1 *data;
    USHORT i;

    data = subtab->table.alternate1;
    if (data && data->AlternateSet) {
      for (i = 0; i < data->AlternateSetCount; i++) {
        struct otl_gsub_altset *altset;

        altset = &(data->AlternateSet[i]);
        if (altset->Alternate)
          RELEASE(altset->Alternate);
        altset->Alternate = NULL;
      }
      RELEASE(data->AlternateSet);
    }
    clt_release_coverage(&data->coverage);
    data->AlternateSet = NULL;
    RELEASE(data);
    subtab->table.alternate1 = NULL;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void otl_gsub_release_ligature ( struct otl_gsub_subtab subtab) [static]

Definition at line 742 of file tt_gsub.c.

{
  if (subtab) {
    struct otl_gsub_ligature1 *data;
    USHORT i, j;

    data = subtab->table.ligature1;
    if (data && data->LigatureSet) {
      for (i = 0; i < data->LigSetCount; i++) {
        struct otl_gsub_ligset *ligset;

        ligset = &(data->LigatureSet[i]);
        for (j = 0;
             j < ligset->LigatureCount; j++) {
          if (ligset->Ligature[j].Component)
            RELEASE(ligset->Ligature[j].Component);
          ligset->Ligature[j].Component = NULL;
        }
        RELEASE(ligset->Ligature);
        ligset->Ligature = NULL;
      }
      RELEASE(data->LigatureSet);
    }
    clt_release_coverage(&data->coverage);
    data->LigatureSet = NULL;
    RELEASE(data);
    subtab->table.ligature1 = NULL;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void otl_gsub_release_single ( struct otl_gsub_subtab subtab) [static]

Definition at line 705 of file tt_gsub.c.

{
  if (subtab) {
    switch((int) subtab->SubstFormat) {
    case 1:
      {
        struct otl_gsub_single1 *data;

        data = subtab->table.single1;
        if (data) {
          clt_release_coverage(&data->coverage);
          RELEASE(data);
        }
        subtab->table.single1 = NULL;
      }
    break;
    case 2:
      {
        struct otl_gsub_single2 *data;

        data = subtab->table.single2;
        if (data) {
          if (data->Substitute)
            RELEASE(data->Substitute);
          clt_release_coverage(&data->coverage);
          RELEASE(data);
        }
        subtab->table.single2 = NULL;
      }
    break;
    default:
      ERROR("Unknown format for single substitution");
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int otl_gsub_select ( otl_gsub gsub_list,
const char *  script,
const char *  language,
const char *  feature 
)

Definition at line 1488 of file tt_gsub.c.

{
  int    i;
  struct otl_gsub_tab *gsub;

  for (i = 0; i < gsub_list->num_gsubs; i++) {
    gsub = &(gsub_list->gsubs[i]);
    if (!strcmp(gsub->script,   script)   &&
        !strcmp(gsub->language, language) &&
        !strcmp(gsub->feature,  feature)) {
      gsub_list->select = i;
      return i;
    }
  }

  gsub_list->select = -1;

  return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void otl_gsub_set_verbose ( void  )

Definition at line 41 of file tt_gsub.c.

{
  verbose++;
}

Here is the caller graph for this function:


Variable Documentation

int verbose = 0 [static]

Definition at line 39 of file tt_gsub.c.