Logo Search packages:      
Sourcecode: wine-unstable version File versions  Download package

mkagl.c

/*
 * Copyright 2001 Ian Pilcher
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"

#include <sys/types.h>
#ifdef HAVE_DIRENT_H
# include <dirent.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>


/*
 *  The array of glyph information
 */

typedef struct
{
    int           UV;
    int           index;            /* in PSDRV_AGLGlyphNames */
    const char    *name;
    const char    *comment;

} GLYPHINFO;

static GLYPHINFO    glyphs[1500];
static int            num_glyphs = 0;


/*
 *  Functions to search and sort the array
 */

static int cmp_by_UV(const void *a, const void *b)
{
    return ((const GLYPHINFO *)a)->UV - ((const GLYPHINFO *)b)->UV;
}

static int cmp_by_name(const void *a, const void *b)
{
    return strcmp(((const GLYPHINFO *)a)->name, ((const GLYPHINFO *)b)->name);
}

static inline void sort_by_UV(void)
{
    qsort(glyphs, num_glyphs, sizeof(GLYPHINFO), cmp_by_UV);
}

static inline void sort_by_name(void)
{
    qsort(glyphs, num_glyphs, sizeof(GLYPHINFO), cmp_by_name);
}

static inline GLYPHINFO *search_by_name(const char *name)
{
    GLYPHINFO     gi;

    gi.name = name;

    return (GLYPHINFO *)bsearch(&gi, glyphs, num_glyphs, sizeof(GLYPHINFO),
          cmp_by_name);
}


/*
 *  Use the 'optimal' combination of tabs and spaces to position the cursor
 */

static inline void fcpto(FILE *f, int newpos, int curpos)
{
    int newtpos = newpos & ~7;
    int curtpos = curpos & ~7;

    while (curtpos < newtpos)
    {
      fputc('\t', f);
      curtpos += 8;
      curpos = curtpos;
    }

    while (curpos < newpos)
    {
      fputc(' ', f);
      ++curpos;
    }
}

/*
 *  Make main() look "purty"
 */

static inline void triple_space(FILE *f)
{
    fputc('\n', f);  fputc('\n', f);
}


/*
 *  Read the Adobe Glyph List from 'glyphlist.txt'
 */

static void read_agl(void)
{
    FILE    *f = fopen("glyphlist.txt", "r");
    char    linebuf[256], namebuf[128], commbuf[128];

    if (f == NULL)
    {
      fprintf(stderr, "Error opening glyphlist.txt\n");
      exit(__LINE__);
    }

    while (fgets(linebuf, sizeof(linebuf), f) != NULL)
    {
      unsigned int      UV;

      if (linebuf[0] == '#')
          continue;

      sscanf(linebuf, "%X;%[^;];%[^\n]", &UV, namebuf, commbuf);

      glyphs[num_glyphs].UV = (int)UV;
      glyphs[num_glyphs].name = strdup(namebuf);
      glyphs[num_glyphs].comment = strdup(commbuf);

      if (glyphs[num_glyphs].name == NULL ||
            glyphs[num_glyphs].comment == NULL)
      {
          fprintf(stderr, "Memory allocation failure\n");
          exit(__LINE__);
      }

      ++num_glyphs;
    }

    fclose(f);

    if (num_glyphs != 1051)
    {
      fprintf(stderr, "Read %i glyphs\n", num_glyphs);
      exit(__LINE__);
    }
}


/*
 *  Read glyph names from all AFM files in current directory
 */

