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.

3543 lines
105 KiB

  1. /*++
  2. Copyright (c) 1996 - 1999 Microsoft Corporation
  3. Module Name:
  4. textout.c
  5. Abstract:
  6. The FMTextOut() function - the call used to output Text.
  7. Environment:
  8. Windows NT Unidrv driver
  9. Revision History:
  10. 01/16/97 -ganeshp-
  11. Created
  12. --*/
  13. //
  14. //This line should be before the line including font.h.
  15. //Comment out this line to disable FTRC and FTST macroes.
  16. //
  17. //#define FILETRACE
  18. #include "font.h"
  19. /*
  20. * Some clipping constants. With a complex clip region, it is desirable
  21. * to avoid enumerating the clip rectangles more than once. To do so,
  22. * we have a bit array, with each bit being set if the glyph is inside
  23. * the clipping region, cleared if not. This allows us to obtain a
  24. * set of glyphs, then determine whether they are printed when the clip
  25. * rectangles are enumerated. Finally, use the bit array to stop
  26. * printing any glyphs outside the clip region. This is slightly heavy
  27. * handed for the simple case.
  28. */
  29. #define RECT_LIMIT 100 // Clipping rectangle max
  30. #define DC_TC_BLACK 0 /* Fixed Text Colors in 4 bit mode */
  31. #define DC_TC_MAX 8 /* used for 16 colour palette wrap around */
  32. #define CMD_TC_FIRST CMD_SELECTBLACKCOLOR
  33. // For Dithered Color BRUSHOBJ.iSolidColor is -1.
  34. #define DITHERED_COLOR -1
  35. //Various TextOut specific flags.
  36. #define TXTOUT_CACHED 0x00000001 // Text is cached and printed after graphics.
  37. #define TXTOUT_SETPOS 0x00000002 // True if cursor position to be set.
  38. #define TXTOUT_FGCOLOR 0x00000004 // Device can paint the text.
  39. #define TXTOUT_COLORBK 0x00000008 // For z-ordering fixes
  40. #define TXTOUT_NOTROTATED 0x00000010 // Set if Text is not rotated.
  41. #define TXTOUT_PRINTASGRX 0x00000020 // Set if Text should be printed as
  42. // Graphics.
  43. #define TXTOUT_DMS 0x00000040 // Set if Device Managed surface
  44. #define TXTOUT_90_ROTATION 0x00000080 // Set if font is 90-rotated.
  45. #define DEVICE_FONT(pfo, tod) ( (pfo->flFontType & DEVICE_FONTTYPE) || \
  46. (tod.iSubstFace) )
  47. #define ERROR_PER_GLYPH_POS 3
  48. #define ERROR_PER_ENUMERATION 15
  49. #define EROOR_PER_GLYPHRECT 5 // For Adjusting height of the glyph rect.
  50. /* NOTE: this must be the same as the winddi.h ENUMRECT */
  51. typedef struct
  52. {
  53. ULONG c; /* Number of rectangles returned */
  54. RECTL arcl[ RECT_LIMIT ]; /* Rectangles supplied */
  55. } MY_ENUMRECTS;
  56. /*
  57. * Local function prototypes.
  58. */
  59. VOID
  60. SelectTextColor(
  61. PDEV *pPDev,
  62. PVOID pvColor
  63. );
  64. VOID
  65. VClipIt(
  66. BYTE *pbClipBits,
  67. TO_DATA *ptod,
  68. CLIPOBJ *pco,
  69. STROBJ *pstro,
  70. int cGlyphs,
  71. int iRot,
  72. BOOL bPartialClipOn
  73. );
  74. BOOL
  75. BPSGlyphOut(
  76. register TO_DATA *pTOD
  77. );
  78. BOOL
  79. BRealGlyphOut(
  80. register TO_DATA *pTOD
  81. );
  82. BOOL
  83. BWhiteText(
  84. TO_DATA *pTOD
  85. );
  86. BOOL
  87. BDLGlyphOut(
  88. TO_DATA *pTOD
  89. );
  90. VOID
  91. VCopyAlign(
  92. BYTE *pjDest,
  93. BYTE *pjSrc,
  94. int cx,
  95. int cy
  96. );
  97. INT
  98. ISubstituteFace(
  99. PDEV *pPDev,
  100. FONTOBJ *pfo);
  101. HGLYPH
  102. HWideCharToGlyphHandle(
  103. PDEV *pPDev,
  104. FONTMAP *pFM,
  105. WCHAR wchOrg);
  106. PHGLYPH
  107. PhAllCharsPrintable(
  108. PDEV *pPDev,
  109. INT iSubst,
  110. ULONG ulGlyphs,
  111. PWCHAR pwchUnicode);
  112. BOOL
  113. BGetStartGlyphandCount(
  114. BYTE *pbClipBits,
  115. DWORD dwEndIndex,
  116. DWORD *pdwStartIndex,
  117. DWORD *pdwGlyphToPrint);
  118. BOOL
  119. BPrintTextAsGraphics(
  120. PDEV *pPDev,
  121. ULONG iSolidColor,
  122. DWORD dwForeColor,
  123. DWORD dwFlags,
  124. INT iSubstFace
  125. );
  126. BOOL
  127. FMTextOut(
  128. SURFOBJ *pso,
  129. STROBJ *pstro,
  130. FONTOBJ *pfo,
  131. CLIPOBJ *pco,
  132. RECTL *prclExtra,
  133. RECTL *prclOpaque,
  134. BRUSHOBJ *pboFore,
  135. BRUSHOBJ *pboOpaque,
  136. POINTL *pptlBrushOrg,
  137. MIX mix
  138. )
  139. /*++
  140. Routine Description:
  141. The call to use for output of text. Our behaviour depends
  142. upon the type of printer. Page printers (e.g. LaserJets) do
  143. whatever is required to send the relevant commands to the printer
  144. during this call. Otherwise (typified by dot matrix printers),
  145. we store the data about the glyph so that we can output the
  146. characters as we are rendering the bitmap. This allows the output
  147. to be printed unidirectionally DOWN the page.
  148. Arguments:
  149. pso; Surface to be drawn on
  150. pstro; The "string" to be produced
  151. pfo; The font to use
  152. pco; Clipping region to limit output
  153. prclExtra; Underline/strikethrough rectangles
  154. prclOpaque; Opaquing rectangle
  155. pboFore; Foreground brush object
  156. pboOpaque; Opaqueing brush
  157. pptlBrushOrg; Brush origin for both above brushes
  158. mix; The mix mode
  159. Return Value:
  160. TRUE for success and FALSE for failure.FALSE logs the error.
  161. Note:
  162. 1/16/1997 -ganeshp-
  163. Created it.
  164. --*/
  165. {
  166. PDEV *pPDev; // Our main PDEV
  167. FONTPDEV *pFontPDev; // FONTMODULE based PDEV
  168. FONTMAP *pfm; // Font's details
  169. GLYPHPOS *pgp, *pgpTmp; // Value passed from gre
  170. XFORMOBJ *pxo; // The transform of interest
  171. FLOATOBJ_XFORM xform;
  172. TO_DATA tod; // Our convenience
  173. RECTL rclRegion; // For z-ordering fixes
  174. HGLYPH *phSubstGlyphOrg, *phSubstGlyph;
  175. POINTL ptlRem;
  176. BOOL (*pfnDrawGlyph)( TO_DATA * ); // How to produce the glyph
  177. PFN_OEMTextOutAsBitmap pfnOEMTextOutAsBitmap = NULL;
  178. I_UNIFONTOBJ UFObj;
  179. ULONG iSolidColor;
  180. DWORD dwGlyphToPrint, dwTotalGlyph, dwPGPStartIndex, dwFlags;
  181. DWORD dwForeColor;
  182. INT iyAdjust; // Adjust for printing position WRT baseline
  183. INT iXInc, iYInc; // Glyph to glyph movement, if needed
  184. INT iRot; // The rotation factor
  185. INT iI, iJ, iStartIndex;
  186. WCHAR *pwchUnicode;
  187. BYTE *pbClipBits; // For clip limits
  188. BYTE ubMask;
  189. BOOL bMore; // Getting glyphs from engine loop
  190. BOOL bRet = FALSE; // Return Value.
  191. //
  192. // First step is to extract the PDEV address from the surface.
  193. // Then we can get to all the other bits & pieces that we need.
  194. // We should also initialize the TO_DATA as much as possible.
  195. //
  196. pPDev = (PDEV *) pso->dhpdev;
  197. if( !(VALID_PDEV(pPDev)) )
  198. {
  199. SetLastError( ERROR_INVALID_PARAMETER );
  200. ERR(( "Invalid or NULL PDEV\n" ))
  201. return FALSE;
  202. }
  203. //
  204. // Quick check on abort - should we return failure NOW
  205. //
  206. if( pPDev->fMode & PF_ABORTED )
  207. return FALSE;
  208. //
  209. // Misc initialization
  210. //
  211. dwFlags = 0;
  212. iRot = 0;
  213. pgp =
  214. pgpTmp = NULL;
  215. pfm = NULL;
  216. pbClipBits = NULL;
  217. phSubstGlyphOrg = NULL;
  218. //
  219. // Initialize TO_DATA
  220. //
  221. ZeroMemory(&tod, sizeof(TO_DATA));
  222. tod.pPDev = pPDev;
  223. tod.pfo = pfo;
  224. tod.flAccel= pstro->flAccel;
  225. pFontPDev = pPDev->pFontPDev; // The important stuff
  226. //
  227. // Initialize TT file pointer to NULL to avoid caching. TT File pointer
  228. // should be initialized per DrvTextOut. Also initialize the TOD pointer.
  229. // This is needed by download routines, which have access to PDEV only.
  230. //
  231. pFontPDev->pTTFile = NULL;
  232. pFontPDev->pcjTTFile = 0;
  233. pFontPDev->ptod = &tod;
  234. pFontPDev->pso = pso; // SURFOBJ changes every call - so reset
  235. pFontPDev->pIFI = FONTOBJ_pifi(pfo);
  236. if( pPDev->dwFreeMem && (pFontPDev->flFlags & FDV_TRACK_FONT_MEM) )
  237. pFontPDev->dwFontMem = pPDev->dwFreeMem;
  238. iSolidColor = pboFore->iSolidColor; // Local Copy.
  239. dwForeColor = BRUSHOBJ_ulGetBrushColor(pboFore);
  240. //
  241. //
  242. // Flag Initialization
  243. //
  244. //
  245. // Check if the printer can set the foreground color.This is necessary
  246. // to support grey or dithered device fonts.
  247. //
  248. if (pFontPDev->flFlags & FDV_SUPPORTS_FGCOLOR)
  249. dwFlags |= TXTOUT_FGCOLOR;
  250. if (DRIVER_DEVICEMANAGED (pPDev))
  251. dwFlags |= TXTOUT_DMS;
  252. //
  253. // Device managed surface has to send White text when it's received.Also
  254. // we don't need to do any Z-order specific checking.
  255. //
  256. if (!(dwFlags & TXTOUT_DMS))
  257. {
  258. BOOL bIsRegionW;
  259. //
  260. // Get rectangle for background checking - z-ordering fix
  261. //
  262. if ( !BIntersectRect(&rclRegion, &(pstro->rclBkGround),&(pco->rclBounds)))
  263. return TRUE;
  264. bIsRegionW = bIsRegionWhite(pso, &rclRegion);
  265. #ifndef DISABLE_NEWRULES
  266. //
  267. // if there is an opaque background or the text color is not black, we
  268. // need to test whether the text overlaps the rules array
  269. //
  270. if (bIsRegionW && pPDev->pbRulesArray && pPDev->dwRulesCount > 0)
  271. {
  272. PRECTL pTmpR = prclOpaque;
  273. if (!pTmpR &&
  274. ((pso->iBitmapFormat == BMF_24BPP ||
  275. iSolidColor != (ULONG)((PAL_DATA*)(pPDev->pPalData))->iBlackIndex) &&
  276. (pso->iBitmapFormat != BMF_24BPP ||
  277. iSolidColor != 0)))
  278. {
  279. pTmpR = &rclRegion;
  280. }
  281. if (pTmpR)
  282. {
  283. DWORD i;
  284. for (i = 0;i < pPDev->dwRulesCount;i++)
  285. {
  286. PRECTL pTmp = &pPDev->pbRulesArray[i];
  287. if (pTmp->right > pTmpR->left &&
  288. pTmp->left < pTmpR->right &&
  289. pTmp->bottom > pTmpR->top &&
  290. pTmp->top < pTmpR->bottom)
  291. {
  292. bIsRegionW = FALSE;
  293. break;
  294. }
  295. }
  296. }
  297. }
  298. #endif
  299. if (((ULONG)pFontPDev->iWhiteIndex == iSolidColor) && !bIsRegionW)
  300. dwFlags |= TXTOUT_CACHED;
  301. //
  302. // Z-ordering fix, check if we are not printing Text as graphics.
  303. //
  304. if (pFontPDev->flFlags & FDV_DLTT || pfo->flFontType & DEVICE_FONTTYPE)
  305. {
  306. //
  307. // If we are banding and this isn't a device font we want to
  308. // use EngTextOut if the textbox crosses a band boundary. This
  309. // is because the bIsRegionWhite test can't test the entire
  310. // region so it is invalid.
  311. //
  312. if ((pPDev->bBanding && !(pfo->flFontType & DEVICE_FONTTYPE) &&
  313. (rclRegion.left != pstro->rclBkGround.left ||
  314. rclRegion.right != pstro->rclBkGround.right ||
  315. rclRegion.bottom != pstro->rclBkGround.bottom ||
  316. (rclRegion.top != pstro->rclBkGround.top &&
  317. pPDev->rcClipRgn.top != 0))) ||
  318. !bIsRegionW)
  319. {
  320. dwFlags |= TXTOUT_COLORBK;
  321. }
  322. }
  323. }
  324. //
  325. // This is necessary because we map low intensity color to black
  326. // in palette management,
  327. // However, if we detect text and graphic overlapping, we map
  328. // low intensity color to white so it's visible over graphics
  329. //
  330. if ( pso->iBitmapFormat == BMF_4BPP &&
  331. dwFlags & TXTOUT_COLORBK)
  332. {
  333. if (pboFore->iSolidColor == 8)
  334. {
  335. iSolidColor = pFontPDev->iWhiteIndex;
  336. dwFlags |= TXTOUT_CACHED;
  337. }
  338. }
  339. //
  340. // Font substitution initialization
  341. //
  342. // Get iFace to substitute TrueType font with.
  343. // Note: pwszOrg is available only when SO_GLYPHINDEX_TEXTOUT is set
  344. // in pstro->flAccel.
  345. // SO_DO_NOT_SUBSTITUTE_DEVICE_FONT also has to be checked for BI-DI
  346. // fonts.
  347. //
  348. // We should now get the transform. This is only really needed
  349. // for a scalable font OR a printer which can do font rotations
  350. // relative to the graphics orientation (i.e. PCL5 printers!).
  351. // It is easier just to get the transform all the time.
  352. //
  353. pxo = FONTOBJ_pxoGetXform( pfo );
  354. XFORMOBJ_iGetFloatObjXform(pxo, &xform);
  355. pFontPDev->pxform = &xform;
  356. if (NO_ROTATION(xform))
  357. dwFlags |= TXTOUT_NOTROTATED;
  358. if (pFontPDev->pIFI->flInfo & FM_INFO_90DEGREE_ROTATIONS)
  359. dwFlags |= TXTOUT_90_ROTATION;
  360. tod.iSubstFace = 0;
  361. tod.phGlyph = NULL;
  362. pwchUnicode = NULL;
  363. tod.cGlyphsToPrint = pstro->cGlyphs;
  364. if (!(pstro->flAccel & SO_GLYPHINDEX_TEXTOUT))
  365. {
  366. pwchUnicode = pstro->pwszOrg;
  367. }
  368. //
  369. // Conditions to substitute:
  370. // The Text is not supposed to be printed as graphics and
  371. // Device can substitute font and
  372. // Font is True Type and
  373. // STROBJ flags have no conflict with substitution.
  374. //
  375. if ( (pfo->flFontType & TRUETYPE_FONTTYPE) &&
  376. !(pstro->flAccel & ( SO_GLYPHINDEX_TEXTOUT |
  377. SO_DO_NOT_SUBSTITUTE_DEVICE_FONT)) )
  378. {
  379. INT iSubstFace;
  380. if ((iSubstFace = ISubstituteFace(pPDev, pfo)) &&
  381. (phSubstGlyphOrg = PhAllCharsPrintable(pPDev,
  382. iSubstFace,
  383. pstro->cGlyphs,
  384. pwchUnicode)))
  385. {
  386. tod.iSubstFace = iSubstFace;
  387. }
  388. }
  389. //
  390. // Check if Text should be printed as graphics or not.
  391. //
  392. if( BPrintTextAsGraphics(pPDev, iSolidColor, dwForeColor, dwFlags, tod.iSubstFace) )
  393. {
  394. dwFlags |= TXTOUT_PRINTASGRX;
  395. tod.iSubstFace = 0;
  396. }
  397. //
  398. // Initialize for OEM Callback function
  399. // ulFontID
  400. // dwFlags
  401. // pIFIMetrics
  402. // pfnGetInfo
  403. // pFontObj
  404. // pStrObj
  405. // pFontMap
  406. // pFontPDev
  407. // ptGrxRes
  408. // pGlyph
  409. //
  410. if(pPDev->pOemHookInfo || (pPDev->ePersonality == kPCLXL))
  411. {
  412. ZeroMemory(&UFObj, sizeof(I_UNIFONTOBJ));
  413. UFObj.pfnGetInfo = UNIFONTOBJ_GetInfo;
  414. UFObj.pPDev = pPDev;
  415. UFObj.pFontObj = pfo;
  416. UFObj.pStrObj = pstro;
  417. UFObj.ptGrxRes = pPDev->ptGrxRes;
  418. UFObj.pIFIMetrics = pFontPDev->pIFI;
  419. if (tod.cGlyphsToPrint)
  420. UFObj.pGlyph = MemAlloc(sizeof(DWORD) * tod.cGlyphsToPrint);
  421. if (pfo &&
  422. !(pfo->flFontType & DEVICE_FONTTYPE) )
  423. {
  424. PFN_OEMTTDownloadMethod pfnOEMTTDownloadMethod;
  425. if (tod.iSubstFace == 0 &&
  426. ( (pPDev->pOemHookInfo &&
  427. (pfnOEMTTDownloadMethod = (PFN_OEMTTDownloadMethod)pPDev->pOemHookInfo[EP_OEMTTDownloadMethod].pfnHook))
  428. || (pPDev->ePersonality == kPCLXL))
  429. )
  430. {
  431. DWORD dwRet = TTDOWNLOAD_DONTCARE;
  432. HANDLE_VECTORPROCS(pPDev, VMTTDownloadMethod, ((PDEVOBJ)pPDev,
  433. (PUNIFONTOBJ)&UFObj,
  434. &dwRet))
  435. else
  436. if(pPDev->pOemEntry)
  437. {
  438. FIX_DEVOBJ(pPDev, EP_OEMTTDownloadMethod);
  439. if(((POEM_PLUGIN_ENTRY)pPDev->pOemEntry)->pIntfOem ) // OEM plug in uses COM and function is implemented.
  440. {
  441. HRESULT hr ;
  442. hr = HComTTDownloadMethod((POEM_PLUGIN_ENTRY)pPDev->pOemEntry,
  443. &pPDev->devobj, (PUNIFONTOBJ)&UFObj, &dwRet);
  444. if(SUCCEEDED(hr))
  445. ; // cool !
  446. }
  447. else
  448. {
  449. dwRet = pfnOEMTTDownloadMethod(&pPDev->devobj,
  450. (PUNIFONTOBJ)&UFObj);
  451. }
  452. }
  453. switch (dwRet)
  454. {
  455. case TTDOWNLOAD_GRAPHICS:
  456. case TTDOWNLOAD_DONTCARE:
  457. dwFlags |= TXTOUT_PRINTASGRX;
  458. break;
  459. //
  460. // A default is to download as bitmap.
  461. //
  462. case TTDOWNLOAD_BITMAP:
  463. UFObj.dwFlags |= UFOFLAG_TTDOWNLOAD_BITMAP | UFOFLAG_TTFONT;
  464. break;
  465. case TTDOWNLOAD_TTOUTLINE:
  466. UFObj.dwFlags |= UFOFLAG_TTDOWNLOAD_TTOUTLINE | UFOFLAG_TTFONT;
  467. break;
  468. }
  469. }
  470. }
  471. pFontPDev->pUFObj = &UFObj;
  472. }
  473. else
  474. {
  475. pFontPDev->pUFObj = NULL;
  476. }
  477. pPDev->fMode |= PF_DOWNLOADED_TEXT;
  478. //
  479. // Get FONTMAP
  480. //
  481. //
  482. // Conditions to download:
  483. // Text should not be printed as graphics and
  484. // Font should be TRUETYPE and
  485. // It is not getting substituted.
  486. //
  487. if ( !(dwFlags & TXTOUT_PRINTASGRX) &&
  488. (pfo->flFontType & TRUETYPE_FONTTYPE) &&
  489. !tod.iSubstFace )
  490. {
  491. //
  492. // This function sets pfm pointer and iFace in TO_DATA.
  493. // tod.iFace
  494. // tod.pfm
  495. //
  496. if (IDownloadFont(&tod, pstro, &iRot) >= 0)
  497. {
  498. pfm = tod.pfm;
  499. //
  500. // yAdj has to be added to tod.pgp->ptl.y
  501. //
  502. iyAdjust = pfm ? (int)(pfm->syAdj) : 0;
  503. }
  504. else
  505. {
  506. //
  507. // If the call fails call engine to draw.
  508. //
  509. pfm = NULL;
  510. }
  511. }
  512. if ( DEVICE_FONT(pfo, tod) ) // Device Font
  513. {
  514. if( pfo->iFace < 1 || (int)pfo->iFace > pPDev->iFonts )
  515. {
  516. SetLastError( ERROR_INVALID_PARAMETER );
  517. ERR(( "Invalid iFace (%ld) in DrvTextOut",pfo->iFace ));
  518. goto ErrorExit;
  519. }
  520. //
  521. // Get the stuff we really need for this font
  522. //
  523. tod.iFace = pfo->iFace;
  524. pfm = PfmGetDevicePFM(pPDev, tod.iSubstFace?tod.iSubstFace:tod.iFace);
  525. if (tod.iSubstFace)
  526. {
  527. UFObj.dwFlags |= UFOFLAG_TTSUBSTITUTED;
  528. ((FONTMAP_DEV*)pfm->pSubFM)->fwdFOAveCharWidth = pFontPDev->pIFI->fwdAveCharWidth;
  529. ((FONTMAP_DEV*)pfm->pSubFM)->fwdFOMaxCharInc = pFontPDev->pIFI->fwdMaxCharInc;
  530. ((FONTMAP_DEV*)pfm->pSubFM)->fwdFOUnitsPerEm = pFontPDev->pIFI->fwdUnitsPerEm;
  531. ((FONTMAP_DEV*)pfm->pSubFM)->fwdFOWinAscender = pFontPDev->pIFI->fwdWinAscender;
  532. }
  533. //
  534. // Deivce font PFM must be returned.
  535. //
  536. if (pfm == NULL)
  537. {
  538. SetLastError( ERROR_INVALID_PARAMETER );
  539. ERR(( "Invalid iFace (%ld) in DrvTextOut",pfo->iFace ));
  540. goto ErrorExit;
  541. }
  542. //
  543. // Set the transform for Device fonts.For downloaded fonts we have already
  544. // set the transform in download code. Check also for HP Intellifont
  545. //
  546. if ( DEVICE_FONT(pfo, tod) )
  547. {
  548. iRot = ISetScale( &pFontPDev->ctl,
  549. pxo,
  550. (( pfm->flFlags & FM_SCALABLE) &&
  551. (((PFONTMAP_DEV)pfm->pSubFM)->wDevFontType ==
  552. DF_TYPE_HPINTELLIFONT)),
  553. (pFontPDev->flText & TC_CR_ANY)?TRUE:FALSE);
  554. }
  555. }
  556. tod.iRot = iRot;
  557. UFObj.pFontMap = pfm;
  558. UFObj.apdlGlyph = tod.apdlGlyph;
  559. UFObj.dwNumInGlyphTbl = pstro->cGlyphs;
  560. //
  561. // TO_DATA initialization
  562. //
  563. tod.pfm = pfm;
  564. if (tod.iSubstFace)
  565. {
  566. BOOL bT2Bold, bT2Italic;
  567. BOOL bDevBold, bDevItalic, bUnderline;
  568. bT2Bold = (pFontPDev->pIFI->fsSelection & FM_SEL_BOLD) ||
  569. (pfo->flFontType & FO_SIM_BOLD);
  570. bT2Italic = (pFontPDev->pIFI->fsSelection & FM_SEL_ITALIC) ||
  571. (pfo->flFontType & FO_SIM_ITALIC);
  572. bDevBold = (pfm->pIFIMet->fsSelection & FM_SEL_BOLD) ||
  573. (pfm->pIFIMet->usWinWeight > FW_NORMAL);
  574. bDevItalic = (pfm->pIFIMet->fsSelection & FM_SEL_ITALIC) ||
  575. (pfm->pIFIMet->lItalicAngle != 0);
  576. bUnderline = ((pFontPDev->flFlags & FDV_UNDERLINE) && prclExtra)?FONTATTR_UNDERLINE:0;
  577. tod.dwAttrFlags =
  578. ((bT2Bold && !bDevBold)?FONTATTR_BOLD:0) |
  579. ((bT2Italic && !bDevItalic)?FONTATTR_ITALIC:0) |
  580. (bUnderline?FONTATTR_UNDERLINE:0) |
  581. FONTATTR_SUBSTFONT;
  582. }
  583. else
  584. tod.dwAttrFlags =
  585. ( ((pfo->flFontType & FO_SIM_BOLD)?FONTATTR_BOLD:0)|
  586. ((pfo->flFontType & FO_SIM_ITALIC)?FONTATTR_ITALIC:0)|
  587. (((pFontPDev->flFlags & FDV_UNDERLINE) && prclExtra)?FONTATTR_UNDERLINE:0)
  588. );
  589. //
  590. // If DEVICE_FONTTYPE not set, we are dealing with a GDI font. If
  591. // the printer can handle it, we should consider downloading the font
  592. // to make it a pseudo device font. If this is a heavily used font,
  593. // then printing will be MUCH faster.
  594. //
  595. // However there are some points to consider. Firstly, we need to
  596. // consider the available memory in the printer; little will be gained
  597. // by downloading a 72 point font, since there can only be a few
  598. // glyphs per page. Also, if the font is not black (or at least a
  599. // solid colour), then it cannot be treated as a downloaded font.
  600. //
  601. // If the font is TT and we are not doing font substitution,
  602. // then check for Conditions for not downloading, which are:
  603. //
  604. // GDI Font with no cache (DDI spec, iUniq == 0) or
  605. // Text should be printed as graphics or
  606. // The Text is white, Assume that there is some merged graphics or
  607. // iDownLoadFont fails and returns an invalid download index or
  608. // OEM font download callback doesn't support correct formats.
  609. //
  610. if ( !(DEVICE_FONT(pfo, tod)) &&
  611. ( (pfo->iUniq == 0) ||
  612. (dwFlags & TXTOUT_PRINTASGRX) ||
  613. ( pfm == NULL ) ||
  614. ( pPDev->pOemHookInfo &&
  615. pPDev->pOemHookInfo[EP_OEMTTDownloadMethod].pfnHook &&
  616. (UFObj.dwFlags & (UFOFLAG_TTDOWNLOAD_BITMAP |
  617. UFOFLAG_TTDOWNLOAD_TTOUTLINE)) == 0)
  618. )
  619. )
  620. {
  621. /*
  622. * GDI font, and either cannot or do not wish to download.
  623. * So, let the engine handle it!
  624. */
  625. PrintAsBitmap:
  626. if (!(dwFlags & TXTOUT_DMS)) // bitmap surface
  627. {
  628. CheckBitmapSurface(pso,&pstro->rclBkGround);
  629. #ifdef WINNT_40 //NT 4.0
  630. STROBJ_vEnumStart(pstro);
  631. #endif
  632. bRet = EngTextOut( pso,
  633. pstro,
  634. pfo,
  635. pco,
  636. prclExtra,
  637. prclOpaque,
  638. pboFore,
  639. pboOpaque,
  640. pptlBrushOrg,
  641. mix );
  642. }
  643. else
  644. HANDLE_VECTORPROCS_RET(pPDev, VMTextOutAsBitmap, bRet, (pso, pstro, pfo, pco, prclExtra, prclOpaque, pboFore, pboOpaque, pptlBrushOrg, mix))
  645. else
  646. {
  647. if ( pPDev->pOemHookInfo &&
  648. (pfnOEMTextOutAsBitmap = (PFN_OEMTextOutAsBitmap)
  649. pPDev->pOemHookInfo[EP_OEMTextOutAsBitmap].pfnHook))
  650. {
  651. bRet = FALSE;
  652. FIX_DEVOBJ(pPDev, EP_OEMTextOutAsBitmap);
  653. if(pPDev->pOemEntry)
  654. {
  655. if(((POEM_PLUGIN_ENTRY)pPDev->pOemEntry)->pIntfOem ) // OEM plug in uses COM and function is implemented.
  656. {
  657. HRESULT hr ;
  658. hr = HComTextOutAsBitmap((POEM_PLUGIN_ENTRY)pPDev->pOemEntry,
  659. pso,
  660. pstro,
  661. pfo,
  662. pco,
  663. prclExtra,
  664. prclOpaque,
  665. pboFore,
  666. pboOpaque,
  667. pptlBrushOrg,
  668. mix );
  669. if(SUCCEEDED(hr))
  670. bRet = TRUE ; // cool !
  671. }
  672. else
  673. {
  674. bRet = pfnOEMTextOutAsBitmap (pso,
  675. pstro,
  676. pfo,
  677. pco,
  678. prclExtra,
  679. prclOpaque,
  680. pboFore,
  681. pboOpaque,
  682. pptlBrushOrg,
  683. mix );
  684. }
  685. }
  686. }
  687. else
  688. bRet = FALSE;
  689. }
  690. goto ErrorExit;
  691. }
  692. //
  693. // Mark the scanlines to indicate the present of text, z-ordering fix
  694. //
  695. // returns BYTE
  696. //
  697. if (!(dwFlags & TXTOUT_DMS)) // bitmap surface
  698. {
  699. //
  700. // Mark the scanlines to indicate the present of text, z-ordering fix
  701. //
  702. ubMask = BGetMask(pPDev, &rclRegion);
  703. for (iI = rclRegion.top; iI < rclRegion.bottom ; iI++)
  704. {
  705. pPDev->pbScanBuf[iI] |= ubMask;
  706. }
  707. }
  708. /*
  709. * Serial printers (those requiring the text be fed out at the same
  710. * time as the raster data) are processed by storing all the text
  711. * at this time, then playing it back while rendering the bitamp.
  712. * THIS ALSO HAPPENS FOR WHITE TEXT, on those printers capable
  713. * of doing this. The difference is that the white text is played
  714. * back in one hit AFTER RENDERING THE BITMAP.
  715. */
  716. //
  717. // Realize the Color
  718. //
  719. if ((!(dwFlags & TXTOUT_DMS)) &&
  720. !(tod.pvColor = GSRealizeBrush(pPDev, pso, pboFore)) )
  721. {
  722. ERR(( "GSRealizeBrush Failed;Can't Realize the Color\n" ));
  723. goto ErrorExit;
  724. }
  725. //
  726. // Font selection
  727. //
  728. // Initialize pfnDrwaGlyph function pointer
  729. // pfnDrwaGlyph cound be
  730. // BPSGlyphOut -- Dot matrics
  731. // BWhiteText -- White character
  732. // BRealGlyphOut -- Device font output
  733. // BDLGlyphOut -- TrueType download font output
  734. //
  735. if( pFontPDev->flFlags & FDV_MD_SERIAL )
  736. {
  737. //
  738. // yAdj has to be added to tod.pgp->ptl.y
  739. // Device font could be scalable font so that iyAdjust calculation
  740. // has to be done after BNewFont.
  741. //
  742. iyAdjust = (int)pfm->syAdj + (int)((PFONTMAP_DEV)pfm->pSubFM)->sYAdjust;
  743. //
  744. // Dot matrix or white text on an LJ style printer
  745. //
  746. pfnDrawGlyph = BPSGlyphOut;
  747. //
  748. //For Serial printer White text is also interlaced.
  749. //
  750. dwFlags &= ~(TXTOUT_CACHED|TXTOUT_SETPOS); /* Assume position is set elsewhere */
  751. }
  752. else
  753. {
  754. /*
  755. * Page printer - e.g. LaserJet. If this is a font that we
  756. * have downloaded, then there is a specific output routine
  757. * to use. Using a downloaded font is rather tricky, as we need
  758. * to translate HGLYPHs to char index, or possibly bitblt the
  759. * bitmap to the page bitmap.
  760. */
  761. if( DEVICE_FONT(pfo, tod) )
  762. {
  763. if (dwFlags & TXTOUT_COLORBK)
  764. {
  765. /* Z-ordering fix, delay device font to the end */
  766. dwFlags |= TXTOUT_CACHED;
  767. }
  768. UFObj.ulFontID = ((PFONTMAP_DEV)pfm->pSubFM)->dwResID;
  769. pfnDrawGlyph = BRealGlyphOut;
  770. BNewFont(pPDev,
  771. tod.iSubstFace?tod.iSubstFace:tod.iFace,
  772. pfm,
  773. tod.dwAttrFlags);
  774. //
  775. // yAdj has to be added to tod.pgp->ptl.y
  776. // Device font could be scalable font so that iyAdjust calculation
  777. // has to be done after BNewFont.
  778. //
  779. iyAdjust = (int)pfm->syAdj + (int)((PFONTMAP_DEV)pfm->pSubFM)->sYAdjust;
  780. }
  781. else
  782. {
  783. //
  784. // GDI font (TrueType), so we will want print it. All the glyphs
  785. // are already downloaded. The font has already been selected by
  786. // IDownloadFont
  787. //
  788. pfnDrawGlyph = BDLGlyphOut;
  789. UFObj.ulFontID = pfm->ulDLIndex;
  790. }
  791. //
  792. // For DMS we don't want to not cache the text. So turn off
  793. // TXTOUT_CACHED flag.
  794. //
  795. if (dwFlags & TXTOUT_DMS)
  796. dwFlags &= ~TXTOUT_CACHED;
  797. //
  798. // For cached text always use BWhiteText as we need to send cached text
  799. // after the graphics.
  800. //
  801. if (dwFlags & TXTOUT_CACHED)
  802. {
  803. pfnDrawGlyph = BWhiteText;
  804. }
  805. dwFlags |= TXTOUT_SETPOS;
  806. }
  807. /*
  808. * Also set the colour - ignored if already set or irrelevant
  809. * We want to select the color only if we are not caching the text.
  810. * Cache text when we have white text or it's a serial printer
  811. */
  812. if (!((dwFlags & TXTOUT_DMS) || (dwFlags & TXTOUT_CACHED) ||
  813. (pFontPDev->flFlags & FDV_MD_SERIAL)))
  814. SelectTextColor( pPDev, tod.pvColor );
  815. //
  816. // Initialize iXInc and iYInc for SO_FLAG_DEFAULT_PLACEMENT
  817. //
  818. iXInc = iYInc = 0; /* We do nothing case */
  819. if( (pstro->flAccel & SO_FLAG_DEFAULT_PLACEMENT) && pstro->ulCharInc )
  820. {
  821. /*
  822. * We need to calculate the positions ourselves, as GDI has
  823. * become lazy to gain some speed - I guess.
  824. */
  825. if( pstro->flAccel & SO_HORIZONTAL )
  826. iXInc = pstro->ulCharInc;
  827. if( pstro->flAccel & SO_VERTICAL )
  828. iYInc = pstro->ulCharInc;
  829. if( pstro->flAccel & SO_REVERSED )
  830. {
  831. /* Going the other way! */
  832. iXInc = -iXInc;
  833. iYInc = -iYInc;
  834. }
  835. }
  836. //
  837. // Allocate GLYPHPOS structure.
  838. //
  839. pgp = MemAlloc(sizeof(GLYPHPOS) * pstro->cGlyphs);
  840. if (!pgp)
  841. {
  842. ERR(("pgp memory allocation failed\r\n"));
  843. goto ErrorExit;
  844. }
  845. //
  846. //
  847. // Allocate pbClipBits. size = cMaxGlyphs / BBITS
  848. //
  849. if (!(pbClipBits = MemAlloc((pstro->cGlyphs + BBITS - 1)/ BBITS)))
  850. {
  851. ERR(("pbClipBits memory allocation failed\r\n"));
  852. goto ErrorExit;
  853. }
  854. //
  855. // Start Glyph Enumuration
  856. //
  857. //
  858. // Enumuration
  859. //
  860. // (a) iStartIndex - phSubstGlyphOrg
  861. // (b) dwPGPStartIndex - pgp, pbClipBits, tod
  862. //
  863. // (pgp, pbClipBits)
  864. // |
  865. // | dwPGPStartIndex
  866. // | |
  867. // | v +Current point in the string.
  868. // | |
  869. // |<----->|
  870. // | |<----dwGlyphToPrint--->| |
  871. // v | v |
  872. // |-----------------------------+-------------------------------|
  873. // ^ |
  874. // |<-----iStartIndex--->|<------------dwTotalGlyph------------->|
  875. // |
  876. // phSubstGlyphOrg
  877. //
  878. iStartIndex = 0;
  879. tod.dwCurrGlyph = 0;
  880. tod.flFlags |= TODFL_FIRST_ENUMRATION;
  881. STROBJ_vEnumStart(pstro);
  882. do
  883. {
  884. #ifndef WINNT_40 //NT 5.0
  885. bMore = STROBJ_bEnumPositionsOnly( pstro, &dwTotalGlyph, &pgpTmp );
  886. #else // NT 4.0
  887. bMore = STROBJ_bEnum( pstro, &dwTotalGlyph, &pgpTmp );
  888. #endif //!WINNT_40
  889. CopyMemory(pgp, pgpTmp, sizeof(GLYPHPOS) * dwTotalGlyph);
  890. //
  891. // Set the first Glyph position in the TextOut data. This can be used
  892. // by Glyph Output functions to optimize.
  893. //
  894. tod.ptlFirstGlyph = pgp[0].ptl;
  895. //
  896. // Evaluate the position of the chars if this is needed.
  897. // SO_FLAG_DEFAULT_PLACEMENT case
  898. //
  899. if( iXInc || iYInc )
  900. {
  901. //
  902. // NT4.0 font support or GDI soft font
  903. //
  904. if ( !(pfo->flFontType & DEVICE_FONTTYPE) ||
  905. (pfm->flFlags & FM_IFIVER40) )
  906. {
  907. for( iI = 1; iI < (int)dwTotalGlyph; ++iI )
  908. {
  909. pgp[ iI ].ptl.x = pgp[ iI - 1 ].ptl.x + iXInc;
  910. pgp[ iI ].ptl.y = pgp[ iI - 1 ].ptl.y + iYInc;
  911. }
  912. }
  913. else
  914. //
  915. // NT5.0 device font support
  916. //
  917. {
  918. PMAPTABLE pMapTable;
  919. PTRANSDATA pTrans;
  920. pMapTable = GET_MAPTABLE(((PFONTMAP_DEV)pfm->pSubFM)->pvNTGlyph);
  921. pTrans = pMapTable->Trans;
  922. //
  923. // iXInc and iYInc are DBCS width when Far East charset.
  924. //
  925. for( iI = 1; iI < (int)dwTotalGlyph; ++iI )
  926. {
  927. if (pTrans[pgp[iI].hg - 1].ubType & MTYPE_SINGLE)
  928. {
  929. pgp[ iI ].ptl.x = pgp[ iI - 1 ].ptl.x + iXInc/2;
  930. pgp[ iI ].ptl.y = pgp[ iI - 1 ].ptl.y + iYInc;
  931. }
  932. else
  933. {
  934. pgp[ iI ].ptl.x = pgp[ iI - 1 ].ptl.x + iXInc;
  935. pgp[ iI ].ptl.y = pgp[ iI - 1 ].ptl.y + iYInc;
  936. }
  937. }
  938. }
  939. }
  940. //
  941. // Initialize the pgp in TextOut Data for Clipping.
  942. //
  943. tod.pgp = pgp;
  944. dwPGPStartIndex = 0;
  945. //
  946. // Check to see if there is any character at the boundary of clipping
  947. // rectangle.
  948. //
  949. VClipIt( pbClipBits, &tod, pco, pstro, dwTotalGlyph, iRot, pFontPDev->flFlags & FDV_ENABLE_PARTIALCLIP);
  950. //
  951. // If partial clipping has happend for TT font, call EngTextOut.
  952. //
  953. if (tod.flFlags & TODFL_TTF_PARTIAL_CLIPPING )
  954. {
  955. //
  956. // We have to use goto, but no other better way.
  957. //
  958. goto PrintAsBitmap;
  959. }
  960. //
  961. // Replace pgp's hg with Device font glyph handle
  962. //
  963. if (tod.iSubstFace)
  964. {
  965. tod.phGlyph =
  966. phSubstGlyph = phSubstGlyphOrg + iStartIndex;
  967. pgpTmp = pgp;
  968. for (iJ = 0; iJ < (INT)(int)dwTotalGlyph; iJ++, pgpTmp++)
  969. {
  970. pgpTmp->hg = *phSubstGlyph++;
  971. }
  972. }
  973. while ( dwTotalGlyph > dwPGPStartIndex )
  974. {
  975. //
  976. // Got the glyph data, so onto the real work!
  977. //
  978. if (BGetStartGlyphandCount(pbClipBits,
  979. dwTotalGlyph,
  980. &dwPGPStartIndex,
  981. &dwGlyphToPrint))
  982. {
  983. //VERBOSE(("dwTotalGlyph = %d\n", dwTotalGlyph));
  984. //VERBOSE(("dwGlyphToPrint = %d\n", dwGlyphToPrint));
  985. //VERBOSE(("dwPGPStartIndex = %d\n", dwPGPStartIndex));
  986. ASSERT((dwTotalGlyph > dwPGPStartIndex));
  987. tod.dwCurrGlyph = iStartIndex + dwPGPStartIndex;
  988. //
  989. // DCR: Add the Glyph position optimization call here.
  990. // If we are drawing Underline or strike through then disable
  991. // default placement optimization.
  992. //
  993. // if( prclExtra )
  994. // tod.flFlags &= ~TODFL_DEFAULT_PLACEMENT;
  995. if (dwFlags & TXTOUT_SETPOS)
  996. {
  997. //
  998. // Set initial position so that LaserJets can
  999. // use relative position. This is deferred until
  1000. // here because applications (e.g. Excel) start
  1001. // printing right off the edge of the page, and
  1002. // our position tracking code then needs to
  1003. // understand what the printer does about moving
  1004. // out of the printable area. This is too risky
  1005. // to be safe, so we save setting the position
  1006. // until we are in the printable region. Note
  1007. // that this assumes that the clipping data we
  1008. // have is limited to the printable region.
  1009. // I believe this to be true (16 June 1993).
  1010. //
  1011. //
  1012. // We need to handle the return value. Devices with
  1013. // resoloutions finer than their movement capability
  1014. // (like LBP-8 IV) get into a knot here , attempting
  1015. // to y-move on each glyph. We pretend we got where
  1016. // we wanted to be.
  1017. //
  1018. VSetCursor( pPDev,
  1019. pgp[dwPGPStartIndex].ptl.x,
  1020. pgp[dwPGPStartIndex].ptl.y+(iyAdjust?iyAdjust:0),
  1021. MOVE_ABSOLUTE,
  1022. &ptlRem);
  1023. pPDev->ctl.ptCursor.y += ptlRem.y;
  1024. VSetRotation( pFontPDev, iRot ); /* It's safe now */
  1025. //
  1026. // If the default placement is not set then we need to set
  1027. // the cursor for each enumration. So we clear the SETPOS
  1028. // flag only for default placement.
  1029. //
  1030. if ((pstro->flAccel & SO_FLAG_DEFAULT_PLACEMENT))
  1031. dwFlags &= ~TXTOUT_SETPOS;
  1032. //
  1033. // we set the cursor to forst glyph position. So set
  1034. // the TODFL_FIRST_GLYPH_POS_SET flag. Output function
  1035. // don't need to do a explicit move to this position.
  1036. //
  1037. tod.flFlags |= TODFL_FIRST_GLYPH_POS_SET;
  1038. }
  1039. tod.pgp = pgp + dwPGPStartIndex;
  1040. tod.cGlyphsToPrint = dwGlyphToPrint;
  1041. if ( iyAdjust )
  1042. {
  1043. for ( iI = 0; iI < (int)dwGlyphToPrint; iI ++)
  1044. tod.pgp[iI].ptl.y += iyAdjust;
  1045. }
  1046. if( !pfnDrawGlyph( &tod ) )
  1047. {
  1048. ERR(( "Glyph Drawing Failed;Can't draw the glyph\n" ));
  1049. goto ErrorExit;
  1050. }
  1051. }
  1052. else // None of the Glyphs are printable.
  1053. {
  1054. //
  1055. // If none of the glyphs are printable that update the counters
  1056. // to point to next run.
  1057. //
  1058. dwGlyphToPrint = dwTotalGlyph;
  1059. }
  1060. dwPGPStartIndex += dwGlyphToPrint;
  1061. }
  1062. iStartIndex += dwTotalGlyph;
  1063. //
  1064. // Clear the first enumartion flag, if more glyphs has to be enumerated.
  1065. //
  1066. if (bMore)
  1067. {
  1068. tod.flFlags &= ~TODFL_FIRST_ENUMRATION;
  1069. }
  1070. } while( bMore );
  1071. //
  1072. // Actual character printing. We may have enumurated once for downloading.
  1073. // So call STROBJ_vEnumStart here.
  1074. //
  1075. //
  1076. // Restore the normal graphics orientation by setting rotation to 0.
  1077. //
  1078. VSetRotation( pFontPDev, 0 );
  1079. /*
  1080. * Do the rectangles. If present, these are defined by prclExtra.
  1081. * Typically these are used for strikethrough and underline.
  1082. */
  1083. if( prclExtra )
  1084. {
  1085. if (!DRIVER_DEVICEMANAGED (pPDev) && // If not device managed surface
  1086. !(pFontPDev->flFlags & FDV_UNDERLINE))
  1087. {
  1088. /* prclExtra is an array of rectangles; we loop through them
  1089. * until we find one where all 4 points are 0.engine does not
  1090. * follow the spec - only sets x coords to 0.
  1091. */
  1092. while( prclExtra->left != prclExtra->right &&
  1093. prclExtra->bottom != prclExtra->top )
  1094. {
  1095. /* Use the engine's Bitblt function to draw the rectangles.
  1096. * last parameter is 0 for black!!
  1097. */
  1098. CheckBitmapSurface(pso,prclExtra);
  1099. if( !EngBitBlt( pso, NULL, NULL, pco, NULL, prclExtra, NULL, NULL,
  1100. pboFore, pptlBrushOrg, 0 ) )
  1101. {
  1102. ERR(( "EngBitBlt Failed;Can't draw rectangle simulations\n" ));
  1103. goto ErrorExit;
  1104. }
  1105. ++prclExtra;
  1106. }
  1107. }
  1108. }
  1109. //
  1110. // Set the dwFreeMem in PDEV
  1111. //
  1112. if( pPDev->dwFreeMem && (pFontPDev->flFlags & FDV_TRACK_FONT_MEM) )
  1113. {
  1114. pPDev->dwFreeMem = pFontPDev->dwFontMem - pFontPDev->dwFontMemUsed;
  1115. pFontPDev->dwFontMemUsed = 0;
  1116. }
  1117. bRet = TRUE;
  1118. //
  1119. // Free pbClipBits
  1120. //
  1121. ErrorExit:
  1122. //
  1123. // In case of white text, BPlayWhite text must free the pgp.
  1124. //
  1125. if (pgp)
  1126. MemFree(pgp);
  1127. if (pbClipBits)
  1128. MemFree(pbClipBits);
  1129. if (phSubstGlyphOrg)
  1130. MemFree(phSubstGlyphOrg);
  1131. MEMFREEANDRESET(tod.apdlGlyph );
  1132. VUFObjFree(pFontPDev);
  1133. pFontPDev->ptod = NULL;
  1134. pFontPDev->pIFI = NULL;
  1135. pFontPDev->pUFObj = NULL;
  1136. return bRet;
  1137. }
  1138. BOOL
  1139. BPrintTextAsGraphics(
  1140. PDEV *pPDev,
  1141. ULONG iSolidColor,
  1142. DWORD dwForeColor,
  1143. DWORD dwFlags,
  1144. INT iSubstFace
  1145. )
  1146. /*++
  1147. Routine Description:
  1148. This routine checks the textout flag for printing text as graphics.
  1149. Arguments:
  1150. pPDev PDEV struct.
  1151. dwFlags TextOut Flags
  1152. Return Value:
  1153. TRUE if text should be printed as graphics else FALSE
  1154. Note:
  1155. 10/9/1997 -ganeshp-
  1156. Created it.
  1157. --*/
  1158. {
  1159. FONTPDEV *pFontPDev; // FONTMODULE based PDEV
  1160. //
  1161. // Local initialization.
  1162. //
  1163. pFontPDev = pPDev->pFontPDev;
  1164. //
  1165. // DMS
  1166. //
  1167. if (pPDev->ePersonality == kPCLXL)
  1168. {
  1169. return FALSE;
  1170. }
  1171. //
  1172. // Condition to print as graphics:
  1173. // No substitution and Download option is FALSE in bitmap mode .
  1174. //
  1175. if ( (!iSubstFace && !(pFontPDev->flFlags & FDV_DLTT)) ||
  1176. //
  1177. // Font is rotated.
  1178. //
  1179. !(dwFlags & TXTOUT_NOTROTATED) ||
  1180. //
  1181. // TXTOUT_COLORBK says that there is a color background. Merging with
  1182. // Graphics. For non DMS case.
  1183. //
  1184. (dwFlags & TXTOUT_COLORBK) ||
  1185. //
  1186. // Color is non Primary color or Model doesn't supports programmable
  1187. // foreground Color
  1188. //
  1189. // Print text as graphics, if device doesn't support programable
  1190. // foreground color and the color of text is dithered and not black.
  1191. //
  1192. (!(dwFlags & TXTOUT_FGCOLOR) &&
  1193. iSolidColor == DITHERED_COLOR &&
  1194. (0x00FFFFFF & dwForeColor) != 0x00000000) ||
  1195. //
  1196. // Disable substitution of device font for TrueType, if device does't
  1197. // support programable foreground color and color is not black.
  1198. //
  1199. (iSubstFace &&
  1200. !(dwFlags & TXTOUT_FGCOLOR) &&
  1201. (0x00FFFFFF & dwForeColor) != 0x00000000)
  1202. )
  1203. {
  1204. return TRUE;
  1205. }
  1206. else
  1207. return FALSE;
  1208. }
  1209. //
  1210. // pfnDrawGlyph functions
  1211. // BDLGlyphOut
  1212. // BWhiteText
  1213. // BRealGlyphOut
  1214. // BDLGGlyphOut
  1215. //
  1216. BOOL
  1217. BDLGlyphOut(
  1218. TO_DATA *pTOD
  1219. )
  1220. /*++
  1221. Routine Description:
  1222. Function to process a glyph for a GDI font we have downloaded. We
  1223. either treat this as a normal character if this glyph has been
  1224. downloaded, or BitBlt it to the page bitmap if it is one we did
  1225. not download.
  1226. Arguments:
  1227. pTOD Textout Data. Holds all necessary information.
  1228. Return Value:
  1229. TRUE for success and FALSE for failure
  1230. Note:
  1231. 1/21/1997 -ganeshp-
  1232. Created it.
  1233. --*/
  1234. {
  1235. BOOL bRet;
  1236. FONTMAP *pFM;
  1237. bRet = FALSE;
  1238. if ( pFM = pTOD->pfm)
  1239. {
  1240. //
  1241. // Check if the glyphout fucntions pointer is not null and then call
  1242. // the function. We also have to check the return value. The fmtxtout
  1243. // function assumes that the Glyphout fucntion will print all the
  1244. // glyphs it requested to print i.e pTOD->cGlyphsToPrint should be
  1245. // equal to return value of pFM->pfnGlyphOut.
  1246. //
  1247. if ( pFM->pfnGlyphOut )
  1248. {
  1249. DWORD dwGlyphPrinted;
  1250. dwGlyphPrinted = pFM->pfnGlyphOut(pTOD);
  1251. if (dwGlyphPrinted != pTOD->cGlyphsToPrint)
  1252. {
  1253. ERR(("UniFont!BDLGlyphOut:pfnGlyphOut didn't print all glyphs\n"));
  1254. }
  1255. else
  1256. bRet = TRUE;
  1257. }
  1258. else
  1259. {
  1260. ERR(("UniFont!BDLGlyphOut:pFM->pfnGlyphOut is NULL\n"));
  1261. }
  1262. }
  1263. else
  1264. {
  1265. ERR(("UniFont!BDLGlyphOut:pTOD->pfm is NULL, Can't do glyphout\n"));
  1266. }
  1267. return bRet;
  1268. }
  1269. BOOL
  1270. BRealGlyphOut(
  1271. register TO_DATA *pTOD
  1272. )
  1273. /*++
  1274. Routine Description:
  1275. Print this glyph on the printer, at the given position. Unlike
  1276. bPSGlyphOut, the data is actually spooled for output now, since this
  1277. function is used for things like LaserJets, i.e. page printers.
  1278. Arguments:
  1279. pTOD Textout Data. Holds all necessary information.
  1280. Return Value:
  1281. TRUE for success and FALSE for failure
  1282. Note:
  1283. 1/21/1997 -ganeshp-
  1284. Created it.
  1285. --*/
  1286. {
  1287. //
  1288. // All we need to do is set the Y position, then call bOutputGlyph
  1289. // to do the actual work.
  1290. //
  1291. PDEV *pPDev;
  1292. PGLYPHPOS pgp; // Glyph positioning info
  1293. DWORD dwGlyph;
  1294. INT iX,iY; // Calculate real position
  1295. BOOL bRet;
  1296. ASSERTMSG(pTOD->pfm->pfnGlyphOut, ("NULL GlyphOut Funtion Ptr\n"));
  1297. pPDev = pTOD->pPDev;
  1298. pgp = pTOD->pgp;
  1299. dwGlyph = pTOD->cGlyphsToPrint;
  1300. if (pTOD->pfm->pfnGlyphOut)
  1301. {
  1302. pTOD->pfm->pfnGlyphOut( pTOD );
  1303. bRet = TRUE;
  1304. }
  1305. else
  1306. {
  1307. ASSERTMSG(FALSE,("NULL GlyphOut function pointer\n"));
  1308. bRet = FALSE;
  1309. }
  1310. return bRet;
  1311. }
  1312. BOOL
  1313. BWhiteText(
  1314. TO_DATA *pTOD
  1315. )
  1316. /*++
  1317. Routine Description:
  1318. Called to store details of the white text. Basically the data is
  1319. stored away until it is time to send it to the printer. That time
  1320. is AFTER the graphics data has been sent.
  1321. Arguments:
  1322. pTOD Textout Data. Holds all necessary information.
  1323. Return Value:
  1324. TRUE for success and FALSE for failure
  1325. Note:
  1326. 1/21/1997 -ganeshp-
  1327. Created it.
  1328. --*/
  1329. {
  1330. WHITETEXT *pWT, *pWTLast;
  1331. FONTCTL FontCtl;
  1332. FONTPDEV* pFontPDev;
  1333. DWORD dwWhiteTextAlign;
  1334. DWORD dwIFIAlign;
  1335. BOOL bRet;
  1336. pFontPDev = pTOD->pPDev->pFontPDev; // The important stuff
  1337. //
  1338. // Note that we allocate a new one of these for each
  1339. // iteration of this loop - that would be slightly wasteful
  1340. // if we ever executed this loop more than once, but that
  1341. // is unlikely.
  1342. //
  1343. pWT = NULL;
  1344. //
  1345. // 64 bit align.
  1346. //
  1347. dwWhiteTextAlign = (sizeof(WHITETEXT) + 7) / 8 * 8;
  1348. dwIFIAlign = (pFontPDev->pIFI->cjThis + 7) / 8 * 8;
  1349. if ( (pWT = (WHITETEXT *)MemAllocZ(dwWhiteTextAlign + dwIFIAlign +
  1350. pTOD->cGlyphsToPrint * sizeof(GLYPHPOS))))
  1351. {
  1352. pWT->next = NULL;
  1353. pWT->sCount = (SHORT)pTOD->cGlyphsToPrint;
  1354. pWT->iFontId = pTOD->iSubstFace?pTOD->iSubstFace:pTOD->iFace;
  1355. pWT->pvColor = pTOD->pvColor;
  1356. pWT->dwAttrFlags = pTOD->dwAttrFlags;
  1357. pWT->flAccel = pTOD->flAccel;
  1358. pWT->rcClipRgn = pTOD->pPDev->rcClipRgn;
  1359. pWT->iRot = pTOD->iRot;
  1360. pWT->eXScale = pFontPDev->ctl.eXScale;
  1361. pWT->eYScale = pFontPDev->ctl.eYScale;
  1362. pWT->pIFI = (IFIMETRICS*)((PBYTE)pWT + dwWhiteTextAlign);
  1363. CopyMemory(pWT->pIFI, pFontPDev->pIFI, pFontPDev->pIFI->cjThis);
  1364. pWT->pgp = (GLYPHPOS *)((PBYTE)pWT->pIFI + dwIFIAlign);
  1365. CopyMemory(pWT->pgp, pTOD->pgp, pWT->sCount * sizeof(GLYPHPOS));
  1366. //
  1367. // True Type Font download case
  1368. //
  1369. if ( (pTOD->pfo->flFontType & TRUETYPE_FONTTYPE) &&
  1370. (pTOD->iSubstFace == 0) )
  1371. {
  1372. //
  1373. // We need to copy the download glyph array.Allocate the array
  1374. // for DLGLYPHs.
  1375. //
  1376. if (!(pWT->apdlGlyph = MemAllocZ( pWT->sCount * sizeof(DLGLYPH *))))
  1377. {
  1378. ERR(("UniFont:BWhiteText: MemAlloc for pWT->apdlGlyph failed\n"));
  1379. goto ErrorExit;
  1380. }
  1381. CopyMemory( pWT->apdlGlyph, &(pTOD->apdlGlyph[pTOD->dwCurrGlyph]),
  1382. pWT->sCount * sizeof(DLGLYPH *) );
  1383. }
  1384. //
  1385. // Put new text at the end of the list
  1386. //
  1387. if (!(pFontPDev->pvWhiteTextFirst))
  1388. pFontPDev->pvWhiteTextFirst = pWT;
  1389. if (pWTLast = (WHITETEXT *)pFontPDev->pvWhiteTextLast)
  1390. pWTLast->next = pWT;
  1391. pFontPDev->pvWhiteTextLast = pWT;
  1392. bRet = TRUE;
  1393. }
  1394. else
  1395. {
  1396. ErrorExit:
  1397. ERR(( "MemAlloc failed for white text.\n" ));
  1398. bRet = FALSE;
  1399. }
  1400. return bRet;
  1401. }
  1402. BOOL
  1403. BPSGlyphOut(
  1404. register TO_DATA *pTOD
  1405. )
  1406. /*++
  1407. Routine Description:
  1408. Places glyphs for dot matrix type printers. These actually store
  1409. the position and glyph data for later printing. This is because
  1410. dot matrix printers cannot or should not reverse line feed -
  1411. for positioning accuracy. Hence, play the data back when the
  1412. bitmap is being rendered to the printer. Output occurs in the
  1413. following function, bDelayGlyphOut.
  1414. Arguments:
  1415. pTOD Textout Data. Holds all necessary information.
  1416. Return Value:
  1417. TRUE/FALSE. FALSE if the glyph storage fails.
  1418. Note:
  1419. 1/21/1997 -ganeshp-
  1420. Created it.
  1421. --*/
  1422. {
  1423. PGLYPHPOS pgp; // Glyph positioning info
  1424. PSGLYPH psg; // Data to store away
  1425. PFONTPDEV pFontPDev;
  1426. DWORD dwGlyph;
  1427. SHORT sFontIndex;
  1428. INT iyVal;
  1429. pFontPDev = (PFONTPDEV)pTOD->pPDev->pFontPDev;
  1430. pgp = pTOD->pgp;
  1431. dwGlyph = pTOD->cGlyphsToPrint;
  1432. /*
  1433. * About all that is needed is to take the parameters, store in
  1434. * a PSGLYPH structure, and call bAddPS to add this glyph to the list.
  1435. */
  1436. sFontIndex = pTOD->iSubstFace?pTOD->iSubstFace:pTOD->iFace;
  1437. //
  1438. // Scalable font support
  1439. //
  1440. psg.eXScale = pFontPDev->ctl.eXScale;
  1441. psg.eYScale = pFontPDev->ctl.eYScale;
  1442. while (dwGlyph--)
  1443. {
  1444. //
  1445. // Transform the input X and Y from band corrdnate to page coordinate.
  1446. //
  1447. if (pTOD->pPDev->bBanding)
  1448. {
  1449. psg.ixVal = pgp->ptl.x + pTOD->pPDev->rcClipRgn.left;
  1450. iyVal = pgp->ptl.y + pTOD->pPDev->rcClipRgn.top;
  1451. }
  1452. else
  1453. {
  1454. psg.ixVal = pgp->ptl.x;
  1455. iyVal = pgp->ptl.y;
  1456. }
  1457. psg.hg = pgp->hg;
  1458. psg.sFontIndex = sFontIndex;
  1459. psg.pvColor = pTOD->pvColor; // Which colour
  1460. psg.dwAttrFlags = pTOD->dwAttrFlags;
  1461. psg.flAccel = pTOD->flAccel;
  1462. if ( BAddPS( ((PFONTPDEV)(pTOD->pPDev->pFontPDev))->pPSHeader,
  1463. &psg,
  1464. iyVal,
  1465. ((FONTMAP_DEV *)(pTOD->pfm->pSubFM))->fwdFOWinAscender) )
  1466. {
  1467. pgp ++;
  1468. }
  1469. else // Failure, So fail the call.
  1470. {
  1471. ERR(( "\nUniFont!BPSGlyphOut: BAddPS Failed.\n" ))
  1472. return FALSE;
  1473. }
  1474. }
  1475. return TRUE;
  1476. }
  1477. //
  1478. // Delay and White test printing entry points
  1479. //
  1480. BOOL
  1481. BPlayWhiteText(
  1482. PDEV *pPDev
  1483. )
  1484. /*++
  1485. Routine Description:
  1486. Arguments:
  1487. pPDev Pointer to PDEV
  1488. Return Value:
  1489. TRUE for success and FALSE for failure
  1490. Note:
  1491. 1/21/1997 -ganeshp-
  1492. Created it.
  1493. --*/
  1494. {
  1495. I_UNIFONTOBJ UFObj;
  1496. FONTPDEV *pFontPDev; /* Miscellaneous uses */
  1497. WHITETEXT *pwt;
  1498. TO_DATA Tod;
  1499. GLYPHPOS *pgp;
  1500. RECTL rcClipRgnOld;
  1501. DWORD dwGlyphCount;
  1502. BOOL bRet = TRUE;
  1503. //
  1504. // Save the Clip rectangle.
  1505. //
  1506. rcClipRgnOld = pPDev->rcClipRgn;
  1507. /*
  1508. * Loop through the linked list of these hanging off the PDEV.
  1509. * Mostly, of course, there will be none.
  1510. */
  1511. pFontPDev = pPDev->pFontPDev;
  1512. pFontPDev->ptod = &Tod;
  1513. ZeroMemory(&Tod, sizeof(TO_DATA));
  1514. ZeroMemory(&UFObj, sizeof(I_UNIFONTOBJ));
  1515. dwGlyphCount = 0;
  1516. pPDev->ctl.dwMode |= MODE_BRUSH_RESET_COLOR;
  1517. GSResetBrush(pPDev);
  1518. for( pwt = pFontPDev->pvWhiteTextFirst; pwt && bRet; pwt = pwt->next )
  1519. {
  1520. int iI; /* Loop index */
  1521. int iRot; /* Rotation amount */
  1522. FONTMAP *pfm;
  1523. /*
  1524. * Not too hard - we know we are dealing with device fonts,
  1525. * and that this is NOT a serial printer, although we could
  1526. * probably handle that too. Hence, all we need do is fill in
  1527. * a TO_DATA structure, and loop through the glyphs we have.
  1528. */
  1529. if( pwt->sCount < 1 )
  1530. continue; /* No data, so skip it */
  1531. Tod.pPDev = pPDev;
  1532. Tod.flAccel = pwt->flAccel;
  1533. Tod.dwAttrFlags = pwt->dwAttrFlags;
  1534. pgp = Tod.pgp = pwt->pgp;
  1535. Tod.cGlyphsToPrint = pwt->sCount;
  1536. if (pwt->dwAttrFlags & FONTATTR_SUBSTFONT)
  1537. {
  1538. Tod.iSubstFace = pwt->iFontId;
  1539. UFObj.dwFlags |= UFOFLAG_TTSUBSTITUTED;
  1540. }
  1541. else
  1542. {
  1543. Tod.iSubstFace = 0;
  1544. UFObj.dwFlags &= ~UFOFLAG_TTSUBSTITUTED;
  1545. }
  1546. Tod.pfm =
  1547. pfm = PfmGetIt( pPDev, pwt->iFontId );
  1548. if (NULL == pfm)
  1549. {
  1550. //
  1551. // Fatal error, PFM is not available.
  1552. //
  1553. continue;
  1554. }
  1555. //
  1556. // The glyph positions are wrt banding rect, so set the PDEV clip region
  1557. // to the recorded clip region.
  1558. //
  1559. pPDev->rcClipRgn = pwt->rcClipRgn;
  1560. //
  1561. // Set the download glyph array for True type downloaded fonts.
  1562. //
  1563. if (pwt->apdlGlyph)
  1564. {
  1565. Tod.apdlGlyph = pwt->apdlGlyph;
  1566. Tod.dwCurrGlyph = 0;
  1567. }
  1568. /*
  1569. * Before switching fonts, and ESPECIALLY before setting the
  1570. * font rotation, we should move to the starting position of
  1571. * the string. Then we can set the rotation and use relative
  1572. * moves to position the characters.
  1573. */
  1574. if(pPDev->pOemHookInfo)
  1575. {
  1576. // ulFontID
  1577. // dwFlags
  1578. // pIFIMetrics
  1579. // pfnGetInfo
  1580. // pFontObj X (set to NULL)
  1581. // pStrObj X (set to NULL)
  1582. // pFontPDev
  1583. // pFontMap
  1584. // ptGrxRes
  1585. // pGlyph
  1586. if (pfm->dwFontType == FMTYPE_DEVICE)
  1587. {
  1588. UFObj.ulFontID = ((PFONTMAP_DEV)pfm->pSubFM)->dwResID;
  1589. }
  1590. else
  1591. {
  1592. UFObj.dwFlags = UFOFLAG_TTFONT;
  1593. UFObj.ulFontID = pfm->ulDLIndex;
  1594. }
  1595. if (Tod.cGlyphsToPrint)
  1596. {
  1597. if (UFObj.pGlyph != NULL && dwGlyphCount < Tod.cGlyphsToPrint)
  1598. {
  1599. MemFree(UFObj.pGlyph);
  1600. UFObj.pGlyph = NULL;
  1601. dwGlyphCount = 0;
  1602. }
  1603. if (UFObj.pGlyph == NULL)
  1604. {
  1605. UFObj.pGlyph = MemAlloc(sizeof(DWORD) * Tod.cGlyphsToPrint);
  1606. dwGlyphCount = Tod.cGlyphsToPrint;
  1607. }
  1608. }
  1609. if (pwt->dwAttrFlags & FONTATTR_SUBSTFONT)
  1610. {
  1611. //
  1612. // In the substitution case, UNIDRV needs to pass TrueType font
  1613. // IFIMETRICS to minidriver.
  1614. //
  1615. UFObj.pIFIMetrics = pwt->pIFI;
  1616. }
  1617. else
  1618. {
  1619. UFObj.pIFIMetrics = pfm->pIFIMet;
  1620. }
  1621. UFObj.pfnGetInfo = UNIFONTOBJ_GetInfo;
  1622. UFObj.pPDev = pPDev;
  1623. UFObj.pFontMap = pfm;
  1624. UFObj.ptGrxRes = pPDev->ptGrxRes;
  1625. if (pwt->apdlGlyph)
  1626. {
  1627. UFObj.apdlGlyph = Tod.apdlGlyph;
  1628. UFObj.dwNumInGlyphTbl = pwt->sCount;
  1629. }
  1630. else
  1631. {
  1632. UFObj.apdlGlyph = NULL;
  1633. UFObj.dwNumInGlyphTbl = 0;
  1634. }
  1635. pFontPDev->pUFObj = &UFObj;
  1636. }
  1637. else
  1638. pFontPDev->pUFObj = NULL;
  1639. //
  1640. // If this is a new font, it's time to change it now.
  1641. // BNewFont() checkes to see if a new font is needed.
  1642. //
  1643. pFontPDev->ctl.eXScale = pwt->eXScale;
  1644. pFontPDev->ctl.eYScale = pwt->eYScale;
  1645. BNewFont(pPDev, pwt->iFontId, pfm, pwt->dwAttrFlags);
  1646. VSetRotation( pFontPDev, pwt->iRot );
  1647. /* Also set the colour - ignored if already set or irrelevant */
  1648. SelectTextColor( pPDev, pwt->pvColor );
  1649. ASSERTMSG(pfm->pfnGlyphOut, ("NULL GlyphOut Funtion Ptr\n"));
  1650. if( !pfm->pfnGlyphOut( &Tod))
  1651. {
  1652. bRet = FALSE;
  1653. break;
  1654. }
  1655. VSetRotation( pFontPDev, 0 ); /* For MoveTo calls */
  1656. //
  1657. // Reset TODFL_FIRST_GLYPH_POS_SET so that the cursor is set next time.
  1658. //
  1659. Tod.flFlags &= ~TODFL_FIRST_GLYPH_POS_SET;
  1660. }
  1661. VSetRotation( pFontPDev, 0 ); /* Back to normal */
  1662. //
  1663. // Cleanup everything.
  1664. //
  1665. {
  1666. WHITETEXT *pwt0, *pwt1;
  1667. for( pwt0 = pFontPDev->pvWhiteTextFirst; pwt0; pwt0 = pwt1 )
  1668. {
  1669. pwt1 = pwt0->next;
  1670. //Free the download glyph array.
  1671. if (pwt0->apdlGlyph)
  1672. MemFree( pwt0->apdlGlyph );
  1673. MemFree( pwt0 );
  1674. }
  1675. pFontPDev->pvWhiteTextFirst =
  1676. pFontPDev->pvWhiteTextLast = NULL;
  1677. VUFObjFree(pFontPDev);
  1678. }
  1679. //
  1680. // Restore the Clip rectangle.
  1681. //
  1682. pPDev->rcClipRgn = rcClipRgnOld;
  1683. return TRUE;
  1684. }
  1685. BOOL
  1686. BDelayGlyphOut(
  1687. PDEV *pPDev,
  1688. INT yPos
  1689. )
  1690. /*++
  1691. Routine Description:
  1692. Called during output to a dot matrix printer. We are passed the
  1693. PSGLYPH data stored above, and go about placing the characters
  1694. on the line.
  1695. Arguments:
  1696. pPDev Pointer to PDEV
  1697. yPos Y coordinate of interest
  1698. Return Value:
  1699. TRUE for success and FALSE for failure
  1700. Note:
  1701. 1/21/1997 -ganeshp-
  1702. Created it.
  1703. --*/
  1704. {
  1705. BOOL bRet; /* Return value */
  1706. PSHEAD *pPSH; /* Base data for glyph info */
  1707. PSGLYPH *ppsg; /* Details of the GLYPH to print */
  1708. FONTMAP *pFM; /* Base address of FONTMAP array */
  1709. FONTPDEV *pFontPDev; /* FM's PDEV - for our convenience */
  1710. I_UNIFONTOBJ UFObj;
  1711. TO_DATA Tod;
  1712. GLYPHPOS gp;
  1713. ASSERT(pPDev);
  1714. /*
  1715. * Check to see if there are any glyphs for this Y position. If so,
  1716. * loop through each glyph, calling the appropriate output function
  1717. * as we go.
  1718. */
  1719. pFontPDev = PFDV; /* UNIDRV data */
  1720. pFontPDev->ptod = &Tod;
  1721. pPSH = pFontPDev->pPSHeader;
  1722. bRet = TRUE; /* Until proven otherwise */
  1723. /* No Glyph Queue, so return. Check if there are device fonts? */
  1724. if(pPDev->iFonts && !pPSH)
  1725. {
  1726. ASSERT(FALSE);
  1727. return FALSE;
  1728. }
  1729. Tod.pPDev = pPDev;
  1730. Tod.pgp = &gp;
  1731. Tod.iSubstFace = 0;
  1732. Tod.cGlyphsToPrint = 1;
  1733. //
  1734. // Check if a minidriver supports OEM plugin.
  1735. //
  1736. if(pPDev->pOemHookInfo)
  1737. {
  1738. ZeroMemory(&UFObj, sizeof(I_UNIFONTOBJ));
  1739. UFObj.pfnGetInfo = UNIFONTOBJ_GetInfo;
  1740. UFObj.pPDev = pPDev;
  1741. UFObj.dwFlags = 0;
  1742. UFObj.ptGrxRes = pPDev->ptGrxRes;
  1743. UFObj.pGlyph = MemAlloc(sizeof(DWORD) * Tod.cGlyphsToPrint);
  1744. UFObj.apdlGlyph = NULL;
  1745. UFObj.dwNumInGlyphTbl = 0;
  1746. pFontPDev->pUFObj = &UFObj;
  1747. }
  1748. else
  1749. pFontPDev->pUFObj = NULL;
  1750. //
  1751. // Actual print out
  1752. //
  1753. if( pPSH && ISelYValPS( pPSH, yPos ) > 0 )
  1754. {
  1755. /*
  1756. * Got some, so first set the Y position, so that the glyphs
  1757. * will appear on the correct line!
  1758. */
  1759. gp.ptl.y = yPos - pPDev->rcClipRgn.top;
  1760. //
  1761. // Reset Brush, since Raster Module might send color selection
  1762. // commnd.Set MODE_BRUSH_RESET_COLOR flag so that the brush
  1763. // color selection command is sent. This will change the current
  1764. // brush color to be default brush color. We need to reset the
  1765. // brush color as on some printers sending a color plane of
  1766. // raster date cahnges the brush color also.
  1767. //
  1768. pPDev->ctl.dwMode |= MODE_BRUSH_RESET_COLOR;
  1769. GSResetBrush(pPDev);
  1770. while( bRet && (ppsg = PSGGetNextPSG( pPSH )) )
  1771. {
  1772. /*
  1773. * Check for the correct font! Since the glyphs are now
  1774. * in an indeterminate order, we need to check EACH one for
  1775. * the font, since each one can be different, as we have
  1776. * no idea of how the glyphs arrived in this order.
  1777. */
  1778. if (pFM = PfmGetIt( pPDev, ppsg->sFontIndex))
  1779. {
  1780. //
  1781. // Error check.
  1782. // BDelayGlyphOut can only handle printer device fonts.
  1783. //
  1784. if (pFM->dwFontType != FMTYPE_DEVICE)
  1785. {
  1786. bRet = FALSE;
  1787. break;
  1788. }
  1789. Tod.flAccel = ppsg->flAccel;
  1790. Tod.dwAttrFlags = ppsg->dwAttrFlags;
  1791. Tod.iFace = ppsg->sFontIndex;
  1792. pFontPDev->ctl.eXScale = ppsg->eXScale;
  1793. pFontPDev->ctl.eYScale = ppsg->eYScale;
  1794. UFObj.pFontMap = Tod.pfm = pFM;
  1795. UFObj.pIFIMetrics = pFM->pIFIMet;
  1796. //
  1797. // Reselect new font
  1798. //
  1799. BNewFont(pPDev, ppsg->sFontIndex, pFM, ppsg->dwAttrFlags);
  1800. SelectTextColor( pPDev, ppsg->pvColor );
  1801. ASSERTMSG(pFM->pfnGlyphOut, ("NULL GlyphOut Funtion Ptr\n"));
  1802. gp.hg = (HGLYPH)(ppsg->hg);
  1803. gp.ptl.x = ppsg->ixVal - pPDev->rcClipRgn.left;
  1804. //
  1805. // Send character string
  1806. //
  1807. bRet = pFM->pfnGlyphOut(&Tod);
  1808. }
  1809. else
  1810. bRet = FALSE;
  1811. }
  1812. }
  1813. VUFObjFree(pFontPDev);
  1814. return bRet;
  1815. }
  1816. //
  1817. // Mics. functions
  1818. //
  1819. VOID
  1820. SelectTextColor(
  1821. PDEV *pPDev,
  1822. PVOID pvColor
  1823. )
  1824. /*++
  1825. Routine Description:
  1826. Select a text color.
  1827. Arguments:
  1828. pPDev Pointer to PDEV
  1829. color Color of the Text.
  1830. Return Value:
  1831. Nothing.
  1832. Note:
  1833. 1/21/1997 -ganeshp-
  1834. Created it.
  1835. --*/
  1836. {
  1837. //Select the Brush and then unrealize it.
  1838. if (!GSSelectBrush( pPDev, pvColor))
  1839. {
  1840. ERR(( "GSSelectBrush Failed;Can't Select the Color\n" ));
  1841. }
  1842. return;
  1843. }
  1844. BCheckForDefaultPlacement(
  1845. GLYPHPOS *pgp,
  1846. SHORT sWidth,
  1847. INT *piTolalError
  1848. )
  1849. /*++
  1850. Routine Description:
  1851. Arguments:
  1852. pgp Current Glyph
  1853. sWidth Width of the previous glyph.
  1854. piTolalError Comulative Error
  1855. Return Value:
  1856. TRUE if the current glyph is at default placement else FALSE.
  1857. Note:
  1858. 11/11/1997 -ganeshp-
  1859. Created it.
  1860. --*/
  1861. {
  1862. GLYPHPOS *pgpPrevious;
  1863. INT iError;
  1864. pgpPrevious = pgp -1;
  1865. iError = (pgpPrevious->ptl.x + sWidth) - pgp->ptl.x;
  1866. *piTolalError += iError;
  1867. //DbgPrint("\nTODEL!BCheckForDefaultPlacement:pgpPrevious->ptl.x = %d, Previous Glyph sWidth = %d,\n\t\tCurrpgp->ptl.x = %d, iError = %d, *piTolalError = %d\n",
  1868. //pgpPrevious->ptl.x, sWidth, pgp->ptl.x, iError, *piTolalError );
  1869. if ( (abs(iError) <= ERROR_PER_GLYPH_POS) /*&& (*piTolalError <= ERROR_PER_ENUMERATION)*/ )
  1870. {
  1871. //DbgPrint("TODEL!BCheckForDefaultPlacement: The Glyph is at Default Placement.\n");
  1872. return TRUE;
  1873. }
  1874. else
  1875. {
  1876. //DbgPrint("TODEL!BCheckForDefaultPlacement: Non Default Placement Glyph Found.\n");
  1877. //DbgPrint("\nTODEL!BCheckForDefaultPlacement:pgpPrevious->ptl.x = %d, Previous Glyph sWidth = %d,\n\t\tCurrpgp->ptl.x = %d, iError = %d, *piTolalError = %d\n",
  1878. //pgpPrevious->ptl.x, sWidth, pgp->ptl.x, iError, *piTolalError );
  1879. return FALSE;
  1880. }
  1881. }
  1882. VOID
  1883. VClipIt(
  1884. BYTE *pbClipBits,
  1885. TO_DATA *ptod,
  1886. CLIPOBJ *pco,
  1887. STROBJ *pstro,
  1888. int cGlyphs,
  1889. int iRot,
  1890. BOOL bPartialClipOn
  1891. )
  1892. /*++
  1893. Routine Description:
  1894. Applies clipping to the glyphos array passed in, and sets bits in
  1895. bClipBits to signify that the corresponding glyph should be printed.
  1896. NOTE: the clipping algorithm is that the glyph is displayed if
  1897. the top, left corner of the character cell is within the clipping
  1898. region. This is the formula of Win 3.1, so it is important for
  1899. us to follow it.
  1900. Arguments:
  1901. pbClipBits Output data is placed here
  1902. ptod Much information
  1903. cGlyphs Number of glyphs in following array
  1904. iRot 90 degree rotation amount (0-3)
  1905. Return Value:
  1906. Nothing
  1907. Note:
  1908. 1/21/1997 -ganeshp-
  1909. Created it.
  1910. --*/
  1911. {
  1912. int iIndex; /* Classic loop variable! */
  1913. ULONG iClipIndex; /* For clipping rectangle */
  1914. int iYTop; /* Font's ascender, scaled if relevant */
  1915. int iYBot; /* Descender, scaled if required */
  1916. BYTE bVal; /* Determine how to set the bits */
  1917. FONTMAP *pFM; /* Speedier access to data */
  1918. FONTPDEV *pFontPDev; /* Ditto */
  1919. GLYPHPOS *pgp; /* Ditto */
  1920. short *asWidth;
  1921. /*
  1922. * Behaviour depends upon the complexity of the clipping region.
  1923. * If it is non-existent (I doubt that this happens, but play it safe)
  1924. * or of complexity DC_TRIVIAL, then set all the relevant bits and
  1925. * return.
  1926. * If DC_RECT is set, the CLIPOBJ contains the clipping rectangle,
  1927. * so clip using that information.
  1928. * Otherwise, it is DC_COMPLEX, and so we need to enumerate clipping
  1929. * rectangles.
  1930. * If we do not need to do anything, then set the bits and return.
  1931. * Otherwise, we have either of the two cases requiring evaluation.
  1932. * For those we want to set the bits to 0 and set the 1 bits as needed.
  1933. *
  1934. * Disable clipping for PCL-XL.
  1935. */
  1936. if( pco &&
  1937. (pco->iDComplexity == DC_RECT || pco->iDComplexity == DC_COMPLEX) &&
  1938. !(ptod->pPDev->ePersonality == kPCLXL))
  1939. bVal = 0; /* Requires us to evaluate it */
  1940. else
  1941. bVal = 0xff; /* Do it all */
  1942. FillMemory( pbClipBits, (cGlyphs + BBITS - 1) / BBITS, bVal );
  1943. if( bVal == 0xff )
  1944. return; /* All done */
  1945. if (!(asWidth = MemAlloc(cGlyphs * sizeof(short))))
  1946. {
  1947. return;
  1948. }
  1949. pFM = ptod->pfm;
  1950. pFontPDev = ptod->pPDev->pFontPDev;
  1951. /*
  1952. * We now calculate the widths of the glpyhs. We need these to
  1953. * correctly clip the data. However, calculating widths can be
  1954. * expensive, and since we need the data later on, we save
  1955. * the values in the width array that ptod points to. This can
  1956. * then be used in the bottom level function, rather than calculating
  1957. * the width again.
  1958. */
  1959. pgp = ptod->pgp;
  1960. //
  1961. // pgp may be NULL causing problems below. So don't clip, just return.
  1962. //
  1963. if (pgp == NULL)
  1964. {
  1965. if (asWidth)
  1966. {
  1967. MemFree(asWidth);
  1968. }
  1969. ASSERTMSG((FALSE),("\nCan't Clip the text.Null pgp in VClipIt. \n"));
  1970. return;
  1971. }
  1972. if (!(ptod->pfo->flFontType & TRUETYPE_FONTTYPE))
  1973. {
  1974. /* The normal case - a standard device font */
  1975. int iWide; /* Calculate the width */
  1976. for( iIndex = 0; iIndex < cGlyphs; ++iIndex, ++pgp )
  1977. {
  1978. iWide = IGetGlyphWidth( ptod->pPDev, pFM, pgp->hg);
  1979. if( pFM->flFlags & FM_SCALABLE )
  1980. {
  1981. /* Need to transform the value to current size */
  1982. iWide = LMulFloatLong(&pFontPDev->ctl.eXScale,iWide);
  1983. }
  1984. asWidth[ iIndex ] = iWide - 1; /* Will be used later */
  1985. }
  1986. }
  1987. else //GDI Font
  1988. {
  1989. GLYPHDATA *pgd;
  1990. /*
  1991. * SPECIAL CASE: DOWNLOADED GDI font. The width is
  1992. * obtained by calling back to GDI to get the data on it.
  1993. */
  1994. for( iIndex = 0; iIndex < cGlyphs; ++iIndex, ++pgp )
  1995. {
  1996. pgd = NULL;
  1997. if( !FONTOBJ_cGetGlyphs( ptod->pfo, FO_GLYPHBITS, (ULONG)1,
  1998. &pgp->hg, &pgd ) )
  1999. {
  2000. if (asWidth)
  2001. {
  2002. MemFree(asWidth);
  2003. }
  2004. ERR(( "FONTOBJ_cGetGlyphs fails\n" ))
  2005. return;
  2006. }
  2007. /*
  2008. * Note about rotations: we do NOT download rotated fonts,
  2009. * so the following piece of code is quite correct.
  2010. */
  2011. if (pgd)
  2012. {
  2013. asWidth[ iIndex ] = (short)(pgd->ptqD.x.HighPart + 15) / 16 - 1;
  2014. }
  2015. else
  2016. {
  2017. ASSERTMSG(FALSE,("UniFont!VClipIt:GLYPHDATA pointer is NULL\n"));
  2018. if (asWidth)
  2019. {
  2020. MemFree(asWidth);
  2021. }
  2022. return;
  2023. }
  2024. }
  2025. }
  2026. /*
  2027. * We also want the Ascender and Descender fields, as these are
  2028. * used to check the Y component. While calculationg these values we have
  2029. * to do special case for Font substitution. In font substitution case
  2030. * True Type font's IFIMERTICS should be used rather than substituted
  2031. * device font's IFIMETRICS.
  2032. */
  2033. //
  2034. // Initialize itTop and iyBot to fontmap values. Then based on what font we
  2035. // are using these values will change.
  2036. //
  2037. iYTop = (INT)((IFIMETRICS *)(pFM->pIFIMet))->fwdWinAscender;
  2038. iYBot = (INT)((IFIMETRICS *)(pFM->pIFIMet))->fwdWinDescender;
  2039. if (ptod->pfo->flFontType & TRUETYPE_FONTTYPE)
  2040. {
  2041. //
  2042. // True Type Font case. Get the values from FONTOBJ ifimetrics.
  2043. //
  2044. ASSERTMSG((pFontPDev->pIFI),("NULL pFontPDev->pIFI, TT Font IFIMETRICS\n"));
  2045. if (pFontPDev->pIFI)
  2046. {
  2047. iYTop = (INT)((IFIMETRICS *)(pFontPDev->pIFI))->fwdWinAscender;
  2048. iYBot = (INT)((IFIMETRICS *)(pFontPDev->pIFI))->fwdWinDescender;
  2049. }
  2050. //
  2051. // We always need to do the sacling as TT font metrics values
  2052. // are in notional space.
  2053. //
  2054. iYTop = LMulFloatLong(&pFontPDev->ctl.eYScale,iYTop);
  2055. iYBot = LMulFloatLong(&pFontPDev->ctl.eYScale,iYBot);
  2056. }
  2057. else
  2058. {
  2059. //
  2060. // Device Font case. We just need to scale for scalable fonts.
  2061. //
  2062. if( pFM->flFlags & FM_SCALABLE )
  2063. {
  2064. iYTop = LMulFloatLong(&pFontPDev->ctl.eYScale,iYTop);
  2065. iYBot = LMulFloatLong(&pFontPDev->ctl.eYScale,iYBot);
  2066. }
  2067. }
  2068. /*
  2069. * Down here means we are serious! Need to determine which (if any)
  2070. * glyphs are within the clip region.
  2071. */
  2072. pgp = ptod->pgp;
  2073. if( pco->iDComplexity == DC_RECT )
  2074. {
  2075. /* The simpler case - one clipping rectangle. */
  2076. RECTL rclClip;
  2077. LONG lFirstGlyphX;
  2078. /* Local access -> speedier access */
  2079. rclClip = pco->rclBounds;
  2080. lFirstGlyphX = 0;
  2081. /*
  2082. * Nothing especially exciting. The clipping is checked for
  2083. * each particular type of rotation, as this is probably faster
  2084. * than having the loop go through the switch statement. The
  2085. * selection criteria are that all the character must be within
  2086. * the clip region in the X direction, while any part of it must
  2087. * be within the clip region in the Y direction. Then we print.
  2088. * Failing either means it is clipped out.
  2089. *
  2090. * NOTE that we fiddle with the clipping rectangle coordinates
  2091. * before the loop, as this saves some computation within the loop.
  2092. */
  2093. switch( iRot )
  2094. {
  2095. case 0: /* Normal direction */
  2096. //
  2097. // Save the x position to restore after clipping calculation.
  2098. //
  2099. lFirstGlyphX = pgp->ptl.x;
  2100. // Check the First Glyph position. If it's just OFF by one or two
  2101. // pixels, print it.
  2102. if ( (pgp->ptl.x != rclClip.left) &&
  2103. (abs(pgp->ptl.x - rclClip.left) <= 2) )
  2104. {
  2105. pgp->ptl.x = rclClip.left;
  2106. }
  2107. for( iIndex = 0; iIndex < cGlyphs; ++iIndex, ++pgp )
  2108. {
  2109. #ifndef OLDWAY
  2110. //
  2111. // We want to draw the character in the first band
  2112. // in which a portion of it appears. This means that
  2113. // if the character starts in the current band we will
  2114. // draw it. We also draw the character if it starts before
  2115. // the first band but some of it exists within the band.
  2116. // The x and y points are relative to the lower left of the
  2117. // character cell so we calculate a upper left value for
  2118. // our testing purposes.
  2119. //
  2120. INT iyTopLeft;
  2121. INT iyBottomLeft, ixRight;
  2122. iyTopLeft = pgp->ptl.y - iYTop;
  2123. iyBottomLeft = pgp->ptl.y + iYBot;
  2124. ixRight = pgp->ptl.x + asWidth[ iIndex ];
  2125. if ((ptod->pfo->flFontType & TRUETYPE_FONTTYPE) &&
  2126. (ptod->flFlags & TODFL_FIRST_ENUMRATION) &&
  2127. bPartialClipOn)
  2128. {
  2129. BOOL bGlyphVisible; // Set if glyph is totally visible.
  2130. BOOL bLeftVisible, bRightVisible,
  2131. bTopVisible, bBottomVisible;
  2132. INT iError, iYdpi;
  2133. //
  2134. // Fix iyTopLeft to be maximum of STROBJ background rectangle's
  2135. // top and current calculated value of the top using asender of
  2136. // the font.This is needed because we want to clip using
  2137. // smallest bounding rectangle for the glyph. We also need to
  2138. // fix iyBottomLeft to be smaller of current value and STROBJ
  2139. // background rectangle's bottom.
  2140. //
  2141. iyTopLeft = max(iyTopLeft, pstro->rclBkGround.top);
  2142. iyBottomLeft = min(iyBottomLeft, pstro->rclBkGround.bottom);
  2143. //
  2144. // If the glyph rectangle's top or bottom is outside the
  2145. // clipping rectangle, we may need adjust the glyph
  2146. // rectangle. This is needed as the glyph rectangle's top and
  2147. // bottom is calculated using ascender and decender. This
  2148. // gives us a bigger rectangle height(worst case) than needed.
  2149. // Adjust the rectangle height by the Error factor. The
  2150. // error factor value is based upon the graphics dpi. For a
  2151. // 600 or 300 dpi printer it's set to 5 pixels and will
  2152. // scale based upon the graphics resolution.This number
  2153. // makes the glyph bounding rectangle small enough to catch
  2154. // the normal non partial clipping case and still catches
  2155. // the partial clipping of the glyphs.This adjustment should
  2156. // be done only if error factor is smaller than ascender or
  2157. // decender. Finally we must check if ptl.y is between
  2158. // topleft and bottomleft.
  2159. //
  2160. if ( (iyTopLeft < rclClip.top) ||
  2161. (iyBottomLeft > rclClip.bottom) )
  2162. {
  2163. iYdpi = ptod->pPDev->ptGrxRes.y;
  2164. if (iYdpi == 300)
  2165. iYdpi = 600;
  2166. iError = (EROOR_PER_GLYPHRECT * iYdpi) / 600;
  2167. if (iYTop > iError)
  2168. iyTopLeft += iError;
  2169. if (iYBot > iError)
  2170. iyBottomLeft -= iError;
  2171. }
  2172. if (iyTopLeft > pgp->ptl.y)
  2173. iyTopLeft = pgp->ptl.y;
  2174. if (iyBottomLeft < pgp->ptl.y)
  2175. iyBottomLeft = pgp->ptl.y;
  2176. //
  2177. // Now test for partial clipping. If the charecter is
  2178. // partially clippeed and the font is truetype, then we need
  2179. // to call EngTextOut.
  2180. //
  2181. // We can only call EngTextOut if we are clipping the first
  2182. // enumaration of the glyphs. EngTextOut doesn't support
  2183. // partial glyph printing.
  2184. //
  2185. //
  2186. // Glyph is fully visible if all the four corners of the
  2187. // glyph rectangle are visible.
  2188. //
  2189. bLeftVisible = (pgp->ptl.x >= rclClip.left);
  2190. bRightVisible = (ixRight <= rclClip.right);
  2191. bTopVisible = (iyTopLeft >= rclClip.top);
  2192. bBottomVisible = (iyBottomLeft <= rclClip.bottom);
  2193. bGlyphVisible = ( bLeftVisible && bRightVisible &&
  2194. bTopVisible && bBottomVisible );
  2195. if (!bGlyphVisible)
  2196. {
  2197. ptod->flFlags |= TODFL_TTF_PARTIAL_CLIPPING;
  2198. //
  2199. // No need to test rest of the glyphs for clipping.
  2200. //
  2201. break;
  2202. }
  2203. }
  2204. else
  2205. {
  2206. if ( (iyTopLeft < rclClip.top) ||
  2207. (iyBottomLeft > rclClip.bottom) )
  2208. {
  2209. INT iError;
  2210. INT iYdpi = ptod->pPDev->ptGrxRes.y;
  2211. if (iYdpi <= 600)
  2212. iYdpi = 600;
  2213. iError = (EROOR_PER_GLYPHRECT * iYdpi) / 600;
  2214. if (iYTop > iError)
  2215. iyTopLeft += iError;
  2216. if (iYBot > iError)
  2217. iyBottomLeft -= iError;
  2218. }
  2219. }
  2220. if( pgp->ptl.x >= rclClip.left &&
  2221. pgp->ptl.x <= rclClip.right &&
  2222. iyTopLeft <= rclClip.bottom &&
  2223. (iyTopLeft >= rclClip.top ||
  2224. (pgp->ptl.y >= rclClip.top &&
  2225. ptod->pPDev->rcClipRgn.top == 0)))
  2226. #else
  2227. if( pgp->ptl.x >= rclClip.left &&
  2228. pgp->ptl.x <= rclClip.right &&
  2229. pgp->ptl.y <= rclClip.bottom &&
  2230. pgp->ptl.y >= rclClip.top )
  2231. #endif
  2232. {
  2233. /* Got it! So set the bit to print it */
  2234. *(pbClipBits + (iIndex >> 3) ) |= 1 << (iIndex & 0x7);
  2235. }
  2236. //
  2237. // Restore the position of the first glyph. It may have been
  2238. // changed.
  2239. //
  2240. if ( iIndex == 0 )
  2241. pgp->ptl.x = lFirstGlyphX;
  2242. }
  2243. break;
  2244. case 1: /* 90 degrees counter clockwise */
  2245. rclClip.left += iYTop;
  2246. rclClip.right -= iYBot;
  2247. /* Check the First Glyph. If it's just OFF by One, print it.*/
  2248. if (abs(pgp->ptl.y - rclClip.bottom) == 1)
  2249. pgp->ptl.y = rclClip.bottom;
  2250. for( iIndex = 0; iIndex < cGlyphs; ++iIndex, ++pgp )
  2251. {
  2252. if( (pgp->ptl.y <= rclClip.bottom) &&
  2253. ((pgp->ptl.y - asWidth[ iIndex ]) >= rclClip.top) &&
  2254. (pgp->ptl.x >= rclClip.left) &&
  2255. (pgp->ptl.x <= rclClip.right) )
  2256. {
  2257. *(pbClipBits + (iIndex >> 3) ) |= 1 << (iIndex & 0x7);
  2258. }
  2259. }
  2260. break;
  2261. case 2: /* 180 degrees, CCW (aka right to left) */
  2262. rclClip.bottom += iYBot;
  2263. rclClip.top -= iYTop;
  2264. /* Check the First Glyph. If it's just OFF by One, print it.*/
  2265. if (abs(pgp->ptl.x - rclClip.right) == 1)
  2266. pgp->ptl.x = rclClip.right;
  2267. for( iIndex = 0; iIndex < cGlyphs; ++iIndex, ++pgp )
  2268. {
  2269. if( pgp->ptl.x <= rclClip.right &&
  2270. (pgp->ptl.x - asWidth[ iIndex ]) >= rclClip.left &&
  2271. pgp->ptl.y <= rclClip.bottom &&
  2272. pgp->ptl.y >= rclClip.top )
  2273. {
  2274. *(pbClipBits + (iIndex >> 3) ) |= 1 << (iIndex & 0x7);
  2275. }
  2276. }
  2277. break;
  2278. case 3: /* 270 degrees CCW */
  2279. rclClip.right += iYBot;
  2280. rclClip.left -= iYTop;
  2281. /* Check the First Glyph. If it's just OFF by One, print it.*/
  2282. if (abs(pgp->ptl.y - rclClip.top) == 1)
  2283. pgp->ptl.y = rclClip.top;
  2284. for( iIndex = 0; iIndex < cGlyphs; ++iIndex, ++pgp )
  2285. {
  2286. if( pgp->ptl.y >= rclClip.top &&
  2287. (pgp->ptl.y + asWidth[ iIndex ]) <= rclClip.bottom &&
  2288. pgp->ptl.x <= rclClip.right &&
  2289. pgp->ptl.x >= rclClip.left )
  2290. {
  2291. *(pbClipBits + (iIndex >> 3) ) |= 1 << (iIndex & 0x7);
  2292. }
  2293. }
  2294. break;
  2295. }
  2296. }
  2297. else // Complex Clipping.
  2298. {
  2299. //
  2300. // For True type font call engine to draw the text.
  2301. //
  2302. if ( (ptod->pfo->flFontType & TRUETYPE_FONTTYPE) && bPartialClipOn)
  2303. {
  2304. ptod->flFlags |= TODFL_TTF_PARTIAL_CLIPPING;
  2305. }
  2306. else // Device font case. We have to clip anyway.
  2307. {
  2308. /* enumerate the rectangles and see */
  2309. int cGLeft;
  2310. BOOL bMore;
  2311. MY_ENUMRECTS erClip;
  2312. /*
  2313. * Let the engine know how we want this handled. All we want
  2314. * to set is the use of rectangles rather than trapezoids for
  2315. * the clipping info. Direction of enumeration is of no great
  2316. * interest, and I don't care how many rectangles are involved.
  2317. * I also see no reason to enumerate the whole region.
  2318. */
  2319. CLIPOBJ_cEnumStart( pco, FALSE, CT_RECTANGLES, CD_ANY, 0 );
  2320. cGLeft = cGlyphs;
  2321. do
  2322. {
  2323. bMore = CLIPOBJ_bEnum( pco, sizeof( erClip ), &erClip.c );
  2324. for( iIndex = 0; iIndex < cGlyphs; ++iIndex )
  2325. {
  2326. RECTL rclGlyph;
  2327. if( pbClipBits[ iIndex >> 3 ] & (1 << (iIndex & 0x7)) )
  2328. continue; /* Already done! */
  2329. /*
  2330. * Compute the RECTL describing this char, then see
  2331. * how this maps to the clipping data.
  2332. */
  2333. switch( iRot )
  2334. {
  2335. case 0:
  2336. rclGlyph.left = (pgp + iIndex)->ptl.x;
  2337. rclGlyph.right = rclGlyph.left + asWidth[ iIndex ];
  2338. rclGlyph.top = (pgp + iIndex)->ptl.y - iYTop;
  2339. rclGlyph.bottom = rclGlyph.top + iYTop + iYBot;
  2340. break;
  2341. case 1:
  2342. rclGlyph.left = (pgp + iIndex)->ptl.x - iYTop;
  2343. rclGlyph.right = rclGlyph.left + iYTop + iYBot;
  2344. rclGlyph.bottom = (pgp + iIndex)->ptl.y;
  2345. rclGlyph.top = rclGlyph.bottom - asWidth[ iIndex ];
  2346. break;
  2347. case 2:
  2348. rclGlyph.right = (pgp + iIndex)->ptl.x;
  2349. rclGlyph.left = rclGlyph.right - asWidth[ iIndex ];
  2350. rclGlyph.bottom = (pgp + iIndex)->ptl.y + iYTop;
  2351. rclGlyph.top = rclGlyph.bottom - iYTop - iYBot;
  2352. break;
  2353. case 3:
  2354. rclGlyph.left = (pgp + iIndex)->ptl.x - iYBot;
  2355. rclGlyph.right = rclGlyph.left + iYTop + iYBot;
  2356. rclGlyph.top = (pgp + iIndex)->ptl.y;
  2357. rclGlyph.bottom = rclGlyph.top + asWidth[ iIndex ];
  2358. break;
  2359. }
  2360. /*
  2361. * Define the char as being printed if any part of it
  2362. * is visible in the Y direction, and all of it in the X
  2363. * direction. This is not really what we want for
  2364. * rotated text, but it is hard to do it correctly,
  2365. * and of dubious benefit.
  2366. */
  2367. for( iClipIndex = 0; iClipIndex < erClip.c; ++iClipIndex )
  2368. {
  2369. if( rclGlyph.right <= erClip.arcl[ iClipIndex ].right &&
  2370. rclGlyph.left >= erClip.arcl[ iClipIndex ].right &&
  2371. rclGlyph.bottom >= erClip.arcl[ iClipIndex ].top &&
  2372. rclGlyph.top <= erClip.arcl[ iClipIndex ].bottom )
  2373. {
  2374. /*
  2375. * Got one, so set the bit to print, and also
  2376. * decrement the count of those remaining.
  2377. */
  2378. pbClipBits[ iIndex >> 3 ] |= (1 << (iIndex & 0x7));
  2379. --cGLeft;
  2380. break;
  2381. }
  2382. }
  2383. }
  2384. } while( bMore && cGLeft > 0 );
  2385. }
  2386. }
  2387. if (asWidth)
  2388. {
  2389. MemFree(asWidth);
  2390. }
  2391. return;
  2392. }
  2393. VOID
  2394. VCopyAlign(
  2395. BYTE *pjDest,
  2396. BYTE *pjSrc,
  2397. int cx,
  2398. int cy
  2399. )
  2400. /*++
  2401. Routine Description:
  2402. Copy the source area to the destination area, aligning the scan lines
  2403. as they are processed.
  2404. Arguments:
  2405. pjDest Output area, DWORD aligned
  2406. pjSrc Input area, BYTE aligned
  2407. cx Number of pixels per scan line
  2408. cy Number of scan lines
  2409. Return Value:
  2410. Nothing.
  2411. Note:
  2412. 1/22/1997 -ganeshp-
  2413. Created it.
  2414. --*/
  2415. {
  2416. /*
  2417. * Basically a trivial function.
  2418. */
  2419. int iX, iY; /* For looping through the bytes */
  2420. int cjFill; /* Extra bytes per output scan line */
  2421. int cjWidth; /* Number of bytes per input scan line */
  2422. cjWidth = (cx + BBITS - 1) / BBITS; /* Input scan line bytes */
  2423. cjFill = ((cjWidth + 3) & ~0x3) - cjWidth;
  2424. for( iY = 0; iY < cy; ++iY )
  2425. {
  2426. /* Copy the scan line bytes, then fill in the trailing bits */
  2427. for( iX = 0; iX < cjWidth; ++iX )
  2428. {
  2429. *pjDest++ = *pjSrc++;
  2430. }
  2431. pjDest += cjFill; /* Output alignment */
  2432. }
  2433. return;
  2434. }
  2435. INT
  2436. ISubstituteFace(
  2437. PDEV *pPDev,
  2438. FONTOBJ *pfo)
  2439. /*++
  2440. Routine Description:
  2441. Return a device font id to substitute TrueType font with.
  2442. Arguments:
  2443. pPDev a pointer to PDEV
  2444. pfo a pointer to FONTOBJ
  2445. Return Value:
  2446. font id
  2447. Note:
  2448. --*/
  2449. {
  2450. PTTFONTSUBTABLE pTTFontSubDefault;
  2451. PIFIMETRICS pIFITT;
  2452. FONTPDEV *pFontPDev;
  2453. PFONTMAP pfm;
  2454. WCHAR awstrFaceName[256];
  2455. PWSTR pwstrTTFaceName, pwstrTTFaceNameRes, pwstrDevFont, pwstrIFIFace;
  2456. DWORD dwCountOfTTSubTable, dwSize;
  2457. PBYTE pubResourceData;
  2458. BOOL bFound, bNonsquare;
  2459. INT iFace, iFaceSim, iI, iCountOfTTSubTable;
  2460. iFace = 0;
  2461. iFaceSim = 0;
  2462. pFontPDev = pPDev->pFontPDev;
  2463. //
  2464. // if dwTTOption is DMTT_DOWNLOAD or DMTT_GRAPHICS,
  2465. // UNIDRV doesn't substitute TrueType font.
  2466. //
  2467. if (pPDev->pdm->dmTTOption != DMTT_SUBDEV)
  2468. {
  2469. //VERBOSE(( "ISubstituteFace: Don't substitute.\n"));
  2470. return 0;
  2471. }
  2472. //
  2473. // If TrueType font is scaled X and Y differently (non-square font),
  2474. // we should not download.
  2475. // Since current UNIDRV can't scale device font x and y independently.
  2476. //
  2477. bNonsquare = NONSQUARE_FONT(pFontPDev->pxform);
  2478. if (bNonsquare && !(pFontPDev->flText & TC_SF_X_YINDEP))
  2479. {
  2480. //VERBOSE(( "ISubstituteFace: Don't substitute non-square TrueType font.\n"));
  2481. return 0;
  2482. }
  2483. //
  2484. // Get TrueType font's facename from IFIMETRICS structure.
  2485. //
  2486. if (!(pIFITT = pFontPDev->pIFI))
  2487. {
  2488. ERR(( "ISubstituteFace: Invalid pFontPDev->pIFI\n"));
  2489. return 0;
  2490. }
  2491. //
  2492. // Get TrueType font face name.
  2493. // In substitution table, there are a list of T2 face name and Device
  2494. // font face name.
  2495. //
  2496. pwstrTTFaceName = (PWSTR)((BYTE *) pIFITT + pIFITT->dpwszFamilyName);
  2497. pTTFontSubDefault = NULL;
  2498. if (!pFontPDev->pTTFontSubReg)
  2499. {
  2500. //
  2501. // Use a default font substitution table, if there no info in registry.
  2502. //
  2503. bFound = FALSE;
  2504. pubResourceData = pPDev->pDriverInfo->pubResourceData;
  2505. pTTFontSubDefault = GETTTFONTSUBTABLE(pPDev->pDriverInfo);
  2506. iCountOfTTSubTable = (INT)pPDev->pDriverInfo->DataType[DT_FONTSUBST].dwCount;
  2507. for (iI = 0; iI < iCountOfTTSubTable; iI++, pTTFontSubDefault++)
  2508. {
  2509. if (!pTTFontSubDefault->arTTFontName.dwCount)
  2510. {
  2511. dwSize = ILoadStringW(&pPDev->WinResData, pTTFontSubDefault->dwRcTTFontNameID, awstrFaceName, 256);
  2512. pwstrTTFaceNameRes = awstrFaceName;
  2513. }
  2514. else
  2515. {
  2516. //
  2517. // dwCount is supposed be the number of characters according to
  2518. // a GPD parser.
  2519. // However, the size is actually the size in byte.
  2520. // We need the number of characters.
  2521. //
  2522. dwSize = pTTFontSubDefault->arTTFontName.dwCount/sizeof(WCHAR);
  2523. pwstrTTFaceNameRes = (PWSTR)(pubResourceData +
  2524. pTTFontSubDefault->arTTFontName.loOffset);
  2525. }
  2526. if (dwSize > 0 &&
  2527. dwSize == wcslen(pwstrTTFaceName) &&
  2528. NULL != pwstrTTFaceNameRes)
  2529. {
  2530. if (!wcsncmp(pwstrTTFaceNameRes, pwstrTTFaceName, dwSize))
  2531. {
  2532. bFound = TRUE;
  2533. break;
  2534. }
  2535. }
  2536. }
  2537. if (!bFound)
  2538. {
  2539. return 0;
  2540. }
  2541. if (pTTFontSubDefault->arDevFontName.dwCount)
  2542. {
  2543. pwstrDevFont = (PWSTR)(pubResourceData +
  2544. pTTFontSubDefault->arDevFontName.loOffset);
  2545. dwSize = pTTFontSubDefault->arDevFontName.dwCount;
  2546. }
  2547. else
  2548. {
  2549. dwSize = ILoadStringW(&pPDev->WinResData, pTTFontSubDefault->dwRcDevFontNameID, awstrFaceName, 256);
  2550. pwstrDevFont = awstrFaceName;
  2551. }
  2552. }
  2553. else
  2554. {
  2555. pwstrDevFont = (PWSTR)PtstrSearchTTSubstTable(pFontPDev->pTTFontSubReg,
  2556. pwstrTTFaceName);
  2557. }
  2558. if (!pwstrDevFont)
  2559. {
  2560. return 0;
  2561. }
  2562. //
  2563. // Get iFace of the font name.
  2564. //
  2565. pfm = pFontPDev->pFontMap;
  2566. for (iI = 1;
  2567. iI <= pPDev->iFonts;
  2568. iI ++, (PBYTE)pfm += SIZEOFDEVPFM() )
  2569. {
  2570. if( pfm->pIFIMet == NULL )
  2571. {
  2572. if (!BFillinDeviceFM( pPDev, pfm, iI - 1 ) )
  2573. {
  2574. continue;
  2575. }
  2576. }
  2577. if (pfm->pIFIMet)
  2578. {
  2579. PIFIMETRICS pDevIFI = pfm->pIFIMet;
  2580. BOOL bT2Bold, bT2Italic;
  2581. bT2Bold = (pIFITT->fsSelection & FM_SEL_BOLD) ||
  2582. (pfo->flFontType & FO_SIM_BOLD);
  2583. bT2Italic = (pIFITT->fsSelection & FM_SEL_ITALIC) ||
  2584. (pfo->flFontType & FO_SIM_ITALIC);
  2585. pwstrIFIFace = (WCHAR*)((BYTE *)pDevIFI + pDevIFI->dpwszFamilyName);
  2586. //
  2587. // (1) FaceName match.
  2588. // (2) Character sets match.
  2589. // -> Set iFaceSim.
  2590. // (3) Bold attributes match. !(bT2Bold xor bDevBold)
  2591. // (4) Italic attributes match. !(bT2Italic xor bDevItalic)
  2592. // -> Set iFace.
  2593. //
  2594. #if 0
  2595. VERBOSE(( "bT2Bold=%d, bT2Italic=%d, IFIFace=%ws, DevFace=%ws\n",
  2596. bT2Bold, bT2Italic, pwstrIFIFace, pwstrDevFont));
  2597. #endif
  2598. if(!wcscmp(pwstrDevFont, pwstrIFIFace) &&
  2599. (pIFITT->jWinCharSet == pDevIFI->jWinCharSet) &&
  2600. ((bNonsquare && (pDevIFI->flInfo & FM_INFO_ANISOTROPIC_SCALING_ONLY)) || !bNonsquare)
  2601. )
  2602. {
  2603. //
  2604. // Substitute TrueType font with simulated device font.
  2605. //
  2606. if( !(((pDevIFI->fsSelection & FM_SEL_BOLD)?TRUE:FALSE) ^ bT2Bold) &&
  2607. !(((pDevIFI->fsSelection & FM_SEL_ITALIC)?TRUE:FALSE) ^ bT2Italic))
  2608. {
  2609. //
  2610. // Attribute match
  2611. // Substitute with bold or italic face device font.
  2612. //
  2613. iFace = iI;
  2614. break;
  2615. }
  2616. else
  2617. if (pfm->pIFIMet->dpFontSim)
  2618. {
  2619. //
  2620. // Attribute doesn't match.
  2621. // Check if this device font can be simulated as bold
  2622. // or italic.
  2623. //
  2624. FONTSIM *pFontSim = (FONTSIM*)((PBYTE)pfm->pIFIMet +
  2625. pfm->pIFIMet->dpFontSim);
  2626. if (! (pFontPDev->flFlags & FDV_INIT_ATTRIB_CMD))
  2627. {
  2628. pFontPDev->pCmdBoldOn = COMMANDPTR(pPDev->pDriverInfo, CMD_BOLDON);
  2629. pFontPDev->pCmdBoldOff = COMMANDPTR(pPDev->pDriverInfo, CMD_BOLDOFF);
  2630. pFontPDev->pCmdItalicOn = COMMANDPTR(pPDev->pDriverInfo, CMD_ITALICON);
  2631. pFontPDev->pCmdItalicOff = COMMANDPTR(pPDev->pDriverInfo, CMD_ITALICOFF);
  2632. pFontPDev->pCmdUnderlineOn = COMMANDPTR(pPDev->pDriverInfo, CMD_UNDERLINEON);
  2633. pFontPDev->pCmdUnderlineOff = COMMANDPTR(pPDev->pDriverInfo, CMD_UNDERLINEOFF);
  2634. pFontPDev->pCmdClearAllFontAttribs = COMMANDPTR(pPDev->pDriverInfo, CMD_CLEARALLFONTATTRIBS);
  2635. pFontPDev->flFlags |= FDV_INIT_ATTRIB_CMD;
  2636. }
  2637. if (bT2Bold && bT2Italic)
  2638. {
  2639. if( pFontSim->dpBoldItalic &&
  2640. pFontPDev->pCmdBoldOn &&
  2641. pFontPDev->pCmdItalicOn )
  2642. {
  2643. iFaceSim = iI;
  2644. break;
  2645. }
  2646. }
  2647. else
  2648. if (bT2Bold)
  2649. {
  2650. if( pFontSim->dpBold &&
  2651. pFontPDev->pCmdBoldOn)
  2652. {
  2653. iFaceSim = iI;
  2654. break;
  2655. }
  2656. }
  2657. else
  2658. if (bT2Italic)
  2659. {
  2660. if (pFontSim->dpItalic &&
  2661. pFontPDev->pCmdItalicOn)
  2662. {
  2663. iFaceSim = iI;
  2664. break;
  2665. }
  2666. }
  2667. }
  2668. }
  2669. }
  2670. }
  2671. if (iFace)
  2672. return iFace;
  2673. else
  2674. return iFaceSim;
  2675. }
  2676. PHGLYPH
  2677. PhAllCharsPrintable(
  2678. PDEV *pPDev,
  2679. INT iSubst,
  2680. ULONG ulGlyphs,
  2681. PWCHAR pwchUnicode)
  2682. {
  2683. PHGLYPH phGlyph;
  2684. PFONTMAP pfm;
  2685. ULONG ulI;
  2686. BOOL bRet;
  2687. //
  2688. // Error check
  2689. //
  2690. if (!pwchUnicode)
  2691. return NULL;
  2692. if (!(PVGetUCGlyphSetData( pPDev, iSubst)) ||
  2693. !(pfm = PfmGetIt( pPDev, iSubst)) ||
  2694. !(phGlyph = MemAlloc(sizeof(HGLYPH) * ulGlyphs)))
  2695. {
  2696. return NULL;
  2697. }
  2698. for (ulI = 0; ulI < ulGlyphs; ulI ++)
  2699. {
  2700. if (!(*(phGlyph+ulI) = HWideCharToGlyphHandle(pPDev,
  2701. pfm,
  2702. *(pwchUnicode+ulI))))
  2703. {
  2704. MemFree(phGlyph);
  2705. phGlyph = NULL;
  2706. break;
  2707. }
  2708. }
  2709. return phGlyph;
  2710. }
  2711. HGLYPH
  2712. HWideCharToGlyphHandle(
  2713. PDEV *pPDev,
  2714. FONTMAP *pFM,
  2715. WCHAR wchOrg)
  2716. /*++
  2717. Routine Description:
  2718. Select a text color.
  2719. Arguments:
  2720. pPDev a pointer to PDEV
  2721. ptod a pointer to TO_DATA
  2722. wchOrg Unidrv character
  2723. Return Value:
  2724. Glyph handle.
  2725. Note:
  2726. --*/
  2727. {
  2728. PFONTMAP_DEV pFMDev;
  2729. HGLYPH hRet;
  2730. DWORD dwI;
  2731. BOOL bFound;
  2732. if (wchOrg < pFM->wFirstChar || pFM->wLastChar < wchOrg)
  2733. {
  2734. return (HGLYPH)0;
  2735. }
  2736. hRet = 1;
  2737. pFMDev = pFM->pSubFM;
  2738. bFound = FALSE;
  2739. if (pFM->flFlags & FM_GLYVER40)
  2740. {
  2741. WCRUN *pWCRuns;
  2742. DWORD dwCRuns;
  2743. if (!pFMDev->pUCTree)
  2744. return (HGLYPH)0;
  2745. dwCRuns = ((FD_GLYPHSET*)pFMDev->pUCTree)->cRuns;
  2746. pWCRuns = ((FD_GLYPHSET*)pFMDev->pUCTree)->awcrun;
  2747. for (dwI = 0; dwI < dwCRuns; dwI ++, pWCRuns ++)
  2748. {
  2749. if (pWCRuns->wcLow <= wchOrg &&
  2750. wchOrg < pWCRuns->wcLow + pWCRuns->cGlyphs )
  2751. {
  2752. hRet = *(pWCRuns->phg + (wchOrg - pWCRuns->wcLow));
  2753. bFound = TRUE;
  2754. break;
  2755. }
  2756. }
  2757. }
  2758. else
  2759. {
  2760. PUNI_GLYPHSETDATA pGlyphSetData;
  2761. PGLYPHRUN pGlyphRun;
  2762. if (pFMDev && pFMDev->pvNTGlyph)
  2763. {
  2764. pGlyphSetData = (PUNI_GLYPHSETDATA)pFMDev->pvNTGlyph;
  2765. pGlyphRun = GET_GLYPHRUN(pFMDev->pvNTGlyph);
  2766. }
  2767. else
  2768. {
  2769. return (HGLYPH)0;
  2770. }
  2771. for (dwI = 0; dwI < pGlyphSetData->dwRunCount; dwI ++, pGlyphRun ++)
  2772. {
  2773. if (pGlyphRun->wcLow <= wchOrg &&
  2774. wchOrg < pGlyphRun->wcLow + pGlyphRun->wGlyphCount )
  2775. {
  2776. hRet += wchOrg - pGlyphRun->wcLow;
  2777. bFound = TRUE;
  2778. break;
  2779. }
  2780. hRet += pGlyphRun->wGlyphCount;
  2781. }
  2782. }
  2783. if (bFound)
  2784. {
  2785. return hRet;
  2786. }
  2787. else
  2788. {
  2789. return (HGLYPH)0;
  2790. }
  2791. }
  2792. BOOL
  2793. BGetStartGlyphandCount(
  2794. BYTE *pbClipBits,
  2795. DWORD dwEndIndex,
  2796. DWORD *pdwStartIndex,
  2797. DWORD *pdwGlyphToPrint)
  2798. /*++
  2799. Routine Description:
  2800. Select a text color.
  2801. Arguments:
  2802. pbClipBits bit flags for character clipping
  2803. dwTotalGlyph a total count of glyph
  2804. pdwStartIndex a pointer to the index of starting glyph
  2805. pdwGlyphtoPrint a pointer to the the number of glyphs to print
  2806. Return Value:
  2807. True if there is any character to print. Otherwise False.
  2808. Note:
  2809. Caller passes the number of characters to print in pdwGlyphCount.
  2810. And the ID of the first character to print.
  2811. --*/
  2812. {
  2813. DWORD dwI;
  2814. BOOL bRet;
  2815. dwI = *pdwStartIndex;
  2816. *pdwStartIndex = *pdwGlyphToPrint = 0;
  2817. bRet = FALSE;
  2818. for (; dwI < dwEndIndex; dwI ++)
  2819. {
  2820. if (pbClipBits[dwI >> 3] & (1 << (dwI & 0x07)))
  2821. {
  2822. if (bRet)
  2823. {
  2824. (*pdwGlyphToPrint)++;
  2825. }
  2826. else
  2827. {
  2828. bRet = TRUE;
  2829. *pdwStartIndex = dwI;
  2830. *pdwGlyphToPrint = 1;
  2831. }
  2832. }
  2833. else
  2834. {
  2835. if (bRet)
  2836. {
  2837. break;
  2838. }
  2839. }
  2840. }
  2841. return bRet;
  2842. }
  2843. //
  2844. // If the difference between width and height is not within +-0.5%,
  2845. // returns TRUE.
  2846. //
  2847. BOOL
  2848. NONSQUARE_FONT(
  2849. PXFORML pxform)
  2850. {
  2851. BOOL bRet;
  2852. FLOATOBJ eMa, eMb, eMc;
  2853. FLOATOBJ Round, RoundM;
  2854. //
  2855. // PCL5e printers can not scale with and height of fonts idependently.
  2856. // This function checks if font is squarely scaled.
  2857. // It means width and height is same.
  2858. // Also this function is functional in 0, 90, 180, and 270 degree rotation.
  2859. // PCL5e printer can't not scale arbitrary degree, but only on 0, 90, 180,
  2860. // and 270 degree. So this function works fine.
  2861. //
  2862. if (FLOATOBJ_EqualLong(&pxform->eM11, (LONG)0))
  2863. {
  2864. eMa = eMc = pxform->eM21;
  2865. eMb = pxform->eM12;
  2866. }
  2867. else
  2868. {
  2869. eMa = eMc = pxform->eM11;
  2870. eMb = pxform->eM22;
  2871. }
  2872. //
  2873. // Set 0.005 (0.5%) round values.
  2874. //
  2875. #ifndef WINNT_40 //NT 5.0
  2876. FLOATOBJ_SetFloat(&Round, (FLOAT)0.005);
  2877. FLOATOBJ_SetFloat(&RoundM, (FLOAT)-0.005);
  2878. #else
  2879. FLOATOBJ_SetFloat(&Round, FLOATL_00_005);
  2880. FLOATOBJ_SetFloat(&RoundM, FLOATL_00_005M);
  2881. #endif //!WINNT_40
  2882. //
  2883. // eM11 = (eM11 - eM22) / eM11
  2884. //
  2885. FLOATOBJ_Sub(&eMa, &eMb);
  2886. FLOATOBJ_Div(&eMa, &eMc);
  2887. //
  2888. // (eM11 - eM22) / eM11 < 0.5%
  2889. //
  2890. bRet = FLOATOBJ_LessThan(&(eMa), &(Round)) &&
  2891. FLOATOBJ_GreaterThan(&(eMa), &(RoundM));
  2892. eMa = eMc;
  2893. FLOATOBJ_Add(&eMa, &eMb);
  2894. FLOATOBJ_Div(&eMa, &eMc);
  2895. bRet = bRet
  2896. || ( FLOATOBJ_LessThan(&eMa, &Round)
  2897. && FLOATOBJ_GreaterThan(&(eMa), &(RoundM)));
  2898. return !bRet;
  2899. }
  2900. #undef FILETRACE