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.

4134 lines
130 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: rfntobj.cxx *
  3. * *
  4. * Non-inline methods for realized font objects. *
  5. * *
  6. * Created: 30-Oct-1990 09:32:48 *
  7. * Author: Gilman Wong [gilmanw] *
  8. * *
  9. * Copyright (c) 1993-1999 Microsoft Corporation *
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. #include "flhack.hxx"
  13. #ifdef _HYDRA_
  14. #include "muclean.hxx"
  15. #endif
  16. #include "winsta.h"
  17. //
  18. // Storage for static globals in rfntobj.hxx
  19. //
  20. extern BOOL G_fConsole;
  21. extern "C" USHORT gProtocolType;
  22. #define IsRemoteConnection() (gProtocolType != PROTOCOL_CONSOLE)
  23. FONTFILE_PRINTKVIEW *gpPrintKViewList = NULL;
  24. HSEMAPHORE ghsemPrintKView;
  25. NTSTATUS MapFontFileInKernel(void*, void**);
  26. VOID vUnmapFontFileInKernel(void* pvKView);
  27. void vCleanupPrintKViewList();
  28. const GAMMA_TABLES RFONTOBJ::gTables =
  29. {
  30. {
  31. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  32. , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  33. , 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01
  34. , 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02
  35. , 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03
  36. , 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05
  37. , 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07
  38. , 0x07, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09
  39. , 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0D
  40. , 0x0D, 0x0D, 0x0E, 0x0E, 0x0F, 0x0F, 0x10, 0x10
  41. , 0x11, 0x11, 0x12, 0x12, 0x13, 0x13, 0x14, 0x14
  42. , 0x15, 0x15, 0x16, 0x17, 0x17, 0x18, 0x18, 0x19
  43. , 0x1A, 0x1A, 0x1B, 0x1C, 0x1C, 0x1D, 0x1E, 0x1E
  44. , 0x1F, 0x20, 0x20, 0x21, 0x22, 0x23, 0x23, 0x24
  45. , 0x25, 0x26, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2A
  46. , 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x31
  47. , 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39
  48. , 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41
  49. , 0x42, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A
  50. , 0x4B, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x53, 0x54
  51. , 0x55, 0x56, 0x58, 0x59, 0x5A, 0x5C, 0x5D, 0x5E
  52. , 0x60, 0x61, 0x62, 0x64, 0x65, 0x66, 0x68, 0x69
  53. , 0x6B, 0x6C, 0x6D, 0x6F, 0x70, 0x72, 0x73, 0x75
  54. , 0x76, 0x78, 0x79, 0x7B, 0x7C, 0x7E, 0x80, 0x81
  55. , 0x83, 0x84, 0x86, 0x88, 0x89, 0x8B, 0x8D, 0x8E
  56. , 0x90, 0x92, 0x93, 0x95, 0x97, 0x99, 0x9A, 0x9C
  57. , 0x9E, 0xA0, 0xA1, 0xA3, 0xA5, 0xA7, 0xA9, 0xAB
  58. , 0xAD, 0xAE, 0xB0, 0xB2, 0xB4, 0xB6, 0xB8, 0xBA
  59. , 0xBC, 0xBE, 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA
  60. , 0xCC, 0xCE, 0xD0, 0xD2, 0xD5, 0xD7, 0xD9, 0xDB
  61. , 0xDD, 0xDF, 0xE1, 0xE4, 0xE6, 0xE8, 0xEA, 0xED
  62. , 0xEF, 0xF1, 0xF3, 0xF6, 0xF8, 0xFA, 0xFD, 0xFF
  63. }
  64. ,
  65. {
  66. 0x00, 0x18, 0x20, 0x27, 0x2C, 0x30, 0x34, 0x37
  67. , 0x3B, 0x3E, 0x40, 0x43, 0x46, 0x48, 0x4A, 0x4D
  68. , 0x4F, 0x51, 0x53, 0x55, 0x56, 0x58, 0x5A, 0x5C
  69. , 0x5D, 0x5F, 0x61, 0x62, 0x64, 0x65, 0x67, 0x68
  70. , 0x6A, 0x6B, 0x6C, 0x6E, 0x6F, 0x70, 0x72, 0x73
  71. , 0x74, 0x75, 0x76, 0x78, 0x79, 0x7A, 0x7B, 0x7C
  72. , 0x7D, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85
  73. , 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8C
  74. , 0x8E, 0x8F, 0x90, 0x91, 0x91, 0x92, 0x93, 0x94
  75. , 0x95, 0x96, 0x97, 0x98, 0x98, 0x99, 0x9A, 0x9A
  76. , 0x9C, 0x9D, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA1
  77. , 0xA2, 0xA3, 0xA4, 0xA5, 0xA5, 0xA6, 0xA7, 0xA7
  78. , 0xA8, 0xA9, 0xAA, 0xAB, 0xAB, 0xAC, 0xAD, 0xAD
  79. , 0xAE, 0xAF, 0xB0, 0xB0, 0xB1, 0xB2, 0xB2, 0xB2
  80. , 0xB4, 0xB4, 0xB5, 0xB6, 0xB6, 0xB7, 0xB8, 0xB8
  81. , 0xB9, 0xBA, 0xBA, 0xBB, 0xBC, 0xBC, 0xBD, 0xBD
  82. , 0xBE, 0xBF, 0xC0, 0xC0, 0xC1, 0xC1, 0xC2, 0xC3
  83. , 0xC3, 0xC4, 0xC4, 0xC5, 0xC6, 0xC6, 0xC7, 0xC7
  84. , 0xC8, 0xC9, 0xC9, 0xCA, 0xCA, 0xCB, 0xCC, 0xCC
  85. , 0xCD, 0xCD, 0xCE, 0xCE, 0xCF, 0xD0, 0xD0, 0xD0
  86. , 0xD1, 0xD2, 0xD2, 0xD3, 0xD3, 0xD4, 0xD4, 0xD5
  87. , 0xD6, 0xD6, 0xD7, 0xD7, 0xD8, 0xD8, 0xD9, 0xD9
  88. , 0xDA, 0xDA, 0xDB, 0xDB, 0xDC, 0xDC, 0xDD, 0xDD
  89. , 0xDE, 0xDE, 0xDF, 0xE0, 0xE0, 0xE1, 0xE1, 0xE1
  90. , 0xE2, 0xE3, 0xE3, 0xE4, 0xE4, 0xE5, 0xE5, 0xE5
  91. , 0xE6, 0xE6, 0xE7, 0xE7, 0xE8, 0xE8, 0xE9, 0xE9
  92. , 0xEA, 0xEA, 0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED
  93. , 0xEE, 0xEE, 0xEF, 0xEF, 0xEF, 0xF0, 0xF0, 0xF0
  94. , 0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4, 0xF5
  95. , 0xF5, 0xF5, 0xF6, 0xF6, 0xF7, 0xF7, 0xF8, 0xF8
  96. , 0xF9, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC
  97. , 0xFC, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFF, 0xFF
  98. }
  99. };
  100. LONG lNormAngle(LONG lAngle);
  101. BOOL
  102. bGetNtoWScales (
  103. EPOINTFL *peptflScale, // return address of scaling factors
  104. XDCOBJ& dco, // defines device to world transformation
  105. PFD_XFORM pfdx, // defines notional to device transformation
  106. PFEOBJ& pfeo, // defines baseline direction
  107. BOOL *pbIdent // return TRUE if NtoW is identity (with repsect
  108. // to EVECTFL transormations, which ignore
  109. // translations)
  110. );
  111. //
  112. // The iUniqueStamp is protected by the ghsemRFONTList semaphore.
  113. //
  114. ULONG iUniqueStamp;
  115. // Maximum number of RFONTs allowed on the PDEV inactive list.
  116. #define cMaxInactiveRFONT 32
  117. // Device height over which we will cache PATHOBJ's instead of bitmaps.
  118. static const ULONG gulOutlineThreshold = 800;
  119. /******************************Public*Routine******************************\
  120. * ulSimpleDeviceOrientation *
  121. * *
  122. * Attempts to calculate a simple orientation angle in DEVICE coordinates. *
  123. * This only ever returns multiples of 90 degrees when it succeeds. If the *
  124. * calculation would be hard, it just returns 3601. *
  125. * *
  126. * Note that the text layout code, for which the escapement and orientation *
  127. * are recorded in the RFONT, always considers its angles to be measured *
  128. * from the x-axis towards the positive y-axis. (So that a unit vector *
  129. * will have a y component equal to the cosine of the angle.) This is NOT *
  130. * what an application specifies in world coordinates! *
  131. * *
  132. * Sat 05-Jun-1993 -by- Bodin Dresevic [BodinD] *
  133. * Wrote it. It looks more formidable than it is. It actually doesn't *
  134. * execute much code. *
  135. \**************************************************************************/
  136. ULONG ulSimpleDeviceOrientation(RFONTOBJ &rfo)
  137. {
  138. // Calculate the orientation in device space.
  139. INT sx = (INT) rfo.prfnt->pteUnitBase.x.lSignum();
  140. INT sy = (INT) rfo.prfnt->pteUnitBase.y.lSignum();
  141. // Exactly one of these must be zero (for the orientation to be simple).
  142. if ((sx^sy)&1)
  143. {
  144. // Calculate the following angles:
  145. //
  146. // sx = 00000001 : 0
  147. // sy = 00000001 : 2700
  148. // sx = FFFFFFFF : 1800
  149. // sy = FFFFFFFF : 900
  150. ULONG ulOrientDev = (sx & 1800) | (sy & 900) | ((-sy) & 2700);
  151. return(ulOrientDev);
  152. }
  153. // If it's not simple, return an answer out of range.
  154. return(3601);
  155. }
  156. /******************************Public*Routine******************************\
  157. * VOID RFONTOBJ::RFONTOBJ (PRFONT prfnt)
  158. *
  159. * Deletion Constructor for RFONTOBJ. Note that this is only used
  160. * in DC deletion, where we create the RFONTOBJ only to let it expire.
  161. *
  162. * We set up the RFONTOBJ only to unlock the handle and blow away the
  163. * rfont.
  164. *
  165. * Ok, so it's sleazy. I couldn't think of a cleaner way. Sue me.
  166. *
  167. * History:
  168. * 06-Feb-92 -by- Paul Butzi
  169. * Wrote it.
  170. \**************************************************************************/
  171. RFONTOBJ::RFONTOBJ (PRFONT _prfnt)
  172. {
  173. prfnt = _prfnt;
  174. if (prfnt != NULL)
  175. {
  176. vMakeInactive();
  177. prfnt = (PRFONT)NULL;
  178. }
  179. }
  180. /******************************Public*Routine******************************\
  181. * RFONTOBJ::vInit (dco, bNeedPaths) *
  182. * *
  183. * Constructor for a realized font user object. More complicated than most *
  184. * contructors, this one doesn't even take an handle as an input. Instead, *
  185. * it accepts a dc reference. This constructor creates a user object for *
  186. * the font realization for the font which is currently selected into the *
  187. * DC. The name of the game here is to be fast in the common case, which *
  188. * is that the LFONT selection has not changed since the last time we were *
  189. * here. *
  190. * *
  191. * Note that the destructor for this class DOES NOT unlock the object. *
  192. * That only happens when the object is deselected in the routine or in the *
  193. * sleazy deselection constructor above. *
  194. * *
  195. * History: *
  196. * *
  197. * 15-Nov-1995 -by- Kirk Olynyk [kirko] *
  198. * Renamed from vInit to to bInit. bInit is called by a stub called vInit *
  199. * If the return value is true then vInit calls vGetCache(), if the *
  200. * return value is false then vInit does not call vGetCache. This assures *
  201. * that the last thing that a valid construtor does is lock the cache *
  202. * semaphore. Before this change, the PFFREFOBJ destructor could sneak *
  203. * in and acquire the font semaphore inside a cache critical section. *
  204. * *
  205. * Tue 10-Mar-1992 18:59:54 -by- Charles Whitmer [chuckwh] *
  206. * Made this, the body of the constructor, optional. *
  207. * *
  208. * 31-Jan-1992 -by- Paul Butzi *
  209. * Serious rewrite. *
  210. * *
  211. * 30-Oct-1990 -by- Gilman Wong [gilmanw] *
  212. * Wrote it. *
  213. \**************************************************************************/
  214. BOOL bGrayRequestTheSame(XDCOBJ &dco)
  215. {
  216. BOOL bRet = TRUE;
  217. // if gulFontInformation did change, this would only matter to tt and ps fonts
  218. // and if this is a screen or memory dc
  219. if (dco.bDisplay() || (dco.dctp() == DCTYPE_MEMORY))
  220. {
  221. PRFONT prfnt = dco.pdc->prfnt();
  222. if (prfnt->fobj.flFontType & (TRUETYPE_FONTTYPE|FO_POSTSCRIPT))
  223. {
  224. FLONG flRequest = 0;
  225. if (gulFontInformation & FE_AA_ON)
  226. {
  227. flRequest |= FO_GRAY16;
  228. if (gulFontInformation & FE_CT_ON)
  229. flRequest |= FO_CLEARTYPE_X;
  230. }
  231. if (prfnt->fobj.flFontType & TRUETYPE_FONTTYPE)
  232. {
  233. if (flRequest != (prfnt->fobj.flFontType & (FO_GRAY16 | FO_CLEARTYPE_X)))
  234. return FALSE;
  235. }
  236. else // (prfnt->fobj.flFontType & FO_POSTSCRIPT)
  237. {
  238. if ((flRequest & FO_GRAY16) != (prfnt->fobj.flFontType & FO_GRAY16))
  239. return FALSE;
  240. }
  241. if ((prfnt->fobj.flFontType & (FO_GRAY16 | FO_CLEARTYPE_X)) && IsRemoteConnection())
  242. {
  243. // the session got changed from console to remote and we need to force ClearType and gray antialiazing off
  244. return FALSE;
  245. }
  246. }
  247. }
  248. return bRet;
  249. }
  250. BOOL RFONTOBJ::bInit(XDCOBJ &dco, BOOL bNeedPaths, FLONG flType)
  251. {
  252. //
  253. // We start out with the currently selected RFONT.
  254. // That way, if we deselect it, we will unlock it!
  255. //
  256. prfnt = dco.pdc->prfnt();
  257. // Early out--maybe the font has not changed.
  258. if
  259. (
  260. bValid() &&
  261. (dco.pdc->hlfntNew() == dco.pdc->hlfntCur())
  262. )
  263. {
  264. if
  265. (
  266. (iGraphicsMode() == dco.pdc->iGraphicsMode()) &&
  267. (bNeedPaths == prfnt->bNeededPaths) &&
  268. (flType == (prfnt->flType & RFONT_TYPE_MASK)) &&
  269. bGrayRequestTheSame(dco) &&
  270. !dco.pdc->bUseMetaPtoD()
  271. )
  272. {
  273. // xform must be initialiazed before checking
  274. // dco.pdc->bXFormChange()
  275. EXFORMOBJ xo(dco, WORLD_TO_DEVICE);
  276. ASSERTGDI(xo.bValid(),
  277. "gdisrv!RFONTOBJ(dco) - invalid xform in dcof\n"
  278. );
  279. // bNeedPath clause is added to the above check since last time
  280. // this font could have been realized with bitmaps or metrics only
  281. // rather than with paths [bodind]
  282. if (!dco.pdc->bXFormChange())
  283. {
  284. // Since the LFONT and xform have not changed, we know that we
  285. // already have the right RFONT selected into the DC
  286. // so we are just going to use it. Remember that if it is
  287. // already selected it is also locked down.
  288. return(TRUE);
  289. }
  290. else
  291. {
  292. // Get World to Device transform (but with translations removed),
  293. // check if it happens to be to essentially the same as the old one
  294. if (xo.bEqualExceptTranslations(&(prfnt->mxWorldToDevice)))
  295. {
  296. dco.pdc->vXformChange(FALSE);
  297. return(TRUE);
  298. }
  299. }
  300. }
  301. }
  302. else
  303. {
  304. // LogFont has definitely changed, so update the current handle.
  305. dco.pdc->hlfntCur(dco.pdc->hlfntNew());
  306. }
  307. // Get PDEV user object (need for bFindRFONT). We also need to make
  308. // sure that we have loaded device fonts before we go off to the font mapper.
  309. // this must be done before the ghsemPublicPFT is locked down.
  310. PDEVOBJ pdo(dco.hdev());
  311. ASSERTGDI(pdo.bValid(), "gdisrv!RFONTOBJ(dco): bad pdev in dc\n");
  312. if (!pdo.bGotFonts())
  313. pdo.bGetDeviceFonts();
  314. // If we get to here, either the LFONT has changed since the last
  315. // text operation, or the XFORM has changed. In either case, we'll look
  316. // on the list of RFONTs on the pdev to see if we can find the right
  317. // realization. If not, we'll just have to realize it now.
  318. vMakeInactive(); // deselects the rfont
  319. //
  320. // Now we have no selected RFONT. We're going to track one down
  321. // that corresponds to the current XFORM and LFONT,
  322. // and 'select' it.
  323. // Lock and Validate the LFONTOBJ user object.
  324. LFONTOBJ lfo(dco.pdc->hlfntNew(), &pdo);
  325. if (!lfo.bValid())
  326. {
  327. WARNING("gdisrv!RFONTOBJ(dco): bad LFONT handle\n");
  328. prfnt = PRFNTNULL; // mark RFONTOBJ invalid
  329. dco.pdc->prfnt(prfnt);
  330. return(FALSE);
  331. }
  332. // This is an opportune time to update the fields in the DC that
  333. // are cached from the LFONTOBJ...
  334. dco.pdc->flSimulationFlags(lfo.flSimulationFlags());
  335. // Note that our internal angles are always towards the positive y-axis,
  336. // but at the API they are towards the negative y-axis.
  337. dco.pdc->lEscapement(lNormAngle(-lfo.lEscapement()));
  338. //
  339. // Now we're ready to track down this RFONT we want...
  340. //
  341. PFE *ppfe; // realize this font
  342. FD_XFORM fdx; // realize with this notional to device xform
  343. FLONG flSim; // simulation flags for realization
  344. POINTL ptlSim; // for bitmap scaling simulations
  345. FLONG flAboutMatch; // info about how the font mapping was done
  346. // We will hold a reference to whatever PFF we map to while trying to
  347. // realize the font.
  348. PFFREFOBJ pffref;
  349. // Temporarily grab the global font semaphore to do the mapping.
  350. {
  351. // Stabilize the public PFT for mapping.
  352. SEMOBJ so(ghsemPublicPFT);
  353. // LFONTOBJ::ppfeMapFont returns a pointer to the physical font face and
  354. // a simulation type (ist)
  355. ppfe = lfo.ppfeMapFont(dco, &flSim, &ptlSim, &flAboutMatch, flType & RFONT_TYPE_HGLYPH);
  356. // Compute the Notional to Device transform for this realization.
  357. PFEOBJ pfeo(ppfe);
  358. IFIOBJ ifio(pfeo.pifi());
  359. ASSERTGDI(pfeo.bValid(), "gdisrv!RFONTOBJ(dco): bad ppfe from mapping\n");
  360. // Map mode settings have no effect on stock logfont under Windows.
  361. // App PeachTree accounting relies on this behavior for postscript
  362. // printing works properly.
  363. BOOL bIgnoreMapMode = (!(pdo.bDisplayPDEV()) && (lfo.fl() & LF_FLAG_STOCK) );
  364. if (
  365. !pfeo.bSetFontXform(
  366. dco, lfo.plfw(),
  367. &fdx,
  368. bIgnoreMapMode ? ND_IGNORE_MAP_MODE : 0,
  369. flSim,
  370. (POINTL* const) &ptlSim,
  371. ifio,
  372. FALSE
  373. )
  374. )
  375. {
  376. WARNING("gdisrv!RFONTOBJ(dco): failed to compute font transform\n");
  377. prfnt = PRFNTNULL; // mark RFONTOBJ invalid
  378. dco.pdc->prfnt(prfnt);
  379. return(FALSE);
  380. }
  381. // this is needed only by ttfd to support win31 hack: VDMX XFORM QUANTIZING
  382. // NOTE: in the case that the requested height is 0 we will pick a default
  383. // value which represent the character height and not the cell height for
  384. // Win 3.1 compatibility. Thus I have he changed this check to be <= 0
  385. // from just < 0. [gerritv]
  386. if (ifio.bTrueType() && (lfo.plfw()->lfHeight <= 0))
  387. flSim |= FO_EM_HEIGHT;
  388. // Tell PFF about this new reference, and then release the global sem.
  389. // Note that vInitRef() must be called while holding the semaphore.
  390. pffref.vInitRef(pfeo.pPFF());
  391. }
  392. // go find the font
  393. EXFORMOBJ xoWtoD(dco, WORLD_TO_DEVICE);
  394. ASSERTGDI(xoWtoD.bValid(), "gdisrv!RFONTOBJ(dco) - \n");
  395. // When looking for an RFONT it is important that we don't consider those
  396. // who have small metrics in the GLYPHDATA cache if there is any possibility
  397. // that we will hit the G1,G2,or G3 cases in the glyph layout code. We will
  398. // possibly hit this if the escapment in the LOGFONT is non-zero or the
  399. // WorldToDevice XFORM is more than simple scaling or has negative values is
  400. // M11 or M22.
  401. BOOL bSmallMetricsOk;
  402. if( ( dco.pdc->lEscapement() == 0 ) &&
  403. xoWtoD.bScale() &&
  404. !xoWtoD.efM22().bIsNegative() &&
  405. !xoWtoD.efM11().bIsNegative() )
  406. {
  407. bSmallMetricsOk = TRUE;
  408. }
  409. else
  410. {
  411. bSmallMetricsOk = FALSE;
  412. }
  413. // Attempt to find an RFONT in the lists cached off the PDEV. Its transform,
  414. // simulation state, style, etc. all must match.
  415. if
  416. (
  417. bFindRFONT
  418. (
  419. &fdx,
  420. flSim,
  421. 0, // lfo.pelfw()->elfStyleSize,
  422. pdo,
  423. &xoWtoD,
  424. ppfe,
  425. bNeedPaths,
  426. dco.pdc->iGraphicsMode(),
  427. bSmallMetricsOk,
  428. flType
  429. )
  430. )
  431. {
  432. dco.pdc->prfnt(prfnt);
  433. dco.pdc->vXformChange(FALSE);
  434. return(TRUE);
  435. }
  436. //
  437. // if we get here, we couldn't find an appropriate font realization.
  438. // Now, we are going to create one just for us to use.
  439. //
  440. if ( !bRealizeFont(&dco,
  441. &pdo,
  442. lfo.pelfw(),
  443. ppfe,
  444. &fdx,
  445. (POINTL* const) &ptlSim,
  446. flSim,
  447. 0, // lfo.pelfw()->elfStyleSize,
  448. bNeedPaths,
  449. bSmallMetricsOk, flType) )
  450. {
  451. WARNING1("gdisrv!RFONTOBJ(dco): realization failed, RFONTOBJ invalidated\n");
  452. prfnt = PRFNTNULL; // mark RFONTOBJ invalid
  453. dco.pdc->prfnt(prfnt);
  454. return(FALSE);
  455. }
  456. ASSERTGDI(bValid(), "gdisrv!RFONTOBJ(dco): invalid hrfnt from realization\n");
  457. // We created a new RFONT, we better hold the PFF reference!
  458. pffref.vKeepIt();
  459. // Select this into the DC if successful.
  460. dco.pdc->prfnt(prfnt);
  461. // Finally, grab the cache semaphore.
  462. dco.pdc->vXformChange(FALSE);
  463. return(TRUE);
  464. }
  465. /******************************Private*Routine******************************\
  466. * RFONTOBJ::bMatchRealization() *
  467. * *
  468. * Return if prfnt matches a font realization caller wants. *
  469. * *
  470. * History: *
  471. * Wed 13-Sep-00 -by- Michael Leonov [mleonov] *
  472. * Moved diplicating code from bFindRFONT into this function. *
  473. * *
  474. \**************************************************************************/
  475. BOOL RFONTOBJ::bMatchRealization(
  476. PFD_XFORM pfdx,
  477. FLONG flSim,
  478. ULONG ulStyleHt,
  479. EXFORMOBJ * pxoWtoD,
  480. PFE * ppfe,
  481. BOOL bNeedPaths,
  482. INT iGraphicsMode,
  483. BOOL bSmallMetricsOk,
  484. FLONG flType
  485. )
  486. {
  487. if (prfnt->ppfe != ppfe)
  488. return FALSE;
  489. if (flType != (prfnt->flType & RFONT_TYPE_MASK))
  490. return FALSE;
  491. FLONG flXOR = prfnt->fobj.flFontType ^ flSim; // set the bits that are different
  492. if ((flXOR & (FO_EM_HEIGHT | FO_SIM_BOLD | FO_SIM_ITALIC)) == 0 )
  493. {
  494. flXOR &= (FO_GRAY16 | FO_CLEARTYPE_X | FO_CLEARTYPENATURAL_X); // focus just on ct and aa
  495. if (flXOR)
  496. {
  497. // The gray bits disagree but we still have a chance.
  498. // If the request is for gray but the font cannot
  499. // provide gray fonts at this particular font size
  500. // then this realization is OK
  501. if (flSim & FO_GRAY16)
  502. {
  503. if (prfnt->fobj.flFontType & FO_NOGRAY16)
  504. {
  505. flXOR &= (FO_CLEARTYPE_X | FO_CLEARTYPENATURAL_X); // still need to look if we ask for the same AA type
  506. }
  507. }
  508. // If asking font sets CT bit but Rfont in cache doesn't set CT bit
  509. // and FO_GRAY16 bit sets, then we assume this font cannot provide
  510. // CT at this size. So this realization is OK
  511. if ( (flSim & FO_CLEARTYPE_X) && !(prfnt->fobj.flFontType & FO_CLEARTYPE_X) )
  512. {
  513. if (prfnt->fobj.flFontType & FO_NOCLEARTYPE)
  514. {
  515. flXOR = 0;
  516. }
  517. }
  518. }
  519. if (flXOR == 0)
  520. if (prfnt->fobj.ulStyleSize == ulStyleHt)
  521. if (bMatchFDXForm(pfdx))
  522. if ( bNeedPaths == prfnt->bNeededPaths )
  523. if ( !pxoWtoD || pxoWtoD->bEqualExceptTranslations(&(prfnt->mxWorldToDevice)))
  524. if (prfnt->iGraphicsMode == iGraphicsMode)
  525. if ( (!bSmallMetricsOk ) ? !(prfnt->cache.bSmallMetrics) : TRUE )
  526. {
  527. return TRUE;
  528. }
  529. }
  530. return FALSE;
  531. }
  532. /******************************Public*Routine******************************\
  533. * RFONTOBJ::bFindRFONT() *
  534. * *
  535. * Find the rfont on the chain on the pdev, if it exists. *
  536. * *
  537. * History: *
  538. * Mon 08-Feb-1993 11:26:31 -by- Charles Whitmer [chuckwh] *
  539. * Added dependency on graphics mode. *
  540. * *
  541. * 10-Feb-92 -by- Paul Butzi *
  542. * Wrote it. *
  543. \**************************************************************************/
  544. BOOL RFONTOBJ::bFindRFONT(
  545. PFD_XFORM pfdx,
  546. FLONG flSim,
  547. ULONG ulStyleHt,
  548. PDEVOBJ& pdo,
  549. EXFORMOBJ *pxoWtoD,
  550. PFE *ppfe,
  551. BOOL bNeedPaths,
  552. INT iGraphicsMode,
  553. BOOL bSmallMetricsOk,
  554. FLONG flType
  555. )
  556. {
  557. ASSERTGDI(prfnt == NULL,
  558. "gdisrv!RFONTOBJ:bFindRFONT - prfnt != NULL");
  559. SEMOBJ so(ghsemRFONTList);
  560. //
  561. // Search active list. If we find it, just increment selection
  562. // count and leave.
  563. //
  564. for ( prfnt = pdo.prfntActive();
  565. prfnt != (PRFONT)NULL;
  566. prfnt = prfnt->rflPDEV.prfntNext)
  567. {
  568. ASSERTGDI(prfnt->cSelected >= 1,
  569. "gdisrv!RFONTOBJ::bFindRFONT - cSelected < 1 on active list\n");
  570. if (bMatchRealization(
  571. pfdx,
  572. flSim,
  573. ulStyleHt,
  574. pxoWtoD,
  575. ppfe,
  576. bNeedPaths,
  577. iGraphicsMode,
  578. bSmallMetricsOk,
  579. flType
  580. ))
  581. {
  582. prfnt->cSelected += 1;
  583. PRFONT head = pdo.prfntActive();
  584. if( head != prfnt )
  585. {
  586. vRemove(&head, PDEV_LIST);
  587. vInsert(&head, PDEV_LIST); // we always insert at head
  588. pdo.prfntActive(head);
  589. }
  590. return TRUE;
  591. }
  592. }
  593. //
  594. // Search inactive list. If we find it, we must take it off the
  595. // inactive list and put it on the active list.
  596. //
  597. PRFONT prfntLast = (RFONT*) NULL;
  598. for ( prfnt = pdo.prfntInactive();
  599. prfnt != NULL;
  600. prfntLast = prfnt, prfnt = prfnt->rflPDEV.prfntNext)
  601. {
  602. ASSERTGDI(prfnt->cSelected == 0,
  603. "gdisrv!RFONTOBJ::bFindRFONT - cSelected != 0 on inactive list\n");
  604. if (bMatchRealization(
  605. pfdx,
  606. flSim,
  607. ulStyleHt,
  608. pxoWtoD,
  609. ppfe,
  610. bNeedPaths,
  611. iGraphicsMode,
  612. bSmallMetricsOk,
  613. flType
  614. ))
  615. {
  616. // first, take it off inactive list
  617. PRFONT prfntHead = pdo.prfntInactive();
  618. vRemove(&prfntHead, PDEV_LIST);
  619. pdo.prfntInactive(prfntHead); // vRemove MAY change head of list
  620. pdo.cInactive(pdo.cInactive()-1);
  621. // finally, put it on the active list and increment Selected count
  622. prfntHead = pdo.prfntActive();
  623. vInsert(&prfntHead, PDEV_LIST);
  624. pdo.prfntActive(prfntHead); // vInsert changes head of list
  625. prfnt->cSelected = 1;
  626. return TRUE;
  627. }
  628. }
  629. prfnt = (RFONT*) NULL;
  630. return FALSE;
  631. }
  632. /******************************Public*Routine******************************\
  633. * RFONTOBJ::VerifyCacheSemaphore
  634. *
  635. * Useful debugging code to verify the semaphore release
  636. *
  637. * History:
  638. *
  639. * 5-4-2000 Yung-Jen Tony Tsai
  640. * Write it.
  641. \**************************************************************************/
  642. #ifdef FE_SB
  643. /******************************Public*Routine******************************\
  644. * RFONTOBJ::bMakeInactiveHelper()
  645. *
  646. * Take the rfont off the active list, put on the inactive list, Return a
  647. * list of linked fonts to deactivate.
  648. *
  649. * History:
  650. *
  651. * 13-Jan-95 -by- Hideyuki Nagase [hideyukn]
  652. * Rewrite it.
  653. *
  654. * 29-Sep-93 -by- Gerrit van Wingerden [gerritv]
  655. * Wrote it.
  656. \**************************************************************************/
  657. BOOL RFONTOBJ::bMakeInactiveHelper(PRFONT *pprfnt)
  658. {
  659. BOOL bLockEUDC = FALSE;
  660. // Quick out if NULL or already inactive.
  661. if ((prfnt == NULL) || (prfnt->cSelected == 0))
  662. return(bLockEUDC);
  663. // If prfVictim is changed to a valid pointer, then a victim was selected
  664. // off the inactive list for deletion.
  665. PRFONT prfVictim = PRFNTNULL;
  666. {
  667. // in order to avoid a deadlock (ghsemRFONTList, ghsemEUDC1)
  668. // we increament the gcEUDCCount first
  669. if (pprfnt != NULL)
  670. {
  671. INCREMENTEUDCCOUNT;
  672. }
  673. SEMOBJ so(ghsemRFONTList);
  674. // Since RFONT is being deselected from a DC, remove a reference count.
  675. prfnt->cSelected -= 1;
  676. // If no more references, take the RFONT off the active list.
  677. if ( prfnt->cSelected == 0 )
  678. {
  679. // if pprfnt is not null, enumrate EUDC RFONT, and store pprfnt array.
  680. if(pprfnt != NULL)
  681. {
  682. if(prfnt->prfntSystemTT)
  683. {
  684. *pprfnt++ = prfnt->prfntSystemTT;
  685. prfnt->prfntSystemTT = NULL;
  686. }
  687. // We need to accumulate a list of Linked/EUDC RFONTS and deactive
  688. // if pprfnt is not null, enumrate EUDC RFONT, and store pprfnt array.
  689. bLockEUDC = TRUE;
  690. if( prfnt->prfntSysEUDC != NULL )
  691. {
  692. *pprfnt++ = prfnt->prfntSysEUDC;
  693. prfnt->prfntSysEUDC = (RFONT *)NULL;
  694. }
  695. if( prfnt->prfntDefEUDC != NULL )
  696. {
  697. *pprfnt++ = prfnt->prfntDefEUDC;
  698. prfnt->prfntDefEUDC = (RFONT *)NULL;
  699. }
  700. for( UINT ii = 0; ii < prfnt->uiNumLinks ; ii++ )
  701. {
  702. if (prfnt->paprfntFaceName[ii] != NULL)
  703. {
  704. *pprfnt++ = prfnt->paprfntFaceName[ii];
  705. prfnt->paprfntFaceName[ii] = (RFONT *)NULL;
  706. }
  707. }
  708. prfnt->uiNumLinks = 0;
  709. prfnt->bFilledEudcArray = FALSE;
  710. }
  711. else
  712. {
  713. ASSERTGDI( (prfnt->prfntSysEUDC == NULL),
  714. "vMakeInactiveHelper:deactivated an RFONT with a System EUDC.\n" );
  715. ASSERTGDI( (prfnt->prfntDefEUDC == NULL),
  716. "vMakeInactiveHelper:deactivated an RFONT with a Default \
  717. EUDC.\n" );
  718. ASSERTGDI( (prfnt->uiNumLinks == 0),
  719. "vMakeInactiveHelper:deactivated an RFONT with uiNumLinks\n");
  720. }
  721. PDEVOBJ pdo(prfnt->hdevConsumer);
  722. // Take it off the active list.
  723. PRFONT prf = pdo.prfntActive();
  724. vRemove(&prf, PDEV_LIST);
  725. pdo.prfntActive(prf); // vRemove might change head of list
  726. // If font file no longer loaded, then make this RFONT the victim
  727. // for deletion.
  728. PFFOBJ pffo(prfnt->pPFF);
  729. ASSERTGDI(pffo.bValid(), "gdisrv!vMakeInactiveRFONTOBJ(): invalid PFF\n");
  730. // Possible race condition. We're checking the count
  731. // without the ghsemPublicPFT semaphore. It could be that
  732. // this is ABOUT to become zero, but we miss it. I claim
  733. // that this rarely happens and if it does, so what? We'll
  734. // eventually get rid of this font when it gets flushed out
  735. // of the inactive list. This code is just an attempt to
  736. // get it out faster. [GilmanW]
  737. if ( (pffo.cLoaded() == 0) && (pffo.cNotEnum() == 0) && (pffo.pPvtDataHeadGet() == NULL) )
  738. {
  739. prfVictim = prfnt;
  740. }
  741. // Otherwise, put it on the inactive list.
  742. else
  743. {
  744. if ( pdo.cInactive() >= cMaxInactiveRFONT )
  745. {
  746. // Too many inactive rfonts, blow one away! Pick the last one on
  747. // the list.
  748. for ( prf = pdo.prfntInactive();
  749. prf != NULL;
  750. prfVictim = prf, prf = prf->rflPDEV.prfntNext)
  751. {
  752. }
  753. // Remove victim from inactive list.
  754. RFONTTMPOBJ rfo(prfVictim);
  755. prf = pdo.prfntInactive();
  756. rfo.vRemove(&prf, PDEV_LIST);
  757. pdo.prfntInactive(prf); // vRemove might change head of list
  758. // We don't need to modify the count because, even though we
  759. // just removed one, we're going to add one back right away.
  760. }
  761. else
  762. {
  763. // We definitely made the list get longer.
  764. pdo.cInactive(pdo.cInactive()+1);
  765. }
  766. prf = pdo.prfntInactive();
  767. vInsert(&prf, PDEV_LIST);
  768. pdo.prfntInactive(prf); // vInsert changes head of list
  769. }
  770. }
  771. }
  772. // decreament the gcEUDCCount if there is no EUDC RFONTs
  773. if (pprfnt != NULL && !bLockEUDC)
  774. {
  775. DECREMENTEUDCCOUNT;
  776. }
  777. // If we removed a victim from the inactive list, we can now delete it.
  778. if ( prfVictim != PRFNTNULL )
  779. {
  780. RFONTTMPOBJ rfloVictim(prfVictim);
  781. // Need this so we can remove this from the PFF's RFONT list.
  782. PFFOBJ pffo(prfVictim->pPFF);
  783. ASSERTGDI(pffo.bValid(), "gdisrv!vMakeInactiveRFONTOBJ(): bad HPFF");
  784. // We pass in NULL for ppdo because we've already removed it from the
  785. // PDEV list.
  786. // bDelete keeps the list head ptrs updated
  787. rfloVictim.bDeleteRFONT((PDEVOBJ *) NULL, &pffo);
  788. }
  789. // No longer valid RFONTOBJ. RFONT is now on the inactive list or deleted.
  790. prfnt = (PRFONT) NULL;
  791. return(bLockEUDC);
  792. }
  793. /******************************Public*Routine******************************\
  794. * RFONTOBJ::vMakeInactive()
  795. *
  796. * Take the rfont off the active list, put on the inactive list
  797. *
  798. * History:
  799. * 13-Jan-95 -by- Hideyuki Nagase [hideyukn]
  800. * Rewrite it.
  801. *
  802. * 29-Sep-93 -by- Gerrit van Wingerden [gerritv]
  803. * Wrote it.
  804. \**************************************************************************/
  805. VOID RFONTOBJ::vMakeInactive()
  806. {
  807. // We will treat this as a NULL terminated array of pointers to RFONTS so
  808. // we need an extra ptr at the end for the NULL termination and
  809. // SystemWide and Default EUDC Rfonts.
  810. PRFONT aprfnt[QUICK_FACE_NAME_LINKS + 4];
  811. PRFONT *pprfnt;
  812. BOOL bLockEUDC, bScratch, bAllocated;
  813. if ((prfnt == NULL) || (prfnt->cSelected == 0))
  814. return;
  815. // if the quick buffer is not enough, just allocate it here.
  816. if( prfnt->uiNumLinks > QUICK_FACE_NAME_LINKS )
  817. {
  818. // we need an extra ptr at the end for the NULL termination and
  819. // SystemWide and Default EUDC Rfonts.
  820. pprfnt = (PRFONT *) PALLOCMEM((prfnt->uiNumLinks+4)*sizeof(PRFONT),'flnk');
  821. if (pprfnt)
  822. {
  823. bAllocated = TRUE;
  824. }
  825. else
  826. {
  827. // this a small allocation which is really unlikely to fail.
  828. // If it does, we are probably in such a deep trouble that
  829. // it does not matter that we will leek even further by not
  830. // freeing mem allocated by this rfont. Also, in the real world,
  831. // we should never have uiNumLinks > QUICK_FACE_NAME_LINKS
  832. #if DBG
  833. WARNING("We are in trouble to release the cache\n");
  834. DbgBreakPoint();
  835. #endif
  836. return;
  837. }
  838. }
  839. else
  840. {
  841. RtlZeroMemory((VOID *)aprfnt, sizeof(aprfnt));
  842. pprfnt = aprfnt;
  843. bAllocated = FALSE;
  844. }
  845. // First deactivate the RFONT itself. vMakeInactiveHelper returns a list of
  846. // linked/EUDC RFONTS which we will then deactivate. If bLockEUDC is TRUE
  847. // on return from this function it means we've blocked EUDC API's from functioning
  848. // because we are deactivating an EUDC RFONT. On return from this function
  849. // we should unblock EUDC API's.
  850. bLockEUDC = bMakeInactiveHelper(pprfnt);
  851. while( *pprfnt != NULL )
  852. {
  853. FLINKMESSAGE(DEBUG_FONTLINK_RFONT,
  854. "vMakeInactive() deactivating linked font %x\n");
  855. RFONTTMPOBJ rfo( *pprfnt );
  856. rfo.bMakeInactiveHelper((PRFONT *)NULL);
  857. // next one..
  858. pprfnt++;
  859. }
  860. // free temorary buffer, if it was allocated.
  861. if( bAllocated ) VFREEMEM( pprfnt );
  862. // possibly unblock EUDC API's
  863. if( bLockEUDC )
  864. {
  865. ASSERTGDI(gcEUDCCount > 0, "gcEUDCCount <= 0");
  866. DECREMENTEUDCCOUNT;
  867. }
  868. }
  869. #endif
  870. /**************************Public*Routine************************\
  871. * vRemoveAllInactiveRFONTs()
  872. *
  873. * Take all of the rfont off the inactive list.
  874. * This is only called by bAllocateCache() after it fails to
  875. * allocate the memory the fisrt time.
  876. *
  877. * History:
  878. *
  879. * Mar-06-98 -by- Xudong Wu [TessieW]
  880. * Wrote it.
  881. \****************************************************************/
  882. VOID vRemoveAllInactiveRFONTs(PPDEV ppdev)
  883. {
  884. PRFONT aprfnt[cMaxInactiveRFONT], prf, prfHead, prfVictim;
  885. ULONG i = 0, cNumVictim;
  886. {
  887. SEMOBJ so(ghsemRFONTList);
  888. PDEVOBJ pdo((HDEV)ppdev);
  889. // remove every RFONT from the inactive list
  890. for (prf = pdo.prfntInactive(); prf != NULL; )
  891. {
  892. aprfnt[i++] = prfVictim = prf;
  893. prf = prf->rflPDEV.prfntNext;
  894. RFONTTMPOBJ rfo(prfVictim);
  895. prfHead = pdo.prfntInactive();
  896. rfo.vRemove(&prfHead, PDEV_LIST);
  897. pdo.prfntInactive(prfHead);
  898. }
  899. pdo.cInactive(0);
  900. }
  901. cNumVictim = i;
  902. ASSERTGDI(cNumVictim <= cMaxInactiveRFONT, "bRemoveAllInactiveRFONT: cNumVictim > cMaxInactiveRFONT");
  903. for (i = 0; i < cNumVictim; i++)
  904. {
  905. RFONTTMPOBJ rfo(aprfnt[i]);
  906. PFFOBJ pffo(aprfnt[i]->pPFF);
  907. ASSERTGDI(pffo.bValid(), "bReamoveAllInactiveRFONT: Invalid pff");
  908. // pass in ppdo as NULL because it has been
  909. // removed from the PDEV list
  910. rfo.bDeleteRFONT((PDEVOBJ *) NULL, &pffo);
  911. }
  912. }
  913. /******************************Public*Routine******************************\
  914. * BOOL RFONTOBJ::bRealizeFont
  915. *
  916. * Realizes the IFI or device font represented by the PFE handle for the
  917. * DC associated with the passed DC user object. Initializes the other
  918. * fields of the RFONT.
  919. *
  920. * Warning:
  921. * Whoever calls this should be holding the semaphore of the PFT in which
  922. * the PFE lives.
  923. *
  924. * Returns:
  925. * TRUE if realization successful, FALSE if error occurs.
  926. *
  927. * History:
  928. * Wed 09-Mar-1994 13:52:26 by Kirk Olynyk [kirko]
  929. * Made the FONTOBJ::flFontType consistent with the contents of the font
  930. * in the case where the type of the original font is overridden.
  931. * Sat 09-Jan-1993 22:11:23 by Kirk Olynyk [kirko]
  932. * Added pptlSim to the input parameter list. This is for bitmap scaling
  933. * simulations.
  934. * 12-Dec-1990 -by- Gilman Wong [gilmanw]
  935. * Wrote it.
  936. \**************************************************************************/
  937. BOOL RFONTOBJ::bRealizeFont(
  938. XDCOBJ *pdco, // realize font for this DC (optional)
  939. PPDEVOBJ ppdo, // realize font for this PDEV
  940. ENUMLOGFONTEXDVW *pelfw, // font wish list (in logical coords)
  941. PFE *ppfe, // realize this font face
  942. PFD_XFORM pfdx, // font xform (Notional to Device)
  943. POINTL* const pptlSim, // for bitmap scaling
  944. FLONG _fl, // xform flags
  945. ULONG ulStyleHtPt, // style ht
  946. BOOL bNeedPaths, // Font realization must cache paths
  947. BOOL bSmallMetricsOk,
  948. FLONG flType
  949. )
  950. {
  951. BOOL bRet = FALSE;
  952. PFEOBJ pfeo(ppfe);
  953. PFD_GLYPHSET pfdgTmp;
  954. ASSERTGDI(pfeo.bValid(),
  955. "gdisrv!bRealizeFontRFONTOBJ(): PFEOBJ constructor failed\n");
  956. // If we can not allocate pfdg, then we would failed to do RFNT initialized.
  957. pfdgTmp = pfeo.pfdg();
  958. if (!pfdgTmp)
  959. {
  960. prfnt = PRFNTNULL;
  961. return bRet; // return FALSE
  962. }
  963. ASSERTGDI(prfnt == NULL,
  964. "gdisrv!bRealizeFontRFONTOBJ(): prfnt != NULL\n");
  965. // Create a default sized RFONT.
  966. prfnt = (RFONT *) PALLOCMEM(sizeof(RFONT), 'tnfG');
  967. if (prfnt == PRFNTNULL)
  968. {
  969. WARNING("gdisrv!bRealizeFontRFONTOBJ(): failed alloc\n");
  970. pfeo.vFreepfdg();
  971. prfnt = PRFNTNULL;
  972. return bRet; // return FALSE
  973. }
  974. PFFOBJ pffo(pfeo.pPFF());
  975. ASSERTGDI(pffo.bValid(),
  976. "gdisrv!bRealizeFontRFONTOBJ(): PFFOBJ constructor failed\n");
  977. ASSERTGDI(pfdx != NULL,
  978. "gdisrv!bRealizeFontRFONTOBJ(): pfdx == NULL\n");
  979. // Set up the RFONT's copy of the FONTOBJ.
  980. //
  981. // This needs to be done before the IFI/device driver dependent stuff
  982. // because it is needed by FdOpenFontContext.
  983. // Note: iUniq should be set here, but we won't set it until we grab
  984. // the ghsemRFONTList because the iUniqueStap needs semaphore
  985. // protection for increment and access. (InterlockedIncrement
  986. // doesn't cut it).
  987. pfo()->sizLogResPpi.cx = ppdo->ulLogPixelsX();
  988. pfo()->sizLogResPpi.cy = ppdo->ulLogPixelsY();
  989. pfo()->ulStyleSize = ulStyleHtPt;
  990. pfo()->flFontType = _fl | pfeo.flFontType(); // combine the simulation and type flage
  991. pfo()->pvConsumer = (PVOID) NULL;
  992. pfo()->pvProducer = (PVOID) NULL;
  993. pfo()->iFace = pfeo.iFont();
  994. pfo()->iFile = pffo.hff();
  995. // nonzero only for tt fonts
  996. //
  997. // Old comment from gilmanw:
  998. // - what about device TT fonts?!? Should iTTUniq be zero?
  999. //
  1000. // iTTUniq should be different between Normal face font and @face Verical font.
  1001. // And also, this value should be uniq for TrueType collection format fonts.
  1002. //
  1003. pfo()->iTTUniq = (pfo()->flFontType & TRUETYPE_FONTTYPE) ? (ULONG_PTR) ppfe : 0;
  1004. // Assert consistency of TrueType. The driver is the TrueType font driver
  1005. // if and only if the font is TrueType.
  1006. #ifdef FINISHED_FONT_DRIVER_WORK
  1007. ASSERTGDI(((pfo()->flFontType & TRUETYPE_FONTTYPE) != 0) ==
  1008. (pffo.hdev() == (HDEV) gppdevTrueType),
  1009. "gdisrv!bRealizeFontRFONTOBJ(): inconsistentflFontType\n");
  1010. #endif
  1011. // Copy the font transform passed in.
  1012. prfnt->fdx = *pfdx;
  1013. prfnt->fdxQuantized = *pfdx;
  1014. prfnt->ptlSim = *pptlSim;
  1015. // Initialize the DDI callback EXFORMOBJ.
  1016. prfnt->xoForDDI.vInit(&prfnt->mxForDDI);
  1017. vSetNotionalToDevice(prfnt->xoForDDI);
  1018. // Save identifiers to the source of the font (physical font).
  1019. prfnt->ppfe = ppfe;
  1020. prfnt->pPFF = pfeo.pPFF();
  1021. #ifdef FE_SB
  1022. // Set Null to indicate this RFONT not yet linked to EUDC
  1023. prfnt->prfntSystemTT = (PRFONT )NULL;
  1024. prfnt->prfntSysEUDC = (PRFONT )NULL;
  1025. prfnt->prfntDefEUDC = (PRFONT )NULL;
  1026. prfnt->paprfntFaceName = (PRFONT *)NULL;
  1027. prfnt->bFilledEudcArray = FALSE;
  1028. // Initialize EUDC status.
  1029. prfnt->flEUDCState = 0;
  1030. prfnt->uiNumLinks = 0;
  1031. prfnt->ulTimeStamp = 0;
  1032. prfnt->bVertical = pfeo.bVerticalFace();
  1033. #endif
  1034. // Save identifiers to the consumer of this font realization.
  1035. if (ppdo != NULL)
  1036. {
  1037. // The dhpdev is really for font producers, which won't support dynamic
  1038. // mode changing:
  1039. prfnt->hdevConsumer = ppdo->hdev();
  1040. prfnt->dhpdev = ppdo->dhpdevNotDynamic();
  1041. }
  1042. else
  1043. {
  1044. prfnt->hdevConsumer = NULL;
  1045. prfnt->dhpdev = 0;
  1046. }
  1047. // Bits per pel?
  1048. //
  1049. // Old comment:
  1050. // - setting cBitsPerPel = 1 is wrong - kriko
  1051. prfnt->cBitsPerPel = 1;
  1052. // Outline (transformable)?
  1053. IFIOBJ ifio(pfeo.pifi());
  1054. prfnt->flInfo = pfeo.pifi()->flInfo;
  1055. pfdg(pfdgTmp);
  1056. // Cache the default character. The bInitCache method below needs it.
  1057. prfnt->hgDefault = hgXlat(ifio.wcDefaultChar());
  1058. // Should this become an error exit, or can this be taken out?
  1059. ASSERTGDI (
  1060. pfdg()->cGlyphsSupported != 0,
  1061. "gdisrv!bRealizeFontRFONTOBJ(): no glyphs in this font\n"
  1062. );
  1063. // Get the device metrics info
  1064. FD_DEVICEMETRICS devm = {0}; // buffer to which the driver returns info
  1065. // Initialize font driver (the font producer) information.
  1066. prfnt->hdevProducer = pffo.hdev();
  1067. // Up to this point nothing has been done that could cause the font driver
  1068. // (the font provider) to realize the font. However, this may now happen
  1069. // when querying for information dependent on the realization. So we are
  1070. // going to HAVE TO KILL font driver realization on every error return
  1071. // from this function
  1072. // FONTASSASIN faKillDriverRealization(&ldo, pfo());
  1073. // get and convert device metrics.
  1074. if ( !bGetDEVICEMETRICS(&devm) )
  1075. {
  1076. WARNING("gdisrv!bRealizeFontRFONTOBJ(): error with DEVICEMETRICS\n");
  1077. vDestroyFont(); // kill the driver realization
  1078. VFREEMEM(prfnt);
  1079. prfnt = PRFNTNULL;
  1080. return bRet; // return FALSE
  1081. }
  1082. // Pre-compute some useful values for text placement and extents.
  1083. // (But only if it's not some journalling guys calling.)
  1084. if (pdco != (XDCOBJ *) NULL)
  1085. {
  1086. // pelfw is null only when pdco is null
  1087. ASSERTGDI(pelfw,"gdisrv! pelfw == NULL\n");
  1088. // Get the unit baseline and ascent vectors from the DEVICEMETRICS.
  1089. prfnt->pteUnitBase.x = devm.pteBase.x; // Converts from FLOAT.
  1090. prfnt->pteUnitBase.y = devm.pteBase.y; // Converts from FLOAT.
  1091. prfnt->pteUnitAscent.x = devm.pteSide.x; // Converts from FLOAT.
  1092. prfnt->pteUnitAscent.y = devm.pteSide.y; // Converts from FLOAT.
  1093. // Save a copy of the DC's World to Device matrix. We'll need this later
  1094. // to identify compatible XFORM's (i.e., DC marked as having a changed
  1095. // transform when, in fact, the transform has not changed in a way that
  1096. // would effect the font realization. Example: translation only changes.
  1097. prfnt->mxWorldToDevice = pdco->pdc->mxWorldToDevice();
  1098. // Compute the scaling factors for fast transforms from world to
  1099. // device space and back.
  1100. // Compute some matrix stuff related to the font realization's transform.
  1101. // Compute Notional to World scaling factors in the baseline and ascender
  1102. // directions.
  1103. // These two routines should be made into a single routine [bodind]
  1104. if
  1105. (
  1106. !bCalcLayoutUnits(pdco) // Uses pteUnitBase, pteUnitAscent.
  1107. ||
  1108. !bGetNtoWScales(
  1109. &prfnt->eptflNtoWScale,
  1110. *pdco,
  1111. &prfnt->fdxQuantized, // the one really used by the rasterizer
  1112. pfeo,
  1113. &prfnt->bNtoWIdent
  1114. )
  1115. )
  1116. {
  1117. WARNING("gdisrv!bRealizeFont(): error computing scaling factors\n");
  1118. vDestroyFont(); // kill the driver realization
  1119. VFREEMEM(prfnt);
  1120. prfnt = PRFNTNULL;
  1121. return bRet; // return FALSE
  1122. }
  1123. // Precompute the offsets for max ascent and descent.
  1124. prfnt->ptfxMaxAscent.x = lCvt(prfnt->pteUnitAscent.x,prfnt->fxMaxAscent);
  1125. prfnt->ptfxMaxAscent.y = lCvt(prfnt->pteUnitAscent.y,prfnt->fxMaxAscent);
  1126. prfnt->ptfxMaxDescent.x = lCvt(prfnt->pteUnitAscent.x,prfnt->fxMaxDescent);
  1127. prfnt->ptfxMaxDescent.y = lCvt(prfnt->pteUnitAscent.y,prfnt->fxMaxDescent);
  1128. // Mark escapement info as invalid.
  1129. prfnt->lEscapement = -1;
  1130. if (pdco->pdc->iGraphicsMode() == GM_COMPATIBLE)
  1131. {
  1132. if (ifio.bStroke())
  1133. {
  1134. // esc and orientation treated as WORLD space concepts
  1135. prfnt->ulOrientation =
  1136. (ULONG) lNormAngle(3600-pelfw->elfEnumLogfontEx.elfLogFont.lfOrientation);
  1137. }
  1138. else
  1139. {
  1140. // force orientation to be equal to escapement, which means
  1141. // that h3 or g2 text out code will be executed
  1142. // in this case ulOrientation and lEsc are device space concepts
  1143. // but it does not really matter, so long as we wind up in h2 or
  1144. // g3 layout routines which are not even going to look at this number.
  1145. if (ifio.bArbXforms())
  1146. {
  1147. // you will always get the orientation you ask for
  1148. prfnt->ulOrientation =
  1149. (ULONG) lNormAngle(3600-pelfw->elfEnumLogfontEx.elfLogFont.lfEscapement);
  1150. }
  1151. else // get one of the discrete choices of the font driver
  1152. {
  1153. prfnt->ulOrientation
  1154. = ulSimpleDeviceOrientation(*this);
  1155. ASSERTGDI(
  1156. prfnt->ulOrientation != 3601,
  1157. "GDISRVL! ulSimpleDeviceOrientation err\n"
  1158. );
  1159. }
  1160. }
  1161. }
  1162. else // advanced mode
  1163. {
  1164. // Try to calculate an orientation angle in world coordinates. Note that
  1165. // we want an exact answer, because it's important to know if the
  1166. // escapement and orientation are exactly equal. In the Win 3.1
  1167. // compatible case, we will force them equal (in ESTROBJ::vInit), but
  1168. // we still need to know if the orientation is 0 for fast horizontal
  1169. // layout. (So we don't really care what the orientation is if it's
  1170. // non-obvious in this case.)
  1171. prfnt->ulOrientation = ulSimpleOrientation(pdco); // Uses pteUnitBase.
  1172. // If we are in advanced mode and the font is scalable, we will assume
  1173. // that the desired orientation is obtained.
  1174. if
  1175. (
  1176. (prfnt->ulOrientation >= 3600)
  1177. && bArbXforms()
  1178. )
  1179. {
  1180. // For text layout, orientation angles are measured from the x-axis
  1181. // towards the positive y-axis. The app measures them towards the
  1182. // negative y-axis. We adjust for this.
  1183. prfnt->ulOrientation =
  1184. (ULONG) lNormAngle(3600-pelfw->elfEnumLogfontEx.elfLogFont.lfOrientation);
  1185. }
  1186. }
  1187. } // end of if (pdco != NULL) clause
  1188. // Make sure essential information is in place for further realization.
  1189. ASSERTGDI(prfnt->hgDefault != HGLYPH_INVALID,"Default glyph invalid!\n");
  1190. prfnt->bNeededPaths = bNeedPaths;
  1191. // Is this font driver, or just a device driver?
  1192. ULONG ulFontCaps = 0;
  1193. PDEVOBJ pdo(prfnt->hdevProducer);
  1194. if (PPFNVALID(pdo, QueryFontCaps))
  1195. {
  1196. ULONG ulBuf[2];
  1197. if ( pdo.QueryFontCaps(2, ulBuf) != FD_ERROR )
  1198. {
  1199. ulFontCaps = ulBuf[1];
  1200. }
  1201. }
  1202. if ( !pdo.bFontDriver() )
  1203. {
  1204. // If not a font driver, then the driver does not provide either bitmaps
  1205. // or outlines. Therefore, it must be that we are using a device-specific
  1206. // font (i.e., metrics only).
  1207. prfnt->bDeviceFont = TRUE;
  1208. // Handle cache typing.
  1209. prfnt->ulContent = FO_HGLYPHS;
  1210. prfnt->cache.cjGlyphMax = 0;
  1211. }
  1212. else
  1213. {
  1214. // If its a font driver, then this font is not device specific. We
  1215. // can get more than just glyph metrics from this realization.
  1216. // we will make sure that glyphs that are up to ~2 inches tall
  1217. // are stored as glyphbits, above that as paths. That should speed up
  1218. // printing on high resolution printers.
  1219. ULONG ulPathThreshold;
  1220. if ( prfnt->fobj.flFontType & (FO_CLEARTYPE_X | FO_GRAY16))
  1221. ulPathThreshold = gulOutlineThreshold / 2;
  1222. else
  1223. ulPathThreshold = gulOutlineThreshold;
  1224. prfnt->bDeviceFont = FALSE;
  1225. // Figure out the type of font data we want to cache
  1226. // First, figure out what the driver would like
  1227. prfnt->ulContent = FO_GLYPHBITS; // assume bitmaps
  1228. if ( bNeedPaths )
  1229. {
  1230. prfnt->ulContent = FO_PATHOBJ;
  1231. }
  1232. else if (prfnt->hdevConsumer != NULL)
  1233. {
  1234. // get device driver user object
  1235. PDEVOBJ pdoConsumer(prfnt->hdevConsumer);
  1236. if (PPFNVALID(pdoConsumer, GetGlyphMode))
  1237. {
  1238. prfnt->ulContent =
  1239. (*PPFNDRV(pdoConsumer, GetGlyphMode)) (prfnt->dhpdev, pfo());
  1240. }
  1241. // multiply resolution by 3 inches to get pixel height limit
  1242. if (pdoConsumer.flGraphicsCapsNotDynamic() & GCAPS_FONT_RASTERIZER)
  1243. {
  1244. ULONG ulTmp = pdoConsumer.ulLogPixelsY() * 3;
  1245. if (ulTmp > gulOutlineThreshold)
  1246. ulPathThreshold = ulTmp;
  1247. // also, if in the future we get 2400 dpi or 4800 dpi devices
  1248. // we do not want this number to get too big, this
  1249. // would cost us too much in terms of font cache memory
  1250. // and rasterization times.
  1251. if (ulPathThreshold > 2400)
  1252. ulPathThreshold = 2400;
  1253. }
  1254. }
  1255. ASSERTGDI(prfnt->ulContent <= FO_PATHOBJ,
  1256. "RFONTOBJ::bRealize - bad ulContent\n");
  1257. // A driver preference requires agreement between the font driver and
  1258. // device driver.
  1259. switch(prfnt->ulContent)
  1260. {
  1261. case FO_GLYPHBITS:
  1262. {
  1263. // If the driver is incapable of supplying bitmaps OR if the height
  1264. // is very large (greater global outline threshold) and the font is
  1265. // capable of doing outlines, then force path mode.
  1266. // we use different threshold for cxMax
  1267. // which is usually about 2 * cyMax
  1268. if
  1269. (
  1270. (!(ulFontCaps & QC_1BIT)) ||
  1271. (bReturnsOutlines() &&
  1272. ((prfnt->cxMax > (2*ulPathThreshold)) ||
  1273. (prfnt->cyMax > ulPathThreshold)))
  1274. )
  1275. prfnt->ulContent = FO_PATHOBJ;
  1276. }
  1277. break;
  1278. case FO_PATHOBJ:
  1279. if ( !(ulFontCaps & QC_OUTLINES))
  1280. prfnt->ulContent = FO_GLYPHBITS;
  1281. break;
  1282. default:
  1283. break;
  1284. }
  1285. }
  1286. // If you force the path mode then turn off antialiasing
  1287. if (prfnt->ulContent == FO_PATHOBJ)
  1288. {
  1289. #if DBG
  1290. if (gflFontDebug & DEBUG_AA)
  1291. KdPrint(("Forcing path mode ==> turning off antialiasing\n"));
  1292. #endif
  1293. prfnt->fobj.flFontType &= ~FO_GRAY16;
  1294. }
  1295. if ( bNeedPaths && (prfnt->ulContent != FO_PATHOBJ))
  1296. {
  1297. WARNING1("Can't get paths for font!\n");
  1298. vDestroyFont(); // kill the driver realization
  1299. VFREEMEM(prfnt);
  1300. prfnt = PRFNTNULL;
  1301. return bRet; // return FALSE
  1302. }
  1303. // we only use small metrics if the bit
  1304. prfnt->cache.bSmallMetrics =
  1305. ( bSmallMetricsOk && ( prfnt->ulOrientation == 0 ) ) ? TRUE : FALSE;
  1306. if (!bInitCache(flType))
  1307. {
  1308. WARNING("gdisrv!bRealizeFontRFONTOBJ(): cache initialization failed\n");
  1309. vDestroyFont(); // kill the driver realization
  1310. VFREEMEM(prfnt);
  1311. prfnt = PRFNTNULL;
  1312. return bRet; // return FALSE
  1313. }
  1314. // set TEXTMETRICS cache to NULL
  1315. prfnt->ptmw = NULL;
  1316. // Made it this far, so everything is OK
  1317. bRet = TRUE;
  1318. //
  1319. // Old comments:
  1320. // - really ought to check list to make sure that no one else
  1321. // realized the font while we were working
  1322. //
  1323. PRFONT prfntHead;
  1324. {
  1325. SEMOBJ so(ghsemRFONTList);
  1326. // Assign the uniqueness ID under semaphore.
  1327. // WARNING:
  1328. // This exact same code is in iGetNextUniqueness() in JNLFONT.CXX.
  1329. // Why not just call it? Because iGetNextUniqueness() would grab
  1330. // the semaphore a second time. I'd rather live with duplicate
  1331. // code!
  1332. iUniqueStamp += 1;
  1333. if (iUniqueStamp == 0) // an iUniq of 0 means "don't cache" in driver
  1334. iUniqueStamp = 1;
  1335. pfo()->iUniq = iUniqueStamp;
  1336. // If a PDEVOBJ * was passed in, we need to update its list.
  1337. if (ppdo != NULL)
  1338. {
  1339. prfnt->cSelected = 1;
  1340. // Add to PDEV list.
  1341. prfntHead = ppdo->prfntActive();
  1342. vInsert(&prfntHead, PDEV_LIST);
  1343. ppdo->prfntActive(prfntHead);
  1344. }
  1345. // Add to PFF list.
  1346. prfntHead = pffo.prfntList();
  1347. vInsert(&prfntHead, PFF_LIST);
  1348. pffo.prfntList(prfntHead);
  1349. }
  1350. if (prfnt->ulContent == FO_GLYPHBITS)
  1351. prfnt->fobj.flFontType |= FO_TYPE_RASTER;
  1352. else
  1353. prfnt->fobj.flFontType &= ~FO_TYPE_RASTER;
  1354. // remember the graphics mode used in computing this realization's
  1355. // notional to world xform:
  1356. if (pdco != (XDCOBJ *) NULL)
  1357. iGraphicsMode(pdco->pdc->iGraphicsMode());
  1358. else
  1359. iGraphicsMode(0);
  1360. #ifdef FE_SB
  1361. prfnt->bIsSystemFont = gbSystemDBCSFontEnabled && pfeo.bSBCSSystemFont();
  1362. #endif
  1363. return bRet;
  1364. }
  1365. /******************************Public*Routine******************************\
  1366. * bCalcLayoutUnits (pdco) *
  1367. * *
  1368. * Initializes the following fields in the RFONT. The unit baseline and *
  1369. * unit ascent vectors pteUnitBase and pteUnitAscent must already be *
  1370. * initialized. The vectors are given to us by the font realization code, *
  1371. * so we can really make no assumptions about them other than that they are *
  1372. * unit vectors in device space and orthogonal in world space. *
  1373. * *
  1374. * efWtoDBase *
  1375. * efDtoWBase *
  1376. * efWtoDAscent *
  1377. * efDtoWAscent *
  1378. * *
  1379. * Fri 05-Feb-1993 16:03:14 -by- Charles Whitmer [chuckwh] *
  1380. * Wrote it. *
  1381. \**************************************************************************/
  1382. BOOL RFONTOBJ::bCalcLayoutUnits(XDCOBJ *pdco)
  1383. {
  1384. EFLOAT efOne;
  1385. efOne.vSetToOne();
  1386. // Get the world to device transform from the DC.
  1387. EXFORMOBJ xo(*pdco, WORLD_TO_DEVICE);
  1388. // Pick up the diagonal components.
  1389. EFLOAT efM11 = xo.efM11();
  1390. EFLOAT efM22 = xo.efM22();
  1391. efM11.vAbs(); efM22.vAbs();
  1392. // Handle the simple (but common) case.
  1393. if (xo.bScale() && (efM11 == efM22))
  1394. {
  1395. EFLOAT efM11Inv;
  1396. efM11Inv.eqDiv(efOne,efM11);
  1397. prfnt->efWtoDBase = efM11;
  1398. prfnt->efWtoDAscent = efM11;
  1399. prfnt->efDtoWBase = efM11Inv;
  1400. prfnt->efDtoWAscent = efM11Inv;
  1401. // in isotropic case even win 31 dudes get it right;
  1402. prfnt->efDtoWBase_31 = prfnt->efDtoWBase ;
  1403. prfnt->efDtoWAscent_31 = prfnt->efDtoWAscent;
  1404. }
  1405. // Handle the slow general case.
  1406. else
  1407. {
  1408. POINTFL ptfl;
  1409. // Get the inverse transform from the DC.
  1410. EXFORMOBJ xoDtoW(*pdco, DEVICE_TO_WORLD);
  1411. if (!xoDtoW.bValid())
  1412. return(FALSE);
  1413. // Back transform the baseline, measure its length.
  1414. xoDtoW.bXform((VECTORFL *) &prfnt->pteUnitBase,(VECTORFL *) &ptfl,1);
  1415. prfnt->efDtoWBase.eqLength(ptfl);
  1416. prfnt->efDtoWBase.vDivBy16(); // Adjust for subpel transform.
  1417. prfnt->efWtoDBase.eqDiv(efOne,prfnt->efDtoWBase);
  1418. // Back transform the ascent, measure its length.
  1419. xoDtoW.bXform((VECTORFL *) &prfnt->pteUnitAscent,(VECTORFL *) &ptfl,1);
  1420. prfnt->efDtoWAscent.eqLength(ptfl);
  1421. prfnt->efDtoWAscent.vDivBy16(); // Adjust for subpel transform.
  1422. prfnt->efWtoDAscent.eqDiv(efOne,prfnt->efDtoWAscent);
  1423. if
  1424. (
  1425. (pdco->pdc->iGraphicsMode() == GM_COMPATIBLE) &&
  1426. !pdco->pdc->bUseMetaPtoD() &&
  1427. !(prfnt->flInfo & FM_INFO_TECH_STROKE)
  1428. )
  1429. {
  1430. // win 31 way of doing it: they scale extent measured
  1431. // along baseline by the (DtoW) xx component even if baseline is
  1432. // along some other direction. Likewise they scale ascender extent by
  1433. // DtoW yy component even if ascender is not collinear with y axis.
  1434. // so fix up backward scaling factors, but leave forward scaling factors
  1435. // correct for the text layout code [bodind]
  1436. // Note that win31 is here at least consistent with respect tt and
  1437. // vector fonts: it returns text extent values that are screwed
  1438. // in the same bogus way for tt and for vector fonts
  1439. prfnt->efDtoWBase_31 = xoDtoW.efM11();
  1440. prfnt->efDtoWAscent_31 = xoDtoW.efM22();
  1441. prfnt->efDtoWBase_31.vAbs();
  1442. prfnt->efDtoWAscent_31.vAbs();
  1443. }
  1444. else
  1445. {
  1446. prfnt->efDtoWBase_31 = prfnt->efDtoWBase ;
  1447. prfnt->efDtoWAscent_31 = prfnt->efDtoWAscent;
  1448. }
  1449. }
  1450. return(TRUE);
  1451. }
  1452. /******************************Public*Routine******************************\
  1453. * ulSimpleOrientation (pdco) *
  1454. * *
  1455. * Attempts to calculate a simple orientation angle in world coordinates. *
  1456. * This only ever returns multiples of 90 degrees when it succeeds. If the *
  1457. * calculation would be hard, it just returns 3601. *
  1458. * *
  1459. * Note that the text layout code, for which the escapement and orientation *
  1460. * are recorded in the RFONT, always considers its angles to be measured *
  1461. * from the x-axis towards the positive y-axis. (So that a unit vector *
  1462. * will have a y component equal to the cosine of the angle.) This is NOT *
  1463. * what an application specifies in world coordinates! *
  1464. * *
  1465. * Fri 05-Feb-1993 18:57:33 -by- Charles Whitmer [chuckwh] *
  1466. * Wrote it. It looks more formidable than it is. It actually doesn't *
  1467. * execute much code. *
  1468. \**************************************************************************/
  1469. ULONG RFONTOBJ::ulSimpleOrientation(XDCOBJ *pdco)
  1470. {
  1471. // Calculate the orientation in device space.
  1472. INT sx = (INT) prfnt->pteUnitBase.x.lSignum();
  1473. INT sy = (INT) prfnt->pteUnitBase.y.lSignum();
  1474. // Exactly one of these must be zero (for the orientation to be simple).
  1475. if ((sx^sy)&1)
  1476. {
  1477. // Calculate the following angles:
  1478. //
  1479. // sx = 00000001 : 0
  1480. // sy = 00000001 : 900
  1481. // sx = FFFFFFFF : 1800
  1482. // sy = FFFFFFFF : 2700
  1483. ULONG ulOrientDev = (sx & 1800) | ((-sy) & 900) | (sy & 2700);
  1484. // Handle the trivial case.
  1485. if (pdco->pdc->bWorldToDeviceIdentity())
  1486. return(ulOrientDev);
  1487. // Locate our transform and examine the matrix.
  1488. EXFORMOBJ xo(*pdco, WORLD_TO_DEVICE);
  1489. INT s11 = (INT) xo.efM11().lSignum();
  1490. INT s12 = (INT) xo.efM12().lSignum();
  1491. INT s21 = (INT) xo.efM21().lSignum();
  1492. INT s22 = (INT) xo.efM22().lSignum();
  1493. // Handle non-inverting transforms.
  1494. // Examine the transform to see if it's a simple multiple of 90
  1495. // degrees rotation and perhaps some scaling.
  1496. // If any of the terms we OR together are non-zero, it's a bad transform.
  1497. if (
  1498. (
  1499. (s11 - s22) // Signs on diagonal must match.
  1500. | (s12 + s21) // Signs off diagonal must be opposite.
  1501. | ((s11^s12^1)&1) // Exactly one diagonal must be zero.
  1502. ) == 0
  1503. )
  1504. {
  1505. // Since we've normalized to a space where (0 1) represents
  1506. // a vector with a 90 degree orientation note that the matrix
  1507. // that rotates us by positive 90 degrees, going from world to
  1508. // device, is:
  1509. //
  1510. // [ 0 1 ]
  1511. // (1 0) [ ] = (0 1)
  1512. // [-1 0 ]
  1513. //
  1514. // I.e. the one with M < 0. From device to world, that's -90 degrees.
  1515. // 21
  1516. ULONG ulOrientWorld = ulOrientDev
  1517. + (s12 & 900)
  1518. + (s11 & 1800)
  1519. + (s21 & 2700);
  1520. // Note that only the single 0xFFFFFFFF term contributes above.
  1521. if (ulOrientWorld >= 3600)
  1522. ulOrientWorld -= 3600;
  1523. return(ulOrientWorld);
  1524. }
  1525. // Now we do the parity inverting transforms.
  1526. else if (
  1527. (
  1528. (s11 + s22) // Signs on diagonal must be opposite.
  1529. | (s12 - s21) // Signs off diagonal must match.
  1530. | ((s11^s12^1)&1) // Exactly one diagonal must be zero.
  1531. ) == 0
  1532. )
  1533. {
  1534. // These are just the simple reflections which take multiples of
  1535. // 90 degrees to multiples of 90 degrees. They are idempotent so
  1536. // device-to-world or world-to-device is irrelevant.
  1537. //
  1538. // [ 1 0 ] [-1 0 ]
  1539. // [ ] => 3600-x [ ] => 5400-x
  1540. // [ 0 -1 ] [ 0 1 ]
  1541. //
  1542. // [ 0 -1 ] [ 0 1 ]
  1543. // [ ] => 6300-x [ ] => 4500-x
  1544. // [-1 0 ] [ 1 0 ]
  1545. ULONG ulOrientWorld = (s22 & 3600) + (s12 & 6300)
  1546. + (s11 & 5400) + ((-s12) & 4500)
  1547. - ulOrientDev;
  1548. // Note that only the single 0xFFFFFFFF term contributes.
  1549. if (ulOrientWorld >= 3600)
  1550. ulOrientWorld -= 3600;
  1551. return(ulOrientWorld);
  1552. }
  1553. }
  1554. // If it's not simple, return an answer out of range.
  1555. return(3601);
  1556. }
  1557. /******************************Public*Routine******************************\
  1558. * RFONTOBJ::bDeleteFONT
  1559. *
  1560. * Delete an RFONT. The ppdo and ppffo point to objects that have RFONT
  1561. * lists that require updating because of the deletion. If NULL, that
  1562. * means the corresponding object does not need deletion (most likely
  1563. * because the list management has already been performed for that object).
  1564. *
  1565. * Warning:
  1566. * Only PFFOBJ::bDelete should pass in a NULL for ppffo. The PFF
  1567. * list needs to be treated specially because PFFs are the only object
  1568. * which might get deleted in response to a RFONT deletion.
  1569. *
  1570. * History:
  1571. * 30-Oct-1990 -by- Gilman Wong [gilmanw]
  1572. * Wrote it.
  1573. \**************************************************************************/
  1574. BOOL RFONTOBJ::bDeleteRFONT (
  1575. PDEVOBJ *ppdo,
  1576. PFFOBJ *ppffo
  1577. )
  1578. {
  1579. PRFONT prfntHead;
  1580. PFEOBJ pfeo(ppfe());
  1581. // free pfdg
  1582. pfeo.vFreepfdg();
  1583. // Tell font producer that font is going away.
  1584. PDEVOBJ pdoPro(prfnt->hdevProducer);
  1585. if ( PPFNVALID(pdoPro, DestroyFont) )
  1586. {
  1587. pdoPro.DestroyFont(pfo());
  1588. }
  1589. // Tell font consumer that font is going away.
  1590. // Note: the PLDEV for the consumer may be NULL (jounalling).
  1591. if (prfnt->hdevConsumer != NULL )
  1592. {
  1593. PDEVOBJ pdoCon(prfnt->hdevConsumer);
  1594. // If this is a display device and we are not in the middle of tearing
  1595. // the pdev down we need to lock the display in order to synchronize
  1596. // this call with other calls to the driver.
  1597. BOOL bLock = ( pdoCon.bDisplayPDEV() && pdoCon.cPdevRefs() != 0 );
  1598. if( bLock )
  1599. {
  1600. GreAcquireSemaphoreEx(pdoCon.hsemDevLock(), SEMORDER_DEVLOCK, NULL);
  1601. GreEnterMonitoredSection(pdoCon.ppdev, WD_DEVLOCK);
  1602. }
  1603. if ( PPFNVALID(pdoCon, DestroyFont) )
  1604. {
  1605. pdoCon.DestroyFont(pfo());
  1606. }
  1607. if( bLock )
  1608. {
  1609. GreExitMonitoredSection(pdoCon.ppdev, WD_DEVLOCK);
  1610. GreReleaseSemaphoreEx(pdoCon.hsemDevLock());
  1611. }
  1612. }
  1613. // Update the RFONT lists. Do this under the ghsemRFONTList semaphore (which
  1614. // may or may not already be held).
  1615. {
  1616. // Stablize the RFONT lists.
  1617. SEMOBJ so(ghsemRFONTList);
  1618. // If a ppdo is passed in, then we need to remove this RFONT from the
  1619. // PDEV list.
  1620. if ( ppdo != (PDEVOBJ *) NULL )
  1621. {
  1622. ASSERTGDI(!bActive(), "gdisrv!bDeleteRFONTOBJ(): RFONT still active\n");
  1623. // Remove from PDEV list.
  1624. prfntHead = ppdo->prfntInactive();
  1625. vRemove(&prfntHead, PDEV_LIST);
  1626. ppdo->prfntInactive(prfntHead);
  1627. // Update the inactive RFONT ref. count.
  1628. ppdo->cInactive(ppdo->cInactive()-1);
  1629. }
  1630. // If a ppffo is passed in, then remove from PFF list. If ppffo is NULL, then
  1631. // bDelete must have been called from PFFOBJ::bDelete(), so we are
  1632. // in the process of deleting RFONTs already and do not need to maintain the
  1633. // list.
  1634. // Note: it is possible to write PFFOBJ::bDelete() so that a bDelete
  1635. // will recursively destroy the entire RFONT list, but I want to
  1636. // avoid the recursion.
  1637. if ( ppffo != (PFFOBJ *) NULL )
  1638. {
  1639. // Remove from PFF list.
  1640. prfntHead = ppffo->prfntList();
  1641. vRemove(&prfntHead, PFF_LIST);
  1642. ppffo->prfntList(prfntHead);
  1643. }
  1644. }
  1645. // Need to tell PFF that this RFONT is going away. Can't do this under the
  1646. // semaphore because bDeleteRFONTRef may cause the driver to be called.
  1647. if ( ppffo != (PFFOBJ *) NULL )
  1648. {
  1649. // Inform PFF that RFONT is going away
  1650. if ( !ppffo->bDeleteRFONTRef() )
  1651. {
  1652. WARNING("gdisrv!bDeleteRFONTOBJ(): PFF deletion failed\n");
  1653. return (FALSE);
  1654. }
  1655. }
  1656. // Destroy the cache
  1657. vDeleteCache();
  1658. // Delete TEXTMETRICS cache
  1659. if( prfnt->ptmw != NULL )
  1660. {
  1661. VFREEMEM( prfnt->ptmw );
  1662. }
  1663. if (prfnt->hsemEUDC)
  1664. GreDeleteSemaphore(prfnt->hsemEUDC);
  1665. // Delete the cache semaphore
  1666. GreDeleteSemaphore(prfnt->hsemCache);
  1667. // Free object memory and invalidate pointer
  1668. VFREEMEM(prfnt);
  1669. prfnt = PRFNTNULL;
  1670. return (TRUE);
  1671. }
  1672. /******************************Member*Function*****************************\
  1673. * BOOL RFONTOBJ::bGetDEVICEMETRICS
  1674. *
  1675. * calls the device or font driver to provide the engine with the
  1676. * FD_DEVICEMETRICS structure
  1677. *
  1678. * History:
  1679. * 08-Apr-1991 -by- Bodin Dresevic [BodinD]
  1680. * Wrote it.
  1681. \**************************************************************************/
  1682. BOOL RFONTOBJ::bGetDEVICEMETRICS(PFD_DEVICEMETRICS pdevm)
  1683. {
  1684. ULONG ulRet;
  1685. // Supply fields to be overwritten by the font provider.
  1686. // The fdxQuantized field is overwritten if the provider wants a different
  1687. // transform. The lExtLeading field is changed from MINLONG if the provider
  1688. // wants to scale this value non-linearly.
  1689. pdevm->fdxQuantized = prfnt->fdx;
  1690. pdevm->lNonLinearExtLeading = MINLONG; // if stays MINLONG, means linear
  1691. pdevm->lNonLinearIntLeading = MINLONG; // if stays MINLONG, means linear
  1692. pdevm->lNonLinearMaxCharWidth = MINLONG; // if stays MINLONG, means linear
  1693. pdevm->lNonLinearAvgCharWidth = MINLONG; // if stays MINLONG, means linear
  1694. PDEVOBJ pdo(prfnt->hdevProducer);
  1695. if ( ((ulRet = pdo.QueryFontData(
  1696. prfnt->dhpdev,
  1697. pfo(),
  1698. QFD_MAXEXTENTS,
  1699. HGLYPH_INVALID,
  1700. (GLYPHDATA *) NULL,
  1701. (PVOID) pdevm,
  1702. (ULONG) sizeof(FD_DEVICEMETRICS))) == FD_ERROR) )
  1703. {
  1704. // The QFD_MAXEXTENTS mode is required of all drivers.
  1705. // However must allow for the possibility of this call to fail.
  1706. // This could happen if the
  1707. // font file is on the net and the net connection dies, and the font
  1708. // driver needs the font file to produce device metrics [bodind]
  1709. return FALSE;
  1710. }
  1711. #if DBG
  1712. {
  1713. EFLOAT efX;
  1714. EFLOAT efY;
  1715. efX = pdevm->pteBase.x;
  1716. efY = pdevm->pteBase.y;
  1717. efX *= efX;
  1718. efY *= efY;
  1719. efY += efX;
  1720. ASSERTGDI(efY < FP_2_0, "pteBase is too large\n");
  1721. efX = pdevm->pteSide.x;
  1722. efY = pdevm->pteSide.y;
  1723. efX *= efX;
  1724. efY *= efY;
  1725. efY += efX;
  1726. ASSERTGDI(efY < FP_2_0, "pteSide is too large\n");
  1727. }
  1728. #endif
  1729. prfnt->flRealizedType = SO_FLAG_DEFAULT_PLACEMENT;
  1730. if (pdevm->flRealizedType & FDM_TYPE_MAXEXT_EQUAL_BM_SIDE)
  1731. prfnt->flRealizedType |= SO_MAXEXT_EQUAL_BM_SIDE;
  1732. if (pdevm->flRealizedType & FDM_TYPE_CHAR_INC_EQUAL_BM_BASE)
  1733. prfnt->flRealizedType |= SO_CHAR_INC_EQUAL_BM_BASE;
  1734. if (pdevm->flRealizedType & FDM_TYPE_ZERO_BEARINGS)
  1735. prfnt->flRealizedType |= SO_ZERO_BEARINGS;
  1736. prfnt->cxMax = pdevm->cxMax;
  1737. prfnt->ptlUnderline1 = pdevm->ptlUnderline1;
  1738. prfnt->ptlStrikeOut = pdevm->ptlStrikeOut;
  1739. prfnt->ptlULThickness = pdevm->ptlULThickness;
  1740. prfnt->ptlSOThickness = pdevm->ptlSOThickness;
  1741. if (pdevm->fxMaxAscender < 0)
  1742. prfnt->fxMaxExtent = pdevm->fxMaxDescender;
  1743. else if (pdevm->fxMaxDescender < 0)
  1744. prfnt->fxMaxExtent = pdevm->fxMaxAscender;
  1745. else
  1746. prfnt->fxMaxExtent = pdevm->fxMaxAscender + pdevm->fxMaxDescender;
  1747. prfnt->fxMaxAscent = pdevm->fxMaxAscender;
  1748. prfnt->fxMaxDescent = -pdevm->fxMaxDescender;
  1749. prfnt->lMaxAscent = FXTOL(8 + prfnt->fxMaxAscent);
  1750. prfnt->lMaxHeight = FXTOL(8 + prfnt->fxMaxAscent - prfnt->fxMaxDescent);
  1751. prfnt->lCharInc = pdevm->lD;
  1752. // new fields
  1753. prfnt->cyMax = pdevm->cyMax;
  1754. prfnt->cjGlyphMax = pdevm->cjGlyphMax; // used to get via QFD_MAXGLYPHBITMAP
  1755. // need to compute the filtering correction for CLEAR_TYPE:
  1756. // x filtering adds a pixel on each side of the glyph
  1757. if (prfnt->fobj.flFontType & FO_CLEARTYPE_X)
  1758. {
  1759. prfnt->cjGlyphMax = CJ_CTGD((prfnt->cxMax + 2), prfnt->cyMax);
  1760. }
  1761. // formerly in reExtra
  1762. prfnt->fdxQuantized = pdevm->fdxQuantized;
  1763. prfnt->lNonLinearExtLeading = pdevm->lNonLinearExtLeading;
  1764. prfnt->lNonLinearIntLeading = pdevm->lNonLinearIntLeading;
  1765. prfnt->lNonLinearMaxCharWidth = pdevm->lNonLinearMaxCharWidth;
  1766. prfnt->lNonLinearAvgCharWidth = pdevm->lNonLinearAvgCharWidth;
  1767. // Get the lMaxNegA lMaxNegC and lMinWidthD for USER
  1768. prfnt->lMaxNegA = pdevm->lMinA;
  1769. prfnt->lMaxNegC = pdevm->lMinC;
  1770. prfnt->lMinWidthD = pdevm->lMinD;
  1771. // cxMax is now computed, copy it to FONTOBJ portion of the RFONTOBJ.
  1772. pfo()->cxMax = prfnt->cxMax;
  1773. // Everythings OK.
  1774. return TRUE;
  1775. }
  1776. /******************************Public*Routine******************************\
  1777. * VOID RFONTOBJ::vGetInfo (
  1778. * PFONTINFO pfi
  1779. * )
  1780. *
  1781. * Fills the FONTINFO buffer pointed to by pfi.
  1782. *
  1783. * Returns:
  1784. * Nothing.
  1785. *
  1786. * History:
  1787. * 03-Oct-1991 -by- Gilman Wong [gilmanw]
  1788. * Wrote it.
  1789. \**************************************************************************/
  1790. VOID RFONTOBJ::vGetInfo(PFONTINFO pfi)
  1791. {
  1792. RtlZeroMemory(pfi, sizeof(FONTINFO));
  1793. pfi->cjThis = sizeof(FONTINFO);
  1794. pfi->cGlyphsSupported = prfnt->pfdg->cGlyphsSupported;
  1795. switch(prfnt->cBitsPerPel)
  1796. {
  1797. case 1:
  1798. pfi->cjMaxGlyph1 = prfnt->cache.cjGlyphMax;
  1799. break;
  1800. case 4:
  1801. pfi->cjMaxGlyph4 = prfnt->cache.cjGlyphMax;
  1802. break;
  1803. case 8:
  1804. pfi->cjMaxGlyph8 = prfnt->cache.cjGlyphMax;
  1805. break;
  1806. case 32:
  1807. pfi->cjMaxGlyph32 = prfnt->cache.cjGlyphMax;
  1808. break;
  1809. }
  1810. if (bDeviceFont())
  1811. pfi->flCaps |= FO_DEVICE_FONT;
  1812. if (bReturnsOutlines())
  1813. pfi->flCaps |= FO_OUTLINE_CAPABLE;
  1814. }
  1815. /******************************Public*Routine******************************\
  1816. * VOID RFONTOBJ::vSetNotionalToDevice (
  1817. * EXFORMOBJ &xfo
  1818. * )
  1819. *
  1820. * Set the XFORMOBJ passed in to be the Notional to Device transform.
  1821. *
  1822. * Returns:
  1823. * TRUE if successful, FALSE otherwise.
  1824. *
  1825. * History:
  1826. * 03-Oct-1991 -by- Gilman Wong [gilmanw]
  1827. * Wrote it.
  1828. \**************************************************************************/
  1829. VOID RFONTOBJ::vSetNotionalToDevice(EXFORMOBJ &xo) // set this transform
  1830. {
  1831. // Make sure to remove translations.
  1832. xo.vRemoveTranslation();
  1833. // Set the rest of the transform matrix.
  1834. xo.vSetElementsLToFx (
  1835. prfnt->fdxQuantized.eXX,
  1836. prfnt->fdxQuantized.eXY,
  1837. prfnt->fdxQuantized.eYX,
  1838. prfnt->fdxQuantized.eYY
  1839. );
  1840. xo.vComputeAccelFlags(XFORM_FORMAT_LTOFX);
  1841. }
  1842. /******************************Public*Routine******************************\
  1843. * BOOL RFONTOBJ::bSetNotionalToWorld (
  1844. * EXFORMOBJ &xoDToW,
  1845. * EXFORMOBJ &xo
  1846. * )
  1847. *
  1848. * Set the incoming XFORMOBJ to be the Notional to World transform for this
  1849. * font.
  1850. *
  1851. * Returns:
  1852. * TRUE if successful, FALSE if an error occurs.
  1853. *
  1854. * History:
  1855. * 27-Jan-1992 -by- Wendy Wu [wendywu]
  1856. * Changed calling interfaces. Left translations alone as we can transform
  1857. * vectors now.
  1858. * 10-Oct-1991 -by- Gilman Wong [gilmanw]
  1859. * Wrote it.
  1860. \**************************************************************************/
  1861. BOOL RFONTOBJ::bSetNotionalToWorld (
  1862. EXFORMOBJ &xoDeviceToWorld, // Device to World transform
  1863. EXFORMOBJ &xo // set this transform
  1864. )
  1865. {
  1866. // Get empty xform to receive Notional to Device transform.
  1867. MATRIX mxNotionalToDevice;
  1868. // This constructor never fails.
  1869. EXFORMOBJ xoNotionalToDevice(&mxNotionalToDevice,DONT_COMPUTE_FLAGS);
  1870. // Set the transform matrix from Notional to Device space.
  1871. xoNotionalToDevice.vSetElementsLToFx (
  1872. prfnt->fdx.eXX,
  1873. prfnt->fdx.eXY,
  1874. prfnt->fdx.eYX,
  1875. prfnt->fdx.eYY
  1876. );
  1877. // Make sure to remove translations.
  1878. xoNotionalToDevice.vRemoveTranslation();
  1879. // Calculate a Notional to World transform.
  1880. // Don't mind about translations. We'll use this to transform vectors only.
  1881. return(xo.bMultiply(xoNotionalToDevice, xoDeviceToWorld,
  1882. COMPUTE_FLAGS | XFORM_FORMAT_LTOL));
  1883. }
  1884. /******************************Public*Routine******************************\
  1885. * RFONTOBJ::bCalcEscapementP (xo,lEsc) *
  1886. * *
  1887. * This is the internal routine that calculates the projection of the *
  1888. * escapement onto the base and ascent vectors, as well as other useful *
  1889. * escapement quantities. *
  1890. * *
  1891. * This is expensive, call only when needed! *
  1892. * *
  1893. * Sat 21-Mar-1992 13:35:49 -by- Charles Whitmer [chuckwh] *
  1894. * Wrote it. *
  1895. \**************************************************************************/
  1896. BOOL RFONTOBJ::bCalcEscapementP(EXFORMOBJ& xo,LONG lEsc)
  1897. {
  1898. ASSERTGDI((lEsc >= 0) && (lEsc < 3600),"Unnormalized angle!\n");
  1899. // Check for simple alignment with the orientation.
  1900. if
  1901. (
  1902. (prfnt->ulOrientation < 3600) &&
  1903. (
  1904. ((ULONG) lEsc == prfnt->ulOrientation)
  1905. || ((ULONG) lEsc == prfnt->ulOrientation + 1800)
  1906. || ((ULONG) lEsc == prfnt->ulOrientation - 1800)
  1907. )
  1908. )
  1909. {
  1910. prfnt->lEscapement = lEsc;
  1911. prfnt->pteUnitEsc = prfnt->pteUnitBase;
  1912. prfnt->efWtoDEsc = prfnt->efWtoDBase;
  1913. prfnt->efDtoWEsc = prfnt->efDtoWBase;
  1914. prfnt->efEscToBase.vSetToOne();
  1915. prfnt->efEscToAscent.vSetToZero();
  1916. if ((ULONG) lEsc != prfnt->ulOrientation)
  1917. {
  1918. prfnt->pteUnitEsc.x.vNegate();
  1919. prfnt->pteUnitEsc.y.vNegate();
  1920. prfnt->efEscToBase.vNegate();
  1921. }
  1922. return(TRUE);
  1923. }
  1924. // Do the general calculation.
  1925. prfnt->lEscapement = -1; // Assume failure.
  1926. if (!xo.bComputeUnits
  1927. (
  1928. lEsc,
  1929. &prfnt->pteUnitEsc,
  1930. &prfnt->efWtoDEsc,
  1931. &prfnt->efDtoWEsc
  1932. )
  1933. )
  1934. return(FALSE);
  1935. /**************************************************************************\
  1936. * Compute the projections along the Base and Ascent axes. *
  1937. * *
  1938. * We compute two quantities r and r as follows: *
  1939. * a b *
  1940. * *
  1941. * E = unit escapement vector *
  1942. * A = unit ascent vector *
  1943. * B = unit baseline vector *
  1944. * *
  1945. * E x B A x E *
  1946. * r = ----- r = ----- *
  1947. * a A x B b A x B *
  1948. * *
  1949. * *
  1950. * These have the property that: *
  1951. * *
  1952. * E = r A + r B *
  1953. * a b *
  1954. * *
  1955. * This allows us to decompose the escapement vector. *
  1956. \**************************************************************************/
  1957. EFLOAT ef; // Ascent x Esc or Esc x Base
  1958. EFLOAT efNorm; // Ascent x Base
  1959. efNorm.eqCross(prfnt->pteUnitAscent,prfnt->pteUnitBase);
  1960. if (efNorm.bIsZero()) // Too singular.
  1961. return(FALSE);
  1962. ef.eqCross(prfnt->pteUnitAscent,prfnt->pteUnitEsc);
  1963. prfnt->efEscToBase.eqDiv(ef,efNorm);
  1964. ef.eqCross(prfnt->pteUnitEsc,prfnt->pteUnitBase);
  1965. prfnt->efEscToAscent.eqDiv(ef,efNorm);
  1966. prfnt->lEscapement = lEsc;
  1967. return(TRUE);
  1968. }
  1969. /******************************Public*Routine******************************\
  1970. * bGetNtoWScales
  1971. *
  1972. * Calculates the Notional to World scaling factor for vectors that are
  1973. * parallel to the baseline direction.
  1974. *
  1975. * History:
  1976. * 14-Apr-1992 14:23:49 Gilman Wong [gilmanw]
  1977. * Modified to support ascender scaling factor as well.
  1978. * Sat 21-Mar-1992 08:03:14 by Kirk Olynyk [kirko]
  1979. * Wrote it.
  1980. \**************************************************************************/
  1981. BOOL bGetNtoWScales (
  1982. EPOINTFL *peptflScale, // return address of scaling factors
  1983. XDCOBJ& dco, // defines device to world transformation
  1984. PFD_XFORM pfdx, // defines notional to device transformation
  1985. PFEOBJ& pfeo, // defines baseline direction
  1986. BOOL *pbIdent // return TRUE if NtoW is identity (with repsect
  1987. // to EVECTFL transormations, which ignore
  1988. // translations)
  1989. )
  1990. {
  1991. MATRIX mxNtoD;
  1992. EXFORMOBJ xoNtoD(&mxNtoD, DONT_COMPUTE_FLAGS);
  1993. xoNtoD.vSetElementsLToFx(
  1994. pfdx->eXX,
  1995. pfdx->eXY,
  1996. pfdx->eYX,
  1997. pfdx->eYY
  1998. );
  1999. xoNtoD.vRemoveTranslation();
  2000. xoNtoD.vComputeAccelFlags(); // XFORM_FORMAT_LTOFX is default
  2001. IFIOBJ ifio(pfeo.pifi());
  2002. POINTL ptlBase = *ifio.pptlBaseline();;
  2003. EVECTORFL evflScaleBase(ptlBase.x, ptlBase.y);
  2004. EVECTORFL evflScaleAsc;
  2005. if ( ifio.bRightHandAscender() )
  2006. {
  2007. evflScaleAsc.x = -ptlBase.y; // ascender is 90 deg CCW from baseline
  2008. evflScaleAsc.y = ptlBase.x;
  2009. }
  2010. else
  2011. {
  2012. evflScaleAsc.x = ptlBase.y; // ascender is 90 deg CW from baseline
  2013. evflScaleAsc.y = -ptlBase.x;
  2014. }
  2015. // assert ptlBase is normalized, this code would not work otherwise
  2016. // If base is normalized, ascender will also be normalized
  2017. ASSERTGDI(
  2018. (ptlBase.x * ptlBase.x + ptlBase.y * ptlBase.y) == 1,
  2019. "gdisrv, unnormalized base vector\n"
  2020. );
  2021. if (!xoNtoD.bXform(evflScaleBase) || !xoNtoD.bXform(evflScaleAsc))
  2022. {
  2023. WARNING("gdisrv!bGetNtoWScale(): bXform(evflScaleBase or Asc) failed\n");
  2024. return(FALSE);
  2025. }
  2026. if (!dco.pdc->bWorldToDeviceIdentity())
  2027. {
  2028. // The notional to world transformation is the product of the notional
  2029. // to device transformation and the device to world transformation
  2030. EXFORMOBJ xoDtoW(dco, DEVICE_TO_WORLD);
  2031. if (!xoDtoW.bValid())
  2032. {
  2033. WARNING("gdisrv!bGetNtoWScale(): xoDtoW is not valid\n");
  2034. return(FALSE);
  2035. }
  2036. #ifdef WASTE_TIME_MULTIPLYING_MATRICES
  2037. // it is bit strange to do this multiply just to get this
  2038. // accelerator [bodind]
  2039. MATRIX mxNtoW;
  2040. EXFORMOBJ xoNtoW(&mxNtoW, DONT_COMPUTE_FLAGS);
  2041. if (!xoNtoW.bMultiply(xoNtoD,xoDtoW))
  2042. {
  2043. WARNING("gdisrv!bGetNtoWScale(): xoNtoW.bMultiply failed\n");
  2044. return(FALSE);
  2045. }
  2046. xoNtoW.vComputeAccelFlags(XFORM_FORMAT_LTOL);
  2047. *pbIdent = xoNtoW.bTranslationsOnly();
  2048. #endif // WASTE_TIME_MULTIPLYING_MATRICES
  2049. // forget about the acceleration in this infrequent case [bodind]
  2050. *pbIdent = FALSE;
  2051. if
  2052. (
  2053. (dco.pdc->iGraphicsMode() == GM_COMPATIBLE) &&
  2054. !dco.pdc->bUseMetaPtoD() &&
  2055. !ifio.bStroke()
  2056. )
  2057. {
  2058. // win 31 way of doing it: they scale extent measured
  2059. // along baseline by the (DtoW) xx component even if baseline in device
  2060. // is along some other direction. Likewise they scale ascender extent by
  2061. // DtoW yy component even if ascender is not collinear with y axis.
  2062. // Note that win31 is here at least consistent with respect tt and
  2063. // vector fonts: it returns text extent values that are screwed
  2064. // in the same bogus way for tt and for vector fonts [bodind]
  2065. evflScaleBase *= xoDtoW.efM11();
  2066. evflScaleAsc *= xoDtoW.efM22();
  2067. // we have to do this becase in else part of the clause
  2068. // this multiplication occurs within bXform
  2069. evflScaleBase.x.vTimes16();
  2070. evflScaleBase.y.vTimes16();
  2071. evflScaleAsc.x.vTimes16();
  2072. evflScaleAsc.y.vTimes16();
  2073. }
  2074. else // do the right thing
  2075. {
  2076. if (!xoDtoW.bXform(evflScaleBase) || !xoDtoW.bXform(evflScaleAsc))
  2077. {
  2078. WARNING("gdisrv! bXform(evflScaleBase or Asc) failed\n");
  2079. return(FALSE);
  2080. }
  2081. }
  2082. }
  2083. else
  2084. {
  2085. // accelerate when user is asking for font at em ht
  2086. *pbIdent = xoNtoD.bTranslationsOnly();
  2087. }
  2088. // The baseline and ascender scaling factors are equal to the length of the
  2089. // transformed Notional baseline unit and ascender unit vectors, respectively.
  2090. peptflScale->x.eqLength(*(POINTFL *) &evflScaleBase);
  2091. peptflScale->y.eqLength(*(POINTFL *) &evflScaleAsc);
  2092. return(TRUE);
  2093. }
  2094. /******************************Public*Routine******************************\
  2095. * RFONTOBJ::vInsert
  2096. *
  2097. * This function is used to help maintain a doubly linked list of RFONTs.
  2098. * Its purpose is to insert this RFONT into a list. New RFONTs are always
  2099. * inserted at the head of the list.
  2100. *
  2101. * WARNING!
  2102. *
  2103. * Caller should always grab the ghsemRFONTList semaphore before calling any
  2104. * of the RFONT list funcitons.
  2105. *
  2106. * History:
  2107. * 23-Jun-1992 -by- Gilman Wong [gilmanw]
  2108. * Wrote it.
  2109. \**************************************************************************/
  2110. VOID RFONTOBJ::vInsert (
  2111. PPRFONT pprfntHead,
  2112. RFL_TYPE rflt
  2113. )
  2114. {
  2115. RFONTLINK *prflNew = NULL;
  2116. RFONTLINK *prflOld = NULL;
  2117. // assert pprfntHead is different from prfnt, if they are same it will cause infinite loop
  2118. ASSERTGDI(
  2119. *pprfntHead != prfnt,
  2120. "*pprfntHead is same as prfnt at RFONTOBJ::vInsert\n"
  2121. );
  2122. // Which set of RFONT links should we use?
  2123. switch (rflt)
  2124. {
  2125. case PFF_LIST:
  2126. prflNew = &(prfnt->rflPFF);
  2127. prflOld = (*pprfntHead != (PRFONT) NULL) ? &((*pprfntHead)->rflPFF) : (PRFONTLINK) NULL;
  2128. break;
  2129. case PDEV_LIST:
  2130. prflNew = &(prfnt->rflPDEV);
  2131. prflOld = (*pprfntHead != (PRFONT) NULL) ? &((*pprfntHead)->rflPDEV) : (PRFONTLINK) NULL;
  2132. break;
  2133. default:
  2134. RIP("gdisrv!vInsertRFONTOBJ(): unknown list type\n");
  2135. break;
  2136. }
  2137. if (prflNew != (RFONTLINK *) NULL)
  2138. {
  2139. // Connect this RFONT to current head.
  2140. prflNew->prfntPrev = (PRFONT) NULL; // head of list has NULL prev
  2141. prflNew->prfntNext = *pprfntHead;
  2142. // Connect current head to this RFONT.
  2143. if (prflOld != (PRFONTLINK) NULL)
  2144. prflOld->prfntPrev = prfnt;
  2145. // Make this RFONT the new head.
  2146. *pprfntHead = prfnt;
  2147. }
  2148. }
  2149. /******************************Public*Routine******************************\
  2150. * RFONTOBJ::vRemove
  2151. *
  2152. * This function is used to help maintain a doubly linked list of RFONTs.
  2153. * Its purpose is to remove this RFONT from the list.
  2154. *
  2155. * WARNING!
  2156. *
  2157. * Caller should always grab the ghsemRFONTList semaphore before calling any
  2158. * of the RFONT list funcitons.
  2159. *
  2160. * History:
  2161. * 23-Jun-1992 -by- Gilman Wong [gilmanw]
  2162. * Wrote it.
  2163. \**************************************************************************/
  2164. VOID RFONTOBJ::vRemove (
  2165. PPRFONT pprfntHead, // a pointer to the head of list
  2166. RFL_TYPE rflt // identifies which list to delete from list
  2167. )
  2168. {
  2169. RFONTLINK *prflVictim = NULL;
  2170. RFONTLINK *prflPrev;
  2171. RFONTLINK *prflNext;
  2172. // Which set of RFONT links should we use?
  2173. switch (rflt)
  2174. {
  2175. case PFF_LIST:
  2176. prflVictim = &(prfnt->rflPFF);
  2177. prflPrev = (prflVictim->prfntPrev != (PRFONT) NULL) ? &(prflVictim->prfntPrev->rflPFF) : (PRFONTLINK) NULL;
  2178. prflNext = (prflVictim->prfntNext != (PRFONT) NULL) ? &(prflVictim->prfntNext->rflPFF) : (PRFONTLINK) NULL;
  2179. break;
  2180. case PDEV_LIST:
  2181. prflVictim = &(prfnt->rflPDEV);
  2182. prflPrev = (prflVictim->prfntPrev != (PRFONT) NULL) ? &(prflVictim->prfntPrev->rflPDEV) : (PRFONTLINK) NULL;
  2183. prflNext = (prflVictim->prfntNext != (PRFONT) NULL) ? &(prflVictim->prfntNext->rflPDEV) : (PRFONTLINK) NULL;
  2184. break;
  2185. default:
  2186. RIP("gdisrv!vInsertRFONTOBJ(): unknown list type\n");
  2187. break;
  2188. }
  2189. // Case 1: this RFONT is at the head of the list.
  2190. if ( prflVictim != (RFONTLINK *) NULL )
  2191. {
  2192. if ( prflVictim->prfntPrev == (PRFONT) NULL )
  2193. {
  2194. // Make the next RFONT the head of the list.
  2195. (*pprfntHead) = prflVictim->prfntNext;
  2196. if (prflNext != (RFONTLINK *) NULL)
  2197. prflNext->prfntPrev = (PRFONT) NULL; // head of list has NULL prev
  2198. }
  2199. // Case 2: this RFONT is not at the head of the list.
  2200. else
  2201. {
  2202. // Connect previous RFONT to next RFONT.
  2203. // Note: since we are guaranteed that this is NOT the head of the
  2204. // list, prflPrev is guaranteed !NULL.
  2205. prflPrev->prfntNext = prflVictim->prfntNext;
  2206. // Connect next RFONT to previous RFONT.
  2207. if (prflNext != (RFONTLINK *) NULL)
  2208. prflNext->prfntPrev = prflVictim->prfntPrev;
  2209. }
  2210. }
  2211. }
  2212. /******************************Public*Routine******************************\
  2213. * RFONTOBJ::lOverhang *
  2214. * *
  2215. * The definitive routine to calculate the Win 3.1 compatible overhang for *
  2216. * simulated bitmap fonts. *
  2217. * *
  2218. * Mon 01-Feb-1993 11:05:10 -by- Charles Whitmer [chuckwh] *
  2219. * Wrote it. *
  2220. \**************************************************************************/
  2221. LONG RFONTOBJ::lOverhang()
  2222. {
  2223. LONG ll = 0;
  2224. FLONG fl = prfnt->fobj.flFontType;
  2225. if
  2226. (
  2227. (prfnt->ppfe->pifi->flInfo & (FM_INFO_TECH_BITMAP|FM_INFO_TECH_STROKE)) &&
  2228. !bDeviceFont()
  2229. )
  2230. {
  2231. if (fl & FO_SIM_ITALIC)
  2232. ll = (prfnt->lMaxHeight - 1) / 2;
  2233. if (fl & FO_SIM_BOLD)
  2234. {
  2235. IFIOBJ ifio(prfnt->ppfe->pifi);
  2236. if (!ifio.bStroke()) // if not vector font
  2237. {
  2238. ll += 1;
  2239. }
  2240. else // vector font
  2241. {
  2242. // overhang has to be computed by scaling (1,0) in notional
  2243. // space to device space and taking the length of this vector.
  2244. // However if length is < 1 we round it up to 1. This is windows
  2245. // 3.1 compatible vector font "hinting" [bodind]
  2246. // Set up transform.
  2247. MATRIX mx;
  2248. EXFORMOBJ xo(&mx, DONT_COMPUTE_FLAGS | XFORM_FORMAT_LTOFX);
  2249. if (!xo.bValid())
  2250. {
  2251. WARNING("gdisrv!lOverhang: XFORMOBJ\n");
  2252. return (FALSE);
  2253. }
  2254. vSetNotionalToDevice(xo);
  2255. POINTL ptlBase = *ifio.pptlBaseline();
  2256. EVECTORFL evtflBase(ptlBase.x,ptlBase.y);
  2257. if (!xo.bXform(evtflBase))
  2258. {
  2259. WARNING("gdisrv!lOverhang(): transform failed\n");
  2260. return 1;
  2261. }
  2262. EFLOAT ef;
  2263. ef.eqLength(*(POINTFL *) &evtflBase);
  2264. LONG lEmbolden = lCvt(ef,1);
  2265. if (lEmbolden == 0)
  2266. lEmbolden = 1;
  2267. ll += lEmbolden;
  2268. }
  2269. }
  2270. }
  2271. return(ll);
  2272. }
  2273. /******************************Public*Routine******************************\
  2274. * RFONTOBJ::bSetNewFDX (dco, bNeedPaths) *
  2275. *
  2276. * This function props up the functionality of the RESETFCOBJ. It either
  2277. * finds a new RFONT or creates one that matches the same ppfe as the current
  2278. * RFONT, but with a different Notional to World transform.
  2279. *
  2280. * Unlike the initialization routines, this function does not modify the DC
  2281. * in anyway. In particular, it does not change the font realization selected
  2282. * into the DC. So this is a peculiar sort of RFONTOBJ in that it can be
  2283. * used to get glyphs and metrics and such (and it is "compatible" with the
  2284. * DC passed in) but it is not selected into any DC. It is, however, classified
  2285. * as an active RFONT. It is the caller's responsibility to make the RFONT
  2286. * inactive (by calling vMakeInactive()).
  2287. *
  2288. * Returns:
  2289. * TRUE if successful, FALSE otherwise.
  2290. *
  2291. \**************************************************************************/
  2292. BOOL RFONTOBJ::bSetNewFDX(XDCOBJ &dco, FD_XFORM &fdx, FLONG flType)
  2293. {
  2294. // Get PDEV user object (need for bFindRFONT)
  2295. PDEVOBJ pdo(dco.hdev());
  2296. ASSERTGDI(pdo.bValid(), "gdisrv!bSetNewFDXRFONTOBJ(): bad pdev in dc\n");
  2297. // go find the font
  2298. EXFORMOBJ xoWtoD(dco, WORLD_TO_DEVICE);
  2299. ASSERTGDI(xoWtoD.bValid(), "gdisrv!bSetNewFDXRFONTOBJ - bad WD xform in DC\n");
  2300. // Grab these out of the current RFONT so we can pass them into the find
  2301. // and realization routines.
  2302. FLONG flSim = pfo()->flFontType & FO_SIM_MASK;
  2303. ULONG ulStyleSize = pfo()->ulStyleSize;
  2304. POINTL ptlSim = prfnt->ptlSim;
  2305. PFE *ppfe = prfnt->ppfe;
  2306. // Release the cache semaphore.
  2307. if (prfnt != PRFNTNULL )
  2308. {
  2309. vReleaseCache();
  2310. }
  2311. // We will hold a reference to whatever PFF we are using while trying to
  2312. // realize the font.
  2313. PFFREFOBJ pffref;
  2314. pffref.vInitRef(prfnt->pPFF);
  2315. // Don't want to make the font inactive, but we must make the RFONTOBJ
  2316. // invalid. So just set it to NULL.
  2317. prfnt = PRFNTNULL;
  2318. // Attempt to find an RFONT in the lists cached off the PDEV. Its transform,
  2319. // simulation state, style, etc. all must match.
  2320. if
  2321. (
  2322. bFindRFONT
  2323. (
  2324. &fdx,
  2325. flSim,
  2326. ulStyleSize,
  2327. pdo,
  2328. &xoWtoD,
  2329. ppfe,
  2330. FALSE,
  2331. dco.pdc->iGraphicsMode(),
  2332. FALSE,
  2333. flType
  2334. )
  2335. )
  2336. {
  2337. vGetCache();
  2338. return TRUE;
  2339. }
  2340. LFONTOBJ lfo(dco.pdc->hlfntNew(), &pdo);
  2341. if (!lfo.bValid())
  2342. {
  2343. WARNING("gdisrv!RFONTOBJ(dco): bad LFONT handle\n");
  2344. prfnt = PRFNTNULL; // mark RFONTOBJ invalid
  2345. return FALSE;
  2346. }
  2347. //
  2348. // if we get here, we couldn't find an appropriate font realization.
  2349. // Now, we are going to create one just for us to use.
  2350. //
  2351. if ( !bRealizeFont(&dco,
  2352. &pdo,
  2353. lfo.pelfw(),
  2354. ppfe,
  2355. &fdx,
  2356. (POINTL* const) &ptlSim,
  2357. flSim,
  2358. ulStyleSize,
  2359. FALSE,
  2360. FALSE, flType) )
  2361. {
  2362. WARNING("gdisrv!bSetNewFDXRFONTOBJ(): realization failed, RFONTOBJ invalidated\n");
  2363. prfnt = PRFNTNULL; // mark RFONTOBJ invalid
  2364. return FALSE;
  2365. }
  2366. ASSERTGDI(bValid(), "gdisrv!bSetNewFDXRFONTOBJ(): invalid hrfnt from realization\n");
  2367. // We created a new RFONT, we better hold the PFF reference!
  2368. pffref.vKeepIt();
  2369. // Finally, grab the cache semaphore.
  2370. vGetCache();
  2371. return TRUE;
  2372. }
  2373. /******************************Public*Routine******************************\
  2374. * bGetWidthTable (iMode,pwc,cwc,plWidth)
  2375. *
  2376. * Gets the advance widths for a bunch of glyphs at the same time. Tries
  2377. * to do it the fast way with DrvQueryAdvanceWidths. A value of NO_WIDTH
  2378. * is returned for widths that take too long to compute.
  2379. *
  2380. * Returns:
  2381. * TRUE If all widths are valid.
  2382. * FALSE If any widths are invalid.
  2383. * GDI_ERROR If an error occurred.
  2384. *
  2385. * History:
  2386. * Wed 13-Jan-1993 03:21:59 -by- Charles Whitmer [chuckwh]
  2387. * Wrote it.
  2388. \**************************************************************************/
  2389. #define HCOUNT 70
  2390. BOOL RFONTOBJ::bGetWidthTable(
  2391. XDCOBJ& dco,
  2392. ULONG cSpecial, // Count of special chars.
  2393. WCHAR *pwcChars, // Pointer to UNICODE text codepoints.
  2394. ULONG cwc, // Count of chars.
  2395. USHORT *psWidth // Width table (returned).
  2396. )
  2397. {
  2398. ULONG cBatch,ii,cc;
  2399. WCHAR *pwc;
  2400. USHORT *ps;
  2401. BOOL bRet = TRUE;
  2402. GLYPHPOS gp;
  2403. // Locate the font driver.
  2404. PDEVOBJ pdo(prfnt->hdevProducer);
  2405. // If it supports the easy function, just call it.
  2406. if ( PPFNDRV( pdo, QueryAdvanceWidths ))
  2407. {
  2408. HGLYPH ahg[HCOUNT];
  2409. // We need space to hold up the translated glyph handles, so we
  2410. // batch the calls.
  2411. cc = cwc;
  2412. ps = psWidth;
  2413. pwc = pwcChars;
  2414. while (cc)
  2415. {
  2416. BOOL b; // Tri-state BOOL.
  2417. cBatch = (cc > HCOUNT) ? HCOUNT : cc;
  2418. // Translate UNICODE to glyph handles.
  2419. // It is important to note that vXlateGlyph array will set the
  2420. // EUDC_WIDTH_REQUESTED flag if a linked character is encountered.
  2421. // It will just return the glyph handle for the default glyph and
  2422. // expects us to patch up this width later.
  2423. vXlatGlyphArray(pwc,(UINT) cBatch,ahg);
  2424. // Get easy widths from the driver.
  2425. b = pdo.QueryAdvanceWidths
  2426. (
  2427. prfnt->dhpdev,
  2428. pfo(),
  2429. QAW_GETEASYWIDTHS,
  2430. ahg,
  2431. (LONG *) ps,
  2432. cBatch
  2433. );
  2434. #ifdef FE_SB
  2435. if (b == GDI_ERROR)
  2436. {
  2437. prfnt->flEUDCState &= ~EUDC_WIDTH_REQUESTED;
  2438. return(GDI_ERROR);
  2439. }
  2440. if( prfnt->flEUDCState & EUDC_WIDTH_REQUESTED )
  2441. {
  2442. prfnt->flEUDCState &= ~EUDC_WIDTH_REQUESTED;
  2443. // If some of the widths requested were in a linked font, then patch
  2444. // them up here.
  2445. WCHAR wcDefault = prfnt->ppfe->pifi->wcDefaultChar;
  2446. for( ii=0; ii < cBatch; ii++ )
  2447. {
  2448. if( ( ahg[ii] == prfnt->hgDefault ) &&
  2449. ( pwc[ii] != wcDefault ) &&
  2450. ( bIsLinkedGlyph(pwc[ii]) || bIsSystemTTGlyph(pwc[ii])) )
  2451. {
  2452. if (cwc - cc + ii < cSpecial ) /* perf: we want to hit the linked font only for required characters */
  2453. {
  2454. if (!bGetGlyphMetrics(1,&gp,&pwc[ii],&dco))
  2455. return(GDI_ERROR);
  2456. ps[ii] = (USHORT)(((GLYPHDATA*) gp.pgdf)->fxD);
  2457. }
  2458. else
  2459. {
  2460. ps[ii] = NO_WIDTH;
  2461. bRet = FALSE;
  2462. }
  2463. }
  2464. }
  2465. }
  2466. #endif
  2467. bRet &= b;
  2468. // Do the next batch.
  2469. ps += cBatch;
  2470. pwc += cBatch;
  2471. cc -= cBatch;
  2472. }
  2473. }
  2474. // Otherwise just mark all widths invalid.
  2475. else
  2476. {
  2477. for (ii=0; ii<cwc; ii++)
  2478. psWidth[ii] = NO_WIDTH;
  2479. bRet = FALSE;
  2480. }
  2481. // Now make sure that all important widths are set, even if it's hard.
  2482. if (!bRet)
  2483. {
  2484. for (ii=0; ii<cSpecial; ii++)
  2485. {
  2486. if (psWidth[ii] == NO_WIDTH)
  2487. {
  2488. if (!bGetGlyphMetrics(1,&gp,&pwcChars[ii],&dco))
  2489. return(GDI_ERROR);
  2490. psWidth[ii] = (USHORT) ((GLYPHDATA*)gp.pgdf)->fxD;
  2491. }
  2492. }
  2493. }
  2494. #ifdef FE_SB
  2495. if (cwc == cSpecial)
  2496. return((bRet == GDI_ERROR) ? (BOOL)GDI_ERROR : TRUE);
  2497. else
  2498. #endif
  2499. return(bRet);
  2500. }
  2501. /******************************Public*Routine******************************\
  2502. * bGetWidthData (pwd) *
  2503. * *
  2504. * Gets font data which is useful on the client side. *
  2505. * *
  2506. * Thu 14-Jan-1993 00:52:43 -by- Charles Whitmer [chuckwh] *
  2507. * Wrote it. *
  2508. \**************************************************************************/
  2509. static const WCHAR RequestedDBCSChars[] = { 0x3000, // Ideograhic Space
  2510. 0x4e00, // Kanji (digit one)
  2511. 0xff21, // FullWidth A
  2512. 0x0000 };
  2513. static const WCHAR OptionalDBCSChars[] = { 0x30a2, // Katakana A
  2514. 0x3041, // Hiragana A
  2515. 0x3131, // Hangul Kiyeok
  2516. 0x3400, // Hangul Kiyeok A
  2517. 0x4e08, // Kanji (Take)
  2518. 0x0000 };
  2519. BOOL RFONTOBJ::bGetWidthData(WIDTHDATA *pwd, XDCOBJ& dco)
  2520. {
  2521. LONG fxHeight = prfnt->lMaxHeight << 4;
  2522. LONG fxCharInc = prfnt->lCharInc << 4;
  2523. LONG fxBreak = prfnt->fxBreak;
  2524. LONG fxDBCSInc = 0;
  2525. LONG fxDefaultInc = 0;
  2526. IFIOBJ ifio(prfnt->ppfe->pifi);
  2527. // If this font has a SHIFTJIS charset and FM_DBCS_FIXED_PITCH is set (and it
  2528. // will be 99% of the time ) then the width of all DBCS characters will be
  2529. // equal to MaxCharInc. Using the is information we can still compute client
  2530. // side extents and char widths for DBCS fonts.
  2531. if( IS_ANY_DBCS_CHARSET(ifio.lfCharSet()) )
  2532. {
  2533. if( ifio.bDBCSFixedPitch() )
  2534. {
  2535. GLYPHPOS gp;
  2536. WCHAR wc;
  2537. LONG fxInc;
  2538. ULONG ulIndex = 0;
  2539. // This logic is for .....
  2540. // In Japanese market, there is some font that has not all glyph
  2541. // of SHIFT-JIS charset. This means some SHIFTJIS glyphs will be replace
  2542. // default character, even it is a valid SHIFTJIS code.
  2543. // we cache widths in client side, its logic is that just retrun DBCS width
  2544. // if the codepoint is valid SHIFTJIS codepoint. but above case real glyph is
  2545. // default char, the width is incorrect. then we just define "Requested chars"
  2546. // for DBCS font, if this font does not have all of these glyph, we don't
  2547. // cache in client side.
  2548. while( (wc = RequestedDBCSChars[ulIndex]) != 0x0000 )
  2549. {
  2550. if( !bGetGlyphMetrics(1,&gp,&wc, &dco) )
  2551. {
  2552. return(FALSE);
  2553. }
  2554. // Does the glyph fall into the category of default glyph ?
  2555. if( gp.hg == prfnt->hgDefault )
  2556. {
  2557. return(FALSE); // we don't cache in client side...
  2558. }
  2559. ulIndex++;
  2560. }
  2561. // treat last char in the array of width as DBCS width.
  2562. fxDBCSInc = (USHORT)(((GLYPHDATA*) gp.pgdf)->fxD);
  2563. ulIndex = 0;
  2564. // check Optional DBCS width.
  2565. while( (wc = OptionalDBCSChars[ulIndex]) != 0x0000 )
  2566. {
  2567. if( !bGetGlyphMetrics(1,&gp,&wc) )
  2568. {
  2569. return(FALSE);
  2570. }
  2571. fxInc = (USHORT)(((GLYPHDATA*) gp.pgdf)->fxD);
  2572. fxDBCSInc = max(fxInc,fxDBCSInc);
  2573. ulIndex++;
  2574. }
  2575. }
  2576. else
  2577. {
  2578. // WARNING("bGetWidthDataRFONTOBJ: DBCS chars not fixed pitch\n");
  2579. return(FALSE); // we don't cache in client side.
  2580. }
  2581. fxDefaultInc = (USHORT)(pgdDefault()->fxD);
  2582. }
  2583. if( ((fxHeight | fxCharInc | fxBreak | fxDBCSInc) & 0xFFFF0000L) == 0 )
  2584. {
  2585. pwd->sHeight = (USHORT) fxHeight;
  2586. pwd->sCharInc = (USHORT) fxCharInc;
  2587. pwd->sBreak = (USHORT) fxBreak;
  2588. // for DBCS client side widhts
  2589. pwd->sDBCSInc = (USHORT) fxDBCSInc;
  2590. pwd->sDefaultInc = (USHORT) fxDefaultInc;
  2591. // Set a Windows 3.1 compatible overhang.
  2592. pwd->sOverhang = (USHORT) (lOverhang() << 4);
  2593. // Get some important ANSI codepoints.
  2594. IFIMETRICS *pifi = prfnt->ppfe->pifi;
  2595. pwd->iFirst = pifi->chFirstChar;
  2596. pwd->iLast = pifi->chLastChar;
  2597. pwd->iDefault = pifi->chDefaultChar;
  2598. pwd->iBreak = pifi->chBreakChar;
  2599. return(TRUE);
  2600. }
  2601. return(FALSE);
  2602. }
  2603. /************************Public*Routine*****************\
  2604. * RFONTOBJ::vChnageiTTUniq
  2605. *
  2606. * This is only called by PreTextOut()
  2607. \*******************************************************/
  2608. void RFONTOBJ::vChangeiTTUniq(FONTFILE_PRINTKVIEW *pPrintKview)
  2609. {
  2610. ULONG i;
  2611. ULONG_PTR uPFE, uPFEend;
  2612. ULONG_PTR iTTUniq;
  2613. uPFE = (ULONG_PTR)ppfe();
  2614. uPFEend = uPFE + sizeof(PFE);
  2615. iTTUniq = pPrintKview->iTTUniq;
  2616. if (pfo()->flFontType & TRUETYPE_FONTTYPE)
  2617. {
  2618. if ((iTTUniq >= uPFE) && (iTTUniq < uPFEend))
  2619. {
  2620. if (iTTUniq < (--uPFEend))
  2621. {
  2622. pPrintKview->iTTUniq++;
  2623. }
  2624. else
  2625. {
  2626. pPrintKview->iTTUniq = uPFE;
  2627. }
  2628. pfo()->iTTUniq = pPrintKview->iTTUniq;
  2629. }
  2630. }
  2631. }
  2632. /******************************Public*Routine******************************\
  2633. *
  2634. * Routine Name:
  2635. *
  2636. * RFONTOBJ:PreTextOut
  2637. *
  2638. * Routine Description:
  2639. *
  2640. * Called before calling to any DrvTextOut to prepare for callbacks
  2641. * to FONTOBJ_pjOpenTypeTable and FONTOBJ_pvTrueTypeFontFile.
  2642. *
  2643. * Arguments:
  2644. *
  2645. * none
  2646. *
  2647. * Called by:
  2648. *
  2649. * bProxyTextOut, GreExtTextOutWLocked
  2650. *
  2651. * Return Value:
  2652. *
  2653. * none
  2654. *
  2655. \**************************************************************************/
  2656. void RFONTOBJ::PreTextOut(XDCOBJ& dco)
  2657. {
  2658. FONTFILE_PRINTKVIEW *pPrintKView;
  2659. if (dco.bPrinter() && !dco.bUMPD() && !bDeviceFont())
  2660. {
  2661. SEMOBJ so(ghsemPrintKView);
  2662. pPrintKView = gpPrintKViewList;
  2663. while (pPrintKView)
  2664. {
  2665. if (pPrintKView->hff == pPFF()->hff)
  2666. {
  2667. pPrintKView->cPrint++;
  2668. if (pPrintKView->pKView == NULL)
  2669. {
  2670. vChangeiTTUniq(pPrintKView);
  2671. }
  2672. }
  2673. pPrintKView = pPrintKView->pNext;
  2674. }
  2675. }
  2676. }
  2677. /******************************Public*Routine******************************\
  2678. *
  2679. * Routine Name:
  2680. *
  2681. * RFONTOBJ::pvFile
  2682. *
  2683. * Routine Description:
  2684. *
  2685. * Generates a kernel mode pointer to the associated font file.
  2686. *
  2687. * Arguments:
  2688. *
  2689. * pcjFile - address of 32-bit variable to receive the size
  2690. * of the TrueType file in bytes.
  2691. *
  2692. * Called by:
  2693. *
  2694. * FONTOBJ_pvTrueTypeFontFile
  2695. *
  2696. * Return Value:
  2697. *
  2698. * A kernel mode pointer to the associated font file.
  2699. *
  2700. \**************************************************************************/
  2701. PVOID RFONTOBJ::pvFile(ULONG *pcjFile)
  2702. {
  2703. char *pchFile;
  2704. ULONG cjFile;
  2705. pchFile = 0;
  2706. cjFile = 0;
  2707. PDEVOBJ pdo( prfnt->hdevProducer );
  2708. if ( pdo.bValid() )
  2709. {
  2710. PFF *pPFF;
  2711. if ( pPFF = prfnt->pPFF )
  2712. {
  2713. HFF hff;
  2714. if ( hff = pPFF->hff )
  2715. {
  2716. if ( pchFile = (char*) pdo.GetTrueTypeFile( hff, &cjFile ))
  2717. {
  2718. pchFile = pchTranslate( pchFile );
  2719. }
  2720. }
  2721. }
  2722. }
  2723. if ( pchFile == 0 )
  2724. {
  2725. cjFile = 0;
  2726. }
  2727. if ( pcjFile )
  2728. {
  2729. *pcjFile = cjFile;
  2730. }
  2731. return( pchFile );
  2732. }
  2733. /******************************Public*Routine******************************\
  2734. *
  2735. * Routine Name:
  2736. *
  2737. * RFONTOBJ::pjTable
  2738. *
  2739. * Routine Description:
  2740. *
  2741. * Generates a kernel mode view of a particular table in the associated
  2742. * OpenType font file.
  2743. *
  2744. * Arguments:
  2745. *
  2746. * ulTag a 4-byte tag of the table according to the OpenType
  2747. * conventions
  2748. *
  2749. * pcjTable the address of a 32-bit variable that will receive the size
  2750. * of the table in bytes.
  2751. *
  2752. * Called by:
  2753. *
  2754. * FONTOBJ_pjOpenTypeTable
  2755. *
  2756. * Return Value:
  2757. *
  2758. * a kernel mode pointer to the desired OpenType table
  2759. *
  2760. \**************************************************************************/
  2761. BYTE *RFONTOBJ::pjTable( ULONG ulTag, ULONG *pcjTable )
  2762. {
  2763. BYTE *pjTable = 0;
  2764. ULONG cjTable = 0;
  2765. PDEVOBJ pdo( prfnt->hdevProducer );
  2766. if ( pdo.bValid() )
  2767. {
  2768. PFF *pPFF;
  2769. LONG lRet;
  2770. if ( pPFF = prfnt->pPFF )
  2771. {
  2772. HFF hff;
  2773. if ( hff = pPFF->hff )
  2774. {
  2775. lRet = pdo.QueryTrueTypeTable( hff,
  2776. 1,
  2777. ulTag,
  2778. 0,
  2779. 0,
  2780. 0,
  2781. &pjTable,
  2782. &cjTable
  2783. );
  2784. if ( lRet == FD_ERROR )
  2785. {
  2786. pjTable = 0;
  2787. }
  2788. else
  2789. {
  2790. pjTable = (BYTE*) pchTranslate( (char*) pjTable );
  2791. }
  2792. }
  2793. }
  2794. }
  2795. if ( pjTable == 0 )
  2796. {
  2797. cjTable = 0;
  2798. }
  2799. if ( pcjTable )
  2800. {
  2801. *pcjTable = cjTable;
  2802. }
  2803. return( pjTable );
  2804. }
  2805. /*******************************Public*Routine********************************\
  2806. * Routine Name:
  2807. *
  2808. * bFindPrintKView()
  2809. *
  2810. * Routine Description:
  2811. *
  2812. * This routine goes through the gpPrintKViewList and try to find whether
  2813. * there is an existing node matches hff and iFile.
  2814. *
  2815. * Return:
  2816. * TRUE if it finds a matching node (hff and iFile), and pNode contains
  2817. * the address of the matching node.
  2818. * Note that the pKView in the node might be NULL, which requires the caller
  2819. * to re-map the view.
  2820. *
  2821. * FALSE if it doesn't find a match node.
  2822. *
  2823. * History:
  2824. * 02-Jun-1999 Xudong Wu [tessiew]
  2825. * Wrote it.
  2826. \*****************************************************************************/
  2827. BOOL bFindPrintKView(
  2828. HFF hff,
  2829. ULONG iFile,
  2830. FONTFILE_PRINTKVIEW **ppNode
  2831. )
  2832. {
  2833. ASSERTGDI(hff, "bFindPrintKView, hff == 0\n");
  2834. FONTFILE_PRINTKVIEW *pPrintKView;
  2835. *ppNode = NULL;
  2836. SEMOBJ so(ghsemPrintKView);
  2837. pPrintKView = gpPrintKViewList;
  2838. while (pPrintKView)
  2839. {
  2840. if
  2841. (
  2842. (pPrintKView->hff == hff) && (pPrintKView->iFile == iFile) // matching node
  2843. )
  2844. {
  2845. *ppNode = pPrintKView;
  2846. return TRUE;
  2847. }
  2848. pPrintKView = pPrintKView->pNext;
  2849. }
  2850. return FALSE;
  2851. }
  2852. /**********************Public*Routine************************\
  2853. * Routine Name:
  2854. *
  2855. * bAddPrintKView()
  2856. *
  2857. * Routine Description:
  2858. *
  2859. * This routine either adds a new node or update the pKView
  2860. * in an existing node to the global gpPrintKViewList
  2861. *
  2862. * If pNode is not NULL, it points to the existing node with
  2863. * the matching hff and iFile.
  2864. *
  2865. * History:
  2866. * 02-Jun-1999 Xudong Wu [tessiew]
  2867. * Wrote it.
  2868. \************************************************************/
  2869. BOOL bAddPrintKView(
  2870. HFF hff,
  2871. PVOID pvKView,
  2872. ULONG iFile,
  2873. ULONG_PTR iTTUniq,
  2874. FONTFILE_PRINTKVIEW *pNode
  2875. )
  2876. {
  2877. FONTFILE_PRINTKVIEW *pNew = NULL;
  2878. SEMOBJ so(ghsemPrintKView);
  2879. // pNode != NULL, existing node with matching hff and iFile
  2880. if (pNode) // just updating the pointer, cPrint is ++'ed at PreTextOut time
  2881. {
  2882. pNode->pKView = pvKView;
  2883. }
  2884. else // new node
  2885. {
  2886. pNew = (FONTFILE_PRINTKVIEW *)PALLOCMEM(sizeof(FONTFILE_PRINTKVIEW), 'pmtG');
  2887. if (pNew)
  2888. {
  2889. pNew->hff = hff;
  2890. pNew->pKView = pvKView;
  2891. pNew->iFile = iFile;
  2892. pNew->cPrint = 1;
  2893. pNew->iTTUniq = iTTUniq;
  2894. // put it at the head of the linked list
  2895. pNew->pNext = gpPrintKViewList;
  2896. gpPrintKViewList = pNew;
  2897. }
  2898. else
  2899. return FALSE;
  2900. }
  2901. return TRUE;
  2902. }
  2903. /******************************Public*Routine******************************\
  2904. *
  2905. * Routine Name:
  2906. *
  2907. * RFONTOBJ::pchTranslate
  2908. *
  2909. * Routine Description:
  2910. *
  2911. * This routine returns a pointer into a kernel mode view of a font file.
  2912. * If the argument is a kernel mode address then this routine simply
  2913. * returns the same address. If the argument is a user mode address
  2914. * then this routine will map a kernel mode view of the font, if
  2915. * necessary, and translate the user mode pointer into an equivalent
  2916. * kernel mode pointer. If it is necessary to map a kernel mode view
  2917. * this routine records that fact in the global list. This view will be
  2918. * unmapped when the fontcontext goes away or at the "clean up" time.
  2919. *
  2920. * Arguments:
  2921. *
  2922. * pch a pointer into the font file. This may be either a user mode
  2923. * view or a kernel mode view.
  2924. *
  2925. * Called by:
  2926. *
  2927. * RFONTOBJ::pjTable
  2928. * RFONTOBJ::pvFile
  2929. *
  2930. * Return Value:
  2931. *
  2932. * a kernel mode pointer to the desired offset into the font file
  2933. *
  2934. \**************************************************************************/
  2935. char* RFONTOBJ::pchTranslate(char *pch)
  2936. {
  2937. NTSTATUS NtStatus;
  2938. ULONG iKernelBase;
  2939. char *pchBase;
  2940. PFF *pPFF_;
  2941. FONTFILEVIEW **ppFFV, *pFFV;
  2942. PVOID pvKView;
  2943. FONTFILE_PRINTKVIEW *pNode = NULL;
  2944. HFF hff;
  2945. //??? is it possible that pch is a kernel address? if so, what should we return?
  2946. if (pch &&
  2947. IS_USER_ADDRESS(pch) &&
  2948. (pPFF_ = prfnt->pPFF) &&
  2949. (hff = pPFF_->hff) &&
  2950. (ppFFV = pPFF_->ppfv))
  2951. {
  2952. for (iKernelBase = 0; iKernelBase < pPFF_->cFiles; ppFFV++, iKernelBase++)
  2953. {
  2954. if (pFFV = *ppFFV)
  2955. {
  2956. pchBase = (char*) ((pFFV->SpoolerBase) ? pFFV->SpoolerBase : pFFV->fv.pvViewFD);
  2957. if (pchBase && (pchBase <= pch) && (pch < pchBase + pFFV->fv.cjView))
  2958. {
  2959. if (!bFindPrintKView(hff, iKernelBase, &pNode) || (pNode->pKView == NULL))
  2960. {
  2961. if (pFFV->fv.pSection)
  2962. {
  2963. if (NT_SUCCESS(MapFontFileInKernel(pFFV->fv.pSection, &pvKView)))
  2964. {
  2965. if (bAddPrintKView(hff, pvKView, iKernelBase, (ULONG_PTR)ppfe(), pNode))
  2966. {
  2967. return (pch - pchBase + (char*)pvKView);
  2968. }
  2969. else
  2970. {
  2971. vUnmapFontFileInKernel(pvKView);
  2972. return NULL;
  2973. }
  2974. }
  2975. }
  2976. else
  2977. {
  2978. RIP("pSection = 0\n");
  2979. }
  2980. }
  2981. else
  2982. {
  2983. pvKView = pNode->pKView;
  2984. return (pch - pchBase + (char*)pvKView);
  2985. }
  2986. }
  2987. }
  2988. }
  2989. }
  2990. return NULL;
  2991. }
  2992. /******************************Public*Routine******************************\
  2993. *
  2994. * Routine Name:
  2995. *
  2996. * RFONTOBJ:PostTextOut
  2997. *
  2998. * Routine Description:
  2999. *
  3000. * Called after calling to any DrvTextOut to keep track of cPrint count
  3001. *
  3002. * Arguments:
  3003. *
  3004. * none
  3005. *
  3006. * Called by:
  3007. *
  3008. * bProxyTextOut, GreExtTextOutWLocked
  3009. *
  3010. * Return Value:
  3011. *
  3012. * none
  3013. *
  3014. \**************************************************************************/
  3015. void RFONTOBJ::PostTextOut(XDCOBJ& dco)
  3016. {
  3017. FONTFILE_PRINTKVIEW *pPrintKView;
  3018. if (dco.bPrinter() && !dco.bUMPD() && !bDeviceFont())
  3019. {
  3020. SEMOBJ so(ghsemPrintKView);
  3021. pPrintKView = gpPrintKViewList;
  3022. while (pPrintKView)
  3023. {
  3024. if (pPrintKView->hff == pPFF()->hff)
  3025. {
  3026. if (pPrintKView->cPrint)
  3027. {
  3028. pPrintKView->cPrint--;
  3029. }
  3030. }
  3031. pPrintKView = pPrintKView->pNext;
  3032. }
  3033. }
  3034. }
  3035. /*******************Public*Routine***********************\
  3036. * Routine Name:
  3037. *
  3038. * vClosePrintKView()
  3039. *
  3040. * Routine Description:
  3041. *
  3042. * This routine goes through the global gpPrintKViewList
  3043. * and unmap all the kernel views, except for those "few" at
  3044. * that are at the moment used by DrvTextOut calls.
  3045. * This is only called when the first attemp of mapping
  3046. * a kernel view on a font file failed.
  3047. \********************************************************/
  3048. void vClosePrintKView()
  3049. {
  3050. FONTFILE_PRINTKVIEW *pPrintKView;
  3051. SEMOBJ so(ghsemPrintKView);
  3052. pPrintKView = gpPrintKViewList;
  3053. while(pPrintKView)
  3054. {
  3055. if
  3056. (
  3057. (pPrintKView->cPrint == 0) && // no DrvTextOut calls in progress with this font
  3058. pPrintKView->pKView // and file is mapped
  3059. )
  3060. {
  3061. vUnmapFontFileInKernel(pPrintKView->pKView);
  3062. pPrintKView->pKView = NULL;
  3063. }
  3064. pPrintKView = pPrintKView->pNext;
  3065. }
  3066. }
  3067. /***********************Public*Routine***************************\
  3068. * Routine Name:
  3069. *
  3070. * MapFontFileInKernel(void* void**)
  3071. *
  3072. * Routine Description:
  3073. *
  3074. * This routine maps a font file in kernel.
  3075. \****************************************************************/
  3076. NTSTATUS MapFontFileInKernel(void *pSection, void** ppvKView)
  3077. {
  3078. NTSTATUS NtStatus;
  3079. SIZE_T Dummy;
  3080. *ppvKView = NULL;
  3081. Dummy = 0; // map entire section into kernel
  3082. #if defined(_GDIPLUS_)
  3083. NtStatus = MapViewInProcessSpace(
  3084. pSection,
  3085. ppvKView,
  3086. &Dummy);
  3087. #elif defined(_HYDRA_)
  3088. // MmMapViewInSessionSpace is internally promoted to
  3089. // MmMapViewInSystemSpace on non-Hydra systems.
  3090. NtStatus = Win32MapViewInSessionSpace(pSection,
  3091. ppvKView,
  3092. &Dummy);
  3093. #else
  3094. NtStatus = MmMapViewInSystemSpace(pSection,
  3095. ppvKView,
  3096. &Dummy);
  3097. #endif
  3098. if (!NT_SUCCESS(NtStatus))
  3099. {
  3100. WARNING("MapFontViewInKernel -- failure at the first attemp\n");
  3101. vClosePrintKView();
  3102. // try again
  3103. #if defined(_GDIPLUS_)
  3104. NtStatus = MapViewInProcessSpace(
  3105. pSection,
  3106. ppvKView,
  3107. &Dummy);
  3108. #elif defined(_HYDRA_)
  3109. // MmMapViewInSessionSpace is internally promoted to
  3110. // MmMapViewInSystemSpace on non-Hydra systems.
  3111. NtStatus = Win32MapViewInSessionSpace(pSection,
  3112. ppvKView,
  3113. &Dummy);
  3114. #else
  3115. NtStatus = MmMapViewInSystemSpace(pSection,
  3116. ppvKView,
  3117. &Dummy);
  3118. #endif
  3119. }
  3120. #ifdef _HYDRA_
  3121. #if DBG
  3122. if (!G_fConsole)
  3123. {
  3124. DebugGreTrackAddMapView(*ppvKView);
  3125. }
  3126. #endif
  3127. #endif
  3128. return (NtStatus);
  3129. }
  3130. /**********************Public*Routine****************************\
  3131. * Routine Name:
  3132. *
  3133. * vUnmapFontFileInKernel(void*)
  3134. *
  3135. * Routine Description:
  3136. *
  3137. * This routine unmap the kernel font file view
  3138. \****************************************************************/
  3139. VOID vUnmapFontFileInKernel(void *pvKView)
  3140. {
  3141. #if defined(_GDIPLUS_)
  3142. UnmapViewInProcessSpace(pvKView);
  3143. #elif defined(_HYDRA_)
  3144. // MmUnmapViewInSessionSpace is internally promoted to
  3145. // MmUnmapViewInSystemSpace on non-Hydra systems.
  3146. Win32UnmapViewInSessionSpace(pvKView);
  3147. #else
  3148. MmUnmapViewInSystemSpace(pvKView);
  3149. #endif
  3150. #ifdef _HYDRA_
  3151. #if DBG
  3152. if (!G_fConsole)
  3153. {
  3154. DebugGreTrackRemoveMapView (pvKView);
  3155. }
  3156. #endif
  3157. #endif
  3158. }
  3159. /*******************Public*Routine********************\
  3160. * vCleanupPrintKViewList
  3161. *
  3162. * For MultiUserNtGreCleanup (Hydra) cleanup.
  3163. *
  3164. * Worker functions for MultiUserGreCleanupAllFonts.
  3165. *
  3166. *
  3167. * History:
  3168. * 01-Jun-1999 -by- Xudong Wu [tessiew]
  3169. * Wrote it.
  3170. \*****************************************************/
  3171. void vCleanupPrintKViewList()
  3172. {
  3173. FONTFILE_PRINTKVIEW *pPrintKView, *pNext;
  3174. pNext = gpPrintKViewList;
  3175. while(pNext)
  3176. {
  3177. ASSERTGDI(!pNext->pKView, "vCleanupPrintKViewList: unmapped pKView\n");
  3178. pPrintKView = pNext;
  3179. pNext = pPrintKView->pNext;
  3180. VFREEMEM(pPrintKView);
  3181. }
  3182. }
  3183. /*********************Public*Routine*******************\
  3184. * Routine Name:
  3185. *
  3186. * UnmapPrintKView(char*)
  3187. *
  3188. * Routine Description:
  3189. *
  3190. * This routine is ONLY called at DestroyFont time
  3191. * when the cRFONT refer count in RFONT is ONE.
  3192. *
  3193. *
  3194. * History:
  3195. * 02-Jun-1999 Xudong Wu [tessiew]
  3196. * Wrote it.
  3197. \******************************************************/
  3198. void UnmapPrintKView(HFF hff)
  3199. {
  3200. FONTFILE_PRINTKVIEW *pPrintKView;
  3201. SEMOBJ so(ghsemPrintKView);
  3202. pPrintKView = gpPrintKViewList;
  3203. while(pPrintKView)
  3204. {
  3205. if (pPrintKView->hff == hff && pPrintKView->pKView)
  3206. {
  3207. ASSERTGDI(!pPrintKView->cPrint, "UnmapPrintKView: cPrint != 0\n");
  3208. vUnmapFontFileInKernel(pPrintKView->pKView);
  3209. pPrintKView->pKView = NULL;
  3210. }
  3211. pPrintKView = pPrintKView->pNext;
  3212. }
  3213. }
  3214. //
  3215. // Implementation of pvFile and pchTranslate for UMPD.
  3216. // Here we need to map the font file into the current process' user mode address
  3217. // instead of kernel's address space.
  3218. //
  3219. PVOID
  3220. RFONTOBJ::pvFileUMPD(
  3221. ULONG *pcjFile,
  3222. PVOID *ppBase
  3223. )
  3224. {
  3225. CHAR *pchFile = NULL;
  3226. ULONG cjFile = 0;
  3227. PFF *pPFF;
  3228. HFF hff;
  3229. PDEVOBJ pdo( prfnt->hdevProducer );
  3230. //
  3231. // pdo.GetTrueTypeFile returns a user mode address in
  3232. // CSR process' address space.
  3233. //
  3234. if (pdo.bValid() &&
  3235. (pPFF = prfnt->pPFF) != NULL &&
  3236. (hff = pPFF->hff) != NULL &&
  3237. (pchFile = (CHAR *) pdo.GetTrueTypeFile(hff, &cjFile)) != NULL)
  3238. {
  3239. //
  3240. // We now need to translate that address into
  3241. // the current process' address space.
  3242. //
  3243. pchFile = pchTranslateUMPD(pchFile, ppBase);
  3244. }
  3245. if (pchFile == NULL)
  3246. cjFile = 0;
  3247. if (pcjFile)
  3248. *pcjFile = cjFile;
  3249. return pchFile;
  3250. }
  3251. CHAR*
  3252. RFONTOBJ::pchTranslateUMPD(
  3253. CHAR *pch,
  3254. PVOID *ppBase
  3255. )
  3256. {
  3257. NTSTATUS NtStatus;
  3258. ULONG iKernelBase;
  3259. CHAR *pchBase;
  3260. PFF *pPFF_;
  3261. FONTFILEVIEW **ppFFV, *pFFV;
  3262. VOID *pSaveFirstSpoolerBase, *pFinalSpoolerBase;
  3263. VOID *pSaveFirstSection, *pFinalSection;
  3264. if ((pch != NULL) &&
  3265. IS_USER_ADDRESS(pch) &&
  3266. (pPFF_ = prfnt->pPFF) != NULL &&
  3267. (ppFFV = pPFF_->ppfv) != NULL)
  3268. {
  3269. for (iKernelBase = 0; iKernelBase < pPFF_->cFiles; ppFFV++, iKernelBase++)
  3270. {
  3271. if ((pFFV = *ppFFV) == NULL)
  3272. continue;
  3273. // type 1 fonts have 2 or 3 files, we save the pSection and SpoolerBase and use for 2nd, 3rd file
  3274. // in remote postscript printing they share the the same section and spooler base
  3275. if (iKernelBase == 0)
  3276. {
  3277. //save the pSection and pSpoolerBase of the 1st font
  3278. pSaveFirstSection = pFFV->fv.pSection;
  3279. pSaveFirstSpoolerBase = pFFV->SpoolerBase;
  3280. }
  3281. if (pFFV->SpoolerBase == NULL)
  3282. {
  3283. pFinalSpoolerBase = pSaveFirstSpoolerBase;
  3284. }
  3285. else
  3286. {
  3287. pFinalSpoolerBase = pFFV->SpoolerBase;
  3288. }
  3289. pchBase = (CHAR*) ((pFinalSpoolerBase) ? pFinalSpoolerBase : pFFV->fv.pvViewFD);
  3290. if (pchBase && (pchBase <= pch) && (pch < pchBase + pFFV->fv.cjView))
  3291. {
  3292. if (pFFV->fv.pSection == NULL)
  3293. {
  3294. pFinalSection = pSaveFirstSection;
  3295. }
  3296. else
  3297. {
  3298. pFinalSection = pFFV->fv.pSection;
  3299. }
  3300. if (pFinalSection == NULL)
  3301. {
  3302. RIP("pSection == NULL\n");
  3303. return NULL;
  3304. }
  3305. LARGE_INTEGER SectionOffset;
  3306. SIZE_T ViewSize;
  3307. *ppBase = NULL;
  3308. ViewSize = 0;
  3309. RtlZeroMemory(&SectionOffset, sizeof(SectionOffset));
  3310. NtStatus = MmMapViewOfSection(
  3311. pFinalSection,
  3312. PsGetCurrentProcess(),
  3313. ppBase,
  3314. 0,
  3315. pFFV->fv.cjView,
  3316. &SectionOffset,
  3317. &ViewSize,
  3318. ViewUnmap,
  3319. 0,
  3320. PAGE_READONLY);
  3321. if (!NT_SUCCESS(NtStatus))
  3322. {
  3323. WARNING("RFONTOBJ::pchTranslateUMPD: MmMapViewOfSection failed\n");
  3324. *ppBase = NULL;
  3325. return NULL;
  3326. }
  3327. return (CHAR *) *ppBase + (pch - pchBase);
  3328. }
  3329. }
  3330. }
  3331. return NULL;
  3332. }