static void read_afms(FILE *f_c, FILE *f_h)
{
    DIR               *d = opendir(".");
    struct dirent   *de;

    fputs(  "/*\n"
          " *  Built-in font metrics\n"
          " */\n"
          "\n"
          "const AFM *const PSDRV_BuiltinAFMs[] =\n"
          "{\n", f_c);


    if (d == NULL)
    {
      fprintf(stderr, "Error opening current directory\n");
      exit(__LINE__);
    }

    while ((de = readdir(d)) != NULL)
    {
      FILE        *f;
      char        *cp, linebuf[256], font_family[128];
      int   i, num_metrics;

      cp = strrchr(de->d_name, '.');                  /* Does it end in   */
      if (cp == NULL || strcasecmp(cp, ".afm") != 0)  /*   .afm or .AFM?  */
          continue;

      f = fopen(de->d_name, "r");
      if (f == NULL)
      {
          fprintf(stderr, "Error opening %s\n", de->d_name);
          exit(__LINE__);
      }

      while (1)
      {
          if (fgets(linebuf, sizeof(linebuf), f) == NULL)
          {
            fprintf(stderr, "FontName not found in %s\n", de->d_name);
            exit(__LINE__);
          }

          if (strncmp(linebuf, "FontName ", 9) == 0)
            break;
      }

      sscanf(linebuf, "FontName %[^\r\n]", font_family);

      for (i = 0; font_family[i] != '\0'; ++i)
          if (font_family[i] == '-')
            font_family[i] = '_';

      fprintf(f_h, "extern const AFM PSDRV_%s;\n", font_family);
      fprintf(f_c, "    &PSDRV_%s,\n", font_family);

      while (1)
      {
          if (fgets(linebuf, sizeof(linebuf), f) == NULL)
          {
            fprintf(stderr, "FamilyName not found in %s\n", de->d_name);
            exit(__LINE__);
          }

          if (strncmp(linebuf, "FamilyName ", 11) == 0)
            break;
      }

      sscanf(linebuf, "FamilyName %[^\r\n]", font_family);

      while (1)
      {
          if (fgets(linebuf, sizeof(linebuf), f) == NULL)
          {
            fprintf(stderr, "StartCharMetrics not found in %s\n",
                  de->d_name);
            exit(__LINE__);
          }

          if (strncmp(linebuf, "StartCharMetrics ", 17) == 0)
            break;
      }

      sscanf(linebuf, "StartCharMetrics %i", &num_metrics);

      for (i = 0; i < num_metrics; ++i)
      {
          char    namebuf[128];

          if (fgets(linebuf, sizeof(linebuf), f) == NULL)
          {
            fprintf(stderr, "Unexpected EOF after %i glyphs in %s\n", i,
                  de->d_name);
            exit(__LINE__);
          }

          cp = strchr(linebuf, 'N');
          if (cp == NULL || strlen(cp) < 3)
          {
            fprintf(stderr, "Parse error after %i glyphs in %s\n", i,
                  de->d_name);
            exit(__LINE__);
          }

          sscanf(cp, "N %s", namebuf);
          if (search_by_name(namebuf) != NULL)
            continue;

          sprintf(linebuf, "FONT FAMILY;%s", font_family);

          glyphs[num_glyphs].UV = -1;
          glyphs[num_glyphs].name = strdup(namebuf);
          glyphs[num_glyphs].comment = strdup(linebuf);

          if (glyphs[num_glyphs].name == NULL ||
                glyphs[num_glyphs].comment == NULL)
          {
            fprintf(stderr, "Memory allocation failure\n");
            exit(__LINE__);
          }

          ++num_glyphs;

          sort_by_name();
      }

      fclose(f);
    }

    closedir(d);

    fputs("    NULL\n};\n", f_c);
}


/*
 *  Write opening comments, etc.
 */

static void write_header(FILE *f)
{
    int i;

    fputc('/', f);
    for (i = 0; i < 79; ++i)
      fputc('*', f);
    fputs("\n"
          " *\n"
          " *\tFont and glyph data for the Wine PostScript driver\n"
          " *\n"
          " *\tCopyright 2001 Ian Pilcher\n"
          " *\n"
          " *\n"
          " *\tThis data is derived from the Adobe Glyph list at\n"
          " *\n"
          " *\t    "
          "http://partners.adobe.com/asn/developer/type/glyphlist.txt\n"
          " *\n"
          " *\tand the Adobe Font Metrics files at\n"
          " *\n"
          " *\t    "
          "ftp://ftp.adobe.com/pub/adobe/type/win/all/afmfiles/base35/\n"
          " *\n"
          " *\twhich are Copyright 1985-1998 Adobe Systems Incorporated.\n"
          " *\n"
          " */\n"
          "\n"
          "#include \"psdrv.h\"\n"
          "#include \"data/agl.h\"\n", f);
}

/*
 *  Write the array of glyph names (also populates indexes)
 */

static void write_glyph_names(FILE *f_c, FILE *f_h)
{
    int i, num_names = 0, index = 0;

    for (i = 0; i < num_glyphs; ++i)
      if (i == 0 || strcmp(glyphs[i - 1].name, glyphs[i].name) != 0)
          ++num_names;

    fputs(  "/*\n"
          " *  Every glyph name in the AGL and the 35 core PostScript fonts\n"
          " */\n"
          "\n", f_c);

    fprintf(f_c, "const INT PSDRV_AGLGlyphNamesSize = %i;\n\n", num_names);

    fprintf(f_c, "GLYPHNAME PSDRV_AGLGlyphNames[%i] =\n{\n", num_names);

    for (i = 0; i < num_glyphs - 1; ++i)
    {
      int cp = 0;

      if (i == 0 || strcmp(glyphs[i - 1].name, glyphs[i].name) != 0)
      {
          fcpto(f_h, 32, fprintf(f_h, "#define GN_%s", glyphs[i].name));
          fprintf(f_h, "(PSDRV_AGLGlyphNames + %i)\n", index);

          cp = fprintf(f_c, "    { %4i, \"%s\" },", index, glyphs[i].name);
          glyphs[i].index = index;
          ++index;
      }
      else
      {
          glyphs[i].index = glyphs[i - 1].index;
      }

      fcpto(f_c, 40, cp);

      fprintf(f_c, "/* %s */\n", glyphs[i].comment);
    }

    fcpto(f_h, 32, fprintf(f_h, "#define GN_%s", glyphs[i].name));
    fprintf(f_h, "(PSDRV_AGLGlyphNames + %i)\n", index);

    glyphs[i].index = index;
    fcpto(f_c, 40, fprintf(f_c, "    { %4i, \"%s\" }", index, glyphs[i].name));
    fprintf(f_c, "/* %s */\n};\n", glyphs[i].comment);
}


