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.

1547 lines
39 KiB

  1. /*++
  2. Copyright (c) 1996 - 1999 Microsoft Corporation
  3. Module Name:
  4. font.c
  5. Abstract:
  6. Functions associated with fonts - switching between, downloading etc.
  7. Environment:
  8. Windows NT Unidrv driver
  9. Revision History:
  10. 12/19/96 -ganeshp-
  11. Created
  12. --*/
  13. #include "font.h"
  14. #include "math.h"
  15. //
  16. // Local Function Prototypes.
  17. //
  18. BOOL
  19. BDeselectFont(
  20. PDEV *pPDev,
  21. FONTMAP *pfm,
  22. INT iFont
  23. );
  24. VOID
  25. VResetFont(
  26. PDEV *pPDev
  27. )
  28. /*++
  29. Routine Description:
  30. Arguments:
  31. pPDev Pointer to PDEV
  32. Return Value:
  33. TRUE for success and FALSE for failure
  34. Note:
  35. 8/7/1997 -ganeshp-
  36. Created it.
  37. --*/
  38. {
  39. FONTPDEV *pFontPDev; /* UNIDRVs PDEV */
  40. //
  41. // All we have to do is to set the iFont to INVALID_FONT.
  42. //
  43. pFontPDev = PFDV;
  44. pFontPDev->ctl.iFont = INVALID_FONT;
  45. FTRC(\nUniFont!VResetFont:Reselecting Current Font\n);
  46. return;
  47. }
  48. BOOL
  49. BNewFont(
  50. PDEV *pPDev,
  51. int iNewFont,
  52. PFONTMAP pfm,
  53. DWORD dwFontAttrib)
  54. /*++
  55. Routine Description:
  56. Switch to a new font. This involves optionally deselecting
  57. the old font, selecting the new font, then recording the new
  58. font as active AND setting the font's attributes.
  59. Arguments:
  60. pPDev Pointer to PDEV
  61. iNewFont The font we want, 1 BASED!!!!!
  62. pfm Pointer to FONTMAP
  63. dwFontAttr Font attribute
  64. Return Value:
  65. TRUE/FALSE - TRUE if font changed, else FALSE.
  66. Note:
  67. 12-19-96: Created it -ganeshp-
  68. --*/
  69. {
  70. FONTPDEV *pFontPDev;
  71. POINTL ptl; // For size comparisons in scalable fonts
  72. FWORD fwdUnitsPerEm, fwdAveCharWidth, fwdMaxCharInc, fwdWinAscender;
  73. BOOL bRet; // What we return
  74. bRet = TRUE;
  75. pFontPDev = PFDV;
  76. fwdAveCharWidth = 0;
  77. fwdUnitsPerEm = 0;
  78. fwdWinAscender = 0;
  79. //
  80. // First check to see if a new font is needed. Compare the
  81. // font index first, then check if it is a scalable font, and
  82. // if so, whether the transform has changed.
  83. //
  84. if ( !pfm && !(pfm = PfmGetIt( pPDev, iNewFont )) )
  85. {
  86. ASSERTMSG(FALSE,("\nUniFont!BNewFont:Null pfm passed in and PfmGetIt failed\n"));
  87. return FALSE;
  88. }
  89. if( pfm->flFlags & FM_SCALABLE )
  90. {
  91. // Device Scalable or TrueType outline download
  92. //
  93. // Calculate the new height/width. If we have the same font AND
  94. // and the same point size, we return as all is now done.
  95. // Otherwise, go through the works.
  96. //
  97. if (dwFontAttrib & FONTATTR_SUBSTFONT)
  98. {
  99. fwdAveCharWidth = ((FONTMAP_DEV*)(pfm->pSubFM))->fwdFOAveCharWidth;
  100. fwdUnitsPerEm = ((FONTMAP_DEV*)(pfm->pSubFM))->fwdFOUnitsPerEm;
  101. fwdWinAscender = ((FONTMAP_DEV*)(pfm->pSubFM))->fwdFOWinAscender;
  102. }
  103. else // Device font or TT Outline download case
  104. {
  105. fwdAveCharWidth = ((IFIMETRICS*)(pfm->pIFIMet))->fwdAveCharWidth;
  106. fwdUnitsPerEm = ((IFIMETRICS*)(pfm->pIFIMet))->fwdUnitsPerEm;
  107. fwdWinAscender = ((IFIMETRICS*)(pfm->pIFIMet))->fwdWinAscender;
  108. }
  109. bRet = BGetPSize( pFontPDev, &ptl, fwdUnitsPerEm, fwdAveCharWidth);
  110. if( !bRet ||
  111. pFontPDev->ctl.iFont == iNewFont &&
  112. pFontPDev->ctl.iSoftFont == (INT)pfm->ulDLIndex &&
  113. pFontPDev->ctl.ptlScale.x == ptl.x &&
  114. pFontPDev->ctl.ptlScale.y == ptl.y )
  115. {
  116. bRet = FALSE;
  117. }
  118. }
  119. else
  120. {
  121. //
  122. // Bitmap font. only check indices
  123. //
  124. if( (iNewFont == pFontPDev->ctl.iFont) &&
  125. (pFontPDev->ctl.iSoftFont == (INT)pfm->ulDLIndex ||
  126. (INT)pfm->ulDLIndex == -1))
  127. {
  128. bRet = FALSE;
  129. }
  130. }
  131. if (bRet)
  132. //
  133. // Need to change a font.
  134. //
  135. {
  136. #if 0
  137. VERBOSE(("\n---------Previous font\n"));
  138. VERBOSE(("iFont =%d\n", pFontPDev->ctl.iFont));
  139. VERBOSE(("ulDLIndex =%d\n", pFontPDev->ctl.iSoftFont));
  140. VERBOSE(("ptlScale.x =%d\n", pFontPDev->ctl.ptlScale.x));
  141. VERBOSE(("ptlScale.y =%d\n", pFontPDev->ctl.ptlScale.y));
  142. VERBOSE(("\n New font\n"));
  143. if (pfm->flFlags & FM_SCALABLE)
  144. {
  145. VERBOSE((" Scalable font\n"));
  146. }
  147. else
  148. {
  149. VERBOSE((" NonScalable font\n"));
  150. }
  151. VERBOSE(("iFont =%d\n", iNewFont));
  152. VERBOSE(("ulDLIndex =%d\n", pfm->ulDLIndex));
  153. VERBOSE(("ptlScale.x =%d\n", ptl.x));
  154. VERBOSE(("ptlScale.y =%d\n\n", ptl.y));
  155. #endif
  156. if (BDeselectFont( pPDev, pFontPDev->ctl.pfm, pFontPDev->ctl.iFont) &&
  157. BUpdateStandardVar(pPDev, pfm, 0, dwFontAttrib, STD_FH|
  158. STD_FW|
  159. STD_FB|
  160. STD_FI|
  161. STD_FU|
  162. STD_FS) &&
  163. pfm->pfnSelectFont( pPDev, pfm, &ptl) )
  164. {
  165. //
  166. // New font available - so update the red tape
  167. //
  168. pFontPDev->ctl.iFont = (short)iNewFont;
  169. pFontPDev->ctl.iSoftFont = (INT)pfm->ulDLIndex;
  170. pFontPDev->ctl.ptlScale = ptl;
  171. pFontPDev->ctl.pfm = pfm;
  172. //
  173. // Need to scale syAdj for UPPERLEFT character position fonts.
  174. //
  175. if( pfm->flFlags & FM_SCALABLE)
  176. {
  177. if ( (pfm->dwFontType == FMTYPE_DEVICE) &&
  178. !(pFontPDev->flFlags & FDV_ALIGN_BASELINE) )
  179. {
  180. FLOATOBJ fo;
  181. int iTmp; /* Temporary holding variable */
  182. fo = pFontPDev->ctl.eYScale;
  183. FLOATOBJ_MulLong(&fo,
  184. fwdWinAscender);
  185. pfm->syAdj = -(SHORT)FLOATOBJ_GetLong(&fo);
  186. }
  187. }
  188. //
  189. // Set the desired mode info into the FONTPDEV
  190. //
  191. if( pfm->dwFontType == FMTYPE_DEVICE &&
  192. ((FONTMAP_DEV*)pfm->pSubFM)->fCaps & DF_BKSP_OK )
  193. pFontPDev->flFlags |= FDV_BKSP_OK;
  194. else
  195. pFontPDev->flFlags &= ~FDV_BKSP_OK;
  196. bRet = BSetFontAttrib( pPDev, 0, dwFontAttrib, TRUE);
  197. }
  198. else
  199. bRet = FALSE;
  200. }
  201. else
  202. //
  203. // Just change the font attribute
  204. //
  205. {
  206. if (pFontPDev->ctl.dwAttrFlags != dwFontAttrib)
  207. {
  208. BUpdateStandardVar(pPDev, pfm, 0, dwFontAttrib, STD_FH|
  209. STD_FW|
  210. STD_FB|
  211. STD_FI|
  212. STD_FU|
  213. STD_FS);
  214. if (!(pfm->dwFontType == FMTYPE_TTOUTLINE) &&
  215. !(pfm->dwFontType == FMTYPE_TTOEM) )
  216. {
  217. bRet = BSetFontAttrib( pPDev,
  218. pFontPDev->ctl.dwAttrFlags,
  219. dwFontAttrib, FALSE);
  220. }
  221. }
  222. }
  223. return bRet;
  224. }
  225. BOOL
  226. BDeselectFont(
  227. PDEV *pPDev,
  228. FONTMAP *pfm,
  229. INT iFont
  230. )
  231. /*++
  232. Routine Description:
  233. Issues a deselect command for the given font.
  234. Arguments:
  235. pPDev Pointer to PDEV.
  236. iFont Font index to be unselected, 1 based
  237. Return Value:
  238. TRUE/FALSE - FALSE if the command write fails.
  239. Note:
  240. 12-23-96: Created it -ganeshp-
  241. --*/
  242. {
  243. //
  244. // iFont < 1: TrueType font case
  245. // iFont == 0: This is a first call of SelectFont
  246. //
  247. // In these cases, just return TRUE;
  248. //
  249. if( iFont == INVALID_FONT)
  250. return TRUE;
  251. if( !pfm )
  252. {
  253. ASSERTMSG((FALSE),("\nUniFont!BDeselectFont: NULL pfm\n"));
  254. return FALSE;
  255. }
  256. return pfm->pfnDeSelectFont(pPDev, pfm);
  257. }
  258. FONTMAP *
  259. PfmGetIt(
  260. PDEV *pPDev,
  261. INT iIndex)
  262. {
  263. FONTMAP *pfm;
  264. //
  265. // Font indexes Less than equal to 0 are for downloaded fonts and greater
  266. // than 0 ( from 1 ) are for device fonts.
  267. //
  268. if (iIndex <= 0)
  269. {
  270. DL_MAP *pdm;
  271. //
  272. // Assume +ve from here on.
  273. //
  274. iIndex = -iIndex;
  275. if (NULL != (pdm = PGetDLMapFromIdx ((PFONTPDEV)(pPDev->pFontPDev),iIndex)))
  276. {
  277. pfm = pdm->pfm;
  278. }
  279. else
  280. {
  281. ERR(("PfmGetIf failed\n"));
  282. pfm = NULL;
  283. }
  284. }
  285. else
  286. {
  287. pfm = PfmGetDevicePFM(pPDev, iIndex);
  288. }
  289. return pfm;
  290. }
  291. FONTMAP *
  292. PfmGetDevicePFM(
  293. PDEV *pPDev,
  294. INT iIndex
  295. )
  296. /*++
  297. Routine Description:
  298. Returns the address of the FONTMAP structure corresponding to the
  299. iDLIndex entry of the downloaded GDI fonts.
  300. Arguments:
  301. pPDev Pointer to PDEV.
  302. iFont Font index to be unselected, 1 based
  303. Return Value:
  304. The address of the FONTMAP structure; 0 on error.
  305. Note:
  306. 12-23-96: Created it -ganeshp-
  307. --*/
  308. {
  309. FONTPDEV *pFontPDev; /* FM PDEV */
  310. FONTMAP *pfm; /* What we return */
  311. DL_MAP_LIST *pdml; /* The linked list of chunks */
  312. pFontPDev = pPDev->pFontPDev;
  313. pfm = NULL; /* Serious error return value */
  314. if( iIndex > 0 )
  315. {
  316. /*
  317. * With lazy fonts, first check that the font count has
  318. * been initialised. This means that the font infrastructure
  319. * has been created, and so we can then go on to the more
  320. * detailed data.
  321. */
  322. if( iIndex >= 1 && iIndex <= pPDev->iFonts )
  323. {
  324. pfm = (PFONTMAP)((PBYTE)pFontPDev->pFontMap
  325. + (SIZEOFDEVPFM() * (iIndex - 1)) );
  326. if( pfm->pIFIMet == NULL )
  327. {
  328. /* Initialise this particular font */
  329. if( !BFillinDeviceFM( pPDev, pfm, iIndex - 1) )
  330. {
  331. pfm = NULL; /* Bad news */
  332. }
  333. }
  334. }
  335. }
  336. return pfm;
  337. }
  338. BOOL
  339. BGetPSize(
  340. FONTPDEV *pFontPDev,
  341. POINTL *pptl,
  342. FWORD fwdUnitsPerEm,
  343. FWORD fwdAveCharWidth
  344. )
  345. /*++
  346. Routine Description:
  347. Apply the font transform to obtain the point size for this font.
  348. Arguments:
  349. pFontPDev Access to font stuff
  350. pptl Where to place the results
  351. pfm Gross font details
  352. Return Value:
  353. TRUE/FALSE, TRUE for success.
  354. Note:
  355. 12-26-96: Created it -ganeshp-
  356. --*/
  357. {
  358. int iTmp; /* Temporary holding variable */
  359. FLOATOBJ fo;
  360. PIFIMETRICS pIFI; /* Ifimetrics of interest */
  361. /*
  362. * The XFORM gives us the scaling factor from notional
  363. * to device space. Notional is based on the fwdEmHeight
  364. * field in the IFIMETRICS, so we use that to convert this
  365. * font height to scan lines. Then divide by device
  366. * font resolution gives us the height in inches, which
  367. * then needs to be converted to point size (multiplication
  368. * by 72 gives us that). We actually calculate to
  369. * hundredths of points, as PCL has this resolution. We
  370. * also need to round to the nearest quarter point.
  371. *
  372. * Also adjust the scale factors to reflect the rounding of the
  373. * point size which is applied.
  374. */
  375. #ifdef USEFLOATS
  376. /* Typically only the height is important: width for fixed pitch */
  377. iTmp = (int)(0.5 + pFontPDev->ctl.eYScale * fwdUnitsPerEm * 7200) /
  378. pFontPDev->pPDev->ptGrxRes.y;
  379. /* if the tranform is very small (Less than a quarter of point size)
  380. * then make it atleast a quarter point. This was causing AV in certain
  381. * cases.
  382. */
  383. if (iTmp < 25)
  384. {
  385. WARNING((UniFont!BGetPSize: Too Small Font Size));
  386. iTmp = 25;
  387. }
  388. pptl->y = ((iTmp + 12) / 25) * 25;
  389. pFontPDev->ctl.eYScale = (pFontPDev->ctl.eYScale * pptl->y) /iTmp;
  390. pFontPDev->ctl.eXScale = (pFontPDev->ctl.eXScale * pptl->y) /iTmp;
  391. iTmp = (int)(pFontPDev->ctl.eXScale * fwdAveCharWidth)
  392. /* if the tranform is very small, so that the width is Less than a 1 pixel,
  393. * then make it atleast a 1 pixel point. This was causing AV in certain
  394. * cases.
  395. */
  396. if (iTmp < 1)
  397. {
  398. iTmp = 1;
  399. }
  400. /* Width factor chars per inch: fixed pitch fonts only */
  401. iTmp = (100 * pFontPDev->pPDev->ptGrxRes.x) / iTmp;
  402. pptl->x = ((iTmp + 12) / 25) * 25;
  403. #else
  404. /* Typically only the height is important: width for fixed pitch */
  405. fo = pFontPDev->ctl.eYScale;
  406. FLOATOBJ_MulLong(&fo,fwdUnitsPerEm);
  407. FLOATOBJ_MulLong(&fo,7200);
  408. #ifndef WINNT_40 //NT 5.0
  409. FLOATOBJ_AddFloat(&fo,(FLOATL)FLOATL_00_50);
  410. #else // NT 4.0
  411. FLOATOBJ_AddFloat(&fo,(FLOAT)0.5);
  412. #endif //!WINNT_40
  413. iTmp = FLOATOBJ_GetLong(&fo);
  414. iTmp /= pFontPDev->pPDev->ptGrxRes.y;
  415. /* if the tranform is very small (Less than a quarter of point size)
  416. * then make it atleast a quarter point. This was causing AV in certain
  417. * cases.
  418. */
  419. if (iTmp < 25)
  420. {
  421. WARNING(("UniFont!BGetPSize: Too Small Font Height, iTmp = %d\n",iTmp));
  422. iTmp = 25;
  423. }
  424. pptl->y = ((iTmp + 12) / 25) * 25;
  425. //
  426. // If there is any arounding error, disable x position optimization.
  427. // The optimization code introduces positioning problem on TrueType font.
  428. //
  429. if (iTmp != pptl->y)
  430. {
  431. pFontPDev->flFlags |= FDV_DISABLE_POS_OPTIMIZE;
  432. }
  433. else
  434. {
  435. pFontPDev->flFlags &= ~FDV_DISABLE_POS_OPTIMIZE;
  436. }
  437. FLOATOBJ_MulLong(&pFontPDev->ctl.eYScale,pptl->y);
  438. FLOATOBJ_DivLong(&pFontPDev->ctl.eYScale,iTmp);
  439. FLOATOBJ_MulLong(&pFontPDev->ctl.eXScale,pptl->y);
  440. FLOATOBJ_DivLong(&pFontPDev->ctl.eXScale,iTmp);
  441. /* Width factor: fixed pitch fonts only */
  442. fo = pFontPDev->ctl.eXScale;
  443. FLOATOBJ_MulLong(&fo,fwdAveCharWidth);
  444. iTmp = FLOATOBJ_GetLong(&fo);
  445. /* if the tranform is very small, so that the width is Less than a 1 pixel,
  446. * then make it atleast a 1 pixel point. This was causing AV in certain
  447. * cases.
  448. */
  449. if (iTmp < 1)
  450. {
  451. iTmp = 1;
  452. }
  453. /* Width factor chars per inch in 100s: fixed pitch fonts only */
  454. iTmp = (100 * pFontPDev->pPDev->ptGrxRes.x) / iTmp;
  455. pptl->x = ((iTmp + 12) / 25) * 25; /* To nearest quarter point */
  456. #endif
  457. return TRUE;
  458. }
  459. INT
  460. ISetScale(
  461. FONTCTL *pctl,
  462. XFORMOBJ *pxo,
  463. BOOL bIntellifont,
  464. BOOL bAnyRotation
  465. )
  466. /*++
  467. Routine Description:
  468. Looks at the XFORM to determine the nearest right angle direction.
  469. This function is useful for scalable fonts on LaserJet printers,
  470. where the device can rotate fonts in multiples of 90 degrees only.
  471. We select the nearest 90 degree multiple.
  472. Arguments:
  473. pctl Where the output is placed.
  474. pxo The transform of interest
  475. bIntellifont TRUE for Intellifont width adjustment
  476. Return Value:
  477. Printer is able rotate any rotation (bAnyRotation is TRUE)
  478. Degress (0 - 359)
  479. Printer is not able rotate any rotation (bAnyRotation is FALSE)
  480. Multiple of 90 degress, i.e. 0 - 3, 3 being 270 degrees.
  481. Note:
  482. 12-26-96: Created it -ganeshp-
  483. --*/
  484. {
  485. /*
  486. * The technique is quite simple. Take a vector and apply the
  487. * transform. Look at the output and compare the (x, y) components.
  488. * The vector to transform is (100 000, 0), so any rotations, shears
  489. * etc are very obvious.
  490. */
  491. int iRet; /* Value to return */
  492. #ifdef USEFLOATS
  493. XFORM xform; /* Obtain the full XFORM then select */
  494. XFORMOBJ_iGetXform( pxo, &xform );
  495. /*
  496. * This logic is based on the following data:-
  497. *
  498. * Angle eM11 eM12 eM21 eM22
  499. * 0 S 0 0 S
  500. * 90 0 -S S 0
  501. * 180 -S 0 0 -S
  502. * 270 0 S -S 0
  503. *
  504. * The value S is some non-zero value, being the scaling
  505. * factor from notional to device.
  506. */
  507. /*
  508. * Further notes on the eXScale and eYScale values. The eXScale field
  509. * is hereby defined as being the value by which x values in font metrics
  510. * are scaled to produce the desired value. IF the font is rotated
  511. * by either 90 or 270 degrees, then this x value ultimately ends up
  512. * in the y direction, but this is not important.
  513. */
  514. if( xform.eM11 )
  515. {
  516. /* Either 0 or 180 rotation */
  517. if( xform.eM11 > 0 )
  518. {
  519. /* Normal case, 0 degree rotation */
  520. iRet = 0;
  521. pctl->eXScale = xform.eM11;
  522. pctl->eYScale = xform.eM22;
  523. }
  524. else
  525. {
  526. /* Reverse case, 180 degree rotation */
  527. iRet = 2;
  528. pctl->eXScale = -xform.eM11;
  529. pctl->eYScale = -xform.eM22;
  530. }
  531. }
  532. else
  533. {
  534. /* Must be 90 or 270 degree rotation */
  535. if( xform.eM12 < 0 )
  536. {
  537. /* The 90 degree case */
  538. iRet = 1;
  539. pctl->eXScale = xform.eM21;
  540. pctl->eYScale = -xform.eM12;
  541. }
  542. else
  543. {
  544. /* The 270 degree case */
  545. iRet = 3;
  546. pctl->eXScale = -xform.eM21;
  547. pctl->eYScale = xform.eM12;
  548. }
  549. }
  550. /*
  551. * Width tables are based on Intellifont's 72.31 points to the inch.
  552. */
  553. if( bIntellifont )
  554. pctl->eXScale = pctl->eXScale * (FLOAT)72.0 / (FLOAT)72.31;
  555. return iRet;
  556. #else
  557. FLOATOBJ_XFORM xform; /* Obtain the full XFORM then select */
  558. XFORMOBJ_iGetFloatObjXform( pxo, &xform );
  559. /*
  560. * This logic is based on the following data:-
  561. *
  562. * Angle eM11 eM12 eM21 eM22
  563. * 0 S 0 0 S
  564. * 90 0 -S S 0
  565. * 180 -S 0 0 -S
  566. * 270 0 S -S 0
  567. *
  568. * The value S is some non-zero value, being the scaling
  569. * factor from notional to device.
  570. */
  571. /*
  572. * Further notes on the eXScale and eYScale values. The eXScale field
  573. * is hereby defined as being the value by which x values in font metrics
  574. * are scaled to produce the desired value. IF the font is rotated
  575. * by either 90 or 270 degrees, then this x value ultimately ends up
  576. * in the y direction, but this is not important.
  577. */
  578. if(!FLOATOBJ_EqualLong(&xform.eM11,0) )
  579. {
  580. double rotate;
  581. //
  582. // R != 90 & R != 270
  583. //
  584. if( FLOATOBJ_GreaterThanLong(&xform.eM11,0) )
  585. {
  586. //
  587. // 0 <= R < 90 or 270 < R <= 360
  588. //
  589. if (FLOATOBJ_EqualLong(&xform.eM21, 0))
  590. {
  591. //
  592. // R = 0
  593. //
  594. iRet = 0;
  595. }
  596. else
  597. if (FLOATOBJ_GreaterThanLong(&xform.eM21, 0))
  598. {
  599. //
  600. // 0 < R < 90
  601. //
  602. iRet = 0;
  603. }
  604. else
  605. {
  606. //
  607. // 270 < R < 360
  608. //
  609. if (bAnyRotation)
  610. iRet = 270;
  611. else
  612. iRet = 3;
  613. }
  614. #ifndef WINNT_40 // NT 5.0
  615. if (bAnyRotation)
  616. {
  617. #pragma warning( disable: 4244)
  618. rotate = atan2(xform.eM21, xform.eM11);
  619. rotate *= 180;
  620. rotate /= FLOATL_PI;
  621. if (rotate < 0)
  622. rotate += 360;
  623. iRet = rotate;
  624. #pragma warning( default: 4244)
  625. }
  626. #endif
  627. }
  628. else
  629. {
  630. //
  631. // 90 < R < 270
  632. //
  633. if ( FLOATOBJ_EqualLong(&xform.eM21, 0))
  634. {
  635. //
  636. // R = 180
  637. //
  638. if (bAnyRotation)
  639. iRet = 180;
  640. else
  641. iRet = 2;
  642. }
  643. else
  644. if ( FLOATOBJ_GreaterThanLong(&xform.eM21, 0))
  645. {
  646. //
  647. // 90 < R < 180
  648. //
  649. if (bAnyRotation)
  650. iRet = 90;
  651. else
  652. iRet = 1;
  653. }
  654. else
  655. {
  656. //
  657. // 180 < R < 270
  658. //
  659. if (bAnyRotation)
  660. iRet = 180;
  661. else
  662. iRet = 2;
  663. }
  664. #ifndef WINNT_40 // NT 5.0
  665. if (bAnyRotation)
  666. {
  667. #pragma warning( disable: 4244)
  668. rotate = atan2(xform.eM21, xform.eM11);
  669. rotate *= 180;
  670. rotate /= FLOATL_PI;
  671. if (rotate < 0)
  672. rotate += 360;
  673. iRet = rotate;
  674. #pragma warning( default: 4244)
  675. }
  676. #endif
  677. FLOATOBJ_Neg(&xform.eM11);
  678. FLOATOBJ_Neg(&xform.eM22);
  679. }
  680. #ifndef WINNT_40 // NT 5.0
  681. if (bAnyRotation)
  682. {
  683. #pragma warning( disable: 4244)
  684. pctl->eXScale = sqrt(xform.eM11 * xform.eM11 + xform.eM12 * xform.eM12);
  685. pctl->eYScale = sqrt(xform.eM22 * xform.eM22 + xform.eM21 * xform.eM21);
  686. #pragma warning( default: 4244)
  687. }
  688. else
  689. #endif
  690. {
  691. pctl->eXScale = xform.eM11;
  692. pctl->eYScale = xform.eM22;
  693. }
  694. }
  695. else
  696. {
  697. //
  698. // 90 or 270
  699. //
  700. if( FLOATOBJ_GreaterThanLong(&xform.eM21,0) )
  701. {
  702. //
  703. // 90
  704. //
  705. if (bAnyRotation)
  706. iRet = 90;
  707. else
  708. iRet = 1;
  709. FLOATOBJ_Neg(&xform.eM12);
  710. }
  711. else
  712. {
  713. //
  714. // 270
  715. //
  716. if (bAnyRotation)
  717. iRet = 270;
  718. else
  719. iRet = 3;
  720. FLOATOBJ_Neg(&xform.eM21);
  721. }
  722. pctl->eXScale = xform.eM12;
  723. pctl->eYScale = xform.eM21;
  724. }
  725. /*
  726. * Width tables are based on Intellifont's 72.31 points to the inch.
  727. */
  728. if( bIntellifont )
  729. {
  730. FLOATOBJ_MulLong(&pctl->eXScale,72);
  731. #ifndef WINNT_40 //NT 5.0
  732. FLOATOBJ_DivFloat(&pctl->eXScale,(FLOATL)FLOATL_72_31);
  733. #else // NT 4.0
  734. FLOATOBJ_DivFloat(&pctl->eXScale,(FLOAT)72.31);
  735. #endif //!WINNT_40
  736. }
  737. return iRet;
  738. #endif //USEFLOATS
  739. }
  740. VOID
  741. VSetRotation(
  742. FONTPDEV *pFontPDev,
  743. int iRot
  744. )
  745. /*++
  746. Routine Description:
  747. Function to set the angular rotation for PCL 5 printers. These allow
  748. fonts to be rotated in multiples of 90 degrees relative to graphics.
  749. Arguments:
  750. pFontPDev Pointer to FONTPDEV.
  751. iRot Rotation amount, range 0 to 3.
  752. Return Value:
  753. TRUE/FALSE, TRUE being that the data was queued to be sent OK.
  754. Note:
  755. 12-26-96: Created it -ganeshp-
  756. --*/
  757. {
  758. PDEV *pPDev = pFontPDev->pPDev;
  759. if( iRot != pFontPDev->ctl.iRotate )
  760. {
  761. /* Rotation angle is different, so change it now */
  762. COMMAND *pCmd = NULL;
  763. if (pFontPDev->flFlags & FDV_90DEG_ROTATION)
  764. {
  765. pCmd = COMMANDPTR(pPDev->pDriverInfo, CMD_SETSIMPLEROTATION);
  766. }
  767. else if ((pFontPDev->flFlags & FDV_ANYDEG_ROTATION))
  768. {
  769. pCmd = COMMANDPTR(pPDev->pDriverInfo, CMD_SETANYROTATION);
  770. }
  771. if (pCmd)
  772. {
  773. pFontPDev->ctl.iRotate = iRot;
  774. BUpdateStandardVar(pPDev, NULL, 0, 0, STD_PRND);
  775. WriteChannel(pPDev, pCmd);
  776. }
  777. }
  778. }
  779. BOOL
  780. BSetFontAttrib(
  781. PDEV *pPDev,
  782. DWORD dwPrevAttrib,
  783. DWORD dwAttrib,
  784. BOOL bReset)
  785. {
  786. PFONTPDEV pFontPDev = pPDev->pFontPDev;
  787. PCOMMAND pBoldCmd = NULL,
  788. pItalicCmd = NULL,
  789. pUnderlineCmd = NULL;
  790. if (! (pFontPDev->flFlags & FDV_INIT_ATTRIB_CMD))
  791. {
  792. pFontPDev->pCmdBoldOn = COMMANDPTR(pPDev->pDriverInfo, CMD_BOLDON);
  793. pFontPDev->pCmdBoldOff = COMMANDPTR(pPDev->pDriverInfo, CMD_BOLDOFF);
  794. pFontPDev->pCmdItalicOn = COMMANDPTR(pPDev->pDriverInfo, CMD_ITALICON);
  795. pFontPDev->pCmdItalicOff = COMMANDPTR(pPDev->pDriverInfo, CMD_ITALICOFF);
  796. pFontPDev->pCmdUnderlineOn = COMMANDPTR(pPDev->pDriverInfo, CMD_UNDERLINEON);
  797. pFontPDev->pCmdUnderlineOff = COMMANDPTR(pPDev->pDriverInfo, CMD_UNDERLINEOFF);
  798. pFontPDev->pCmdClearAllFontAttribs = COMMANDPTR(pPDev->pDriverInfo, CMD_CLEARALLFONTATTRIBS);
  799. pFontPDev->flFlags |= FDV_INIT_ATTRIB_CMD;
  800. }
  801. //
  802. // pCmdBoldOn,Off, pCmdItalicOn,Off, pCmdUnderlineOn,Off
  803. // and pCmdClearAllFont Attribs are initialized in PDEV initialization.
  804. //
  805. if (!pFontPDev->pCmdBoldOn &&
  806. !pFontPDev->pCmdItalicOn &&
  807. !pFontPDev->pCmdUnderlineOn)
  808. {
  809. //
  810. // This printer doesn't support font attributes.
  811. //
  812. return TRUE;
  813. }
  814. if (bReset || (dwAttrib & FONTATTR_BOLD) != (dwPrevAttrib & FONTATTR_BOLD))
  815. {
  816. if(dwAttrib & FONTATTR_BOLD)
  817. pBoldCmd = pFontPDev->pCmdBoldOn;
  818. else
  819. pBoldCmd = pFontPDev->pCmdBoldOff;
  820. }
  821. if (bReset || (dwAttrib & FONTATTR_ITALIC) != (dwPrevAttrib & FONTATTR_ITALIC))
  822. {
  823. if(dwAttrib & FONTATTR_ITALIC)
  824. pItalicCmd = pFontPDev->pCmdItalicOn;
  825. else
  826. pItalicCmd = pFontPDev->pCmdItalicOff;
  827. }
  828. if (bReset || (dwAttrib & FONTATTR_UNDERLINE) != (dwPrevAttrib & FONTATTR_UNDERLINE))
  829. {
  830. if (dwAttrib & FONTATTR_UNDERLINE)
  831. pUnderlineCmd = pFontPDev->pCmdUnderlineOn;
  832. else
  833. pUnderlineCmd = pFontPDev->pCmdUnderlineOff;
  834. }
  835. if (
  836. pFontPDev->pCmdClearAllFontAttribs
  837. &&
  838. (bReset ||
  839. (pFontPDev->pCmdBoldOn && !pFontPDev->pCmdBoldOff) ||
  840. (pFontPDev->pCmdItalicOn && !pFontPDev->pCmdItalicOff) ||
  841. (pFontPDev->pCmdUnderlineOn && !pFontPDev->pCmdUnderlineOff)
  842. )
  843. )
  844. {
  845. WriteChannel(pPDev, pFontPDev->pCmdClearAllFontAttribs);
  846. //
  847. // Reset all font attributes
  848. //
  849. if (dwAttrib & FONTATTR_BOLD)
  850. pBoldCmd = pFontPDev->pCmdBoldOn;
  851. if (dwAttrib & FONTATTR_ITALIC)
  852. pItalicCmd = pFontPDev->pCmdItalicOn;
  853. if (dwAttrib & FONTATTR_UNDERLINE)
  854. pBoldCmd = pFontPDev->pCmdUnderlineOn;
  855. }
  856. if (pBoldCmd)
  857. WriteChannel(pPDev, pBoldCmd);
  858. if (pItalicCmd)
  859. WriteChannel(pPDev, pItalicCmd);
  860. if (pUnderlineCmd)
  861. WriteChannel(pPDev, pUnderlineCmd);
  862. ((FONTPDEV*)pPDev->pFontPDev)->ctl.dwAttrFlags = dwAttrib;
  863. return TRUE;
  864. }
  865. INT
  866. IGetGlyphWidth(
  867. PDEV *pPDev,
  868. FONTMAP *pFM,
  869. HGLYPH hg
  870. )
  871. /*++
  872. Routine Description:
  873. Function to get the width of a given Glyph.
  874. Arguments:
  875. pFM, Font data .
  876. hg Handle to glyph.
  877. Return Value:
  878. Scaled width wrt the current graphics resolution of a glyph.
  879. This width is in notional space and must be transformed to
  880. device space.
  881. Note:
  882. 12-26-96: Created it -ganeshp-
  883. --*/
  884. {
  885. if( pFM->flFlags & FM_GLYVER40 )
  886. {
  887. //
  888. // Old Format
  889. // This function return scaled width for fixed-pitch and proportioanl
  890. // pitch font.
  891. //
  892. return IGetIFIGlyphWidth(pPDev, pFM, hg);
  893. }
  894. else
  895. {
  896. //
  897. // New Format
  898. // This function return scaled width for fixed-pitch and proportioanl
  899. // pitch font.
  900. //
  901. return IGetUFMGlyphWidth(pPDev, pFM, hg);
  902. }
  903. }
  904. LONG LMulFloatLong(
  905. PFLOATOBJ pfo,
  906. LONG l)
  907. /*++
  908. Routine Description:
  909. Helper Function to multiply a Float with a long.
  910. Arguments:
  911. pfo, Float data .
  912. l Long data.
  913. Return Value:
  914. Returns a long data.
  915. Note:
  916. 12-29-96: Created it -ganeshp-
  917. --*/
  918. {
  919. FLOATOBJ fo;
  920. fo = *pfo;
  921. FLOATOBJ_MulLong(&fo,l);
  922. #ifndef WINNT_40 //NT 5.0
  923. FLOATOBJ_AddFloat(&fo,(FLOATL)FLOATL_00_50);
  924. #else // NT 4.0
  925. FLOATOBJ_AddFloat(&fo,(FLOAT)0.5);
  926. #endif //!WINNT_40
  927. return(FLOATOBJ_GetLong(&fo));
  928. }
  929. BOOL
  930. BUpdateStandardVar(
  931. PDEV *pPDev,
  932. PFONTMAP pfm,
  933. INT iGlyphIndex,
  934. DWORD dwFontAtt,
  935. DWORD dwFlags)
  936. /*++
  937. Routine Description:
  938. Updates GPD standard variable according to the pFontMap passed.
  939. Arguments:
  940. pPDev - a pointer to the physical device
  941. pfm - a pointer to the FONTMAP data structure
  942. iGlyphIndex - an index of glyph
  943. dwFontAtt - a font attribute
  944. dwFlags - a type of standard variable
  945. Return Value:
  946. TRUE if suceeded. Otheriwse FALSE;
  947. --*/
  948. {
  949. FONTPDEV *pFontPDev;
  950. IFIMETRICS *pIFIMet;
  951. FLOATOBJ fo;
  952. //VERBOSE(("BUpdateStandardVar dwFlags=%x\n",dwFlags));
  953. pFontPDev = pPDev->pFontPDev;
  954. //
  955. // Update standard variables
  956. //
  957. // Font related variables
  958. // ---------------------------------------------------
  959. // NextGlyph TT Download STD_GL
  960. // FontHeight TT/Device font STD_FH
  961. // FontWidth TT/Device font STD_FW
  962. // FontBold TT/Device font STD_FB
  963. // FontItalic TT/Device font STD_FI
  964. // FontUnderline TT/Device font STD_FU
  965. // FontStrikeThru TT/Device font STD_FS
  966. // NextFontID TT Download STD_NFID
  967. // CurrentFontID TT Download STD_CFID
  968. // PrintDirection TT/Device font STD_PRND
  969. //
  970. // STD_STD = STD_GL| STD_FH| STD_FW| STD_FB| STD_FI| STD_FU| STD_FS
  971. // STD_TT = STD_NFID| STD_CFID| STD_PRND
  972. //
  973. if (pfm)
  974. {
  975. pIFIMet = (IFIMETRICS *) pfm->pIFIMet;
  976. //
  977. // TT Outline has to be scaled as well as device font.
  978. //if (pfm->dwFontType == FMTYPE_TTBITMAP)
  979. //
  980. if (pIFIMet->flInfo & FM_INFO_TECH_TRUETYPE)
  981. {
  982. //
  983. // FontHeight
  984. //
  985. if (dwFlags & STD_FH)
  986. {
  987. pPDev->dwFontHeight = (WORD)( max(pIFIMet->rclFontBox.top,
  988. pIFIMet->fwdWinAscender) -
  989. min(-pIFIMet->fwdWinDescender,
  990. pIFIMet->rclFontBox.bottom ) +
  991. 1);
  992. pPDev->dwFontHeight *= pPDev->ptGrxScale.y;
  993. }
  994. //
  995. // FontWidth
  996. //
  997. if (dwFlags & STD_FW)
  998. {
  999. //
  1000. // FontMaxWidth update
  1001. //
  1002. pPDev->dwFontMaxWidth = pIFIMet->fwdMaxCharInc;
  1003. pPDev->dwFontMaxWidth *= pPDev->ptGrxScale.x;
  1004. //
  1005. // FontWidth update
  1006. //
  1007. pPDev->dwFontWidth = max(pIFIMet->rclFontBox.right -
  1008. pIFIMet->rclFontBox.left + 1,
  1009. pIFIMet->fwdAveCharWidth );
  1010. pPDev->dwFontWidth *= pPDev->ptGrxScale.x;
  1011. }
  1012. }
  1013. else
  1014. {
  1015. //
  1016. // FontHeight
  1017. //
  1018. if (dwFlags & STD_FH)
  1019. {
  1020. fo = pFontPDev->ctl.eYScale;
  1021. if (dwFontAtt & FONTATTR_SUBSTFONT)
  1022. {
  1023. FLOATOBJ_MulLong(&fo, ((FONTMAP_DEV*)pfm->pSubFM)->fwdFOUnitsPerEm);
  1024. }
  1025. else
  1026. FLOATOBJ_MulLong(&fo, pIFIMet->fwdUnitsPerEm);
  1027. FLOATOBJ_MulLong(&fo, pPDev->ptGrxScale.y);
  1028. pPDev->dwFontHeight = FLOATOBJ_GetLong(&fo);
  1029. }
  1030. //
  1031. // FontWidth
  1032. //
  1033. if (dwFlags & STD_FW)
  1034. {
  1035. //
  1036. // FontWidth update
  1037. //
  1038. fo = pFontPDev->ctl.eXScale;
  1039. if (dwFontAtt & FONTATTR_SUBSTFONT)
  1040. {
  1041. FLOATOBJ_MulLong(&fo,((FONTMAP_DEV*)pfm->pSubFM)->fwdFOAveCharWidth);
  1042. }
  1043. else
  1044. FLOATOBJ_MulLong(&fo, pIFIMet->fwdAveCharWidth);
  1045. FLOATOBJ_MulLong(&fo, pPDev->ptGrxScale.x);
  1046. pPDev->dwFontWidth = FLOATOBJ_GetLong(&fo);
  1047. //
  1048. // FontMaxWidth update
  1049. //
  1050. fo = pFontPDev->ctl.eXScale;
  1051. if (dwFontAtt & FONTATTR_SUBSTFONT)
  1052. {
  1053. FLOATOBJ_MulLong(&fo,((FONTMAP_DEV*)pfm->pSubFM)->fwdFOMaxCharInc);
  1054. }
  1055. else
  1056. FLOATOBJ_MulLong(&fo, pIFIMet->fwdMaxCharInc);
  1057. FLOATOBJ_MulLong(&fo, pPDev->ptGrxScale.x);
  1058. pPDev->dwFontMaxWidth = FLOATOBJ_GetLong(&fo);
  1059. }
  1060. }
  1061. }
  1062. //
  1063. //
  1064. // Font attributes, dwFontBold
  1065. // dwFontItalic
  1066. //
  1067. if (dwFlags & STD_FB)
  1068. pPDev->dwFontBold = dwFontAtt & FONTATTR_BOLD;
  1069. if (dwFlags & STD_FI)
  1070. pPDev->dwFontItalic = dwFontAtt & FONTATTR_ITALIC;
  1071. //
  1072. // TrueType font font ID/glyph ID
  1073. //
  1074. if (dwFlags & STD_NFID && NULL != pfm)
  1075. pPDev->dwNextFontID = pfm->ulDLIndex;
  1076. else
  1077. pPDev->dwNextFontID = 0;
  1078. //
  1079. // Glyph ID
  1080. //
  1081. if (dwFlags & STD_GL)
  1082. pPDev->dwNextGlyph = iGlyphIndex;
  1083. //
  1084. // String rotation
  1085. //
  1086. if (dwFlags & STD_PRND)
  1087. {
  1088. if (!(pFontPDev->flText & TC_CR_ANY))
  1089. pPDev->dwPrintDirection = pFontPDev->ctl.iRotate * 90;
  1090. else
  1091. pPDev->dwPrintDirection = pFontPDev->ctl.iRotate;
  1092. }
  1093. //
  1094. // Font ID
  1095. //
  1096. if (dwFlags & STD_CFID)
  1097. pPDev->dwCurrentFontID = pfm->ulDLIndex;
  1098. return TRUE;
  1099. }
  1100. INT
  1101. IFont100toStr(
  1102. BYTE *pjOut,
  1103. INT iBufSize, //Size of buffer(in bytes) pointed to by pjOut.
  1104. int iVal
  1105. )
  1106. /*++
  1107. Routine Description:
  1108. Convert a font size parameter to ASCII. Note that the value is
  1109. 100 times its actual value, and we need to include the decimal
  1110. point and trailing zeroes should these be significant.
  1111. Arguments:
  1112. BYTE pjOut Output area
  1113. int iVal Value to convert
  1114. Return Value:
  1115. Number of bytes added to output buffer.
  1116. -1 if some error occurs.
  1117. Note:
  1118. 12-26-96: Created it -ganeshp-
  1119. --*/
  1120. {
  1121. int iSize; /* Count bytes placed in output area */
  1122. int cDigits; /* Count number of digits processed */
  1123. BYTE *pjConv; /* For stepping through local array */
  1124. BYTE ajConv[ 16 ]; /* Local conversion buffer */
  1125. /*
  1126. * Convert the value into ASCII, remembering that there are
  1127. * two digits following the decimal point; these need not be
  1128. * sent if they are zero.
  1129. */
  1130. pjConv = ajConv;
  1131. cDigits = 0;
  1132. while( iVal > 0 || cDigits < 3 )
  1133. {
  1134. *pjConv++ = (iVal % 10) + '0';
  1135. iVal /= 10;
  1136. ++cDigits;
  1137. }
  1138. iSize = 0;
  1139. if ( iBufSize < cDigits - 2 )
  1140. {
  1141. ERR(( "fonts!IFont100toStr(): Too many digits in command\n"));
  1142. return -1;
  1143. }
  1144. while( cDigits > 2 )
  1145. {
  1146. pjOut[ iSize++ ] = *--pjConv; /* Backwards from MSD */
  1147. --cDigits;
  1148. }
  1149. /* Test for digits following the decimal point */
  1150. if( ajConv[ 1 ] != '0' || ajConv[ 0 ] != '0' )
  1151. {
  1152. if ( iBufSize - iSize >= 2 ) //test if pjOut has enough space to hold 2 bytes
  1153. {
  1154. pjOut[ iSize++ ] = '.';
  1155. pjOut[ iSize++ ] = ajConv[ 1 ];
  1156. }
  1157. else
  1158. {
  1159. return -1;
  1160. }
  1161. /* Test for the least significant digit */
  1162. if( ajConv[ 0 ] != '0' )
  1163. {
  1164. if ( iBufSize - iSize >= 1 )
  1165. {
  1166. pjOut[ iSize++ ] = ajConv[ 0 ];
  1167. }
  1168. else
  1169. {
  1170. return -1;
  1171. }
  1172. }
  1173. }
  1174. return iSize;
  1175. }
  1176. VOID
  1177. VSetCursor(
  1178. IN PDEV *pPDev,
  1179. IN INT iX,
  1180. IN INT iY,
  1181. IN WORD wMoveType,
  1182. OUT POINTL *pptlRem
  1183. )
  1184. /*++
  1185. Routine Description:
  1186. This routine set the absolute cursor position.
  1187. Arguments:
  1188. pPDev Pointer to PDEV
  1189. iX, iY Input cursor position to move
  1190. wMoveType Type of the input Value, MOVE_RELATIVE, MOVE_ABSOLUTE or
  1191. MOVE_UPDATE
  1192. pptlRem Remainder part which couldn't be moved. Return values from XMoveTo
  1193. and YMoveTo.
  1194. Return Value:
  1195. None
  1196. Note:
  1197. 8/12/1997 -ganeshp-
  1198. Created it.
  1199. --*/
  1200. {
  1201. FONTPDEV *pFontPDev;
  1202. TO_DATA *pTod;
  1203. #if defined(_M_IA64) // NTBUG #206444 (203236)
  1204. volatile
  1205. #endif
  1206. WORD wUpdate = 0;
  1207. pFontPDev = pPDev->pFontPDev;
  1208. pTod = pFontPDev->ptod;
  1209. if (wMoveType & MOVE_UPDATE)
  1210. {
  1211. wUpdate = MV_UPDATE;
  1212. }
  1213. if (wMoveType & MOVE_ABSOLUTE)
  1214. {
  1215. //
  1216. //Transform the input X and Y from band coordinates to page coordinates.
  1217. //
  1218. iX += pPDev->rcClipRgn.left;
  1219. iY += pPDev->rcClipRgn.top;
  1220. pptlRem->y = YMoveTo( pPDev, iY, MV_GRAPHICS | wUpdate );
  1221. if (pPDev->fMode & PF_ROTATE)
  1222. pptlRem->x = XMoveTo( pPDev, iX, MV_GRAPHICS | wUpdate);
  1223. else
  1224. pptlRem->x = XMoveTo( pPDev, iX, MV_GRAPHICS | MV_FINE | wUpdate);
  1225. }
  1226. else if (wMoveType & MOVE_RELATIVE)
  1227. {
  1228. //
  1229. // if we are moving relative then no need to do the transform. Just
  1230. // call XMoveTo and YMoveTo
  1231. //
  1232. pptlRem->x = XMoveTo( pPDev, iX, MV_GRAPHICS | MV_RELATIVE | wUpdate);
  1233. pptlRem->y = YMoveTo( pPDev, iY, MV_GRAPHICS | MV_RELATIVE | wUpdate);
  1234. }
  1235. //
  1236. // If PF_RESELECTFONT_AFTER_XMOVE is set, UNIDRV has to reset font after
  1237. // XMoveTo command.
  1238. //
  1239. if (pFontPDev->ctl.iFont == INVALID_FONT)
  1240. {
  1241. BNewFont(pPDev,
  1242. (pTod->iSubstFace?pTod->iSubstFace:pTod->iFace),
  1243. pTod->pfm,
  1244. pTod->dwAttrFlags);
  1245. }
  1246. return;
  1247. }