Main Page   Modules   Alphabetical List   Compound List   File List   Compound Members   File Members  

fontmetric.c

Go to the documentation of this file.
00001 /*  $Id: fontmetric.c,v 1.6 2000/12/11 22:15:36 dbryson Exp $
00002 **
00003 **  Copyright (c) 2000 Derry Bryson <derry@techass.com>
00004 **
00005 **  Description:
00006 **  
00007 **    Postscript Library
00008 **
00009 **
00010 **  License:
00011 **
00012 **    This library is free software; you can redistribute it and/or
00013 **    modify it under the terms of the GNU Lesser General Public
00014 **    License as published by the Free Software Foundation; either
00015 **    version 2.1 of the License, or (at your option) any later version.
00016 **
00017 **    This library is distributed in the hope that it will be useful,
00018 **    but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 **    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020 **    Lesser General Public License for more details.
00021 **
00022 **    You should have received a copy of the GNU Lesser General Public
00023 **    License along with this library; if not, write to the Free Software
00024 **    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 **
00026 **
00027 **  Contact:
00028 **
00029 **      Mail:
00030 **
00031 **        Technology Associates, Inc.
00032 **        LIBPS Project
00033 **        1455 Deming Way #11
00034 **        Sparks, NV  89431
00035 **        USA
00036 **
00037 **      Email:
00038 **
00039 **        libps@techass.com
00040 **
00041 **      See our website at:
00042 **
00043 **        libps.sourceforge.net
00044 **
00045 */
00046 
00054 #ifdef HAVE_CONFIG_H
00055 # include "psconfig.h"
00056 #endif
00057 
00058 #include <stdio.h>
00059 #include <stdlib.h>
00060 #include <string.h>
00061 #include <ctype.h>
00062 
00063 #define PSCOMPILINGLIB
00064 #include "ps/ps.h"
00065 
00066 /******************************************************************************
00067 ****  PSAFMDirection  *********************************************************
00068 ******************************************************************************/
00069 
00078 PSAFMDirection* 
00079 psAFMDirectionAlloc(void)
00080 {
00081   return psAFMDirectionCalloc(1);
00082 }
00083 
00094 PSAFMDirection*
00095 psAFMDirectionCalloc(int count)
00096 {
00097   return calloc(count, sizeof(PSAFMDirection));
00098 }
00099 
00107 void 
00108 psAFMDirectionFree(PSAFMDirection* d)
00109 {
00110   free(d);
00111 }
00112 
00113 /******************************************************************************
00114 ****  PSAFMCharMetric  ********************************************************
00115 ******************************************************************************/
00116 
00125 PSAFMCharMetric* 
00126 psAFMCharMetricAlloc(void)
00127 {
00128   return psAFMCharMetricCalloc(1);
00129 }
00130 
00139 PSAFMCharMetric* 
00140 psAFMCharMetricCalloc(int count)
00141 {
00142   return calloc(count, sizeof(PSAFMCharMetric));
00143 }
00144 
00152 void 
00153 psAFMCharMetricFree(PSAFMCharMetric* cm)
00154 {
00155   if(cm)
00156   {
00157     if(cm->name)
00158       free(cm->name);
00159     free(cm);
00160   }
00161 }
00162 
00163 /******************************************************************************
00164 ****  PSAFM  ******************************************************************
00165 ******************************************************************************/
00166 
00175 PSAFM*
00176 psAFMAlloc(void)
00177 {
00178   return psAFMCalloc(1);
00179 }
00180 
00189 PSAFM*
00190 psAFMCalloc(int count)
00191 {
00192   return calloc(count, sizeof(PSAFM));
00193 }
00194 
00202 void
00203 psAFMFree(PSAFM *fontMetric)
00204 {
00205   int
00206     i;
00207  
00208   if(fontMetric)
00209   {
00210     if(fontMetric->fontName)
00211       free(fontMetric->fontName);
00212     if(fontMetric->fullName)
00213       free(fontMetric->fullName);
00214     if(fontMetric->familyName)
00215       free(fontMetric->familyName);
00216     if(fontMetric->weight)
00217       free(fontMetric->weight);
00218     if(fontMetric->version)
00219       free(fontMetric->version);
00220     if(fontMetric->notice)
00221       free(fontMetric->notice);
00222     if(fontMetric->encodingScheme)
00223       free(fontMetric->encodingScheme);
00224     if(fontMetric->escChar)
00225       free(fontMetric->escChar);
00226     if(fontMetric->characterSet)
00227       free(fontMetric->characterSet);
00228     if(fontMetric->charMetrics)
00229     {
00230       for(i = 0; i < fontMetric->numCharMetrics; i++)
00231         if(fontMetric->charMetrics[i].name)
00232           free(fontMetric->charMetrics[i].name);
00233       free(fontMetric->charMetrics);
00234     }
00235     free(fontMetric);
00236   }
00237 }
00238 
00248 PSAFM*
00249 psAFMLoad(char *fileName)
00250 {
00251   PSAFM
00252     *fm = NULL;
00253     
00254   FILE
00255     *fp;
00256     
00257   PSStream
00258     *str;
00259 
00260   fp = fopen(fileName, "rb");
00261   if(fp)
00262   {
00263     str = psStreamAlloc(fp, &psStandardStreamFuncs);
00264     if(str)
00265     {
00266       fm = psAFMParse(str);
00267       psStreamFree(str);
00268     }
00269     else
00270       pserrno = PSERR_ERRNO;
00271     fclose(fp);
00272   }
00273   else
00274     pserrno = PSERR_ERRNO;
00275   
00276   return fm;  
00277 }
00278 
00279 static char*
00280 StripWhiteSpace(char *s)
00281 {
00282   char
00283     *p,
00284     *q;
00285     
00286   if(s)
00287   {   
00288     /*
00289     **  Strip whitespace from front of string
00290     */
00291     for(p = s; *p && isspace(*p); p++)
00292       ;
00293     if(p != s)
00294     {
00295       for(q = s; *p; p++, q++)
00296         *q = *p;
00297       *q = 0;
00298     }
00299     
00300     /*
00301     **  Strip whitespace from end of string
00302     */
00303     for(p = s + strlen(s) - 1; p >= s && isspace(*p); p--)
00304         *p = 0;
00305   }
00306  
00307   return s;
00308 }
00309 
00310 #define MATCH(line, key)  (!strncmp((line), (key), strlen((key))))
00311 
00312 static int 
00313 ParseCharMetric(PSAFM *fm, char *line, PSAFMCharMetric *cm)
00314 {
00315   char
00316     *p;
00317     
00318   if(MATCH(line, "C"))
00319   {
00320     for(p = line + 1; *p && isspace(*p); p++)
00321       ;
00322     cm->code = atoi(p);
00323   }
00324   else if(MATCH(line, "CH"))
00325   {
00326     for(p = line + 2; *p && isspace(*p); p++)
00327       ;
00328     sscanf(p, "%x", &cm->code);
00329   }
00330   else
00331     return 0;
00332     
00333   for(; *p && *p != ';'; p++)
00334     ;
00335   if(*p = ';')
00336     p++;
00337     
00338   p = strtok(p, ";");
00339   while(p)
00340   {
00341     while(*p && isspace(*p))
00342       p++;
00343       
00344     if(MATCH(p, "WX"))
00345     {
00346       for(p = p + 2; *p && isspace(*p); p++)
00347         ;
00348       cm->wx = atoi(p);
00349     }
00350     else if(MATCH(p, "N"))
00351     {
00352       for(p = p + 1; *p && isspace(*p); p++)
00353         ;
00354       cm->name = strdup(p);
00355     }
00356     else if(MATCH(p, "B"))
00357     {
00358       /* ignore */
00359     }
00360     else if(MATCH(p, "L"))
00361     {
00362       /* ignore */
00363     }
00364     
00365     p = strtok(NULL, ";");
00366   }
00367   return 1;
00368 }
00369 
00379 PSAFM*
00380 psAFMParse(PSStream *str)
00381 {
00382   int
00383     done,
00384     state,
00385     curDirection,
00386     curCharMetric;
00387     
00388   char
00389     *p,
00390     s[PS_MAX_LINE_LEN];
00391     
00392   PSAFM
00393     *fm;
00394 
00395   pserrno = PSERR_NONE;
00396   state = AFM_STATE_START;
00397   curDirection = 0;
00398   curCharMetric = 0;
00399   
00400   fm = psAFMAlloc();
00401   if(!fm)
00402     return NULL;
00403 
00404   done = 0;  
00405   while(!done)
00406   {
00407     if(!psGetS(s, PS_MAX_LINE_LEN, str))
00408     {
00409       done = 1;
00410       continue;
00411     }
00412       
00413     StripWhiteSpace(s);
00414     if(strlen(s) && !MATCH(s, PSAFM_COMMENT))
00415     {
00416       switch(state)
00417       {
00418         case AFM_STATE_START :
00419           if(MATCH(s, PSAFM_STARTFONTMETRICS))
00420           {
00421             state = AFM_STATE_GLOBAL;
00422           }
00423           else
00424           {
00425             done = 1;
00426             pserrno = PSERR_BADAFMKEYNAME;
00427           }
00428         break;
00429       
00430         case AFM_STATE_GLOBAL :
00431           if(MATCH(s, PSAFM_STARTDIRECTION))
00432           {
00433             state = AFM_STATE_DIRECTION;
00434             curDirection = atoi(s + strlen(PSAFM_STARTDIRECTION));
00435           }
00436           else if(MATCH(s, PSAFM_STARTCHARMETRICS))
00437           {
00438             state = AFM_STATE_CHARMETRIC;
00439             for(p = s + strlen(PSAFM_STARTCHARMETRICS); *p && isspace(*p); p++)
00440               ;
00441             fm->numCharMetrics = atoi(p);
00442             fm->charMetrics = psAFMCharMetricCalloc(fm->numCharMetrics);
00443             if(!fm->charMetrics)
00444             {
00445               done = 1;
00446               pserrno = PSERR_ERRNO;
00447             }
00448           }
00449           else if(MATCH(s, PSAFM_STARTKERNINGDATA))
00450             state = AFM_STATE_KERNING;
00451           else if(MATCH(s, PSAFM_STARTCOMPOSITES))
00452             state = AFM_STATE_COMPOSITES;
00453           else if(MATCH(s, PSAFM_ENDFONTMETRICS))
00454           {
00455             pserrno = PSERR_NONE;
00456             state = AFM_STATE_DONE;
00457           }
00458           else if(MATCH(s, PSAFM_METRICSETS))
00459           {
00460             fm->metricsSets = atoi(s + strlen(PSAFM_METRICSETS));
00461           }
00462           else if(MATCH(s, PSAFM_FONTNAME))
00463           {
00464             for(p = s + strlen(PSAFM_FONTNAME); *p && isspace(*p); p++)
00465               ;
00466             fm->fontName = strdup(p);
00467           }
00468           else if(MATCH(s, PSAFM_FULLNAME))
00469           {
00470             for(p = s + strlen(PSAFM_FULLNAME); *p && isspace(*p); p++)
00471               ;
00472             fm->fullName = strdup(p);
00473           }
00474           else if(MATCH(s, PSAFM_FAMILYNAME))
00475           {
00476             for(p = s + strlen(PSAFM_FAMILYNAME); *p && isspace(*p); p++)
00477               ;
00478             fm->familyName = strdup(p);
00479           }
00480           else if(MATCH(s, PSAFM_WEIGHT))
00481           {
00482             for(p = s + strlen(PSAFM_WEIGHT); *p && isspace(*p); p++)
00483               ;
00484             fm->weight = strdup(p);
00485           }
00486           else if(MATCH(s, PSAFM_FONTBBOX))
00487           {
00488             fm->fontBBox[0] = strtod(s + strlen(PSAFM_FONTBBOX), &p);
00489             if(p)
00490               fm->fontBBox[1] = strtod(p, &p);
00491             if(p)
00492               fm->fontBBox[2] = strtod(p, &p);
00493             if(p)
00494               fm->fontBBox[3] = strtod(p, &p);
00495           }
00496           else if(MATCH(s, PSAFM_VERSION))
00497           {
00498             for(p = s + strlen(PSAFM_VERSION); *p && isspace(*p); p++)
00499               ;
00500             fm->version = strdup(p);
00501           }
00502           else if(MATCH(s, PSAFM_NOTICE))
00503           {
00504             for(p = s + strlen(PSAFM_NOTICE); *p && isspace(*p); p++)
00505               ;
00506             fm->notice = strdup(p);
00507           }
00508           else if(MATCH(s, PSAFM_ENCODINGSCHEME))
00509           {
00510             for(p = s + strlen(PSAFM_ENCODINGSCHEME); *p && isspace(*p); p++)
00511               ;
00512             fm->encodingScheme = strdup(p);
00513           }
00514           else if(MATCH(s, PSAFM_MAPPINGSCHEME))
00515           {
00516             for(p = s + strlen(PSAFM_MAPPINGSCHEME); *p && isspace(*p); p++)
00517               ;
00518             fm->mappingScheme = atoi(p);
00519           }
00520           else if(MATCH(s, PSAFM_ESCCHAR))
00521           {
00522             for(p = s + strlen(PSAFM_ESCCHAR); *p && isspace(*p); p++)
00523               ;
00524             fm->escChar = strdup(p);
00525           }
00526           else if(MATCH(s, PSAFM_CHARACTERSET))
00527           {
00528             for(p = s + strlen(PSAFM_CHARACTERSET); *p && isspace(*p); p++)
00529               ;
00530             fm->characterSet = strdup(p);
00531           }
00532           else if(MATCH(s, PSAFM_CHARACTERS))
00533           {
00534             for(p = s + strlen(PSAFM_CHARACTERS); *p && isspace(*p); p++)
00535               ;
00536             fm->characters = atoi(p);
00537           }
00538           else if(MATCH(s, PSAFM_ISBASEFONT))
00539           {
00540             for(p = s + strlen(PSAFM_ISBASEFONT); *p && isspace(*p); p++)
00541               ;
00542             fm->isBaseFont = MATCH(p, PSAFM_TRUE);
00543           }
00544           else if(MATCH(s, PSAFM_VVECTOR))
00545           {
00546             fm->vVector[0] = strtod(s + strlen(PSAFM_VVECTOR), &p);
00547             if(p)
00548               fm->vVector[1] = strtod(p, &p);
00549           }
00550           else if(MATCH(s, PSAFM_ISFIXEDV))
00551           {
00552             for(p = s + strlen(PSAFM_ISFIXEDV); *p && isspace(*p); p++)
00553               ;
00554             fm->isFixedV = MATCH(p, PSAFM_TRUE);
00555           }
00556           else if(MATCH(s, PSAFM_CAPHEIGHT))
00557           {
00558             for(p = s + strlen(PSAFM_CAPHEIGHT); *p && isspace(*p); p++)
00559               ;
00560             fm->capHeight = atof(p);
00561           }
00562           else if(MATCH(s, PSAFM_XHEIGHT))
00563           {
00564             for(p = s + strlen(PSAFM_XHEIGHT); *p && isspace(*p); p++)
00565               ;
00566             fm->xHeight = atof(p);
00567           }
00568           else if(MATCH(s, PSAFM_ASCENDER))
00569           {
00570             for(p = s + strlen(PSAFM_ASCENDER); *p && isspace(*p); p++)
00571               ;
00572             fm->ascender = atof(p);
00573           }
00574           else if(MATCH(s, PSAFM_DESCENDER))
00575           {
00576             for(p = s + strlen(PSAFM_DESCENDER); *p && isspace(*p); p++)
00577               ;
00578             fm->descender = atof(p);
00579           }
00580           else if(MATCH(s, PSAFM_UNDERLINEPOSITION))
00581           {
00582             for(p = s + strlen(PSAFM_UNDERLINEPOSITION); *p && isspace(*p); p++)
00583               ;
00584             fm->directions[curDirection].underlinePosition = atof(p);
00585           }
00586           else if(MATCH(s, PSAFM_UNDERLINETHICKNESS))
00587           {
00588             for(p = s + strlen(PSAFM_UNDERLINETHICKNESS); *p && isspace(*p); p++)
00589               ;
00590             fm->directions[curDirection].underlineThickness = atof(p);
00591           }
00592           else if(MATCH(s, PSAFM_ITALICANGLE))
00593           {
00594             for(p = s + strlen(PSAFM_ITALICANGLE); *p && isspace(*p); p++)
00595               ;
00596             fm->directions[curDirection].italicAngle = atof(p);
00597           }
00598           else if(MATCH(s, PSAFM_CHARWIDTH))
00599           {
00600             fm->directions[curDirection].charWidth[0] = strtod(s + strlen(PSAFM_CHARWIDTH), &p);
00601             if(p)
00602               fm->directions[curDirection].charWidth[1] = strtod(p, &p);
00603           }
00604           else if(MATCH(s, PSAFM_ISFIXEDPITCH))
00605           {
00606             for(p = s + strlen(PSAFM_ISFIXEDPITCH); *p && isspace(*p); p++)
00607               ;
00608             fm->directions[curDirection].isFixedPitch = MATCH(p, PSAFM_TRUE);
00609           }
00610           else
00611           {
00612             done = 1;
00613             pserrno = PSERR_BADAFMKEYNAME;
00614           }
00615         break;
00616         
00617         case AFM_STATE_DIRECTION :
00618           if(MATCH(s, PSAFM_ENDDIRECTION))
00619             state = AFM_STATE_GLOBAL;
00620           else if(MATCH(s, PSAFM_UNDERLINEPOSITION))
00621           {
00622             for(p = s + strlen(PSAFM_UNDERLINEPOSITION); *p && isspace(*p); p++)
00623               ;
00624             fm->directions[curDirection].underlinePosition = atof(p);
00625           }
00626           else if(MATCH(s, PSAFM_UNDERLINETHICKNESS))
00627           {
00628             for(p = s + strlen(PSAFM_UNDERLINETHICKNESS); *p && isspace(*p); p++)
00629               ;
00630             fm->directions[curDirection].underlineThickness = atof(p);
00631           }
00632           else if(MATCH(s, PSAFM_ITALICANGLE))
00633           {
00634             for(p = s + strlen(PSAFM_ITALICANGLE); *p && isspace(*p); p++)
00635               ;
00636             fm->directions[curDirection].italicAngle = atof(p);
00637           }
00638           else if(MATCH(s, PSAFM_CHARWIDTH))
00639           {
00640             fm->directions[curDirection].charWidth[0] = strtod(s + strlen(PSAFM_CHARWIDTH), &p);
00641             if(p)
00642               fm->directions[curDirection].charWidth[1] = strtod(p, &p);
00643           }
00644           else if(MATCH(s, PSAFM_ISFIXEDPITCH))
00645           {
00646             for(p = s + strlen(PSAFM_ISFIXEDPITCH); *p && isspace(*p); p++)
00647               ;
00648             fm->directions[curDirection].isFixedPitch = MATCH(p, PSAFM_TRUE);
00649           }
00650           else
00651           {
00652             done = 1;
00653             pserrno = PSERR_BADAFMKEYNAME;
00654           }
00655         break;
00656         
00657         case AFM_STATE_CHARMETRIC :
00658           if(MATCH(s, PSAFM_ENDCHARMETRICS))
00659             state = AFM_STATE_GLOBAL;
00660           else if(curCharMetric >= fm->numCharMetrics)
00661           {
00662             done = 1;
00663             pserrno = PSERR_TOOMANYCHARMETRICS;
00664           }
00665           else if(!ParseCharMetric(fm, s, &fm->charMetrics[curCharMetric]))
00666           {
00667             done = 1;
00668             pserrno = PSERR_BADAFMCHARMETRIC;
00669           }
00670           else 
00671             curCharMetric++;
00672         break;
00673         
00674         case AFM_STATE_KERNING :
00675           if(MATCH(s, PSAFM_ENDKERNINGDATA))
00676             state = AFM_STATE_GLOBAL;
00677         break;
00678         
00679         case AFM_STATE_COMPOSITES :
00680           if(MATCH(s, PSAFM_ENDCOMPOSITES))
00681             state = AFM_STATE_GLOBAL;
00682         break;
00683         
00684         case AFM_STATE_DONE :
00685           done = 1;
00686         break;
00687       }    
00688     }
00689   }
00690 
00691   if(pserrno)
00692   {
00693     psAFMFree(fm);
00694     fm = NULL;
00695   }  
00696   return fm;
00697 }
00698 
00709 PSAFMCharMetric* 
00710 psAFMLookupCharMetricByCode(PSAFM* fm, int code)
00711 {
00712   int
00713     i;
00714     
00715   for(i = 0; i < fm->numCharMetrics; i++)
00716     if(fm->charMetrics[i].code == code)
00717       return &fm->charMetrics[i];
00718       
00719   return NULL;
00720 }
00721 
00729 PSAFMCharMetric* 
00730 psAFMLookupCharMetricByName(PSAFM* fm, char *name)
00731 {
00732   int
00733     i;
00734     
00735   for(i = 0; i < fm->numCharMetrics; i++)
00736     if(!strcmp(fm->charMetrics[i].name, name))
00737       return &fm->charMetrics[i];
00738       
00739   return NULL;
00740 }
00741 
00751 double 
00752 psAFMGetTextWidth(PSAFM* fm, char* text)
00753 {
00754   double
00755     w = 0.0;
00756     
00757   PSAFMCharMetric
00758     *cm;
00759     
00760   while(*text)
00761   {
00762     if((cm = psAFMLookupCharMetricByCode(fm, *text)) != NULL)
00763        w += cm->wx;
00764     text++;
00765   }
00766   return w;
00767 }
00768 
00779 int psAFMGetPSWeight(PSAFM* fm)
00780 {
00781   static struct
00782   {
00783     char
00784       *name;
00785       
00786     int 
00787       weight;
00788   }
00789     weights[] = 
00790     {
00791       { "demi", PS_FONT_WEIGHT_SEMIBOLD },
00792       { "book", PS_FONT_WEIGHT_NORMAL },
00793       { "light", PS_FONT_WEIGHT_LIGHT },
00794       { "bold", PS_FONT_WEIGHT_BOLD },
00795       { "medium", PS_FONT_WEIGHT_MEDIUM },
00796       { "roman", PS_FONT_WEIGHT_NORMAL },
00797       { NULL, PS_FONT_WEIGHT_UNKNOWN }
00798     };
00799     
00800   int
00801     i;
00802       
00803   for(i = 0; weights[i].name; i++)
00804     if(!strcasecmp(weights[i].name, fm->weight))
00805       break;
00806       
00807   return weights[i].weight;
00808 }
00809 
00821 int psAFMGetPSWidth(PSAFM* fm)
00822 {
00823   return PS_FONT_WIDTH_NORMAL;
00824 }
00825 
00835 int psAFMGetPSItalic(PSAFM* fm)
00836 {
00837   return fm->directions[0].italicAngle > 0.0;
00838 }

Generated at Mon Dec 11 22:46:27 2000 for Postscript Utility Library by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000