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

1912 lines
57 KiB

  1. /****************************Module*Header******************************\
  2. * Module Name: SOFTFONT.C
  3. *
  4. * Module Descripton:
  5. * Functions associated with PCL softfonts. These are fonts which are
  6. * downloaded into the printer. We read those files and interpre the
  7. * information contained therein. This happens during font installation
  8. * time, so that when in use, this information is in the format
  9. * required by the driver.
  10. *
  11. * Warnings:
  12. *
  13. * Issues:
  14. *
  15. * Copyright (c) 1996, 1997 Microsoft Corporation
  16. \***********************************************************************/
  17. #include "precomp.h"
  18. /*
  19. * A macro to swap the bytes around: we then get them in little endian
  20. * order from the big endian 68000 format.
  21. */
  22. #define SWAB( x ) ((WORD)(x) = (WORD)((((x) >> 8) & 0xff) | (((x) << 8) & 0xff00)))
  23. #define BBITS 8 /* Bits in a byte */
  24. /*
  25. * Define the values returned from the header checking code. The
  26. * function is called to see what is next in the file, and so we
  27. * can determine that the file is in an order we understand.
  28. */
  29. #define TYPE_INDEX 0 /* Character index record follows */
  30. #define TYPE_HEADER 1 /* Character header */
  31. #define TYPE_CONT 2 /* Continuation record */
  32. #define TYPE_INVALID 3 /* Unexpected sequence */
  33. /*
  34. * The structure and data for matching symbol sets with translation tables.
  35. */
  36. typedef struct
  37. {
  38. WORD wSymSet; /* Symbol set encoded in file */
  39. short sCTT; /* Translation table index */
  40. } CTT_MAP;
  41. /*
  42. * Note about this table: we do not include the generic7 ctt, this simply
  43. * maps glyphs 128 - 255 to 0x7f. Since we only use the glyphs available
  44. * in the font, and these we discover from the file, we have no need of
  45. * this type since we will map such chars because of the wcLastChar in
  46. * the IFIMETRICS!
  47. */
  48. static const CTT_MAP CttMap[] =
  49. {
  50. { 277, 2 }, /* Roman 8 */
  51. { 269, 4 }, /* Math 8 */
  52. { 21, 5 }, /* US ASCII */
  53. { 14, 19 }, /* ECMA-94 */
  54. { 369, 20 }, /* Z1A - variety of ECMA-94, ss = 11Q */
  55. };
  56. #define NUM_CTTMAP (sizeof( CttMap ) / sizeof( CttMap[ 0 ] ))
  57. /*
  58. * The bClass field mapping table: maps from values in bClass parameter
  59. * to bits in the dwSelBits field.
  60. */
  61. static const DWORD dwClassMap[] =
  62. {
  63. FDH_BITMAP, /* A bitmap font */
  64. FDH_COMPRESSED, /* A compressed bitmap */
  65. FDH_CONTOUR, /* A contour font (Intellifont special) */
  66. FDH_CONTOUR, /* A compressed contour font: presume as above */
  67. };
  68. #define MAX_CLASS_MAP (sizeof( dwClassMap ) / sizeof( dwClassMap[ 0 ] ))
  69. /*
  70. * Typeface to name index. Comes from the LaserJet III technical manual.
  71. */
  72. static const WCHAR *pwcName[] =
  73. {
  74. L"Line Printer",
  75. L"Pica",
  76. L"Elite",
  77. L"Courier",
  78. L"Helv" ,
  79. L"TmsRmn",
  80. L"Letter Gothic",
  81. L"Script",
  82. L"Prestige",
  83. L"Caslon",
  84. L"Orator",
  85. L"Presentations",
  86. L"Helv Cond",
  87. L"Serifa",
  88. L"Futura",
  89. L"Palatino",
  90. L"ITC Souvenir",
  91. L"Optima",
  92. L"Garamond",
  93. L"Cooper Black",
  94. L"Coronet Bold",
  95. L"Broadway",
  96. L"Bauer Bodoni Black Condensed",
  97. L"Century Schoolbook",
  98. L"University Roman",
  99. L"Helvetica Outline",
  100. L"Futura Condensed",
  101. L"ITC Korinna",
  102. L"Naskh",
  103. L"Cloister Black",
  104. L"ITC Galliard",
  105. L"ITC Avant Garde Gothic",
  106. L"Brush",
  107. L"Blippo",
  108. L"Hobo",
  109. L"Windsor",
  110. L"Helvetica Compressed",
  111. L"Helvetica Extra Compressed",
  112. L"Peignot",
  113. L"Baskerville",
  114. L"ITC Garamond Condensed",
  115. L"Trade Gothic",
  116. L"Goudy Old Style",
  117. L"ITC Zapf Chancery",
  118. L"Clarendon",
  119. L"ITC Zapf Dingbats",
  120. L"Cooper",
  121. L"ITC Bookman",
  122. L"Stick",
  123. L"HP-GL Drafting",
  124. L"HP-GL Spline",
  125. L"Gill Sans",
  126. L"Univers",
  127. L"Bodoni",
  128. L"Rockwell",
  129. L"Mellior",
  130. L"ITC Tiffany",
  131. L"ITC Clearface",
  132. L"Amelia",
  133. L"Park Avenue",
  134. L"Handel Gothic",
  135. L"Dom Casual",
  136. L"ITC Benguiat",
  137. L"ITC Cheltenham",
  138. L"Century Expanded",
  139. L"Franklin Gothic",
  140. L"Franklin Gothic Expressed",
  141. L"Frankiln Gothic Extra Condensed",
  142. L"Plantin",
  143. L"Trump Mediaeval",
  144. L"Futura Black",
  145. };
  146. #define NUM_TYPEFACE (sizeof( pwcName ) / sizeof( pwcName[ 0 ] ))
  147. BOOL bWrite( HANDLE, void *, int );
  148. /*
  149. * Local function prototypes.
  150. */
  151. BYTE *pbReadSFH( BYTE *, SF_HEADER * );
  152. BYTE *pbReadIndex( BYTE *, int * );
  153. BYTE *pbReadCHH( BYTE *, CH_HEADER *, BOOL );
  154. int iNextType( BYTE * );
  155. PWSTR strcpy2WChar( PWSTR, LPSTR );
  156. DWORD FICopy(HANDLE, HANDLE);
  157. int iWriteFDH( HANDLE, FI_DATA * );
  158. BOOL bWrite( HANDLE, void *, int );
  159. /* SoftFont to NT conversion functions */
  160. IFIMETRICS *SfhToIFI( SF_HEADER *, HANDLE, PWSTR );
  161. #if PRINT_INFO
  162. /*
  163. * Print out the IFIMETRICS results!
  164. */
  165. typedef VOID (*VPRINT) (char*,...);
  166. VOID
  167. vPrintIFIMETRICS(
  168. IFIMETRICS *pifi,
  169. VPRINT vPrint
  170. );
  171. #endif
  172. /****************************** Function Header ***************************
  173. * bSFontToFontMap
  174. * Read in a PCL softfont file and generate all the fontmap details
  175. * The file contains a header with general font information, followed
  176. * by an array of entries, one per glyph, each of which contains a
  177. * header with per glyph data such as char width.
  178. *
  179. * RETURNS:
  180. * TRUE/FALSE, TRUE for success.
  181. *
  182. * HISTORY:
  183. * 09:54 on Wed 19 Feb 1992 -by- Lindsay Harris [lindsayh]
  184. * First incarnation.
  185. *
  186. ***************************************************************************/
  187. BOOL
  188. bSFontToFIData( pFIDat, hheap, pbFile, dwSize )
  189. FI_DATA *pFIDat; /* FI_DATA with all the important stuff! */
  190. HANDLE hheap; /* For storage allocation */
  191. BYTE *pbFile; /* Mmemory mapped file with the softfont */
  192. DWORD dwSize; /* Number of bytes in the file */
  193. {
  194. int iVal; /* Character code from file */
  195. int iI; /* Loop index */
  196. int iType; /* Record type that we have */
  197. int iMaxWidth; /* Widest glyph we found */
  198. int iWidth; /* For calculating the average width */
  199. int cGlyphs; /* For the above */
  200. SF_HEADER sfh; /* Header information */
  201. CH_HEADER chh; /* Per glyph information */
  202. BYTE *pbEnd;
  203. WCHAR *pwch; /* Points to font name to display */
  204. IFIMETRICS *pIFI;
  205. WCHAR awchTemp[ 128 ]; /* For building up the name to show user */
  206. pbEnd = pbFile + dwSize; /* Last byte + 1 */
  207. ZeroMemory( pFIDat, sizeof( FI_DATA ) );
  208. if( (pbFile = pbReadSFH( pbFile, &sfh )) == 0 )
  209. return FALSE; /* No go - presume wrong format */
  210. pFIDat->dsIFIMet.pvData = pIFI = SfhToIFI( &sfh, hheap, L"PCL_SF" );
  211. if( pIFI == 0 )
  212. return FALSE;
  213. pFIDat->dsIFIMet.cBytes = pIFI->cjThis;
  214. if( sfh.bSpacing )
  215. {
  216. /*
  217. * Allocate space for the width table, if there is to be one.
  218. * Only proportionally spaced fonts have this luxury!
  219. */
  220. iI = (pIFI->chLastChar - pIFI->chFirstChar + 1) * sizeof( short );
  221. if( !(pFIDat->dsWidthTab.pvData = (short *)HEAPALLOC( hheap, iI )) )
  222. {
  223. HeapFree( hheap, 0, (LPSTR)pIFI );
  224. return FALSE;
  225. }
  226. pFIDat->dsWidthTab.cBytes = iI;
  227. ZeroMemory( pFIDat->dsWidthTab.pvData, iI ); /* Zero the width table */
  228. }
  229. /* Else clause not required, since the structure is initialised to 0 */
  230. /*
  231. * Generate an ID string for this font. The ID string is displayed
  232. * in UI components, so we use the font name + point size. The + 15 s
  233. * allows for the string "%d Pt" at the end of the name.
  234. */
  235. /*
  236. * If the typeface field gives us a name, then we should display that
  237. * one to the user. We check to see if the value is within range,
  238. * and use the pointer value if so. Note that this pointer is NULL
  239. * for an unknown name, so we need to check that we end up pointing
  240. * at something!
  241. */
  242. pwch = NULL; /* Means have not found one, yet */
  243. if( sfh.bTypeface >= 0 && sfh.bTypeface < NUM_TYPEFACE )
  244. {
  245. /* We have the "proper" name for this one! */
  246. (const WCHAR *)pwch = pwcName[ sfh.bTypeface ];
  247. }
  248. if( pwch == NULL )
  249. {
  250. /* Use the name supplied */
  251. pwch = (WCHAR *)((BYTE *)pIFI + pIFI->dpwszFaceName);
  252. }
  253. else
  254. {
  255. /* Use the "standard" name we found above, and add StyleName */
  256. StringCchCopyW(awchTemp, CCHOF(awchTemp), pwch); /* Standard name */
  257. pwch = (WCHAR *)((BYTE *)pIFI + pIFI->dpwszStyleName);
  258. if( *pwch )
  259. {
  260. StringCchCatW(awchTemp, CCHOF(awchTemp), L" ");
  261. StringCchCatW(awchTemp, CCHOF(awchTemp), pwch);
  262. }
  263. pwch = awchTemp;
  264. }
  265. /* Allocate the storage we need */
  266. iI = (15 + wcslen( pwch )) * sizeof( WCHAR );
  267. if( !(pFIDat->dsIdentStr.pvData = HEAPALLOC( hheap, iI )) )
  268. {
  269. HeapFree( hheap, 0, (LPSTR)pIFI );
  270. HeapFree( hheap, 0, pFIDat->dsWidthTab.pvData );
  271. return FALSE;
  272. }
  273. pFIDat->dsIdentStr.cBytes = iI;
  274. /* Calculate point size, to nearest quarter point */
  275. iI = 25 * (((pIFI->fwdWinAscender + pIFI->fwdWinDescender) * 72 * 4 + 150)
  276. / 300);
  277. StringCchPrintfW(pFIDat->dsIdentStr.pvData,
  278. pFIDat->dsIdentStr.cBytes / sizeof(WCHAR),
  279. L"%ws %d.%0d Pt", pwch, iI / 100, iI % 100);
  280. /*
  281. * Set the landscape/portrait selection bits.
  282. */
  283. pFIDat->dwSelBits |= sfh.bOrientation ? FDH_LANDSCAPE : FDH_PORTRAIT;
  284. /*
  285. * Loop through the remainder of the file processing whatever
  286. * glyphs we discover. Process means read the header to determine
  287. * widths etc.
  288. */
  289. iMaxWidth = 0;
  290. iWidth = 0;
  291. cGlyphs = 0;
  292. while( pbFile < pbEnd )
  293. {
  294. /* First step is to find the character index for this glyph */
  295. short sWidth; /* Width in integral pels */
  296. iType = iNextType( pbFile );
  297. if( iType == TYPE_INVALID )
  298. return FALSE; /* Cannot use this one */
  299. if( iType == TYPE_INDEX )
  300. {
  301. if( !(pbFile = pbReadIndex( pbFile, &iVal )) )
  302. return FALSE;
  303. if( iVal < 0 )
  304. break; /* Illegal value: assume EOF */
  305. continue; /* Onwards & upwards */
  306. }
  307. if( !(pbFile = pbReadCHH( pbFile, &chh, iType == TYPE_CONT )) )
  308. return FALSE;
  309. if( iType == TYPE_CONT )
  310. continue; /* Nothing else to do! */
  311. if( chh.bFormat == CH_FM_RASTER )
  312. pFIDat->dwSelBits |= FDH_BITMAP;
  313. else
  314. {
  315. if( chh.bFormat == CH_FM_SCALE )
  316. pFIDat->dwSelBits |= FDH_SCALABLE;
  317. }
  318. if( chh.bClass >= 1 && chh.bClass <= MAX_CLASS_MAP )
  319. {
  320. pFIDat->dwSelBits |= dwClassMap[ chh.bClass - 1 ];
  321. }
  322. else
  323. {
  324. /*
  325. * Not a format we understand - yet!
  326. */
  327. #if PRINT_INFO
  328. DbgPrint( "...Not our format: Format = %d, Class = %d\n",
  329. chh.bFormat, chh.bClass );
  330. #endif
  331. HeapFree( hheap, 0, (LPSTR)pIFI );
  332. return FALSE;
  333. }
  334. /*
  335. * If this is a valid glyph, then we may want to record its
  336. * width (if proportionally spaced) and we are also interested
  337. * in some of the cell dimensions too!
  338. */
  339. if( iVal >= (int)pIFI->chFirstChar && iVal <= (int)pIFI->chLastChar &&
  340. (sfh.bFontType != PCL_FT_8LIM || (iVal <= 127 || iVal >= 160)) )
  341. {
  342. /* Is valid for this font, so process it. */
  343. sWidth = (chh.wDeltaX + 2) / 4; /* PCL in quarter dots */
  344. if( pFIDat->dsWidthTab.pvData )
  345. *((short *)pFIDat->dsWidthTab.pvData + iVal - pIFI->chFirstChar) =
  346. sWidth;
  347. if( sWidth > (WORD)iMaxWidth )
  348. iMaxWidth = sWidth; /* Bigger & better */
  349. /* Accumulate the averages */
  350. iWidth += sWidth;
  351. cGlyphs++;
  352. }
  353. }
  354. /*
  355. * Most softfonts do not include the space char! SO, we check to
  356. * see if it's width is zero. If so, we use the wPitch field to
  357. * calculate the HMI (horizontal motion index) and hence the width
  358. * of the space char.
  359. */
  360. iVal = ' ' - pIFI->chFirstChar; /* Offset of space in width array */
  361. if( pFIDat->dsWidthTab.pvData &&
  362. *((short *)pFIDat->dsWidthTab.pvData + iVal) == 0 )
  363. {
  364. /*
  365. * Zero width space, so fill it in now. The HMI is determined
  366. * from the pitch in the font header, so we use that to
  367. * evaluate the size. The pitch is in 0.25 dot units, so
  368. * round it to the nearest numbr of dots.
  369. */
  370. *((short *)pFIDat->dsWidthTab.pvData + iVal) = (short)((sfh.wPitch + 2) / 4);
  371. cGlyphs++;
  372. iWidth += (sfh.wPitch + 2) / 4;
  373. }
  374. /*
  375. * A slight amendment to the IFIMETRICS. We calculate the average
  376. * width, given the character data we have read!
  377. */
  378. if( cGlyphs > 0 )
  379. {
  380. pIFI->fwdAveCharWidth = (iWidth + cGlyphs / 2) / cGlyphs;
  381. }
  382. if( iMaxWidth > 0 )
  383. {
  384. pIFI->fwdMaxCharInc = (short)iMaxWidth;
  385. }
  386. #if PRINT_INFO
  387. /*
  388. * Print out the IFIMETRICS for this font - debugging is easier!
  389. */
  390. vPrintIFIMETRICS( pIFI, (VPRINT)DbgPrint );
  391. #endif
  392. /*
  393. * Set up the relevant translation table. This is based on the
  394. * symbol set of the font. We use a lookup table to scan and match
  395. * the value from those we have. If outside the range, set to no
  396. * translation. Not much choice here.
  397. */
  398. for( iI = 0; iI < NUM_CTTMAP; ++iI )
  399. {
  400. if( CttMap[ iI ].wSymSet == sfh.wSymSet )
  401. {
  402. /* Bingo! */
  403. pFIDat->dsCTT.cBytes = CttMap[ iI ].sCTT;
  404. break;
  405. }
  406. }
  407. /* The following are GROSS assumptions!! */
  408. pFIDat->wXRes = 300;
  409. pFIDat->wYRes = 300;
  410. return TRUE;
  411. }
  412. /***************************** Function Header *****************************
  413. * pbReadSFH
  414. * Read a PCL SoftFont header and fill in the structure passed to us.
  415. * The file is presumed mapped into memory, and that it's address
  416. * is passed to us. We return the address of the first byte past
  417. * the header we process.
  418. *
  419. * RETURNS:
  420. * Address of next location if OK, else 0 for failure (bad format).
  421. *
  422. * HISTORY:
  423. * 11:01 on Wed 19 Feb 1992 -by- Lindsay Harris [lindsayh]
  424. * Numero uno.
  425. *
  426. ****************************************************************************/
  427. BYTE *
  428. pbReadSFH( pbFile, psfh )
  429. BYTE *pbFile; /* THE file */
  430. SF_HEADER *psfh; /* Where the data goes */
  431. {
  432. int iSize; /* Determine header size */
  433. /*
  434. * The file should start off with \033)s...W where ... is a decimal
  435. * ASCII count of the number of bytes following. This may be larger
  436. * than the size of the SF_HEADER.
  437. */
  438. if( *pbFile++ != '\033' || *pbFile++ != ')' || *pbFile++ != 's' )
  439. {
  440. #if PRINT_INFO
  441. DbgPrint( "Rasdd!pbReadSFH: bad file - first 2 bytes\n" );
  442. #endif
  443. return 0;
  444. }
  445. /* Now have a decimal byte count - convert it */
  446. iSize = 0;
  447. while( *pbFile >= '0' && *pbFile <= '9' )
  448. iSize = iSize * 10 + *pbFile++ - '0';
  449. if( *pbFile++ != 'W' )
  450. {
  451. #if PRINT_INFO
  452. DbgPrint( "Rasdd!pbReadSFH: bad file: W missing\n" );
  453. #endif
  454. return 0;
  455. }
  456. if( iSize < sizeof( SF_HEADER ) )
  457. {
  458. #if PRINT_INFO
  459. DbgPrint( "Rasdd!pbReadSFH: Header size too small: %d vs %d\n", iSize,
  460. sizeof( SF_HEADER ) );
  461. #endif
  462. return 0;
  463. }
  464. /*
  465. * Now COPY the data into the structure passed in. This IS NECESSARY
  466. * as the file data may not be aligned - the file contains no holes,
  467. * so we may have data with an incorrect offset.
  468. */
  469. CopyMemory( psfh, pbFile, sizeof( SF_HEADER ) );
  470. /*
  471. * The big endian/little endian switch.
  472. */
  473. SWAB( psfh->wSize );
  474. SWAB( psfh->wBaseline );
  475. SWAB( psfh->wCellWide );
  476. SWAB( psfh->wCellHeight );
  477. SWAB( psfh->wSymSet );
  478. SWAB( psfh->wPitch );
  479. SWAB( psfh->wHeight );
  480. SWAB( psfh->wXHeight );
  481. SWAB( psfh->wTextHeight );
  482. SWAB( psfh->wTextWidth );
  483. return pbFile + iSize; /* Next part of the operation */
  484. }
  485. /**************************** Function Header *******************************
  486. * iNextType
  487. * Read ahead to see what sort of record appears next.
  488. *
  489. * RETURNS:
  490. * The type of record found.
  491. *
  492. * HISTORY:
  493. * 15:17 on Tue 03 Mar 1992 -by- Lindsay Harris [lindsayh]
  494. * First version.
  495. *
  496. ****************************************************************************/
  497. int
  498. iNextType( pbFile )
  499. BYTE *pbFile;
  500. {
  501. /*
  502. * First character MUST be an escape!
  503. */
  504. CH_HEADER *pCH; /* Character header: for continuation */
  505. if( *pbFile++ != '\033' )
  506. return TYPE_INVALID; /* No go */
  507. /*
  508. * If the next two bytes are "*c", we have a character code command.
  509. * Otherwise, we can expect a "(s", which indicates a font
  510. * descriptor command.
  511. */
  512. if( *pbFile == '*' && *(pbFile + 1) == 'c' )
  513. {
  514. /*
  515. * Verifu that this really is an index record: we should see
  516. * a numeric string and then a 'E'.
  517. */
  518. pbFile += 2;
  519. while( *pbFile >= '0' && *pbFile <= '9' )
  520. ++pbFile;
  521. return *pbFile == 'E' ? TYPE_INDEX : TYPE_INVALID;
  522. }
  523. if( *pbFile != '(' || *(pbFile + 1) != 's' )
  524. return TYPE_INVALID;
  525. /*
  526. * Must now check to see if this is a continuation record or a
  527. * new record. There is a byte in the header to indicate which
  528. * it is. But first skip the byte count and trailing W.
  529. */
  530. pbFile += 2;
  531. while( *pbFile >= '0' && *pbFile <= '9' )
  532. pbFile++;
  533. if( *pbFile != 'W' )
  534. return TYPE_INVALID;
  535. pCH = (CH_HEADER *)(pbFile + 1);
  536. /*
  537. * Note that alignment is not a problem in the following
  538. * since we are dealing with a byte quantity.
  539. */
  540. return pCH->bContinuation ? TYPE_CONT : TYPE_HEADER;
  541. }
  542. /**************************** Function Header *******************************
  543. * pbReadIndex
  544. * Reads data from the pointer passed to us, and attempts to interpret
  545. * it as a PCL Character Code escape sequence.
  546. *
  547. * RETURNS:
  548. * Pointer to byte past command, else 0 for failure.
  549. *
  550. * HISTORY:
  551. * 16:21 on Wed 19 Feb 1992 -by- Lindsay Harris [lindsayh]
  552. * Number one
  553. *
  554. *****************************************************************************/
  555. BYTE *
  556. pbReadIndex( pbFile, piCode )
  557. BYTE *pbFile; /* Where to start looking */
  558. int *piCode; /* Where the result is placed */
  559. {
  560. /*
  561. * Command sequence is "\033*c..E" - where ... is the ASCII decimal
  562. * representation of the character code for this glyph. That is
  563. * the value returned in *piCode.
  564. */
  565. int iVal;
  566. if( *pbFile == '\0' )
  567. {
  568. /* EOF is not really an error: return an OK value and -1 index */
  569. *piCode = -1;
  570. return pbFile; /* Presume EOF */
  571. }
  572. if( *pbFile++ != '\033' || *pbFile++ != '*' || *pbFile++ != 'c' )
  573. {
  574. #if PRINT_INFO
  575. DbgPrint( "Rasdd!pbReadIndex: invalid character code\n" );
  576. #endif
  577. return 0;
  578. }
  579. iVal = 0;
  580. while( *pbFile >= '0' && *pbFile <= '9' )
  581. iVal = iVal * 10 + *pbFile++ - '0';
  582. *piCode = iVal;
  583. if( *pbFile++ != 'E' )
  584. {
  585. #if PRINT_INFO
  586. DbgPrint( "Rasdd!pbReadIndex: Missing 'E' in character code escape\n" );
  587. #endif
  588. return 0;
  589. }
  590. return pbFile;
  591. }
  592. /**************************** Function Header *******************************
  593. * pbReadCHH
  594. * Function to read the Character Header at the memory location
  595. * pointed to by by pbFile, return a filled in CH_HEADER structure,
  596. * and advance the file address to the next header.
  597. *
  598. * RETURNS:
  599. * Address of first byte past where we finish; else 0 for failure.
  600. *
  601. * HISTORY:
  602. * 11:23 on Thu 20 Feb 1992 -by- Lindsay Harris [lindsayh]
  603. * Gotta start somewhere.
  604. *
  605. ****************************************************************************/
  606. BYTE *
  607. pbReadCHH( pbFile, pchh, bCont )
  608. BYTE *pbFile; /* File mapped into memory */
  609. CH_HEADER *pchh; /* Structure to fill in */
  610. BOOL bCont; /* TRUE if this is a continuation record */
  611. {
  612. int iSize; /* Bytes of data to skip over */
  613. /*
  614. * The entry starts with a string "\033(s..W" where .. is the ASCII
  615. * decimal count of the number of bytes following the W. Since this
  616. * includes the download stuff, we would expect more than the size
  617. * of the CH_HEADER.
  618. */
  619. if( *pbFile++ != '\033' || *pbFile++ != '(' || *pbFile++ != 's' )
  620. {
  621. #if PRINT_INFO
  622. DbgPrint( "Rasdd!pbReadCHH: bad format, first 3 bytes\n" );
  623. #endif
  624. return 0;
  625. }
  626. iSize = 0;
  627. while( *pbFile >= '0' && *pbFile <= '9' )
  628. iSize = iSize * 10 + *pbFile++ - '0';
  629. if( iSize < sizeof( CH_HEADER ) )
  630. {
  631. #if PRINT_INFO
  632. DbgPrint( "Rasdd!pbReadCHH: size field (%ld) < header size\n", iSize );
  633. #endif
  634. return 0;
  635. }
  636. if( *pbFile++ != 'W' )
  637. {
  638. #if PRINT_INFO
  639. DbgPrint( "Rasdd!pbReadCHH: invalid escape sequence\n" );
  640. #endif
  641. return 0;
  642. }
  643. /*
  644. * If this is a continuation record, there is no more to do but
  645. * return the address past this record.
  646. */
  647. if( bCont )
  648. return pbFile + iSize;
  649. /* Copy the data to the structure - may not be aligned in the file */
  650. CopyMemory( pchh, pbFile, sizeof( CH_HEADER ) );
  651. pbFile += iSize; /* End of this record */
  652. SWAB( pchh->sLOff );
  653. SWAB( pchh->sTOff );
  654. SWAB( pchh->wChWidth );
  655. SWAB( pchh->wChHeight );
  656. SWAB( pchh->wDeltaX );
  657. /*
  658. * If this glyph is in landscape, we need to swap some data
  659. * around, since the data format is designed for the printer's
  660. * convenience, and not ours!
  661. */
  662. if( pchh->bOrientation )
  663. {
  664. /* Landscape, so swap the entries around */
  665. short sSwap;
  666. WORD wSwap;
  667. /* Left & Top offsets: see pages 10-19, 10-20 of LJ II manual */
  668. sSwap = pchh->sTOff;
  669. pchh->sTOff = -pchh->sLOff;
  670. pchh->sLOff = (short)(sSwap + 1 - pchh->wChHeight);
  671. /* Delta X remains the same */
  672. /* Height and Width are switched around */
  673. wSwap = pchh->wChWidth;
  674. pchh->wChWidth = pchh->wChHeight;
  675. pchh->wChHeight = wSwap;
  676. }
  677. /*
  678. * pbFile is pointing at the correct location when we reach here.
  679. */
  680. return pbFile;
  681. }
  682. /*************************** Function Header *******************************
  683. * SfhToIFI
  684. * Generate IFIMETRICS data from the PCL softfont header. There are
  685. * some fields we are unable to evaluate, e.g. first/last char,
  686. * since these are obtained from the file.
  687. *
  688. * RETURNS:
  689. * Pointer to IFIMETRICS, allocated from heap; 0 on error.
  690. *
  691. * HISTORY:
  692. * 13:57 on Fri 18 Jun 1993 -by- Lindsay Harris [lindsayh]
  693. * Assorted bug fixing for that infamous tax program
  694. *
  695. * 16:03 on Thu 11 Mar 1993 -by- Lindsay Harris [lindsayh]
  696. * Correct conversion to Unicode - perhaps??
  697. *
  698. * 16:45 on Wed 03 Mar 1993 -by- Lindsay Harris [lindsayh]
  699. * Update to libc wcs functions rather than printers\lib versions.
  700. *
  701. * 14:19 on Thu 20 Feb 1992 -by- Lindsay Harris [lindsayh]
  702. * Fresh off the presses.
  703. *
  704. ****************************************************************************/
  705. IFIMETRICS *
  706. SfhToIFI( psfh, hheap, pwstrUniqNm )
  707. SF_HEADER *psfh; /* The data source */
  708. HANDLE hheap; /* Source of memory */
  709. PWSTR pwstrUniqNm; /* Unique name for IFIMETRICS */
  710. {
  711. /*
  712. * Several hard parts: the hardest are the panose numbers.
  713. * It is messy, though not difficult to generate the variations
  714. * of the font name.
  715. */
  716. register IFIMETRICS *pIFI;
  717. int iI; /* Loop index, of course! */
  718. int cWC; /* Number of WCHARS to add */
  719. int cbAlloc; /* Number of bytes to allocate */
  720. int cChars; /* Number chars to convert to Unicode */
  721. WCHAR *pwch, *pwchEnd; /* For string manipulations */
  722. WCHAR *pwchTypeface; /* Name from typeface value */
  723. WCHAR *pwchGeneric; /* Generic windows name */
  724. char ajName[ SFH_NM_SZ + 1 ]; /* Guaranteed null terminated name */
  725. WCHAR awcName[ SFH_NM_SZ + 1 ]; /* Wide version of the above */
  726. /* NOTE: FOLLOWING 2 MUST BE 256 ENTRIES LONG!!! */
  727. WCHAR awcAttrib[ 256 ]; /* For generating attributes */
  728. BYTE ajANSI[ 256 ]; /* ANSI equivalent of above */
  729. /*
  730. * First massage the font name. We need to null terminate it, since
  731. * the softfont data need not be. And we also need to truncate any
  732. * trailing blanks.
  733. *
  734. * But we also calculate all the aliases we are going to add. Apart
  735. * from the name in the file (which may not be useful), there is
  736. * the name based on the bTypeface field in the header, AND there
  737. * is the generic (SWISS/MODERN/ROMAN) type based on the font
  738. * characteristics.
  739. *
  740. * NOTE: change of plans here: we only use the font name from the
  741. * file if the header's typeface index is for a font that we don't
  742. * know about. This causes the least problems for GDI and it's
  743. * font mapper.
  744. */
  745. if( psfh->bTypeface >= 0 && psfh->bTypeface < NUM_TYPEFACE )
  746. {
  747. (const WCHAR *)pwchTypeface = pwcName[ psfh->bTypeface ];
  748. }
  749. else
  750. {
  751. FillMemory( ajName, SFH_NM_SZ, ' ' );
  752. strncpy( ajName, psfh->chName, SFH_NM_SZ );
  753. ajName[ SFH_NM_SZ ] = '\0';
  754. for( iI = strlen( ajName ) - 1; iI >= 0; --iI )
  755. {
  756. if( ajName[ iI ] != ' ' )
  757. {
  758. ajName[ iI + 1 ] = '\0'; /* Must be the end */
  759. break;
  760. }
  761. }
  762. strcpy2WChar( awcName, ajName ); /* Base name */
  763. pwchTypeface = awcName; /* For later use */
  764. }
  765. /*
  766. * The generic name is based on 2 facts: fixed or variable pitch,
  767. * and variable pitch switches between serifed and non-serifed fonts.
  768. */
  769. if( psfh->bSpacing )
  770. {
  771. /*
  772. * Proportional font, so we need to look for serifs.
  773. */
  774. if( (psfh->bSerifStyle >= 2 && psfh->bSerifStyle <= 8) ||
  775. (psfh->bSerifStyle & 0xc0) == 0x80 )
  776. {
  777. /* A font with serifs, so set this as a Roman font */
  778. pwchGeneric = L"Roman";
  779. }
  780. else
  781. pwchGeneric = L"Swiss"; /* No serifs */
  782. }
  783. else
  784. pwchGeneric = L"Modern";
  785. /*
  786. * Produce the desired attributes: Italic, Bold, Light etc.
  787. * This is largely guesswork, and there should be a better method.
  788. */
  789. awcAttrib[ 0 ] = L'\0';
  790. awcAttrib[ 1 ] = L'\0'; /* Write out an empty string */
  791. if( psfh->bStyle ) /* 0 normal, 1 italic */
  792. StringCchCatW(awcAttrib, CCHOF(awcAttrib), L" Italic");
  793. if( psfh->sbStrokeW >= PCL_BOLD ) /* As per HP spec */
  794. StringCchCatW(awcAttrib, CCHOF(awcAttrib), L" Bold");
  795. else
  796. {
  797. if( psfh->sbStrokeW <= PCL_LIGHT )
  798. StringCchCatW(awcAttrib, CCHOF(awcAttrib), L" Light");
  799. }
  800. /*
  801. * First step is to determine the length of the WCHAR strings
  802. * that are placed at the end of the IFIMETRICS, since we need
  803. * to include these in our storage allocation.
  804. *
  805. * The attribute string appears in 3 entries of IFIMETRICS, so
  806. * calculate how much storage this will take. NOTE THAT THE LEADING
  807. * CHAR IN awcAttrib is NOT placed in the style name field, so we
  808. * subtract one in the following formula to account for this.
  809. */
  810. cWC = 3 * wcslen( pwchTypeface ) + /* Base name */
  811. wcslen( pwchGeneric ) + /* In the alias section */
  812. 3 * wcslen( awcAttrib ) + /* In most places */
  813. wcslen( pwstrUniqNm ) + 1 + /* Printer name plus space */
  814. 6; /* Terminating nulls */
  815. cbAlloc = sizeof( IFIMETRICS ) + sizeof( WCHAR ) * cWC;
  816. pIFI = (IFIMETRICS *)HEAPALLOC( hheap, cbAlloc );
  817. if( !pIFI )
  818. return NULL; /* Not very nice! */
  819. ZeroMemory( pIFI, cbAlloc ); /* In case we miss something */
  820. pIFI->cjThis = cbAlloc; /* Everything */
  821. pIFI->cjIfiExtra = 0;
  822. /* The family name: straight from the FaceName - no choice?? */
  823. pwch = (WCHAR *)(pIFI + 1); /* At the end of the structure */
  824. pIFI->dpwszFamilyName = (PTRDIFF)((BYTE *)pwch - (BYTE *)pIFI);
  825. pwchEnd = pwch + cWC;
  826. StringCchCopyW(pwch, pwchEnd - pwch, pwchTypeface); /* Base name */
  827. /* Add the aliases too! */
  828. pwch += wcslen( pwch ) + 1; /* After the nul */
  829. StringCchCopyW(pwch, pwchEnd - pwch, pwchGeneric); /* Windows generic */
  830. pwch += wcslen( pwch ) + 2; /* Skip what we just put in */
  831. /* Now the face name: we add bold, italic etc to family name */
  832. pIFI->dpwszFaceName = (PTRDIFF)((BYTE *)pwch - (BYTE *)pIFI);
  833. StringCchCopyW(pwch, pwchEnd - pwch, pwchTypeface); /* Base name */
  834. StringCchCatW(pwch, pwchEnd - pwch, awcAttrib);
  835. /* Now the unique name - well, sort of, anyway */
  836. pwch += wcslen( pwch ) + 1; /* Skip what we just put in */
  837. pIFI->dpwszUniqueName = (PTRDIFF)((BYTE *)pwch - (BYTE *)pIFI);
  838. StringCchCopyW(pwch, pwchEnd - pwch, pwstrUniqNm);
  839. StringCchCatW(pwch, pwchEnd - pwch, L" ");
  840. StringCchCatW(pwch, pwchEnd - pwch, (PWSTR)((BYTE *)pIFI + pIFI->dpwszFaceName));
  841. /* Onto the attributes only component */
  842. pwch += wcslen( pwch ) + 1; /* Skip what we just put in */
  843. pIFI->dpwszStyleName = (PTRDIFF)((BYTE *)pwch - (BYTE *)pIFI);
  844. StringCchCatW(pwch, pwchEnd - pwch, &awcAttrib[1]);
  845. #if DBG
  846. /*
  847. * Check on a few memory sizes: JUST IN CASE.....
  848. */
  849. if( (wcslen( awcAttrib ) * sizeof( WCHAR )) >= sizeof( awcAttrib ) )
  850. {
  851. DbgPrint( "Rasdd!SfhToIFI: STACK CORRUPTED BY awcAttrib" );
  852. HeapFree( hheap, 0, (LPSTR)pIFI ); /* No memory leaks */
  853. return 0;
  854. }
  855. if( ((BYTE *)(pwch + wcslen( pwch ) + 1)) > ((BYTE *)pIFI + cbAlloc) )
  856. {
  857. DbgPrint( "Rasdd!SfhToIFI: IFIMETRICS overflow: Wrote to 0x%lx, allocated to 0x%lx\n",
  858. ((BYTE *)(pwch + wcslen( pwch ) + 1)),
  859. ((BYTE *)pIFI + cbAlloc) );
  860. HeapFree( hheap, 0, (LPSTR)pIFI ); /* No memory leaks */
  861. return 0;
  862. }
  863. #endif
  864. /*
  865. * Change to use new IFIMETRICS.
  866. */
  867. pIFI->flInfo = FM_INFO_TECH_BITMAP | FM_INFO_1BPP |
  868. FM_INFO_RIGHT_HANDED | FM_INFO_FAMILY_EQUIV;
  869. pIFI->lEmbedId = 0;
  870. pIFI->lItalicAngle = 0;
  871. pIFI->lCharBias = 0;
  872. pIFI->dpCharSets = 0; // no multiple charsets in rasdd fonts
  873. pIFI->fwdUnitsPerEm = psfh->wCellHeight;
  874. pIFI->fwdLowestPPEm = 1; /* Not important for us */
  875. pIFI->fwdWinAscender = psfh->wBaseline;
  876. pIFI->fwdWinDescender = psfh->wCellHeight - psfh->wBaseline;
  877. pIFI->fwdMacAscender = pIFI->fwdWinAscender;
  878. pIFI->fwdMacDescender = - pIFI->fwdWinDescender;
  879. pIFI->fwdMacLineGap = 0;
  880. pIFI->fwdTypoAscender = pIFI->fwdMacAscender;
  881. pIFI->fwdTypoDescender = pIFI->fwdMacDescender;
  882. pIFI->fwdTypoLineGap = pIFI->fwdMacLineGap;
  883. pIFI->fwdAveCharWidth = (psfh->wTextWidth + 2) / 4;
  884. pIFI->fwdMaxCharInc = psfh->wCellWide;
  885. pIFI->fwdCapHeight = psfh->wBaseline;
  886. pIFI->fwdXHeight = psfh->wBaseline;
  887. pIFI->fwdUnderscoreSize = psfh->bUHeight;
  888. pIFI->fwdUnderscorePosition = -(psfh->sbUDist - psfh->bUHeight / 2);
  889. pIFI->fwdStrikeoutSize = psfh->bUHeight;
  890. pIFI->fwdStrikeoutPosition = psfh->wBaseline / 3;
  891. pIFI->jWinCharSet = OEM_CHARSET;
  892. if( psfh->bSpacing )
  893. {
  894. /*
  895. * Proportional, so also look at the serif style. Consult the
  896. * LaserJet III Technical Reference Manual to see the following
  897. * constants. Basically, the serif fonts have a value between
  898. * 2 and 8, or the top two bits have the value 64.
  899. */
  900. if( (psfh->bSerifStyle >= 2 && psfh->bSerifStyle <= 8) ||
  901. (psfh->bSerifStyle & 0xc0) == 0x80 )
  902. {
  903. pIFI->jWinPitchAndFamily = FF_ROMAN | VARIABLE_PITCH;
  904. }
  905. else
  906. pIFI->jWinPitchAndFamily = FF_SWISS | VARIABLE_PITCH;
  907. }
  908. else
  909. {
  910. /* Fixed pitch, so select FF_MODERN as the style */
  911. pIFI->jWinPitchAndFamily = FF_MODERN | FIXED_PITCH;
  912. }
  913. pIFI->usWinWeight = 400; /* Normal weight */
  914. pIFI->panose.bWeight = PAN_WEIGHT_MEDIUM;
  915. if( psfh->sbStrokeW >= PCL_BOLD ) /* As per HP spec */
  916. {
  917. /* Set a bold value */
  918. pIFI->usWinWeight = 700;
  919. pIFI->panose.bWeight = PAN_WEIGHT_BOLD;
  920. }
  921. else
  922. {
  923. if( psfh->sbStrokeW <= PCL_LIGHT )
  924. {
  925. pIFI->usWinWeight = 200;
  926. pIFI->panose.bWeight = PAN_WEIGHT_LIGHT;
  927. }
  928. }
  929. pIFI->fsType = FM_NO_EMBEDDING;
  930. /*
  931. * The first/last/break/default glyphs: these are determined by the
  932. * type of the font. ALL PCL fonts (according to HP documentation)
  933. * include the space character, so we use that.
  934. */
  935. if( psfh->bFontType != PCL_FT_PC8 )
  936. pIFI->chFirstChar = ' ';
  937. else
  938. pIFI->chFirstChar = 0;
  939. if( psfh->bFontType == PCL_FT_7BIT )
  940. pIFI->chLastChar = 127;
  941. else
  942. pIFI->chLastChar = 255;
  943. pIFI->chDefaultChar = '.' - pIFI->chFirstChar;
  944. pIFI->chBreakChar = ' ' - pIFI->chFirstChar;
  945. /* Fill in the WCHAR versions of these values */
  946. cChars = pIFI->chLastChar - pIFI->chFirstChar + 1;
  947. for( iI = 0; iI < cChars; ++iI )
  948. ajANSI[ iI ] = (BYTE)(pIFI->chFirstChar + iI);
  949. MultiByteToWideChar( CP_ACP, 0, ajANSI, cChars, awcAttrib, cChars );
  950. pIFI->wcDefaultChar = awcAttrib[ pIFI->chDefaultChar ];
  951. pIFI->wcBreakChar = awcAttrib[ pIFI->chBreakChar ];
  952. pIFI->wcFirstChar = 0xffff;
  953. pIFI->wcLastChar = 0;
  954. /* Scan for first and last */
  955. for( iI = 0; iI < cChars; ++iI )
  956. {
  957. if( awcAttrib[ iI ] > pIFI->wcLastChar )
  958. pIFI->wcLastChar = awcAttrib[ iI ];
  959. if( awcAttrib[ iI ] < pIFI->wcFirstChar )
  960. pIFI->wcFirstChar = awcAttrib[ iI ];
  961. }
  962. /* StemDir: either roman or italic */
  963. if( psfh->sbStrokeW >= PCL_BOLD ) /* As per HP spec */
  964. pIFI->fsSelection |= FM_SEL_BOLD;
  965. if( psfh->bStyle )
  966. {
  967. /*
  968. * Tan (17.5 degrees) = .3153
  969. */
  970. pIFI->ptlCaret.x = 3153;
  971. pIFI->ptlCaret.y = 10000;
  972. pIFI->fsSelection |= FM_SEL_ITALIC;
  973. }
  974. else
  975. {
  976. pIFI->ptlCaret.x = 0;
  977. pIFI->ptlCaret.y = 1;
  978. }
  979. if( (pIFI->fsSelection & (FM_SEL_ITALIC | FM_SEL_BOLD)) == 0 )
  980. pIFI->fsSelection |= FM_SEL_REGULAR;
  981. if( !psfh->bSpacing )
  982. pIFI->flInfo |= FM_INFO_CONSTANT_WIDTH;
  983. pIFI->ptlBaseline.x = 1;
  984. pIFI->ptlBaseline.y = 0;
  985. pIFI->ptlAspect.x = pIFI->ptlAspect.y = 300;
  986. pIFI->fwdSubscriptXSize = (FWORD)(pIFI->fwdAveCharWidth / 4);
  987. pIFI->fwdSubscriptYSize = (FWORD)(pIFI->fwdWinAscender / 4);
  988. pIFI->fwdSubscriptXOffset = (FWORD)(3 * pIFI->fwdAveCharWidth / 4);
  989. pIFI->fwdSubscriptYOffset = (FWORD)(-pIFI->fwdWinAscender / 4);
  990. pIFI->fwdSuperscriptXSize = (FWORD)(pIFI->fwdAveCharWidth / 4);
  991. pIFI->fwdSuperscriptYSize = (FWORD)(pIFI->fwdWinAscender / 4);
  992. pIFI->fwdSuperscriptXOffset = (FWORD)(3 * pIFI->fwdAveCharWidth / 4);
  993. pIFI->fwdSuperscriptYOffset = (FWORD)(3 * pIFI->fwdWinAscender / 4);
  994. pIFI->rclFontBox.left = 0;
  995. pIFI->rclFontBox.top = pIFI->fwdWinAscender;
  996. pIFI->rclFontBox.right = pIFI->fwdMaxCharInc;
  997. pIFI->rclFontBox.bottom = -pIFI->fwdWinDescender;
  998. pIFI->achVendId[ 0 ] = 'U';
  999. pIFI->achVendId[ 1 ] = 'n';
  1000. pIFI->achVendId[ 2 ] = 'k';
  1001. pIFI->achVendId[ 3 ] = 'n';
  1002. pIFI->cKerningPairs = 0;
  1003. pIFI->ulPanoseCulture = FM_PANOSE_CULTURE_LATIN;
  1004. pIFI->panose.bFamilyType = PAN_ANY;
  1005. pIFI->panose.bSerifStyle = PAN_ANY;
  1006. pIFI->panose.bProportion = PAN_ANY;
  1007. pIFI->panose.bContrast = PAN_ANY;
  1008. pIFI->panose.bStrokeVariation = PAN_ANY;
  1009. pIFI->panose.bArmStyle = PAN_ANY;
  1010. pIFI->panose.bLetterform = PAN_ANY;
  1011. pIFI->panose.bMidline = PAN_ANY;
  1012. pIFI->panose.bXHeight = PAN_ANY;
  1013. return pIFI;
  1014. }
  1015. /************************* Function Header ********************************
  1016. * strcpy2WChar
  1017. * Convert a char * string to a WCHAR string. Basically this means
  1018. * converting each input character to 16 bits by zero extending it.
  1019. *
  1020. * RETURNS:
  1021. * Value of first parameter.
  1022. *
  1023. * HISTORY:
  1024. * 12:35 on Thu 18 Mar 1993 -by- Lindsay Harris [lindsayh]
  1025. * Use the correct conversion method to Unicode.
  1026. *
  1027. * 09:36 on Thu 07 Mar 1991 -by- Lindsay Harris [lindsayh]
  1028. * Created it.
  1029. *
  1030. **************************************************************************/
  1031. PWSTR
  1032. strcpy2WChar( pWCHOut, lpstr )
  1033. PWSTR pWCHOut; /* Destination */
  1034. LPSTR lpstr; /* Source string */
  1035. {
  1036. /*
  1037. * Put buffering around the NLS function that does all this stuff.
  1038. */
  1039. int cchIn; /* Number of input chars */
  1040. cchIn = strlen( lpstr ) + 1;
  1041. MultiByteToWideChar( CP_ACP, 0, lpstr, cchIn, pWCHOut, cchIn );
  1042. return pWCHOut;
  1043. }
  1044. /******************************************************************************
  1045. *
  1046. * FIWriteFix
  1047. *
  1048. * Function:
  1049. * Write the IFIMETRICS fixed data to the output file
  1050. *
  1051. * Returns:
  1052. * Number of bytes written
  1053. *
  1054. ******************************************************************************/
  1055. DWORD
  1056. FIWriteFix(
  1057. HANDLE hFile,
  1058. WORD wDataID,
  1059. FI_DATA *pFD // Pointer to data to write
  1060. )
  1061. {
  1062. DATA_HEADER dh;
  1063. DWORD dwSize;
  1064. //
  1065. // Then write out the header, followed by the actual data
  1066. //
  1067. dh.dwSignature = DATA_IFI_SIG;
  1068. dh.wSize = (WORD)sizeof(DATA_HEADER);
  1069. dh.wDataID = wDataID;
  1070. dh.dwDataSize = sizeof(FI_DATA_HEADER) +
  1071. pFD->dsIFIMet.cBytes +
  1072. pFD->dsWidthTab.cBytes +
  1073. pFD->dsSel.cBytes +
  1074. pFD->dsDesel.cBytes +
  1075. pFD->dsIdentStr.cBytes +
  1076. pFD->dsETM.cBytes;
  1077. dh.dwReserved = 0;
  1078. WriteFile(hFile, (PVOID)&dh, sizeof(DATA_HEADER), &dwSize, NULL);
  1079. return sizeof(DATA_HEADER) + iWriteFDH(hFile, pFD);
  1080. }
  1081. /******************************************************************************
  1082. *
  1083. * FIWriteVar
  1084. *
  1085. * Function:
  1086. * Write the PCL variable data to the output file
  1087. *
  1088. * Returns:
  1089. * Number of bytes written
  1090. *
  1091. ******************************************************************************/
  1092. DWORD
  1093. FIWriteVar(
  1094. HANDLE hFile, // The file to which the data is written
  1095. TCHAR *ptchName // File name containing the data
  1096. )
  1097. {
  1098. DATA_HEADER dh;
  1099. HANDLE hIn;
  1100. DWORD dwSize = 0;
  1101. if (ptchName == 0 || *ptchName == (TCHAR)0)
  1102. return 0;
  1103. hIn = CreateFileW(ptchName,
  1104. GENERIC_READ,
  1105. FILE_SHARE_READ,
  1106. NULL,
  1107. OPEN_EXISTING,
  1108. 0,
  1109. 0);
  1110. if (hIn == INVALID_HANDLE_VALUE)
  1111. {
  1112. WARNING(("Error %d opening file %ws\n", GetLastError(), ptchName));
  1113. return 0;
  1114. }
  1115. //
  1116. // First write out the header, followed by the actual data
  1117. //
  1118. dh.dwSignature = DATA_VAR_SIG;
  1119. dh.wSize = (WORD)sizeof(DATA_HEADER);
  1120. dh.wDataID = 0;
  1121. dh.dwDataSize = GetFileSize(hIn, NULL);
  1122. dh.dwReserved = 0;
  1123. if (WriteFile(hFile, (PVOID)&dh, sizeof(DATA_HEADER), &dwSize, NULL))
  1124. {
  1125. dwSize += FICopy(hFile, hIn);
  1126. }
  1127. CloseHandle(hIn);
  1128. return dwSize;
  1129. }
  1130. /******************************************************************************
  1131. *
  1132. * FIWriteRawVar
  1133. *
  1134. * Function:
  1135. * Write the PCL variable data to the output file
  1136. *
  1137. * Returns:
  1138. * Number of bytes written
  1139. *
  1140. ******************************************************************************/
  1141. DWORD
  1142. FIWriteRawVar(
  1143. HANDLE hFile, // The file to which the data is written
  1144. PBYTE pRawVar, // Buffer containing PCL data
  1145. DWORD dwSize // Size of buffer
  1146. )
  1147. {
  1148. DATA_HEADER dh;
  1149. DWORD dwBytesWritten = 0;
  1150. if (pRawVar == NULL || dwSize == 0)
  1151. return 0;
  1152. //
  1153. // First write out the header, followed by the actual data
  1154. //
  1155. dh.dwSignature = DATA_VAR_SIG;
  1156. dh.wSize = (WORD)sizeof(DATA_HEADER);
  1157. dh.wDataID = 0;
  1158. dh.dwDataSize = dwSize;
  1159. dh.dwReserved = 0;
  1160. if (! WriteFile(hFile, (PVOID)&dh, sizeof(DATA_HEADER), &dwBytesWritten, NULL) ||
  1161. ! WriteFile(hFile, (PVOID)pRawVar, dwSize, &dwSize, NULL))
  1162. return 0;
  1163. return dwSize+dwBytesWritten;
  1164. }
  1165. /************************** Function Header ********************************
  1166. * FICopy
  1167. * Copy the file contents of the input handle to that of the output
  1168. * handle.
  1169. *
  1170. * RETURNS:
  1171. * Number of bytes copied, -1 on error, 0 is legitimate.
  1172. *
  1173. * HISTORY:
  1174. * 18:06 on Mon 24 Feb 1992 -by- Lindsay Harris [lindsayh]
  1175. * Start
  1176. *
  1177. ***************************************************************************/
  1178. DWORD
  1179. FICopy(
  1180. HANDLE hOut, /* Output file: write to current position */
  1181. HANDLE hIn /* Input file: copy from current position to EOF */
  1182. )
  1183. {
  1184. /*
  1185. * Simple read/write operations until EOF is reached on the input.
  1186. * May also be errors, so handle these too. As we are dealing with
  1187. * relatively small files (a few 10s of k), we use a stack buffer.
  1188. */
  1189. #define CPBSZ 2048
  1190. DWORD dwSize;
  1191. DWORD dwGot;
  1192. DWORD dwTot; /* Accumulate number of bytes copied */
  1193. BYTE ajBuf[ CPBSZ ];
  1194. dwTot = 0;
  1195. while (ReadFile(hIn, ajBuf, CPBSZ, &dwGot, NULL))
  1196. {
  1197. /* A read of zero means we have reached EOF */
  1198. if (dwGot == 0)
  1199. return dwTot; /* However much so far */
  1200. if (!WriteFile( hOut, ajBuf, dwGot, &dwSize, NULL) ||
  1201. dwSize != dwGot)
  1202. {
  1203. /* Assume some serious problem */
  1204. return 0;
  1205. }
  1206. dwTot += dwSize;
  1207. }
  1208. /*
  1209. * We only come here for an error, so return the bad news.
  1210. */
  1211. return 0;
  1212. }
  1213. /******************************* Function Header *****************************
  1214. * iWriteFDH
  1215. * Write the FI_DATA_HEADER data out to our file. We do the conversion
  1216. * from addresses to offsets, and write out any data we find.
  1217. *
  1218. * RETURNS:
  1219. * The number of bytes actually written; -1 for error, 0 for nothing.
  1220. *
  1221. * HISTORY:
  1222. * 16:58 on Thu 05 Mar 1992 -by- Lindsay Harris [lindsayh]
  1223. * Based on an experimental version first used in font installer.
  1224. *
  1225. * 17:11 on Fri 21 Feb 1992 -by- Lindsay Harris [lindsayh]
  1226. * First version.
  1227. *
  1228. *****************************************************************************/
  1229. int
  1230. iWriteFDH( hFile, pFD )
  1231. HANDLE hFile; /* File wherein to place the data */
  1232. FI_DATA *pFD; /* Pointer to FM to write out */
  1233. {
  1234. /*
  1235. * Decide how many bytes will be written out. We presume that the
  1236. * file pointer is located at the correct position when we are called.
  1237. */
  1238. int iSize; /* Evaluate output size */
  1239. FI_DATA_HEADER fdh; /* Header written to file */
  1240. if( pFD == 0 )
  1241. return 0; /* Perhaps only deleting? */
  1242. memset( &fdh, 0, sizeof( fdh ) ); /* Zero for convenience */
  1243. /*
  1244. * Set the miscellaneous flags etc.
  1245. */
  1246. fdh.cjThis = sizeof( fdh );
  1247. fdh.fCaps = pFD->fCaps;
  1248. fdh.wFontType= pFD->wFontType; /* Device Font Type */
  1249. fdh.wXRes = pFD->wXRes;
  1250. fdh.wYRes = pFD->wYRes;
  1251. fdh.sYAdjust = pFD->sYAdjust;
  1252. fdh.sYMoved = pFD->sYMoved;
  1253. fdh.u.sCTTid = (short)pFD->dsCTT.cBytes;
  1254. fdh.dwSelBits = pFD->dwSelBits;
  1255. fdh.wPrivateData = pFD->wPrivateData;
  1256. iSize = sizeof( fdh ); /* Our header already */
  1257. fdh.dwIFIMet = iSize; /* Location of IFIMETRICS */
  1258. iSize += pFD->dsIFIMet.cBytes; /* Bytes in struct */
  1259. /*
  1260. * And there may be a width table too! The pFD values are zero if none.
  1261. */
  1262. if( pFD->dsWidthTab.cBytes )
  1263. {
  1264. fdh.dwWidthTab = iSize;
  1265. iSize += pFD->dsWidthTab.cBytes;
  1266. }
  1267. /*
  1268. * Finally are the select/deselect strings.
  1269. */
  1270. if( pFD->dsSel.cBytes )
  1271. {
  1272. fdh.dwCDSelect = iSize;
  1273. iSize += pFD->dsSel.cBytes;
  1274. }
  1275. if( pFD->dsDesel.cBytes )
  1276. {
  1277. fdh.dwCDDeselect = iSize;
  1278. iSize += pFD->dsDesel.cBytes;
  1279. }
  1280. /*
  1281. * There may also be some sort of identification string.
  1282. */
  1283. if( pFD->dsIdentStr.cBytes )
  1284. {
  1285. fdh.dwIdentStr = iSize;
  1286. iSize += pFD->dsIdentStr.cBytes;
  1287. }
  1288. if( pFD->dsETM.cBytes )
  1289. {
  1290. fdh.dwETM = iSize;
  1291. iSize += pFD->dsETM.cBytes;
  1292. }
  1293. /*
  1294. * Sizes all figured out, so write the data!
  1295. */
  1296. if( !bWrite( hFile, &fdh, sizeof( fdh ) ) ||
  1297. !bWrite( hFile, pFD->dsIFIMet.pvData, pFD->dsIFIMet.cBytes ) ||
  1298. !bWrite( hFile, pFD->dsWidthTab.pvData, pFD->dsWidthTab.cBytes ) ||
  1299. !bWrite( hFile, pFD->dsSel.pvData, pFD->dsSel.cBytes ) ||
  1300. !bWrite( hFile, pFD->dsDesel.pvData, pFD->dsDesel.cBytes ) ||
  1301. !bWrite( hFile, pFD->dsIdentStr.pvData, pFD->dsIdentStr.cBytes ) ||
  1302. !bWrite( hFile, pFD->dsETM.pvData, pFD->dsETM.cBytes ) )
  1303. return 0;
  1304. return iSize; /* Number of bytes written */
  1305. }
  1306. /************************* Function Header *********************************
  1307. * bWrite
  1308. * Writes data out to a file handle. Returns TRUE on success.
  1309. * Functions as a nop if the size request is zero.
  1310. *
  1311. * RETURNS:
  1312. * TRUE/FALSE, TRUE for success.
  1313. *
  1314. * HISTORY:
  1315. * 17:38 on Fri 21 Feb 1992 -by- Lindsay Harris [lindsayh]
  1316. * # 1
  1317. *
  1318. ****************************************************************************/
  1319. BOOL
  1320. bWrite( hFile, pvBuf, iSize )
  1321. HANDLE hFile; /* The file to which to write */
  1322. VOID *pvBuf; /* Data to write */
  1323. int iSize; /* Number of bytes to write */
  1324. {
  1325. /*
  1326. * Simplify the ugly NT interface. Returns TRUE if the WriteFile
  1327. * call returns TRUE and the number of bytes written equals the
  1328. * number of bytes desired.
  1329. */
  1330. BOOL bRet;
  1331. DWORD dwSize; /* Filled in by WriteFile */
  1332. bRet = TRUE;
  1333. if( iSize > 0 &&
  1334. (!WriteFile( hFile, pvBuf, (DWORD)iSize, &dwSize, NULL ) ||
  1335. (DWORD)iSize != dwSize) )
  1336. bRet = FALSE; /* Too bad */
  1337. return bRet;
  1338. }
  1339. #if PRINT_INFO
  1340. /******************************Public*Routine******************************\
  1341. * vCheckIFIMETRICS
  1342. *
  1343. * This is where you put sanity checks on an incomming IFIMETRICS structure.
  1344. *
  1345. * History:
  1346. * Sun 01-Nov-1992 22:55:31 by Kirk Olynyk [kirko]
  1347. * Wrote it.
  1348. \**************************************************************************/
  1349. VOID
  1350. vCheckIFIMETRICS(
  1351. IFIMETRICS *pifi,
  1352. VPRINT vPrint
  1353. )
  1354. {
  1355. BOOL bGoodPitch;
  1356. BYTE jPitch =
  1357. pifi->jWinPitchAndFamily & (DEFAULT_PITCH | FIXED_PITCH | VARIABLE_PITCH);
  1358. if (pifi->flInfo & FM_INFO_CONSTANT_WIDTH)
  1359. {
  1360. bGoodPitch = (jPitch == FIXED_PITCH);
  1361. }
  1362. else
  1363. {
  1364. bGoodPitch = (jPitch == VARIABLE_PITCH);
  1365. }
  1366. if (!bGoodPitch)
  1367. {
  1368. vPrint("\n\n<INCONSISTENCY DETECTED>\n");
  1369. vPrint(
  1370. " jWinPitchAndFamily = %-#2x, flInfo = %-#8lx\n\n",
  1371. pifi->jWinPitchAndFamily,
  1372. pifi->flInfo
  1373. );
  1374. }
  1375. }
  1376. /******************************Public*Routine******************************\
  1377. * vPrintIFIMETRICS
  1378. *
  1379. * Dumps the IFMETERICS to the screen
  1380. *
  1381. * History:
  1382. * Wed 13-Jan-1993 10:14:21 by Kirk Olynyk [kirko]
  1383. * Updated it to conform to some changes to the IFIMETRICS structure
  1384. *
  1385. * Thu 05-Nov-1992 12:43:06 by Kirk Olynyk [kirko]
  1386. * Wrote it.
  1387. \**************************************************************************/
  1388. VOID
  1389. vPrintIFIMETRICS(
  1390. IFIMETRICS *pifi,
  1391. VPRINT vPrint
  1392. )
  1393. {
  1394. //
  1395. // Convenient pointer to Panose number
  1396. //
  1397. PANOSE *ppan = &pifi->panose;
  1398. PWSZ pwszFamilyName = (PWSZ)(((BYTE*) pifi) + pifi->dpwszFamilyName);
  1399. PWSZ pwszStyleName = (PWSZ)(((BYTE*) pifi) + pifi->dpwszStyleName );
  1400. PWSZ pwszFaceName = (PWSZ)(((BYTE*) pifi) + pifi->dpwszFaceName );
  1401. PWSZ pwszUniqueName = (PWSZ)(((BYTE*) pifi) + pifi->dpwszUniqueName);
  1402. vPrint(" cjThis %-#8lx\n" , pifi->cjThis );
  1403. vPrint(" cjIfiExtra %-#8lx\n" , pifi->cjIfiExtra );
  1404. vPrint(" pwszFamilyName \"%ws\"\n", pwszFamilyName );
  1405. if( pifi->flInfo & FM_INFO_FAMILY_EQUIV )
  1406. {
  1407. /* Aliasing is in effect! */
  1408. while( *(pwszFamilyName += wcslen( pwszFamilyName ) + 1) )
  1409. vPrint(" \"%ws\"\n", pwszFamilyName );
  1410. }
  1411. vPrint(" pwszStyleName \"%ws\"\n", pwszStyleName );
  1412. vPrint(" pwszFaceName \"%ws\"\n", pwszFaceName );
  1413. vPrint(" pwszUniqueName \"%ws\"\n", pwszUniqueName );
  1414. vPrint(" dpFontSim %-#8lx\n" , pifi->dpFontSim );
  1415. vPrint(" lEmbedId %d\n", pifi->lEmbedId );
  1416. vPrint(" lItalicAngle %d\n", pifi->lItalicAngle);
  1417. vPrint(" lCharBias %d\n", pifi->lCharBias );
  1418. vPrint(" lEmbedId %d\n" , pifi->lEmbedId);
  1419. vPrint(" lItalicAngle %d\n" , pifi->lItalicAngle);
  1420. vPrint(" lCharBias %d\n" , pifi->lCharBias);
  1421. vPrint(" jWinCharSet %04x\n" , pifi->jWinCharSet );
  1422. vPrint(" jWinPitchAndFamily %04x\n" , pifi->jWinPitchAndFamily );
  1423. vPrint(" usWinWeight %d\n" , pifi->usWinWeight );
  1424. vPrint(" flInfo %-#8lx\n" , pifi->flInfo );
  1425. vPrint(" fsSelection %-#6lx\n" , pifi->fsSelection );
  1426. vPrint(" fsType %-#6lx\n" , pifi->fsType );
  1427. vPrint(" fwdUnitsPerEm %d\n" , pifi->fwdUnitsPerEm );
  1428. vPrint(" fwdLowestPPEm %d\n" , pifi->fwdLowestPPEm );
  1429. vPrint(" fwdWinAscender %d\n" , pifi->fwdWinAscender );
  1430. vPrint(" fwdWinDescender %d\n" , pifi->fwdWinDescender );
  1431. vPrint(" fwdMacAscender %d\n" , pifi->fwdMacAscender );
  1432. vPrint(" fwdMacDescender %d\n" , pifi->fwdMacDescender );
  1433. vPrint(" fwdMacLineGap %d\n" , pifi->fwdMacLineGap );
  1434. vPrint(" fwdTypoAscender %d\n" , pifi->fwdTypoAscender );
  1435. vPrint(" fwdTypoDescender %d\n" , pifi->fwdTypoDescender );
  1436. vPrint(" fwdTypoLineGap %d\n" , pifi->fwdTypoLineGap );
  1437. vPrint(" fwdAveCharWidth %d\n" , pifi->fwdAveCharWidth );
  1438. vPrint(" fwdMaxCharInc %d\n" , pifi->fwdMaxCharInc );
  1439. vPrint(" fwdCapHeight %d\n" , pifi->fwdCapHeight );
  1440. vPrint(" fwdXHeight %d\n" , pifi->fwdXHeight );
  1441. vPrint(" fwdSubscriptXSize %d\n" , pifi->fwdSubscriptXSize );
  1442. vPrint(" fwdSubscriptYSize %d\n" , pifi->fwdSubscriptYSize );
  1443. vPrint(" fwdSubscriptXOffset %d\n" , pifi->fwdSubscriptXOffset );
  1444. vPrint(" fwdSubscriptYOffset %d\n" , pifi->fwdSubscriptYOffset );
  1445. vPrint(" fwdSuperscriptXSize %d\n" , pifi->fwdSuperscriptXSize );
  1446. vPrint(" fwdSuperscriptYSize %d\n" , pifi->fwdSuperscriptYSize );
  1447. vPrint(" fwdSuperscriptXOffset %d\n" , pifi->fwdSuperscriptXOffset);
  1448. vPrint(" fwdSuperscriptYOffset %d\n" , pifi->fwdSuperscriptYOffset);
  1449. vPrint(" fwdUnderscoreSize %d\n" , pifi->fwdUnderscoreSize );
  1450. vPrint(" fwdUnderscorePosition %d\n" , pifi->fwdUnderscorePosition);
  1451. vPrint(" fwdStrikeoutSize %d\n" , pifi->fwdStrikeoutSize );
  1452. vPrint(" fwdStrikeoutPosition %d\n" , pifi->fwdStrikeoutPosition );
  1453. vPrint(" chFirstChar %-#4x\n" , (int) (BYTE) pifi->chFirstChar );
  1454. vPrint(" chLastChar %-#4x\n" , (int) (BYTE) pifi->chLastChar );
  1455. vPrint(" chDefaultChar %-#4x\n" , (int) (BYTE) pifi->chDefaultChar );
  1456. vPrint(" chBreakChar %-#4x\n" , (int) (BYTE) pifi->chBreakChar );
  1457. vPrint(" wcFirsChar %-#6x\n" , pifi->wcFirstChar );
  1458. vPrint(" wcLastChar %-#6x\n" , pifi->wcLastChar );
  1459. vPrint(" wcDefaultChar %-#6x\n" , pifi->wcDefaultChar );
  1460. vPrint(" wcBreakChar %-#6x\n" , pifi->wcBreakChar );
  1461. vPrint(" ptlBaseline {%d,%d}\n" , pifi->ptlBaseline.x,
  1462. pifi->ptlBaseline.y );
  1463. vPrint(" ptlAspect {%d,%d}\n" , pifi->ptlAspect.x,
  1464. pifi->ptlAspect.y );
  1465. vPrint(" ptlCaret {%d,%d}\n" , pifi->ptlCaret.x,
  1466. pifi->ptlCaret.y );
  1467. vPrint(" rclFontBox {%d,%d,%d,%d}\n",pifi->rclFontBox.left,
  1468. pifi->rclFontBox.top,
  1469. pifi->rclFontBox.right,
  1470. pifi->rclFontBox.bottom );
  1471. vPrint(" achVendId \"%c%c%c%c\"\n",pifi->achVendId[0],
  1472. pifi->achVendId[1],
  1473. pifi->achVendId[2],
  1474. pifi->achVendId[3] );
  1475. vPrint(" cKerningPairs %d\n" , pifi->cKerningPairs );
  1476. vPrint(" ulPanoseCulture %-#8lx\n" , pifi->ulPanoseCulture);
  1477. vPrint(
  1478. " panose {%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x}\n"
  1479. , ppan->bFamilyType
  1480. , ppan->bSerifStyle
  1481. , ppan->bWeight
  1482. , ppan->bProportion
  1483. , ppan->bContrast
  1484. , ppan->bStrokeVariation
  1485. , ppan->bArmStyle
  1486. , ppan->bLetterform
  1487. , ppan->bMidline
  1488. , ppan->bXHeight );
  1489. vCheckIFIMETRICS(pifi, vPrint);
  1490. }
  1491. #endif /* PRINT_INFO */