home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Misc / FTREE0.3.LHA / ftree / src / RCS / afm.c,v next >
Encoding:
Text File  |  1994-04-27  |  13.0 KB  |  555 lines

  1. head    1.3;
  2. access;
  3. symbols
  4.     stage1:1.1;
  5. locks; strict;
  6. comment    @ * @;
  7.  
  8.  
  9. 1.3
  10. date    94.04.27.11.37.54;    author peteric;    state Exp;
  11. branches;
  12. next    1.2;
  13.  
  14. 1.2
  15. date    94.03.26.11.28.03;    author peteric;    state Exp;
  16. branches;
  17. next    1.1;
  18.  
  19. 1.1
  20. date    94.03.07.12.43.26;    author peteric;    state Exp;
  21. branches;
  22. next    ;
  23.  
  24.  
  25. desc
  26. @Adobe Font Metric file reader for Ftree.
  27. @
  28.  
  29.  
  30. 1.3
  31. log
  32. @included definitions for the standard Adobe & Latin font
  33. encodings, support for kerned fonts and ligatures, and a better
  34. font lookup system.
  35. @
  36. text
  37. @/*************************************************************************
  38.  *
  39.  *     $RCSfile: afm.c,v $
  40.  *
  41.  *    $Author: peteric $
  42.  *
  43.  *    $Date: 1994/03/26 11:28:03 $
  44.  *
  45.  *    $Revision: 1.2 $
  46.  *
  47.  *    Purpose:    Main routine for ftree family tree formatter.
  48.  *            
  49.  *    $Log: afm.c,v $
  50.  * Revision 1.2  1994/03/26  11:28:03  peteric
  51.  * Modified to use Adobe's parseAFM code. Includes
  52.  * stand-alone tester. Kerning data still to be included.
  53.  *
  54.  * Revision 1.1  1994/03/07  12:43:26  peteric
  55.  * Initial revision
  56.  *
  57.  *    
  58.  *
  59.  *************************************************************************/
  60.  
  61. #include <stdlib.h>
  62. #include <stdarg.h>
  63. #include <string.h>
  64. #include <ctype.h>
  65. #include <errno.h>
  66. #include "ftree.h"
  67. #include "parseAFM.h"
  68.  
  69. int kern(FontInfo *afonti, char *cname1, char *cname2);
  70. CharMetricInfo *lookupname(FontInfo *afonti, char *cname, char **p);
  71. CharMetricInfo *simplelookupname(FontInfo *afonti, char *cname);
  72.  
  73. #define MAXFONTS    8
  74. #define EOS        '\0'
  75.  
  76. static FontInfo *fonts[MAXFONTS] = {0};
  77.  
  78. char *AdobeStandardEncoding[256] =
  79. {
  80.     ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  81.     ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  82.     ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  83.     ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  84.     "space", "exclam", "quotedbl", "numbersign",
  85.     "dollar", "percent", "ampersand", "quoteright",
  86.     "parenleft", "parenright", "asterisk", "plus",
  87.     "comma", "hyphen", "period", "slash",
  88.     "zero", "one", "two", "three",
  89.     "four", "five", "six", "seven",
  90.     "eight", "nine", "colon", "semicolon",
  91.     "less", "equal", "greater", "question",
  92.     "at", "A", "B", "C", "D", "E", "F", "G",
  93.     "H", "I", "J", "K", "L", "M", "N", "O",
  94.     "P", "Q", "R", "S", "T", "U", "V", "W",
  95.     "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
  96.     "quoteleft", "a", "b", "c", "d", "e", "f", "g",
  97.     "h", "i", "j", "k", "l", "m", "n", "o",
  98.     "p", "q", "r", "s", "t", "u", "v", "w",
  99.     "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", ".notdef",
  100.  
  101.     ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  102.     ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  103.     ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  104.     ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  105.     ".notdef", "exclamdown", "cent", "sterling",
  106.     "fraction", "yen", "florin", "section",
  107.     "currency", "quotesingle", "quotedblleft", "guillemotleft",
  108.     "guilsinglleft", "guilsinglright", "fi", "fl",
  109.     ".notdef", "endash", "dagger", "daggerdbl",
  110.     "periodcentered", ".notdef", "paragraph", "bullet",
  111.     "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
  112.     "ellipsis", "perthousand", ".notdef", "questiondown",
  113.     ".notdef", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent",
  114.     "dieresis", ".notdef", "ring", "cedilla", ".notdef", "hungarumlaut", "ogonek", "caron",
  115.     "emdash", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  116.     ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  117.     ".notdef", "AE", ".notdef", "ordfeminine", ".notdef", ".notdef", ".notdef", ".notdef",
  118.     "Lslash", "Oslash", "OE", "ordmasculine", ".notdef", ".notdef", ".notdef", ".notdef",
  119.     ".notdef", "ae", ".notdef", ".notdef", ".notdef", "dotlessi", ".notdef", ".notdef",
  120.     "lslash", "oslash", "oe", "germandbls", ".notdef", ".notdef", ".notdef", ".notdef"
  121. };
  122.  
  123. char *ISOLatin1Encoding[256] =
  124. {
  125.     ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  126.     ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  127.     ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  128.     ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  129.     "space", "exclam", "quotedbl", "numbersign",
  130.     "dollar", "percent", "ampersand", "quoteright",
  131.     "parenleft", "parenright", "asterisk", "plus",
  132.     "comma", "minus", "period", "slash",
  133.     "zero", "one", "two", "three",
  134.     "four", "five", "six", "seven",
  135.     "eight", "nine", "colon", "semicolon",
  136.     "less", "equal", "greater", "question",
  137.     "at", "A", "B", "C", "D", "E", "F", "G",
  138.     "H", "I", "J", "K", "L", "M", "N", "O",
  139.     "P", "Q", "R", "S", "T", "U", "V", "W",
  140.     "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
  141.     "quoteleft", "a", "b", "c", "d", "e", "f", "g",
  142.     "h", "i", "j", "k", "l", "m", "n", "o",
  143.     "p", "q", "r", "s", "t", "u", "v", "w",
  144.     "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", ".notdef",
  145.  
  146.     ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  147.     ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
  148.     "dotlessi", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent",
  149.     "dieresis", ".notdef", "ring", "cedilla", ".notdef", "hungarumlaut", "ogonek", "caron",
  150.     "space", "exclamdown", "cent", "sterling",
  151.     "currency", "yen", "brokenbar", "section",
  152.     "dieresis", "copyright", "ordfeminine", "guillemotleft",
  153.     "logicalnot", "hyphen", "registered", "macron",
  154.     "degree", "plusminus", "twosuperior", "threesuperior",
  155.     "acute", "mu", "paragraph", "periodcentered",
  156.     "cedilla", "onesuperior", "ordmasculine", "guillemotright",
  157.     "onequarter", "onehalf", "threequarters", "questiondown",
  158.     "Agrave", "Aacute", "Acircumflex", "Atilde",
  159.     "Adieresis", "Aring", "AE", "Ccedilla",
  160.     "Egrave", "Eacute", "Ecircumflex", "Edieresis",
  161.     "Igrave", "Iacute", "Icircumflex", "Idieresis",
  162.     "Eth", "Ntilde", "Ograve", "Oacute",
  163.     "Ocircumflex", "Otilde", "Odieresis", "multiply",
  164.     "Oslash", "Ugrave", "Uacute", "Ucircumflex",
  165.     "Udieresis", "Yacute", "Thorn", "germandbls",
  166.     "agrave", "aacute", "acircumflex", "atilde",
  167.     "adieresis", "aring", "ae", "ccedilla",
  168.     "egrave", "eacute", "ecircumflex", "edieresis",
  169.     "igrave", "iacute", "icircumflex", "idieresis",
  170.     "eth", "ntilde", "ograve", "oacute",
  171.     "ocircumflex", "otilde", "odieresis", "divide",
  172.     "oslash", "ugrave", "uacute", "ucircumflex",
  173.     "udieresis", "yacute", "thorn", "ydieresis"
  174. };
  175.  
  176.  
  177. FILE *openfontfile(char *name);
  178.  
  179. int loadfont(fontinfo_t *font)
  180. {
  181.     int i, code;
  182.     FILE *fp;
  183.     
  184.     for(i = 0; i < MAXFONTS; i++)
  185.         if (fonts[i] == 0)
  186.             break;
  187.     
  188.     if (i == MAXFONTS)
  189.     {
  190.         errmsg("Maximum number of fonts (%d) loaded; cannot load %s\n",
  191.                 MAXFONTS, font->font);
  192.         return FALSE;
  193.     }
  194.     
  195.     fp = openfontfile(font->font);
  196.     if (fp == NULL)
  197.     {
  198.         errmsg("Cannot open font file for font %s: %s\n",
  199.                 font->font, strerror(errno));
  200.         return FALSE;
  201.     }
  202.     
  203.     code = parseFile(fp, &fonts[i], P_ALL);
  204.     
  205.     fclose(fp);
  206.  
  207.     return code == ok;
  208. }
  209.  
  210. FILE *openfontfile(char *name)
  211. {
  212.     int i;
  213.     FILE *fp;
  214.     char filen[128];
  215.     char *patt;
  216.     char *p;
  217.     static char *paths[][2] =
  218.     {
  219.         {"psfonts:",            ".afm",        },
  220.         {"psfonts:afm/",        "",        },
  221.         {"psfonts:OtherFonts/",        ".afm",        },
  222.         {"psfonts:OtherFonts/afm/",    "",        },
  223.         {"psfonts:afm/",        ".afm",        },
  224.         {"psfonts:OtherFonts/afm/",    ".afm",        },
  225.         {"/usr/local/lib/fonts/afm/",    "",        },
  226.         {"/usr/local/lib/fonts/afm/",    ".afm",        },
  227.         {NULL, NULL},
  228.     };
  229.  
  230.     if (psfontpath[0] != EOS)
  231.     {
  232.         patt = strdup(psfontpath);
  233.         fp = NULL;
  234.         p = strtok(patt, ":");
  235.         for(i = 0; p != NULL && fp == NULL; i++)
  236.         {
  237.             sprintf(filen, p, name);
  238.  
  239.             fp = fopen(filen, "r");
  240.             p = strtok(NULL, ":");
  241.         }
  242.         free(patt);
  243.     }
  244.     else
  245.     {
  246.         fp = NULL;
  247.         for(i = 0; paths[i][0] != NULL && fp == NULL; i++)
  248.         {
  249.             strcpy(filen, paths[i][0]);
  250.             strcat(filen, name);
  251.             strcat(filen, paths[i][1]);
  252.  
  253.             fp = fopen(filen, "r");
  254.         }
  255.     }
  256.     return fp;
  257. }
  258.  
  259. void unloadfont(fontinfo_t *font)
  260. {
  261.     int i;
  262.     
  263.     for(i = 0; i < MAXFONTS; i++)
  264.     {
  265.         if (fonts[i] && streq(fonts[i]->gfi->fontName, font->font))
  266.         {
  267.             freeStorage(fonts[i]);
  268.             fonts[i] = NULL;
  269.             break;
  270.         }
  271.     }
  272. }
  273.  
  274. double stringwidth(fontinfo_t *font, double afmconst, char *string)
  275. {
  276.     char *p, **encv;
  277.     CharMetricInfo *cd;
  278.     int i, cw;
  279.     double w;
  280.     FontInfo *afonti = NULL;
  281.     
  282.     /*
  283.      * look for the requested font
  284.      */
  285.     for(i = 0; i < MAXFONTS; i++)
  286.     {
  287.         if (fonts[i] && streq(fonts[i]->gfi->fontName, font->font))
  288.         {
  289.             afonti = fonts[i];
  290.             break;
  291.         }
  292.     }
  293.  
  294.     /*
  295.      * if no font info available (e.g. no font file for this font)
  296.      * then attempt an approximation, using the supplied font width
  297.      * constant afmconst. This is supposed to return a width which
  298.      * is at least as great as the true width. Of course, it will
  299.      * probably end up being larger.
  300.      */
  301.     if (afonti == NULL)
  302.     {
  303.         if (afmconst != 0.0)
  304.         {
  305.             w = font->size * strlen(string) * afmconst;
  306.             return w;
  307.         }
  308.         else
  309.             return -1;
  310.     }
  311.  
  312.     if (streq(afonti->gfi->encodingScheme, "AdobeStandardEncoding"))
  313.         encv = AdobeStandardEncoding;
  314.     else if (streq(afonti->gfi->encodingScheme, "ISOLatin1Encoding"))
  315.         encv = ISOLatin1Encoding;
  316.     else
  317.     {
  318.         warnmsg("Unknown encoding '%s' of font %s. Using Standard encoding\n",
  319.             afonti->gfi->encodingScheme, afonti->gfi->fontName);
  320.         encv = AdobeStandardEncoding;
  321.     }
  322.  
  323.     for (p = string, w = 0.0; *p != EOS; p++)
  324.     {
  325.         cd = lookupname(afonti, encv[*p], &p);
  326.         if (cd != NULL)
  327.         {
  328.             cw = cd->wx;
  329.             /* dbprintf(("stringwidth: translates to: %s, width %d\n", cd->name, cw)); */
  330.             cw += kern(afonti, cd->name, encv[p[1]]);
  331.             w += cw;
  332.             /* dbprintf(("stringwidth: kern %s: final width %d, sum %.2f\n", cd->name, cw, w)); */
  333.         }
  334.     }
  335.     w = (w * font->size) / 1000.0;
  336.     
  337.     return w;
  338. }
  339.  
  340. int kern(FontInfo *afonti, char *cname1, char *cname2)
  341. {
  342.     PairKernData *pkd = afonti->pkd;
  343.     int i, np, kx;
  344.     CharMetricInfo *cd;
  345.     
  346.     if (streq(cname1, ".notdef") || streq(cname2, ".notdef"))
  347.         return 0;
  348.     
  349.     pkd = afonti->pkd;
  350.     np = afonti->numOfPairs; 
  351.     cd = NULL;
  352.     kx = 0;
  353.     for(i = 0; i < np; pkd++, i++)
  354.     {
  355.         if (streq(cname1, pkd->name1))
  356.         {
  357.             if (cd == NULL)
  358.                 cd = simplelookupname(afonti, cname2);
  359.             if (cd && streq(cd->name, pkd->name2))
  360.             {
  361.                 kx += pkd->xamt;
  362.                 break;
  363.             }
  364.         }
  365.     }
  366.     /* dbprintf(("kern: returning %d for kern letter: %s%s%s\n", kx, cname1, cd ? " and letter: " : "", cd ? cd->name : "")); */
  367.     
  368.     return kx;
  369. }
  370.  
  371. CharMetricInfo *simplelookupname(FontInfo *afonti, char *cname)
  372. {
  373.     int i, nc;
  374.     CharMetricInfo *cd;
  375.  
  376.     /* dbprintf(("simplelookupname: looking up %s\n", cname)); */
  377.  
  378.     cd = afonti->cmi;
  379.     nc = afonti->numOfChars;
  380.     for(i = 0; i < nc; i++, cd++)
  381.     {
  382.         if (streq(cname, cd->name))
  383.             break;
  384.     }
  385.     
  386.     if (i == nc)
  387.     {
  388.         /* dbprintf(("No glyph for '%s'\n", cname)); */
  389.         cd = NULL;
  390.     }
  391.     return cd;
  392. }
  393.  
  394. CharMetricInfo *lookupname(FontInfo *afonti, char *cname, char **p)
  395. {
  396.     unsigned int l;
  397.     CharMetricInfo *cd;
  398.     Ligature *ligp;
  399.     char *q;
  400.  
  401.     /* dbprintf(("lookupname: looking up %s\n", cname)); */
  402.     
  403.     cd = simplelookupname(afonti, cname);
  404.     
  405.     if (cd != NULL)
  406.     {
  407. #if 0
  408.         dbprintf(("lookupname: glyph '%s': ligatures: ", cd->name));
  409.         ligp = cd->ligs;
  410.         while(ligp)
  411.         {
  412.             if (ligp->succ)
  413.                 dbprintf(("S: %s ", ligp->succ));
  414.             else
  415.                 dbprintf(("S: >??< "));
  416.             if (ligp->lig)
  417.                 dbprintf(("L: %s, ", ligp->lig));
  418.             else
  419.                 dbprintf(("L: >??< "));
  420.             ligp = ligp->next;
  421.         }
  422.         dbprintf(("\n"));
  423. #endif
  424.  
  425.         q = (*p)+1;
  426.         ligp = cd->ligs;
  427.         while(ligp != NULL && *q != EOS)
  428.         {
  429.             l = strlen(ligp->succ);
  430.             /* dbprintf(("lookupname: check lig. '%s' against %d char(s) from: '%c'\n", ligp->succ, l, *q)); */
  431.             if (ligp->succ[0] == *q)
  432.             {
  433.                 *p += l;
  434.                 cd = simplelookupname(afonti, ligp->lig);
  435.             
  436.                 /* dbprintf(("lookupname: ligature %s (%d) to get char %s\n", ligp->succ, l, cd->name)); */
  437.  
  438.                 ligp = NULL;
  439.             }
  440.             else
  441.                 ligp = ligp->next;
  442.         }
  443.     }
  444.     return cd;
  445. }
  446. @
  447.  
  448.  
  449. 1.2
  450. log
  451. @Modified to use Adobe's parseAFM code. Includes
  452. stand-alone tester. Kerning data still to be included.
  453. @
  454. text
  455. @d7 1
  456. a7 1
  457.  *    $Date: 1994/03/07 12:43:26 $
  458. d9 1
  459. a9 1
  460.  *    $Revision: 1.1 $
  461. d14 4
  462. d33 3
  463. d40 100
  464. a139 1
  465. FontInfo *fonts[MAXFONTS] = {0};
  466. d179 2
  467. d183 1
  468. d185 1
  469. d189 2
  470. d194 1
  471. a194 2
  472.     fp = NULL;
  473.     for(i = 0; paths[i][0] != NULL && fp == NULL; i++)
  474. d196 6
  475. a201 3
  476.         strcpy(filen, paths[i][0]);
  477.         strcat(filen, name);
  478.         strcat(filen, paths[i][1]);
  479. d203 16
  480. a218 1
  481.         fp = fopen(filen, "r");
  482. d240 3
  483. a242 2
  484.     char *p;
  485.     int i, ec, cw;
  486. d246 3
  487. d258 7
  488. d275 12
  489. a286 1
  490.     
  491. d289 9
  492. a297 4
  493.         ec = *p;
  494.         cw = afonti->cmi[ec].wx;
  495.         w += cw;
  496.         /* printf("Char '%c'/%d => w(%6d) => tot(%f)\n", ec, ec, cw, w); */
  497. d304 106
  498. @
  499.  
  500.  
  501. 1.1
  502. log
  503. @Initial revision
  504. @
  505. text
  506. @d3 1
  507. a3 1
  508.  *     $RCSfile$
  509. d5 1
  510. a5 1
  511.  *    $Author$
  512. d7 1
  513. a7 1
  514.  *    $Date$
  515. d9 1
  516. a9 1
  517.  *    $Revision$
  518. d13 4
  519. a16 1
  520.  *    $Log$
  521. d24 10
  522. d35 1
  523. a35 1
  524. #include "ftree.h"
  525. d37 1
  526. a37 1
  527. typedef struct
  528. d39 28
  529. a66 5
  530.     char name[64];
  531.     int nchars;
  532.     char *encoding;
  533.     int *widths;
  534. } fontd_t;
  535. d68 1
  536. a68 1
  537. char *afmNames[] =
  538. d70 23
  539. a92 3
  540.     "StartMetrics",
  541.     "EndMetrics",
  542. };
  543. d94 1
  544. a94 1
  545. void loadfont(char *name)
  546. d96 1
  547. d98 9
  548. d109 1
  549. a109 1
  550. int stringwidth(char *font, char *string)
  551. d111 36
  552. a147 1
  553. }
  554. @
  555.