/*
 *  Write the AGL encoding vector, sorted by glyph name
 */

static void write_encoding_by_name(FILE *f)
{
    int i, size = 0, even = 1;

    for (i = 0; i < num_glyphs; ++i)
      if (glyphs[i].UV != -1 &&
            (i == 0 || strcmp(glyphs[i - 1].name, glyphs[i].name) != 0))
          ++size;                 /* should be 1039 */

    fputs(  "/*\n"
          " *  The AGL encoding vector, sorted by glyph name - "
                "duplicates omitted\n"
          " */\n"
          "\n", f);

    fprintf(f, "const INT PSDRV_AGLbyNameSize = %i;\n\n", size);
    fprintf(f, "const UNICODEGLYPH PSDRV_AGLbyName[%i] =\n{\n", size);

    for (i = 0; i < num_glyphs - 1; ++i)
    {
      int cp;

      if (glyphs[i].UV == -1)
          continue;

      if (i != 0 && strcmp(glyphs[i - 1].name, glyphs[i].name) == 0)
          continue;

      cp = fprintf(f, "    { 0x%.4x, GN_%s },", glyphs[i].UV, glyphs[i].name);

      even = !even;
      if (even)
          fputc('\n', f);
      else
          fcpto(f, 40, cp);
    }

    fprintf(f, "    { 0x%.4x, GN_%s }\n};\n", glyphs[i].UV, glyphs[i].name);
}

/*
 *  Write the AGL encoding vector, sorted by Unicode value
 */

static void write_encoding_by_UV(FILE *f)
{
    int i, size = 0, even = 1;

    for (i = 0; i < num_glyphs; ++i)
      if (glyphs[i].UV != -1)
          ++size;                   /* better be 1051! */

    sort_by_UV();

    fputs(  "/*\n"
          " *  The AGL encoding vector, sorted by Unicode value - "
                "duplicates included\n"
          " */\n"
          "\n", f);

    fprintf(f, "const INT PSDRV_AGLbyUVSize = %i;\n\n", size);
    fprintf(f, "const UNICODEGLYPH PSDRV_AGLbyUV[%i] =\n{\n", size);

    for (i = 0; i < num_glyphs - 1; ++i)
    {
      int cp;

      if (glyphs[i].UV == -1)
          continue;

      cp = fprintf(f, "    { 0x%.4x, GN_%s },", glyphs[i].UV, glyphs[i].name);

      even = !even;
      if (even)
          fputc('\n', f);
      else
          fcpto(f, 40, cp);
    }

    fprintf(f, "    { 0x%.4x, GN_%s }\n};\n", glyphs[i].UV, glyphs[i].name);
}


/*
 *  Do it!
 */

int main(int argc, char *argv[])
{
    FILE    *f_c, *f_h;

    if (argc < 3)
    {
      fprintf(stderr, "Usage: %s <C file> <header file>\n", argv[0]);
      exit(__LINE__);
    }

    f_c = fopen(argv[1], "w");
    if (f_c == NULL)
    {
      fprintf(stderr, "Error opening %s for writing\n", argv[1]);
      exit(__LINE__);
    }

    f_h = fopen(argv[2], "w");
    if (f_h == NULL)
    {
      fprintf(stderr, "Error opening %s for writing\n", argv[2]);
      exit(__LINE__);
    }

    write_header(f_c);
    triple_space(f_c);
    read_agl();
    read_afms(f_c, f_h);          /* also writes font list */
    triple_space(f_c);
    write_glyph_names(f_c, f_h);
    triple_space(f_c);
    write_encoding_by_name(f_c);
    triple_space(f_c);
    write_encoding_by_UV(f_c);

    /* Clean up */
    fclose(f_c);
    fclose(f_h);

    return 0;
}

Generated by  Doxygen 1.6.0   Back to index