|
|
1.1 root 1: //--------------------------------------------------------------------------
2: //
3: // Module Name: AFMTOPFM.C
4: //
5: // This module of the afm compiler parses the afm file and collects
6: // information in the PFM structure. It then passes control to the
7: // pfm module which outputs the pfm file.
8: //
9: // USAGE: AFM <AFM filename> <MS database filename>
10: // output is filename.pfm.
11: //
12: // Author: Kent Settle (kentse)
13: // Created: 18-Mar-1991
14: //
15: // Copyright (c) 1988 - 1993 Microsoft Corporation
16: //--------------------------------------------------------------------------
17:
18: #include <string.h>
19: #include "pscript.h"
20: #include "mapping.h"
21: #include "tables.h"
22:
23: int _fltused; // HEY, it shut's up the linker. That's why it's here.
24:
25: #define U_SPACE 0x20
26: #define U_SYMBOL_BULLET 0x00B7
27: #define U_BULLET 0x2022
28:
29: // Alias Family Tables.
30:
31: static char *TimesAlias[] = {"Times", "Tms Rmn", "Times Roman", "TimesRoman",
32: "TmsRmn", "Varitimes", "Dutch",
33: "Times New Roman", "TimesNewRomanPS",
34: NULL };
35:
36: static char *HelveticaAlias[] = {"Helvetica", "Helv", "Arial", "Swiss", NULL};
37:
38: static char *CourierAlias[] = {"Courier", "Courier New", NULL};
39:
40: static char *HelveticaNarrowAlias[] = {"Helvetica-Narrow", "Helvetica Narrow",
41: "Arial-Narrow", "Arial Narrow", NULL};
42:
43: static char *PalatinoAlias[] = {"Palatino", "Zapf Calligraphic",
44: "Bookman Antiqua", "Book Antiqua",
45: "ZapfCalligraphic", NULL};
46:
47: static char *BookmanAlias[] = {"ITC Bookman", "Bookman Old Style", "Bookman",
48: NULL};
49:
50: static char *NewCenturySBAlias[] = {"NewCenturySchlbk", "New Century Schoolbook",
51: "Century Schoolbook", "NewCenturySchoolBook",
52: "New Century SchoolBook", "CenturySchoolBook",
53: NULL};
54:
55: static char *AvantGardeAlias[] = {"AvantGarde", "ITC Avant Garde Gothic",
56: "Century Gothic", "ITC Avant Garde", NULL};
57:
58: static char *ZapfChanceryAlias[] = {"ZapfChancery", "ITC Zapf Chancery",
59: "Monotype Corsiva", NULL};
60:
61: static char *ZapfDingbatsAlias[] = {"ZapfDingbats", "ITC Zapf Dingbats",
62: "Monotype Sorts", "Zapf Dingbats", NULL};
63:
64: static USHORT ausIFIMetrics2WinWeight[12] =
65: {
66: FW_DONTCARE,
67: FW_DONTCARE,
68: FW_LIGHT,
69: FW_LIGHT,
70: FW_NORMAL,
71: FW_NORMAL,
72: FW_NORMAL,
73: FW_BOLD,
74: FW_BOLD,
75: FW_BOLD,
76: FW_BOLD,
77: FW_BOLD
78: };
79:
80: //#define ALL_METRICS
81:
82: // declarations of routines defined within this module.
83:
84: VOID PrintLine(char *);
85: VOID ParseKernPairs(PPARSEDATA);
86: VOID ParseKernData(PPARSEDATA);
87: VOID ParseFontName(PPARSEDATA);
88: VOID ParseFullName(PPARSEDATA);
89: VOID ParseFamilyName(PPARSEDATA);
90: VOID ParseWeight(PPARSEDATA);
91: BOOL ParseCharMetrics(PPARSEDATA);
92: int ParseCharName(PPARSEDATA);
93: int ParseCharWidth(PPARSEDATA);
94: VOID ParseBoundingBox(PPARSEDATA);
95: VOID InitPfm(PPARSEDATA);
96: VOID SetWidths(PPARSEDATA);
97: BOOL WritePFM(PWSTR, PPARSEDATA);
98: VOID ParseAfm(PPARSEDATA);
99: int ParseCharCode(PPARSEDATA);
100: int GetCharCode(char *, PPARSEDATA);
101: BOOL GetFirstLastChar(PPARSEDATA);
102: VOID BuildNTFM(PPARSEDATA, PSTR);
103: VOID InitIFIMETRICS(PPARSEDATA);
104: VOID CompleteIFIMETRICS(PPARSEDATA);
105: VOID ParseMSFamilyName(PPARSEDATA);
106: VOID ParsePitch(PPARSEDATA);
107: VOID GetFamilyAliases(IFIMETRICS *, PSTR);
108:
109: // external declarations.
110:
111: extern BOOL GetLine(PPARSEDATA);
112: extern int GetFloat(int, PPARSEDATA);
113: extern int GetNumber(PPARSEDATA);
114: extern VOID UnGetLine(PPARSEDATA);
115: extern VOID EatWhite(PPARSEDATA);
116: extern VOID GetWord(char *, int, PPARSEDATA);
117: extern int MapToken(char *, TABLE_ENTRY *);
118: extern int GetKeyword(TABLE_ENTRY *, PPARSEDATA);
119:
120: //--------------------------------------------------------------------------
121: //
122: // VOID InitPfm(pdata)
123: // PPARSEDATA pdata;
124: //
125: // Initialize the NTFM structure.
126: //
127: // Returns:
128: // This routine returns no value.
129: //
130: // History:
131: // 18-Mar-1991 -by- Kent Settle (kentse)
132: // Brought in from PM, and cleaned up.
133: //--------------------------------------------------------------------------
134:
135: VOID InitPfm(pdata)
136: PPARSEDATA pdata;
137: {
138: PNTFM pntfm;
139:
140: pntfm = pdata->pntfm;
141:
142: pntfm->cjThis = DWORDALIGN(sizeof(NTFM));
143: pntfm->ulVersion = (ULONG)PFM_VERSION;
144: pntfm->fwdLowerCaseAscent = 0;
145: pntfm->loszFullName = 0;
146: pntfm->loszFontName = 0;
147: pntfm->loszFamilyName = 0;
148: pntfm->cKernPairs = 0;
149: pntfm->cCharacters = 0;
150: pntfm->cjSoftFont = 0;
151: pntfm->loSoftFont = 0;
152: pntfm->loIFIMETRICS = 0;
153: }
154:
155:
156: //--------------------------------------------------------------------------
157: // VOID ParseAfm(pdata)
158: // PPARSEDATA pdata;
159: //
160: // Parses most of the AFM file to fill in the NTFM structure.
161: //
162: // Parameters:
163: // None.
164: //
165: // Returns:
166: // This routine returns no value.
167: //
168: // History:
169: // 19-Mar-1991 -by- Kent Settle (kentse)
170: // Ripped out of main.
171: //--------------------------------------------------------------------------
172:
173: VOID ParseAfm(pdata)
174: PPARSEDATA pdata;
175: {
176: int iToken;
177: BOOL fEndOfInput;
178: PNTFM pntfm;
179: PIFIMETRICS pTmpIFI;
180: FLOAT eCharSlope;
181:
182: // get local pointers.
183:
184: pntfm = pdata->pntfm;
185: pTmpIFI = pdata->pTmpIFI;
186:
187: // fill in some default values.
188:
189: InitIFIMETRICS(pdata);
190:
191: fEndOfInput = FALSE;
192: while (!fEndOfInput)
193: {
194: GetLine(pdata);
195: iToken = GetKeyword(AFMKeywordTable, pdata);
196:
197: switch(iToken)
198: {
199: case TK_STARTFONTMETRICS:
200: break;
201:
202: case TK_STARTKERNDATA:
203: ParseKernData(pdata);
204: break;
205:
206: case TK_FONTNAME:
207: ParseFontName(pdata);
208: break;
209:
210: case TK_FULLNAME:
211: ParseFullName(pdata);
212: break;
213:
214: case TK_FAMILYNAME:
215: ParseFamilyName(pdata);
216: break;
217:
218: case TK_WEIGHT:
219: ParseWeight(pdata);
220:
221: pTmpIFI->usWinWeight = ausIFIMetrics2WinWeight[pTmpIFI->panose.bWeight];
222:
223: if (pTmpIFI->usWinWeight > FW_NORMAL)
224: pTmpIFI->fsSelection |= FM_SEL_BOLD;
225:
226: break;
227:
228: case TK_ITALICANGLE:
229: eCharSlope = (FLOAT)(GetFloat(10, pdata) / 10);
230:
231: if ((LONG)(eCharSlope * 1000) == 0)
232: {
233: pTmpIFI->ptlCaret.x = 0;
234: pTmpIFI->ptlCaret.y = 1;
235: }
236: else
237: {
238: pTmpIFI->fsSelection |= FM_SEL_ITALIC;
239:
240: // lean 17.5 degrees away from the y-axis.
241:
242: pTmpIFI->ptlCaret.x = 3153;
243: pTmpIFI->ptlCaret.y = 10000;
244: }
245:
246: break;
247:
248: case TK_MSFAMILY:
249: ParseMSFamilyName(pdata);
250: break;
251:
252: case TK_ISFIXEDPITCH:
253: ParsePitch(pdata);
254:
255: break;
256:
257: case TK_ENCODINGSCHEME:
258: break;
259:
260: case TK_UNDERLINEPOSITION:
261: pTmpIFI->fwdUnderscorePosition = (FWORD) GetNumber(pdata);
262: #ifdef ALL_METRICS
263: DbgPrint("fwdUnderscorePosition = %d\n",
264: pTmpIFI->fwdUnderscorePosition);
265: #endif
266: break;
267:
268: case TK_UNDERLINETHICKNESS:
269: pTmpIFI->fwdUnderscoreSize = (FWORD)GetNumber(pdata);
270: pTmpIFI->fwdStrikeoutSize = pTmpIFI->fwdUnderscoreSize;
271: #ifdef ALL_METRICS
272: DbgPrint("fwdUnderscoreSize = %d\n",
273: pTmpIFI->fwdUnderscoreSize);
274: #endif
275: break;
276:
277: case TK_FONTBBOX:
278: ParseBoundingBox(pdata);
279: break;
280:
281: case TK_CAPHEIGHT:
282: break;
283:
284: case TK_XHEIGHT:
285: pTmpIFI->fwdXHeight = (FWORD)GetNumber(pdata);
286: #ifdef ALL_METRICS
287: DbgPrint("fwdXHeight = %d\n", pTmpIFI->fwdXHeight);
288: #endif
289: break;
290:
291: case TK_ASCENDER:
292: pntfm->fwdLowerCaseAscent = (FWORD)GetNumber(pdata);
293: #ifdef ALL_METRICS
294: DbgPrint("fwdLowerCaseAscent = %d\n",
295: pntfm->fwdLowerCaseAscent);
296: #endif
297: break;
298:
299: case TK_STARTCHARMETRICS:
300: ParseCharMetrics(pdata);
301: break;
302:
303: case TK_ENDFONTMETRICS:
304: fEndOfInput = TRUE;
305: break;
306:
307: }
308:
309: pdata->szLine = pdata->rgbLine;
310: }
311: }
312:
313:
314: //--------------------------------------------------------------------------
315: //
316: // VOID SetWidths();
317: //
318: // This routine computes the maximum and average character widths from the
319: // character metrics in the NTFM structure.
320: //
321: // Parameters:
322: // None.
323: //
324: // Returns:
325: // This routine returns no value.
326: //
327: // History:
328: // 01-Apr-1991 -by- Kent Settle (kentse)
329: // Wrote it.
330: //--------------------------------------------------------------------------
331:
332: VOID SetWidths(pdata)
333: PPARSEDATA pdata;
334: {
335: USHORT i;
336: int iAvg;
337: int iMax;
338:
339: iAvg = 0;
340: iMax = 0;
341:
342: // calculate maximum and average character widths.
343:
344: for (i = 0; i < pdata->pntfm->cCharacters; i++)
345: {
346: iAvg += (int)pdata->TmpCharWidths[i];
347: if (iMax < (int)pdata->TmpCharWidths[i])
348: iMax = (int)pdata->TmpCharWidths[i];
349: }
350:
351: pdata->pTmpIFI->fwdAveCharWidth = (FWORD)(iAvg / pdata->pntfm->cCharacters);
352:
353: pdata->pTmpIFI->fwdMaxCharInc = (FWORD)iMax;
354:
355: #ifdef ALL_METRICS
356: DbgPrint("fwdAveCharWidth = %d\n", pdata->pTmpIFI->fwdAveCharWidth);
357: DbgPrint("fwdMaxCharInc = %d\n", pdata->pTmpIFI->fwdMaxCharInc);
358: #endif
359: }
360:
361:
362: //--------------------------------------------------------------------------
363: //
364: // VOID ParseKernPairs();
365: //
366: // Parse the pairwise kerning data.
367: //
368: // Parameters:
369: // None.
370: //
371: // Returns:
372: // This routine returns no value.
373: //
374: // History:
375: // 13-Mar-1992 -by- Kent Settle (kentse)
376: // Modified to use FD_KERNINGPAIR struct instead of KP.
377: // 18-Mar-1991 -by- Kent Settle (kentse)
378: // Brought in from PM, and cleaned up.
379: //--------------------------------------------------------------------------
380:
381: VOID ParseKernPairs(pdata)
382: PPARSEDATA pdata;
383: {
384: int i;
385: int iCh1;
386: int iCh2;
387: int iKernAmount;
388: int iToken;
389: int cPairs;
390: char szWord[80];
391: WCHAR wc1, wc2;
392: UCMap *pmap;
393: UCMap *pmapReset;
394: BOOL bFound;
395: cPairs = GetNumber(pdata);
396:
397: pdata->pntfm->cKernPairs = (USHORT)cPairs;
398:
399: // point to the appropriate mapping table in mapping.h.
400:
401: if (!strcmp(pdata->szTmpFontName, "Symbol"))
402: pmap = SymbolMap;
403: else if (!strcmp(pdata->szTmpFontName, "ZapfDingbats"))
404: pmap = DingbatsMap;
405: else
406: pmap = LatinMap;
407:
408: pmapReset = pmap;
409:
410: for (i = 0; i < cPairs; ++i)
411: {
412: if (GetLine(pdata))
413: break;
414: if (GetKeyword(AFMKeywordTable, pdata) != TK_KPX)
415: {
416: UnGetLine(pdata);
417: break;
418: }
419:
420: GetWord(szWord, sizeof(szWord), pdata);
421: #ifdef ALL_METRICS
422: DbgPrint("Char1 = %s ", szWord);
423: #endif
424: iCh1 = GetCharCode(szWord, pdata);
425: GetWord(szWord, sizeof(szWord), pdata);
426: #ifdef ALL_METRICS
427: DbgPrint("Char2 = %s ", szWord);
428: #endif
429: iCh2 = GetCharCode(szWord, pdata);
430:
431: iKernAmount = GetNumber(pdata);
432:
433: #ifdef ALL_METRICS
434: DbgPrint("Amount = %d\n", iKernAmount);
435: #endif
436:
437: iCh1 = iCh1 & 0x0FF; // 0 <= CharacerCode <= 255.
438: iCh2 = iCh2 & 0x0FF;
439:
440: // we now have the postscript character code for each character
441: // of the kerning pair. we now need to convert them to UNICODE.
442:
443: pmap = pmapReset;
444:
445: bFound = FALSE;
446:
447: while (pmap->szChar)
448: {
449: if ((USHORT)(pmap->usPSValue & 0x7FFF) == (USHORT)iCh1)
450: {
451: wc1 = pmap->usUCValue;
452: bFound = TRUE;
453: break;
454: }
455: pmap++;
456: }
457:
458: if (!bFound)
459: DbgPrint("GetPairs: Error char code %d not found.\n", iCh1);
460:
461: pmap = pmapReset;
462:
463: bFound = FALSE;
464:
465: while (pmap->szChar)
466: {
467: if ((USHORT)(pmap->usPSValue & 0x7FFF) == (USHORT)iCh2)
468: {
469: wc2 = pmap->usUCValue;
470: bFound = TRUE;
471: break;
472: }
473: pmap++;
474: }
475:
476: #ifdef ALL_METRICS
477: if (!bFound)
478: DbgPrint("GetPairs: Error char code %d not found.\n", iCh2);
479: #endif
480: pdata->TmpKernPairs[i].wcFirst = wc1;
481: pdata->TmpKernPairs[i].wcSecond = wc2;
482: pdata->TmpKernPairs[i].fwdKern = (FWORD)iKernAmount;
483: }
484:
485: GetLine(pdata);
486: iToken = GetKeyword(AFMKeywordTable, pdata);
487:
488: #if DBG
489: if (pdata->fEOF)
490: RIP("GetPairs: Premature end of file encountered\n");
491: else if (iToken != TK_ENDKERNPAIRS)
492: {
493: DbgPrint("GetPairs: expected EndKernPairs\n");
494: DbgPrint("%s\n", pdata->rgbLine);
495: }
496: #endif
497:
498: return;
499: }
500:
501:
502: //--------------------------------------------------------------------------
503: // VOID ParseKernData(pdata)
504: // PPARSEDATA pdata;
505: //
506: // Start processing the pairwise kerning data.
507: //
508: // Parameters:
509: // None.
510: //
511: // Returns:
512: // This routine returns no value.
513: //
514: // History:
515: // 18-Mar-1991 -by- Kent Settle (kentse)
516: // Brought in from PM, and cleaned up.
517: //--------------------------------------------------------------------------
518:
519: VOID ParseKernData(pdata)
520: PPARSEDATA pdata;
521: {
522: if (!GetLine(pdata))
523: {
524: if (GetKeyword(AFMKeywordTable, pdata) == TK_STARTKERNPAIRS)
525: ParseKernPairs(pdata);
526: else
527: RIP("PSCRPTUI!ParseKernData: expected StartKernPairs\n");
528: }
529: else
530: RIP("PSCRPTUI!ParseKernData: unexpected end of file\n");
531: }
532:
533:
534: //--------------------------------------------------------------------------
535: // VOID ParseFontName(pdata)
536: // PPARSEDATA pdata;
537: //
538: // Move the font name from the input buffer into the pfm structure.
539: //
540: // Parameters:
541: // None.
542: //
543: // Returns:
544: // This routine returns no value.
545: //
546: // History:
547: // 18-Mar-1991 -by- Kent Settle (kentse)
548: // Brought in from PM, and cleaned up.
549: //--------------------------------------------------------------------------
550:
551: VOID ParseFontName(pdata)
552: PPARSEDATA pdata;
553: {
554: EatWhite(pdata);
555:
556: // get the length of the font name.
557:
558: pdata->cbFontName = strlen((char *)(pdata->szLine)) + 1;
559:
560: // now copy the facename to temporary storage.
561:
562: memcpy(pdata->szTmpFontName, pdata->szLine, pdata->cbFontName);
563:
564: #ifdef ALL_METRICS
565: DbgPrint("FontName = %s.\n", pdata->szLine);
566: #endif
567: }
568:
569:
570: //--------------------------------------------------------------------------
571: // VOID ParseFullName(pdata)
572: // PPARSEDATA pdata;
573: //
574: // Move the full name from the input buffer into the pfm structure.
575: //
576: // Parameters:
577: // None.
578: //
579: // Returns:
580: // This routine returns no value.
581: //
582: // History:
583: // 29-Mar-1991 -by- Kent Settle (kentse)
584: // Wrote it.
585: //--------------------------------------------------------------------------
586:
587: VOID ParseFullName(pdata)
588: PPARSEDATA pdata;
589: {
590: EatWhite(pdata);
591:
592: // get the length of the full name.
593:
594: pdata->cbFullName = strlen((char *)(pdata->szLine)) + 1;
595:
596: // now copy the Uniquename to temporary storage.
597:
598: memcpy(pdata->szTmpFullName, pdata->szLine, pdata->cbFullName);
599:
600: #ifdef ALL_METRICS
601: DbgPrint("FullName = %s.\n", pdata->szLine);
602: #endif
603: }
604:
605:
606: //--------------------------------------------------------------------------
607: //
608: // VOID ParseFamilyName();
609: //
610: // Move the family name from the input buffer into the pfm structure.
611: //
612: // Parameters:
613: // None.
614: //
615: // Returns:
616: // This routine returns no value.
617: //
618: // History:
619: // 29-Mar-1991 -by- Kent Settle (kentse)
620: // Wrote it.
621: //--------------------------------------------------------------------------
622:
623: VOID ParseFamilyName(pdata)
624: PPARSEDATA pdata;
625: {
626: EatWhite(pdata);
627:
628: // get the length of the family name.
629:
630: pdata->cbFamilyName = strlen((char *)(pdata->szLine)) + 1;
631:
632: // now copy the familyname to temporary storage.
633:
634: memcpy(pdata->szTmpFamilyName, pdata->szLine, pdata->cbFamilyName);
635:
636: #ifdef ALL_METRICS
637: DbgPrint("FamilyNameName = %s.\n", pdata->szLine);
638: #endif
639: }
640:
641:
642: //--------------------------------------------------------------------------
643: // VOID ParseMSFamilyName(pdata)
644: // PPARSEDATA pdata;
645: //
646: // gets the MSFamily name, and converts it to a value.
647: //
648: // Parameters:
649: // None.
650: //
651: // Returns:
652: // This routine returns no value.
653: //
654: // History:
655: // 18-Mar-1991 -by- Kent Settle (kentse)
656: // Brought in from PM, and cleaned up.
657: //--------------------------------------------------------------------------
658:
659: VOID ParseMSFamilyName(pdata)
660: PPARSEDATA pdata;
661: {
662: char szWord[80];
663: BOOL bFound = FALSE;
664: TABLE_ENTRY *pTable;
665:
666: // clear out the MSFamily flags.
667:
668: pdata->pTmpIFI->jWinPitchAndFamily &= ~(FF_DECORATIVE | FF_DONTCARE |
669: FF_MODERN | FF_ROMAN | FF_SCRIPT |
670: FF_SWISS);
671: GetWord(szWord, sizeof(szWord), pdata);
672:
673: #ifdef ALL_METRICS
674: DbgPrint("MSFamily = %s\n", szWord);
675: #endif
676:
677: pTable = MSFamilyTable;
678: while (pTable->szStr)
679: {
680: if (!strcmp(szWord, pTable->szStr))
681: {
682: pdata->pTmpIFI->jWinPitchAndFamily |= pTable->iValue;
683: bFound = TRUE;
684: break;
685: }
686:
687: ++pTable;
688: }
689:
690: // set flag, if not found.
691:
692: if (!bFound)
693: {
694: #if DBG
695: #ifdef ALL_METRICS
696: DbgPrint("ParseMSFamilyName: unknown MSFamily = \"%s\"\n", szWord);
697: #endif
698: #endif
699: pdata->pTmpIFI->jWinPitchAndFamily |= FF_DONTCARE;
700: }
701: }
702:
703:
704: //--------------------------------------------------------------------------
705: // VOID ParseMSFamilyName(pdata)
706: // PPARSEDATA pdata;
707: //
708: // gets the MSFamily name, and converts it to a value.
709: //
710: // Parameters:
711: // None.
712: //
713: // Returns:
714: // This routine returns no value.
715: //
716: // History:
717: // 18-Mar-1991 -by- Kent Settle (kentse)
718: // Brought in from PM, and cleaned up.
719: //--------------------------------------------------------------------------
720:
721: VOID ParsePitch(pdata)
722: PPARSEDATA pdata;
723: {
724: CHAR szWord[6];
725:
726: GetWord(szWord, sizeof(szWord), pdata);
727:
728: pdata->pTmpIFI->jWinPitchAndFamily &= ~(FIXED_PITCH | VARIABLE_PITCH);
729:
730: if ((!(strncmp(szWord, "True", 4))) ||
731: (!(strncmp(szWord, "true", 4))))
732: {
733: pdata->pTmpIFI->jWinPitchAndFamily |= FIXED_PITCH;
734: #ifdef ALL_METRICS
735: DbgPrint("Font is fixed pitch.\n");
736: #endif
737: }
738: else
739: {
740: pdata->pTmpIFI->jWinPitchAndFamily |= VARIABLE_PITCH;
741: #ifdef ALL_METRICS
742: DbgPrint("Font is variable pitch.\n");
743: #endif
744: }
745: }
746:
747: //--------------------------------------------------------------------------
748: // VOID ParseWeight(pdata)
749: // PPARSEDATA pdata;
750: //
751: // Parse the fonts weight and set the corresponding entry in the PFM
752: // structure.
753: //
754: // Parameters:
755: // None.
756: //
757: // Returns:
758: // This routine returns no value.
759: //
760: // History:
761: // 18-Mar-1991 -by- Kent Settle (kentse)
762: // Brought in from PM, and cleaned up.
763: //--------------------------------------------------------------------------
764:
765: VOID ParseWeight(pdata)
766: PPARSEDATA pdata;
767: {
768: char szWord[80];
769: BOOL bFound = FALSE;
770: TABLE_ENTRY *pTable;
771:
772: GetWord(szWord, sizeof(szWord), pdata);
773:
774: #ifdef ALL_METRICS
775: DbgPrint("Weight = %s\n", szWord);
776: #endif
777:
778: pTable = WeightTable;
779: while (pTable->szStr)
780: {
781: #ifdef ALL_METRICS
782: DbgPrint("\tweight = %s\n", pTable->szStr);
783: #endif
784: if (!strcmp(szWord, pTable->szStr))
785: {
786: pdata->pTmpIFI->panose.bWeight = pTable->iValue;
787: bFound = TRUE;
788: break;
789: }
790:
791: ++pTable;
792: }
793:
794: // check for and flag error conditions.
795:
796: if (!bFound)
797: {
798: #if DBG
799: #ifdef ALL_METRICS
800: DbgPrint("ParseWeight: unknown font weight = \"%s\"\n", szWord);
801: #endif
802: #endif
803: pdata->pTmpIFI->panose.bWeight = PAN_WEIGHT_MEDIUM;
804: }
805: }
806:
807:
808: //--------------------------------------------------------------------------
809: // BOOL ParseCharMetrics(pdata)
810: // PPARSEDATA pdata;
811: //
812: // Parse the character metrics entry in the input file and set the
813: // width and bounding box in the PFM structure.
814: //
815: // Parameters:
816: // None.
817: //
818: // Returns:
819: // This routine returns no value.
820: //
821: // History:
822: // 18-Mar-1991 -by- Kent Settle (kentse)
823: // Brought in from PM, and cleaned up.
824: //--------------------------------------------------------------------------
825:
826: BOOL ParseCharMetrics(pdata)
827: PPARSEDATA pdata;
828: {
829: int cChars;
830: USHORT usCount = 0;
831: int i;
832: int iWidth;
833: int iChar;
834:
835: cChars = GetNumber(pdata);
836: for (i = 0; i < cChars; ++i)
837: {
838: if (GetLine(pdata))
839: {
840: RIP("PSCRPTUI!ParseCharMetrics: unexpected end of file encountered\n");
841: return(FALSE);
842: }
843:
844: iChar = ParseCharCode(pdata);
845:
846: iWidth = ParseCharWidth(pdata);
847:
848: iChar = ParseCharName(pdata);
849:
850: if (iChar >= 0)
851: {
852: pdata->TmpCharWidths[usCount] = (USHORT)iWidth;
853: pdata->TmpCharCodes[usCount] = (BYTE)iChar;
854:
855: usCount++; // increment character counter.
856:
857: #ifdef ALL_METRICS
858: DbgPrint("iChar = %x, CharWidth = %d\n",
859: pdata->TmpCharCodes[usCount - 1],
860: pdata->TmpCharWidths[usCount - 1]);
861: #endif
862: }
863: }
864:
865: pdata->pntfm->cCharacters = usCount;
866: GetLine(pdata);
867: if (GetKeyword(AFMKeywordTable, pdata) != TK_ENDCHARMETRICS)
868: {
869: RIP("PSCRPTUI!ParseCharMetrics: expected EndCharMetrics\n");
870: SetLastError(ERROR_INVALID_DATA);
871: return(FALSE);
872: }
873:
874: return(TRUE);
875: }
876:
877:
878: //--------------------------------------------------------------------------
879: // int ParseCharName(pdata)
880: // PPARSEDATA pdata;
881: //
882: // Parse a character's name and return its numeric value.
883: //
884: // Parameters:
885: // None.
886: //
887: // Returns:
888: // This routine returns numeric value of given character.
889: //
890: // History:
891: // 18-Mar-1991 -by- Kent Settle (kentse)
892: // Brought in from PM, and cleaned up.
893: //--------------------------------------------------------------------------
894:
895: int ParseCharName(pdata)
896: PPARSEDATA pdata;
897: {
898: int iChar;
899: char szWord[18];
900:
901: EatWhite(pdata);
902: GetWord(szWord, sizeof(szWord), pdata);
903:
904: if (!strcmp("N", szWord))
905: {
906: GetWord(szWord, sizeof(szWord), pdata);
907: #ifdef ALL_METRICS
908: DbgPrint("Char = %s ", szWord);
909: #endif
910: iChar = GetCharCode(szWord, pdata);
911: }
912: else
913: {
914: RIP("PSCRPTUI!ParseCharName: expected name field\n");
915: SetLastError(ERROR_INVALID_DATA);
916: return(-1);
917: }
918:
919: return(iChar);
920: }
921:
922:
923: //--------------------------------------------------------------------------
924: // int ParseCharWidth(pdata)
925: // PPARSEDATA pdata;
926: //
927: // Parse a character's width and return its numeric value.
928: //
929: // Parameters:
930: // None.
931: //
932: // Returns:
933: // This routine returns numeric value of given character's width.
934: //
935: // History:
936: // 18-Mar-1991 -by- Kent Settle (kentse)
937: // Brought in from PM, and cleaned up.
938: //--------------------------------------------------------------------------
939:
940: int ParseCharWidth(pdata)
941: PPARSEDATA pdata;
942: {
943: int iWidth;
944: char szWord[16];
945:
946: GetWord(szWord, sizeof(szWord), pdata);
947: if (!strcmp("WX", szWord))
948: {
949: iWidth = GetNumber(pdata);
950: if (iWidth==0)
951: {
952: RIP("PSCRPTUI!ParseCharWidth: zero character width\n");
953: SetLastError(ERROR_INVALID_DATA);
954: return(-1);
955: }
956:
957: EatWhite(pdata);
958: if (*(pdata->szLine++) != ';')
959: {
960: RIP("PSCRPTUI!ParseCharWidth: missing semicolon\n");
961: SetLastError(ERROR_INVALID_DATA);
962: return(-1);
963: }
964: }
965: else
966: {
967: RIP("PSCRPTUI!ParseCharWidth: expected \"WX\"\n");
968: SetLastError(ERROR_INVALID_DATA);
969: return(-1);
970: }
971:
972: return(iWidth);
973: }
974:
975:
976: //--------------------------------------------------------------------------
977: // int ParseCharCode(pdata)
978: // PPARSEDATA pdata;
979: //
980: // Parse the ASCII form of a character's code point and return its
981: // numeric value.
982: //
983: // Parameters:
984: // None.
985: //
986: // Returns:
987: // This routine returns numeric value of given character's codepoint.
988: //
989: // History:
990: // 18-Mar-1991 -by- Kent Settle (kentse)
991: // Brought in from PM, and cleaned up.
992: //--------------------------------------------------------------------------
993:
994: int ParseCharCode(pdata)
995: PPARSEDATA pdata;
996: {
997: int iChar;
998: char szWord[16];
999:
1000: iChar = 0;
1001: GetWord(szWord, sizeof(szWord), pdata);
1002: if (!strcmp("C", szWord))
1003: {
1004: iChar = GetNumber(pdata);
1005: if (iChar==0)
1006: {
1007: RIP("PSCRPTUI!ParseCharCode: invalid character code\n");
1008: SetLastError(ERROR_INVALID_DATA);
1009: return(-1);
1010: }
1011:
1012: EatWhite(pdata);
1013: if (*(pdata->szLine++) != ';')
1014: {
1015: RIP("PSCRPTUI!ParseCharCode: missing semicolon\n");
1016: SetLastError(ERROR_INVALID_DATA);
1017: return(-1);
1018: }
1019: }
1020: return(iChar);
1021: }
1022:
1023:
1024: //--------------------------------------------------------------------------
1025: // VOID ParseBoundingBox(pdata)
1026: // PPARSEDATA pdata;
1027: //
1028: // Parses a characters's bounding box and stores its size in
1029: // the NTFM structure.
1030: //
1031: // Parameters:
1032: // None.
1033: //
1034: // Returns:
1035: // This routine returns no value.
1036: //
1037: // History:
1038: // 18-Mar-1991 -by- Kent Settle (kentse)
1039: // Brought in from PM, and cleaned up.
1040: //--------------------------------------------------------------------------
1041:
1042: VOID ParseBoundingBox(pdata)
1043: PPARSEDATA pdata;
1044: {
1045: pdata->pntfm->rcBBox.left = GetNumber(pdata);
1046: pdata->pntfm->rcBBox.bottom = GetNumber(pdata);
1047: pdata->pntfm->rcBBox.right = GetNumber(pdata);
1048: pdata->pntfm->rcBBox.top = GetNumber(pdata);
1049: }
1050:
1051:
1052:
1053: //--------------------------------------------------------------------------
1054: // BOOL WritePFM(pwstrPFMFile, pdata)
1055: // PWSTR pwstrPFMFile;
1056: // PPARSEDATA pdata;
1057: //
1058: // Flush the ouput buffer to the file. Note that this function is only
1059: // called after the entire pfm structure has been built in the output buffer.
1060: //
1061: // Parameters:
1062: // None.
1063: //
1064: // Returns:
1065: // This routine returns TRUE if success, FALSE otherwise.
1066: //
1067: // History:
1068: // 20-Mar-1991 -by- Kent Settle (kentse)
1069: // Wrote it.
1070: //--------------------------------------------------------------------------
1071:
1072: BOOL WritePFM(pwstrPFMFile, pdata)
1073: PWSTR pwstrPFMFile;
1074: PPARSEDATA pdata;
1075: {
1076: HANDLE hPFMFile;
1077: ULONG ulCount;
1078:
1079: // create the .PFM file.
1080:
1081: hPFMFile = CreateFile(pwstrPFMFile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
1082: CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1083:
1084: if (hPFMFile == INVALID_HANDLE_VALUE)
1085: {
1086: RIP("PSCRPTUI!WritePFM: Can't open .PFM file.\n");
1087: return(FALSE);
1088: }
1089:
1090: // write to the .PFM file, then close it.
1091:
1092: if (!WriteFile(hPFMFile, (LPVOID)pdata->pntfm, (DWORD)pdata->pntfm->cjThis,
1093: (LPDWORD)&ulCount, (LPOVERLAPPED)NULL))
1094: {
1095: RIP("PSCRPTUI!WritePFM: WriteFile to .PFM file failed.\n");
1096: return(FALSE);
1097: }
1098:
1099: if (ulCount != pdata->pntfm->cjThis)
1100: {
1101: RIP("PSCRPTUI!WritePFM: WriteFile count to .PFM file failed.\n");
1102: return(FALSE);
1103: }
1104:
1105: if (!CloseHandle(hPFMFile))
1106: RIP("PSCRPTUI!WritePFM: CloseHandle of .PFM file failed.\n");
1107:
1108: return(TRUE);
1109: }
1110:
1111:
1112: //--------------------------------------------------------------------------
1113: //
1114: // int GetCharCode(szWord, pdata)
1115: // char *szWord;
1116: // PPARSEDATA pdata;
1117: //
1118: // This routine is given a pointer to the character string. It returns
1119: // the character code, as defined in mapping.h, corresponding to this
1120: // character.
1121: //
1122: // Parameters:
1123: // szWord
1124: // Pointer to character name string.
1125: //
1126: // Returns:
1127: // This routine returns -1 if character not found, otherwise it
1128: // returns the character code.
1129: //
1130: // History:
1131: // 27-Mar-1991 -by- Kent Settle (kentse)
1132: // Wrote it.
1133: //--------------------------------------------------------------------------
1134:
1135: int GetCharCode(szWord, pdata)
1136: char *szWord;
1137: PPARSEDATA pdata;
1138: {
1139: UCMap *pmap;
1140:
1141: //!!! maybe there is a better way to do this???
1142:
1143: // point to the appropriate mapping table in mapping.h.
1144:
1145: if (!strcmp(pdata->szTmpFontName, "Symbol"))
1146: pmap = SymbolMap;
1147: else if (!strcmp(pdata->szTmpFontName, "ZapfDingbats"))
1148: pmap = DingbatsMap;
1149: else
1150: pmap = LatinMap;
1151:
1152: while (pmap->szChar)
1153: {
1154: if (!strcmp(szWord, pmap->szChar))
1155: return((int)(pmap->usPSValue & 0x7FFF));
1156: pmap++;
1157: }
1158:
1159: #ifdef ALL_METRICS
1160: DbgPrint("GetCharCode: Undefined Character = %s.\n", szWord);
1161: #endif
1162: return(-1);
1163: }
1164:
1165:
1166: //--------------------------------------------------------------------------
1167: //
1168: // BOOL GetFirstLastChar()
1169: //
1170: // This routine searches through the encoding table in mapping.h to
1171: // determine the first and last characters in the font. The character
1172: // codes are stored into the NTFM structure in UNICODE value.
1173: //
1174: // Parameters:
1175: // None.
1176: //
1177: // Returns:
1178: // This routine returns TRUE for success, FALSE otherwise.
1179: //
1180: // History:
1181: // 18-Apr-1991 -by- Kent Settle (kentse)
1182: // Wrote it.
1183: //--------------------------------------------------------------------------
1184:
1185: BOOL GetFirstLastChar(pdata)
1186: PPARSEDATA pdata;
1187: {
1188: PUCMap pmap;
1189: PUCMap pmapReset;
1190: USHORT usFirst = MAX_UNICODE_VALUE;
1191: USHORT usLast = MIN_UNICODE_VALUE;
1192: USHORT i;
1193: USHORT usTmp;
1194:
1195: //!!! maybe there is a better way to do this???
1196:
1197: // point to the appropriate mapping table in mapping.h.
1198:
1199: if (!strcmp(pdata->szTmpFontName, "Symbol"))
1200: pmap = SymbolMap;
1201: else if (!strcmp(pdata->szTmpFontName, "ZapfDingbats"))
1202: pmap = DingbatsMap;
1203: else
1204: pmap = LatinMap;
1205:
1206: pmapReset = pmap;
1207:
1208: // for every character in the font, do a lookup in the mapping
1209: // table in mapping.h to find the corresponding UNICODE value.
1210:
1211: for (i = 0; i < pdata->pntfm->cCharacters; i++)
1212: {
1213: while (pmap->szChar)
1214: {
1215: if ((BYTE)pdata->TmpCharCodes[i] == (BYTE)(pmap->usPSValue & 0xFF))
1216: {
1217: usTmp = pmap->usUCValue;
1218: if (usFirst > usTmp)
1219: usFirst = usTmp;
1220: if (usLast < usTmp)
1221: usLast = usTmp;
1222: break;
1223: }
1224:
1225: pmap++;
1226: }
1227:
1228: // reset pointer.
1229:
1230: pmap = pmapReset;
1231: }
1232:
1233: // make sure we have valid numbers.
1234:
1235: if (usFirst > usLast)
1236: {
1237: RIP("PSCRPTUI!etFirstLastChar: first char > last.\n");
1238: SetLastError(ERROR_INVALID_DATA);
1239: return(FALSE);
1240: }
1241:
1242: // everything must be OK.
1243:
1244: pdata->pTmpIFI->wcFirstChar = (WCHAR)usFirst;
1245: pdata->pTmpIFI->wcLastChar = (WCHAR)usLast;
1246:
1247: #ifdef ALL_METRICS
1248: DbgPrint("FirstChar = %x, LastChar = %x.\n", usFirst, usLast);
1249: #endif
1250:
1251: return(TRUE);
1252: }
1253:
1254:
1255: //--------------------------------------------------------------------------
1256: //
1257: // VOID BuildNTFM(pdata, pPFA)
1258: // PPARSEDATA pdata;
1259: // CHAR *pPFA;
1260: //
1261: // This routine builds an NTFM structure from all the temporary values
1262: // which have been determined by now.
1263: //
1264: // Returns:
1265: // This routine returns no value.
1266: //
1267: // History:
1268: // 18-Apr-1991 -by- Kent Settle (kentse)
1269: // Wrote it.
1270: //--------------------------------------------------------------------------
1271:
1272: VOID BuildNTFM(pdata, pPFA)
1273: PPARSEDATA pdata;
1274: CHAR *pPFA;
1275: {
1276: PNTFM pntfm;
1277: int cbKernPairs, cbWidths;
1278: DWORD cbPFA;
1279: PSTR pstr;
1280:
1281: // get local pointer.
1282:
1283: pntfm = pdata->pntfm;
1284:
1285: // deal with the softfont if there is one.
1286:
1287: if (pPFA)
1288: {
1289: // the first DWORD of the .PFA file contains the length in BYTES of the
1290: // remainder of the .PFA file.
1291:
1292: cbPFA = *(DWORD *)pPFA;
1293: pntfm->cjSoftFont = DWORDALIGN(cbPFA);
1294: }
1295:
1296: // there are several bits of data which have now been put into temporary
1297: // storage, but need to be attached to the NTFM structure.
1298:
1299: cbKernPairs = (pntfm->cKernPairs * sizeof(FD_KERNINGPAIR));
1300: cbWidths = DWORDALIGN(pntfm->cCharacters * sizeof(USHORT));
1301: pntfm->cjThis += DWORDALIGN(pdata->cbFullName) + DWORDALIGN(pdata->cbFontName) +
1302: DWORDALIGN(pdata->cbFamilyName) + DWORDALIGN(cbKernPairs) +
1303: cbWidths + DWORDALIGN(pntfm->cCharacters) +
1304: DWORDALIGN(pntfm->cjSoftFont);
1305:
1306: if (pntfm->cjThis > INIT_PFM)
1307: {
1308: #if DBG
1309: DbgPrint("afm: PFM size greater than allocated.\n");
1310: #endif
1311: return;
1312: }
1313:
1314: pntfm->loszFullName = DWORDALIGN(sizeof(NTFM));
1315: pntfm->loszFontName = pntfm->loszFullName + DWORDALIGN(pdata->cbFullName);
1316: pntfm->loszFamilyName = pntfm->loszFontName + DWORDALIGN(pdata->cbFontName);
1317: pntfm->loKernPairs = pntfm->loszFamilyName +
1318: DWORDALIGN(pdata->cbFamilyName);
1319: pntfm->loCharMetrics = pntfm->loKernPairs + DWORDALIGN(cbKernPairs);
1320:
1321: if (pPFA)
1322: pntfm->loSoftFont = pntfm->loCharMetrics +
1323: DWORDALIGN(pntfm->cCharacters) + cbWidths;
1324:
1325: pntfm->loIFIMETRICS = pntfm->loCharMetrics +
1326: DWORDALIGN(pntfm->cCharacters) + cbWidths +
1327: DWORDALIGN(pntfm->cjSoftFont);
1328:
1329: pstr = (char *)pntfm + pntfm->loszFullName;
1330: memcpy(pstr, pdata->szTmpFullName, pdata->cbFullName);
1331: pstr += DWORDALIGN(pdata->cbFullName);
1332: memcpy(pstr, pdata->szTmpFontName, pdata->cbFontName);
1333: pstr += DWORDALIGN(pdata->cbFontName);
1334: memcpy(pstr, (char *)pdata->szTmpFamilyName, pdata->cbFamilyName);
1335: pstr += DWORDALIGN(pdata->cbFamilyName);
1336: memcpy(pstr, (char *)pdata->TmpKernPairs, cbKernPairs);
1337: pstr += DWORDALIGN(cbKernPairs);
1338: memcpy(pstr, (char *)pdata->TmpCharWidths, cbWidths);
1339: pstr += cbWidths;
1340: memcpy(pstr, (char *)pdata->TmpCharCodes, pntfm->cCharacters);
1341: pstr += DWORDALIGN(pntfm->cCharacters);
1342:
1343: #ifdef ALL_METRICS
1344: DbgPrint("FullName = %s\n", (char *)pntfm + pntfm->loszFullName);
1345: DbgPrint("FontName = %s\n", (char *)pntfm + pntfm->loszFontName);
1346: DbgPrint("FamilyName = %s\n", (char *)pntfm + pntfm->loszFamilyName);
1347: #endif
1348:
1349: // deal with the soft font, if there is one.
1350:
1351: if (pPFA)
1352: {
1353: // skip over the DWORD count.
1354:
1355: pPFA += sizeof(DWORD);
1356: memcpy(pstr, pPFA, cbPFA);
1357: pstr += DWORDALIGN(cbPFA);
1358: }
1359:
1360: // fill in the rest of the IFIMETRICS.
1361:
1362: CompleteIFIMETRICS(pdata);
1363:
1364: pntfm->cjThis += pdata->pTmpIFI->cjThis;
1365:
1366: // copy the IFIMETRICS stucture to the NTFM.
1367:
1368: memcpy(pstr, (CHAR *)pdata->pTmpIFI, pdata->pTmpIFI->cjThis);
1369: }
1370:
1371:
1372: //--------------------------------------------------------------------------
1373: //
1374: // VOID InitIFIMETRICS(pdata)
1375: // PPARSEDATA pdata;
1376: //
1377: // This routine initializes the IFIMETRICS structure with default values.
1378: //
1379: // Returns:
1380: // This routine returns no value.
1381: //
1382: // History:
1383: // 25-Mar-1993 -by- Kent Settle (kentse)
1384: // Wrote it.
1385: //--------------------------------------------------------------------------
1386:
1387: VOID InitIFIMETRICS(pdata)
1388: PPARSEDATA pdata;
1389: {
1390: PIFIMETRICS pTmpIFI;
1391:
1392: pTmpIFI = pdata->pTmpIFI;
1393:
1394: // initialize the size of the structure
1395: // we will have to add the size of added strings later
1396:
1397: pTmpIFI->cjThis = DWORDALIGN(sizeof(IFIMETRICS));
1398:
1399: pTmpIFI->ulVersion = FM_VERSION_NUMBER;
1400:
1401: pTmpIFI->jWinCharSet = ANSI_CHARSET; // !!! i guess
1402: pTmpIFI->jWinPitchAndFamily = FF_DONTCARE | VARIABLE_PITCH;// !!! i Guess
1403: pTmpIFI->flInfo = FM_INFO_ARB_XFORMS |
1404: FM_INFO_NOT_CONTIGUOUS |
1405: FM_INFO_TECH_OUTLINE_NOT_TRUETYPE |
1406: FM_INFO_1BBP |
1407: FM_INFO_RIGHT_HANDED;
1408: pTmpIFI->fsType = FM_NO_EMBEDDING;
1409: pTmpIFI->fwdUnitsPerEm = 1000; // for PostScript fonts.
1410: pTmpIFI->fwdLowestPPEm = 1; // !!!I guess [kirko]
1411:
1412: pTmpIFI->fwdCapHeight = 0; //!!![kirko] Kent-can you do better?
1413: pTmpIFI->fwdSubscriptXSize = 300; // !!! a guess
1414: pTmpIFI->fwdSubscriptYSize = 300; // !!! a guess
1415: pTmpIFI->fwdSubscriptXOffset = 600; // !!! a guess
1416: pTmpIFI->fwdSubscriptYOffset = -100; // !!! a guess
1417: pTmpIFI->fwdSuperscriptXSize = 300; // !!! a guess
1418: pTmpIFI->fwdSuperscriptYSize = 300; // !!! a guess
1419: pTmpIFI->fwdSuperscriptXOffset = 600; // !!! a guess
1420: pTmpIFI->fwdSuperscriptYOffset = 300; // !!! a guess
1421:
1422: pTmpIFI->wcBreakChar = U_SPACE;
1423: WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&pTmpIFI->wcBreakChar, 1,
1424: (LPSTR)&pTmpIFI->chBreakChar, 1, NULL, NULL);
1425:
1426: pTmpIFI->ptlBaseline.x = 1;
1427: pTmpIFI->ptlBaseline.y = 0;
1428: pTmpIFI->ptlAspect.x = 1;
1429: pTmpIFI->ptlAspect.y = 1;
1430: pTmpIFI->achVendId[0] = 'U';
1431: pTmpIFI->achVendId[1] = 'n';
1432: pTmpIFI->achVendId[2] = 'k';
1433: pTmpIFI->achVendId[3] = 'n';
1434: pTmpIFI->ulPanoseCulture = FM_PANOSE_CULTURE_LATIN;
1435: pTmpIFI->panose.bFamilyType = PAN_ANY;
1436: pTmpIFI->panose.bSerifStyle = PAN_ANY;
1437: pTmpIFI->panose.bProportion = PAN_ANY;
1438: pTmpIFI->panose.bContrast = PAN_ANY;
1439: pTmpIFI->panose.bStrokeVariation= PAN_ANY;
1440: pTmpIFI->panose.bArmStyle = PAN_ANY;
1441: pTmpIFI->panose.bLetterform = PAN_ANY;
1442: pTmpIFI->panose.bMidline = PAN_ANY;
1443: pTmpIFI->panose.bXHeight = PAN_ANY;
1444: }
1445:
1446:
1447:
1448: //--------------------------------------------------------------------------
1449: //
1450: // VOID CompleteIFIMETRICS(pdata)
1451: // PPARSEDATA pdata;
1452: //
1453: // This routine fill in IFIMETRICS values using NTFM values.
1454: //
1455: // Returns:
1456: // This routine returns no value.
1457: //
1458: // History:
1459: // 25-Mar-1993 -by- Kent Settle (kentse)
1460: // Wrote it.
1461: //--------------------------------------------------------------------------
1462:
1463: VOID CompleteIFIMETRICS(pdata)
1464: PPARSEDATA pdata;
1465: {
1466: PIFIMETRICS pTmpIFI;
1467: WINFONTPAIR *pTable;
1468: BOOL bFound;
1469: PSTR pstr;
1470: PNTFM pntfm;
1471: LONG InternalLeading;
1472:
1473: // get local pointers.
1474:
1475: pntfm = pdata->pntfm;
1476: pTmpIFI = pdata->pTmpIFI;
1477:
1478: // for Win31 compatability - if there is a match in WinFontTable for
1479: // the Adobe facename, use the Windows Face Name for the IFIMETRICS
1480: // family name, otherwise, use the Adobe family name.
1481:
1482: //!!! use nls conversion for this.
1483:
1484: pTable = (WINFONTPAIR *)WinFontTable;
1485: bFound = FALSE;
1486:
1487: while(pTable->pstrAdobeFace)
1488: {
1489: if (!(strncmp(pTable->pstrAdobeFace,
1490: (CHAR *)pntfm + pntfm->loszFontName, MAX_FONT_NAME)))
1491: {
1492: pstr = pTable->pstrWinFace;
1493: bFound = TRUE;
1494: break;
1495: }
1496:
1497: pTable++;
1498: }
1499:
1500: if (!bFound)
1501: pstr = (CHAR *)pntfm + pntfm->loszFamilyName;
1502:
1503: // WIN31 COMPATABILITY! Check to see if this face name has aliases.
1504: // if it does, then we need to set the FM_INFO_FAMILY_EQUIV bit of
1505: // pTmpIFI->flInfo, and fill in an array of family aliases.
1506:
1507: GetFamilyAliases(pTmpIFI, pstr);
1508:
1509: // make the style name the same as the family name.
1510:
1511: pTmpIFI->dpwszStyleName = pTmpIFI->dpwszFamilyName;
1512:
1513: // get the face name for the font.
1514:
1515: pTmpIFI->dpwszFaceName = pTmpIFI->cjThis;
1516:
1517: strcpy2WChar((PWSZ)((char *)pTmpIFI + pTmpIFI->dpwszFaceName),
1518: (PSZ)((char *)pntfm + pntfm->loszFontName));
1519:
1520: // while we have the face name, lets fill in the windows compatability
1521: // stuff.
1522:
1523: if (!strcmp((char *)pntfm + pntfm->loszFontName, "Symbol"))
1524: pTmpIFI->jWinCharSet = SYMBOL_CHARSET;
1525: else if (!strcmp((char *)pntfm + pntfm->loszFontName, "ZapfDingbats"))
1526: pTmpIFI->jWinCharSet = OEM_CHARSET;
1527: else
1528: pTmpIFI->jWinCharSet = ANSI_CHARSET;
1529:
1530: pTmpIFI->chFirstChar = (BYTE)0x20;
1531: pTmpIFI->chLastChar = (BYTE)0xFE;
1532:
1533: pTmpIFI->cjThis += ((wcslen((PWSZ)((char *)pTmpIFI +
1534: pTmpIFI->dpwszFaceName)) + 1) * sizeof(WCHAR));
1535:
1536: // get the unique name for the font.
1537:
1538: pTmpIFI->dpwszUniqueName = pTmpIFI->cjThis;
1539: strcpy2WChar((PWSZ)((char *)pTmpIFI + pTmpIFI->dpwszUniqueName),
1540: (PSZ)((char *)pntfm + pntfm->loszFullName));
1541: pTmpIFI->cjThis += ((wcslen((PWSZ)((char *)pTmpIFI +
1542: pTmpIFI->dpwszUniqueName)) + 1) * sizeof(WCHAR));
1543:
1544: pTmpIFI->dpFontSim = 0;
1545:
1546: pTmpIFI->fwdWinAscender = (FWORD) pntfm->rcBBox.top;
1547: pTmpIFI->fwdWinDescender = -(FWORD) pntfm->rcBBox.bottom;
1548: pTmpIFI->fwdMacAscender = pTmpIFI->fwdWinAscender;
1549: pTmpIFI->fwdMacDescender = -pTmpIFI->fwdWinDescender;
1550:
1551: // as windows does, set total leading to 19.6% of EmHeight.
1552: // therefore, ExternalLeading = 196 - InternalLeading.
1553:
1554: InternalLeading = (pntfm->rcBBox.top - pntfm->rcBBox.bottom) -
1555: ADOBE_FONT_UNITS;
1556:
1557: if (InternalLeading < 0)
1558: InternalLeading = 0;
1559:
1560: pTmpIFI->fwdMacLineGap = 196 - InternalLeading;
1561: if (pTmpIFI->fwdMacLineGap < 0)
1562: pTmpIFI->fwdMacLineGap = 0;
1563:
1564: pTmpIFI->fwdTypoLineGap = 0;
1565: pTmpIFI->fwdTypoAscender = pTmpIFI->fwdWinAscender;
1566: pTmpIFI->fwdTypoDescender = pTmpIFI->fwdWinDescender;
1567: pTmpIFI->fwdStrikeoutPosition = pTmpIFI->fwdWinAscender / 2;
1568:
1569: // hardcoded from mapping.h values.
1570:
1571: if (!(strcmp((char *) pntfm + pntfm->loszFontName, "ZapfDingbats")))
1572: {
1573: pTmpIFI->wcDefaultChar = U_SPACE;
1574: pTmpIFI->chDefaultChar = (BYTE)0x20;
1575: }
1576: else if (!(strcmp((char *) pntfm + pntfm->loszFontName, "Symbol")))
1577: {
1578: pTmpIFI->wcDefaultChar = U_SYMBOL_BULLET;
1579: pTmpIFI->chDefaultChar = (BYTE)0xB7;
1580: }
1581:
1582: else
1583: {
1584: pTmpIFI->wcDefaultChar = U_BULLET;
1585: pTmpIFI->chDefaultChar = (BYTE)0x8C;
1586: }
1587:
1588: WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&pTmpIFI->wcDefaultChar, 1,
1589: (LPSTR)&pTmpIFI->chDefaultChar, 1, NULL, NULL);
1590:
1591: pTmpIFI->cKerningPairs = pntfm->cKernPairs;
1592:
1593: // set the average and maximum character widths for the font.
1594:
1595: SetWidths(pdata);
1596:
1597: // find the first and last characters for the given font.
1598:
1599: GetFirstLastChar(pdata);
1600: }
1601:
1602:
1603: //--------------------------------------------------------------------------
1604: //
1605: // VOID GetFamilyAliases(pifi, pstr)
1606: // IFIMETRICS *pifi;
1607: // PSTR pstr;
1608: //
1609: // This routine fill in the family name of the IFIMETRICS structure.
1610: //
1611: // Returns:
1612: // This routine returns no value.
1613: //
1614: // History:
1615: // 25-Mar-1993 -by- Kent Settle (kentse)
1616: // Wrote it.
1617: //--------------------------------------------------------------------------
1618:
1619: VOID GetFamilyAliases(pifi, pstr)
1620: IFIMETRICS *pifi;
1621: PSTR pstr;
1622: {
1623: PSTR *pTable;
1624: PWSTR pwstr;
1625: DWORD cb;
1626:
1627: // assume no alias table found.
1628:
1629: pTable = (PSTR *)(NULL);
1630:
1631: // this is an ugly hardcoded Win31 Hack that we need to be compatible
1632: // with since some stupid apps have hardcoded font names.
1633:
1634: if (!(strcmp(pstr, "Times")))
1635: pTable = TimesAlias;
1636:
1637: else if (!(strcmp(pstr, "Helvetica")))
1638: pTable = HelveticaAlias;
1639:
1640: else if (!(strcmp(pstr, "Courier")))
1641: pTable = CourierAlias;
1642:
1643: else if (!(strcmp(pstr, "Helvetica-Narrow")))
1644: pTable = HelveticaNarrowAlias;
1645:
1646: else if (!(strcmp(pstr, "Palatino")))
1647: pTable = PalatinoAlias;
1648:
1649: else if (!(strcmp(pstr, "Bookman")))
1650: pTable = BookmanAlias;
1651:
1652: else if (!(strcmp(pstr, "NewCenturySchlbk")))
1653: pTable = NewCenturySBAlias;
1654:
1655: else if (!(strcmp(pstr, "AvantGarde")))
1656: pTable = AvantGardeAlias;
1657:
1658: else if (!(strcmp(pstr, "ZapfChancery")))
1659: pTable = ZapfChanceryAlias;
1660:
1661: else if (!(strcmp(pstr, "ZapfDingbats")))
1662: pTable = ZapfDingbatsAlias;
1663:
1664: // get offset to family name from start of IFIMETRICS structure.
1665:
1666: pifi->dpwszFamilyName = pifi->cjThis;
1667: pwstr = (PWSZ)((char *)pifi + pifi->dpwszFamilyName);
1668:
1669: if (pTable)
1670: {
1671: // set the pifi->flInfo flag.
1672:
1673: pifi->flInfo |= FM_INFO_FAMILY_EQUIV;
1674:
1675: // now fill in the array of alias family names.
1676:
1677: while (*pTable)
1678: {
1679: strcpy2WChar(pwstr, (PSTR)*pTable++);
1680: cb = ((wcslen(pwstr) + 1) * sizeof(WCHAR));
1681: pifi->cjThis += cb;
1682: pwstr += (cb >> 1);
1683: }
1684:
1685: // add the extra NULL terminator to the end of the array.
1686:
1687: *pwstr = (WCHAR)'\0';
1688: pifi->cjThis += sizeof(WCHAR);
1689: }
1690: else
1691: {
1692: // fill in the single family name.
1693:
1694: strcpy2WChar(pwstr, pstr);
1695: pifi->cjThis += ((wcslen(pwstr) + 1) * sizeof(WCHAR));
1696: }
1697: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.