Back to index

lightning-sunbird  0.9+nobinonly
nsAFMObject.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsAFMObject.h"
00039 #include "Helvetica.h"
00040 #include "Helvetica-Bold.h"
00041 #include "Helvetica-BoldOblique.h"
00042 #include "Helvetica-Oblique.h"
00043 #include "Times-Roman.h"
00044 #include "Times-Bold.h"
00045 #include "Times-BoldItalic.h"
00046 #include "Times-Italic.h"
00047 #include "Courier.h"
00048 #include "Courier-Bold.h"
00049 #include "Courier-BoldOblique.h"
00050 #include "Courier-Oblique.h"
00051 #include "Symbol.h"
00052 #include "nsReadableUtils.h"
00053 #include "nsVoidArray.h"
00054 
00055 struct SubstituteMap {
00056   const char *name;
00057   PRUint8    italic;
00058   PRBool     bold;
00059   PRInt16    index;
00060 };
00061 
00062 static SubstituteMap gSubstituteMap[] = {
00063   { "serif", 0,0,0},
00064   { "serif", 0,1,1},
00065   { "serif", 1,1,2},
00066   { "serif", 1,0,3},
00067   { "sans-serif", 0,0,4},
00068   { "sans-serif", 0,1,5},
00069   { "sans-serif", 1,1,6},
00070   { "sans-serif", 1,0,7},
00071   { "monospace", 0,0,8},
00072   { "monospace", 0,1,9},
00073   { "monospace", 1,1,10},
00074   { "monospace", 1,0,11},
00075 };
00076 
00077 
00078 static  const PRUint32 gNumSubstituteMap = sizeof(gSubstituteMap)/sizeof(SubstituteMap);
00079 
00080 #define NS_IS_BOLD(weight)  ((weight) >= 401 ? 1 : 0)
00081 
00082 // this is the basic font set supported currently
00083 DefFonts gSubstituteFonts[] = 
00084 {
00085   {"Times-Roman","Times",400,0,&Times_RomanAFM,AFMTimes_RomanChars,-1},
00086   {"Times-Bold","Times",700,0,&Times_BoldAFM,AFMTimes_BoldChars,-1},
00087   {"Times-BoldItalic","Times",700,1,&Times_BoldItalicAFM,AFMTimes_BoldItalicChars,-1},
00088   {"Times-Italic","Times",400,1,&Times_ItalicAFM,AFMTimes_ItalicChars,-1},
00089   {"Helvetica","Helvetica",400,0,&HelveticaAFM,AFMHelveticaChars,-1},
00090   {"Helvetica-Bold","Helvetica",700,0,&Helvetica_BoldAFM,AFMHelvetica_BoldChars,-1},
00091   {"Helvetica-BoldOblique","Helvetica",700,2,&Helvetica_BoldObliqueAFM,AFMHelvetica_BoldObliqueChars,-1},
00092   {"Helvetica-Oblique","Helvetica",400,2,&Helvetica_ObliqueAFM,AFMHelvetica_ObliqueChars,-1},
00093   {"Courier","Courier",400,0,&CourierAFM,AFMCourierChars,-1},
00094   {"Courier-Bold","Courier",700,0,&Courier_BoldAFM,AFMCourier_BoldChars,-1},
00095   {"Courier-BoldOblique","Courier",700,2,&Courier_BoldObliqueAFM,AFMCourier_BoldObliqueChars,-1},
00096   {"Courier-Oblique","Courier",400,2,&Courier_ObliqueAFM,AFMCourier_ObliqueChars,-1},
00097   {"Symbol","Symbol",400,0,&SymbolAFM,AFMSymbolChars,-1}
00098 };
00099 
00100 
00105 static struct keyname_st
00106 {
00107   const char *name;
00108   AFMKey key;
00109 } keynames[] =
00110 {
00111   {"Ascender",                     kAscender},
00112   {"Axes",                  kAxes},
00113   {"AxisLabel",             kAxisLabel},
00114   {"AxisType",                     kAxisType},
00115   {"B",                            kB},
00116   {"BlendAxisTypes",               kBlendAxisTypes},
00117   {"BlendDesignMap",               kBlendDesignMap},
00118   {"BlendDesignPositions",  kBlendDesignPositions},
00119   {"C",                            kC},
00120   {"CC",                    kCC},
00121   {"CH",                    kCH},
00122   {"CapHeight",             kCapHeight},
00123   {"CharWidth",             kCharWidth},
00124   {"CharacterSet",          kCharacterSet},
00125   {"Characters",            kCharacters},
00126   {"Comment",                      kComment},
00127   {"Descendents",           kDescendents},
00128   {"Descender",             kDescender},
00129   {"EncodingScheme",               kEncodingScheme},
00130   {"EndAxis",                      kEndAxis},
00131   {"EndCharMetrics",               kEndCharMetrics},
00132   {"EndCompFontMetrics",    kEndCompFontMetrics},
00133   {"EndComposites",         kEndComposites},
00134   {"EndDescendent",         kEndDescendent},
00135   {"EndDirection",          kEndDirection},
00136   {"EndFontMetrics",               kEndFontMetrics},
00137   {"EndKernData",           kEndKernData},
00138   {"EndKernPairs",          kEndKernPairs},
00139   {"EndMaster",             kEndMaster},
00140   {"EndMasterFontMetrics",  kEndMasterFontMetrics},
00141   {"EndTrackKern",          kEndTrackKern},
00142   {"EscChar",                      kEscChar},
00143   {"FamilyName",            kFamilyName},
00144   {"FontBBox",                     kFontBBox},
00145   {"FontName",                     kFontName},
00146   {"FullName",                     kFullName},
00147   {"IsBaseFont",            kIsBaseFont},
00148   {"IsFixedPitch",          kIsFixedPitch},
00149   {"IsFixedV",                     kIsFixedV},
00150   {"ItalicAngle",           kItalicAngle},
00151   {"KP",                    kKP},
00152   {"KPH",                   kKPH},
00153   {"KPX",                   kKPX},
00154   {"KPY",                   kKPY},
00155   {"L",                            kL},
00156   {"MappingScheme",         kMappingScheme},
00157   {"Masters",                      kMasters},
00158   {"MetricsSets",           kMetricsSets},
00159   {"N",                            kN},
00160   {"Notice",                kNotice},
00161   {"PCC",                   kPCC},
00162   {"StartAxis",             kStartAxis},
00163   {"StartCharMetrics",             kStartCharMetrics},
00164   {"StartCompFontMetrics",  kStartCompFontMetrics},
00165   {"StartComposites",              kStartComposites},
00166   {"StartDescendent",              kStartDescendent},
00167   {"StartDirection",               kStartDirection},
00168   {"StartFontMetrics",             kStartFontMetrics},
00169   {"StartKernData",         kStartKernData},
00170   {"StartKernPairs",        kStartKernPairs},
00171   {"StartMaster",           kStartMaster},
00172   {"StartMasterFontMetrics",       kStartMasterFontMetrics},
00173   {"StartTrackKern",               kStartTrackKern},
00174   {"TrackKern",             kTrackKern},
00175   {"UnderlinePosition",     kUnderlinePosition},
00176   {"UnderlineThickness",    kUnderlineThickness},
00177   {"VV",                    kVV},
00178   {"VVector",                      kVVector},
00179   {"Version",                      kVersion},
00180   {"W",                            kW},
00181   {"W0",                    kW0},
00182   {"W0X",                   kW0X},
00183   {"W0Y",                   kW0Y},
00184   {"W1",                    kW1},
00185   {"W1X",                   kW1X},
00186   {"W1Y",                   kW1Y},
00187   {"WX",                    kWX},
00188   {"WY",                    kWY},
00189   {"Weight",                kWeight},
00190   {"WeightVector",          kWeightVector},
00191   {"XHeight",                      kXHeight},
00192   {"", (AFMKey)0},
00193 };
00194 
00195 #define ISSPACE(ch) ((ch)==' '||(ch)=='\n'||(ch)=='\r'||(ch)=='\t'||(ch)==';')
00196 
00197 /*
00198  * The AFM keys.  This array must be kept sorted because keys are
00199  * searched by using binary search.
00200  */
00201 
00202 // ==============================================================================
00203 
00208 nsAFMObject :: nsAFMObject()
00209 {
00210   mPSFontInfo = nsnull;
00211 }
00212 
00217 nsAFMObject :: ~nsAFMObject()
00218 {
00219 
00220   if(mPSFontInfo->mAFMCharMetrics){
00221     delete [] mPSFontInfo->mAFMCharMetrics;
00222   }
00223 
00224   if(mPSFontInfo){
00225     delete mPSFontInfo;
00226   }
00227 }
00228 
00234 void
00235 nsAFMObject :: Init(nscoord aFontHeight)
00236 {
00237   // read the file asked for
00238   mFontHeight = aFontHeight;
00239 }
00240 
00245 PRInt16
00246 nsAFMObject::CheckBasicFonts(const nsFont &aFont,PRBool aPrimaryOnly)
00247 {
00248 PRInt16     ourfont = -1;
00249 PRInt32     i,curIndex,score;
00250 nsAutoString    psfontname;
00251 
00252   // have to find the correct fontfamily, weight and style
00253   psfontname = aFont.name;
00254   
00255   // look in the font table for one of the fonts in the passed in list
00256   for(i=0,curIndex=-1;i<NUM_AFM_FONTS;i++){
00257     gSubstituteFonts[i].mIndex = psfontname.RFind((const char*)gSubstituteFonts[i].mFamily,PR_TRUE);
00258 
00259     // if a font was found matching this criteria
00260     if((gSubstituteFonts[i].mIndex==0) || (!aPrimaryOnly && gSubstituteFonts[i].mIndex>=0)){
00261       // give it a score
00262       score = abs(PRInt32(aFont.weight)-PRInt32(gSubstituteFonts[i].mWeight));
00263       score+= abs(PRInt32(aFont.style)-PRInt32(gSubstituteFonts[i].mStyle));
00264       if(score == 0){
00265         curIndex = i;
00266         break;
00267       }
00268       gSubstituteFonts[i].mIndex = score;
00269     }
00270   }
00271   
00272   // if its ok to look for the second best, and we did not find a perfect match
00273   score = 32000;
00274   if((PR_FALSE == aPrimaryOnly)&&(curIndex !=0)) {
00275     for(i=0;i<NUM_AFM_FONTS;i++){
00276       if((gSubstituteFonts[i].mIndex>0) && (gSubstituteFonts[i].mIndex<score)){
00277         score = gSubstituteFonts[i].mIndex;
00278         curIndex = i;
00279       }   
00280     }
00281   }
00282 
00283 
00284   if(curIndex>=0){
00285     mPSFontInfo = new AFMFontInformation;
00286     memset(mPSFontInfo,0,sizeof(AFMFontInformation));
00287     
00288     memcpy(mPSFontInfo,(gSubstituteFonts[curIndex].mFontInfo),sizeof(AFMFontInformation));
00289     mPSFontInfo->mAFMCharMetrics = new AFMscm[mPSFontInfo->mNumCharacters];
00290     memset(mPSFontInfo->mAFMCharMetrics,0,sizeof(AFMscm)*mPSFontInfo->mNumCharacters);
00291     memcpy(mPSFontInfo->mAFMCharMetrics,gSubstituteFonts[curIndex].mCharInfo,gSubstituteFonts[curIndex].mFontInfo->mNumCharacters*sizeof(AFMscm));
00292     ourfont = curIndex;
00293   }
00294   
00295   return ourfont;
00296 }
00297 
00301 static PRBool PR_CALLBACK
00302 GenericFontEnumCallback(const nsString& aFamily, PRBool aGeneric, void* aData)
00303 {
00304   nsVoidArray* array = NS_STATIC_CAST(nsVoidArray*, aData);
00305   char* name = ToNewCString(aFamily);
00306   if (name) {
00307     array->AppendElement(name);
00308     return PR_TRUE; // don't stop
00309   }
00310   return PR_FALSE;
00311 }
00312 
00317 PRInt16
00318 nsAFMObject::CreateSubstituteFont(const nsFont &aFontName)
00319 {
00320 PRInt16     ourfont = 0;
00321 PRUint32    i = gNumSubstituteMap;
00322 
00323   // Get Font List
00324   nsVoidArray fontNames;
00325   // Iterate over the list of names using the callback mechanism of nsFont...
00326   aFontName.EnumerateFamilies(GenericFontEnumCallback, &fontNames); // ignore return value
00327 
00328   PRInt32 k;
00329   PRBool found = PR_FALSE;
00330   for (k=0;k<fontNames.Count() && !found;k++) {
00331     char * fontName = (char*)fontNames[k];
00332     for(i=0;i<gNumSubstituteMap;i++) {
00333       //printf("Looking for Name[%s] Checking [%s]\n", NS_LossyConvertUCS2toASCII(name).get(),gSubstituteMap[i].name);
00334       if(!nsCRT::strcasecmp(fontName, gSubstituteMap[i].name) && 
00335          (aFontName.style != NS_FONT_STYLE_NORMAL)== gSubstituteMap[i].italic &&
00336          NS_IS_BOLD(aFontName.weight) == gSubstituteMap[i].bold) {
00337         ourfont = gSubstituteMap[i].index;
00338         found = PR_TRUE;
00339         break;
00340       }
00341     }
00342   } // for
00343 
00344   for (k=0;k<fontNames.Count();k++) {
00345     nsMemory::Free((char*)fontNames[k]);
00346   }
00347 
00348   // no matches in the substitution table -- default to times
00349   if(i == gNumSubstituteMap){
00350 
00351 #ifdef DEBUG
00352     printf(" NO FONT WAS FOUND Name[%s]\n", NS_LossyConvertUCS2toASCII(aFontName.name).get());
00353 #endif
00354     if(aFontName.style == NS_FONT_STYLE_NORMAL){
00355       ourfont = NS_IS_BOLD(aFontName.weight) ? 1 : 0;
00356     } else {
00357       ourfont = NS_IS_BOLD(aFontName.weight) ? 2 : 3;
00358     }
00359   }
00360 
00361   mPSFontInfo = new AFMFontInformation;
00362   memset(mPSFontInfo,0,sizeof(AFMFontInformation));
00363 
00364   // put in default AFM data, can't find the correct AFM file
00365   memcpy(mPSFontInfo,gSubstituteFonts[ourfont].mFontInfo,sizeof(AFMFontInformation));
00366   mPSFontInfo->mAFMCharMetrics = new AFMscm[mPSFontInfo->mNumCharacters];
00367   memset(mPSFontInfo->mAFMCharMetrics,0,sizeof(AFMscm)*mPSFontInfo->mNumCharacters);
00368   memcpy(mPSFontInfo->mAFMCharMetrics,gSubstituteFonts[ourfont].mCharInfo,Times_RomanAFM.mNumCharacters*sizeof(AFMscm));
00369   return ourfont;
00370 }
00371 
00376 PRBool
00377 nsAFMObject::AFM_ReadFile(const nsFont &aFontName)
00378 {
00379 PRBool  done=PR_FALSE;
00380 PRBool  success = PR_FALSE;
00381 PRBool  bvalue;
00382 AFMKey  key;
00383 double  value;
00384 PRInt32 ivalue;
00385 char* AFMFileName= ToNewUTF8String(aFontName.name); // file we will open
00386 
00387   if(nsnull == AFMFileName) 
00388     return (success);
00389 
00390     if((0==strcmp(AFMFileName,"..")) || (0==strcmp(AFMFileName,"."))) {
00391       Recycle(AFMFileName);
00392       return (success);
00393     }
00394 
00395    // Open the file
00396   mAFMFile = fopen((const char *)AFMFileName,"r");
00397   Recycle(AFMFileName);
00398 
00399   if(nsnull != mAFMFile) {
00400     // create the structure to put the information in
00401     mPSFontInfo = new AFMFontInformation;
00402     memset(mPSFontInfo,0,sizeof(AFMFontInformation));
00403 
00404     // Check for valid AFM file
00405     GetKey(&key);
00406     if(key == kStartFontMetrics){
00407       GetAFMNumber(&mPSFontInfo->mFontVersion);
00408 
00409       while(!done){
00410         GetKey(&key);
00411         switch (key){
00412           case kComment:
00413             GetLine();
00414             break;
00415           case kStartFontMetrics:
00416             GetAFMNumber(&mPSFontInfo->mFontVersion);
00417             break;
00418           case kEndFontMetrics:
00419             done = PR_TRUE;
00420             break;
00421           case kStartCompFontMetrics:
00422           case kEndCompFontMetrics:
00423           case kStartMasterFontMetrics:
00424           case kEndMasterFontMetrics:
00425             break;
00426           case kFontName:
00427             mPSFontInfo->mFontName = GetAFMString();
00428             break;
00429           case kFullName:
00430             mPSFontInfo->mFullName = GetAFMString();
00431             break;
00432           case kFamilyName:
00433             mPSFontInfo->mFamilyName = GetAFMString();
00434             break;
00435           case kWeight:
00436             mPSFontInfo->mWeight = GetAFMString();
00437             break;
00438           case kFontBBox:
00439             GetAFMNumber(&mPSFontInfo->mFontBBox_llx);
00440             GetAFMNumber(&mPSFontInfo->mFontBBox_lly);
00441             GetAFMNumber(&mPSFontInfo->mFontBBox_urx);
00442             GetAFMNumber(&mPSFontInfo->mFontBBox_ury);
00443             break;
00444           case kVersion:
00445             mPSFontInfo->mVersion = GetAFMString();
00446             break;
00447                case kNotice:
00448                  mPSFontInfo->mNotice = GetAFMString();
00449             // we really dont want to keep this around...
00450             delete [] mPSFontInfo->mNotice;
00451             mPSFontInfo->mNotice = 0;
00452                  break;
00453                case kEncodingScheme:
00454                  mPSFontInfo->mEncodingScheme = GetAFMString();
00455                  break;
00456                case kMappingScheme:
00457                  GetAFMInt(&mPSFontInfo->mMappingScheme);
00458                  break;
00459                case kEscChar:
00460                  GetAFMInt(&mPSFontInfo->mEscChar);
00461                  break;
00462                case kCharacterSet:
00463                  mPSFontInfo->mCharacterSet = GetAFMString();
00464                  break;
00465                case kCharacters:
00466                  GetAFMInt(&mPSFontInfo->mCharacters);
00467                  break;
00468                case kIsBaseFont:
00469                  GetAFMBool (&mPSFontInfo->mIsBaseFont);
00470                  break;
00471                case kVVector:
00472                  GetAFMNumber(&mPSFontInfo->mVVector_0);
00473                  GetAFMNumber(&mPSFontInfo->mVVector_1);
00474                  break;
00475                case kIsFixedV:
00476                  GetAFMBool (&mPSFontInfo->mIsFixedV);
00477                  break;
00478                case kCapHeight:
00479                  GetAFMNumber(&mPSFontInfo->mCapHeight);
00480                  break;
00481                case kXHeight:
00482                  GetAFMNumber(&mPSFontInfo->mXHeight);
00483                  break;
00484                case kAscender:
00485                  GetAFMNumber(&mPSFontInfo->mAscender);
00486                  break;
00487                case kDescender:
00488                  GetAFMNumber(&mPSFontInfo->mDescender);
00489                  break;
00490                case kStartDirection:
00491                  GetAFMInt(&ivalue);
00492                  break;
00493                case kUnderlinePosition:
00494                  GetAFMNumber(&mPSFontInfo->mUnderlinePosition);
00495                  break;
00496                case kUnderlineThickness:
00497                  GetAFMNumber(&mPSFontInfo->mUnderlineThickness);
00498                  break;
00499                case kItalicAngle:
00500                  GetAFMNumber(&value);
00501                  break;
00502                case kCharWidth:
00503                  GetAFMNumber(&value);   // x
00504                  GetAFMNumber(&value);   // y
00505                  break;
00506                case kIsFixedPitch:
00507                  GetAFMBool (&bvalue);
00508                  break;
00509                case kEndDirection:
00510                  break;
00511                case kStartCharMetrics:
00512                  GetAFMInt(&mPSFontInfo->mNumCharacters);     // number of charaters that follow
00513             mPSFontInfo->mAFMCharMetrics = new AFMscm[mPSFontInfo->mNumCharacters];
00514             memset(mPSFontInfo->mAFMCharMetrics,0,sizeof(AFMscm)*mPSFontInfo->mNumCharacters);
00515                  ReadCharMetrics (mPSFontInfo,mPSFontInfo->mNumCharacters);
00516                  break;
00517                case kStartKernData:
00518                  break;
00519                case kStartKernPairs:
00520             break;
00521           default:
00522             break;
00523         }
00524       }
00525     }
00526   fclose(mAFMFile);
00527   success = PR_TRUE;
00528   } else {
00529   // put in default AFM data, can't find the correct AFM file
00530   //memcpy(mPSFontInfo,&HelveticaAFM,sizeof(AFMFontInformation));
00531  // mPSFontInfo->mAFMCharMetrics = new AFMscm[mPSFontInfo->mNumCharacters];
00532   //memset(mPSFontInfo->mAFMCharMetrics,0,sizeof(AFMscm)*mPSFontInfo->mNumCharacters);
00533   //memcpy(mPSFontInfo->mAFMCharMetrics,AFMHelveticaChars,HelveticaAFM.mNumCharacters*sizeof(AFMscm));
00534   }
00535 
00536   return(success);
00537 }
00538 
00543 void
00544 
00545 nsAFMObject::GetKey(AFMKey *aKey)
00546 {
00547 PRInt32   key,len;
00548 
00549   while(1){
00550     len = GetToken(); 
00551     if(len>0) {
00552       key = MatchKey(mToken);
00553       if(key >=0){
00554         *aKey = (AFMKey)key;
00555         return;
00556       }
00557 
00558     GetLine(); // skip the entire line, and key
00559     }
00560   }
00561 }
00562 
00567 PRInt32
00568 nsAFMObject::MatchKey(char *aKey)
00569 {
00570 PRInt32 lower = 0;
00571 PRInt32 upper = NUM_KEYS;
00572 PRInt32 midpoint,cmpvalue;
00573 PRBool  found = PR_FALSE;
00574 
00575   while((upper >=lower) && !found) {
00576     midpoint = (lower+upper)/2;
00577     if(keynames[midpoint].name == nsnull) {
00578       break;
00579     }
00580     cmpvalue = strcmp(aKey,keynames[midpoint].name);
00581     if(cmpvalue == 0){
00582       found = PR_TRUE;
00583     }else{
00584      if (cmpvalue <0){
00585         upper = midpoint-1;
00586       }else{
00587         lower = midpoint+1;
00588       }
00589     }
00590   }
00591 
00592   if(found)
00593     return keynames[midpoint].key;
00594   else
00595     return -1;
00596 }
00597 
00602 PRInt32
00603 nsAFMObject::GetToken()
00604 {
00605 PRInt32   ch;
00606 PRInt32   i;
00607 PRInt32   len;
00608 
00609   // skip leading whitespace
00610   while((ch=getc(mAFMFile)) != EOF) {
00611     if(!ISSPACE(ch))
00612       break;
00613   }
00614 
00615   if(ch == EOF)
00616     return 0;
00617 
00618   ungetc(ch,mAFMFile);
00619 
00620   // get name
00621   len = (PRInt32)sizeof(mToken);
00622   for(i=0,ch=getc(mAFMFile);i<len && ch!=EOF && !ISSPACE(ch);i++,ch=getc(mAFMFile)){
00623       mToken[i] = ch;
00624   }
00625 
00626   // is line longer than the AFM specifications
00627   if(((PRUint32)i)>=sizeof(mToken))
00628     return 0;
00629 
00630   mToken[i] = '\0';
00631   return i;
00632 }
00633 
00634 
00639 PRInt32 
00640 nsAFMObject::GetLine()
00641 {
00642 PRInt32 i, ch;
00643 
00644   // Skip the leading whitespace. 
00645   while ((ch = getc (mAFMFile)) != EOF){
00646       if (!ISSPACE (ch))
00647         break;
00648   }
00649 
00650   if (ch == EOF)
00651     return 0;
00652 
00653   ungetc (ch, mAFMFile);
00654 
00655   // Read to the end of the line. 
00656   for (i = 0, ch = getc (mAFMFile);((PRUint32)i) < sizeof (mToken) - 1 && ch != EOF && ch != '\n';i++, ch = getc (mAFMFile)){
00657     mToken[i] = ch;
00658   }
00659 
00660   if (((PRUint32)i) >= sizeof (mToken) - 1){
00661     //parse_error (handle, AFM_ERROR_SYNTAX);
00662   }
00663 
00664   // Skip all trailing whitespace. 
00665   for (i--; i >= 0 && ISSPACE (mToken[i]); i--)
00666     ;
00667   i++;
00668 
00669   mToken[i] = '\0';
00670 
00671   return i;
00672 }
00673 
00678 void
00679 nsAFMObject::GetAFMBool (PRBool *aBool)
00680 {
00681 
00682   GetToken();
00683   if (strcmp (mToken, "true") == 0) {
00684          *aBool = PR_TRUE;
00685   }else if(strcmp (mToken, "false")){
00686     *aBool = PR_FALSE;
00687   }else {
00688     *aBool = PR_FALSE;
00689   }
00690 }
00691 
00696 void
00697 nsAFMObject::ReadCharMetrics (AFMFontInformation *aFontInfo,PRInt32 aNumCharacters)
00698 {
00699 PRInt32 i = 0,ivalue,first=1;
00700 AFMscm  *cm = nsnull;
00701 AFMKey  key;
00702 PRBool  done = PR_FALSE;
00703 double  notyet;
00704 char    *name;
00705 
00706   while (done!=PR_TRUE && i<aNumCharacters){
00707     GetKey (&key);
00708     switch (key){
00709       case kC:
00710         if (first){
00711           first = 0;
00712         }else{
00713           i++;
00714         }
00715         if (i >= aNumCharacters){
00716           done = PR_TRUE;
00717           //parse_error (handle, AFM_ERROR_SYNTAX);
00718         }
00719 
00720         cm = &(aFontInfo->mAFMCharMetrics[i]);
00721         // character code
00722         GetAFMInt(&ivalue);          // character code
00723         cm->mCharacter_Code = ivalue;
00724         //if (cm->mCharacter_Code >= 0 && cm->mCharacter_Code <= 255)
00725           //font->encoding[cm->character_code] = cm;
00726         break;
00727       case kCH:
00728         break;
00729       case kWX:
00730       case kW0X:
00731         GetAFMNumber(&(cm->mW0x));
00732         cm->mW0y = 0.0;
00733         break;
00734       case kW1X:
00735         GetAFMNumber(&(cm->mW1x));
00736         cm->mW1y = 0.0;
00737         break;
00738       case kWY:
00739       case kW0Y:
00740         GetAFMNumber(&(cm->mW0y));
00741         cm->mW0x = 0.0;
00742         break;
00743       case kW1Y:
00744         GetAFMNumber(&(cm->mW1y));
00745         cm->mW1x = 0.0;
00746         break;
00747       case kW:
00748       case kW0:
00749         GetAFMNumber(&(cm->mW0x));
00750         GetAFMNumber(&(cm->mW0y));
00751         break;
00752 
00753       case kW1:
00754         GetAFMNumber(&(cm->mW1x));
00755         GetAFMNumber(&(cm->mW1y));
00756         break;
00757       case kVV:
00758         //GetAFMNumber(&(cm->mVv_x));
00759         //GetAFMNumber(&(cm->mVv_y));
00760         GetAFMNumber(&notyet);
00761         GetAFMNumber(&notyet);
00762         break;
00763       case kN:
00764         //cm->mName = GetAFMName();
00765         name = GetAFMName();
00766         delete [] name;
00767         break;
00768 
00769       case kB:
00770         GetAFMNumber(&(cm->mLlx));
00771         GetAFMNumber(&(cm->mLly));
00772         GetAFMNumber(&(cm->mUrx));
00773         GetAFMNumber(&(cm->mUry));
00774         break;
00775       case kL:
00776         // XXX Skip ligatures.
00777         GetLine ();
00778       break;
00779 
00780       case kEndCharMetrics:
00781         //  SYNTAX ERROR???
00782         done = PR_TRUE;
00783         break;
00784       default:
00785         break;
00786     }
00787   }
00788 }
00789 
00790 
00795 char*
00796 nsAFMObject::GetAFMString (void) 
00797 {
00798 PRInt32 len;
00799 char    *thestring;
00800 
00801   GetLine();
00802   len = strlen(mToken);
00803   thestring = new char[len+1];
00804   strcpy(thestring,mToken);
00805   return(thestring);
00806 }
00807 
00812 char*
00813 nsAFMObject::GetAFMName (void) 
00814 {
00815 PRInt32 len;
00816 char    *thestring;
00817 
00818   GetToken();
00819   len = strlen(mToken);
00820   thestring = new char[len+1];
00821   strcpy(thestring,mToken);
00822   return(thestring);
00823 }
00824 
00832 void
00833 nsAFMObject :: GetStringWidth(const char *aString,nscoord& aWidth,nscoord aLength)
00834 {
00835 char    *cptr;
00836 PRInt32 i,idx,fwidth;
00837 float   totallen=0.0f;
00838 
00839   // add up the length of the character widths, in floating to avoid roundoff
00840   aWidth = 0;
00841   cptr = (char*) aString;
00842   for(i=0;i<aLength;i++,cptr++){
00843     idx = *cptr-32;
00844     fwidth = (PRInt32)(mPSFontInfo->mAFMCharMetrics[idx].mW0x);
00845     totallen += fwidth;
00846   }
00847 
00848   // totallen is in 1/1000's of a point for a one-point-high version of the
00849   // font. Scale by the desired font height (which is in twips).
00850   aWidth = NSToCoordRound((totallen * mFontHeight)/1000.0f);
00851 }
00852 
00853 
00861 void
00862 nsAFMObject :: GetStringWidth(const PRUnichar *aString,nscoord& aWidth,nscoord aLength)
00863 {
00864 PRUint8   asciichar;
00865 PRUnichar *cptr;
00866 PRInt32   i ,fwidth,idx;
00867 float     totallen=0.0f;
00868 
00869  //XXX This needs to get the aString converted to a normal cstring  DWC
00870  aWidth = 0;
00871  cptr = (PRUnichar*)aString;
00872 
00873   for(i=0;i<aLength;i++,cptr++){
00874     fwidth = 0;
00875     if (*cptr & 0xff00)
00876     {
00877       if (0x0400 == (*cptr & 0xff00)) { // Cyrillic
00878         fwidth = 600;
00879       } else {
00880         fwidth = 1056;
00881       }
00882     } else {
00883       // < 0x0100
00884       asciichar = (*cptr)&0x00ff;
00885       idx = asciichar-32;
00886       if(idx >= 0 )
00887         fwidth = (PRInt32)(mPSFontInfo->mAFMCharMetrics[idx].mW0x);
00888       else if (*cptr  == 0x0020) 
00889         fwidth = 1056;
00890     }
00891 
00892     totallen += fwidth;
00893   }
00894 
00895   // totallen is in 1/1000ths of a point for a one-point-high version of the
00896   // font. Scale by the desired font height (which is in twips).
00897   aWidth = NSToCoordRound((totallen * mFontHeight)/1000.0f);
00898 }
00899 
00900 
00901 
00902 #define CORRECTSTRING(d)  (d?d:"")
00903 #define BOOLOUT(B)        (mPSFontInfo->mIsBaseFont==PR_TRUE?"PR_TRUE":"PR_FALSE")
00904 
00909 void    
00910 nsAFMObject :: WriteFontHeaderInformation(FILE *aOutFile)
00911 {
00912 
00913   // main information of the font
00914   fprintf(aOutFile,"%f,\n",mPSFontInfo->mFontVersion);
00915   fprintf(aOutFile,"\"%s\",\n",CORRECTSTRING(mPSFontInfo->mFontName));
00916   fprintf(aOutFile,"\"%s\",\n",CORRECTSTRING(mPSFontInfo->mFullName));
00917   fprintf(aOutFile,"\"%s\",\n",CORRECTSTRING(mPSFontInfo->mFamilyName));
00918   fprintf(aOutFile,"\"%s\",\n",CORRECTSTRING(mPSFontInfo->mWeight));
00919   fprintf(aOutFile,"%f,\n",mPSFontInfo->mFontBBox_llx);
00920   fprintf(aOutFile,"%f,\n",mPSFontInfo->mFontBBox_lly);
00921   fprintf(aOutFile,"%f,\n",mPSFontInfo->mFontBBox_urx);
00922   fprintf(aOutFile,"%f,\n",mPSFontInfo->mFontBBox_ury);
00923   fprintf(aOutFile,"\"%s\",\n",CORRECTSTRING(mPSFontInfo->mVersion));
00924   fprintf(aOutFile,"\"%s\",\n",CORRECTSTRING(mPSFontInfo->mNotice));
00925   fprintf(aOutFile,"\"%s\",\n",CORRECTSTRING(mPSFontInfo->mEncodingScheme));
00926   fprintf(aOutFile,"%d,\n",mPSFontInfo->mMappingScheme);
00927   fprintf(aOutFile,"%d,\n",mPSFontInfo->mEscChar);
00928   fprintf(aOutFile,"\"%s\",\n", CORRECTSTRING(mPSFontInfo->mCharacterSet));
00929   fprintf(aOutFile,"%d,\n",mPSFontInfo->mCharacters);
00930   fprintf(aOutFile,"%s,\n",BOOLOUT(mPSFontInfo->mIsBaseFont));
00931   fprintf(aOutFile,"%f,\n",mPSFontInfo->mVVector_0);
00932   fprintf(aOutFile,"%f,\n",mPSFontInfo->mVVector_1);
00933   fprintf(aOutFile,"%s,\n",BOOLOUT(mPSFontInfo->mIsFixedV));
00934   fprintf(aOutFile,"%f,\n",mPSFontInfo->mCapHeight);
00935   fprintf(aOutFile,"%f,\n",mPSFontInfo->mXHeight);
00936   fprintf(aOutFile,"%f,\n",mPSFontInfo->mAscender);
00937   fprintf(aOutFile,"%f,\n",mPSFontInfo->mDescender);
00938   fprintf(aOutFile,"%f,\n",mPSFontInfo->mUnderlinePosition);
00939   fprintf(aOutFile,"%f,\n",mPSFontInfo->mUnderlineThickness);
00940   fprintf(aOutFile,"%d\n",mPSFontInfo->mNumCharacters);
00941 }
00942 
00947 void    
00948 nsAFMObject :: WriteFontCharInformation(FILE *aOutFile)
00949 {
00950 PRInt32 i;
00951 
00952 
00953   // individual font characteristics
00954   for(i=0;i<mPSFontInfo->mNumCharacters;i++) {
00955     fprintf(aOutFile,"{\n");
00956     fprintf(aOutFile,"%d, \n",mPSFontInfo->mAFMCharMetrics[i].mCharacter_Code);
00957     fprintf(aOutFile,"%f, \n",mPSFontInfo->mAFMCharMetrics[i].mW0x);
00958     fprintf(aOutFile,"%f, \n",mPSFontInfo->mAFMCharMetrics[i].mW0y);
00959     fprintf(aOutFile,"%f, \n",mPSFontInfo->mAFMCharMetrics[i].mW1x);
00960     fprintf(aOutFile,"%f, \n",mPSFontInfo->mAFMCharMetrics[i].mW1y);
00961     //fprintf(aOutFile,"\"%s\", \n", CORRECTSTRING(mPSFontInfo->mAFMCharMetrics[i].mName));
00962     //fprintf(aOutFile,"%f, \n",mPSFontInfo->mAFMCharMetrics[i].mVv_x);
00963     //fprintf(aOutFile,"%f, \n",mPSFontInfo->mAFMCharMetrics[i].mVv_y);
00964     fprintf(aOutFile,"%f, \n",mPSFontInfo->mAFMCharMetrics[i].mLlx);
00965     fprintf(aOutFile,"%f, \n",mPSFontInfo->mAFMCharMetrics[i].mLly);
00966     fprintf(aOutFile,"%f, \n",mPSFontInfo->mAFMCharMetrics[i].mUrx);
00967     fprintf(aOutFile,"%f \n",mPSFontInfo->mAFMCharMetrics[i].mUry);
00968     //fprintf(aOutFile,"%f, \n",mPSFontInfo->mAFMCharMetrics[i].num_ligatures);
00969     fprintf(aOutFile,"}\n");
00970     if ( i != mPSFontInfo->mNumCharacters - 1 )
00971        fputc( ',', aOutFile ); 
00972     fputc( '\n', aOutFile );
00973   }
00974 }
00975