Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2318 lines
72 KiB

  1. //---------------------------------------------------------------------------
  2. // makepfm.c
  3. //---------------------------------------------------------------------------
  4. // Create PFM file for Rev-3 fonts
  5. //---------------------------------------------------------------------------
  6. //
  7. // Copyright 1990, 1991 -- Adobe Systems, Inc.
  8. // PostScript is a trademark of Adobe Systems, Inc.
  9. //
  10. // NOTICE: All information contained herein or attendant hereto is, and
  11. // remains, the property of Adobe Systems, Inc. Many of the intellectual
  12. // and technical concepts contained herein are proprietary to Adobe Systems,
  13. // Inc. and may be covered by U.S. and Foreign Patents or Patents Pending or
  14. // are protected as trade secrets. Any dissemination of this information or
  15. // reproduction of this material are strictly forbidden unless prior written
  16. // permission is obtained from Adobe Systems, Inc.
  17. //
  18. //---------------------------------------------------------------------------
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <fcntl.h>
  23. #include <ctype.h>
  24. #include <io.h>
  25. #include <sys\types.h>
  26. #include <sys\stat.h>
  27. #include "windows.h"
  28. #pragma pack(1)
  29. #include "makepfm.h"
  30. #pragma pack(4)
  31. #include "fvscodes.h" // FVS_xxxxxx (font validation status) codes and macros.
  32. #ifdef WIN30
  33. #define LPCSTR LPSTR
  34. #endif
  35. #define WINATM 1
  36. #if !WINATM
  37. LPSZ stringtable[] = {
  38. "MAKEPFM utility version %s released on %s.\n",
  39. "Copyright (C) 1989-91, Adobe Systems Inc. All Rights Reserved.\n\n",
  40. "Usage: makepfm [options] AFMfile\n",
  41. " -h n - set device to PCL (n=1 for 1 byte typeface, 2 for 2 byte).\n",
  42. " -p n - integral point size - only for PCL.\n",
  43. " -c str - PCL symbol set (9U for WinAnsi for example) - only for PCL.\n",
  44. " -d - set orientation to landscape - only for PCL.\n",
  45. " -e str - encoding file.\n",
  46. " -o str - output file.\n",
  47. " -i str - fontinfo file.\n",
  48. " -l str - optional log file - defaults to \"user.log\".\n",
  49. " -f str - take input parameters from file instead of command line.\n",
  50. " -w - display warning messages.\n",
  51. " -s n - force dfCharSet to n.\n",
  52. "Unrecognized command-line option: '%s'\n",
  53. "Unable to open: %s\n",
  54. "Too many track kerning data. Ignoring after %d.\n",
  55. "Unexpected end of file - expected: %s\n",
  56. "Expected: %s - current line: %s\n",
  57. "Parsing character metrics - current line: %s\n",
  58. "Parsing %s.\n",
  59. "Missing \"MSFamily\" value\n",
  60. "Can't create: %s\n",
  61. "Disk is full...\n",
  62. "Memory allocation\n",
  63. "encoding file",
  64. "Creating font metrics ( %s )",
  65. "Finished.\n",
  66. NULL
  67. };
  68. #endif
  69. AFM afm = { 0 };
  70. static ETM etm;
  71. static PFM pfm;
  72. static PFMEXT pfmext;
  73. static DRIVERINFO d;
  74. typedef LPSZ GlyphName;
  75. /* CHAR rgbBuffer[2048]; The file buffer */
  76. CHAR rgbBuffer[8704] = ""; /* increased to handle an additional 512 bytes of width info */
  77. static INT cbBuffer; /* The number of bytes in the buffer */
  78. static INT cbMaxBuffer; /* Maximum size of the buffer */
  79. static LPSZ pbBuffer; /* Ptr to current location in buffer */
  80. static CHAR rgbLine[160]; /* The current line of text being processed */
  81. static LPSZ szLine; /* Ptr to the current location in the line */
  82. static BOOL fEOF = FALSE;
  83. static BOOL fUnGetLine = FALSE;
  84. /*----------------------------------------------------------------------------*/
  85. static LPSZ notdef = "";
  86. #define IBULLET 0x095 /* 87-1-15 sec (was 1) */
  87. #define ISPACE 0x20
  88. #define IWINSPACE 0xA0
  89. static BOOL parseError;
  90. static float sf; /* scale factor for converting to display widths */
  91. /* flags type of PFM to build POSTSCRIPT vs PCL */
  92. INT devType = POSTSCRIPT;
  93. PCLINFO pclinfo = { PORTRAIT, WINANSI_SET, epsymGENERIC8, 0, 0, 2, 0, NULL };
  94. static SHORT fiCapHeight;
  95. static GlyphName *glyphArray;
  96. extern GlyphName *SetupGlyphArray(LPSZ) ;
  97. INT charset = -1;
  98. static BOOL forceVariablePitch = TRUE;
  99. /* names, pointers, and handles for output, log and data files */
  100. CHAR encfile[MAX_PATH] = "";
  101. CHAR outfile[MAX_PATH] = "";
  102. CHAR infofile[MAX_PATH] = "";
  103. static INT fhIn;
  104. #define TK_STARTKERNDATA 2
  105. #define TK_STARTKERNPAIRS 3
  106. #define TK_KPX 4
  107. #define TK_ENDKERNPAIRS 5
  108. #define TK_ENDKERNDATA 6
  109. #define TK_FONTNAME 7
  110. #define TK_WEIGHT 8
  111. #define TK_ITALICANGLE 9
  112. #define TK_ISFIXEDPITCH 10
  113. #define TK_UNDERLINEPOSITION 11
  114. #define TK_UNDERLINETHICKNESS 12
  115. #define TK_FONTBBOX 13
  116. #define TK_CAPHEIGHT 14
  117. #define TK_XHEIGHT 15
  118. #define TK_DESCENDER 16
  119. #define TK_ASCENDER 17
  120. #define TK_STARTCHARMETRICS 18
  121. #define TK_ENDCHARMETRICS 19
  122. #define TK_ENDFONTMETRICS 20
  123. #define TK_STARTFONTMETRICS 21
  124. #define TK_STARTTRACKKERN 22
  125. #define TK_TRACKKERN 23
  126. #define TK_ENDTRACKKERN 24
  127. static KEY afmKeys[] = {
  128. "FontBBox", TK_FONTBBOX,
  129. "StartFontMetrics", TK_STARTFONTMETRICS,
  130. "FontName", TK_FONTNAME,
  131. "Weight", TK_WEIGHT,
  132. "ItalicAngle", TK_ITALICANGLE,
  133. "IsFixedPitch", TK_ISFIXEDPITCH,
  134. "UnderlinePosition", TK_UNDERLINEPOSITION,
  135. "UnderlineThickness", TK_UNDERLINETHICKNESS,
  136. "CapHeight", TK_CAPHEIGHT,
  137. "XHeight", TK_XHEIGHT,
  138. "Descender", TK_DESCENDER,
  139. "Ascender", TK_ASCENDER,
  140. "StartCharMetrics", TK_STARTCHARMETRICS,
  141. "EndCharMetrics", TK_ENDCHARMETRICS,
  142. "StartKernData", TK_STARTKERNDATA,
  143. "StartKernPairs", TK_STARTKERNPAIRS,
  144. "KPX", TK_KPX,
  145. "EndKernPairs", TK_ENDKERNPAIRS,
  146. "EndKernData", TK_ENDKERNDATA,
  147. "EndFontMetrics", TK_ENDFONTMETRICS,
  148. "StartTrackKern", TK_STARTTRACKKERN,
  149. "TrackKern", TK_TRACKKERN,
  150. "EndTrackKern", TK_ENDTRACKKERN,
  151. NULL, 0
  152. };
  153. #define CVTTOSCR(i) (INT)(((float)(i) * sf) + 0.5)
  154. #define DRIVERINFO_VERSION (1)
  155. /*----------------------------------------------------------------------------*/
  156. VOID KxSort(KX *, KX *);
  157. INT GetCharCode(LPSZ, GlyphName *);
  158. VOID ParseKernPairs(INT);
  159. VOID ParseTrackKern(INT);
  160. VOID ParseKernData(INT);
  161. VOID ParseFontName(VOID);
  162. VOID ParseMSFields(VOID);
  163. VOID ParseCharMetrics(BOOL);
  164. VOID ParseCharBox(BBOX *);
  165. LPSZ ParseCharName(VOID);
  166. INT ParseCharWidth(VOID);
  167. INT ParseCharCode(VOID);
  168. VOID ParseBoundingBox(BOOL);
  169. VOID ParsePitchType(VOID);
  170. VOID InitAfm(VOID);
  171. short _MakePfm(VOID);
  172. BOOL ReadFontInfo(INT);
  173. VOID GetCharMetrics(INT, CM *);
  174. VOID SetCharMetrics(INT, CM *);
  175. VOID GetSmallCM(INT, CM *);
  176. VOID SetFractionMetrics(INT, INT, INT, INT);
  177. VOID FixCharWidths(VOID);
  178. VOID SetAfm(VOID);
  179. VOID SetAvgWidth(VOID);
  180. VOID SetMaxWidth(VOID);
  181. /*----------------------------------------------------------------------------*/
  182. VOID ResetBuffer(VOID);
  183. VOID PutByte(SHORT);
  184. VOID PutRgb(LPSZ, INT);
  185. VOID PutWord(SHORT);
  186. VOID PutLong(long);
  187. VOID SetDf(INT);
  188. VOID PutString(LPSZ);
  189. VOID PutDeviceName(LPSZ);
  190. VOID PutFaceName(VOID);
  191. BOOL MakeDf(BOOL, SHORT, LPSZ);
  192. VOID PutPairKernTable(SHORT);
  193. VOID PutTrackKernTable(SHORT);
  194. VOID PutExtentOrWidthTable(INT);
  195. BOOL WritePfm(LPSZ);
  196. /*----------------------------------------------------------------------------*/
  197. VOID SetDriverInfo(VOID);
  198. VOID PutDriverInfo(INT);
  199. LPSZ GetEscapeSequence(VOID);
  200. /*----------------------------------------------------------------------------*/
  201. VOID AfmToEtm(BOOL);
  202. VOID PutEtm(BOOL);
  203. /*----------------------------------------------------------------------------*/
  204. VOID StartParse(VOID);
  205. BOOL szIsEqual(LPSZ, LPSZ);
  206. VOID szMove(LPSZ, LPSZ, INT);
  207. BOOL GetBuffer(INT);
  208. VOID UnGetLine(VOID);
  209. BOOL GetLine(INT);
  210. BOOL _GetLine(INT);
  211. VOID EatWhite(VOID);
  212. VOID GetWord(LPSZ, INT);
  213. BOOL GetString(LPSZ, INT);
  214. BOOL GetNumber(SHORT *);
  215. BOOL GetFloat(float *, SHORT *);
  216. INT MapToken(LPSZ, KEY *);
  217. INT GetToken(INT, KEY *);
  218. /*----------------------------------------------------------------------------*/
  219. GlyphName *AllocateGlyphArray(INT);
  220. VOID PutGlyphName(GlyphName *, INT, LPSZ);
  221. /*----------------------------------------------------------------------------*/
  222. #if DEBUG_MODE
  223. VOID DumpAfm(VOID);
  224. VOID DumpKernPairs(VOID);
  225. VOID DumpKernTracks(VOID);
  226. VOID DumpCharMetrics(VOID);
  227. VOID DumpPfmHeader(VOID);
  228. VOID DumpCharWidths(VOID);
  229. VOID DumpPfmExtension(VOID);
  230. VOID DumpDriverInfo(VOID);
  231. VOID DumpEtm(VOID);
  232. #endif
  233. /*----------------------------------------------------------------------------*/
  234. extern INT OpenParseFile(LPSZ); /* main.c */
  235. extern INT OpenTargetFile(LPSZ);
  236. // extern VOID cdecl PostWarning(LPCSTR, ...);
  237. // extern VOID cdecl PostError(LPCSTR, ...);
  238. extern LPVOID AllocateMem(UINT);
  239. extern VOID FreeAllMem(VOID);
  240. extern VOID WriteDots(VOID);
  241. extern GlyphName *SetupGlyphArray(LPSZ);
  242. #if !WINATM
  243. extern GlyphName *NewGlyphArray(INT);
  244. extern LPSZ ReadLine(FILE *, LPSZ, INT);
  245. extern LPSZ FirstTokenOnLine(FILE *, LPSZ, INT);
  246. extern LPSZ Token(INT);
  247. extern VOID ParseError(VOID);
  248. #endif
  249. /*----------------------------------------------------------------------------*/
  250. /***************************************************************
  251. * Name: KxSort()
  252. * Action: Sort the pair kerning data using the quicksort algorithm.
  253. ******************************************************************/
  254. VOID KxSort(pkx1, pkx2)
  255. KX *pkx1;
  256. KX *pkx2;
  257. {
  258. static WORD iPivot;
  259. INT iKernAmount;
  260. KX *pkx1T;
  261. KX *pkx2T;
  262. if (pkx1>=pkx2) return;
  263. iPivot = pkx1->iKey;;
  264. iKernAmount = pkx1->iKernAmount;
  265. pkx1T = pkx1;
  266. pkx2T = pkx2;
  267. while (pkx1T < pkx2T)
  268. {
  269. while (pkx1T < pkx2T)
  270. {
  271. if (pkx2T->iKey < iPivot)
  272. {
  273. pkx1T->iKey = pkx2T->iKey;
  274. pkx1T->iKernAmount = pkx2T->iKernAmount;
  275. ++pkx1T;
  276. break;
  277. }
  278. else
  279. --pkx2T;
  280. }
  281. while (pkx1T < pkx2T)
  282. {
  283. if (pkx1T->iKey > iPivot)
  284. {
  285. pkx2T->iKey = pkx1T->iKey;
  286. pkx2T->iKernAmount = pkx1T->iKernAmount;
  287. --pkx2T;
  288. break;
  289. }
  290. else
  291. ++pkx1T;
  292. }
  293. }
  294. pkx2T->iKey = iPivot;
  295. pkx2T->iKernAmount = (SHORT)iKernAmount;
  296. ++pkx2T;
  297. if ((pkx1T - pkx1) < (pkx2 - pkx2T))
  298. {
  299. KxSort(pkx1, pkx1T);
  300. KxSort(pkx2T, pkx2);
  301. }
  302. else
  303. {
  304. KxSort(pkx2T, pkx2);
  305. KxSort(pkx1, pkx1T);
  306. }
  307. }
  308. /******************************************************************
  309. * Name: GetCharCode(glyphname, glypharray)
  310. * Action: Lookup glyphname in glypharray & return index.
  311. ********************************************************************/
  312. INT GetCharCode(glyphname, glypharray)
  313. LPSZ glyphname;
  314. GlyphName *glypharray;
  315. {
  316. register INT i;
  317. if ( STRCMP(glyphname, "") != 0 )
  318. for(i=0; glypharray[i]!=NULL; i++)
  319. if ( STRCMP(glypharray[i], glyphname) == 0 ) return(i);
  320. /* printf("GetCharCode: Undefined character = %s\n", glyphname); */
  321. return(-1);
  322. }
  323. /******************************************************************
  324. * Name: ParseKernPairs()
  325. * Action: Parse the pairwise kerning data.
  326. ********************************************************************/
  327. VOID ParseKernPairs(pcl)
  328. INT pcl;
  329. {
  330. UINT iCh1, iCh2;
  331. KP *pkp;
  332. INT iToken;
  333. WORD cPairs, i;
  334. SHORT iKernAmount;
  335. CHAR szWord[80];
  336. GetNumber(&cPairs);
  337. if( cPairs == 0 )
  338. return;
  339. pkp = &afm.kp;
  340. pkp->cPairs = 0;
  341. pkp->rgPairs = (PKX) AllocateMem( (UINT) (sizeof(KX) * cPairs) );
  342. if( pkp->rgPairs == NULL ) {
  343. ; // PostError(str(MSG_PFM_BAD_MALLOC));
  344. parseError = TRUE;
  345. return;
  346. }
  347. for (i = 0; i < cPairs; ++i) {
  348. if( !GetLine(fhIn) ) break;
  349. if( GetToken(fhIn, afmKeys) != TK_KPX ) {
  350. UnGetLine();
  351. break;
  352. }
  353. GetWord(szWord, sizeof(szWord));
  354. iCh1 = (UINT)GetCharCode(szWord, glyphArray);
  355. GetWord(szWord, sizeof(szWord));
  356. iCh2 = (UINT)GetCharCode(szWord, glyphArray);
  357. GetNumber(&iKernAmount);
  358. /* no kern pairs for unencoded characters or miniscule kern amounts */
  359. if( (iCh1 == -1 || iCh2 == -1) || (pcl && CVTTOSCR(iKernAmount) == 0) )
  360. continue;
  361. pkp->rgPairs[pkp->cPairs].iKey = iCh2 << 8 | iCh1;
  362. pkp->rgPairs[pkp->cPairs++].iKernAmount =
  363. (pcl) ? CVTTOSCR(iKernAmount) : iKernAmount;
  364. }
  365. GetLine(fhIn);
  366. iToken = GetToken(fhIn, afmKeys);
  367. if( iToken == TK_EOF )
  368. ; // PostWarning(str(MSG_PFM_BAD_EOF), "EndKernPairs");
  369. else if( iToken != TK_ENDKERNPAIRS ) {
  370. ; // PostError(str(MSG_PFM_BAD_TOKEN), "EndKernPairs", rgbLine);
  371. parseError = TRUE;
  372. }
  373. KxSort(&afm.kp.rgPairs[0], &afm.kp.rgPairs[afm.kp.cPairs - 1]);
  374. }
  375. /******************************************************************
  376. * Name: ParseTrackKern()
  377. * Action: Parse the track kerning data.
  378. ********************************************************************/
  379. VOID ParseTrackKern(pcl)
  380. INT pcl;
  381. {
  382. float one;
  383. INT i;
  384. KT *pkt;
  385. INT iToken;
  386. one = (float) 1;
  387. pkt = &afm.kt;
  388. GetNumber(&pkt->cTracks);
  389. if( pkt->cTracks > MAXTRACKS) ; // PostWarning(str(MSG_PFM_BAD_TRACK), MAXTRACKS);
  390. for (i = 0; i < pkt->cTracks; ++i) {
  391. if( !GetLine(fhIn) ) {
  392. ; // PostError(str(MSG_PFM_BAD_EOF), "EndTrackKern");
  393. parseError = TRUE;
  394. return;
  395. }
  396. if( GetToken(fhIn, afmKeys) != TK_TRACKKERN ) {
  397. ; // PostError(str(MSG_PFM_BAD_TOKEN), "EndTrackKern", rgbLine);
  398. parseError = TRUE;
  399. return;
  400. }
  401. if( i < MAXTRACKS) {
  402. GetNumber(&pkt->rgTracks[i].iDegree);
  403. GetFloat(&one, &pkt->rgTracks[i].iPtMin);
  404. (pcl) ? GetFloat(&sf, &pkt->rgTracks[i].iKernMin) :
  405. GetFloat(&one, &pkt->rgTracks[i].iKernMin);
  406. GetFloat(&one, &pkt->rgTracks[i].iPtMax);
  407. (pcl) ? GetFloat(&sf, &pkt->rgTracks[i].iKernMax) :
  408. GetFloat(&one, &pkt->rgTracks[i].iKernMax);
  409. }
  410. }
  411. GetLine(fhIn);
  412. iToken = GetToken(fhIn, afmKeys);
  413. if( iToken == TK_EOF ) {
  414. ; // PostError(str(MSG_PFM_BAD_EOF), "EndTrackKern");
  415. parseError = TRUE;
  416. }
  417. else if( iToken != TK_ENDTRACKKERN ) {
  418. ; // PostError(str(MSG_PFM_BAD_TOKEN), "EndTrackKern", rgbLine);
  419. parseError = TRUE;
  420. }
  421. }
  422. /********************************************************
  423. * Name: ParseKernData()
  424. * Action: Start processing the kerning data.
  425. *************************************************************/
  426. VOID ParseKernData(pcl)
  427. INT pcl;
  428. {
  429. INT iToken;
  430. do {
  431. if ( !GetLine(fhIn) ) {
  432. ; // PostError(str(MSG_PFM_BAD_EOF), "EndKernData");
  433. parseError = TRUE;
  434. }
  435. iToken = GetToken(fhIn, afmKeys);
  436. if( iToken == TK_STARTKERNPAIRS ) ParseKernPairs(pcl);
  437. else if( iToken == TK_STARTTRACKKERN ) ParseTrackKern(pcl);
  438. } while( iToken != TK_ENDKERNDATA);
  439. }
  440. /***********************************************************
  441. * Name: ParseFontName()
  442. * Action: Move the font name from the input buffer into the afm
  443. * structure.
  444. **************************************************************/
  445. VOID ParseFontName()
  446. {
  447. EatWhite();
  448. szMove(afm.szFont, szLine, sizeof(afm.szFont));
  449. }
  450. /**************************************************************
  451. * Name: ParseCharMetrics()
  452. * Action: Parse the character metrics entry in the input file
  453. * and set the width and bounding box in the afm structure.
  454. *****************************************************************/
  455. VOID ParseCharMetrics(pcl)
  456. BOOL pcl;
  457. {
  458. SHORT cChars;
  459. INT i, iChar, iWidth;
  460. BBOX rcChar;
  461. if (afm.iFamily == FF_DECORATIVE)
  462. glyphArray = AllocateGlyphArray(255);
  463. else
  464. glyphArray = SetupGlyphArray(encfile);
  465. if( glyphArray == NULL ) {
  466. parseError = TRUE;
  467. return;
  468. }
  469. GetNumber(&cChars);
  470. for (i = 0; i < cChars; ++i) {
  471. if( !GetLine(fhIn) ) {
  472. ; // PostError(str(MSG_PFM_BAD_EOF), "EndCharMetrics");
  473. parseError = TRUE;
  474. return;
  475. }
  476. iChar = ParseCharCode();
  477. iWidth = ParseCharWidth();
  478. if( afm.iFamily == FF_DECORATIVE ) {
  479. if( iChar < 0 || iChar > 255 ) continue;
  480. PutGlyphName(glyphArray, iChar, ParseCharName());
  481. } else {
  482. iChar = GetCharCode(ParseCharName(), glyphArray);
  483. if( iChar == -1 ) continue;
  484. }
  485. ParseCharBox(&rcChar);
  486. if( parseError == TRUE ) return;
  487. afm.rgcm[iChar].iWidth = (pcl) ? CVTTOSCR(iWidth) : iWidth;
  488. afm.rgcm[iChar].rc.top = (pcl) ? CVTTOSCR(rcChar.top) : rcChar.top;
  489. afm.rgcm[iChar].rc.left = (pcl) ? CVTTOSCR(rcChar.left) : rcChar.left;
  490. afm.rgcm[iChar].rc.right = (pcl) ? CVTTOSCR(rcChar.right) : rcChar.right;
  491. afm.rgcm[iChar].rc.bottom = (pcl) ? CVTTOSCR(rcChar.bottom) : rcChar.bottom;
  492. }
  493. GetLine(fhIn);
  494. if (GetToken(fhIn, afmKeys)!=TK_ENDCHARMETRICS) {
  495. ; // PostError(str(MSG_PFM_BAD_TOKEN), "EndCharMetrics", rgbLine);
  496. parseError = TRUE;
  497. }
  498. }
  499. /***************************************************************
  500. * Name: ParseCharBox()
  501. * Action: Parse the character's bounding box and return its
  502. * dimensions in the destination rectangle.
  503. *****************************************************************/
  504. VOID ParseCharBox(prc)
  505. BBOX *prc; /* Pointer to the destination rectangle */
  506. {
  507. CHAR szWord[16];
  508. GetWord(szWord, sizeof(szWord));
  509. if( szIsEqual("B", szWord) ) {
  510. GetNumber(&prc->left);
  511. GetNumber(&prc->bottom);
  512. GetNumber(&prc->right);
  513. GetNumber(&prc->top);
  514. }
  515. else {
  516. ; // PostError(str(MSG_PFM_BAD_CHARMETRICS), rgbLine);
  517. parseError = TRUE;
  518. return;
  519. }
  520. EatWhite();
  521. if (*szLine++ != ';') {
  522. ; // PostError(str(MSG_PFM_BAD_CHARMETRICS), rgbLine);
  523. parseError = TRUE;
  524. }
  525. }
  526. /*********************************************************
  527. * Name: ParseCharName()
  528. * Action: Parse a character's name
  529. ************************************************************/
  530. LPSZ ParseCharName()
  531. {
  532. static CHAR szWord[40];
  533. EatWhite();
  534. GetWord(szWord, sizeof(szWord));
  535. if (szIsEqual("N", szWord))
  536. GetWord(szWord, sizeof(szWord));
  537. else {
  538. ; // PostError(str(MSG_PFM_BAD_CHARMETRICS), rgbLine);
  539. parseError = TRUE;
  540. return(szWord);
  541. }
  542. EatWhite();
  543. if (*szLine++ != ';') {
  544. ; // PostError(str(MSG_PFM_BAD_CHARMETRICS), rgbLine);
  545. parseError = TRUE;
  546. }
  547. return(szWord);
  548. }
  549. /***********************************************************
  550. * Name: ParseCharWidth()
  551. * Action: Parse a character's width and return its numeric
  552. * value.
  553. *************************************************************/
  554. INT ParseCharWidth()
  555. {
  556. SHORT iWidth = 0;
  557. CHAR szWord[16];
  558. GetWord(szWord, sizeof(szWord));
  559. if (szIsEqual("WX", szWord)) {
  560. GetNumber(&iWidth);
  561. if (iWidth==0) ; // PostWarning(str(MSG_PFM_BAD_CHARMETRICS), rgbLine);
  562. EatWhite();
  563. if (*szLine++ != ';') {
  564. ; // PostError(str(MSG_PFM_BAD_CHARMETRICS), rgbLine);
  565. parseError = TRUE;
  566. }
  567. }
  568. else {
  569. ; // PostError(str(MSG_PFM_BAD_CHARMETRICS), rgbLine);
  570. parseError = TRUE;
  571. }
  572. return(iWidth);
  573. }
  574. /*****************************************************************
  575. * Name: ParseCharCode()
  576. * Action: Parse the ascii form of a character's code point and
  577. * return its numeric value.
  578. ******************************************************************/
  579. INT ParseCharCode()
  580. {
  581. SHORT iChar;
  582. CHAR szWord[16];
  583. iChar = 0;
  584. GetWord(szWord, sizeof(szWord));
  585. if (szIsEqual("C", szWord)) {
  586. GetNumber(&iChar);
  587. if (iChar==0) {
  588. ; // PostError(str(MSG_PFM_BAD_CHARMETRICS), rgbLine);
  589. parseError = TRUE;
  590. return(0);
  591. }
  592. EatWhite();
  593. if (*szLine++ != ';') {
  594. ; // PostError(str(MSG_PFM_BAD_CHARMETRICS), rgbLine);
  595. parseError = TRUE;
  596. }
  597. }
  598. return(iChar);
  599. }
  600. /****************************************************************
  601. * Name: ParseBounding Box()
  602. * Action: Parse a character's bounding box and return its size in
  603. * the afm structure.
  604. *******************************************************************/
  605. VOID ParseBoundingBox(pcl)
  606. BOOL pcl;
  607. {
  608. SHORT i;
  609. /* 8-26-91 yh Note that values in rcBBox are not scaled for PCL either */
  610. GetNumber(&i);
  611. // afm.rcBBox.left = (pcl) ? CVTTOSCR(i) : i;
  612. afm.rcBBox.left = i;
  613. GetNumber(&i);
  614. // afm.rcBBox.bottom = (pcl) ? CVTTOSCR(i) : i;
  615. afm.rcBBox.bottom = i;
  616. GetNumber(&i);
  617. // afm.rcBBox.right = (pcl) ? CVTTOSCR(i) : i;
  618. afm.rcBBox.right = i;
  619. GetNumber(&i);
  620. // afm.rcBBox.top = (pcl) ? CVTTOSCR(i) : i;
  621. afm.rcBBox.top = i;
  622. }
  623. /************************************************************
  624. * Name: ParsePitchType()
  625. *
  626. * Action: Parse the pitch type and set the variable pitch
  627. * flag in the afm structure.
  628. * Always set the pitch to be variable pitch for
  629. * our fonts in Windows
  630. *
  631. **********************************************************/
  632. VOID ParsePitchType()
  633. {
  634. CHAR szWord[16];
  635. EatWhite();
  636. GetWord(szWord, sizeof(szWord));
  637. if( !STRCMP(_strlwr(szWord), "true" ) ) {
  638. afm.fWasVariablePitch = FALSE;
  639. afm.fVariablePitch = forceVariablePitch;
  640. }
  641. // afm.fVariablePitch = TRUE;
  642. }
  643. /***********************************************************
  644. * Name: InitAfm()
  645. * Action: Initialize the afm structure.
  646. ************************************************************/
  647. VOID InitAfm()
  648. {
  649. register int i;
  650. afm.iFirstChar = 0x20;
  651. afm.iLastChar = 0x0ff;
  652. afm.iAvgWidth = 0;
  653. afm.iMaxWidth = 0;
  654. afm.iItalicAngle = 0;
  655. afm.iFamily = 0;
  656. afm.ulOffset = 0;
  657. afm.ulThick = 0;
  658. afm.iAscent = 0;
  659. afm.iDescent = 0;
  660. afm.fVariablePitch = TRUE;
  661. afm.fWasVariablePitch = TRUE;
  662. afm.szFont[0] = 0;
  663. afm.szFace[0] = 0;
  664. afm.iWeight = 400;
  665. afm.kp.cPairs = 0;
  666. afm.kt.cTracks = 0;
  667. afm.rcBBox.left = 0;
  668. afm.rcBBox.bottom = 0;
  669. afm.rcBBox.right = 0;
  670. afm.rcBBox.top = 0;
  671. for(i=0; i<256; i++ ) {
  672. afm.rgcm[i].rc.left = 0;
  673. afm.rgcm[i].rc.bottom = 0;
  674. afm.rgcm[i].rc.right = 0;
  675. afm.rgcm[i].rc.top = 0;
  676. afm.rgcm[i].iWidth = 0;
  677. }
  678. }
  679. /*----------------------------------------------------------------------------
  680. ** Returns: 16-bit encoded value indicating error and type of file where
  681. ** error occurred. (see fvscodes.h) for definitions.
  682. ** The following table lists the "status" portion of the codes
  683. ** returned.
  684. **
  685. ** FVS_SUCCESS
  686. ** FVS_INVALID_FONTFILE
  687. ** FVS_FILE_OPEN_ERR
  688. ** FVS_FILE_BUILD_ERR
  689. */
  690. short _MakePfm()
  691. {
  692. INT hfile;
  693. SHORT i;
  694. float ten = (float) 10;
  695. BOOL fPrint = FALSE, fEndOfInput = FALSE, fStartInput = FALSE;
  696. BOOL bRes;
  697. // if ( devType == PCL ) sf = ((float)afm.iPtSize / 1000.0) * (300.0 / 72.0);
  698. InitAfm();
  699. if( (hfile = OpenParseFile(infofile)) == -1 ) {
  700. ; // PostError(str(MSG_PFM_BAD_FOPEN), infofile);
  701. return(FVS_MAKE_CODE(FVS_FILE_OPEN_ERR, FVS_FILE_INF));
  702. }
  703. if( !ReadFontInfo(hfile) ) {
  704. CLOSE(hfile);
  705. ; // PostError(str(MSG_PFM_BAD_PARSE), infofile);
  706. return(FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_INF));
  707. }
  708. CLOSE(hfile);
  709. if( (fhIn = OpenParseFile(afm.szFile)) == -1 ) {
  710. ; // PostError(str(MSG_PFM_BAD_FOPEN), afm.szFile);
  711. return(FVS_MAKE_CODE(FVS_FILE_OPEN_ERR, FVS_FILE_AFM));
  712. }
  713. parseError = FALSE;
  714. while (!fEndOfInput) {
  715. if( !GetLine(fhIn) ) break;
  716. switch( GetToken(fhIn, afmKeys) ) {
  717. case TK_STARTFONTMETRICS:
  718. fStartInput = TRUE;
  719. break;
  720. case TK_STARTKERNDATA:
  721. ParseKernData(devType == PCL);
  722. break;
  723. case TK_FONTNAME:
  724. ParseFontName();
  725. break;
  726. case TK_WEIGHT:
  727. break;
  728. case TK_ITALICANGLE:
  729. GetFloat(&ten, &afm.iItalicAngle);
  730. break;
  731. case TK_ISFIXEDPITCH:
  732. ParsePitchType();
  733. break;
  734. case TK_UNDERLINEPOSITION:
  735. GetNumber(&i);
  736. afm.ulOffset = (devType==POSTSCRIPT) ? abs(i) : CVTTOSCR(abs(i));
  737. break;
  738. case TK_UNDERLINETHICKNESS:
  739. GetNumber(&i);
  740. afm.ulThick = (devType == POSTSCRIPT) ? i : CVTTOSCR(i);
  741. break;
  742. case TK_FONTBBOX:
  743. ParseBoundingBox(devType == PCL);
  744. break;
  745. case TK_CAPHEIGHT:
  746. GetNumber(&i);
  747. if( fiCapHeight == 0 ) fiCapHeight = i;
  748. break;
  749. case TK_XHEIGHT:
  750. break;
  751. case TK_DESCENDER:
  752. GetNumber(&i);
  753. afm.iDescent = (devType == POSTSCRIPT) ? i : CVTTOSCR(i);
  754. break;
  755. case TK_ASCENDER:
  756. GetNumber(&i);
  757. if (i < 667) i = 667;
  758. afm.iAscent = (devType == POSTSCRIPT) ? i : CVTTOSCR(i);
  759. break;
  760. case TK_STARTCHARMETRICS:
  761. if (afm.iFamily == 0) {
  762. ; // PostError(str(MSG_PFM_MISSING_MSFAMILY));
  763. CLOSE(fhIn);
  764. return(FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_AFM));
  765. }
  766. ParseCharMetrics(devType == PCL);
  767. break;
  768. case TK_ENDFONTMETRICS:
  769. fEndOfInput = TRUE;
  770. break;
  771. }
  772. if( parseError ) {
  773. CLOSE(fhIn);
  774. return(FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_AFM));
  775. }
  776. }
  777. CLOSE(fhIn);
  778. if( !fStartInput ) {
  779. ; // PostError(str(MSG_PFM_BAD_EOF), "StartFontMetrics");
  780. return(FVS_MAKE_CODE(FVS_INVALID_FONTFILE, FVS_FILE_AFM));
  781. }
  782. FixCharWidths();
  783. SetAfm();
  784. #if DEBUG_MODE
  785. DumpAfm();
  786. DumpKernPairs();
  787. DumpKernTracks();
  788. DumpCharMetrics();
  789. #endif
  790. bRes = MakeDf(FALSE, (SHORT)devType, outfile);
  791. FreeAllMem();
  792. return(bRes ? FVS_MAKE_CODE(FVS_SUCCESS, FVS_FILE_UNK) :
  793. FVS_MAKE_CODE(FVS_FILE_BUILD_ERR, FVS_FILE_PFM));
  794. }
  795. /*----------------------------------------------------------------------------*/
  796. BOOL ReadFontInfo(hfile)
  797. INT hfile;
  798. {
  799. INT iToken;
  800. CHAR szTemp[6];
  801. BOOL found[LAST_FI_TOKEN+1];
  802. static KEY infKeys[] = {
  803. "MSMenuName", TK_MSMENUNAME,
  804. "VPStyle", TK_VPSTYLE,
  805. "Pi", TK_PI,
  806. "Serif", TK_SERIF,
  807. "PCLStyle", TK_PCLSTYLE,
  808. "PCLStrokeWeight", TK_PCLSTROKEWEIGHT,
  809. "PCLTypefaceID", TK_PCLTYPEFACEID,
  810. "CapHeight", TK_INF_CAPHEIGHT,
  811. NULL, 0
  812. };
  813. fiCapHeight = 0;
  814. for(iToken=0; iToken<=LAST_FI_TOKEN; iToken++) found[iToken] = FALSE;
  815. while( GetLine(hfile) ) {
  816. iToken = GetToken(hfile,infKeys);
  817. found[iToken] = TRUE;
  818. switch(iToken) {
  819. case TK_MSMENUNAME:
  820. if( !GetString(afm.szFace, sizeof(afm.szFace)) ) return(FALSE);
  821. break;
  822. case TK_VPSTYLE:
  823. if( !GetString(szTemp, sizeof(szTemp)) ) return(FALSE);
  824. switch( toupper(szTemp[0]) ) {
  825. case 'N':
  826. case 'I': afm.iWeight = FW_NORMAL; break;
  827. case 'B':
  828. case 'T': afm.iWeight = FW_BOLD; break;
  829. default: return(FALSE); break;
  830. }
  831. break;
  832. case TK_PI:
  833. GetWord(szTemp, sizeof(szTemp));
  834. if( !STRCMP(_strupr(szTemp), "TRUE") )
  835. afm.iFamily = FF_DECORATIVE;
  836. else if( STRCMP(szTemp, "FALSE") ) return(FALSE);
  837. break;
  838. case TK_SERIF:
  839. GetWord(szTemp, sizeof(szTemp));
  840. if( !STRCMP(_strupr(szTemp), "TRUE") ) {
  841. if( afm.iFamily != FF_DECORATIVE ) afm.iFamily = FF_ROMAN;
  842. }
  843. else if( !STRCMP(szTemp, "FALSE") ) {
  844. if( afm.iFamily != FF_DECORATIVE ) afm.iFamily = FF_SWISS;
  845. }
  846. else return(FALSE);
  847. break;
  848. case TK_INF_CAPHEIGHT:
  849. GetNumber(&fiCapHeight);
  850. break;
  851. case TK_PCLSTYLE:
  852. GetNumber(&pclinfo.style);
  853. break;
  854. case TK_PCLSTROKEWEIGHT:
  855. GetNumber(&pclinfo.strokeWeight);
  856. break;
  857. case TK_PCLTYPEFACEID:
  858. GetNumber((SHORT *)&pclinfo.typeface);
  859. if( pclinfo.typefaceLen == 1 ) pclinfo.typeface &= 0xFF;
  860. break;
  861. }
  862. }
  863. if( found[TK_MSMENUNAME] == FALSE ||
  864. found[TK_VPSTYLE] == FALSE ||
  865. found[TK_PI] == FALSE ||
  866. found[TK_SERIF] == FALSE ||
  867. found[TK_INF_CAPHEIGHT] == FALSE ) return(FALSE);
  868. if ( devType == PCL )
  869. if( found[TK_PCLSTYLE] == FALSE ||
  870. found[TK_PCLSTROKEWEIGHT] == FALSE ||
  871. found[TK_PCLTYPEFACEID] == FALSE ) return(FALSE);
  872. return(TRUE);
  873. }
  874. #if DEBUG_MODE
  875. /*----------------------------------------------------------------------------*/
  876. VOID DumpAfm()
  877. {
  878. printf("\nAFM HEADER\n");
  879. printf("afm.iFirstChar: %d\n", afm.iFirstChar);
  880. printf("afm.iLastChar: %d\n", afm.iLastChar);
  881. printf("afm.iPtSize: %d\n", afm.iPtSize);
  882. printf("afm.iAvgWidth: %d\n", afm.iAvgWidth);
  883. printf("afm.iMaxWidth: %d\n", afm.iMaxWidth);
  884. printf("afm.iItalicAngle: %d\n", afm.iItalicAngle);
  885. printf("afm.iFamily: %d\n", afm.iFamily);
  886. printf("afm.ulOffset: %d\n", afm.ulOffset);
  887. printf("afm.ulThick: %d\n", afm.ulThick);
  888. printf("afm.iAscent: %d\n", afm.iAscent);
  889. printf("afm.iDescent: %d\n", afm.iDescent);
  890. printf("afm.fVariablePitch: %d\n", afm.fVariablePitch);
  891. printf("afm.szFile: %s\n", afm.szFile);
  892. printf("afm.szFont: %s\n", afm.szFont);
  893. printf("afm.szFace: %s\n", afm.szFace);
  894. printf("afm.iWeight: %d\n", afm.iWeight);
  895. printf("afm.rcBBox - top: %d left: %d right: %d bottom: %d\n",
  896. afm.rcBBox.top, afm.rcBBox.left, afm.rcBBox.right, afm.rcBBox.bottom);
  897. }
  898. /*----------------------------------------------------------------------------*/
  899. VOID DumpKernPairs()
  900. {
  901. INT indx;
  902. printf("\nKERN PAIRS\n");
  903. printf("afm.kp.cPairs: %d\n", afm.kp.cPairs);
  904. for (indx = 0; indx < afm.kp.cPairs; indx++)
  905. printf("afm.kp.rgPairs[%d] - iKey: %u iKernAmount: %d\n", indx,
  906. afm.kp.rgPairs[indx].iKey, afm.kp.rgPairs[indx].iKernAmount);
  907. }
  908. /*----------------------------------------------------------------------------*/
  909. VOID DumpKernTracks()
  910. {
  911. INT indx;
  912. printf("\nKERN TRACKS\n");
  913. printf("afm.kt.cTracks: %d\n", afm.kt.cTracks);
  914. for (indx = 0; indx < afm.kt.cTracks; indx++) {
  915. printf("track: %d iDegree: %d iPtMin: %d iKernMin: %d iPtMax: %d iKernMax: %d\n",
  916. indx,
  917. afm.kt.rgTracks[indx].iDegree,
  918. afm.kt.rgTracks[indx].iPtMin,
  919. afm.kt.rgTracks[indx].iKernMin,
  920. afm.kt.rgTracks[indx].iPtMax,
  921. afm.kt.rgTracks[indx].iKernMax);
  922. }
  923. }
  924. /*----------------------------------------------------------------------------*/
  925. VOID DumpCharMetrics()
  926. {
  927. INT indx;
  928. printf("\nCHARACTER METRICS\n");
  929. for (indx = afm.iFirstChar; indx <= afm.iLastChar; ++indx) {
  930. printf("indx: %d width: %d top: %d left: %d right: %d bottom: %d\n",
  931. indx,
  932. afm.rgcm[indx].iWidth,
  933. afm.rgcm[indx].rc.top,
  934. afm.rgcm[indx].rc.left,
  935. afm.rgcm[indx].rc.right,
  936. afm.rgcm[indx].rc.bottom);
  937. }
  938. }
  939. /*----------------------------------------------------------------------------*/
  940. #endif
  941. /******************************************************
  942. * Name: GetCharMetrics()
  943. * Action: Get the character metrics for a specified character.
  944. **********************************************************/
  945. VOID GetCharMetrics(iChar, pcm)
  946. INT iChar;
  947. CM *pcm;
  948. {
  949. CM *pcmSrc;
  950. pcmSrc = &afm.rgcm[iChar];
  951. pcm->iWidth = pcmSrc->iWidth;
  952. pcm->rc.top = pcmSrc->rc.top;
  953. pcm->rc.left = pcmSrc->rc.left;
  954. pcm->rc.bottom = pcmSrc->rc.bottom;
  955. pcm->rc.right = pcmSrc->rc.right;
  956. }
  957. /*************************************************************
  958. * Name: SetCharMetrics()
  959. * Action: Set the character metrics for a specified character.
  960. ***************************************************************/
  961. VOID SetCharMetrics(iChar, pcm)
  962. INT iChar;
  963. CM *pcm;
  964. {
  965. CM *pcmDst;
  966. pcmDst = &afm.rgcm[iChar];
  967. pcmDst->iWidth = pcm->iWidth;
  968. pcmDst->rc.top = pcm->rc.top;
  969. pcmDst->rc.left = pcm->rc.left;
  970. pcmDst->rc.bottom = pcm->rc.bottom;
  971. pcmDst->rc.right = pcm->rc.right;
  972. }
  973. /************************************************************
  974. * Name: GetSmallCM()
  975. * Action: Compute the character metrics for small sized characters
  976. * such as superscripts.
  977. **************************************************************/
  978. VOID GetSmallCM(iCh, pcm)
  979. INT iCh;
  980. CM *pcm;
  981. {
  982. GetCharMetrics(iCh, pcm);
  983. pcm->iWidth = pcm->iWidth / 2;
  984. pcm->rc.bottom = pcm->rc.top + (pcm->rc.top - pcm->rc.bottom)/2;
  985. pcm->rc.right = pcm->rc.left + (pcm->rc.right - pcm->rc.left)/2;
  986. }
  987. /*************************************************************
  988. * Name: SetFractionMetrics()
  989. * Action: Set the character metrics for a fractional character
  990. * which must be simulated.
  991. ***************************************************************/
  992. VOID SetFractionMetrics(iChar, iTop, iBottom, pcl)
  993. INT iChar; /* The character code point */
  994. INT iTop; /* The ascii numerator character */
  995. INT iBottom; /* The denominator character */
  996. INT pcl; /* device type */
  997. {
  998. INT cxBottom; /* The width of the denominator */
  999. CM cm;
  1000. #define IFRACTIONBAR 167
  1001. /* Set denominator width to 60 percent of bottom character */
  1002. GetCharMetrics(iBottom, &cm);
  1003. cxBottom = (INT)((long)cm.iWidth * (long)((pcl) ? CVTTOSCR(60) : 60)
  1004. / (long)((pcl) ? CVTTOSCR(100) : 100));
  1005. /* Set numerator width to 40 percent of top character */
  1006. GetCharMetrics(iTop, &cm);
  1007. cxBottom = (INT)((long)cm.iWidth * (long)((pcl) ? CVTTOSCR(40) : 40)
  1008. / (long)((pcl) ? CVTTOSCR(100) : 100));
  1009. cm.iWidth = iTop + iBottom + (pcl) ? CVTTOSCR(IFRACTIONBAR) : IFRACTIONBAR;
  1010. cm.rc.right = cm.rc.left + cm.iWidth;
  1011. SetCharMetrics(iChar, &cm);
  1012. }
  1013. /***********************************************************************
  1014. * Name: FixCharWidths()
  1015. * Action: Fix up the character widths for those characters which
  1016. * must be simulated in the driver.
  1017. *************************************************************************/
  1018. VOID FixCharWidths()
  1019. {
  1020. CM cm;
  1021. CM cmSubstitute;
  1022. INT i;
  1023. #if 0
  1024. if (afm.iFamily == FF_DECORATIVE) {
  1025. GetCharMetrics(ISPACE, &cmSubstitute);
  1026. for (i = afm.iFirstChar; i <= afm.iLastChar; ++i) {
  1027. GetCharMetrics(i, &cm);
  1028. if (cm.iWidth == 0) {
  1029. SetCharMetrics(i, &cmSubstitute);
  1030. }
  1031. }
  1032. return;
  1033. }
  1034. /* this is a text font */
  1035. GetCharMetrics(IBULLET, &cmSubstitute);
  1036. for (i=0x07f; i<0x091; ++i) SetCharMetrics(i, &cmSubstitute);
  1037. for (i=0x098; i<0x0a1; ++i) SetCharMetrics(i, &cmSubstitute);
  1038. #else
  1039. /* yh 8-27-91 Added some characters for Windows 3.1. */
  1040. if (afm.iFamily == FF_DECORATIVE)
  1041. GetCharMetrics(ISPACE, &cmSubstitute);
  1042. else { /* WINANSI encoding */
  1043. GetCharMetrics(ISPACE, &cm); /* 'space' is encoded twice */
  1044. SetCharMetrics(IWINSPACE, &cm);
  1045. GetCharMetrics(IBULLET, &cmSubstitute);
  1046. }
  1047. for (i = afm.iFirstChar; i <= afm.iLastChar; ++i) {
  1048. GetCharMetrics(i, &cm);
  1049. if (cm.iWidth == 0)
  1050. SetCharMetrics(i, &cmSubstitute);
  1051. }
  1052. #endif
  1053. }
  1054. /***************************************************************
  1055. * Name: SetAfm()
  1056. * Action: Set the character metrics in the afm to their default values.
  1057. ********************************************************************/
  1058. VOID SetAfm()
  1059. {
  1060. INT i, cx;
  1061. afm.iFirstChar = 0x0020;
  1062. afm.iLastChar = 0x00ff;
  1063. if( !afm.fVariablePitch ) {
  1064. cx = afm.rgcm[afm.iFirstChar].iWidth;
  1065. for (i=afm.iFirstChar; i<=afm.iLastChar; ++i)
  1066. afm.rgcm[i].iWidth = (SHORT)cx;
  1067. }
  1068. SetAvgWidth();
  1069. SetMaxWidth();
  1070. }
  1071. /******************************************************************
  1072. * Name: SetAvgWidth()
  1073. * Action: This routine computes the average character width
  1074. * from the character metrics in the afm structure.
  1075. ********************************************************************/
  1076. VOID SetAvgWidth()
  1077. {
  1078. CM *rgcm;
  1079. INT i;
  1080. long cx; /* The average character width */
  1081. long cb; /* The number of characters */
  1082. rgcm = afm.rgcm;
  1083. cx = 0L;
  1084. cb = (long) (afm.iLastChar - afm.iFirstChar + 1);
  1085. for (i=afm.iFirstChar; i<=afm.iLastChar; ++i)
  1086. cx += (long) rgcm[i].iWidth;
  1087. afm.iAvgWidth = (INT) (cx / cb);
  1088. }
  1089. /*****************************************************************
  1090. * Name: SetMaxWidth()
  1091. * Action: This routine computes the maximum character width from
  1092. * the character metrics in the afm structure.
  1093. *******************************************************************/
  1094. VOID SetMaxWidth()
  1095. {
  1096. CM *rgcm;
  1097. INT cx;
  1098. INT i;
  1099. rgcm = afm.rgcm;
  1100. cx = 0;
  1101. for (i=afm.iFirstChar; i<=afm.iLastChar; ++i)
  1102. if (rgcm[i].iWidth > cx) cx = rgcm[i].iWidth;
  1103. afm.iMaxWidth = (SHORT)cx;
  1104. }
  1105. /*----------------------------------------------------------------------------*/
  1106. /*----------------------------------------------------------------------------*/
  1107. /*----------------------------------------------------------------------------*/
  1108. /******************************************************************
  1109. * Name: ResetBuffer()
  1110. * Action: This function resets the output buffer.
  1111. ********************************************************************/
  1112. VOID ResetBuffer()
  1113. {
  1114. pbBuffer = rgbBuffer;
  1115. cbMaxBuffer = sizeof(rgbBuffer);
  1116. cbBuffer = 0;
  1117. }
  1118. /****************************************************************
  1119. * Name: PutByte()
  1120. * Action: This function writes a byte to the output buffer.
  1121. ******************************************************************/
  1122. VOID PutByte(iByte)
  1123. SHORT iByte;
  1124. {
  1125. if ((cbBuffer+1)<cbMaxBuffer)
  1126. {
  1127. *pbBuffer++ = (BYTE) (iByte & 0x0ff);
  1128. ++cbBuffer;
  1129. }
  1130. }
  1131. /****************************************************************
  1132. * Name: PutRgb()
  1133. * Action: This function writes an array of bytes to the output buffer.
  1134. ******************************************************************/
  1135. VOID PutRgb(pb, cb)
  1136. LPSZ pb;
  1137. INT cb;
  1138. {
  1139. while (--cb>=0)
  1140. PutByte(*pb++);
  1141. }
  1142. /****************************************************************
  1143. * Name: PutWord()
  1144. * Action: This function writes a word to the output buffer.
  1145. ******************************************************************/
  1146. VOID PutWord(iWord)
  1147. SHORT iWord;
  1148. {
  1149. if ((cbBuffer+2)<cbMaxBuffer)
  1150. {
  1151. *pbBuffer++ = (CHAR) (iWord & 0x0ff);
  1152. *pbBuffer++ = (CHAR) ( (iWord >> 8) & 0x0ff );
  1153. cbBuffer += 2;
  1154. }
  1155. }
  1156. /****************************************************************
  1157. * Name: PutLong()
  1158. * Action: This function writes a long word to the output buffer.
  1159. ******************************************************************/
  1160. VOID PutLong(lWord)
  1161. long lWord;
  1162. {
  1163. PutWord((WORD) (lWord & 0x0ffffL));
  1164. lWord >>= 16;
  1165. PutWord((WORD) (lWord & 0x0ffffL));
  1166. }
  1167. /**************************************************************
  1168. * Name: SetDf()
  1169. * Action: This function sets the values in the device font structure
  1170. * from the values in the afm structure.
  1171. *****************************************************************/
  1172. static CHAR szCopyright[] = "Copyright 1988-1991 Adobe Systems Inc.";
  1173. VOID SetDf(pcl)
  1174. INT pcl;
  1175. {
  1176. //WORD minAscent;
  1177. WORD pixHeight;
  1178. WORD internalLeading;
  1179. SHORT leading;
  1180. #ifndef FF_MASKFAMILY
  1181. #define FF_MASKFAMILY ((BYTE) 0xF0)
  1182. #endif
  1183. #define MAX(a,b) ((a)>(b)?(a):(b))
  1184. pfm.iVersion = 0x0100; /* Version 1.00 */
  1185. szMove(pfm.szCopyright, szCopyright, sizeof(pfm.szCopyright));
  1186. pfm.iType = (pcl) ? PCL_FONTTYPE : PS_FONTTYPE;
  1187. pfm.iCharSet = (charset == -1) ? (BYTE) ANSI_CHARSET : (BYTE) charset;
  1188. /* (pcl && (afm.iFamily==FF_DECORATIVE)) ? PCL_PI_CHARSET : ANSI_CHARSET );
  1189. Windows WRITE only displays fonts with CharSet=0 in the menu */
  1190. pfm.iDefaultChar = (BYTE) (
  1191. ( (afm.iFamily==FF_DECORATIVE) ? ISPACE : IBULLET ) - afm.iFirstChar );
  1192. pfm.iBreakChar = (BYTE) (ISPACE - afm.iFirstChar);
  1193. /* for a scalable font (i.e. PostScript) default to 80 column text */
  1194. pfm.iPoints = (pcl) ? afm.iPtSize : 10;
  1195. /* if we ever support other bitmapped printers we will no longer be able
  1196. to assume that the default x and y res are 300. */
  1197. pfm.iVertRes = 300;
  1198. pfm.iHorizRes = 300;
  1199. pfm.iItalic = (BYTE) ((afm.iItalicAngle != 0) ? 1 : 0);
  1200. pfm.iWeight = afm.iWeight;
  1201. pfm.iPitchAndFamily = (BYTE) afm.iFamily;
  1202. pfm.iFirstChar = (BYTE) afm.iFirstChar;
  1203. pfm.iLastChar = (BYTE) afm.iLastChar;
  1204. pfm.iAvgWidth = afm.iAvgWidth;
  1205. pfm.iMaxWidth = afm.iMaxWidth;
  1206. pfm.iPixWidth = (afm.fVariablePitch) ? 0 : afm.iAvgWidth;
  1207. /* pfm.iPixHeight = afm.rcBBox.top - afm.rcBBox.bottom;
  1208. * Changed to reduce round off error. 8-26-91 yh
  1209. */
  1210. pixHeight = afm.rcBBox.top - afm.rcBBox.bottom;
  1211. pfm.iPixHeight = (pcl) ? CVTTOSCR(pixHeight) : pixHeight;
  1212. /* pfm.iInternalLeading =
  1213. * (pcl) ? pfm.iPixHeight - ((afm.iPtSize * 300) / 72) : 0;
  1214. * Changed to match ATM. 7-31-91 yh
  1215. * Changed to reduce round off error. 8-26-91 yh
  1216. */
  1217. internalLeading = max(0, pixHeight - EM);
  1218. pfm.iInternalLeading = (pcl) ? CVTTOSCR(internalLeading) : internalLeading;
  1219. /* pfm.iAscent = afm.rcBBox.top;
  1220. * Changed to fix text alignment problem. 10-08-90 yh
  1221. */
  1222. /* pfm.iAscent = afm.iAscent;
  1223. * Changed to match ATM. 7-31-91 yh
  1224. * Changed to reduce round off error. 8-26-91 yh
  1225. */
  1226. pfm.iAscent = (pcl) ?
  1227. CVTTOSCR(EM + afm.rcBBox.bottom) + CVTTOSCR(internalLeading) :
  1228. EM + afm.rcBBox.bottom + internalLeading;
  1229. /* Deleted to match ATM. yh 9-13-91
  1230. * minAscent = (pcl) ? CVTTOSCR(667) : 667; 2/3 of EM
  1231. * if( pfm.iAscent < minAscent ) pfm.iAscent = minAscent;
  1232. */
  1233. /* pfm.iExternalLeading = 196; */
  1234. /* Changed to 0 to fix a bug in PCL landscape. Was getting huge leading. */
  1235. /*
  1236. * yh 8-26-91 Changed ExternalLeading for pcl to match ATM .
  1237. */
  1238. if (!pcl)
  1239. /* PostScript driver ignores this field and comes up with own
  1240. * ExternalLeading value.
  1241. *
  1242. * !!! HACK ALERT !!!
  1243. *
  1244. * ATM needs to have ExternalLeading=0. PFMs generated with Rev. 2
  1245. * MAKEPFM have a bug in default & break character fields. We had
  1246. * encoding number instead of offsets. ATM uses following algorithm
  1247. * to recognize the Rev. 2 PFMs:
  1248. * rev2pfm = pfmRec->fmExternalLeading != 0 &&
  1249. * etmRec->etmStrikeOutOffset == 500 &&
  1250. * pfmRec->fmDefaultChar >= pfmRec->fmFirstChar;
  1251. * So, we need to make sure that either ExternalLeading stays zero or
  1252. * StrikeOutOffset is not 500. With current algorithm, StrikeOutOffset
  1253. * is very likely to be less than 500.
  1254. * etm.iStrikeOutOffset = fiCapHeight / 2 - (afm.ulThick / 2);
  1255. */
  1256. pfm.iExternalLeading = 0;
  1257. else if (!afm.fWasVariablePitch)
  1258. pfm.iExternalLeading = 0;
  1259. else /* pcl & Variable pitch */
  1260. {
  1261. /* Adjust external leading such that we are compatible */
  1262. /* with the values returned by the PostScript driver. */
  1263. /* Who did this code?? Microsoft? Has to be! */
  1264. switch (pfm.iPitchAndFamily & FF_MASKFAMILY)
  1265. {
  1266. case FF_ROMAN: leading = (pfm.iVertRes + 18) / 36; //2-pnt leading
  1267. break;
  1268. case FF_SWISS: if (pfm.iPoints <= 12)
  1269. leading = (pfm.iVertRes + 18) / 36; //2-pnt leading
  1270. else if (pfm.iPoints < 14)
  1271. leading = (pfm.iVertRes + 12) / 24; //3-pnt leading
  1272. else
  1273. leading = (pfm.iVertRes + 9) / 18; //4-pnt leading
  1274. break;
  1275. default: /* Give 19.6% of the height for leading. */
  1276. leading = (short) (
  1277. (long) (pfm.iPixHeight-pfm.iInternalLeading)
  1278. * 196L / 1000L );
  1279. break;
  1280. }
  1281. pfm.iExternalLeading = MAX(0, (SHORT)(leading - pfm.iInternalLeading));
  1282. }
  1283. pfm.iWidthBytes = 0;
  1284. if (afm.fVariablePitch) pfm.iPitchAndFamily |= 1;
  1285. pfm.iUnderline = 0;
  1286. pfm.iStrikeOut = 0;
  1287. pfm.oBitsPointer = 0L;
  1288. pfm.oBitsOffset = 0L;
  1289. }
  1290. /**********************************************************
  1291. * Name: PutString()
  1292. * Action: This function writes a null terminated string
  1293. * to the output file.
  1294. ***********************************************************/
  1295. VOID PutString(sz)
  1296. LPSZ sz;
  1297. {
  1298. INT bCh = 0;
  1299. do
  1300. {
  1301. if ((cbBuffer+1)<cbMaxBuffer)
  1302. {
  1303. bCh = *pbBuffer++ = *sz++;
  1304. ++cbBuffer;
  1305. }
  1306. } while( bCh && cbBuffer<cbMaxBuffer);
  1307. }
  1308. /***************************************************************
  1309. * Name: PutdeviceName()
  1310. * Action: This function writes the device name to the output file.
  1311. **************************************************************/
  1312. VOID PutDeviceName(szDevice)
  1313. LPSZ szDevice;
  1314. {
  1315. pfm.oDevice = cbBuffer;
  1316. PutString(szDevice);
  1317. }
  1318. /***************************************************************
  1319. * Name: PutFaceName()
  1320. * Action: This function writes the font's face name to the output file.
  1321. **************************************************************/
  1322. VOID PutFaceName()
  1323. {
  1324. pfm.oFace = cbBuffer;
  1325. PutString(afm.szFace);
  1326. }
  1327. /**************************************************************
  1328. * Name: MakeDf()
  1329. * Action: This function writes the device font info structure
  1330. * to the output file.
  1331. * Method: This function makes two passes over the data. On the first pass
  1332. * it collects offset data as it places data in the output buffer. On the
  1333. * second pass, it first resets the output buffer and then writes the data
  1334. * to the output buffer again with the offsets computed from pass 1.
  1335. ***************************************************************/
  1336. BOOL MakeDf(fPass2, devType, outfile)
  1337. BOOL fPass2; /* TRUE if this is the second pass */
  1338. SHORT devType; /* 1=POSTSCRIPT 2=PCL */
  1339. LPSZ outfile;
  1340. {
  1341. BOOL result = TRUE;
  1342. INT iMarker;
  1343. ResetBuffer();
  1344. SetDf(devType == PCL);
  1345. /* put out the PFM header structure */
  1346. PutWord(pfm.iVersion);
  1347. PutLong(pfm.iSize);
  1348. PutRgb(pfm.szCopyright, 60);
  1349. PutWord(pfm.iType);
  1350. PutWord(pfm.iPoints);
  1351. PutWord(pfm.iVertRes);
  1352. PutWord(pfm.iHorizRes);
  1353. PutWord(pfm.iAscent);
  1354. PutWord(pfm.iInternalLeading);
  1355. PutWord(pfm.iExternalLeading);
  1356. PutByte(pfm.iItalic);
  1357. PutByte(pfm.iUnderline);
  1358. PutByte(pfm.iStrikeOut);
  1359. PutWord(pfm.iWeight);
  1360. PutByte(pfm.iCharSet);
  1361. PutWord(pfm.iPixWidth);
  1362. PutWord(pfm.iPixHeight);
  1363. PutByte(pfm.iPitchAndFamily);
  1364. PutWord(pfm.iAvgWidth);
  1365. PutWord(pfm.iMaxWidth);
  1366. PutByte(pfm.iFirstChar);
  1367. PutByte(pfm.iLastChar);
  1368. PutByte(pfm.iDefaultChar);
  1369. PutByte(pfm.iBreakChar);
  1370. PutWord(pfm.iWidthBytes);
  1371. PutLong(pfm.oDevice);
  1372. PutLong(pfm.oFace);
  1373. PutLong(pfm.oBitsPointer);
  1374. PutLong(pfm.oBitsOffset);
  1375. /* need to determine if proportional etc. */
  1376. if (devType == PCL) PutExtentOrWidthTable(1);
  1377. /* put out the PFM extension structure */
  1378. iMarker = cbBuffer;
  1379. PutWord(pfmext.oSizeFields);
  1380. PutLong(pfmext.oExtMetricsOffset);
  1381. PutLong(pfmext.oExtentTable);
  1382. PutLong(pfmext.oOriginTable);
  1383. PutLong(pfmext.oPairKernTable);
  1384. PutLong(pfmext.oTrackKernTable);
  1385. PutLong(pfmext.oDriverInfo);
  1386. PutLong(pfmext.iReserved);
  1387. pfmext.oSizeFields = cbBuffer - iMarker;
  1388. if (devType == POSTSCRIPT) {
  1389. /* Put the extended text metrics table */
  1390. pfmext.oExtMetricsOffset = cbBuffer;
  1391. PutEtm(FALSE);
  1392. PutDeviceName("PostScript");
  1393. PutFaceName();
  1394. PutDriverInfo(FALSE);
  1395. /* Put the extent table */
  1396. PutExtentOrWidthTable(0);
  1397. pfmext.oOriginTable = 0;
  1398. pfmext.iReserved = 0;
  1399. PutPairKernTable(POSTSCRIPT);
  1400. PutTrackKernTable(POSTSCRIPT);
  1401. }
  1402. if (devType == PCL) {
  1403. PutFaceName();
  1404. PutDeviceName("PCL/HP LaserJet");
  1405. /* Put the extended text metrics table */
  1406. pfmext.oExtMetricsOffset = cbBuffer;
  1407. PutEtm(TRUE);
  1408. PutPairKernTable(PCL);
  1409. PutTrackKernTable(PCL);
  1410. PutDriverInfo(TRUE);
  1411. pfmext.oOriginTable = 0;
  1412. pfmext.iReserved = 0;
  1413. }
  1414. if( !fPass2 ) {
  1415. pfm.iSize = (long)cbBuffer;
  1416. if( !MakeDf(TRUE, devType, outfile) ) result = FALSE;
  1417. }
  1418. else {
  1419. if( !WritePfm(outfile) ) result = FALSE;
  1420. #if DEBUG_MODE
  1421. DumpPfmHeader();
  1422. DumpCharWidths();
  1423. DumpPfmExtension();
  1424. #endif
  1425. }
  1426. if (cbBuffer>=cbMaxBuffer) // Too complex font
  1427. result = FALSE;
  1428. return(result);
  1429. }
  1430. /*******************************************************************
  1431. * Name: PutPairKernTable(devType)
  1432. * Action: Send the pairwise kerning table to the output file.
  1433. *********************************************************************/
  1434. VOID PutPairKernTable(devType)
  1435. SHORT devType; /* 1=POSTSCRIPT 2=PCL */
  1436. {
  1437. WORD i;
  1438. if( afm.kp.cPairs > 0 ) {
  1439. pfmext.oPairKernTable = cbBuffer;
  1440. #if DEBUG_MODE
  1441. printf("Pair Kern Table - pairs: %d\n", afm.kp.cPairs);
  1442. #endif
  1443. if( devType == POSTSCRIPT ) PutWord(afm.kp.cPairs);
  1444. for (i = 0; i < afm.kp.cPairs; ++i) {
  1445. PutWord(afm.kp.rgPairs[i].iKey);
  1446. PutWord(afm.kp.rgPairs[i].iKernAmount);
  1447. #if DEBUG_MODE
  1448. printf("key: %x kern amount: %d\n",
  1449. afm.kp.rgPairs[i].iKey, afm.kp.rgPairs[i].iKernAmount);
  1450. #endif
  1451. }
  1452. }
  1453. else
  1454. pfmext.oPairKernTable = 0;
  1455. }
  1456. /******************************************************************
  1457. * Name: PutTrackKernTable(devType)
  1458. * Action: Send the track kerning table to the output file.
  1459. ********************************************************************/
  1460. VOID PutTrackKernTable(devType)
  1461. SHORT devType; /* 1=POSTSCRIPT 2=PCL */
  1462. {
  1463. INT i;
  1464. if (afm.kt.cTracks == 0)
  1465. {
  1466. pfmext.oTrackKernTable = 0;
  1467. return;
  1468. }
  1469. pfmext.oTrackKernTable = cbBuffer;
  1470. if (devType == POSTSCRIPT) PutWord(afm.kt.cTracks);
  1471. for (i=0; i<afm.kt.cTracks; ++i)
  1472. {
  1473. PutWord(afm.kt.rgTracks[i].iDegree);
  1474. PutWord(afm.kt.rgTracks[i].iPtMin);
  1475. PutWord(afm.kt.rgTracks[i].iKernMin);
  1476. PutWord(afm.kt.rgTracks[i].iPtMax);
  1477. PutWord(afm.kt.rgTracks[i].iKernMax);
  1478. }
  1479. }
  1480. /***************************************************************
  1481. * Name: PutExtentTable()
  1482. * Action: Send the character extent information to the output file.
  1483. *****************************************************************/
  1484. VOID PutExtentOrWidthTable(width)
  1485. INT width; /* 0=extent 1=width */
  1486. {
  1487. INT i;
  1488. /* is the typeface proportional ?? */
  1489. if (pfm.iPitchAndFamily & 1)
  1490. {
  1491. pfmext.oExtentTable = (width) ? 0 : cbBuffer;
  1492. for (i = afm.iFirstChar; i <= afm.iLastChar; i++)
  1493. PutWord(afm.rgcm[i].iWidth);
  1494. if (width) PutWord(0);
  1495. }
  1496. else
  1497. pfmext.oExtentTable = 0;
  1498. }
  1499. /***********************************************************
  1500. * Name: WritePfm()
  1501. * Action: Flush the ouput buffer to the file. Note that this
  1502. * function is only called after the entire pfm structure
  1503. * has been built in the output buffer.
  1504. *************************************************************/
  1505. BOOL WritePfm(outfile)
  1506. LPSZ outfile;
  1507. {
  1508. INT fh;
  1509. if( (fh = OpenTargetFile(outfile) ) == -1 ) {
  1510. ; // PostError(str(MSG_PFM_BAD_CREATE), outfile);
  1511. return(FALSE);
  1512. }
  1513. if( cbBuffer > 0 )
  1514. if( (WORD)WRITE_BLOCK(fh, rgbBuffer, cbBuffer) != (WORD)cbBuffer ) {
  1515. CLOSE(fh);
  1516. ; // PostError(str(MSG_PFM_DISK_FULL));
  1517. return(FALSE);
  1518. }
  1519. CLOSE(fh);
  1520. return(TRUE);
  1521. }
  1522. #if DEBUG_MODE
  1523. /*----------------------------------------------------------------------------*/
  1524. VOID DumpPfmHeader()
  1525. {
  1526. printf("\nDUMP PFM HEADER\n");
  1527. printf("pfm.iVersion=%d\n",pfm.iVersion);
  1528. printf("pfm.iSize=%ld\n",pfm.iSize);
  1529. printf("pfm.szCopyright=%s\n",pfm.szCopyright);
  1530. printf("pfm.iType=%d\n",pfm.iType);
  1531. printf("pfm.iPoints=%d\n",pfm.iPoints);
  1532. printf("pfm.iVertRes=%d\n",pfm.iVertRes);
  1533. printf("pfm.iHorizRes=%d\n",pfm.iHorizRes);
  1534. printf("pfm.iAscent=%d\n",pfm.iAscent);
  1535. printf("pfm.iInternalLeading=%d\n",pfm.iInternalLeading);
  1536. printf("pfm.iExternalLeading=%d\n",pfm.iExternalLeading);
  1537. printf("pfm.iItalic=%d\n",pfm.iItalic);
  1538. printf("pfm.iUnderline=%d\n",pfm.iUnderline);
  1539. printf("pfm.iStrikeOut=%d\n",pfm.iStrikeOut);
  1540. printf("pfm.iWeight=%d\n",pfm.iWeight);
  1541. printf("pfm.iCharSet=%d\n",pfm.iCharSet);
  1542. printf("pfm.iPixWidth=%d\n",pfm.iPixWidth);
  1543. printf("pfm.iPixHeight=%d\n",pfm.iPixHeight);
  1544. printf("pfm.iPitchAndFamily=%d\n",pfm.iPitchAndFamily);
  1545. printf("pfm.iAvgWidth=%d\n",pfm.iAvgWidth);
  1546. printf("pfm.iMaxWidth=%d\n",pfm.iMaxWidth);
  1547. printf("pfm.iFirstChar=%c\n",pfm.iFirstChar);
  1548. printf("pfm.iLastChar=%c\n",pfm.iLastChar);
  1549. printf("pfm.iDefaultChar=%d\n",pfm.iDefaultChar);
  1550. printf("pfm.iBreakChar=%d\n",pfm.iBreakChar);
  1551. printf("pfm.iWidthBytes=%d\n",pfm.iWidthBytes);
  1552. printf("pfm.oDevice=%x\n",pfm.oDevice);
  1553. printf("pfm.oFace=%x\n",pfm.oFace);
  1554. printf("pfm.oBitsPointer=%ld\n",pfm.oBitsPointer);
  1555. printf("pfm.oBitsOffset=%ld\n",pfm.oBitsOffset);
  1556. }
  1557. /*----------------------------------------------------------------------------*/
  1558. VOID DumpCharWidths()
  1559. {
  1560. INT indx;
  1561. printf("\nCHARACTER WIDTHS\n");
  1562. for (indx = afm.iFirstChar; indx <= afm.iLastChar; indx++)
  1563. printf("indx: %d width: %d\n", indx, afm.rgcm[indx].iWidth);
  1564. }
  1565. /*----------------------------------------------------------------------------*/
  1566. VOID DumpPfmExtension()
  1567. {
  1568. printf("\nDUMP PFM EXTENSION\n");
  1569. printf("pfmext.oSizeFields=%d\n",pfmext.oSizeFields);
  1570. printf("pfmext.oExtMetricsOffset=%x\n",pfmext.oExtMetricsOffset);
  1571. printf("pfmext.oExtentTable=%x\n",pfmext.oExtentTable);
  1572. printf("pfmext.oOriginTable=%x\n",pfmext.oOriginTable);
  1573. printf("pfmext.oPairKernTable=%x\n",pfmext.oPairKernTable);
  1574. printf("pfmext.oTrackKernTable=%x\n",pfmext.oTrackKernTable);
  1575. printf("pfmext.oDriverInfo=%x\n",pfmext.oDriverInfo);
  1576. printf("pfm.iReserved=%x\n",pfm.iReserved);
  1577. }
  1578. #endif
  1579. /*----------------------------------------------------------------------------*/
  1580. /*----------------------------------------------------------------------------*/
  1581. /*----------------------------------------------------------------------------*/
  1582. /*----------------------------------------------------------------------------*/
  1583. /* Main purpose of these structures is to set up a translation table which
  1584. allows the driver to translate the font from the character set indicated in
  1585. the dfCharset field into the printer-specific character set. */
  1586. #define AVGSIZE (30 * 1024)
  1587. VOID SetDriverInfo()
  1588. {
  1589. INT i;
  1590. long sumWidth = 0L;
  1591. for (i = afm.iFirstChar; i <= afm.iLastChar; i++)
  1592. sumWidth = sumWidth + (long)afm.rgcm[i].iWidth;
  1593. d.epSize = sizeof(DRIVERINFO);
  1594. d.epVersion = DRIVERINFO_VERSION;
  1595. d.epMemUsage = (long) ( ((sumWidth+7L) >> 3) * (long)pfm.iPixHeight + 63L );
  1596. d.xtbl.symbolSet = pclinfo.symbolsetNum;
  1597. d.xtbl.offset = 0L;
  1598. d.xtbl.len = 0;
  1599. d.xtbl.firstchar = 0;
  1600. d.xtbl.lastchar = 0;
  1601. pclinfo.epEscapeSequence = GetEscapeSequence();
  1602. }
  1603. /*----------------------------------------------------------------------------*/
  1604. VOID PutDriverInfo(pcl)
  1605. INT pcl;
  1606. {
  1607. pfmext.oDriverInfo = cbBuffer;
  1608. if (pcl) {
  1609. SetDriverInfo();
  1610. PutWord(d.epSize);
  1611. PutWord(d.epVersion);
  1612. PutLong(d.epMemUsage);
  1613. PutLong(d.epEscape);
  1614. PutWord((WORD)d.xtbl.symbolSet);
  1615. PutLong(d.xtbl.offset);
  1616. PutWord(d.xtbl.len);
  1617. PutByte(d.xtbl.firstchar);
  1618. PutByte(d.xtbl.lastchar);
  1619. d.epEscape = cbBuffer;
  1620. PutString(pclinfo.epEscapeSequence);
  1621. } else
  1622. PutString(afm.szFont);
  1623. }
  1624. /*--------------------------------------------------------------------------*/
  1625. LPSZ GetEscapeSequence()
  1626. {
  1627. static char escapeStr[80];
  1628. char fixedPitch[2], pitch[10], height[10], *cp;
  1629. int enc;
  1630. float size;
  1631. size = (float) afm.iPtSize;
  1632. if( afm.fWasVariablePitch == TRUE ) {
  1633. STRCPY(fixedPitch, "1");
  1634. enc = ISPACE;
  1635. }
  1636. else {
  1637. STRCPY(fixedPitch, "");
  1638. enc = afm.iFirstChar;
  1639. }
  1640. sprintf(pitch, "%1.3f", 300.0 / (float)afm.rgcm[enc].iWidth);
  1641. if( cp = strchr(pitch, '.') ) cp[3] = '\0';
  1642. sprintf(height, "%1.2f", size);
  1643. sprintf(escapeStr, "\x01B&l%dO\x01B(%s\x01B(s%sp%sh%sv%ds%db%uT",
  1644. pclinfo.orientation, pclinfo.symbolsetStr,
  1645. fixedPitch, pitch, height,
  1646. pclinfo.style, pclinfo.strokeWeight, pclinfo.typeface);
  1647. return(escapeStr);
  1648. }
  1649. /*----------------------------------------------------------------------------*/
  1650. #if DEBUG_MODE
  1651. VOID DumpDriverInfo()
  1652. {
  1653. printf("\nDUMP DRIVERINFO STRUCTURE\n");
  1654. printf("d.epSize: %d\n", d.epSize);
  1655. printf("d.epVersion: %d\n", d.epVersion);
  1656. printf("d.epMemUsage: %ld\n", d.epMemUsage);
  1657. printf("d.epEscape: %ld\n", d.epEscape);
  1658. printf("d.xtbl.symbolSet: %d\n", d.xtbl.symbolSet);
  1659. printf("d.xtbl.offset: %ld\n", d.xtbl.offset);
  1660. printf("d.xtbl.len: %d\n", d.xtbl.len);
  1661. printf("d.xtbl.firstchar: %d\n", d.xtbl.firstchar);
  1662. printf("d.xtbl.lastchar: %d\n", d.xtbl.lastchar);
  1663. printf("d.epEscapeSequence: %s\n", d.epEscapeSequence);
  1664. }
  1665. #endif
  1666. /*----------------------------------------------------------------------------*/
  1667. /*----------------------------------------------------------------------------*/
  1668. /*----------------------------------------------------------------------------*/
  1669. /*----------------------------------------------------------------------------*/
  1670. /* Convert from PostScript to extended text metrics */
  1671. VOID AfmToEtm(pcl)
  1672. BOOL pcl; /* true if this is a PCL type device */
  1673. {
  1674. etm.iSize = 52;
  1675. /* point size in twips */
  1676. etm.iPointSize = afm.iPtSize * 20;
  1677. etm.iOrientation = (pcl) ? pclinfo.orientation + 1 : 0;
  1678. etm.iMasterHeight = (pcl) ? pfm.iPixHeight : 1000;
  1679. etm.iMinScale = (pcl) ? etm.iMasterHeight : 3;
  1680. etm.iMaxScale = (pcl) ? etm.iMasterHeight : 1000;
  1681. etm.iMasterUnits = (pcl) ? etm.iMasterHeight : 1000;
  1682. /* in general need to worry a little about what happens if these various
  1683. glyphs are not present as in a decorative font. */
  1684. etm.iCapHeight = afm.rgcm['H'].rc.top;
  1685. etm.iXHeight = afm.rgcm['x'].rc.top;
  1686. etm.iLowerCaseAscent = afm.rgcm['d'].rc.top;
  1687. etm.iLowerCaseDescent = - afm.rgcm['p'].rc.bottom;
  1688. etm.iSlant = (pcl) ? afm.iItalicAngle * 10 : afm.iItalicAngle;
  1689. etm.iSuperScript = (pcl) ? 0 : -500;
  1690. etm.iSubScript = (pcl) ? 0 : 250;
  1691. etm.iSuperScriptSize = (pcl) ? 0 : 500;
  1692. etm.iSubScriptSize = (pcl) ? 0 : 500;
  1693. etm.iUnderlineOffset = (pcl) ? 0 : afm.ulOffset;
  1694. etm.iUnderlineWidth = (pcl) ? 1 : afm.ulThick;
  1695. etm.iDoubleUpperUnderlineOffset = (pcl) ? 0 : afm.ulOffset / 2;
  1696. etm.iDoubleLowerUnderlineOffset = (pcl) ? 0 : afm.ulOffset;
  1697. etm.iDoubleUpperUnderlineWidth = (pcl) ? 1 : afm.ulThick / 2;
  1698. etm.iDoubleLowerUnderlineWidth = (pcl) ? 1 : afm.ulThick / 2;
  1699. etm.iStrikeOutOffset = (pcl) ? 0 : fiCapHeight / 2 - (afm.ulThick / 2);
  1700. etm.iStrikeOutWidth = (pcl) ? 1 : afm.ulThick;
  1701. etm.nKernPairs = afm.kp.cPairs;
  1702. etm.nKernTracks = afm.kt.cTracks;
  1703. }
  1704. /*----------------------------------------------------------------------------*/
  1705. VOID PutEtm(pcl)
  1706. BOOL pcl; /* true if this is a PCL type device */
  1707. {
  1708. AfmToEtm(pcl);
  1709. PutWord(etm.iSize);
  1710. PutWord(etm.iPointSize);
  1711. PutWord(etm.iOrientation);
  1712. PutWord(etm.iMasterHeight);
  1713. PutWord(etm.iMinScale);
  1714. PutWord(etm.iMaxScale);
  1715. PutWord(etm.iMasterUnits);
  1716. PutWord(etm.iCapHeight);
  1717. PutWord(etm.iXHeight);
  1718. PutWord(etm.iLowerCaseAscent);
  1719. PutWord(etm.iLowerCaseDescent);
  1720. PutWord(etm.iSlant);
  1721. PutWord(etm.iSuperScript);
  1722. PutWord(etm.iSubScript);
  1723. PutWord(etm.iSuperScriptSize);
  1724. PutWord(etm.iSubScriptSize);
  1725. PutWord(etm.iUnderlineOffset);
  1726. PutWord(etm.iUnderlineWidth);
  1727. PutWord(etm.iDoubleUpperUnderlineOffset);
  1728. PutWord(etm.iDoubleLowerUnderlineOffset);
  1729. PutWord(etm.iDoubleUpperUnderlineWidth);
  1730. PutWord(etm.iDoubleLowerUnderlineWidth);
  1731. PutWord(etm.iStrikeOutOffset);
  1732. PutWord(etm.iStrikeOutWidth);
  1733. PutWord(etm.nKernPairs);
  1734. PutWord(etm.nKernTracks);
  1735. #if DEBUG_MODE
  1736. DumpEtm();
  1737. #endif
  1738. }
  1739. /*----------------------------------------------------------------------------*/
  1740. #if DEBUG_MODE
  1741. VOID DumpEtm()
  1742. {
  1743. printf("\nDUMP ETM STRUCTURE\n");
  1744. printf("etm.iSize: %d\n", etm.iSize);
  1745. printf("etm.iPointSize: %d\n", etm.iPointSize);
  1746. printf("etm.iOrientation: %d\n", etm.iOrientation);
  1747. printf("etm.iMasterHeight: %d\n", etm.iMasterHeight);
  1748. printf("etm.iMinScale: %d\n", etm.iMinScale);
  1749. printf("etm.iMaxScale: %d\n", etm.iMaxScale);
  1750. printf("etm.iMasterUnits: %d\n", etm.iMasterUnits);
  1751. printf("etm.iCapHeight: %d\n", etm.iCapHeight);
  1752. printf("etm.iXHeight: %d\n", etm.iXHeight);
  1753. printf("etm.iLowerCaseAscent: %d\n", etm.iLowerCaseAscent);
  1754. printf("etm.iLowerCaseDescent: %d\n", etm.iLowerCaseDescent);
  1755. printf("etm.iSlant: %d\n", etm.iSlant);
  1756. printf("etm.iSuperScript: %d\n", etm.iSuperScript);
  1757. printf("etm.iSubScript: %d\n", etm.iSubScript);
  1758. printf("etm.iSuperScriptSize: %d\n", etm.iSuperScriptSize);
  1759. printf("etm.iSubScriptSize: %d\n", etm.iSubScriptSize);
  1760. printf("etm.iUnderlineOffset: %d\n", etm.iUnderlineOffset);
  1761. printf("etm.iUnderlineWidth: %d\n", etm.iUnderlineWidth);
  1762. printf("etm.iDoubleUpperUnderlineOffset: %d\n",
  1763. etm.iDoubleUpperUnderlineOffset);
  1764. printf("etm.iDoubleLowerUnderlineOffset: %d\n",
  1765. etm.iDoubleLowerUnderlineOffset);
  1766. printf("etm.iDoubleUpperUnderlineWidth: %d\n",
  1767. etm.iDoubleUpperUnderlineWidth);
  1768. printf("etm.iDoubleLowerUnderlineWidth: %d\n",
  1769. etm.iDoubleLowerUnderlineWidth);
  1770. printf("etm.iStrikeOutOffset: %d\n", etm.iStrikeOutOffset);
  1771. printf("etm.iStrikeOutWidth: %d\n", etm.iStrikeOutWidth);
  1772. printf("etm.nKernPairs: %d\n", etm.nKernPairs);
  1773. printf("etm.nKernTracks: %d\n", etm.nKernTracks);
  1774. }
  1775. #endif
  1776. /*----------------------------------------------------------------------------*/
  1777. /*----------------------------------------------------------------------------*/
  1778. /*----------------------------------------------------------------------------*/
  1779. /*----------------------------------------------------------------------------*/
  1780. /**************************************************************
  1781. * Name: StartParse()
  1782. ***************************************************************/
  1783. VOID StartParse()
  1784. {
  1785. fEOF = FALSE;
  1786. fUnGetLine = FALSE;
  1787. cbBuffer = 0;
  1788. }
  1789. /**************************************************************
  1790. * Name: szIsEqual()
  1791. * Action: Compare two NULL terminated strings.
  1792. * Returns: TRUE if they are equal FALSE if they are different
  1793. ***************************************************************/
  1794. BOOL szIsEqual(sz1, sz2)
  1795. LPSZ sz1;
  1796. LPSZ sz2;
  1797. {
  1798. while (*sz1 && *sz2)
  1799. if (*sz1++ != *sz2++) return(FALSE);
  1800. return(*sz1 == *sz2);
  1801. }
  1802. /**************************************************************
  1803. * Name: szMove()
  1804. * Action: Copy a string. This function will copy at most the
  1805. * number of bytes in the destination area - 1.
  1806. ***************************************************************/
  1807. VOID szMove(szDst, szSrc, cbDst)
  1808. LPSZ szDst; /* Ptr to the destination area */
  1809. LPSZ szSrc; /* Ptr to the source area */
  1810. INT cbDst; /* The size of the destination area */
  1811. {
  1812. while (*szDst++ = *szSrc++)
  1813. if (--cbDst <= 0) {
  1814. *(szDst-1) = 0;
  1815. break;
  1816. }
  1817. }
  1818. /*****************************************************************
  1819. * Name: GetBuffer()
  1820. * Action: Read a new buffer full of text from the input file.
  1821. ******************************************************************/
  1822. BOOL GetBuffer(hfile)
  1823. INT hfile;
  1824. {
  1825. cbBuffer = 0;
  1826. if (!fEOF) {
  1827. cbBuffer = READ_BLOCK(hfile, rgbBuffer, sizeof(rgbBuffer));
  1828. if (cbBuffer<=0) {
  1829. cbBuffer = 0;
  1830. fEOF = TRUE;
  1831. }
  1832. }
  1833. pbBuffer = rgbBuffer;
  1834. return(!fEOF);
  1835. }
  1836. /*****************************************************************
  1837. * Name: UnGetLine()
  1838. * Action: This routine pushes the most recent line back into the
  1839. * input buffer.
  1840. *******************************************************************/
  1841. VOID UnGetLine()
  1842. {
  1843. fUnGetLine = TRUE;
  1844. szLine = rgbLine;
  1845. }
  1846. /******************************************************************
  1847. * Name: GetLine()
  1848. * Action: This routine gets the next line of text out of the
  1849. * input buffer. Handles both binary & text mode.
  1850. ********************************************************************/
  1851. BOOL GetLine(hfile)
  1852. INT hfile;
  1853. {
  1854. CHAR szWord[10];
  1855. // WriteDots();
  1856. szLine = rgbLine;
  1857. do { /* skip comment lines */
  1858. if( !_GetLine(hfile) ) return(FALSE);
  1859. GetWord(szWord, sizeof(szWord));
  1860. } while( szIsEqual("Comment", szWord) );
  1861. szLine = rgbLine;
  1862. return(TRUE);
  1863. }
  1864. BOOL _GetLine(hfile)
  1865. INT hfile;
  1866. {
  1867. INT cbLine;
  1868. CHAR bCh;
  1869. if( fUnGetLine ) {
  1870. szLine = rgbLine;
  1871. fUnGetLine = FALSE;
  1872. return(TRUE);
  1873. }
  1874. cbLine = 0;
  1875. szLine = rgbLine;
  1876. *szLine = 0;
  1877. if( !fEOF )
  1878. {
  1879. while( TRUE )
  1880. {
  1881. if ( cbBuffer <= 0 )
  1882. if( !GetBuffer(hfile) ) return(FALSE);
  1883. while( --cbBuffer >= 0 )
  1884. {
  1885. bCh = *pbBuffer++;
  1886. if( bCh=='\n' || ++cbLine > (sizeof(rgbLine)-1) )
  1887. {
  1888. *szLine = 0;
  1889. szLine = rgbLine;
  1890. EatWhite();
  1891. if( *szLine != 0 ) goto DONE;
  1892. szLine = rgbLine;
  1893. cbLine = 0;
  1894. continue;
  1895. }
  1896. else if( bCh >= ' ' )
  1897. {
  1898. *szLine++ = bCh;
  1899. }
  1900. }
  1901. }
  1902. }
  1903. *szLine = 0;
  1904. DONE:
  1905. szLine = rgbLine;
  1906. return(!fEOF);
  1907. }
  1908. /****************************************************************
  1909. * Name: EatWhite()
  1910. * Action: This routine moves the input buffer pointer forward to
  1911. * the next non-white character.
  1912. ******************************************************************/
  1913. VOID EatWhite()
  1914. {
  1915. while (*szLine && (*szLine==' ' || *szLine=='\t'))
  1916. ++szLine;
  1917. }
  1918. /*******************************************************************
  1919. * Name: GetWord()
  1920. * Action: This routine gets the next word delimited by white space
  1921. * from the input buffer.
  1922. *********************************************************************/
  1923. VOID GetWord(szWord, cbWord)
  1924. LPSZ szWord; /* Ptr to the destination area */
  1925. INT cbWord; /* The size of the destination area */
  1926. {
  1927. CHAR bCh;
  1928. EatWhite();
  1929. while (--cbWord>0) {
  1930. switch(bCh = *szLine++) {
  1931. case 0:
  1932. case ' ':
  1933. case '\t': --szLine;
  1934. goto DONE;
  1935. case ';': *szWord++ = bCh;
  1936. goto DONE;
  1937. default: *szWord++ = bCh;
  1938. break;
  1939. }
  1940. }
  1941. DONE:
  1942. *szWord = 0;
  1943. }
  1944. /*******************************************************************
  1945. * Name: GetString()
  1946. * Action: This routine gets the next word delimited by parentheses
  1947. * from the input buffer.
  1948. *********************************************************************/
  1949. BOOL GetString(szWord, cbWord)
  1950. LPSZ szWord; /* Ptr to the destination area */
  1951. INT cbWord; /* The size of the destination area */
  1952. {
  1953. CHAR bCh;
  1954. BOOL result = TRUE;
  1955. EatWhite();
  1956. if( *szLine == '(' ) szLine++;
  1957. else result = FALSE;
  1958. while (--cbWord>0) {
  1959. switch(bCh = *szLine++) {
  1960. case 0: result = FALSE;
  1961. goto DONE;
  1962. case ')': --szLine;
  1963. goto DONE;
  1964. default: *szWord++ = bCh;
  1965. break;
  1966. }
  1967. }
  1968. DONE:
  1969. *szWord = 0;
  1970. return(result);
  1971. }
  1972. /************************************************************
  1973. * Name: GetNumber()
  1974. * Action: This routine parses an ASCII decimal number from the
  1975. * input file stream and returns its value.
  1976. ***************************************************************/
  1977. BOOL GetNumber(piVal)
  1978. SHORT *piVal;
  1979. {
  1980. INT iVal;
  1981. BOOL fNegative;
  1982. fNegative = FALSE;
  1983. iVal = 0;
  1984. EatWhite();
  1985. if (*szLine=='-') {
  1986. fNegative = TRUE;
  1987. ++szLine;
  1988. }
  1989. if (*szLine<'0' || *szLine>'9') {
  1990. *piVal = 0;
  1991. return(FALSE);
  1992. }
  1993. while (*szLine>='0' && *szLine<='9')
  1994. iVal = iVal * 10 + (*szLine++ - '0');
  1995. if (fNegative) iVal = - iVal;
  1996. if (*szLine==0 || *szLine==' ' || *szLine=='\t' || *szLine==';') {
  1997. *piVal = (SHORT)iVal;
  1998. return(TRUE);
  1999. }
  2000. else {
  2001. *piVal = 0;
  2002. return(FALSE);
  2003. }
  2004. }
  2005. /******************************************************************
  2006. * Name: GetFloat()
  2007. * Action: This routine parses an ASCII floating point decimal number
  2008. * from the input file stream and returns its value scaled
  2009. * by a specified amount.
  2010. *********************************************************************/
  2011. BOOL GetFloat(pScale, piVal)
  2012. float *pScale; /* The amount to scale the value by */
  2013. SHORT *piVal;
  2014. {
  2015. float scale;
  2016. long lVal;
  2017. long lDivisor;
  2018. BOOL fNegative;
  2019. scale = *pScale;
  2020. EatWhite();
  2021. fNegative = FALSE;
  2022. lVal = 0L;
  2023. if (*szLine=='-') {
  2024. fNegative = TRUE;
  2025. ++szLine;
  2026. }
  2027. if (*szLine<'0' || *szLine>'9') {
  2028. *piVal = 0;
  2029. return(FALSE);
  2030. }
  2031. while (*szLine>='0' && *szLine<='9') lVal = lVal * 10 + (*szLine++ - '0');
  2032. lDivisor = 1L;
  2033. if (*szLine=='.') {
  2034. ++szLine;
  2035. while (*szLine>='0' && *szLine<='9') {
  2036. lVal = lVal * 10 + (*szLine++ - '0');
  2037. lDivisor = lDivisor * 10;
  2038. }
  2039. }
  2040. lVal = (lVal * (long) scale) / lDivisor;
  2041. if (fNegative) lVal = - lVal;
  2042. if (*szLine==0 || *szLine==' ' || *szLine=='\t' || *szLine==';') {
  2043. *piVal = (INT) lVal;
  2044. return(TRUE);
  2045. }
  2046. else {
  2047. *piVal = 0;
  2048. return(FALSE);
  2049. }
  2050. }
  2051. /***************************************************************
  2052. * Name: MapToken()
  2053. * Action: This routine maps an ascii key word into an integer token.
  2054. * Returns: The token value.
  2055. ******************************************************************/
  2056. INT MapToken(szWord, map)
  2057. LPSZ szWord; /* Ptr to the ascii keyword string */
  2058. KEY *map;
  2059. {
  2060. KEY *pkey;
  2061. pkey = map;
  2062. while (pkey->szKey) {
  2063. if( szIsEqual(szWord, pkey->szKey) ) return(pkey->iValue);
  2064. ++pkey;
  2065. }
  2066. return(TK_UNDEFINED);
  2067. }
  2068. /*********************************************************************
  2069. * Name: GetToken()
  2070. * Action: Get the next token from the input stream.
  2071. ***********************************************************************/
  2072. INT GetToken(hfile, map)
  2073. INT hfile;
  2074. KEY *map;
  2075. {
  2076. CHAR szWord[80];
  2077. if (*szLine==0)
  2078. if( !GetLine(hfile) ) return(TK_EOF);
  2079. GetWord(szWord, sizeof(szWord));
  2080. return(MapToken(szWord, map));
  2081. }
  2082. /*--------------------------------------------------------------------------*/
  2083. /*--------------------------------------------------------------------------*/
  2084. /*--------------------------------------------------------------------------*/
  2085. /*--------------------------------------------------------------------------*/
  2086. GlyphName *AllocateGlyphArray(arraymax)
  2087. INT arraymax;
  2088. {
  2089. GlyphName *p;
  2090. INT i;
  2091. p = (GlyphName *) AllocateMem( (UINT) (sizeof(LPSZ) * (arraymax+2)) );
  2092. if( p == NULL ) {
  2093. ; // PostError(str(MSG_PFM_BAD_MALLOC));
  2094. return(NULL);
  2095. }
  2096. for(i=0; i<=arraymax; i++)
  2097. p[i] = notdef;
  2098. p[i] = NULL;
  2099. return(p);
  2100. }
  2101. /*--------------------------------------------------------------------------*/
  2102. VOID PutGlyphName(array, index, glyph)
  2103. GlyphName *array;
  2104. INT index;
  2105. LPSZ glyph;
  2106. {
  2107. LPSZ p;
  2108. if ( !STRCMP(glyph, ".notdef") )
  2109. array[index] = notdef;
  2110. else {
  2111. p = (LPSZ) AllocateMem((UINT) (strlen(glyph)+1));
  2112. if ( p == NULL ) {
  2113. ; // PostError(str(MSG_PFM_BAD_MALLOC));
  2114. parseError = TRUE;
  2115. return;
  2116. }
  2117. STRCPY(p, glyph);
  2118. array[index] = p;
  2119. }
  2120. }
  2121. /*--------------------------------------------------------------------------*/