Source code of Windows XP (NT5)
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.

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