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.

1615 lines
47 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: ttgdi.cxx
  3. *
  4. * These are TrueType specific calls introduced into GDI by Win 3.1. They
  5. * all assume the existence of the TrueType font driver (or rasterizer
  6. * as it is known in Win 3.1).
  7. *
  8. * Created: 11-Feb-1992 15:03:45
  9. * Author: Gilman Wong [gilmanw]
  10. *
  11. * Copyright (c) 1992-1999 Microsoft Corporation
  12. *
  13. \**************************************************************************/
  14. #include "precomp.hxx"
  15. /*
  16. ;********************************Public*Routine********************************
  17. ;This function is used to create a font directory for a given engine font file
  18. ;in it's native format. This font directory can be used to create .FON like
  19. ;DLLs.
  20. ;Returns: DX:AX # of bytes copied into lpFontDir buffer or -1L in case of
  21. ; some error.
  22. ;
  23. ; GDI uses the Serif Style value in the Panose record of the OS/2 table to
  24. ; drive the Font Family for Windows. This is based on a simple table look
  25. ; up and the current mapping is as follows:
  26. ;
  27. ; Serif Style Font Family
  28. ; ----------------------------------------------------------------
  29. ; 0 (Any) FF_DONTCARE
  30. ; 1 (No Fit) FF_DONTCARE
  31. ; 2 (Cove) FF_ROMAN
  32. ; 3 (Obtuse Cove) FF_ROMAN
  33. ; 4 (Square Cove) FF_ROMAN
  34. ; 5 (Obtuse Square Cove) FF_ROMAN
  35. ; 6 (Square) FF_ROMAN
  36. ; 7 (Thin) FF_ROMAN
  37. ; 8 (Bone) FF_ROMAN
  38. ; 9 (Exaggerated) FF_ROMAN
  39. ;10 (Triangle) FF_ROMAN
  40. ;11 (Normal Sans) FF_SWISS
  41. ;12 (Obtuse Sans) FF_SWISS
  42. ;13 (Perp Sans) FF_SWISS
  43. ;14 (Flared) FF_SWISS
  44. ;15 (Rounded) FF_SWISS
  45. ;
  46. ;******************************************************************************
  47. */
  48. // Generic FFH header information.
  49. #define HEADERSTUFFLEN1 (5 * sizeof(USHORT))
  50. #define COPYRIGHTLEN 60
  51. #define MOREHEADERSTUFFLEN (2 * sizeof(USHORT))
  52. #define HEADERSTUFFLEN (HEADERSTUFFLEN1 + COPYRIGHTLEN)
  53. static USHORT ausHeaderStuff[5] = {
  54. 1, 0, 0x0200, ((SIZEFFH)+4+LF_FACESIZE), 0
  55. };
  56. static USHORT ausMoreHeaderStuff[2] = {
  57. WIN_VERSION, GDI_VERSION
  58. };
  59. #define MAXPMWEIGHT 9
  60. #define WOW_EMBEDING 2
  61. /**************************************************************************\
  62. * NtGdiMakeFontDir
  63. *
  64. * Code is over here!
  65. \**************************************************************************/
  66. ULONG GreMakeFontDir(
  67. FLONG flEmbed, // mark file as "hidden"
  68. PBYTE pjFontDir, // pointer to structure to fill
  69. PWSZ pwszPathname // path of font file to use
  70. )
  71. {
  72. ULONG cjNames; // localW nNamesLength
  73. HFF hff; // localD lhFontFile
  74. PIFIMETRICS pifi; // localV pIfiMetrics, %(size IFIMETRICS)
  75. ULONG_PTR idifi;
  76. ULONG cjIFI;
  77. // If TrueType disabled, then fail.
  78. // Not needed since our TrueType driver is part of the engine DLL and
  79. // should never be disabled. At least, not yet...
  80. if (gppdevTrueType == NULL)
  81. {
  82. return ( 0);
  83. }
  84. // Use TrueType driver to load font file.
  85. PDEVOBJ pdo((HDEV)gppdevTrueType);
  86. // Create a bogus PFF that only has the file name set. This insures that
  87. // the call to EngMapFontFile will suceed.
  88. FONTFILEVIEW fv, *pfv = &fv;
  89. memset( (PVOID) &fv, 0, sizeof(fv) );
  90. fv.pwszPath = pwszPathname;
  91. PVOID pvView;
  92. ULONG cjView;
  93. if (!EngMapFontFileFDInternal((ULONG_PTR)&fv, (PULONG *)&pvView, &cjView, FALSE))
  94. {
  95. WARNING("GreMakeFontDir: EngMapFontFile failed\n");
  96. return(FALSE);
  97. }
  98. hff = pdo.LoadFontFile(
  99. 1
  100. , (ULONG_PTR *)&pfv
  101. , &pvView
  102. , &cjView
  103. , 0 // pdv
  104. , (ULONG) gusLanguageID
  105. , 0
  106. );
  107. if ( !hff )
  108. {
  109. KdPrint(("gdisrv!cjMakeFontDir(): failed to load TrueType file %ws\n", pwszPathname));
  110. return ( 0);
  111. }
  112. EngUnmapFontFileFD((ULONG_PTR)&fv);
  113. // Grab a pointer to the IFIMETRICS as well as the size of the structure.
  114. if ( (pifi = pdo.QueryFont(
  115. 0,
  116. hff,
  117. 1, // currently, only 1 .TTF per .FOT
  118. &idifi)) == (PIFIMETRICS) NULL )
  119. {
  120. // Make sure to unload on error exit.
  121. if ( !pdo.UnloadFontFile(hff) )
  122. {
  123. WARNING("cjMakeFontDir(): IFI error--failed to unload file\n");
  124. return (FALSE);
  125. }
  126. // Error exit.
  127. WARNING("cjMakeFontDir(): IFI error in TrueType driver\n");
  128. return (FALSE);
  129. }
  130. cjIFI = pifi->cjThis;
  131. // NOTE PERF: [GilmanW] 01-Nov-1992 A note to myself...
  132. //
  133. // Tsk-tsk! Gilman, this is very inefficient. You should create a stack
  134. // object that loads the font file and ifimetrics. Its destructor will
  135. // automatically free the ifimetrics and unload the file. That saves
  136. // having to do the MALLOCOBJ and copy.
  137. // Copy the IFIMETRICS so we can unload the font file NOW (and simplify
  138. // error cleanup).
  139. MALLOCOBJ moIFI(cjIFI);
  140. if ( !moIFI.bValid() )
  141. {
  142. // Make sure to unload on error exit.
  143. if ( !pdo.UnloadFontFile(hff) )
  144. {
  145. WARNING("cjMakeFontDir(): IFI error--failed to unload file\n");
  146. return (0);
  147. }
  148. // Error exit.
  149. WARNING("cjMakeFontDir(): could not allocate buffer for IFIMETRICS\n");
  150. return ( 0);
  151. }
  152. RtlCopyMemory(moIFI.pv(), (PVOID) pifi, cjIFI);
  153. // Tell the TrueType driver to free the IFIMETRICS.
  154. if ( PPFNVALID(pdo, Free) )
  155. {
  156. pdo.Free(pifi, idifi);
  157. }
  158. pifi = (PIFIMETRICS) moIFI.pv();
  159. IFIOBJ ifio(pifi);
  160. // Tell the TrueType driver to unload the font file.
  161. if ( !pdo.UnloadFontFile(hff) )
  162. {
  163. WARNING("cjMakeFontDir(): IFI error--failed to unload file\n");
  164. return (0);
  165. }
  166. // Copy header info into the font directory.
  167. PBYTE pjWritePointer = pjFontDir;
  168. RtlCopyMemory(pjWritePointer, ausHeaderStuff, HEADERSTUFFLEN1);
  169. pjWritePointer += HEADERSTUFFLEN1;
  170. //
  171. // Add the copyright string.
  172. //
  173. ULONG cjTmp = strlen("Windows! Windows! Windows!") + 1;
  174. RtlCopyMemory(pjWritePointer, "Windows! Windows! Windows!", cjTmp);
  175. // If this is an embeded font we need to embed either a PID or TID depending on
  176. // whether or not we were called from WOW. If we were called from WOW then we
  177. // expect flEmbeded to be WOW_EMBEDING.
  178. if( flEmbed )
  179. {
  180. ULONG pid = (flEmbed == WOW_EMBEDING) ?
  181. (ULONG) W32GetCurrentTID() : (ULONG) W32GetCurrentPID();
  182. // we are overwriting the copyright string with the PID or TID but
  183. // since this is an embeded font we don't care about the copyright
  184. // string
  185. //
  186. // Unaligned write
  187. //
  188. RtlCopyMemory( pjWritePointer,
  189. &pid,
  190. sizeof( ULONG ) );
  191. }
  192. RtlZeroMemory(pjWritePointer + cjTmp, COPYRIGHTLEN - cjTmp);
  193. // pjWritePointer += COPYRIGHTLEN;
  194. pjWritePointer += cjTmp;
  195. // Note: version stamps (Win version, Engine version) are put in the
  196. // copyright field immediately after the copyright string.
  197. RtlCopyMemory(pjWritePointer, ausMoreHeaderStuff, MOREHEADERSTUFFLEN);
  198. // pjWritePointer += MOREHEADERSTUFFLEN;
  199. pjWritePointer += (COPYRIGHTLEN - cjTmp);
  200. // Engine type and embedded flags.
  201. *pjWritePointer++ = (BYTE) ( PF_ENGINE_TYPE |
  202. ((flEmbed) ? PF_ENCAPSULATED : 0) |
  203. ((flEmbed == WOW_EMBEDING) ? PF_TID : 0));
  204. // Selection type flag.
  205. *pjWritePointer++ = (BYTE) (ifio.fsSelection() & 0x00ff);
  206. // Em square.
  207. WRITE_WORD(pjWritePointer, ifio.fwdUnitsPerEm());
  208. pjWritePointer += 2;
  209. // Horizontal and vertical resolutions.
  210. WRITE_WORD(pjWritePointer, 72);
  211. pjWritePointer += 2;
  212. WRITE_WORD(pjWritePointer, 72);
  213. pjWritePointer += 2;
  214. // Ascent.
  215. WRITE_WORD(pjWritePointer, ifio.fwdWinAscender());
  216. pjWritePointer += 2;
  217. // Internal leading.
  218. WRITE_WORD(pjWritePointer, ifio.fwdInternalLeading());
  219. pjWritePointer += 2;
  220. // External leading.
  221. WRITE_WORD(pjWritePointer, ifio.fwdExternalLeading());
  222. pjWritePointer += 2;
  223. // Italic, strikeout, and underline flags.
  224. *pjWritePointer++ = ifio.bItalic() ? 0xffff : 0;
  225. *pjWritePointer++ = ifio.lfUnderline() ? 0xffff : 0;
  226. *pjWritePointer++ = ifio.lfStrikeOut() ? 0xffff : 0;
  227. WRITE_WORD(pjWritePointer, ifio.lfWeight());
  228. pjWritePointer += 2;
  229. // Character set.
  230. // Old Comment:
  231. // - is this right? Maybe we should check. At least make sure ttfd
  232. // handles this so ifi.usCharSet is correct.
  233. *pjWritePointer++ = ifio.lfCharSet();
  234. // Pix width (set to zero for some reason). [Windows 3.1 compatibility]
  235. WRITE_WORD(pjWritePointer, 0);
  236. pjWritePointer += 2;
  237. // Font height.
  238. WRITE_WORD(pjWritePointer, (WORD) ifio.lfHeight());
  239. pjWritePointer += 2;
  240. // PitchAndFamily.
  241. *pjWritePointer++ = ifio.tmPitchAndFamily();
  242. // Average character width (if zero, estimate as fwdMaxCharInc/2).
  243. WRITE_WORD(
  244. pjWritePointer,
  245. ifio.lfWidth() ? (WORD) ifio.lfWidth() : ifio.fwdMaxCharInc()/2
  246. );
  247. pjWritePointer += 2;
  248. // Maximum width.
  249. WRITE_WORD(pjWritePointer, ifio.fwdMaxCharInc());
  250. pjWritePointer += 2;
  251. // The special characters (first, last, default, break).
  252. *pjWritePointer++ = ifio.chFirstChar();
  253. *pjWritePointer++ = ifio.chLastChar();
  254. WRITE_WORD(pjWritePointer, DEF_BRK_CHARACTER); // write it in one shot
  255. pjWritePointer += 2;
  256. // Force WidthBytes entry to zero, no device name.
  257. *pjWritePointer++ = 0;
  258. *pjWritePointer++ = 0;
  259. *pjWritePointer++ = 0;
  260. *pjWritePointer++ = 0;
  261. *pjWritePointer++ = 0;
  262. *pjWritePointer++ = 0;
  263. // Offset to facename.
  264. WRITE_DWORD(pjWritePointer, (DWORD) SIZEFFH + 4 + 1);
  265. pjWritePointer += 4;
  266. // Store rasterization thresholds.
  267. WRITE_WORD(pjWritePointer, (WORD) ifio.fwdLowestPPEm());
  268. pjWritePointer += 2;
  269. WRITE_WORD(pjWritePointer, ifio.wCharBias());
  270. pjWritePointer += 2;
  271. // Move pointer to where facenames belong.
  272. pjWritePointer = pjFontDir + SIZEFFH + 4 + 1;
  273. // Write out family name.
  274. vToASCIIN((PSZ) pjWritePointer, LF_FACESIZE, ifio.pwszFamilyName(), wcslen(ifio.pwszFamilyName()) + 1);
  275. // measure the ansi string again. If dbcs, it may be longer than cwcTmp
  276. cjNames = strlen((PSZ) pjWritePointer) + 1;
  277. pjWritePointer += cjNames;
  278. // Write out face name.
  279. vToASCIIN((PSZ) pjWritePointer, LF_FULLFACESIZE, ifio.pwszFaceName(), wcslen(ifio.pwszFaceName()) + 1);
  280. // measure the ansi string again. If dbcs, it may be longer than cwcTmp
  281. cjTmp = strlen((PSZ) pjWritePointer) + 1;
  282. cjNames += cjTmp;
  283. pjWritePointer += cjTmp;
  284. // Write out style name.
  285. vToASCIIN((PSZ) pjWritePointer, LF_FACESIZE, ifio.pwszStyleName(), wcslen(ifio.pwszStyleName()) + 1);
  286. cjNames += (strlen((PSZ) pjWritePointer) + 1);
  287. return (cjNames + SIZEFFH + 4 + 1);
  288. }
  289. /******************************Public*Routine******************************\
  290. * GreGetRasterizerCaps
  291. *
  292. * Fills the RASTERIZER_STATUS structure.
  293. *
  294. * Returns:
  295. * TRUE if successful; FALSE otherwise.
  296. *
  297. * History:
  298. * 16-Feb-1992 -by- Gilman Wong [gilmanw]
  299. * Wrote it.
  300. \**************************************************************************/
  301. BOOL GreGetRasterizerCaps (
  302. LPRASTERIZER_STATUS praststat // pointer to a RASTERIZER_STATUS struc
  303. )
  304. {
  305. // Parameter check.
  306. if (praststat == (LPRASTERIZER_STATUS) NULL)
  307. {
  308. WARNING("GreGetRasterizerCaps(): bad parameter\n");
  309. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  310. return (FALSE);
  311. }
  312. // Fill in size.
  313. praststat->nSize = sizeof(RASTERIZER_STATUS);
  314. // Fill in TrueType driver flags.
  315. praststat->wFlags = (USHORT) ((gppdevTrueType != NULL) ? TT_ENABLED : 0);
  316. praststat->wFlags |= (gcTrueTypeFonts != 0) ? TT_AVAILABLE : 0;
  317. // Fill in language id.
  318. praststat->nLanguageID = gusLanguageID;
  319. return (TRUE);
  320. }
  321. /******************************Public*Routine******************************\
  322. *
  323. * ulGetFontData2
  324. *
  325. * Effects:
  326. *
  327. * History:
  328. * 17-Jul-1995 -by- Bodin Dresevic [BodinD]
  329. * Wrote it.
  330. \**************************************************************************/
  331. ULONG ulGetFontData2 (
  332. DCOBJ& dco,
  333. DWORD dwTable,
  334. DWORD dwOffset,
  335. PVOID pvBuffer,
  336. ULONG cjData
  337. )
  338. {
  339. ULONG cjRet = (ULONG) -1;
  340. // Get RFONT user object. Need this to realize font.
  341. // Old Comment:
  342. // - This should get changed to an LFONTOBJ (paulb)
  343. RFONTOBJ rfo(dco, FALSE);
  344. if (!rfo.bValid())
  345. {
  346. WARNING("GetFontData(): could not lock HRFONT\n");
  347. return (cjRet);
  348. }
  349. // Get PFE user object. Need this for iFont.
  350. PFEOBJ pfeo(rfo.ppfe());
  351. if (!pfeo.bValid())
  352. {
  353. WARNING("GetFontData(): could not lock HPFE\n");
  354. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  355. return (cjRet);
  356. }
  357. // Get PFF user object. Need this for HFF.
  358. PFFOBJ pffo(pfeo.pPFF());
  359. if (!pffo.bValid())
  360. {
  361. WARNING("GetFontData(): could not lock HPFF\n");
  362. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  363. return (cjRet);
  364. }
  365. // Get FDEV user object.
  366. PDEVOBJ pdo(rfo.hdevProducer());
  367. // As long as the driver LOOKS like the TrueType driver, we will allow the
  368. // call to succeed. Otherwise, we quit right now!
  369. //
  370. // In this case, TrueType means supporting the TrueType Tagged File Format.
  371. cjRet = pdo.QueryTrueTypeTable (
  372. pffo.hff(),
  373. pfeo.iFont(),
  374. (ULONG) dwTable,
  375. (PTRDIFF) dwOffset,
  376. (ULONG) cjData,
  377. (PBYTE) pvBuffer,
  378. 0,
  379. 0
  380. );
  381. return (cjRet);
  382. }
  383. /******************************Public*Routine******************************\
  384. * GreGetFontData
  385. *
  386. * History:
  387. * 16-Feb-1992 -by- Gilman Wong [gilmanw]
  388. * Wrote it.
  389. \**************************************************************************/
  390. ULONG ulGetFontData (
  391. HDC hdc,
  392. DWORD dwTable,
  393. DWORD dwOffset,
  394. PVOID pvBuffer,
  395. ULONG cjData
  396. )
  397. {
  398. ULONG cjRet = (ULONG) -1;
  399. // Get DC user object.
  400. DCOBJ dco(hdc);
  401. if (!dco.bValid())
  402. {
  403. WARNING("GetFontData(): bad handle for DC\n");
  404. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  405. return (cjRet);
  406. }
  407. return ulGetFontData2(dco, dwTable, dwOffset, pvBuffer, cjData);
  408. }
  409. /******************************Public*Routine******************************\
  410. *
  411. * vFixedToEf
  412. *
  413. * History:
  414. * Thu 17-Nov-1994 07:15:12 by Kirk Olynyk [kirko]
  415. * Made it simpler.
  416. * 11-Jun-1992 -by- Bodin Dresevic [BodinD]
  417. * Wrote it.
  418. \**************************************************************************/
  419. VOID vFixedToEf (
  420. EFLOAT *pef,
  421. FIXED& fxd
  422. )
  423. {
  424. *pef = *(LONG*) &fxd;
  425. pef->vMultByPowerOf2(-16);
  426. }
  427. /*********************************Class************************************\
  428. * class RESETFCOBJ
  429. *
  430. * (brief description)
  431. *
  432. * Public Interface:
  433. *
  434. * History:
  435. * 10-Jun-1992 -by- Bodin Dresevic [BodinD]
  436. * Wrote it.
  437. \**************************************************************************/
  438. #define B_ONE(e) (((e).value == 1) && ((e).fract == 0))
  439. #define B_ZERO(e) (((e).value == 0) && ((e).fract == 0))
  440. class RESETFCOBJ // resetfco
  441. {
  442. private:
  443. BOOL bValid_;
  444. BOOL bTrivialXform;
  445. RFONTOBJ *prfo;
  446. public:
  447. RESETFCOBJ(
  448. DCOBJ& dco,
  449. RFONTOBJ& rfo,
  450. LPMAT2 lpmat2, // "extra" xform applied after the existing xform in dc
  451. BOOL bIgnoreRotation,
  452. FLONG flType
  453. );
  454. ~RESETFCOBJ();
  455. BOOL bValid() {return bValid_;};
  456. BOOL bTrivXform() {return bTrivialXform;};
  457. };
  458. /******************************Public*Routine******************************\
  459. *
  460. * RESETFCOBJ::RESETFCOBJ
  461. *
  462. *
  463. * resets the xform in rfo.hfc() to be what it used to be times lpma2
  464. *
  465. *
  466. * History:
  467. * 01-Nov-1992 Gilman Wong [gilmanw]
  468. * IFI/DDI merge.
  469. *
  470. * 11-Jun-1992 -by- Bodin Dresevic [BodinD]
  471. * Wrote it.
  472. \**************************************************************************/
  473. RESETFCOBJ::RESETFCOBJ(
  474. DCOBJ& dco,
  475. RFONTOBJ& rfo,
  476. LPMAT2 lpmat2, // "extra" xform applied after the existing xform in dc
  477. BOOL bIgnoreRotation,
  478. FLONG flType
  479. )
  480. {
  481. ASSERTGDI(lpmat2 != (LPMAT2)NULL, "RESETFCOBJ:lpmat2\n");
  482. bValid_ = TRUE;
  483. prfo = &rfo;
  484. bTrivialXform = (
  485. B_ONE(lpmat2->eM11) && B_ONE(lpmat2->eM22) &&
  486. B_ZERO(lpmat2->eM12) && B_ZERO(lpmat2->eM21)
  487. );
  488. // If the escapement or orientation values of the LOGFONT are non-zero and
  489. // we are in compatible mode, we will need to recompute the NtoD transform
  490. // while ingnoring these values. This is for the sake of Win 3.1 compatablity.
  491. LFONTOBJ lfo(dco.pdc->hlfntNew());
  492. if (!lfo.bValid())
  493. {
  494. WARNING("GreGetGlyphOutline(): bad LFONTHANDLE\n");
  495. bValid_ = FALSE;
  496. return;
  497. }
  498. if( ( lfo.plfw()->lfEscapement || lfo.plfw()->lfOrientation ) &&
  499. ( bIgnoreRotation ) )
  500. {
  501. bTrivialXform = FALSE;
  502. }
  503. if (!bTrivialXform)
  504. {
  505. // Create an EXFORMOBJ. We will use this to hold the transform passed
  506. // in via the LPMAT2.
  507. MATRIX mxExtra;
  508. EXFORMOBJ xoExtra(&mxExtra, XFORM_FORMAT_LTOL);
  509. // EXFORMOBJ should not be able to fail.
  510. ASSERTGDI (
  511. xoExtra.bValid(),
  512. "GreGetGlyphOutline(): EXFORMOBJ failed\n"
  513. );
  514. // Stuff lpMat2 into the "extra" EXFORMOBJ.
  515. EFLOAT ef11, ef12, ef21, ef22;
  516. vFixedToEf(&ef11, lpmat2->eM11);
  517. vFixedToEf(&ef22, lpmat2->eM22);
  518. vFixedToEf(&ef12, lpmat2->eM12);
  519. vFixedToEf(&ef21, lpmat2->eM21);
  520. {
  521. ef12.vNegate();
  522. ef21.vNegate();
  523. xoExtra.vSetElementsLToL(ef11, ef12, ef21, ef22);
  524. }
  525. // note that the section above is different from
  526. // xoExtra.vSetElementsLToL(ef11, ef12, ef21, ef22);
  527. // because of our interpretation of NtoD xform. with our conventions
  528. // ntod xform transforms notional space defined as having y axis pointing down
  529. // to device space also with y axis down by left vector mult.
  530. // vD = vN * N2D. The matrix passed by the user uses different convention:
  531. // y axis up in both spaces. so we have to use
  532. // Sigma_3 M Sigma_3 instead of M, (Sigma_3 = diag(1,-1)) to convert
  533. // from app convetions to our conventions [bodind]
  534. xoExtra.vRemoveTranslation(); // don't leave translations uninitialized
  535. // Need these EXFORMOBJs to calculate the new CONTEXTINFO.
  536. MATRIX mxN2D;
  537. EXFORMOBJ xoN2D(&mxN2D, XFORM_FORMAT_LTOFX);
  538. MATRIX mxNewN2D;
  539. EXFORMOBJ xoNewN2D(&mxNewN2D, XFORM_FORMAT_LTOFX);
  540. // EXFORMOBJs should not be able to fail.
  541. ASSERTGDI (
  542. xoN2D.bValid() && xoNewN2D.bValid(),
  543. "GreGetGlyphOutline(): EXFORMOBJ failed\n"
  544. );
  545. FD_XFORM fdx;
  546. if( bIgnoreRotation )
  547. {
  548. // If bIgnoreRotation is set it means we've been called from WOW and
  549. // need toingore the orientation and escapment values in the LOGFONT.
  550. // To do this we will need to recompute the font driver transform.
  551. // This behavior is neccesary for Corel Draw 5.0 to be able to print
  552. // rotated text properly.
  553. PFEOBJ pfeo(rfo.ppfe());
  554. ASSERTGDI(pfeo.bValid(), "gdisrv!RFONTOBJ(dco): bad ppfe from mapping\n");
  555. IFIOBJ ifio(pfeo.pifi());
  556. POINTL ptlSim;
  557. ptlSim.x = ptlSim.y = 0;
  558. if (
  559. !pfeo.bSetFontXform(
  560. dco, lfo.plfw(),
  561. &fdx,
  562. ND_IGNORE_ESC_AND_ORIENT,
  563. 0,
  564. (POINTL* const) &ptlSim,
  565. ifio,
  566. FALSE
  567. )
  568. )
  569. {
  570. WARNING("RESETFCOBJ: failed to compute font transform\n");
  571. bValid_ = FALSE;
  572. return;
  573. }
  574. xoN2D.vRemoveTranslation();
  575. xoN2D.vSetElementsLToFx( fdx.eXX, fdx.eXY, fdx.eYX, fdx.eYY );
  576. xoN2D.vComputeAccelFlags(XFORM_FORMAT_LTOFX);
  577. }
  578. else
  579. {
  580. rfo.vSetNotionalToDevice(xoN2D);
  581. }
  582. // Combine the transforms.
  583. if ( !xoNewN2D.bMultiply(xoN2D, xoExtra, DONT_COMPUTE_FLAGS | XFORM_FORMAT_LTOFX) )
  584. {
  585. WARNING("GreGetGlyphOutline(): EXFORMOBJ::bMultiply failed\n");
  586. bValid_ = FALSE;
  587. return;
  588. }
  589. // Get the new transform as an FD_XFORM.
  590. xoNewN2D.vGetCoefficient(&fdx);
  591. // Attempt to get an RFONT with the new transform.
  592. bValid_ = rfo.bSetNewFDX(dco, fdx, flType);
  593. }
  594. }
  595. /******************************Public*Routine******************************\
  596. *
  597. * RESETFCOBJ::~RESETFCOBJ()
  598. *
  599. * resets the xform in rfo.hfc to its original value
  600. *
  601. * History:
  602. * 01-Nov-1992 Gilman Wong [gilmanw]
  603. * IFI/DDI merge.
  604. *
  605. * 11-Jun-1992 -by- Bodin Dresevic [BodinD]
  606. * Wrote it.
  607. \**************************************************************************/
  608. RESETFCOBJ::~RESETFCOBJ()
  609. {
  610. if (bValid_ && !bTrivialXform)
  611. {
  612. // Release the cache semaphore and make inactive.
  613. prfo->vReleaseCache();
  614. prfo->vMakeInactive();
  615. }
  616. }
  617. #define BITS_OFFSET (offsetof(GLYPHBITS,aj))
  618. BOOL IsSingularEudcGlyph
  619. (
  620. GLYPHDATA *wpgd, BOOL bSimulatedBold
  621. );
  622. /******************************Public*Routine******************************\
  623. * GreGetGlyphOutline
  624. *
  625. * History:
  626. * 05-Mar-1995 Kirk Olynyk [kirko]
  627. * Added support for GGO_GRAY2_BITMAP, GGO_GRAY4_BITMAP, GGO_GRAY8_BITMAP.
  628. * I have introduced new modes for DrvQueryFontData that require
  629. * that the bitmaps have scans that begin and end on DWORD
  630. * boundaries as required by GetGlyphOutline(). This is the
  631. * natural format of the TrueType driver.
  632. * I also rearranged the code to have a single return point.
  633. * 01-Nov-1992 Gilman Wong [gilmanw]
  634. * IFI/DDI merge.
  635. *
  636. * 16-Feb-1992 -by- Gilman Wong [gilmanw]
  637. * Wrote it.
  638. \**************************************************************************/
  639. ULONG GreGetGlyphOutlineInternal (
  640. HDC hdc,
  641. WCHAR wch, // WCHAR or HGLYPH???
  642. UINT ulFormat, // data format
  643. GLYPHMETRICS *lpgm, // glyph metrics
  644. ULONG cjBuffer, // size of buffer
  645. void *pvBuffer, // buffer for data in the format, ulFormat
  646. MAT2 *lpmat2, // "extra" xform applied after existing Notional to Device xform
  647. BOOL bIgnoreRotation
  648. )
  649. {
  650. HGLYPH hg;
  651. GLYPHDATA gd;
  652. ULONG iMode, uRet, cjRet;
  653. BOOL bGlyphIndex, bBufferSizeWanted, flTTO;
  654. BOOL bUnhinted;
  655. FLONG flType;
  656. cjRet = GDI_ERROR; // assume error
  657. bGlyphIndex = (ulFormat & GGO_GLYPH_INDEX); // record glyph index bit
  658. bUnhinted = (ulFormat & GGO_UNHINTED); // remember if unhinted outlines are wanted
  659. ulFormat &= ~(GGO_GLYPH_INDEX | GGO_UNHINTED); // and then erase it from ulFormat
  660. bBufferSizeWanted = (pvBuffer == 0) || (cjBuffer == 0);
  661. flType = bGlyphIndex ? RFONT_TYPE_HGLYPH : RFONT_TYPE_UNICODE;
  662. if ( (lpgm == 0) || (lpmat2 == 0) )
  663. {
  664. WARNING("GreGetGlyphOutline(): bad parameter\n");
  665. SAVE_ERROR_CODE( ERROR_INVALID_PARAMETER );
  666. }
  667. else
  668. {
  669. DCOBJ dco(hdc);
  670. if ( !dco.bValid() )
  671. {
  672. WARNING("GreGetGlyphOutline(): bad handle for DC\n");
  673. SAVE_ERROR_CODE( ERROR_INVALID_HANDLE );
  674. }
  675. else
  676. {
  677. RFONTOBJ rfo(dco, FALSE);
  678. RFONTTMPOBJ rfoLinkSystem;
  679. RFONTTMPOBJ rfoLinkDefault;
  680. RFONTTMPOBJ rfoLinkFace;
  681. GLYPHDATA *wpgdTemp;
  682. PRFONT prfnt;
  683. PRFONT prfntTmp;
  684. UINT EudcType;
  685. UINT numFaceName;
  686. BOOL bEUDC = FALSE;
  687. // Set Basefont as default.
  688. RFONTOBJ *prfo = &rfo;
  689. // restructure this later
  690. if(!rfo.bValid())
  691. {
  692. goto GetGlyphOutlineData;
  693. }
  694. // Get the HGLYPH for the WCHAR. Note we only check bGlyphIndex for the
  695. // original font. If this is an hglyph rfont then we wont allow linked
  696. // glyphs
  697. hg = (bGlyphIndex) ? (HGLYPH) wch : rfo.hgXlat(wch);
  698. // Check the target glyph is linked font or base font.
  699. if ((hg == rfo.hgDefault()) && !bGlyphIndex && rfo.bIsLinkedGlyph(wch))
  700. {
  701. prfnt = rfo.prfntFont();
  702. GreAcquireSemaphore(prfnt->hsemEUDC);
  703. HGLYPH hgFound = HGLYPH_INVALID;
  704. HGLYPH hgLink = HGLYPH_INVALID;
  705. // this value will be decremented in RFONTOBJ::dtHeler()
  706. INCREMENTEUDCCOUNT;
  707. FLINKMESSAGE2(DEBUG_FONTLINK_RFONT,
  708. "GreGetGlyphOutlineInternal():No request to change EUDC \
  709. data %d\n",gcEUDCCount);
  710. // initialize EUDC info
  711. rfo.vInitEUDC(dco);
  712. // if we have system wide eudc, lock the cache.
  713. if( prfnt->prfntSysEUDC != NULL )
  714. {
  715. RFONTTMPOBJ rfoTemp( prfnt->prfntSysEUDC );
  716. rfoTemp.vGetCache();
  717. }
  718. // The linked RFONT is initialized for Default EUDC grab the semaphore.
  719. if( prfnt->prfntDefEUDC != NULL )
  720. {
  721. RFONTTMPOBJ rfoTemp( prfnt->prfntDefEUDC );
  722. rfoTemp.vGetCache();
  723. }
  724. // if we have face name eudc, lock the cache for all the linked fonts
  725. for( UINT ii = 0; ii < prfnt->uiNumLinks; ii++ )
  726. {
  727. RFONTTMPOBJ rfoTemp( prfnt->paprfntFaceName[ii] );
  728. rfoTemp.vGetCache();
  729. }
  730. // Need to indicate that this RFONT's EUDC data has been initialized.
  731. prfnt->flEUDCState |= EUDC_INITIALIZED;
  732. GreReleaseSemaphore(prfnt->hsemEUDC);
  733. // First, try to find out target glyph from facename linked font.
  734. numFaceName = 0;
  735. for( ii = 0; ii < prfnt->uiNumLinks; ii++ )
  736. {
  737. rfoLinkFace.vInit( prfnt->paprfntFaceName[ii] );
  738. if ((hgLink = rfoLinkFace.hgXlat(wch)) != rfoLinkFace.hgDefault())
  739. {
  740. RFONTTMPOBJ rfoTemp( prfnt->paprfntFaceName[ii] );
  741. if (rfoTemp.bValid())
  742. {
  743. if( (wpgdTemp = rfoTemp.pgdGetEudcMetrics( wch, &rfo)) != NULL )
  744. {
  745. if( !IsSingularEudcGlyph(wpgdTemp, rfoTemp.pfo()->flFontType & FO_SIM_BOLD))
  746. {
  747. numFaceName = ii;
  748. EudcType = EUDCTYPE_FACENAME;
  749. hgFound = hgLink;
  750. prfo = &rfoLinkFace;
  751. break;
  752. }
  753. }
  754. }
  755. }
  756. }
  757. // Check if the glyph is in the DEFAULT EUDC font
  758. if( (hgFound == HGLYPH_INVALID) && (prfnt->prfntDefEUDC != NULL) )
  759. {
  760. rfoLinkDefault.vInit( prfnt->prfntDefEUDC );
  761. if ((hgLink = rfoLinkDefault.hgXlat(wch)) != rfoLinkDefault.hgDefault())
  762. {
  763. RFONTTMPOBJ rfoTemp( prfnt->prfntDefEUDC );
  764. if (rfoTemp.bValid())
  765. {
  766. if( (wpgdTemp = rfoTemp.pgdGetEudcMetrics( wch , &rfo)) != NULL )
  767. {
  768. if( !IsSingularEudcGlyph(wpgdTemp, rfoTemp.pfo()->flFontType & FO_SIM_BOLD) )
  769. {
  770. numFaceName = 0;
  771. EudcType = EUDCTYPE_DEFAULT;
  772. hgFound = hgLink;
  773. prfo = &rfoLinkDefault;
  774. }
  775. }
  776. }
  777. }
  778. }
  779. // Try to find out System EUDC.
  780. if( (hgFound == HGLYPH_INVALID) && (prfnt->prfntSysEUDC != NULL) )
  781. {
  782. rfoLinkSystem.vInit( prfnt->prfntSysEUDC );
  783. if ((hgLink = rfoLinkSystem.hgXlat(wch)) != rfoLinkSystem.hgDefault())
  784. {
  785. numFaceName = 0;
  786. EudcType = EUDCTYPE_SYSTEM_WIDE;
  787. hgFound = hgLink;
  788. prfo = &rfoLinkSystem;
  789. }
  790. }
  791. if( hgFound != HGLYPH_INVALID )
  792. {
  793. hg = hgFound;
  794. bEUDC = TRUE; // find any EUDC object. prfo is not rfo object.
  795. }
  796. else
  797. {
  798. rfo.dtHelper();
  799. prfnt->flEUDCState = FALSE;
  800. }
  801. }
  802. GetGlyphOutlineData:
  803. if ( !prfo->bValid() )
  804. {
  805. WARNING("GreGetGlyphOutline(): could not lock HRFONT\n");
  806. SAVE_ERROR_CODE( ERROR_CAN_NOT_COMPLETE );
  807. }
  808. else
  809. {
  810. PDEVOBJ pdo( prfo->hdevProducer() );
  811. if ( !pdo.bValid() )
  812. {
  813. WARNING("GreGetGlyphOutline -- invalid PDEV\n");
  814. SAVE_ERROR_CODE( ERROR_CAN_NOT_COMPLETE );
  815. }
  816. else if ( !PPFNVALID(pdo, QueryTrueTypeOutline) )
  817. {
  818. WARNING1("GreGetGlyphOuline -- DrvQueryTrueTypeOutline\n");
  819. SAVE_ERROR_CODE( ERROR_CAN_NOT_COMPLETE );
  820. }
  821. else
  822. {
  823. // reset the xform in the rfo.hfc() if needed:
  824. RESETFCOBJ resetfco( dco, *prfo, lpmat2, bIgnoreRotation, flType );
  825. if ( !resetfco.bValid() )
  826. {
  827. WARNING("GreGetGlyphOutline(): resetfco\n");
  828. SAVE_ERROR_CODE( ERROR_CAN_NOT_COMPLETE );
  829. }
  830. else
  831. {
  832. prfntTmp = NULL;
  833. if (bEUDC && !resetfco.bTrivXform())
  834. {
  835. switch (EudcType)
  836. {
  837. case EUDCTYPE_SYSTEM_WIDE:
  838. prfntTmp = prfnt->prfntSysEUDC;
  839. prfnt->prfntSysEUDC = NULL;
  840. break;
  841. case EUDCTYPE_DEFAULT:
  842. prfntTmp = prfnt->prfntDefEUDC;
  843. prfnt->prfntDefEUDC = NULL;
  844. break;
  845. case EUDCTYPE_FACENAME:
  846. prfntTmp = prfnt->paprfntFaceName[numFaceName];
  847. prfnt->paprfntFaceName[numFaceName] = NULL;
  848. break;
  849. default:
  850. break;
  851. }
  852. }
  853. switch ( ulFormat )
  854. {
  855. case GGO_BITMAP:
  856. case GGO_GRAY2_BITMAP:
  857. case GGO_GRAY4_BITMAP:
  858. case GGO_GRAY8_BITMAP:
  859. switch ( ulFormat )
  860. {
  861. case GGO_BITMAP:
  862. iMode = QFD_TT_GRAY1_BITMAP; // 8 pixels per byte
  863. break;
  864. case GGO_GRAY2_BITMAP:
  865. iMode = QFD_TT_GRAY2_BITMAP; // one byte per pixel: 0..4
  866. break;
  867. case GGO_GRAY4_BITMAP:
  868. iMode = QFD_TT_GRAY4_BITMAP; // one byte per pixel: 0..16
  869. break;
  870. case GGO_GRAY8_BITMAP:
  871. iMode = QFD_TT_GRAY8_BITMAP; // one byte per pixel: 0..64
  872. break;
  873. }
  874. cjRet =
  875. pdo.QueryFontData(
  876. 0, // device handle of PDEV
  877. prfo->pfo(),
  878. iMode, // QFD_TT_GRAY[1248]_BITMAP
  879. hg, // glyph handle
  880. &gd, // pointer to GLYPHDATA structure
  881. pvBuffer, // pointer to dest buffer
  882. cjBuffer // size of dest buffer
  883. );
  884. break;
  885. case GGO_NATIVE:
  886. case GGO_BEZIER:
  887. flTTO = 0;
  888. if (ulFormat == GGO_BEZIER)
  889. flTTO |= TTO_QUBICS;
  890. if (bUnhinted)
  891. flTTO |= TTO_UNHINTED;
  892. // We're lucky, FdQueryTrueTypeOutline will return size if EITHER
  893. // a NULL buffer or size of zero is passed in. So we don't need
  894. // separate cases. Note that this assumes that the outline is
  895. // appropriate to a monochrome bitmap. There should be no scaling
  896. // for the case of antialiased fonts.
  897. cjRet =
  898. pdo.QueryTrueTypeOutline(
  899. 0,
  900. prfo->pfo(),
  901. hg,
  902. flTTO,
  903. &gd,
  904. cjBuffer,
  905. (TTPOLYGONHEADER *) pvBuffer
  906. );
  907. if ( cjRet == FD_ERROR )
  908. {
  909. ASSERTGDI(cjRet == GDI_ERROR, "FD_ERROR != GDI_ERROR\n");
  910. WARNING(
  911. "GreGetGlyphOutline(): FdQueryTrueTypeOutline()"
  912. "--couldn't get buffer size\n"
  913. );
  914. }
  915. break;
  916. case GGO_METRICS:
  917. // Call to get just the metrics.
  918. cjRet =
  919. pdo.QueryFontData(
  920. 0, // device handle of PDEV
  921. prfo->pfo(),
  922. QFD_TT_GLYPHANDBITMAP, // mode of call
  923. hg, // glyph handle
  924. &gd, // pointer to GLYPHDATA structure
  925. 0, // pointer to destination buffer
  926. 0 // size of destination buffer in bytes
  927. );
  928. if ( cjRet == FD_ERROR )
  929. {
  930. ASSERTGDI(cjRet == GDI_ERROR, "FD_ERROR != GDI_ERROR\n");
  931. WARNING(
  932. "GreGetGlyphOutline(): FdQueryFontData()"
  933. "--couldn't get GLYPHMETRICS\n"
  934. );
  935. }
  936. break;
  937. default:
  938. WARNING("GreGetGlyphOutline(): bad parameter, unknown format\n");
  939. break;
  940. }
  941. }
  942. if ( cjRet != GDI_ERROR )
  943. {
  944. // Convert the GLYPHDATA metrics to GLYPHMETRICS.
  945. lpgm->gmBlackBoxX = (UINT) (gd.rclInk.right - gd.rclInk.left);
  946. lpgm->gmBlackBoxY = (UINT) (gd.rclInk.bottom - gd.rclInk.top);
  947. // this is true by virtue of the fact that for tt fonts bitmap
  948. // is of the same size as the black box. The exception to this
  949. // rule is the empty space char which is a blank 1x1 bitmap
  950. lpgm->gmptGlyphOrigin.x = gd.rclInk.left;
  951. lpgm->gmptGlyphOrigin.y = - gd.rclInk.top;
  952. lpgm->gmCellIncX = (WORD) FXTOLROUND(gd.ptqD.x.u.HighPart);
  953. lpgm->gmCellIncY = (WORD) FXTOLROUND(gd.ptqD.y.u.HighPart);
  954. }
  955. }
  956. if (bEUDC)
  957. {
  958. rfo.dtHelper(FALSE);
  959. prfnt->flEUDCState = FALSE;
  960. if (prfntTmp)
  961. {
  962. switch (EudcType)
  963. {
  964. case EUDCTYPE_SYSTEM_WIDE:
  965. prfnt->prfntSysEUDC = prfntTmp;
  966. break;
  967. case EUDCTYPE_DEFAULT:
  968. prfnt->prfntDefEUDC = prfntTmp;
  969. break;
  970. case EUDCTYPE_FACENAME:
  971. prfnt->paprfntFaceName[numFaceName] = prfntTmp;
  972. break;
  973. default:
  974. break;
  975. }
  976. }
  977. ASSERTGDI(gcEUDCCount > 0, "gcEUDCCount <= 0");
  978. DECREMENTEUDCCOUNT;
  979. }
  980. }
  981. }
  982. }
  983. return( cjRet );
  984. }
  985. VOID vIFIMetricsToETM(
  986. EXTTEXTMETRIC *petm,
  987. RFONTOBJ& rfo,
  988. DCOBJ& dco,
  989. IFIMETRICS *pifi
  990. );
  991. /******************************Public*Routine******************************\
  992. *
  993. * GreGetETM
  994. *
  995. * support for aldus escape
  996. *
  997. * History:
  998. * 19-Oct-1993 -by- Bodin Dresevic [BodinD]
  999. * Wrote it.
  1000. \**************************************************************************/
  1001. BOOL
  1002. APIENTRY
  1003. NtGdiGetETM(
  1004. HDC hdc,
  1005. EXTTEXTMETRIC *petm
  1006. )
  1007. {
  1008. EXTTEXTMETRIC kmETM;
  1009. BOOL bRet = FALSE;
  1010. // Get DC user object.
  1011. DCOBJ dco(hdc);
  1012. if (petm && dco.bValid())
  1013. {
  1014. RFONTOBJ rfo(dco, FALSE);
  1015. if (rfo.bValid())
  1016. {
  1017. // see if we can dispatch the call directly to the device driver
  1018. PDEVOBJ pdo(rfo.hdevProducer());
  1019. if (PPFNDRV(pdo,FontManagement))
  1020. {
  1021. ULONG iMode = GETEXTENDEDTEXTMETRICS;
  1022. SURFOBJ *pso = NULL;
  1023. if (pdo.bUMPD())
  1024. {
  1025. // we need to have a dhpdev when calling out to UMPD
  1026. pso = (SURFOBJ *)pdo.dhpdev();
  1027. }
  1028. BOOL bSupported = GetETMFontManagement(
  1029. rfo,
  1030. pdo,
  1031. pso,
  1032. NULL,
  1033. QUERYESCSUPPORT, // iMode
  1034. sizeof(ULONG), // cjIn
  1035. (PVOID)&iMode, // pvIn
  1036. 0, // cjOut
  1037. (PVOID)NULL // pvOut
  1038. );
  1039. if (bSupported)
  1040. {
  1041. SURFOBJ soFake;
  1042. SURFOBJ *pso = pdo.pSurface()->pSurfobj();
  1043. if (pso == (SURFOBJ *) NULL) // create vanilla surfobj
  1044. {
  1045. RtlFillMemory((BYTE *) &soFake,sizeof(SURFOBJ),0);
  1046. soFake.dhpdev = rfo.prfnt->dhpdev;
  1047. soFake.hdev = rfo.hdevConsumer();
  1048. soFake.iType = (USHORT)STYPE_DEVICE;
  1049. pso = &soFake;
  1050. }
  1051. bRet = pdo.FontManagement(
  1052. pso,
  1053. rfo.pfo(),
  1054. GETEXTENDEDTEXTMETRICS,
  1055. 0,
  1056. (PVOID)NULL,
  1057. (ULONG)sizeof(EXTTEXTMETRIC),
  1058. (PVOID)&kmETM
  1059. );
  1060. }
  1061. }
  1062. // if GETEXTENDEDTEXTMETRIC is not supported do something:
  1063. // Get PFE user object.
  1064. if (!bRet)
  1065. {
  1066. PFEOBJ pfeo(rfo.ppfe());
  1067. if (pfeo.bValid())
  1068. {
  1069. if (pfeo.flFontType() & TRUETYPE_FONTTYPE)
  1070. {
  1071. vIFIMetricsToETM(&kmETM,rfo,dco,pfeo.pifi());
  1072. bRet = TRUE;
  1073. }
  1074. }
  1075. }
  1076. }
  1077. }
  1078. if (bRet)
  1079. {
  1080. __try
  1081. {
  1082. ProbeForWrite(petm,sizeof(EXTTEXTMETRIC),sizeof(ULONG));
  1083. RtlMoveMemory(petm,&kmETM,sizeof(EXTTEXTMETRIC));
  1084. }
  1085. __except(EXCEPTION_EXECUTE_HANDLER)
  1086. {
  1087. // SetLastError(GetExceptionCode());
  1088. bRet = FALSE;
  1089. }
  1090. }
  1091. return bRet;
  1092. }
  1093. /******************************Public*Routine******************************\
  1094. * GreGetOutlineTextMetricsInternalW
  1095. *
  1096. * History:
  1097. *
  1098. * 20-Apr-1993 -by- Gerrit van Wingerden [gerritv]
  1099. * Added bTTOnly field so we can service the Aldus escape for Win 3.1 compat.
  1100. * Changed to GreGe...InternalW to avoid a header file change in wingdip.h
  1101. *
  1102. * 16-Feb-1992 -by- Gilman Wong [gilmanw]
  1103. * Wrote it.
  1104. \**************************************************************************/
  1105. UINT cjOTMAWSize (
  1106. PIFIMETRICS pifi, // compute size of OTM produced by this buffer
  1107. UINT *pcjotmw
  1108. );
  1109. ULONG
  1110. GreGetOutlineTextMetricsInternalW(
  1111. HDC hdc,
  1112. ULONG cjotm,
  1113. OUTLINETEXTMETRICW *potmw,
  1114. TMDIFF *ptmd
  1115. )
  1116. {
  1117. ULONG cjRet = 0;
  1118. // Early out test. Zero data requested.
  1119. if ( (cjotm == 0) && (potmw != (OUTLINETEXTMETRICW*) NULL) )
  1120. {
  1121. WARNING("GreGetOutlineTextMetrics(): bad parameter\n");
  1122. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1123. return (cjRet);
  1124. }
  1125. // Get DC user object.
  1126. DCOBJ dco(hdc);
  1127. if (!dco.bValid())
  1128. {
  1129. WARNING("GreGetOutlineTextMetrics(): bad handle for DC\n");
  1130. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  1131. return (cjRet);
  1132. }
  1133. // the following is a copy of what is done during GreGetCharSet(), to fix 735873
  1134. // where bIFIMetricsToTextMetricWStrict() get called while DIRTY_CHARSET is set and
  1135. // copy an unitialized value from dco.pdc->iCS_CP to ptmw->tmCharSet
  1136. // if the font is not mapped, we need to map it
  1137. if (dco.ulDirty() & DIRTY_CHARSET)
  1138. {
  1139. // force mapping
  1140. FLONG flSim;
  1141. POINTL ptlSim;
  1142. FLONG flAboutMatch;
  1143. PFE *ppfe;
  1144. PDEVOBJ pdo(dco.hdev());
  1145. ASSERTGDI(pdo.bValid(), "GreGetOutlineTextMetrics: bad pdev in dc\n");
  1146. if (!pdo.bGotFonts())
  1147. pdo.bGetDeviceFonts();
  1148. LFONTOBJ lfo(dco.pdc->hlfntNew(), &pdo);
  1149. if (!lfo.bValid())
  1150. {
  1151. WARNING("GreGetOutlineTextMetrics!RFONTOBJ(dco): bad LFONT handle\n");
  1152. return(cjRet);
  1153. }
  1154. {
  1155. // Stabilize the public PFT for mapping.
  1156. SEMOBJ so(ghsemPublicPFT);
  1157. // LFONTOBJ::ppfeMapFont returns a pointer to the physical font face and
  1158. // a simulation type (ist)
  1159. // also store charset to the DC
  1160. ppfe = lfo.ppfeMapFont(dco, &flSim, &ptlSim, &flAboutMatch);
  1161. ASSERTGDI(!(dco.ulDirty() & DIRTY_CHARSET),
  1162. "NtGdiGetCharSet, charset is dirty\n");
  1163. }
  1164. }
  1165. // Get RFONT user object.
  1166. // Old Comment:
  1167. // - This should really be an LFONTOBJ
  1168. RFONTOBJ rfo(dco, FALSE);
  1169. if (!rfo.bValid())
  1170. {
  1171. WARNING("GreGetOutlineTextMetrics(): could not lock HRFONT\n");
  1172. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  1173. return (cjRet);
  1174. }
  1175. // Get PFE user object.
  1176. PFEOBJ pfeo(rfo.ppfe());
  1177. if (!pfeo.bValid())
  1178. {
  1179. WARNING("GreGetOutlineTextMetrics(): could not lock HPFE\n");
  1180. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  1181. return (cjRet);
  1182. }
  1183. // Get LDEV user object for the font driver.
  1184. PDEVOBJ pdo(rfo.hdevProducer());
  1185. // Check the font driver. If we are in TT only mode, we will allow only
  1186. // the TrueType driver to succeed. However, in this sense, the TrueType
  1187. // driver is any driver that exports DrvQueryTrueTypeOutline. Afterall,
  1188. // if it can supply the actual outlines, it should be able to supply the
  1189. // metrics.
  1190. //
  1191. // Actually, it would be nice to allow this function to work for all
  1192. // drivers since all drivers supply the IFIMETRICS and therefore can
  1193. // answer this question. However, we are much too afraid that this will
  1194. // break some obscure compatibility so we will let our TT driver and
  1195. // 3rd part TT-like drivers succeed.
  1196. //
  1197. // If we not in TT only mode, then everybody succeed this function! Yay!
  1198. if (PPFNVALID(pdo, QueryTrueTypeOutline))
  1199. {
  1200. // Size if full OUTLINETEXTMETRICW (including strings) is copied.
  1201. UINT cjotmw;
  1202. // use cjotma field of tmd to ship cjotma to the client side, [bodind]
  1203. ptmd->cjotma = (ULONG)cjOTMAWSize(pfeo.pifi(), &cjotmw);
  1204. // If return buffer is NULL, then only size needs to be returned.
  1205. if (potmw == NULL)
  1206. {
  1207. cjRet = cjotmw;
  1208. }
  1209. else
  1210. {
  1211. // Is return buffer big enough for the conversion routine (which is not
  1212. // capable of converting a partial OUTLINETEXTMETRICW structure [unless,
  1213. // of course, it's one without the strings]).
  1214. if (cjotm <= sizeof(OUTLINETEXTMETRICW))
  1215. {
  1216. // Allocate a buffer for a full OUTLINETEXTMETRICW, since conversion
  1217. // routine needs at least that much memory.
  1218. OUTLINETEXTMETRICW otmwTmp;
  1219. RtlZeroMemory(&otmwTmp, sizeof(OUTLINETEXTMETRICW));
  1220. // Convert IFIMETRICS to OUTLINETEXTMETRICW using temp buffer.
  1221. if (
  1222. (cjRet = cjIFIMetricsToOTMW(
  1223. ptmd,
  1224. &otmwTmp,
  1225. rfo,
  1226. dco,
  1227. pfeo.pifi(),
  1228. FALSE // do not need strings
  1229. )) == 0 )
  1230. {
  1231. WARNING("GreGetOutlineTextMetrics(): error creating OUTLINETEXTMETRIC\n");
  1232. return (cjRet);
  1233. }
  1234. // Copy needed part of OUTLINETEXTMETRICW into return buffer.
  1235. RtlCopyMemory((PVOID) potmw, (PVOID) &otmwTmp, cjotm);
  1236. return cjotm;
  1237. }
  1238. // Otherwise asking for strings
  1239. // We have to assume that all the strings are desired. If
  1240. // cjCopy > sizeof(OUTLINETEXTMETRICW) how can we
  1241. // know how many strings are requested? Afterall, the app is not
  1242. // supposed to have apriori knowledge of the length of the strings.
  1243. // Note that this is also a Win3.1 compatible assumption. (They
  1244. // assume the same thing).
  1245. if ( cjotm >= cjotmw )
  1246. {
  1247. // Convert IFIMETRICS to OUTLINETEXTMETRICW using return buffer.
  1248. cjRet = cjIFIMetricsToOTMW(ptmd,potmw, rfo, dco, pfeo.pifi(), TRUE);
  1249. // clean up the rest of the buffer so that neilc - " Mr. c2 guy" is happy
  1250. {
  1251. LONG lDiff = (LONG)cjotm - (LONG)cjRet;
  1252. ASSERTGDI(lDiff >= 0, "GetOTM, lDiff < 0");
  1253. if (lDiff > 0)
  1254. RtlZeroMemory(((BYTE*)potmw + cjRet), lDiff);
  1255. }
  1256. }
  1257. }
  1258. }
  1259. return (cjRet);
  1260. }