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.

3993 lines
137 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: fontmap.cxx *
  3. * *
  4. * Routines for mapping fonts. *
  5. * *
  6. * Created: 17-Jun-1992 11:12:16 *
  7. * Author: Kirk Olynyk [kirko] *
  8. * *
  9. * Copyright (c) 1992-1999 Microsoft Corporation *
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. extern "C" VOID vInitMapper();
  13. extern "C" NTSTATUS DefaultFontQueryRoutine(IN PWSTR, IN ULONG, IN PVOID,
  14. IN ULONG, IN PVOID, IN PVOID);
  15. #pragma alloc_text(INIT, vInitMapper)
  16. #pragma alloc_text(INIT, DefaultFontQueryRoutine)
  17. // external procedures from draweng.cxx
  18. VOID vArctan(EFLOAT, EFLOAT,EFLOAT&, LONG&);
  19. // external procedure from FONTSUB.CXX
  20. #ifdef LANGPACK
  21. extern "C" BOOL EngLpkInstalled();
  22. #endif
  23. /*** globals defined in this module ***/
  24. #if DBG
  25. #define DEBUG_SMALLSUBSTITUTION 0x80
  26. FLONG gflFontDebug = 0;
  27. PFE *ppfeBreak = 0;
  28. LONG lDevFontThresh = FM_DEVICE_FONTS_ARE_BETTER_BELOW_THIS_SIZE;
  29. #endif
  30. static const WCHAR gpwszDefFixedSysFaceName[] = L"FIXEDSYS";
  31. #define WIN31_SMALL_WISH_HEIGHT 2
  32. #define WIN31_SMALL_FONT_HEIGHT 3
  33. PFE *gppfeMapperDefault = PPFENULL; // set to something meaningfule
  34. // at boot by bInitSystemFont()
  35. // in stockfnt.cxx
  36. // Storage for static globals in MAPPER
  37. PDWORD MAPPER::SignatureTable; // base of the signature table
  38. PWCHAR MAPPER::FaceNameTable; // base of the face name table
  39. BYTE MAPPER::DefaultCharset; // default charset is equivilent to this
  40. /******************************Public*Routine******************************\
  41. * BYTE jMapCharset()
  42. *
  43. * This routine is stollen from Win95 code (converted from asm).
  44. * It checks if a font supports a requested charset.
  45. *
  46. * History:
  47. * 2-Jul-1997 -by- Yung-Jen Tony Tsai [yungt]
  48. * 17-Jan-1995 -by- Bodin Dresevic [BodinD]
  49. * Wrote it.
  50. \**************************************************************************/
  51. BYTE jMapCharset(BYTE lfCharSet, PFEOBJ &pfeo)
  52. {
  53. BYTE jCharSet;
  54. BYTE jLinkedCharSet;
  55. BYTE * ajCharSets;
  56. BYTE * ajCharSetsEnd;
  57. BYTE * pjCharSets;
  58. IFIMETRICS *pifi = pfeo.pifi();
  59. // if only one charset supported in a font, this is the best match to
  60. // the request that the font can offer.
  61. // the check for FM_INFO_TECH_TYPE1 is a temporary hack until
  62. // we add a new field to the IFI metrics for the Type1 font ID's
  63. // [gerritv] 8-23-95
  64. if (pifi->dpCharSets == 0)
  65. {
  66. return( pifi->jWinCharSet );
  67. }
  68. // this is what is meant by default_charset:
  69. if (lfCharSet == DEFAULT_CHARSET)
  70. {
  71. lfCharSet = MAPPER::DefaultCharset;
  72. }
  73. // if several charsets are supported, let us check out
  74. // if the requested one is one of them:
  75. ajCharSets = (BYTE *)pifi + pifi->dpCharSets;
  76. ajCharSetsEnd = ajCharSets + MAXCHARSETS;
  77. for (pjCharSets = ajCharSets; pjCharSets < ajCharSetsEnd; pjCharSets++)
  78. {
  79. if (*pjCharSets == lfCharSet)
  80. {
  81. return( lfCharSet );
  82. }
  83. if (*pjCharSets == DEFAULT_CHARSET) // terminator
  84. {
  85. // The charset did not support in base font.
  86. // We need to check the charset of linked font
  87. // If there is one, then we get it
  88. // otherwise, we return BaseFont.ajCharSets[0]
  89. jCharSet = ajCharSets[0];
  90. break;
  91. }
  92. }
  93. if (pfeo.pGetLinkedFontEntry())
  94. {
  95. // No charset in the base font matches the requested charset.
  96. // And this base font has lined font. Then we should check
  97. // the charsets in the linked font to see if there is a
  98. // match there as well.
  99. PLIST_ENTRY p = pfeo.pGetLinkedFontList()->Flink;
  100. while ( p != pfeo.pGetLinkedFontList() )
  101. {
  102. PPFEDATA ppfeData = CONTAINING_RECORD(p,PFEDATA,linkedFontList);
  103. PFEOBJ pfeoEudc(ppfeData->appfe[PFE_NORMAL]);
  104. pifi = pfeoEudc.pifi();
  105. if (pifi->dpCharSets == 0 && pifi->jWinCharSet == lfCharSet)
  106. {
  107. return ( lfCharSet );
  108. }
  109. else if (pifi->dpCharSets)
  110. {
  111. ajCharSets = (BYTE *)pifi + pifi->dpCharSets;
  112. ajCharSetsEnd = ajCharSets + MAXCHARSETS;
  113. for (pjCharSets = ajCharSets; pjCharSets < ajCharSetsEnd; pjCharSets++)
  114. {
  115. if (*pjCharSets == lfCharSet)
  116. {
  117. return ( lfCharSet );
  118. }
  119. if (*pjCharSets == DEFAULT_CHARSET) // terminator
  120. {
  121. break; // End of for loop
  122. }
  123. }
  124. }
  125. p = p->Flink;
  126. }
  127. }
  128. return(jCharSet);
  129. }
  130. /******************************Public*Routine******************************\
  131. * GreGetCannonicalName(
  132. *
  133. * The input is the zero terminated name of the form
  134. *
  135. * foo_XXaaaYYbbb...ZZccc
  136. *
  137. * where XX, YY, ZZ are numerals (arbitrary number of them) and
  138. * aaa, bbb, ccc are not numerals, i.e. spaces, or another '_' signs or
  139. * letters with abbreviated axes names.
  140. *
  141. * This face name will be considered equivalent to face name foo
  142. * with DESIGNVECTOR [XX,YY, ...ZZ], number of axes being determined
  143. * by number of numeral sequences.
  144. *
  145. *
  146. * Effects:
  147. *
  148. * History:
  149. * 25-Jun-1997 -by- Bodin Dresevic [BodinD]
  150. * Wrote it.
  151. \**************************************************************************/
  152. #define IS_DIGIT(x) (((x) >= L'0') && ((x) <= L'9'))
  153. #define GET_DIGIT(X) ((X) - L'0')
  154. #define WC_UNDERSCORE L'_'
  155. VOID GreGetCannonicalName(
  156. const WCHAR *pwszIn, // foo_XX_YY
  157. WCHAR *pwszOut, // Cannonical and capitalized name FOO
  158. ULONG *pcAxes,
  159. DESIGNVECTOR *pdv // [XX,YY] on out
  160. )
  161. {
  162. // The input is the zero terminated name of the form
  163. //
  164. // foo_XXaaaYYbbb...ZZccc
  165. //
  166. // where XX, YY, ZZ are numerals (arbitrary number of them) and
  167. // aaa, bbb, ccc are not numerals, i.e. spaces, or another '_' signs or
  168. // letters with abbreviated axes names.
  169. //
  170. // This face name will be considered equivalent to face name foo
  171. // with DESIGNVECTOR [XX,YY, ...ZZ], number of axes being determined
  172. // by number of numeral sequences.
  173. const WCHAR *pwc;
  174. ULONG cAxes = 0;
  175. ULONG cwc;
  176. for
  177. (
  178. pwc = pwszIn ;
  179. (*pwc) && !((*pwc == WC_UNDERSCORE) && IS_DIGIT(pwc[1]));
  180. pwc++
  181. )
  182. {
  183. // do nothing;
  184. }
  185. // copy out, zero terminate
  186. // Sundown safe truncation
  187. cwc = (ULONG)(pwc - pwszIn);
  188. memcpy(pwszOut, pwszIn, cwc * sizeof(WCHAR));
  189. pwszOut[cwc] = L'\0';
  190. // If we found at least one WC_UNDERSCORE followed by the DIGIT
  191. // we have to compute DV. Underscore followed by the DIGIT is Adobe's rule
  192. if ((*pwc == WC_UNDERSCORE) && IS_DIGIT(pwc[1]))
  193. {
  194. // step to the next character behind undescore
  195. pwc++;
  196. while (*pwc)
  197. {
  198. // go until you hit the first digit
  199. for ( ; *pwc && !IS_DIGIT(*pwc) ; pwc++)
  200. {
  201. // do nothing
  202. }
  203. if (*pwc)
  204. {
  205. // we have just hit the digit
  206. ULONG dvValue = GET_DIGIT(*pwc);
  207. // go until you hit first nondigit or the terminator
  208. pwc++;
  209. for ( ; *pwc && IS_DIGIT(*pwc); pwc++)
  210. {
  211. dvValue = dvValue * 10 + GET_DIGIT(*pwc);
  212. }
  213. pdv->dvValues[cAxes] = (LONG)dvValue;
  214. // we have just parsed a string of numerals
  215. cAxes++;
  216. }
  217. }
  218. }
  219. // record the findings
  220. *pcAxes = cAxes;
  221. pdv->dvNumAxes = cAxes;
  222. pdv->dvReserved = STAMP_DESIGNVECTOR;
  223. }
  224. /******************************Member*Function*****************************\
  225. * bInitMapper()
  226. *
  227. * This callback routine reads the default facename entries from the registry.
  228. * The entries have a the following form:
  229. *
  230. * FontMapper
  231. * FaceName1 = REG_DWORD FontSignature1
  232. * FaceName2 = REG_DWORD FontSignature2
  233. * .........
  234. * Default = REG_DWORD Charset equivilent to default charset
  235. *
  236. * The FontSignature entry has the following format:
  237. *
  238. *
  239. * |-----------------Used when fixed pitch is requested
  240. * ||--------------- Used when FF_ROMAN is requested
  241. * |||-------------- Used when vertical face is requested
  242. * |||-------------- Used as first choice for BM font
  243. * ||||------------- Used as second choice for BM font
  244. * ||||
  245. * |||| |------- Bits 0-7 Charset
  246. * |||| |
  247. * YYYYYYYYXXXXYYYYXXXXXXXX
  248. *
  249. * The bits specified by Y's are unused. Thus determine what face name is
  250. * to be used by default, the mapper will create a signature based on pitch,
  251. * family, charset, etc fields in the LOGFONT and then try to match it against
  252. * the signature/facename pairs in the registry. Putting these values in
  253. * the registry makes it possible add extra entries for other charsets such
  254. * as Shift-JIS and Big-5.
  255. *
  256. *
  257. * History:
  258. * Thu 2-Jun-1994 16:42:11 by Gerrit van Wingerden [gerritv]
  259. * Wrote it.
  260. \**************************************************************************/
  261. extern "C"
  262. NTSTATUS
  263. DefaultFontQueryRoutine
  264. (
  265. IN PWSTR ValueName,
  266. IN ULONG ValueType,
  267. IN PVOID ValueData,
  268. IN ULONG ValueLength,
  269. IN PVOID Context,
  270. IN PVOID EntryContext
  271. )
  272. {
  273. PREGREADER RegRead = (PREGREADER) Context;
  274. if( !_wcsicmp( ValueName, L"DEFAULT" ) )
  275. {
  276. // The value "Default" is a special case.
  277. // It doesn't refer to the facename and instead indicates
  278. // which charset the default charset is equivilent to.
  279. DWORD Data = *((DWORD*)ValueData);
  280. RegRead->DefaultCharset = (BYTE) Data;
  281. }
  282. else if( RegRead->NextValue == NULL )
  283. {
  284. // If NextValue is NULL then this is the first pass
  285. // of the enumeration and we are just figuring out
  286. // the number of entries and size of buffer we
  287. // will need.
  288. RegRead->TableSize += ( wcslen(ValueName) + 1 ) * sizeof(WCHAR);
  289. RegRead->NumEntries += 1;
  290. }
  291. else
  292. {
  293. // On this pass we are actually building up a table of
  294. // signtures and face names to match them.
  295. if( ValueType == REG_DWORD )
  296. {
  297. // move the font signature portion to the high word,
  298. // the low word will store the offset to the facename
  299. DWORD Data = (*((DWORD*)ValueData));
  300. Data |= ( RegRead->NextFaceName - RegRead->FaceNameBase ) << 16;
  301. *(RegRead->NextValue)++ = Data;
  302. // We ignore the last character of the string
  303. // if it is a number. This allows us to have
  304. // multiple entries for the same face name like
  305. // Roman0, Roman1, etc.
  306. UINT ValueLen = wcslen(ValueName);
  307. wcscpy( RegRead->NextFaceName, ValueName );
  308. if( ValueName[ValueLen-1] >= (WCHAR) '0' &&
  309. ValueName[ValueLen-1] <= (WCHAR) '9' )
  310. {
  311. ValueLen -= 1;
  312. (RegRead->NextFaceName)[ValueLen] = (WCHAR) 0;
  313. }
  314. RegRead->NextFaceName += ValueLen+1;
  315. // Finally update the number of entries
  316. RegRead->NumEntries += 1;
  317. }
  318. else
  319. {
  320. WARNING("DefaultFontQueryRoutine:invalid registry entry\n");
  321. return(!STATUS_SUCCESS);
  322. }
  323. }
  324. return( STATUS_SUCCESS );
  325. }
  326. /******************************Member*Function*****************************\
  327. * vInitMapper()
  328. *
  329. * This funtion reads in the FontSignature/Default facenmame pairs from
  330. * the registry. The format of these pairs is described in the comment
  331. * for the DefaultFontQueryRoutine function. vInitMapper() is called once
  332. * when winsrv is initialized.
  333. *
  334. * If there is an error in initialization the mapper can still work but just
  335. * won't fill in default facenames properly and will perform considerably
  336. * slower for requests in which no facename is specified or which an invalid
  337. * facename is specified.
  338. *
  339. * History:
  340. * Thu 2-Jun-1994 16:42:11 by Gerrit van Wingerden [gerritv]
  341. * Wrote it.
  342. \**************************************************************************/
  343. extern "C" VOID vInitMapper()
  344. {
  345. RTL_QUERY_REGISTRY_TABLE QueryTable[2];
  346. DWORD Status;
  347. REGREADER RegRead;
  348. QueryTable[0].QueryRoutine = DefaultFontQueryRoutine;
  349. QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
  350. QueryTable[0].Name = (PWSTR)NULL;
  351. QueryTable[0].EntryContext = NULL;
  352. QueryTable[0].DefaultType = REG_NONE;
  353. QueryTable[0].DefaultData = NULL;
  354. QueryTable[0].DefaultLength = 0;
  355. QueryTable[1].QueryRoutine = NULL;
  356. QueryTable[1].Flags = 0;
  357. QueryTable[1].Name = NULL;
  358. RegRead.NumEntries = 0;
  359. RegRead.TableSize = 0;
  360. RegRead.NextValue = NULL;
  361. MAPPER::SignatureTable = NULL;
  362. MAPPER::FaceNameTable = NULL;
  363. Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
  364. L"FontMapper",
  365. QueryTable,
  366. &RegRead,
  367. NULL );
  368. if( NT_SUCCESS(Status) )
  369. {
  370. MAPPER::SignatureTable = (PDWORD)
  371. PALLOCMEM(RegRead.NumEntries * sizeof(DWORD) + RegRead.TableSize,'pamG');
  372. if( MAPPER::SignatureTable == NULL )
  373. {
  374. WARNING("vInitMapper:Unable to allocate enough memory\n");
  375. return;
  376. }
  377. // Set all the proper pointers in the REGREAD structure
  378. // for the next pass of the enumeration to use.
  379. RegRead.NextValue = MAPPER::SignatureTable;
  380. RegRead.FaceNameBase = (PWCHAR) &(MAPPER::SignatureTable[RegRead.NumEntries]);
  381. RegRead.NumEntries = 0;
  382. RegRead.NextFaceName = RegRead.FaceNameBase;
  383. // do the second pass of the enumeration
  384. Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
  385. L"FontMapper",
  386. QueryTable,
  387. &RegRead,
  388. NULL );
  389. // we are done
  390. if( NT_SUCCESS(Status) )
  391. {
  392. MAPPER::FaceNameTable = RegRead.FaceNameBase;
  393. MAPPER::DefaultCharset = RegRead.DefaultCharset;
  394. return;
  395. }
  396. // else fall through to error warning and reset MAPPER::FaceNameTable
  397. VFREEMEM(MAPPER::SignatureTable);
  398. MAPPER::SignatureTable = NULL;
  399. }
  400. WARNING("vInitMapper:Error enumerating default face names\n");
  401. }
  402. /******************************Member*Function*****************************\
  403. * PWSZ FindFaceName
  404. *
  405. * This routine takes a signature (described above)
  406. * and tries to find a defualt facename that matches it.
  407. * If it doesn't find a match if will return a pointer
  408. * to an empty string.
  409. *
  410. * History:
  411. * Thu 2-Jun-1994 16:42:11 by Gerrit van Wingerden [gerritv]
  412. * Wrote it.
  413. \**************************************************************************/
  414. PWSZ FindFaceName( DWORD Signature )
  415. {
  416. PDWORD SigPtr;
  417. for( SigPtr = MAPPER::SignatureTable;
  418. SigPtr < (PDWORD) MAPPER::FaceNameTable;
  419. SigPtr += 1)
  420. {
  421. if( (*SigPtr & 0xFFFF ) == Signature )
  422. {
  423. return( MAPPER::FaceNameTable + (*SigPtr >> 16 & 0xFFFF ) );
  424. }
  425. }
  426. // Return a pointer to an empty string. Nothing will match
  427. // this causing us to fall through to a case where do a
  428. // mapping which doesnt take face name into account.
  429. return( (PWSZ) L"" );
  430. }
  431. /******************************Member*Function*****************************\
  432. * MAPPER::MAPPER() *
  433. * *
  434. * History: *
  435. * Tue 29-Dec-1992 09:22:31 by Kirk Olynyk [kirko] *
  436. * Added back in the case for small font substitution. *
  437. * *
  438. * Fri 18-Dec-1992 22:43:09 -by- Charles Whitmer [chuckwh] *
  439. * Slimmed it down by removing lots of structure copies. *
  440. * *
  441. * Tue 10-Dec-1991 12:45:41 by Kirk Olynyk [kirko] *
  442. * Wrote it. *
  443. \**************************************************************************/
  444. MAPPER::MAPPER
  445. (
  446. XDCOBJ *pdcoSrc, // current DC
  447. FLONG *pflSim_,
  448. POINTL *pptlSim_,
  449. FLONG *pflAboutMatch_,
  450. const ENUMLOGFONTEXDVW *pelfwWishSrc, // wish list in World Coordinates
  451. const WCHAR * pwszFaceName_,
  452. ULONG ulMaxPenaltySrc, // pruning criteria
  453. BOOL bIndexFont_,
  454. FLONG flOptions = 0
  455. )
  456. {
  457. fl = 0;
  458. ifio.vSet((IFIMETRICS*) NULL);
  459. pdco = pdcoSrc;
  460. pelfwWish = pelfwWishSrc;
  461. pwszFaceName = pwszFaceName_;
  462. // check if this face name might a long foo_XX_YY name of the instance
  463. ULONG cAxes;
  464. flMM = 0;
  465. GreGetCannonicalName(
  466. pwszFaceName_, // foo_XX_YY
  467. this->awcBaseName, // Cannonical and capitalized name FOO
  468. &cAxes,
  469. &this->dvWish);
  470. ppfeMMInst = NULL; // no instances found yet that match this instances base font
  471. // if GreGetCannonicalName did not find any axes info in the name,
  472. // but the design vector is specified explicitly we use it.
  473. // If however, cAxes from the name is not zero, we ignore
  474. // whatever may be specified in the design vector explicitely.
  475. if (cAxes == 0)
  476. {
  477. if (pelfwWish->elfDesignVector.dvNumAxes)
  478. {
  479. RtlCopyMemory(
  480. &this->dvWish,
  481. &pelfwWish->elfDesignVector,
  482. SIZEOFDV(pelfwWish->elfDesignVector.dvNumAxes)
  483. );
  484. }
  485. else
  486. {
  487. awcBaseName[0] = 0;
  488. }
  489. }
  490. else
  491. {
  492. flMM |= FLMM_DV_FROM_NAME;
  493. }
  494. ulMaxPenalty = ulMaxPenaltySrc;
  495. bIndexFont = bIndexFont_;
  496. ASSERTGDI(pdco && pelfwWish,"Bad call to MAPPER\n");
  497. // to begin with use the lfCharSet value from the logfont, this may
  498. // be latter replaced by the value from [font substitutes]
  499. jMapCharSet = pelfwWish->elfEnumLogfontEx.elfLogFont.lfCharSet;
  500. {
  501. pflAboutMatch = pflAboutMatch_;
  502. *pflAboutMatch = 0;
  503. ppfeBest = (PFE*) NULL;
  504. ulBestTime = ULONG_MAX;
  505. pflSimBest = pflSim_;
  506. pptlSimBest = pptlSim_;
  507. *pflSimBest = 0;
  508. pptlSimBest->x = 1;
  509. pptlSimBest->y = 1;
  510. }
  511. // Is it a display DC or it's moral equivilent?
  512. fl |= pdco->bPrinter() ? 0 : FM_BIT_DISPLAY_DC;
  513. // Set the GM_COMPATIBLE bit.
  514. //
  515. // If we are playing a metafile , world to page transform may be set
  516. // even if the graphics mode is COMPATIBLE, in which case the mapping
  517. // will occur the same way as it would in the advanced mode case
  518. // [bodind].
  519. if
  520. (
  521. (pdco->pdc->iGraphicsMode() == GM_COMPATIBLE) &&
  522. (pdco->pdc->bWorldToPageIdentity() || !pdco->pdc->bUseMetaPtoD())
  523. )
  524. {
  525. fl |= FM_BIT_GM_COMPATIBLE;
  526. }
  527. else
  528. {
  529. // If you are in advanced mode, then ignore the windows
  530. // hack for stock fonts
  531. flOptions &= ~FM_BIT_PIXEL_COORD;
  532. }
  533. if (pelfwWish->elfEnumLogfontEx.elfLogFont.lfQuality == PROOF_QUALITY)
  534. {
  535. fl |= FM_BIT_PROOF_QUALITY;
  536. }
  537. // The windows short circuit mapper doesn't get called
  538. // when an a NULL facename is requested. In this case
  539. // windows goes to the long mapper where a true type font
  540. // will win over a raster font for some reason if the weight
  541. // requested is FW_BOLD or FW_NORMAL. We on the other
  542. // hand will give out a raster font in this case which
  543. // causes CA Super Project to break. We mark this case
  544. // here and fail bFindBitmapFont font when it occurs. [gerritv]
  545. if( ( pelfwWish->elfEnumLogfontEx.elfLogFont.lfWeight == FW_NORMAL ) ||
  546. ( pelfwWish->elfEnumLogfontEx.elfLogFont.lfWeight == FW_BOLD ) )
  547. {
  548. fl |= FM_BIT_WEIGHT_NOT_FAST_BM;
  549. }
  550. // If the requested facename is Ms Shell Dlg then we wont
  551. // worry about charset. This is a hack to make the shell
  552. // work with other versions of Ms Sans Serif
  553. // such as Greek [gerritv]
  554. if( pwszFaceName[0] == U_LATIN_CAPITAL_LETTER_M &&
  555. pwszFaceName[1] == U_LATIN_CAPITAL_LETTER_S &&
  556. pwszFaceName[2] == U_SPACE &&
  557. pwszFaceName[3] == U_LATIN_CAPITAL_LETTER_S &&
  558. pwszFaceName[4] == U_LATIN_CAPITAL_LETTER_H &&
  559. pwszFaceName[5] == U_LATIN_CAPITAL_LETTER_E &&
  560. pwszFaceName[6] == U_LATIN_CAPITAL_LETTER_L &&
  561. pwszFaceName[7] == U_LATIN_CAPITAL_LETTER_L &&
  562. pwszFaceName[8] == U_SPACE &&
  563. pwszFaceName[9] == U_LATIN_CAPITAL_LETTER_D &&
  564. pwszFaceName[10] == U_LATIN_CAPITAL_LETTER_L &&
  565. pwszFaceName[11] == U_LATIN_CAPITAL_LETTER_G &&
  566. pwszFaceName[12] == U_NULL
  567. )
  568. {
  569. fl |= FM_BIT_MS_SHELL_DLG;
  570. }
  571. else if
  572. (
  573. // If the requested facename is 'system' then Windows 3.1
  574. // compatibilty requires that we treat this case specially
  575. pwszFaceName[0] == U_LATIN_CAPITAL_LETTER_S &&
  576. pwszFaceName[1] == U_LATIN_CAPITAL_LETTER_Y &&
  577. pwszFaceName[2] == U_LATIN_CAPITAL_LETTER_S &&
  578. pwszFaceName[3] == U_LATIN_CAPITAL_LETTER_T &&
  579. pwszFaceName[4] == U_LATIN_CAPITAL_LETTER_E &&
  580. pwszFaceName[5] == U_LATIN_CAPITAL_LETTER_M &&
  581. pwszFaceName[6] == U_NULL
  582. )
  583. {
  584. // record the fact that 'SYSTEM' has been requested
  585. fl |= FM_BIT_SYSTEM_REQUEST;
  586. // If the request was for a fixed pitch font, then the
  587. // application really wants 'FIXEDSYS' instead
  588. if ((pelfwWish->elfEnumLogfontEx.elfLogFont.lfPitchAndFamily & 0xF) == FIXED_PITCH)
  589. {
  590. pwszFaceName = gpwszDefFixedSysFaceName;
  591. }
  592. }
  593. else if
  594. (
  595. pwszFaceName[0] == U_LATIN_CAPITAL_LETTER_T &&
  596. pwszFaceName[1] == U_LATIN_CAPITAL_LETTER_M &&
  597. pwszFaceName[2] == U_LATIN_CAPITAL_LETTER_S &&
  598. pwszFaceName[3] == U_SPACE &&
  599. pwszFaceName[4] == U_LATIN_CAPITAL_LETTER_R &&
  600. pwszFaceName[5] == U_LATIN_CAPITAL_LETTER_M &&
  601. pwszFaceName[6] == U_LATIN_CAPITAL_LETTER_N &&
  602. pwszFaceName[7] == U_NULL
  603. )
  604. {
  605. fl |= FM_BIT_TMS_RMN_REQUEST;
  606. }
  607. else if
  608. (
  609. // If the user requests symbol then he can goof up
  610. // the character set. This was put in to allow
  611. // "Spyglass Plot" to work See Bug #18228
  612. pwszFaceName[0] == U_LATIN_CAPITAL_LETTER_S &&
  613. pwszFaceName[1] == U_LATIN_CAPITAL_LETTER_Y &&
  614. pwszFaceName[2] == U_LATIN_CAPITAL_LETTER_M &&
  615. pwszFaceName[3] == U_LATIN_CAPITAL_LETTER_B &&
  616. pwszFaceName[4] == U_LATIN_CAPITAL_LETTER_O &&
  617. pwszFaceName[5] == U_LATIN_CAPITAL_LETTER_L
  618. )
  619. {
  620. fl |= FM_BIT_CHARSET_ACCEPT;
  621. }
  622. // If user requests vertical font. We have to map this logical font to vertical
  623. // Physical font
  624. else if
  625. (
  626. pwszFaceName[0] == U_COMMERCIAL_AT
  627. )
  628. {
  629. fl |= FM_BIT_VERT_FACE_REQUEST;
  630. }
  631. // Copy over the requested sizes. We will transform them to device
  632. // coordinates later if needed.
  633. lDevWishHeight = pelfwWish->elfEnumLogfontEx.elfLogFont.lfHeight;
  634. lDevWishWidth = ABS( pelfwWish->elfEnumLogfontEx.elfLogFont.lfWidth );
  635. {
  636. // Lock the PDEV to get some important information
  637. PDEVOBJ pdo((HDEV)pdco->pdc->ppdev());
  638. ulLogPixelsX = pdo.ulLogPixelsX();
  639. ulLogPixelsY = pdo.ulLogPixelsY();
  640. fl |= (pdo.flTextCaps() & TC_RA_ABLE) ? FM_BIT_DEVICE_RA_ABLE : 0;
  641. fl |= (pdo.flTextCaps() & TC_CR_90) ? FM_BIT_DEVICE_CR_90_ALL : 0;
  642. fl |= (pdo.cFonts()) ? FM_BIT_DEVICE_HAS_FONTS : 0;
  643. fl |= (pdo.ulTechnology() == DT_PLOTTER) ? FM_BIT_DEVICE_PLOTTER : 0;
  644. fl |= (pdo.ulTechnology() == DT_CHARSTREAM) ? FM_BIT_DEVICE_ONLY : 0;
  645. ASSERTGDI(
  646. !((pdo.ulTechnology() == DT_PLOTTER) &&
  647. (pdo.flTextCaps() & TC_RA_ABLE)),
  648. "winsrv!I didn't anticipate a plotter "
  649. "that can handle bitmap fonts\n"
  650. );
  651. if (lDevWishHeight == 0)
  652. {
  653. // "If lfHeight is zero, a reasonable default size is
  654. // substituted." [SDK Vol 2]. Fortunately, the
  655. // device driver is kind enough to suggest a nice
  656. // height (in pixels). We shall put this suggestion
  657. // into lDefaultDeviceHeight
  658. //
  659. // NOTE:
  660. //
  661. // I have assumed that the suggested font height, as
  662. // given in lDefaultDeviceHeight is in pixel units
  663. lDevWishHeight = pdo.pdevinfoNotDynamic()->lfDefaultFont.lfHeight;
  664. // Inform bCalculateWishCell that the height needs no transform.
  665. fl |= FM_BIT_HEIGHT;
  666. }
  667. // At this point the PDEVOBJ passes out of scope and unlocks the PDEV
  668. }
  669. if (lDevWishHeight < 0)
  670. {
  671. fl |= FM_BIT_USE_EMHEIGHT;
  672. lDevWishHeight *= -1;
  673. }
  674. // Cache the wish weight and assign default weight if
  675. // no weight specified. (This way we don't have to
  676. // compute this each time in msCheckFont. And we
  677. // can't modify pelfwWish directly because it is
  678. // declared "const").
  679. lWishWeight = (LONG) pelfwWish->elfEnumLogfontEx.elfLogFont.lfWeight;
  680. if( lWishWeight == FW_DONTCARE )
  681. {
  682. // if FW_DONTCARE then we compute penalities
  683. // slightly differently so we keep track of this
  684. fl |= FM_BIT_FW_DONTCARE ;
  685. lWishWeight = FW_NORMAL;
  686. }
  687. // If the caller did not provide a face name, we provide a default.
  688. if (pwszFaceName[0] == (WCHAR) 0)
  689. {
  690. bGetFaceName();
  691. }
  692. fl |= (flOptions & FM_ALLOWED_OPTIONS) | FM_BIT_STILL_ALIVE;
  693. }
  694. /******************************Member*Function*****************************\
  695. * BOOL bGetFaceName() *
  696. * *
  697. * Gets a face name when there is none *
  698. * *
  699. * Comments *
  700. * *
  701. * you got here because no facename was provided by *
  702. * the user. At this point we shall select the font *
  703. * based upon its height and pitch and family. First *
  704. * we examine the height in device space. If the *
  705. * height has been calculated already then the *
  706. * FM_BIT_HEIGHT bit will have been set and no *
  707. * calculation is needed. Otherwise we must *
  708. * calculate the requested height in pixel unit. We *
  709. * do this by calling off to *
  710. * MAPPER::bCaluculateWishCell(). If this returns *
  711. * with FALSE then the transformation was not *
  712. * appropriate to a bitmap font and we can choose *
  713. * only from TrueType defaults. If *
  714. * MAPPER::bCalculateWishCell returns true then *
  715. * this->lDevWishHeight has been calculated. At that *
  716. * point we must see if it is in the range where the *
  717. * 'small' fonts should be used, otherwise we must *
  718. * default to the TrueType fonts. *
  719. * *
  720. * Returns: *
  721. * The only situation for this function to return FALSE is if the *
  722. * FM_BIT_DISABLE_TT_NAMES bit is set in the MAPPER state. When this *
  723. * bit is set, the function may fail to find a suitable new facename *
  724. * (because the catch-all of the TT core facenames is turned off). *
  725. * *
  726. * History: *
  727. * *
  728. * Thu 2-Jun-1994 16:42:11 by Gerrit van Wingerden [gerritv] *
  729. * Rewrote it to get default facenames from the registry *
  730. * Thu 11-Mar-1993 14:09:49 by Kirk Olynyk [kirko] *
  731. * Wrote it. *
  732. \**************************************************************************/
  733. BOOL MAPPER::bGetFaceName()
  734. {
  735. BYTE Charset;
  736. // if the default charset is specified then use the
  737. // registry entry to determine what it really means
  738. Charset = (jMapCharSet == DEFAULT_CHARSET) ?
  739. MAPPER::DefaultCharset : jMapCharSet;
  740. fl |= FM_BIT_CALLED_BGETFACENAME;
  741. // compute the signature of the desired font
  742. DWORD Signature = (DWORD) Charset;
  743. if(( pelfwWish->elfEnumLogfontEx.elfLogFont.lfPitchAndFamily & (LOGFONT_PITCH_SET) ) == FIXED_PITCH )
  744. {
  745. Signature |= DFS_FIXED_PITCH;
  746. }
  747. if(( pelfwWish->elfEnumLogfontEx.elfLogFont.lfPitchAndFamily & (FF_SET) ) == FF_ROMAN )
  748. {
  749. // the font family is only important for variable pitch fonts
  750. Signature |= DFS_FF_ROMAN;
  751. }
  752. else
  753. if(( pelfwWish->elfEnumLogfontEx.elfLogFont.lfPitchAndFamily & (LOGFONT_PITCH_SET) ) == DEFAULT_PITCH &&
  754. ( pelfwWish->elfEnumLogfontEx.elfLogFont.lfPitchAndFamily & (FF_SET) ) == FF_MODERN )
  755. {
  756. // Windows95 may sometimes chooses Courier instead of Courier New
  757. Signature |= DFS_FIXED_PITCH;
  758. }
  759. if( fl & FM_BIT_VERT_FACE_REQUEST )
  760. {
  761. Signature |= DFS_VERTICAL;
  762. }
  763. // In the case of the ANSI character set, we need to
  764. // consider the possibility of using one of the small
  765. // bitmap fonts. If this search is unsuccessful, we
  766. // will fall into the default case, which chooses an
  767. // appropriate TrueType font from the core set.
  768. //
  769. // The following set of conditions check to see if
  770. // the requested height is so small so as to make
  771. // TrueType fonts look awful. The only way to know
  772. // is to calculate the wish cell by calling to
  773. // bCalculateWishCell().
  774. //
  775. // bCalculateWishCell() will return FALSE if the font
  776. // request is not suitable for a bitmap font. It
  777. // turns out that this condition may be too
  778. // stringent. Win 3.1 compatibility forces us to
  779. // choose "Courier New" as the default small fixed
  780. // pitch font. Thus, it is possible that
  781. // bCalculateWishCell() would reject "Courier New" on
  782. // the false premise that the transform is
  783. // incompatible with all small fonts because they
  784. // should be bitmap fonts. In any case, I will go
  785. // with the follwing conditions until I am proven
  786. // wrong. It is my belief that in such a case,
  787. // "Courier New" will be picked up in the else
  788. // clause.
  789. if
  790. (
  791. ( Charset == ANSI_CHARSET ) &&
  792. (fl & FM_BIT_DEVICE_RA_ABLE ) &&
  793. ((fl & FM_BIT_CELL) ? TRUE : bCalculateWishCell() ) &&
  794. ((fl & FM_BIT_ORIENTATION) ? TRUE : bCalcOrientation() ) &&
  795. (
  796. iOrientationDevice == 0 * ORIENTATION_90_DEG ||
  797. iOrientationDevice == 1 * ORIENTATION_90_DEG ||
  798. iOrientationDevice == 2 * ORIENTATION_90_DEG ||
  799. iOrientationDevice == 3 * ORIENTATION_90_DEG
  800. )
  801. )
  802. {
  803. // Note: If we break out of this switch, we will fall into
  804. // the TT case below. We are writing it this way so that
  805. // we can bail out of the "small font" case and into the TT
  806. // case if we have to.
  807. PWSZ pwszBitmap;
  808. pwszBitmap = FindFaceName( Signature | DFS_BITMAP_A );
  809. // Try the first choice
  810. if ( bFindBitmapFont(pwszBitmap) )
  811. {
  812. pwszFaceName = pwszBitmap;
  813. #if DBG
  814. if (gflFontDebug & DEBUG_MAPPER)
  815. {
  816. DbgPrint("MAPPER::bGetFaceName() --> \"%ws\"\n", pwszFaceName);
  817. }
  818. #endif
  819. return( TRUE );
  820. }
  821. // The first choice doesn't cut it, try the second choice
  822. pwszBitmap = FindFaceName( Signature | DFS_BITMAP_B );
  823. if ( bFindBitmapFont(pwszBitmap) )
  824. {
  825. pwszFaceName = pwszBitmap;
  826. #if DBG
  827. if (gflFontDebug & DEBUG_MAPPER)
  828. {
  829. DbgPrint("MAPPER::bGetFaceName() --> \"%ws\"\n", pwszFaceName);
  830. }
  831. #endif
  832. return( TRUE );
  833. }
  834. // If we get to here, we couldn't find a suitable raster
  835. // small font. If the FM_BIT_DISABLE_TT_NAMES flag is
  836. // set, return error. Otherwise, fall into the TT facename
  837. // substitution code below in the default case.
  838. if (fl & FM_BIT_DISABLE_TT_NAMES)
  839. {
  840. #if DBG
  841. if (gflFontDebug & DEBUG_MAPPER)
  842. {
  843. DbgPrint("MAPPER::bGetFaceName() failed\n");
  844. }
  845. #endif
  846. return( FALSE );
  847. }
  848. }
  849. // find the face name
  850. PWSZ pwszTemp = FindFaceName( Signature );
  851. if (*pwszTemp || !(fl & FM_BIT_FACENAME_MATCHED))
  852. {
  853. // If a new name was found then it should be used. On the
  854. // other hand, if a new name was not found then we must check
  855. // to see if the face name as specified in the LOGFONT was
  856. // ever found in the font tables. If the original face name
  857. // was found then we should use it again, but this time
  858. // allow character set mismatches. If the original name was
  859. // not found in the font table then return a string of zero
  860. // length causing the font mapper to fall into the emergency
  861. // procedure.
  862. pwszFaceName = pwszTemp;
  863. }
  864. #if DBG
  865. if (gflFontDebug & DEBUG_MAPPER)
  866. {
  867. DbgPrint("MAPPER::bGetFaceName() --> \"%ws\"\n", pwszFaceName);
  868. }
  869. #endif
  870. return( TRUE );
  871. }
  872. /******************************Public*Routine******************************\
  873. * BOOL MAPPER::bFindBitmapFont *
  874. * *
  875. * The purpose of this function is to determine whether a bitmap font *
  876. * with the given facename and EXACTLY the wish height exists. The *
  877. * purpose is to support Windows 3.1 compatible "small font" behavior. *
  878. * The Win 3.1 short circuit mapper (written by DavidW) forces mapping to *
  879. * the either of the standard small fonts ("Small fonts" and "MS Serif") *
  880. * only if the exact height requested exists. *
  881. * *
  882. * Returns: *
  883. * TRUE if font found, otherwise FALSE. *
  884. * *
  885. * History: *
  886. * 21-Apr-1993 -by- Gilman Wong [gilmanw] *
  887. * Wrote it. *
  888. \**************************************************************************/
  889. BOOL MAPPER::bFindBitmapFont(PWSZ pwszFindFace)
  890. {
  891. PFELINK *ppfel;
  892. HASHBUCKET *pbkt;
  893. FONTHASHTYPE fht;
  894. BOOL bRet = FALSE;
  895. // we need to fail at certain weights to insure Win 3.1 compatibility
  896. if( fl & FM_BIT_WEIGHT_NOT_FAST_BM )
  897. {
  898. return( FALSE );
  899. }
  900. // We are only going to check the family table.
  901. // This is a very specialized search, so if its
  902. // not there it shouldn't be anywhere!
  903. PUBLIC_PFTOBJ pfto;
  904. FHOBJ fho(&pfto.pPFT->pfhFamily);
  905. if (!fho.bValid())
  906. {
  907. return( bRet );
  908. }
  909. fht = fho.fht();
  910. pbkt = fho.pbktSearch(pwszFindFace,(UINT*)NULL);
  911. if (!pbkt)
  912. {
  913. FONTSUB* pfsub = pfsubAlternateFacename(pwszFindFace);
  914. // only check "old style substitutions"
  915. if (pfsub && (pfsub->fcsAltFace.fjFlags & FJ_NOTSPECIFIED))
  916. {
  917. pbkt = fho.pbktSearch((PWSZ)pfsub->fcsAltFace.awch,(UINT*)NULL);
  918. }
  919. }
  920. if (!pbkt)
  921. {
  922. return( bRet );
  923. }
  924. // Scan the PFE list for an exact height match.
  925. for (ppfel = pbkt->ppfelEnumHead; ppfel; ppfel = ppfel->ppfelNext)
  926. {
  927. PFEOBJ pfeo(ppfel->ppfe);
  928. IFIOBJ ifio(pfeo.pifi());
  929. if (ifio.bBitmap())
  930. {
  931. LONG lH;
  932. lH = (fl & FM_BIT_USE_EMHEIGHT) ?
  933. (LONG) ifio.fwdUnitsPerEm() : ifio.lfHeight();
  934. if
  935. (
  936. lDevWishHeight == lH ||
  937. ( lDevWishHeight == WIN31_SMALL_WISH_HEIGHT
  938. && lH == WIN31_SMALL_FONT_HEIGHT
  939. )
  940. )
  941. {
  942. if (lDevWishWidth == 0 || lDevWishWidth == ifio.lfWidth())
  943. {
  944. return( TRUE );
  945. }
  946. }
  947. }
  948. }
  949. return( bRet );
  950. }
  951. /******************************Member*Function*****************************\
  952. * BOOL MAPPER::bCalcOrientation() *
  953. * *
  954. * History: *
  955. * Tue 23-Mar-1993 22:24:19 by Kirk Olynyk [kirko] *
  956. * Wrote it. *
  957. \**************************************************************************/
  958. BOOL MAPPER::bCalcOrientation()
  959. {
  960. INT s11,s12,s21,s22;
  961. if (fl & FM_BIT_GM_COMPATIBLE)
  962. {
  963. // Taken from bGetNtoD_Win31()
  964. iOrientationDevice = pelfwWish->elfEnumLogfontEx.elfLogFont.lfEscapement;
  965. if (iOrientationDevice != 0)
  966. {
  967. if ( (pdco->pdc->bWorldToPageIdentity()) &&
  968. (!(pdco->pdc->bPageToDeviceScaleIdentity())) &&
  969. (pdco->pdc->efM11().lSignum() !=
  970. pdco->pdc->efM22().lSignum()) )
  971. {
  972. iOrientationDevice = -iOrientationDevice;
  973. }
  974. }
  975. fl |= FM_BIT_ORIENTATION;
  976. return( TRUE );
  977. }
  978. else if (pdco->pdc->bWorldToDeviceIdentity() || (fl & FM_BIT_PIXEL_COORD))
  979. {
  980. iOrientationDevice = pelfwWish->elfEnumLogfontEx.elfLogFont.lfOrientation;
  981. fl |= FM_BIT_ORIENTATION;
  982. return( TRUE );
  983. }
  984. EXFORMOBJ xo(*pdco, WORLD_TO_DEVICE);
  985. s11 = (INT) xo.efM11().lSignum();
  986. s12 = (INT) xo.efM12().lSignum();
  987. s21 = (INT) xo.efM21().lSignum();
  988. s22 = (INT) xo.efM22().lSignum();
  989. if (pdco->pdc->bYisUp())
  990. {
  991. s21 = -s21;
  992. s22 = -s22;
  993. }
  994. if (pelfwWish->elfEnumLogfontEx.elfLogFont.lfOrientation % 900)
  995. {
  996. return( FALSE );
  997. }
  998. if
  999. (
  1000. (s11 - s22) // Signs on diagonal must match.
  1001. | (s12 + s21) // Signs off diagonal must be opposite.
  1002. | ((s11^s12^1)&1) // Exactly one diagonal must be zero.
  1003. )
  1004. {
  1005. return( FALSE );
  1006. }
  1007. iOrientationDevice =
  1008. pelfwWish->elfEnumLogfontEx.elfLogFont.lfOrientation
  1009. + (s12 & 900)
  1010. + (s11 & 1800)
  1011. + (s21 & 2700);
  1012. if (iOrientationDevice >= 3600)
  1013. iOrientationDevice -= 3600;
  1014. fl |= FM_BIT_ORIENTATION;
  1015. return( TRUE );
  1016. }
  1017. /******************************Member*Function*****************************\
  1018. * MAPPER::bCalculateWishCell *
  1019. * *
  1020. * Calculates either the 'ascent' vector or 'width' vector of the font *
  1021. * in device space units. Then the equivalent 'height' and/or width *
  1022. * is filled in the the MAPPER::elfWishDevice fields. The height and width *
  1023. * are defined to be positive. *
  1024. * *
  1025. * Also computes the wished for orientation in device coordinates. *
  1026. * This is needed whenever the cell is needed! *
  1027. * *
  1028. * We use three flags which have the following meaning when set, and should *
  1029. * be used for no other purpose. *
  1030. * *
  1031. * FM_BIT_CELL Informs the world that bCalculateWishCell has *
  1032. * been called in the past, and successfully *
  1033. * transformed the height, width, and orientation *
  1034. * to device space. (OUTPUT) *
  1035. * *
  1036. * FM_BIT_BAD_WISH_CELL A flag internal to this function to tell it *
  1037. * that it has been called already and the *
  1038. * calculation failed. (INTERNAL) *
  1039. * *
  1040. * FM_BIT_HEIGHT Informs this function that the height is *
  1041. * already in device space. (INPUT) *
  1042. * *
  1043. * History: *
  1044. * Fri 18-Dec-1992 02:51:39 -by- Charles Whitmer [chuckwh] *
  1045. * Rewrote. Utilizing the assumption that it only gets called for raster *
  1046. * fonts, I was able to delete hundreds of lines of complex code! *
  1047. * *
  1048. * Mon 30-Dec-1991 14:35:22 by Kirk Olynyk [kirko] *
  1049. * Wrote it. *
  1050. \**************************************************************************/
  1051. LONG lNormAngle(LONG);
  1052. BOOL MAPPER::bCalculateWishCell()
  1053. {
  1054. INT s11,s12,s21,s22;
  1055. LONG lAngle = lNormAngle(pelfwWish->elfEnumLogfontEx.elfLogFont.lfOrientation);
  1056. // If we've failed here before, it's no better now!
  1057. if (fl & FM_BIT_BAD_WISH_CELL)
  1058. {
  1059. return( FALSE );
  1060. }
  1061. // Make sure we haven't been called before!
  1062. ASSERTGDI
  1063. (
  1064. (fl & FM_BIT_CELL) == 0,
  1065. "gdi!MAPPER::bCalculateWishCell: Useless call!\n"
  1066. );
  1067. // Handle the trivial case.
  1068. if (pdco->pdc->bWorldToDeviceIdentity() || (fl & FM_BIT_PIXEL_COORD))
  1069. {
  1070. iOrientationDevice = lAngle;
  1071. fl |= (FM_BIT_CELL | FM_BIT_HEIGHT | FM_BIT_WIDTH);
  1072. return( TRUE );
  1073. }
  1074. // Locate our transform and examine the matrix.
  1075. EXFORMOBJ xo(*pdco, WORLD_TO_DEVICE);
  1076. s11 = (INT) xo.efM11().lSignum();
  1077. s12 = (INT) xo.efM12().lSignum();
  1078. s21 = (INT) xo.efM21().lSignum();
  1079. s22 = (INT) xo.efM22().lSignum();
  1080. // Change to an equivalent transform where the y axis goes down.
  1081. // We remove a sign change from the matrix components that hit y.
  1082. if (pdco->pdc->bYisUp())
  1083. {
  1084. s21 = -s21;
  1085. s22 = -s22;
  1086. }
  1087. // If we are in GM_ADVANCED mode, make sure the orientation and transform
  1088. // are consistent with a bitmap font. In GM_COMPATIBLE mode, just ignore
  1089. // it all. Note that iOrientationDevice remains undefined in GM_COMPATIBLE
  1090. // mode.
  1091. if (!(fl & FM_BIT_GM_COMPATIBLE) && !(fl & FM_BIT_ORIENTATION))
  1092. {
  1093. // Reject random orientations. Even under simple
  1094. // scaling transforms, they don't transform well.
  1095. // (Assuming we're mapping to a raster font.)
  1096. if (lAngle % 900)
  1097. {
  1098. #if DBG
  1099. if (gflFontDebug & DEBUG_MAPPER)
  1100. {
  1101. DbgPrint(
  1102. "\tMAPPER::bCalculateWishCell detected a bad orientation\n");
  1103. }
  1104. #endif
  1105. fl |= FM_BIT_BAD_WISH_CELL;
  1106. return( FALSE );
  1107. }
  1108. // Examine the transform to see if it's a simple multiple of 90
  1109. // degrees rotation and perhaps some scaling.
  1110. // Check for parity flipping transforms which are not allowed.
  1111. // (That would require reflecting a bitmap, something we don't
  1112. // consider likely.) Also look for complex transforms.
  1113. // If any of the terms we OR together are non-zero,
  1114. // it's a bad transform.
  1115. if (
  1116. (s11 - s22) // Signs on diagonal must match.
  1117. | (s12 + s21) // Signs off diagonal must be opposite.
  1118. | ((s11^s12^1)&1) // Exactly one diagonal must be zero.
  1119. )
  1120. {
  1121. #if DBG
  1122. if (gflFontDebug & DEBUG_MAPPER)
  1123. {
  1124. DbgPrint("\tMAPPER::bCalculateWishCell "
  1125. "detected a bad trasform -- returning FALSE");
  1126. DbgPrint("{%d,%d,%d,%d}\n",s11,s12,s21,s22);
  1127. }
  1128. #endif
  1129. fl |= FM_BIT_BAD_WISH_CELL;
  1130. return( FALSE );
  1131. }
  1132. // Since we've normalized to a space where (0 -1) represents
  1133. // a vector with a 90 degree orientation (like MM_TEXT) note
  1134. // that the matrix that rotates us by positive 90 degrees is:
  1135. //
  1136. // [ 0 -1 ]
  1137. // (0 -1) [ ] = (-1 0)
  1138. // [ 1 0 ]
  1139. //
  1140. // I.e. the one with M < 0. Knowing this, the rest is easy!
  1141. // 12
  1142. iOrientationDevice =
  1143. lAngle
  1144. + (s12 & 900)
  1145. + (s11 & 1800)
  1146. + (s21 & 2700);
  1147. // Note that only the single 0xFFFFFFFF term contributes above.
  1148. if (iOrientationDevice >= 3600)
  1149. iOrientationDevice -= 3600;
  1150. fl |= FM_BIT_ORIENTATION;
  1151. }
  1152. // Transform the height to device coordinates.
  1153. if (!(fl & FM_BIT_HEIGHT))
  1154. {
  1155. // lDevWishHeight = lCvt(s22 ? xo.efM22() : xo.efM21(),lDevWishHeight);
  1156. if (s22)
  1157. lDevWishHeight = lCvt(xo.efM22(),lDevWishHeight);
  1158. else
  1159. lDevWishHeight = lCvt(xo.efM21(),lDevWishHeight);
  1160. if (lDevWishHeight < 0)
  1161. lDevWishHeight = -lDevWishHeight;
  1162. lDevWishHeight = LONG_FLOOR_OF_FIX(lDevWishHeight + FIX_HALF);
  1163. }
  1164. // Transform the width to device coordinates.
  1165. if (pelfwWish->elfEnumLogfontEx.elfLogFont.lfWidth && !(fl & FM_BIT_WIDTH))
  1166. {
  1167. // lDevWishWidth = lCvt(s11 ? xo.efM11() : xo.efM12(),lDevWishWidth);
  1168. if (s11)
  1169. lDevWishWidth = lCvt(xo.efM11(),lDevWishWidth);
  1170. else
  1171. lDevWishWidth = lCvt(xo.efM12(),lDevWishWidth);
  1172. if (lDevWishWidth < 0)
  1173. lDevWishWidth = -lDevWishWidth;
  1174. lDevWishWidth = LONG_FLOOR_OF_FIX(lDevWishWidth + FIX_HALF);
  1175. }
  1176. fl |= (FM_BIT_CELL | FM_BIT_HEIGHT | FM_BIT_WIDTH);
  1177. return( TRUE );
  1178. }
  1179. /******************************Member*Function*****************************\
  1180. * MAPPER::bNearMatch *
  1181. * *
  1182. * History: *
  1183. * 24-Sept-1196 -by- Xudong Wu [TesieW] *
  1184. * Add checking on Private/Embedded fonts *
  1185. * Tue 28-Dec-1993 09:39:24 by Kirk Olynyk [kirko] *
  1186. * Changed the way msCheckFamily works for the case when the physical *
  1187. * font has FF_DONTCARE for the family *
  1188. * Fri 18-Dec-1992 23:19:09 -by- Charles Whitmer [chuckwh] *
  1189. * Simplified a lot of stuff and then pulled all the routines in line. *
  1190. * We were spending an extra 12 instructions per part checked by having *
  1191. * them out of line, which adds up to about half the time in this routine! *
  1192. * Tue 10-Dec-1991 11:33:28 by Kirk Olynyk [kirko] *
  1193. * Wrote it. *
  1194. \**************************************************************************/
  1195. extern PW32PROCESS gpidSpool; // global
  1196. int MAPPER::bNearMatch(PFEOBJ &pfeo, BYTE *pjCharSet, BOOL bEmergency)
  1197. {
  1198. int iRet = FALSE; // return value
  1199. ULONG ul; // Temp variable.
  1200. BYTE jAsk, jHav;
  1201. PFE *ppfeNew = pfeo.ppfeGet();
  1202. // Clear the per-font status bits
  1203. fl &= ~(FM_BIT_NO_MAX_HEIGHT | FM_BIT_SYSTEM_FONT);
  1204. if (pfeo.ppfeGet() == gppfeMapperDefault)
  1205. {
  1206. fl |= FM_BIT_SYSTEM_FONT;
  1207. }
  1208. ifio.vSet(pfeo.pifi());
  1209. if (pfeo.bDead())
  1210. {
  1211. // The font is in a "ready to die" state. That is, the engine is
  1212. // ready to delete the font, but has had to delay it until all
  1213. // outstanding references (via RFONTs) has disappeared. Meanwhile,
  1214. // we must not allow enumeration or mapping to this font.
  1215. #if DBG
  1216. if (gflFontDebug & DEBUG_MAPPER)
  1217. {
  1218. DbgPrint(
  1219. "msCheckFont is returning FM_REJECT because pfeo.bDead() is true\n");
  1220. }
  1221. #endif
  1222. ulPenaltyTotal = FM_REJECT;
  1223. return( iRet );
  1224. }
  1225. // private pfe NOT added by the current process.
  1226. // spooler has the right to access all the fonts
  1227. if (!pfeo.bEmbPvtOk() && (gpidSpool != (PW32PROCESS)W32GetCurrentProcess()))
  1228. {
  1229. ulPenaltyTotal = FM_REJECT;
  1230. return( iRet );
  1231. }
  1232. // Skip the PFE_UFIMATCH fonts since they are added to the public font table temporarily
  1233. // for remote printing. These PFEs should be mapped only by bFoundForcedMatch() calls.
  1234. if (pfeo.bUFIMatchOnly())
  1235. {
  1236. ulPenaltyTotal = FM_REJECT;
  1237. return( iRet );
  1238. }
  1239. // spooler has the right to access all the fonts
  1240. if (pfeo.bPrivate() && (gpidSpool != (PW32PROCESS)W32GetCurrentProcess()))
  1241. {
  1242. // The font is embedded then it can only be seen if the call is
  1243. // Win 3.1 compatible (i.e. called by ppfeGetAMatch), the
  1244. // embedded bit is set in the caller's logical font, and the clients
  1245. // PID or TID matches that embeded in the *.fot file.
  1246. if (pfeo.bEmbedOk())
  1247. {
  1248. if (!(pelfwWish->elfEnumLogfontEx.elfLogFont.lfClipPrecision & CLIP_EMBEDDED))
  1249. {
  1250. #if DBG
  1251. if (gflFontDebug & DEBUG_MAPPER)
  1252. {
  1253. DbgPrint("msCheckFont is returning FM_REJECT\n");
  1254. DbgPrint("because the font is embedded\n\n");
  1255. }
  1256. #endif
  1257. ulPenaltyTotal = FM_REJECT;
  1258. return( iRet );
  1259. }
  1260. }
  1261. }
  1262. ulPenaltyTotal = 0;
  1263. // Assume be default that the font that is chosen will no have
  1264. // any bold or italic simulations
  1265. flSimulations = 0;
  1266. // Assume by default that if we happen to choose a bitmap font, there
  1267. // will be no streching in either the height-direction or width-direction
  1268. ptlSimulations.x = 1;
  1269. ptlSimulations.y = 1;
  1270. // At this point, the code used to have the following nice structure. For
  1271. // performance reasons, I pulled the code of each of these routines inline.
  1272. // Even so, the functionality of each of the following sections should
  1273. // remain clean and distinct. [chuckwh]
  1274. //
  1275. // if
  1276. // (
  1277. // (msCheckPitchAndFamily()) == MSTAT_NEAR &&
  1278. // (msCheckHeight() ) == MSTAT_NEAR &&
  1279. // (msCheckAspect() ) == MSTAT_NEAR &&
  1280. // (msCheckItalic() ) == MSTAT_NEAR &&
  1281. // (msCheckWeight() ) == MSTAT_NEAR &&
  1282. // (msCheckOutPrecision() ) == MSTAT_NEAR &&
  1283. // (msCheckWidth() ) == MSTAT_NEAR &&
  1284. // (msCheckOrientation(pfeo.iOrientation())) == MSTAT_NEAR
  1285. // )
  1286. // {
  1287. // return( MSTAT_NEAR );
  1288. // }
  1289. // return( MSTAT_FAR );
  1290. MSBREAKPOINT("msCheckForMMFont");
  1291. if ((fl & FM_BIT_BASENAME_MATCHED) && !(pfeo.pifi()->flInfo & FM_INFO_TECH_MM))
  1292. {
  1293. CHECKPRINT("CheckForMMFont", FM_REJECT );
  1294. ulPenaltyTotal = FM_REJECT;
  1295. return( iRet );
  1296. }
  1297. // if glyph index font is required, but this font does not support it, reject it
  1298. MSBREAKPOINT("msCheckForGlyphIndexFont");
  1299. if (bIndexFont && !ppfeNew->pgiset)
  1300. {
  1301. CHECKPRINT("CheckForGlyphIndexFont", FM_REJECT );
  1302. ulPenaltyTotal = FM_REJECT;
  1303. return( iRet );
  1304. }
  1305. MSBREAKPOINT("msCheckPitch");
  1306. {
  1307. jHav = (BYTE) (ifio.lfPitchAndFamily() & LOGFONT_PITCH_SET);
  1308. jAsk =
  1309. (BYTE) (pelfwWish->elfEnumLogfontEx.elfLogFont.lfPitchAndFamily & LOGFONT_PITCH_SET);
  1310. ul = 0;
  1311. if (jAsk != DEFAULT_PITCH)
  1312. {
  1313. if (jAsk == FIXED_PITCH)
  1314. {
  1315. if (jHav & VARIABLE_PITCH)
  1316. {
  1317. ul = FM_WEIGHT_PITCHFIXED;
  1318. }
  1319. }
  1320. else if (!(jHav & VARIABLE_PITCH))
  1321. {
  1322. ul = FM_WEIGHT_PITCHVARIABLE;
  1323. }
  1324. }
  1325. else if (jHav & FIXED_PITCH)
  1326. {
  1327. ul = FM_WEIGHT_DEFAULTPITCHFIXED;
  1328. }
  1329. if (ul)
  1330. {
  1331. CHECKPRINT("Pitch",ul);
  1332. ulPenaltyTotal += ul;
  1333. if (bNoMatch(ppfeNew))
  1334. {
  1335. return( iRet );
  1336. }
  1337. }
  1338. }
  1339. MSBREAKPOINT("msCheckFamily");
  1340. {
  1341. jHav = (BYTE)(ifio.lfPitchAndFamily() & FF_SET);
  1342. jAsk = (BYTE)(pelfwWish->elfEnumLogfontEx.elfLogFont.lfPitchAndFamily & FF_SET);
  1343. if (jAsk == FF_DONTCARE)
  1344. {
  1345. if (jMapCharSet == SYMBOL_CHARSET)
  1346. {
  1347. // If the application asked for the symbol character set
  1348. // and did not specify a family preference
  1349. // then we should arrange it so that the choice of fonts
  1350. // is family neutral so I set the asked for family
  1351. // to be equal to the family of the current candidate
  1352. // font.
  1353. jAsk = (BYTE)(ifio.lfPitchAndFamily() & FF_SET);
  1354. }
  1355. else
  1356. {
  1357. // If the application did not specify a family preference
  1358. // then we shall pick one for it. Normally we choose
  1359. // Swiss except for the case where the application
  1360. // asked for "Tms Rmn" where we ask for a Roman (serifed)
  1361. // font.
  1362. if (jHav != FF_DONTCARE)
  1363. {
  1364. // I have decide to excecute this family proxy
  1365. // request only in the case where the font doesn't
  1366. // have a family of FF_DONTCARE. The reason for this
  1367. // is interesting. Consider the case where a font,
  1368. // for what ever reason, chooses to have FF_DONTCARE
  1369. // for the family. Of course this is a bug but what
  1370. // can we do. Anyway, an application enumerates the
  1371. // fonts and gets back a logical font with
  1372. // FF_DONTCARE for the family. Then suppose the
  1373. // application takes that font and uses it to create
  1374. // a font of its own (this is what the ChooseFont
  1375. // common dialog box does all the time). Then we
  1376. // have the situation, where the logical font and the
  1377. // intended font both have FF_DONTCARE for their
  1378. // chosen family. If the statement below where
  1379. // excecuted, the family request would be changed to
  1380. // something that does not match the physical font.
  1381. // Trouble will occur if there is another font around
  1382. // with the same face name or family name. You may
  1383. // not get the font you wanted because we have
  1384. // erroneously added a family mismatch penalty. (See
  1385. // Bug #4912)
  1386. //
  1387. // Tue 28-Dec-1993 09:38:29 by Kirk Olynyk [kirko]
  1388. jAsk = (BYTE)((fl & FM_BIT_TMS_RMN_REQUEST) ? FF_ROMAN : FF_SWISS);
  1389. }
  1390. }
  1391. }
  1392. if (jAsk != jHav)
  1393. {
  1394. ul = 0;
  1395. if (jHav)
  1396. {
  1397. if
  1398. (
  1399. // Win 3.1 dogma -- Are jAsk and jHav on opposite sides of
  1400. // the FF_MODERN barrier? if so, a familiy match
  1401. // isn't likely
  1402. ((jAsk <= FF_MODERN) && (jHav > FF_MODERN)) ||
  1403. ((jAsk > FF_MODERN) && (jHav <= FF_MODERN))
  1404. )
  1405. {
  1406. ul += FM_WEIGHT_FAMILYUNLIKELY;
  1407. }
  1408. ul += FM_WEIGHT_FAMILY;
  1409. }
  1410. else
  1411. {
  1412. ul = FM_WEIGHT_FAMILYUNKNOWN;
  1413. }
  1414. if (ul)
  1415. {
  1416. CHECKPRINT("Family",ul);
  1417. ulPenaltyTotal += ul;
  1418. if (bNoMatch(ppfeNew))
  1419. {
  1420. return( iRet );
  1421. }
  1422. }
  1423. }
  1424. }
  1425. MSBREAKPOINT("msCheckCharSet");
  1426. {
  1427. if( (jMapCharSet != DEFAULT_CHARSET) &&
  1428. (!( fl & FM_BIT_MS_SHELL_DLG ) ))
  1429. {
  1430. *pjCharSet = jMapCharset(jMapCharSet, pfeo);
  1431. if (jMapCharSet != *pjCharSet)
  1432. {
  1433. if( fl & FM_BIT_CHARSET_ACCEPT )
  1434. {
  1435. CHECKPRINT("CharSet",FM_WEIGHT_CHARSET);
  1436. ulPenaltyTotal += FM_WEIGHT_CHARSET;
  1437. if (bNoMatch(ppfeNew))
  1438. {
  1439. return( iRet );
  1440. }
  1441. }
  1442. else
  1443. {
  1444. CHECKPRINT("CharSet", FM_REJECT );
  1445. ulPenaltyTotal = FM_REJECT;
  1446. return( iRet );
  1447. }
  1448. }
  1449. }
  1450. else
  1451. {
  1452. // we still want to call jMapCharset, except, we do not want to give a
  1453. // big weight to the charset, the app does not care. We still want to give
  1454. // a small preference to the one that matches MAPPER::DefaultCharSet
  1455. *pjCharSet = jMapCharset(jMapCharSet, pfeo);
  1456. if ((jMapCharSet == DEFAULT_CHARSET) && !(fl & FM_BIT_MS_SHELL_DLG))
  1457. {
  1458. if (MAPPER::DefaultCharset != *pjCharSet)
  1459. {
  1460. CHECKPRINT("CharSet",1);
  1461. ulPenaltyTotal += 2;
  1462. if (bNoMatch(ppfeNew))
  1463. {
  1464. return( iRet );
  1465. }
  1466. }
  1467. }
  1468. }
  1469. }
  1470. MSBREAKPOINT("msCheckFamilyName");
  1471. if (bEmergency)
  1472. {
  1473. // we only check facename in case we are in vEmergency() loop,
  1474. // else, face name match is guaranteed.
  1475. BOOL bAliasMatch;
  1476. if (!pfeo.bCheckFamilyName(pwszFaceName,0, &bAliasMatch))
  1477. {
  1478. // no facename match, add penalty
  1479. CHECKPRINT("FamilyName",FM_WEIGHT_FACENAME);
  1480. ulPenaltyTotal += FM_WEIGHT_FACENAME;
  1481. }
  1482. else
  1483. {
  1484. if (bAliasMatch)
  1485. {
  1486. // add a small penalty for matching alias, not the real name
  1487. CHECKPRINT("Alias Match",FM_WEIGHT_DEVICE_ALIAS);
  1488. ulPenaltyTotal += FM_WEIGHT_DEVICE_ALIAS;
  1489. }
  1490. }
  1491. if (bNoMatch(ppfeNew))
  1492. {
  1493. return( iRet );
  1494. }
  1495. }
  1496. MSBREAKPOINT("msCheckVertAttr");
  1497. {
  1498. // If requested font is vertlcal face font, We have to map it to vertical
  1499. // face font
  1500. if ( fl & FM_BIT_VERT_FACE_REQUEST )
  1501. {
  1502. if ( *ifio.pwszFamilyName() != U_COMMERCIAL_AT )
  1503. {
  1504. CHECKPRINT("VertAttr",FM_REJECT);
  1505. ulPenaltyTotal = FM_REJECT;
  1506. return(iRet);
  1507. }
  1508. }
  1509. else
  1510. if (*ifio.pwszFamilyName() == U_COMMERCIAL_AT)
  1511. {
  1512. // if the user hasn't requested a @face font then don't map to one
  1513. CHECKPRINT("VertAttr",FM_REJECT);
  1514. ulPenaltyTotal = FM_REJECT;
  1515. return(iRet);
  1516. }
  1517. }
  1518. MSBREAKPOINT("msCheckHeight");
  1519. if (!ifio.bContinuousScaling())
  1520. {
  1521. if (!(fl & FM_BIT_CELL) && !bCalculateWishCell())
  1522. {
  1523. // The transform is incompatible with a raster font.
  1524. ulPenaltyTotal = FM_REJECT;
  1525. #if DBG
  1526. if (gflFontDebug & DEBUG_MAPPER)
  1527. {
  1528. if (fl & FM_BIT_BAD_WISH_CELL)
  1529. {
  1530. DbgPrint("\t\tFM_BIT_BAD_WISH_CELL\n");
  1531. }
  1532. }
  1533. #endif
  1534. CHECKPRINT("Height", FM_REJECT);
  1535. return( iRet );
  1536. }
  1537. // Raster fonts shall be used only in the case when
  1538. // the transformation from World to Device
  1539. // coordinates is a simple scale, and the orientation
  1540. // angle is along either the x or y-axis.
  1541. //
  1542. // The physical height to compare against is either
  1543. // the cell height or em-height depending upon the
  1544. // sign of the LOGFONT::lfHeight field passed in by
  1545. // the application
  1546. //
  1547. // differences of over a pixel are the only ones that
  1548. // count so, we count pixels instead of angstroms
  1549. //
  1550. // Don't reject for the height penalty if the
  1551. // requested char set and physical font's char set
  1552. // are both symbol, or if the requested font is the
  1553. // system font since the system font is special.
  1554. LONG
  1555. lDevHeight =
  1556. (fl & FM_BIT_USE_EMHEIGHT) ? ifio.fwdUnitsPerEm() : ifio.lfHeight();
  1557. if (
  1558. lDevHeight < lDevWishHeight &&
  1559. ifio.bIntegralScaling() &&
  1560. !(fl & FM_BIT_PROOF_QUALITY) &&
  1561. WIN31_BITMAP_HEIGHT_SCALING_CRITERIA(lDevWishHeight,lDevHeight)
  1562. )
  1563. {
  1564. LONG lTemp = WIN31_BITMAP_HEIGHT_SCALING(lDevWishHeight,lDevHeight);
  1565. ptlSimulations.y = min(WIN31_BITMAP_HEIGHT_SCALING_MAX,lTemp);
  1566. }
  1567. else
  1568. {
  1569. ptlSimulations.y = 1;
  1570. }
  1571. ul = 0;
  1572. if (ptlSimulations.y > 1)
  1573. {
  1574. // Check to see if the height scaling is too gross according to
  1575. // the Win31 criteria
  1576. if (!(fl & FM_BIT_NO_MAX_HEIGHT))
  1577. {
  1578. if (WIN31_BITMAP_HEIGHT_SCALING_BAD(ptlSimulations.y,lDevHeight))
  1579. {
  1580. #if DBG
  1581. // needed by CHECKPRINT macro
  1582. ulPenaltyTotal = FM_REJECT;
  1583. #endif
  1584. CHECKPRINT("Height (scaling too big)",FM_REJECT);
  1585. return( iRet );
  1586. }
  1587. }
  1588. lDevHeight *= ptlSimulations.y;
  1589. ul += (ULONG) ptlSimulations.y * FM_WEIGHT_INT_SIZE_SYNTH;
  1590. // This next statement is found in the Win 3.1 code. Ours is not to
  1591. // question why.
  1592. ul |= (ULONG) (ptlSimulations.y-1)*WIN31_BITMAP_WIDTH_SCALING_MAX;
  1593. }
  1594. if (lDevWishHeight >= lDevHeight)
  1595. {
  1596. ul += FM_WEIGHT_HEIGHT * ((ULONG) (lDevWishHeight - lDevHeight));
  1597. }
  1598. else
  1599. {
  1600. // Under Win 3.1 the only non-scalable device fonts
  1601. // we run into are those from the printer UniDriver.
  1602. // Unfortunately, this driver has a very different
  1603. // idea of how font mapping is done. It allows the
  1604. // realized font to be one pel larger than the
  1605. // request with no penalty, but otherwise the penalty
  1606. // is fairly prohibitive. I am not simulating that
  1607. // exactly here (since it would be impossible), but I
  1608. // do allow the off by one miss, and then impose a 20
  1609. // pel penalty. I believe this will reduce by
  1610. // another order of magnitude the number of font
  1611. // mapping differences that remain. [chuckwh]
  1612. // 6/12/93.
  1613. if
  1614. (
  1615. (fl & (FM_BIT_DEVICE_FONT+FM_BIT_GM_COMPATIBLE))
  1616. == (FM_BIT_DEVICE_FONT+FM_BIT_GM_COMPATIBLE)
  1617. )
  1618. {
  1619. if (lDevHeight - lDevWishHeight > 1)
  1620. {
  1621. ul += FM_WEIGHT_HEIGHT *
  1622. (
  1623. (ULONG)
  1624. (
  1625. lDevHeight
  1626. - lDevWishHeight
  1627. + 5 * FM_PHYS_FONT_TOO_LARGE_FACTOR
  1628. )
  1629. );
  1630. }
  1631. }
  1632. else
  1633. {
  1634. ul += FM_WEIGHT_HEIGHT *
  1635. (
  1636. (ULONG)
  1637. (
  1638. lDevHeight
  1639. - lDevWishHeight
  1640. + FM_PHYS_FONT_TOO_LARGE_FACTOR
  1641. )
  1642. );
  1643. }
  1644. }
  1645. if (ul)
  1646. {
  1647. CHECKPRINT("Height",ul);
  1648. ulPenaltyTotal += ul;
  1649. if (bNoMatch(ppfeNew))
  1650. {
  1651. return( iRet );
  1652. }
  1653. if
  1654. (
  1655. ul >= FM_WEIGHT_FACENAME &&
  1656. !(fl & (FM_BIT_NO_MAX_HEIGHT | FM_BIT_SYSTEM_FONT))
  1657. )
  1658. {
  1659. return( iRet );
  1660. }
  1661. }
  1662. }
  1663. MSBREAKPOINT("msCheckAspect");
  1664. // 1. Check if aspect ratio filtering is turned on.
  1665. // 2. Do not check aspect ratio if not raster.
  1666. // 3. Win 3.1 says that the system font cannot be rejected
  1667. // on the basis of the aspect ratio test
  1668. // 4. Win 3.1 style aspect ratio test. In Win 3.1, the X and Y
  1669. // resolutions are checked, not the actual aspect ratio.
  1670. // 5. [GilmanW] 10-Jun-1992
  1671. // For 100% Windows 3.1 compatibility we should not check the true
  1672. // aspect ratio.
  1673. //
  1674. // But as KirkO says, lets leave it for now, as long as we comment
  1675. // it. So, unless you are KirkO or GilmanW, please don't remove
  1676. // this comment.
  1677. if
  1678. (
  1679. (pdco->pdc->flFontMapper() & ASPECT_FILTERING)
  1680. && (ifio.lfOutPrecision() == OUT_RASTER_PRECIS)
  1681. && !(fl & FM_BIT_SYSTEM_FONT)
  1682. && (
  1683. (ulLogPixelsX != (ULONG) ifio.pptlAspect()->x)
  1684. || (ulLogPixelsY != (ULONG) ifio.pptlAspect()->y)
  1685. )
  1686. && (
  1687. (ulLogPixelsX * (ULONG) ifio.pptlAspect()->y)
  1688. != (ulLogPixelsY * (ULONG) ifio.pptlAspect()->x)
  1689. )
  1690. )
  1691. {
  1692. CHECKPRINT("Aspect", FM_REJECT);
  1693. ulPenaltyTotal = FM_REJECT;
  1694. return( iRet );
  1695. }
  1696. MSBREAKPOINT("msCheckItalic");
  1697. if (pelfwWish->elfEnumLogfontEx.elfLogFont.lfItalic)
  1698. {
  1699. // if you get here then the application wants an italicized font
  1700. // if the non simulated font is italicized already then
  1701. // then the penalty is zero.
  1702. if (!ifio.bNonSimItalic())
  1703. {
  1704. if (ifio.bSimItalic())
  1705. {
  1706. flSimulations |= FO_SIM_ITALIC;
  1707. ul = FM_WEIGHT_ITALICSIM;
  1708. }
  1709. else
  1710. {
  1711. ul = FM_WEIGHT_ITALIC;
  1712. }
  1713. CHECKPRINT("Italic",ul);
  1714. ulPenaltyTotal += ul;
  1715. if (bNoMatch(ppfeNew))
  1716. {
  1717. return( iRet );
  1718. }
  1719. }
  1720. }
  1721. else
  1722. {
  1723. // The application doesn't want italicization,
  1724. // the normal font is its best shot
  1725. if (ifio.bNonSimItalic())
  1726. {
  1727. CHECKPRINT("Italic",FM_WEIGHT_ITALIC);
  1728. ulPenaltyTotal += FM_WEIGHT_ITALIC;
  1729. if (bNoMatch(ppfeNew))
  1730. {
  1731. return( iRet );
  1732. }
  1733. }
  1734. }
  1735. MSBREAKPOINT("msCheckWeight");
  1736. {
  1737. LONG lPen;
  1738. lPen = ifio.lfNonSimWeight() - lWishWeight;
  1739. if (fl & FM_BIT_FW_DONTCARE)
  1740. {
  1741. lPen = NT_FAST_DONTCARE_WEIGHT_PENALTY(ABS( lPen ));
  1742. CHECKPRINT("Weight", (DWORD) lPen );
  1743. ulPenaltyTotal += (DWORD) lPen;
  1744. if (bNoMatch(ppfeNew))
  1745. {
  1746. return( iRet );
  1747. }
  1748. }
  1749. else if (lPen != 0)
  1750. {
  1751. if (lPen < 0)
  1752. {
  1753. // non simulated font isn't bold enough -> try a simulation
  1754. lPen = -lPen;
  1755. if( (WIN31_BITMAP_EMBOLDEN_CRITERIA(lPen)) &&
  1756. (ifio.pvSimBold() != NULL) )
  1757. {
  1758. flSimulations |= FO_SIM_BOLD;
  1759. lPen -= FM_WEIGHT_SIMULATED_WEIGHT;
  1760. }
  1761. }
  1762. lPen = NT_FAST_WEIGHT_PENALTY(lPen);
  1763. CHECKPRINT("Weight",(DWORD) lPen );
  1764. ulPenaltyTotal += (DWORD) lPen;
  1765. if (bNoMatch(ppfeNew))
  1766. {
  1767. return( iRet );
  1768. }
  1769. }
  1770. }
  1771. MSBREAKPOINT("msCheckOutPrecision");
  1772. if (!(fl & FM_BIT_DEVICE_FONT))
  1773. {
  1774. // If the device is a plotter then it can't do bitmap fonts
  1775. //
  1776. // If you get to here we are considering the suitability of
  1777. // a non-device font for the current device. The only case
  1778. // where this could be a problem is if the font is a raster
  1779. // font and the device cannot handle raster fonts.
  1780. //
  1781. // I have assume that a plotter can never handle a raster font.
  1782. // Other than that the a raster font is rejected if the device
  1783. // does not set the TC_RA_ABLE bit and the font does not tell
  1784. // you to ignore the TC_RA_ABLE bit.
  1785. // bodind:
  1786. // we need to eliminate raster fonts on non square resolution printers
  1787. // you can not get any type of wysiwig with these
  1788. if (ifio.lfOutPrecision() == OUT_RASTER_PRECIS)
  1789. {
  1790. if
  1791. (
  1792. (fl & FM_BIT_DEVICE_PLOTTER) || (pdco->flGraphicsCaps() & GCAPS_NUP) ||
  1793. !(((fl & FM_BIT_DEVICE_RA_ABLE) && (ulLogPixelsX == ulLogPixelsY))
  1794. || ifio.bIGNORE_TC_RA_ABLE())
  1795. )
  1796. {
  1797. ulPenaltyTotal = FM_REJECT;
  1798. CHECKPRINT("OutPrecision", FM_REJECT);
  1799. return( iRet );
  1800. }
  1801. }
  1802. // We also want to reject non-True Type fonts if the
  1803. // msCheckOutPrecision has
  1804. // been set to OUT_TT_ONLY_PRECIS. [gerritv]
  1805. if (
  1806. (pelfwWish->elfEnumLogfontEx.elfLogFont.lfOutPrecision == OUT_TT_ONLY_PRECIS) &&
  1807. (ifio.lfOutPrecision() != OUT_OUTLINE_PRECIS)
  1808. )
  1809. {
  1810. ulPenaltyTotal = FM_REJECT;
  1811. CHECKPRINT("OutPrecision: font isn't True Type", FM_REJECT);
  1812. return( iRet );
  1813. }
  1814. // new value, reject non ps fonts
  1815. if (
  1816. (pelfwWish->elfEnumLogfontEx.elfLogFont.lfOutPrecision == OUT_PS_ONLY_PRECIS) &&
  1817. !(ifio.pifi->flInfo & FM_INFO_TECH_TYPE1))
  1818. {
  1819. ulPenaltyTotal = FM_REJECT;
  1820. CHECKPRINT("OutPrecision: font isn't PostScript font", FM_REJECT);
  1821. return( iRet );
  1822. }
  1823. }
  1824. // If OUT_TT_PRECIS is used,
  1825. // the mapper gives the slight preference to screen outline font over the
  1826. // device font, everything else being equal. The example of
  1827. // this sitation is arial font, which exists as screen tt font
  1828. // as well as pcl printer device font. If the lfCharSet = 0,
  1829. // weight etc all match, using OUT_SCREEN_OUTLINE_PRECIS would allow applications
  1830. // to choose arial screen (tt) font over arial device.
  1831. // This is important because arial tt will typically have a larger
  1832. // character set and the apps will want to take advantage of it.
  1833. // The difference between this flag and OUT_TT_ONLY_PRECIS is
  1834. // that the latter one forces outline font on screen but does not
  1835. // give preference to outline font over device font on device.
  1836. // Another example might be Helvetica Type 1 font, and screen version
  1837. // may have more glyphs than the small Helvetica built
  1838. // into pscript printers. This of course assumes atm driver installed.
  1839. // Also, setting this flag would pick tt symbol over bitmap symbol.
  1840. if (
  1841. ((pelfwWish->elfEnumLogfontEx.elfLogFont.lfOutPrecision == OUT_SCREEN_OUTLINE_PRECIS)
  1842. // the following line will ensure that when user are not specifying lfOutPrecision,
  1843. // TrueType will be prefered when Lpk is installed.
  1844. // this will ensure correct font to be choosen in Arabic/Hebrew/Shaping printing
  1845. // while still allowing application to specify exactely what lfOutPrecision they want
  1846. // by selecting lfOutPrecision OUT_RASTER_PRECIS, OUT_DEVICE_PRECIS or OUT_PS_ONLY_PRECIS
  1847. || ( EngLpkInstalled() &&
  1848. (pelfwWish->elfEnumLogfontEx.elfLogFont.lfOutPrecision != OUT_RASTER_PRECIS) &&
  1849. (pelfwWish->elfEnumLogfontEx.elfLogFont.lfOutPrecision != OUT_DEVICE_PRECIS) &&
  1850. (pelfwWish->elfEnumLogfontEx.elfLogFont.lfOutPrecision != OUT_PS_ONLY_PRECIS))
  1851. // gdi will map to tt, driver will do device font substitution when it
  1852. // finds appropriate, i.e. when glyphs needed for printout exist
  1853. // the device font that is being substituted
  1854. || (pdco->flGraphicsCaps() & GCAPS_SCREENPRECISION)
  1855. ) &&
  1856. ((fl & FM_BIT_DEVICE_FONT) || (ifio.lfOutPrecision() != OUT_OUTLINE_PRECIS))
  1857. )
  1858. {
  1859. CHECKPRINT("lfOutPrecision",(DWORD) FM_WEIGHT_FAVOR_TT);
  1860. ulPenaltyTotal += FM_WEIGHT_FAVOR_TT;
  1861. if (bNoMatch(ppfeNew))
  1862. {
  1863. return( iRet );
  1864. }
  1865. }
  1866. MSBREAKPOINT("msCheckWidth");
  1867. if (!ifio.bArbXforms() && !ifio.bAnisotropicScalingOnly())
  1868. {
  1869. // If the physical font is scalable. I make the bold assumption
  1870. // that any width can be achieved through linear transformation.
  1871. // This untrue but I will try to get away with this.
  1872. //
  1873. // [kirko] I believe that the correct thing to do is to compare
  1874. // the ratio of the height to with of the request and compare it
  1875. // with the ratio of the height to width of the font in design
  1876. // space. Then assign a penalty based upon the difference.
  1877. LONG lDevWidth = ifio.lfWidth();
  1878. ptlSimulations.x = 1;
  1879. if (pelfwWish->elfEnumLogfontEx.elfLogFont.lfWidth != 0)
  1880. {
  1881. if (!(fl & FM_BIT_CELL) && !bCalculateWishCell())
  1882. {
  1883. // The transform is incompatible with a raster font.
  1884. ulPenaltyTotal = FM_REJECT;
  1885. #if DBG
  1886. if (gflFontDebug & DEBUG_MAPPER)
  1887. {
  1888. if (fl & FM_BIT_BAD_WISH_CELL)
  1889. {
  1890. DbgPrint("\t\tFM_BIT_BAD_WISH_CELL\n");
  1891. }
  1892. }
  1893. #endif
  1894. CHECKPRINT("Width", FM_REJECT);
  1895. return( iRet );
  1896. }
  1897. if
  1898. (
  1899. ifio.bIntegralScaling() &&
  1900. !(fl & FM_BIT_PROOF_QUALITY) &&
  1901. WIN31_BITMAP_WIDTH_SCALING_CRITERIA(lDevWishWidth, lDevWidth)
  1902. )
  1903. {
  1904. // set ptlSimulations.x
  1905. LONG lTemp = WIN31_BITMAP_WIDTH_SCALING(lDevWishWidth,lDevWidth);
  1906. ptlSimulations.x = min(WIN31_BITMAP_WIDTH_SCALING_MAX, lTemp);
  1907. }
  1908. else if (ifio.bIsotropicScalingOnly())
  1909. {
  1910. // For simple scaling fonts, the scaling is determined by the
  1911. // ratio of the font space height to the device space height
  1912. // request.
  1913. ASSERTGDI(ifio.lfHeight(),"msCheckWidth finds lfHeight == 0\n");
  1914. {
  1915. lDevWidth *= lDevWishHeight;
  1916. lDevWidth /= ifio.lfHeight();
  1917. }
  1918. }
  1919. else
  1920. {
  1921. // nothing needs to be done
  1922. }
  1923. ul = 0;
  1924. if (ptlSimulations.x > 1)
  1925. {
  1926. lDevWidth *= ptlSimulations.x;
  1927. ul += (ULONG) ptlSimulations.x
  1928. * FM_WEIGHT_INT_SIZE_SYNTH;
  1929. // Win 3.1 compatibility dictates the next statement
  1930. ul |= (ULONG) (ptlSimulations.x - 1);
  1931. }
  1932. ul += FM_WEIGHT_FWIDTH
  1933. * (ULONG) ABS(lDevWishWidth - lDevWidth);
  1934. if (ul)
  1935. {
  1936. CHECKPRINT("Width",ul);
  1937. ulPenaltyTotal += ul;
  1938. if (bNoMatch(ppfeNew))
  1939. {
  1940. return( iRet );
  1941. }
  1942. }
  1943. }
  1944. else
  1945. {
  1946. // If you get to here then the application has specified a width
  1947. // of zero.
  1948. //
  1949. // If the application asks for proof quality then no simulations
  1950. // are allowed. No width penalty is assessed in the case where
  1951. // the applicaition does not specify a width.
  1952. if (ifio.bIntegralScaling() && !(fl & FM_BIT_PROOF_QUALITY))
  1953. {
  1954. // since no width has been specified we must do aspect
  1955. // ratio matching Win 3.1 style [gerritv]
  1956. ul = 0;
  1957. ULONG ulDevAspect, ulFontAspect, ulFontAspectSave;
  1958. // Since FontAspects and DevAspects will usually be one we will
  1959. // introduce some fast cases to avoid extraneous multiplies and
  1960. // divides
  1961. BOOL bSpeedup = FALSE;
  1962. if (ifio.pptlAspect()->x == ifio.pptlAspect()->y)
  1963. {
  1964. if (ulLogPixelsX == ulLogPixelsY)
  1965. {
  1966. // this is the common case under which
  1967. // we can avoid many multiplies and divides.
  1968. bSpeedup = TRUE;
  1969. }
  1970. }
  1971. if (!bSpeedup)
  1972. {
  1973. // this is taken straight from the Win 3.1 code
  1974. ulDevAspect = ( ulLogPixelsY * 100 ) / ulLogPixelsX;
  1975. ulFontAspectSave = ( ( ifio.pptlAspect()->x * 100 ) /
  1976. ifio.pptlAspect()->y );
  1977. ulFontAspect = ulFontAspectSave / ptlSimulations.y;
  1978. }
  1979. if ((!bSpeedup) || (ptlSimulations.y != 1))
  1980. {
  1981. if ( (bSpeedup) ||
  1982. WIN31_BITMAP_ASPECT_BASED_SCALING(ulDevAspect,ulFontAspect) )
  1983. {
  1984. // divide with rounding
  1985. if (bSpeedup)
  1986. {
  1987. ptlSimulations.x = ptlSimulations.y;
  1988. }
  1989. else
  1990. {
  1991. if( ulFontAspect == 0 )
  1992. {
  1993. ulPenaltyTotal = FM_REJECT;
  1994. return( iRet );
  1995. }
  1996. ptlSimulations.x = ulDevAspect / ulFontAspect;
  1997. }
  1998. // enforce maximum scalling factor
  1999. ptlSimulations.x =
  2000. min( WIN31_BITMAP_WIDTH_SCALING_MAX, ptlSimulations.x );
  2001. ul +=
  2002. WIN31_BITMAP_WIDTH_SCALING_PENALTY((ULONG)ptlSimulations.x);
  2003. }
  2004. else
  2005. {
  2006. ASSERTGDI(ptlSimulations.x == 1, "ptlSimulations.x != 1\n");
  2007. }
  2008. if
  2009. (
  2010. (!bSpeedup) || (ptlSimulations.x != ptlSimulations.y)
  2011. )
  2012. {
  2013. if( ptlSimulations.y == 0 )
  2014. {
  2015. ulPenaltyTotal = FM_REJECT;
  2016. return( iRet );
  2017. }
  2018. ulFontAspect = ulFontAspectSave *
  2019. ptlSimulations.x / ptlSimulations.y;
  2020. ULONG ulTemp = (ULONG) ABS((LONG)(ulDevAspect - ulFontAspect));
  2021. ul += WIN31_BITMAP_ASPECT_MISMATCH_PENALTY( ulTemp );
  2022. }
  2023. if (ul)
  2024. {
  2025. CHECKPRINT("Width",ul);
  2026. ulPenaltyTotal += ul;
  2027. if (bNoMatch(ppfeNew))
  2028. {
  2029. return( iRet );
  2030. }
  2031. }
  2032. }
  2033. else
  2034. {
  2035. // do nothing: no scaling means no penalty
  2036. }
  2037. }
  2038. }
  2039. }
  2040. MSBREAKPOINT("msCheckScaling");
  2041. if
  2042. (
  2043. (ptlSimulations.x > 1 || ptlSimulations.y > 1)
  2044. )
  2045. {
  2046. // Following Win 3.1 we penalize if there is a scaling at all. And there
  2047. // is an additional penalty if the scaling of the height and width
  2048. // directions are not the same.
  2049. #if DBG
  2050. ULONG ulTemp = ulPenaltyTotal;
  2051. #endif
  2052. // Penalize for scaling at all
  2053. ulPenaltyTotal += FM_WEIGHT_SIZESYNTH;
  2054. // Penalize even more if the scaling is anisotropic.
  2055. // Win 3.1 uses the hard coded factor of 100 and so do we!
  2056. if (ptlSimulations.x > ptlSimulations.y)
  2057. {
  2058. ulPenaltyTotal += (ULONG)
  2059. FM_WEIGHT_FUNEVENSIZESYNTH * MULDIV(100, ptlSimulations.x, ptlSimulations.y);
  2060. }
  2061. else if ( ptlSimulations.x < ptlSimulations.y )
  2062. {
  2063. ulPenaltyTotal += (ULONG)
  2064. FM_WEIGHT_FUNEVENSIZESYNTH * MULDIV(100, ptlSimulations.y, ptlSimulations.x);
  2065. }
  2066. CHECKPRINT("msCheckScaling",ulPenaltyTotal-ulTemp);
  2067. if (bNoMatch(ppfeNew))
  2068. {
  2069. return( iRet );
  2070. }
  2071. }
  2072. MSBREAKPOINT("msCheckOrientation");
  2073. if (!ifio.bArbXforms())
  2074. {
  2075. // Either this matches or it doesn't. The penalty is either
  2076. // maximally prohibitive or it is zero.
  2077. //
  2078. // Discussion:
  2079. //
  2080. // All vector fonts are assumed to be OK
  2081. //
  2082. // Raster Font are OK (1) The requested baseline
  2083. // direction agrees with the direction of the raster
  2084. // font (2) The transformation from world to device
  2085. // coordinates is the combination of a scale and a
  2086. // rotation by a multiple of 90 degrees. This means
  2087. // that we will reject if a reflection exists or if
  2088. // there is shear.
  2089. //
  2090. // I shall make the assumption that raster fonts can be
  2091. // used only in the case where the notional to device
  2092. // transformation is a simple scale followed by a rotation
  2093. // that is a multiple of 90 degrees. This means that the
  2094. // baseline in device space is along either the x-axis or
  2095. // y-axis. Moreover, the acender direction must be
  2096. // perpendicular to the baseline. There are a lot of
  2097. // cases where this could happen. For example, suppose
  2098. // that the original orientation was alpha, and their was
  2099. // a world to device transformation that was 90 degrees
  2100. // minus alpha. The resulting orientation would be along
  2101. // one of the axes. However, I will not check for such a
  2102. // coincidence. I will allow only cases where the
  2103. // original orientation in world coordinates is a multiple
  2104. // of 90 degrees, and the world to device transformation
  2105. // is a simple combination of scales and rotations by 90
  2106. // degrees.
  2107. //
  2108. // The orientation should have been computed when we
  2109. // checked heights above.
  2110. //
  2111. // Under Win 3.1 we cannot reject a font because of orientation
  2112. // mismatch if it the device is the screen
  2113. if (!((fl & FM_BIT_GM_COMPATIBLE) && (fl & FM_BIT_DISPLAY_DC)))
  2114. {
  2115. ul = 1;
  2116. if ((fl & FM_BIT_ORIENTATION) || bCalcOrientation())
  2117. {
  2118. ul = (ULONG) iOrientationDevice - pfeo.iOrientation();
  2119. if (ul && (fl & FM_BIT_DEVICE_CR_90_ALL) && (fl & FM_BIT_DEVICE_FONT))
  2120. {
  2121. if (ul > (ULONG) iOrientationDevice)
  2122. {
  2123. ul = (ULONG) (- (LONG) ul);
  2124. }
  2125. ul = ul % ORIENTATION_90_DEG;
  2126. }
  2127. if (ul && ifio.b90DegreeRotations())
  2128. {
  2129. if (ul > (ULONG) iOrientationDevice)
  2130. {
  2131. ul = (ULONG) (- (LONG) ul);
  2132. }
  2133. ul = ul % ORIENTATION_90_DEG;
  2134. }
  2135. }
  2136. if ( ul )
  2137. {
  2138. ulPenaltyTotal = FM_REJECT;
  2139. CHECKPRINT("Orientation",FM_REJECT);
  2140. return( iRet );
  2141. }
  2142. }
  2143. }
  2144. MSBREAKPOINT("msCheckAlias");
  2145. {
  2146. // Checks to see if the font is really an alias for a device font.
  2147. //
  2148. // Discussion:
  2149. //
  2150. // In the Win/WFW3.1 architecture, the device drivers get
  2151. // a chance to do font mapping. Some device drivers, like
  2152. // the PostScript driver and the HP PCL drivers, allow
  2153. // some of the device fonts to be aliased to other names.
  2154. // For example, while the PostScript printer might
  2155. // physically have a "Helvetica" font, the driver allows
  2156. // "Helv", "Arial", and "Swiss" to be mapped to it (with
  2157. // only a small penalty). More precisely, "Helv" et. al
  2158. // are in the "Helvetica" equivalence class.
  2159. //
  2160. // We do not want such a font to be returned without error.
  2161. // Otherwise, if we return this as an exact match, we will not
  2162. // be able to map to REAL fonts that may exist in the engine.
  2163. // For example, since "Arial" is in the equivalence class for
  2164. // "Helvetica", without a penalty we may return "Helvetica" as
  2165. // an exact match. This shorts out the mapper before it can
  2166. // get to the TrueType "Arial" that REALLY exists as an engine
  2167. // font. Therefore, we will impose a slight penalty for
  2168. // aliased fonts.
  2169. //
  2170. //
  2171. // If the FM_BIT_EQUIV_NAME bit is set, the font list we are
  2172. // looking at is really an aliased font name for a device font.
  2173. if (fl & FM_BIT_EQUIV_NAME)
  2174. {
  2175. ulPenaltyTotal += FM_WEIGHT_DEVICE_ALIAS;
  2176. if ( bNoMatch(ppfeNew) )
  2177. {
  2178. return( iRet );
  2179. }
  2180. }
  2181. }
  2182. // The last thing we do is always design vector.
  2183. // If everything else matchhes exactly but the design vector
  2184. // we will record the pfe and have the atm driver create the instance
  2185. // corresponding to this design vector.
  2186. MSBREAKPOINT("msCheckDesignVector");
  2187. {
  2188. DESIGNVECTOR *pdv, *pdvWish;
  2189. if (fl & FM_BIT_BASENAME_MATCHED)
  2190. {
  2191. // the name takes precedance, ie if we have explicit dv == [UU,VV]
  2192. // as well as dv specified through font's family
  2193. // name of the form foo_XX_YY, we ignore dv in ENUMLOGFONTEXDV
  2194. // and use the one specified by the name, [XX,YY] in this case.
  2195. pdvWish = &dvWish;
  2196. }
  2197. else
  2198. {
  2199. pdvWish = (DESIGNVECTOR *)&pelfwWish->elfDesignVector;
  2200. }
  2201. if (pdvWish->dvNumAxes)
  2202. {
  2203. pdv = ifio.pdvDesVect();
  2204. if
  2205. (
  2206. pdv && pdv->dvNumAxes &&
  2207. (pdvWish->dvNumAxes == pdv->dvNumAxes) &&
  2208. (ulPenaltyTotal <= 35000)
  2209. )
  2210. {
  2211. ppfeMMInst = ppfeNew;
  2212. }
  2213. if
  2214. (
  2215. !pdv ||
  2216. (pdvWish->dvNumAxes != pdv->dvNumAxes) ||
  2217. memcmp(pdvWish->dvValues, pdv->dvValues, pdv->dvNumAxes*sizeof(LONG))
  2218. )
  2219. {
  2220. CHECKPRINT("DesignVector",FM_REJECT);
  2221. ulPenaltyTotal = FM_REJECT;
  2222. return(iRet);
  2223. }
  2224. }
  2225. }
  2226. // We are all done!
  2227. return( TRUE );
  2228. }
  2229. /******************************Member*Function*****************************\
  2230. * IFIOBJ::lfOrientation *
  2231. * *
  2232. * Returns the Orientation (angle of the baseline in tenths of degrees *
  2233. * measured counter clockwise from the x-axis) in device space. *
  2234. * *
  2235. * History: *
  2236. * Thu 17-Dec-1992 16:22:56 -by- Charles Whitmer [chuckwh] *
  2237. * Changed the easy case to wierd bit manipulation. *
  2238. * *
  2239. * Tue 24-Sep-1991 10:54:24 by Kirk Olynyk [kirko] *
  2240. * Wrote it. *
  2241. \**************************************************************************/
  2242. LONG IFIOBJ::lfOrientation()
  2243. {
  2244. INT sx = SIGNUM(pifi->ptlBaseline.x);
  2245. INT sy = SIGNUM(pifi->ptlBaseline.y);
  2246. if ((sx^sy)&1) // I.e. if exactly one of them is zero...
  2247. {
  2248. // Return the following angles:
  2249. //
  2250. // sx = 00000001 : 0
  2251. // sy = 00000001 : 900
  2252. // sx = FFFFFFFF : 1800
  2253. // sy = FFFFFFFF : 2700
  2254. return( (sx & 1800) | (sy & 2700) | ((-sy) & 900) );
  2255. }
  2256. // Do the hard case.
  2257. LONG lDummy;
  2258. EFLOATEXT efltX(pifi->ptlBaseline.x);
  2259. EFLOATEXT efltY(pifi->ptlBaseline.y);
  2260. EFLOAT efltTheta;
  2261. vArctan(efltX, efltY, efltTheta, lDummy);
  2262. *(EFLOATEXT*) &efltTheta *= (LONG) 10;
  2263. return( efltTheta.bEfToL(lDummy) ? lDummy : 0 );
  2264. }
  2265. /******************************Public*Routine******************************\
  2266. * MAPPER::bFoundExactMatch() *
  2267. * *
  2268. * This routine searches for a match to an extended logical font. *
  2269. * It is assumed that the face name has infinite weight. Therefore *
  2270. * the face name is searched for in the hash table that is provided by *
  2271. * the caller. If the name is found, then the best match is searched for *
  2272. * among the elements of the linked list of PFE's containing the same *
  2273. * face name. *
  2274. * *
  2275. * If the name is found, then the MAPFONT_FOUND_NAME flag is set in *
  2276. * pflAboutMatch. If the name was found by using facename substitution *
  2277. * (ie., alternate facename), then the MAPFONT_ALTNAME_USED flag is also *
  2278. * set. *
  2279. * *
  2280. * The return value of the function report whether the match was exact. *
  2281. * This information is actually redundant. It could be retrived by *
  2282. * looking at mapper.ulPenaltyTotal *
  2283. * *
  2284. * Important Operating Principles *
  2285. * *
  2286. * 1. The value pointed to pppfeRet is modified only if i) an the name *
  2287. * is matched, and ii) the match is better than any found previously *
  2288. * *
  2289. * History: *
  2290. * Fri 18-Dec-1992 04:57:29 -by- Charles Whitmer [chuckwh] *
  2291. * Rewrote it for performance. One major change is that I only take the *
  2292. * winning PFE and move it to the front of the list, rather than *
  2293. * continually shuffling the list. This cuts down overhead and should *
  2294. * have about the same effect. *
  2295. * *
  2296. * Wed 22-Apr-1992 10:47:50 by Kirk Olynyk [kirko] *
  2297. * Wrote it. *
  2298. \**************************************************************************/
  2299. BOOL
  2300. MAPPER::bFoundExactMatch(
  2301. FONTHASH **ppfh
  2302. )
  2303. {
  2304. PFELINK *ppfelBest = NULL, *ppfel;
  2305. HASHBUCKET *apbkt[3];
  2306. BYTE ajCharSet[3];
  2307. FONTHASHTYPE fht;
  2308. int i,iBest;
  2309. BOOL bRet = FALSE;
  2310. BYTE jCharSet = DEFAULT_CHARSET;
  2311. // This is returned as the *pflAboutMatch in the MAPPER class if and only
  2312. // if we find a better match. So we store it temporarily in this local
  2313. // rather than set it directly.
  2314. *pflAboutMatch &= ~MAPFONT_FOUND_NAME;
  2315. FHOBJ fho(ppfh);
  2316. if (!fho.bValid())
  2317. {
  2318. return( bRet );
  2319. }
  2320. fht = fho.fht();
  2321. // Note well: mapper.pwszFaceName must ALWAYS be CAPITALIZED!
  2322. const WCHAR * pwszTarg = this->pwszFaceName;
  2323. // Attempt to locate the name.
  2324. #define I_ORIGINAL 0
  2325. #define I_ALTERNATE 1
  2326. #define I_BASE 2
  2327. apbkt[I_ORIGINAL] = apbkt[I_ALTERNATE] = apbkt[I_BASE] = NULL;
  2328. ajCharSet[I_ORIGINAL] =
  2329. ajCharSet[I_BASE] =
  2330. ajCharSet[I_ALTERNATE] = (BYTE)pelfwWish->elfEnumLogfontEx.elfLogFont.lfCharSet;
  2331. FONTSUB* pfsub = pfsubGetFontSub(pwszTarg,
  2332. (BYTE)pelfwWish->elfEnumLogfontEx.elfLogFont.lfCharSet);
  2333. if (pfsub)
  2334. {
  2335. // charsets specified or not in the substitution entry ?
  2336. if (pfsub->fcsAltFace.fjFlags & FJ_NOTSPECIFIED)
  2337. {
  2338. // old style substitution, no charsets are specified
  2339. // First search for the facename on the left hand side,
  2340. // if not found search for the one on the right hand side.
  2341. // In both cases use the original charset in the logfont.
  2342. apbkt[I_ORIGINAL] = fho.pbktSearch(pwszTarg,(UINT*)NULL);
  2343. apbkt[I_ALTERNATE] = fho.pbktSearch((PWSZ)pfsub->fcsAltFace.awch,(UINT*)NULL);
  2344. }
  2345. else
  2346. {
  2347. // charsets are specified in the font substitution entry.
  2348. // When the charset requested in the logfont matches the one on
  2349. // the left hand side of the substitution, we shall actually go
  2350. // for the alternate facename and charset, without even looking
  2351. // if the font with facename and charset specified on the left
  2352. // hand side is installed on the system.
  2353. // This is win95 behavior which actually makes some sense.
  2354. apbkt[I_ALTERNATE] = fho.pbktSearch((PWSZ)pfsub->fcsAltFace.awch,(UINT*)NULL);
  2355. ajCharSet[I_ALTERNATE] = pfsub->fcsAltFace.jCharSet;
  2356. }
  2357. }
  2358. else
  2359. {
  2360. apbkt[I_ORIGINAL] = fho.pbktSearch(pwszTarg,(UINT*)NULL);
  2361. }
  2362. // now search for the bucket corresponding to the cannonical name if any
  2363. // We will only do this for FAMILY i.e menu names, not for face names:
  2364. if (awcBaseName[0] && (fht == FHT_FAMILY))
  2365. apbkt[I_BASE] = fho.pbktSearch(this->awcBaseName,(UINT*)NULL, NULL, FALSE);
  2366. if (!apbkt[I_ORIGINAL] && !apbkt[I_ALTERNATE] && !apbkt[I_BASE])
  2367. {
  2368. return( bRet );
  2369. }
  2370. // If we get to here, we were able to find a hash bucket
  2371. // of the correct name.
  2372. *pflAboutMatch |= MAPFONT_FOUND_NAME;
  2373. fl |= FM_BIT_FACENAME_MATCHED;
  2374. // Scan the PFE list for the best match.
  2375. for (i = 0; i < 3; i++)
  2376. {
  2377. if (!apbkt[i])
  2378. {
  2379. continue;
  2380. }
  2381. vResetCharSet(ajCharSet[i]);
  2382. if (apbkt[i]->fl & HB_EQUIV_FAMILY)
  2383. {
  2384. fl |= FM_BIT_EQUIV_NAME;
  2385. }
  2386. else
  2387. {
  2388. fl &= ~FM_BIT_EQUIV_NAME;
  2389. }
  2390. if (i == I_BASE)
  2391. {
  2392. fl |= FM_BIT_BASENAME_MATCHED;
  2393. }
  2394. else
  2395. {
  2396. fl &= ~FM_BIT_BASENAME_MATCHED;
  2397. }
  2398. for
  2399. (
  2400. ppfelBest = NULL, ppfel = apbkt[i]->ppfelEnumHead;
  2401. ppfel;
  2402. ppfel = ppfel->ppfelNext
  2403. )
  2404. {
  2405. #if DBG
  2406. if (gflFontDebug & DEBUG_MAPPER && ppfel->ppfe == ppfeBreak)
  2407. {
  2408. DbgPrint(" **** breaking on ppfel = %-#8lx\n\n", ppfel);
  2409. DbgBreakPoint();
  2410. }
  2411. #endif
  2412. PFEOBJ pfeo(ppfel->ppfe);
  2413. if (this->bNearMatch(pfeo,&jCharSet))
  2414. {
  2415. DUMP_CHOSEN_FONT(pfeo);
  2416. iBest = i;
  2417. // remember the good one
  2418. ppfelBest = ppfel;
  2419. // remember the simulation information for the best font
  2420. // choice to this time
  2421. vSetBest(ppfel->ppfe, fl & FM_BIT_DEVICE_FONT, jCharSet);
  2422. if (this->ulPenaltyTotal == 0)
  2423. {
  2424. // If the match was exact, return immediately unless
  2425. // there this is a true type font and there are
  2426. // rasterfonts of the same face name. In this case
  2427. // we must give the rasterfonts a chance since in the
  2428. // event of a tie, the raster font must win to be Win
  2429. // 3.1 compatibile!
  2430. if( !( apbkt[i]->cRaster ) ||
  2431. ( pfeo.flFontType() & RASTER_FONTTYPE ))
  2432. {
  2433. bRet = TRUE;
  2434. break;
  2435. }
  2436. // we need to give the raster fonts a chance we do this
  2437. // by setting ulPenaltyTotal to 1.
  2438. // This way only an exact match will beat us out.
  2439. this->ulPenaltyTotal = 1;
  2440. }
  2441. // prune the search
  2442. this->ulMaxPenalty = this->ulPenaltyTotal;
  2443. }
  2444. else
  2445. {
  2446. DUMP_REJECTED_FONT(pfeo);
  2447. }
  2448. }
  2449. if (bRet == TRUE)
  2450. {
  2451. break;
  2452. }
  2453. }
  2454. // Return a good one if we found it.
  2455. if (ppfelBest)
  2456. {
  2457. // We found a better match, so better change the about flags.
  2458. if (iBest == I_ALTERNATE || fht == FHT_FACE)
  2459. {
  2460. *pflAboutMatch |= MAPFONT_ALTFACE_USED;
  2461. }
  2462. // record code page, needed for correct code page to
  2463. // unicode translation In case of single charset
  2464. // font, we always cheat and represent the font
  2465. // glyphset using ansi to unicode conversion using
  2466. // the current ansi code page, even though the
  2467. // underlining font may contain a symbol or an oem
  2468. // code page. But we do not care, we just need to
  2469. // make the round trip a->u->a works for these fonts.
  2470. // Also we want the client side cacheing of char
  2471. // widths for GTE and GCW to work for these fonts.
  2472. // there are two exceptions to this rule: 1) the default ansi code page is
  2473. // not SBCS since this doesn't guarantee roundtrupe conversion and
  2474. // 2) the charset of the font is DBCS
  2475. ULONG ulCodePage;
  2476. // the best charset so far is remembered in pflAboutMatch
  2477. BYTE jBestCharSet = (BYTE)(*pflAboutMatch >> 24);
  2478. if
  2479. (
  2480. (jBestCharSet != OEM_CHARSET) ||
  2481. ppfelBest->ppfe->pifi->dpCharSets ||
  2482. (ppfelBest->ppfe->flPFE & PFE_DEVICEFONT) ||
  2483. IS_ANY_DBCS_CHARSET(jBestCharSet)
  2484. )
  2485. {
  2486. ulCodePage = ulCharsetToCodePage(jBestCharSet);
  2487. }
  2488. else
  2489. {
  2490. // just use 1252 if the default CP is not SBCS
  2491. ulCodePage = (gbDBCSCodePage) ? 1252 : CP_ACP;
  2492. }
  2493. *pflAboutMatch |= (ulCodePage << 8);
  2494. }
  2495. fl &= ~FM_BIT_EQUIV_NAME;
  2496. return( bRet );
  2497. }
  2498. /****************************************************************************
  2499. * MAPPER::bFoundForcedMatch( PUNIVERSAL_FONT_ID pufi )
  2500. *
  2501. * This routine forces mapping to a PFE identified by a UFI. It will compute
  2502. * simulations to be performed on the font as well.
  2503. * History:
  2504. * Oct-21-97 by Xudong Wu [tessiew]
  2505. * Disable the ufi matching for device fonts
  2506. * 5/11/1995 by Gerrit van Wingerden [gerritv]
  2507. * Wrote it.
  2508. *****************************************************************************/
  2509. BOOL MAPPER::bFoundForcedMatch(UNIVERSAL_FONT_ID *pufi)
  2510. {
  2511. #if DBG
  2512. if (gflFontDebug & DEBUG_MAPPER)
  2513. {
  2514. DbgPrint("MAPPER::bFoundForcedMatch: " );
  2515. DbgPrint("CheckSum = %x Index = %d\n", pufi->CheckSum, pufi->Index );
  2516. }
  2517. #endif
  2518. PFE *ppfe;
  2519. // for device font, the ufi on the print server side
  2520. // might not match the one on the client side
  2521. // so we don't use the ufi-match on device fonts any more
  2522. if(UFI_DEVICE_FONT(pufi))
  2523. {
  2524. ppfe = NULL;
  2525. }
  2526. else if(UFI_TYPE1_FONT(pufi))
  2527. {
  2528. DEVICE_PFTOBJ pftoDevice;
  2529. FONTHASH **ppfh = (FONTHASH**) NULL;
  2530. PFF *pPFF;
  2531. if (pPFF = pftoDevice.pPFFGet(pdco->hdev()))
  2532. {
  2533. PFFOBJ pffo(pPFF);
  2534. if (pffo.bValid())
  2535. {
  2536. ppfh = &pffo.pPFF->pfhFamily;
  2537. }
  2538. }
  2539. if (ppfh == (FONTHASH**) NULL)
  2540. {
  2541. WARNING1("MAPPER::bFoundForcedMatch() -- invalid FONTHASH\n");
  2542. return( FALSE );
  2543. }
  2544. // Prepare to enumerate through all the device fonts
  2545. ENUMFHOBJ fho(ppfh);
  2546. for (ppfe = fho.ppfeFirst(); ppfe; ppfe = fho.ppfeNext())
  2547. {
  2548. PFEOBJ pfeo(ppfe);
  2549. if (UFI_SAME_FACE(pfeo.pUFI(), pufi))
  2550. {
  2551. if( pfeo.bDead() )
  2552. {
  2553. WARNING("MAPPER::bFoundForcedMatch mapped to dead PFE\n");
  2554. }
  2555. else
  2556. {
  2557. break;
  2558. }
  2559. }
  2560. }
  2561. }
  2562. else
  2563. {
  2564. ppfe = ppfeGetPFEFromUFI(pufi,
  2565. FALSE, // public font table
  2566. TRUE); // check process
  2567. }
  2568. if ( ppfe == NULL )
  2569. {
  2570. WARNING1("MAPPER::bFoundForcedMatch unable to find forced match\n");
  2571. return( FALSE );
  2572. }
  2573. // If we are here we found the right PFE,
  2574. // now we need to compute ptlSim and flSim.
  2575. ptlSimulations.x = 1;
  2576. ptlSimulations.y = 1;
  2577. flSimulations = 0;
  2578. PFEOBJ pfeo(ppfe);
  2579. ifio.vSet( pfeo.pifi() );
  2580. // first compute any possible height simulations
  2581. if (!ifio.bContinuousScaling())
  2582. {
  2583. LONG
  2584. lDevHeight =
  2585. (fl & FM_BIT_USE_EMHEIGHT) ? ifio.fwdUnitsPerEm() : ifio.lfHeight();
  2586. if (
  2587. lDevHeight < lDevWishHeight &&
  2588. ifio.bIntegralScaling() &&
  2589. !(fl & FM_BIT_PROOF_QUALITY) &&
  2590. WIN31_BITMAP_HEIGHT_SCALING_CRITERIA(lDevWishHeight,lDevHeight)
  2591. )
  2592. {
  2593. LONG lTemp = WIN31_BITMAP_HEIGHT_SCALING(lDevWishHeight,lDevHeight);
  2594. ptlSimulations.y = min(WIN31_BITMAP_HEIGHT_SCALING_MAX,lTemp);
  2595. }
  2596. else
  2597. {
  2598. ptlSimulations.y = 1;
  2599. }
  2600. }
  2601. // next check for italic simulations
  2602. if (pelfwWish->elfEnumLogfontEx.elfLogFont.lfItalic)
  2603. {
  2604. // if you get here then the application wants an italicized font
  2605. if (!ifio.bNonSimItalic() && ifio.bSimItalic())
  2606. {
  2607. flSimulations |= FO_SIM_ITALIC;
  2608. }
  2609. }
  2610. // bold simulations
  2611. LONG lPen;
  2612. lPen = ifio.lfNonSimWeight() - lWishWeight;
  2613. if( !(fl & FM_BIT_FW_DONTCARE) && (lPen < 0 ) )
  2614. {
  2615. // non simulated font isn't bold enough -> try a simulation
  2616. lPen = -lPen;
  2617. if( (WIN31_BITMAP_EMBOLDEN_CRITERIA(lPen)) &&
  2618. (ifio.pvSimBold() != NULL) )
  2619. {
  2620. flSimulations |= FO_SIM_BOLD;
  2621. }
  2622. }
  2623. // width simulations
  2624. if (!ifio.bArbXforms() && !ifio.bAnisotropicScalingOnly())
  2625. {
  2626. LONG lDevWidth = ifio.lfWidth();
  2627. ptlSimulations.x = 1;
  2628. if (pelfwWish->elfEnumLogfontEx.elfLogFont.lfWidth != 0)
  2629. {
  2630. if( !(fl & FM_BIT_CELL) )
  2631. {
  2632. bCalculateWishCell();
  2633. }
  2634. if
  2635. (
  2636. ifio.bIntegralScaling() &&
  2637. !(fl & FM_BIT_PROOF_QUALITY) &&
  2638. WIN31_BITMAP_WIDTH_SCALING_CRITERIA(lDevWishWidth, lDevWidth)
  2639. )
  2640. {
  2641. // set ptlSimulations.x
  2642. LONG lTemp = WIN31_BITMAP_WIDTH_SCALING(lDevWishWidth,lDevWidth);
  2643. ptlSimulations.x = min(WIN31_BITMAP_WIDTH_SCALING_MAX, lTemp);
  2644. }
  2645. }
  2646. else
  2647. {
  2648. if (ifio.bIntegralScaling() && !(fl & FM_BIT_PROOF_QUALITY))
  2649. {
  2650. // since no width has been specified we must do aspect
  2651. // ratio matching Win 3.1 style [gerritv]
  2652. ULONG ulDevAspect, ulFontAspect, ulFontAspectSave;
  2653. // Since FontAspects and DevAspects will usually be one we will
  2654. // introduce some fast cases to avoid extraneous multiplies and
  2655. // divides
  2656. BOOL bSpeedup = FALSE;
  2657. if (ifio.pptlAspect()->x == ifio.pptlAspect()->y)
  2658. {
  2659. if (ulLogPixelsX == ulLogPixelsY)
  2660. {
  2661. // this is the common case under which
  2662. // we can avoid many multiplies and divides.
  2663. bSpeedup = TRUE;
  2664. }
  2665. }
  2666. if (!bSpeedup)
  2667. {
  2668. // this is taken straight from the Win 3.1 code
  2669. ulDevAspect = ( ulLogPixelsY * 100 ) / ulLogPixelsX;
  2670. ulFontAspectSave = ( ( ifio.pptlAspect()->x * 100 ) /
  2671. ifio.pptlAspect()->y );
  2672. ulFontAspect = ulFontAspectSave / ptlSimulations.y;
  2673. }
  2674. if ((!bSpeedup) || (ptlSimulations.y != 1))
  2675. {
  2676. if
  2677. (
  2678. (bSpeedup) ||
  2679. WIN31_BITMAP_ASPECT_BASED_SCALING(ulDevAspect,ulFontAspect)
  2680. )
  2681. {
  2682. // divide with rounding
  2683. if (bSpeedup)
  2684. {
  2685. ptlSimulations.x = ptlSimulations.y;
  2686. }
  2687. else
  2688. {
  2689. if (ulFontAspect == 0)
  2690. {
  2691. WARNING1("MAPPER::bFoundForcedMatch "
  2692. "ulFontAspect == 0\n");
  2693. return( FALSE );
  2694. }
  2695. ptlSimulations.x = ulDevAspect / ulFontAspect;
  2696. }
  2697. // enforce maximum scalling factor
  2698. ptlSimulations.x =
  2699. min( WIN31_BITMAP_WIDTH_SCALING_MAX, ptlSimulations.x );
  2700. }
  2701. else
  2702. {
  2703. ASSERTGDI(ptlSimulations.x == 1, "ptlSimulations.x != 1\n");
  2704. }
  2705. }
  2706. }
  2707. }
  2708. }
  2709. // need to do this here because vSetBest will update ptlSim and pflSim
  2710. // Another important point to note here is that the charset and code page
  2711. // needed for ansi to unicode conversion will remain uninitialized.
  2712. // I think that this is ok because for metafile spooled printing the text is
  2713. // always going to recorded as unicode so that this conversion will never
  2714. // have to be performed [bodind]
  2715. vSetBest( ppfe, TRUE, DEFAULT_CHARSET );
  2716. #if DBG
  2717. if (gflFontDebug & DEBUG_MAPPER)
  2718. {
  2719. DbgPrint("MAPPER::bFoundForcedMatch: ppfeBest = %-#x\n", ppfeBest );
  2720. }
  2721. #endif
  2722. return( TRUE );
  2723. }
  2724. /******************************Public*Routine******************************\
  2725. * ppfeGetAMatch *
  2726. * *
  2727. * Returns the best fit to a wish defined by the application. *
  2728. * *
  2729. * History: *
  2730. * Wed 11-Dec-1991 09:32:11 by Kirk Olynyk [kirko] *
  2731. * Wrote it. *
  2732. \**************************************************************************/
  2733. PFE *ppfeGetAMatch (
  2734. XDCOBJ& dco, // The DC defines all the relevant
  2735. // transformations and physical
  2736. // sizes to be used to determine
  2737. // the suitablity of a font
  2738. ENUMLOGFONTEXDVW *pelfwWishSrc, // defines the font that is wished
  2739. // for by the application
  2740. const WCHAR * pwszFaceName, // The sought name.
  2741. ULONG ulMaxPenalty, // a cutoff for the sum of all the
  2742. // individual penalties of each of the
  2743. // fields of the LOGFONT structure.
  2744. // If the sum of all the penalties
  2745. // associated with a physical font
  2746. // is greater than this cutoff, then
  2747. // the phyisical font is rejected
  2748. // as a potential match.
  2749. FLONG fl, // This is a set of flags defining
  2750. // how mapping is to proceed and/or
  2751. // various parameters are to be
  2752. // interpreted. The flags that are
  2753. // supported are:
  2754. //
  2755. // FM_BIT_PIXEL_COORD
  2756. //
  2757. // If this flag is not present, then the
  2758. // dimensionful quantities in the
  2759. // logical font are in world coordinates.
  2760. // If this flag is present then the
  2761. // dimensionful (length like) quantities
  2762. // in the logical font are in pixel
  2763. // coordinates (one unit = one pixel).
  2764. // This bit is set only for stock
  2765. // fonts, which are defined by the device
  2766. // driver and are to be transformation
  2767. // independent.
  2768. FLONG *pflSim, // a place to put the simulation
  2769. // flags.
  2770. POINTL *pptlSim, // this recieves the height- and width-
  2771. // scaling factor for bitmap fonts
  2772. FLONG *pflAboutMatch, // This returns information about how
  2773. // the match was achieved. Flags
  2774. // supported are:
  2775. //
  2776. // MAPFONT_FOUND_NAME
  2777. //
  2778. // This flag indicates that a facename
  2779. // was found by the mapper.
  2780. //
  2781. // MAPFONT_ALTFACE_USED
  2782. //
  2783. // This flag indicates that the facename
  2784. // found was an alternate or substitute
  2785. // facename.
  2786. BOOL bIndexFont_ // font MUST support ETO_GLYPH_INDEX
  2787. )
  2788. {
  2789. ASSERTGDI(!(fl & ~FM_BIT_PIXEL_COORD),"GDISRV!ppfeGetAMatch -- invalid fl\n");
  2790. PPFEGETAMATCH_DEBUG_MACRO_1;
  2791. MAPPER
  2792. mapper(
  2793. &dco
  2794. , pflSim
  2795. , pptlSim
  2796. , pflAboutMatch
  2797. , pelfwWishSrc
  2798. , pwszFaceName
  2799. , ulMaxPenalty
  2800. , bIndexFont_
  2801. , fl
  2802. );
  2803. // Currently there is no way for the MAPPER constructor
  2804. // to fail. In the future it may be able to fail and we
  2805. // will need to check here.
  2806. ASSERTGDI(mapper.bValid(),"GDISRV!ppfeGetAMatch -- invalid mapper\n");
  2807. #if DBG
  2808. if (gflFontDebug & DEBUG_DUMP_FHOBJ)
  2809. {
  2810. if (mapper.bDeviceFontsExist())
  2811. {
  2812. DEVICE_PFTOBJ pftoDevice;
  2813. PFFOBJ pffo(pftoDevice.pPFFGet(dco.pdc->hdev()));
  2814. if (pffo.bValid())
  2815. {
  2816. FHOBJ fhoFamily(&pffo.pPFF->pfhFamily);
  2817. FHOBJ fhoFace(&pffo.pPFF->pfhFace);
  2818. DbgPrint("\n\n\tDumping Device Family Names\n");
  2819. fhoFamily.vPrint((VPRINT) DbgPrint);
  2820. DbgPrint("\n\n\tDumping Device Face Names\n");
  2821. fhoFace.vPrint((VPRINT) DbgPrint);
  2822. }
  2823. }
  2824. else
  2825. {
  2826. DbgPrint("\n\tTHERE ARE NO DEVICE FONTS!\n\n");
  2827. }
  2828. PUBLIC_PFTOBJ pfto;
  2829. FHOBJ fhoFamily(&pfto.pPFT->pfhFamily);
  2830. FHOBJ fhoFace(&pfto.pPFT->pfhFace);
  2831. DbgPrint("\n\n\tDumping Engine Family Names\n");
  2832. fhoFamily.vPrint((VPRINT) DbgPrint);
  2833. DbgPrint("\n\n\tDumping Engine Face Names\n");
  2834. fhoFace.vPrint((VPRINT) DbgPrint);
  2835. }
  2836. #endif
  2837. UNIVERSAL_FONT_ID ufi;
  2838. if( dco.pdc->bForcedMapping( &ufi ) )
  2839. {
  2840. // If we got here we are playing back an EMF spoolfile
  2841. // which was generated on a remote machine. We must do
  2842. // forced mapping based on UFI's
  2843. if( mapper.bFoundForcedMatch(&ufi) )
  2844. {
  2845. PPFEGETAMATCH_DEBUG_RETURN(mapper.ppfeRet());
  2846. }
  2847. else
  2848. {
  2849. WARNING1("ppfeGetAMatch: bFoundForceMatch "
  2850. "failed to find a match");
  2851. }
  2852. }
  2853. // check the Private PFT before device and public PFT if gpPFTPrivate != NULL
  2854. // We do not want to go through small font hack for private fonts.
  2855. if (gpPFTPrivate && gpPFTPrivate->cFiles)
  2856. {
  2857. PUBLIC_PFTOBJ pftoPrivate(gpPFTPrivate);
  2858. mapper.vNotDeviceFonts(); // put mapper in "check engine fonts" state
  2859. if
  2860. (
  2861. mapper.bFoundExactMatch(&pftoPrivate.pPFT->pfhFamily) ||
  2862. mapper.bFoundExactMatch(&pftoPrivate.pPFT->pfhFace)
  2863. )
  2864. {
  2865. PPFEGETAMATCH_DEBUG_RETURN(mapper.ppfeRet());
  2866. }
  2867. }
  2868. // check the device fonts first (if they exist)
  2869. DEVICE_PFTOBJ pftoDevice;
  2870. if (mapper.bDeviceFontsExist())
  2871. {
  2872. PFF *pPFF;
  2873. // put mapper in "check device fonts" state
  2874. mapper.vDeviceFonts();
  2875. if (pPFF = pftoDevice.pPFFGet(dco.hdev()))
  2876. {
  2877. PFFOBJ pffo(pPFF);
  2878. if (pffo.bValid())
  2879. {
  2880. if
  2881. (
  2882. mapper.bFoundExactMatch(&pffo.pPFF->pfhFamily) ||
  2883. mapper.bFoundExactMatch(&pffo.pPFF->pfhFace)
  2884. )
  2885. {
  2886. PPFEGETAMATCH_DEBUG_RETURN(mapper.ppfeRet());
  2887. }
  2888. }
  2889. if( mapper.bDeviceOnly() )
  2890. {
  2891. //
  2892. // If the device insists that we use only its fonts then
  2893. // we will do so. If the application requested a device
  2894. // font then we will map to that font and that font
  2895. // is contained in mapper.ppfeRet(). Otherwise, if the
  2896. // application asked for a face name that is not contained
  2897. // in the list of device fonts, then the current value
  2898. // of mapper.ppfeRet() will be NULL. In that case we
  2899. // will simply map to an arbitrary device font without
  2900. // regard to the size requested by the application.
  2901. // Caveat Emptor.
  2902. //
  2903. PFE *ppfeRet;
  2904. ppfeRet = mapper.ppfeRet();
  2905. if (ppfeRet == 0 || ppfeRet->pPFF != pPFF)
  2906. {
  2907. *pflSim = 0;
  2908. *pflAboutMatch = 0;
  2909. pptlSim->x = pptlSim->y = 1;
  2910. FONTHASH **ppfh = &pffo.pPFF->pfhFamily;
  2911. ENUMFHOBJ fho(ppfh);
  2912. ppfeRet = fho.ppfeFirst();
  2913. }
  2914. PPFEGETAMATCH_DEBUG_RETURN( ppfeRet );
  2915. }
  2916. }
  2917. }
  2918. // If an exact match was not found check the Engine fonts
  2919. PUBLIC_PFTOBJ pftoPublic;
  2920. mapper.vNotDeviceFonts(); // put mapper in "check engine fonts" state
  2921. if
  2922. (
  2923. mapper.bFoundExactMatch(&pftoPublic.pPFT->pfhFamily) ||
  2924. mapper.bFoundExactMatch(&pftoPublic.pPFT->pfhFace)
  2925. )
  2926. {
  2927. PPFEGETAMATCH_DEBUG_RETURN(mapper.ppfeRet());
  2928. }
  2929. // If you get here, and ppfeRet != 0 then then lfFaceName
  2930. // has been matched by either the device or gdi. In either
  2931. // case, we terminate the search and return the best match
  2932. // found. This is somewhat incompatible with Windows 3.1
  2933. // which considers FaceName less important that pitch
  2934. // and family. Windows 3.1 would continue the search over
  2935. // all available fonts in order to get a better match.
  2936. if (mapper.ppfeRet())
  2937. {
  2938. PPFEGETAMATCH_DEBUG_RETURN(mapper.ppfeRet());
  2939. }
  2940. // At this point we know that no exact match will be found
  2941. // amongst the fonts installed on the system at this time.
  2942. // We shall therefore try to see if this was a request for mm instance
  2943. // for an mm font whose other instance is installed and create the
  2944. // requested instance dynamically.
  2945. // In the future we may exted this function to go out and search for the
  2946. // font that has not been addfontresource'ed at this time
  2947. // (perhaps by calling to font drivers, or maybe not)
  2948. // and install it dynamically.
  2949. PFE *ppfeRet = mapper.ppfeSynthesizeAMatch(pflSim, pflAboutMatch, pptlSim);
  2950. if (ppfeRet)
  2951. {
  2952. PPFEGETAMATCH_DEBUG_RETURN(ppfeRet);
  2953. }
  2954. // If you get to here then the face name has not been found
  2955. // in either the Device or GDI fonts. A font of a different
  2956. // face name will have to be substituted. Try to match to a
  2957. // Device font, but the match better be a good one!
  2958. if (!(dco.flGraphicsCaps() & GCAPS_SCREENPRECISION))
  2959. {
  2960. if (mapper.bDeviceFontsExist())
  2961. {
  2962. mapper.vAttemptDeviceMatch();
  2963. if (mapper.ppfeRet())
  2964. {
  2965. PPFEGETAMATCH_DEBUG_RETURN(mapper.ppfeRet());
  2966. }
  2967. }
  2968. }
  2969. // Well ... we are left with attempting to match to GDI fonts.
  2970. // Since the original request face name was a flop,
  2971. // I will attempt a suitable GDI FaceName.
  2972. if( !(mapper.bCalled_bGetFaceName()))
  2973. {
  2974. #if DBG
  2975. if (gflFontDebug & DEBUG_MAPPER)
  2976. DbgPrint("\n\tAttempting to match to an"
  2977. " engine font of a different name\n");
  2978. #endif
  2979. mapper.bGetFaceName();
  2980. mapper.vReset();
  2981. mapper.vNotDeviceFonts(); // put mapper in "check engine fonts" state
  2982. if
  2983. (
  2984. mapper.bFoundExactMatch(&pftoPublic.pPFT->pfhFamily) ||
  2985. mapper.bFoundExactMatch(&pftoPublic.pPFT->pfhFace)
  2986. )
  2987. {
  2988. PPFEGETAMATCH_DEBUG_RETURN(mapper.ppfeRet());
  2989. }
  2990. if (mapper.ppfeRet())
  2991. {
  2992. PPFEGETAMATCH_DEBUG_RETURN(mapper.ppfeRet());
  2993. }
  2994. }
  2995. // Up until now we've reject fonts whose charset doesn't
  2996. // match the requested charset even though the facename
  2997. // matches. At this point we allow for the possibility
  2998. // of chosing a font whose charset doesn't match. However,
  2999. // we will make the penalty so high that for such a font that
  3000. // if any other font exists whose charset does match,
  3001. // it will alwats beat the font whose charset doesn't match.
  3002. mapper.vAcceptDiffCharset();
  3003. // We are in big trouble now! To recount the story to this point.
  3004. // We have failed to match the facename against either the device
  3005. // or engine fonts. Then we failed to match against any device font
  3006. // even though we ignored the name. Finally, we could not match
  3007. // default facenames against the GDI fonts.
  3008. // Now we call the emergency routine that gets a font, any font.
  3009. mapper.vEmergency();
  3010. // Either vEmergency() got a font or it didn't. It doesn't matter,
  3011. // we have no choice but to return at this point.
  3012. PPFEGETAMATCH_DEBUG_RETURN(mapper.ppfeRet());
  3013. }
  3014. /******************************Member*Function*****************************\
  3015. * MAPPER::vAttemptDeviceMatch() *
  3016. * *
  3017. * Considers every device font and tries to find the best match. *
  3018. * Facenames are ignored. *
  3019. * *
  3020. * History: *
  3021. * Thu 11-Mar-1993 15:44:59 by Kirk Olynyk [kirko] *
  3022. * Wrote it. *
  3023. \**************************************************************************/
  3024. VOID MAPPER::vAttemptDeviceMatch()
  3025. {
  3026. FONTHASH **ppfh = (FONTHASH**) NULL;
  3027. PFE *ppfeRet = (PFE*) NULL;
  3028. PFE *ppfe;
  3029. BYTE jCharSet = DEFAULT_CHARSET;
  3030. #if DBG
  3031. if (gflFontDebug & DEBUG_MAPPER)
  3032. {
  3033. DbgPrint("\n\tMAPPER::vAtteptDeviceMatch()\n");
  3034. }
  3035. #endif
  3036. // If the application asked for symbol then I will only allow GDI
  3037. // to do font substitution. This request will probably end with
  3038. // WingDings
  3039. if (jMapCharSet == SYMBOL_CHARSET)
  3040. {
  3041. return;
  3042. }
  3043. DEVICE_PFTOBJ pftoDevice;
  3044. PFF *pPFF;
  3045. if (pPFF = pftoDevice.pPFFGet(pdco->hdev()))
  3046. {
  3047. PFFOBJ pffo(pPFF);
  3048. if (pffo.bValid())
  3049. {
  3050. ppfh = &pffo.pPFF->pfhFamily;
  3051. }
  3052. }
  3053. if (ppfh == (FONTHASH**) NULL)
  3054. {
  3055. RIP("MAPPER::vAttemptDeviceMatch() -- invalid FONTHASH\nReturning NULL");
  3056. return;
  3057. }
  3058. // Set a very stringent pruning criteria!
  3059. vReset(FM_WEIGHT_ITALIC-1);
  3060. // reset the mapping information
  3061. fl |= FM_BIT_DEVICE_FONT;
  3062. // Prepare to enumerate through all the device fonts
  3063. ENUMFHOBJ fho(ppfh);
  3064. for (ppfe = fho.ppfeFirst(); ppfe; ppfe = fho.ppfeNext())
  3065. {
  3066. PFEOBJ pfeo(ppfe);
  3067. if (this->bNearMatch(pfeo,&jCharSet))
  3068. {
  3069. DUMP_CHOSEN_FONT(pfeo);
  3070. if (this->ulPenaltyTotal == 0)
  3071. {
  3072. // this is a slimey hack to get some excel scenario to work the same
  3073. // way it does on NT as it does on Win 95. In this scenario excel
  3074. // is asking for Ms Sans Serif on an HP Laser 4Si. On Win 95 this
  3075. // maps to Arial. However, on NT we map to Univers or some other
  3076. // font before we can even look at Arial as a result what used to
  3077. // print on 3 pages now prints on 6. Since the scenario is used for
  3078. // benchmarking this is undesireable. To fix this we penalize
  3079. // any fonts that are not Arial so that we will at least look at Arial
  3080. // and then choose it.
  3081. // bad news, some customers rely on the first device font matched by bNearMatch()
  3082. // for printing. Without the hack, it picks the first match and returns. With the
  3083. // hack, it picks the last device font matched by bNearMatch() and returns.
  3084. // in oder to make sure that the apps will still get the first device font matched by
  3085. // bNearMatch(), we only update the ppfeBest if this->ulPenaltyTotal < this->ulMaxPenalty.
  3086. if(_wcsicmp( pfeo.pwszFamilyName(), L"Arial"))
  3087. {
  3088. this->ulPenaltyTotal += 1;
  3089. }
  3090. else
  3091. {
  3092. vSetBest(ppfe, TRUE, jCharSet);
  3093. return;
  3094. }
  3095. }
  3096. // keep the first device font that we picked
  3097. if (this->ulPenaltyTotal < this->ulMaxPenalty)
  3098. {
  3099. vSetBest(ppfe, TRUE, jCharSet);
  3100. this->ulMaxPenalty = this->ulPenaltyTotal; // prune the search
  3101. }
  3102. }
  3103. else
  3104. {
  3105. DUMP_REJECTED_FONT(pfeo);
  3106. }
  3107. }
  3108. if (this->ppfeBest)
  3109. {
  3110. // record code page, needed for correct
  3111. // code page to unicode translation
  3112. *pflAboutMatch |= (ulCharsetToCodePage((UINT) (*pflAboutMatch >> 24)) << 8);
  3113. }
  3114. // If we still don't have a device font and this is the generic
  3115. // printer driver then just take the first device font.
  3116. }
  3117. /******************************Public*Routine******************************\
  3118. * MAPPER::vEmergency *
  3119. * *
  3120. * Go through the Engine fonts without regard to name ... *
  3121. * *
  3122. * History: *
  3123. * Fri 05-Mar-1993 08:44:38 by Kirk Olynyk [kirko] *
  3124. * Wrote it. *
  3125. \**************************************************************************/
  3126. VOID MAPPER::vEmergency()
  3127. {
  3128. PFE *ppfe;
  3129. BYTE jCharSet = DEFAULT_CHARSET;
  3130. BYTE jMatchCharset = DEFAULT_CHARSET;
  3131. #if DBG
  3132. if (gflFontDebug & DEBUG_MAPPER)
  3133. {
  3134. WARNING("\n\tMAPPER::vEmergency\n");
  3135. }
  3136. #endif
  3137. PUBLIC_PFTOBJ pftoPublic;
  3138. vReset();
  3139. fl &= ~FM_BIT_DEVICE_FONT;
  3140. ENUMFHOBJ fho(&pftoPublic.pPFT->pfhFamily);
  3141. for
  3142. (
  3143. ppfe = fho.ppfeFirst();
  3144. ppfe;
  3145. ppfe = fho.ppfeNext()
  3146. )
  3147. {
  3148. PFEOBJ pfeo(ppfe);
  3149. if (this->bNearMatch(pfeo,&jCharSet, TRUE)) // called from vEmergency
  3150. {
  3151. DUMP_CHOSEN_FONT(pfeo);
  3152. vSetBest(ppfe, FALSE, jCharSet);
  3153. // bNearMatch modifies jCharSet even if it doesn't find a match
  3154. // so subsquent calls to bNearMatch could change jCharSet to
  3155. // something else. Save a copy for use down below.
  3156. jMatchCharset = jCharSet;
  3157. if (this->ulPenaltyTotal == 0)
  3158. {
  3159. *pflAboutMatch |= (ulCharsetToCodePage((UINT) jCharSet) << 8);
  3160. return;
  3161. }
  3162. this->ulMaxPenalty = this->ulPenaltyTotal; // prune the search
  3163. }
  3164. else
  3165. {
  3166. DUMP_REJECTED_FONT(pfeo);
  3167. }
  3168. }
  3169. // We can actually improve it here.
  3170. // If the device is not a plotter, then we can actually
  3171. // give it any bitmap font.
  3172. // We could attempt to match against any bitmap font.
  3173. if (!this->ppfeBest)
  3174. {
  3175. this->ppfeBest = gppfeMapperDefault;
  3176. this->ulBestTime = gppfeMapperDefault->ulTimeStamp;
  3177. }
  3178. // record the code page, needed for correct
  3179. // code page to unicode translation
  3180. *pflAboutMatch |= (ulCharsetToCodePage((UINT) jMatchCharset) << 8);
  3181. }
  3182. /******************************Public*Routine******************************\
  3183. *
  3184. * PFE * MAPPER::ppfeSynthesizeAMatch (FLONG *pflSim, FLONG *pflAboutMatch, POINTL *pptlSim)
  3185. *
  3186. *
  3187. * Effects: if no exact instance is found, install one on the fly
  3188. *
  3189. * History:
  3190. * 30-Jan-1998 -by- Bodin Dresevic [BodinD]
  3191. * Wrote it.
  3192. \**************************************************************************/
  3193. PFE * MAPPER::ppfeSynthesizeAMatch (FLONG *pflSim, FLONG *pflAboutMatch, POINTL *pptlSim)
  3194. {
  3195. PFE *ppfeRet = NULL;
  3196. DESIGNVECTOR *pdvWish; // dv of the instance we wish to load
  3197. ULONG cjDV;
  3198. ULONG cFonts = 0; // number of fonts faces loaded
  3199. // let us get the pdv:
  3200. if (flMM & FLMM_DV_FROM_NAME) // we got the axes from the name
  3201. {
  3202. // the name takes precedance, ie if we have explicit dv == [UU,VV]
  3203. // as well as dv specified through font's family
  3204. // name of the form foo_XX_YY, we ignore dv in ENUMLOGFONTEXDV
  3205. // and use the one specified by the name, [XX,YY] in this case.
  3206. pdvWish = &dvWish;
  3207. }
  3208. else
  3209. {
  3210. pdvWish = (DESIGNVECTOR *)&pelfwWish->elfDesignVector;
  3211. }
  3212. cjDV = SIZEOFDV(pdvWish->dvNumAxes);
  3213. // for now we do this only if another instance is already loaded
  3214. if (ppfeMMInst)
  3215. {
  3216. // get to the PFF of the other instance, need file path data
  3217. PFFOBJ pffMMInst(ppfeMMInst->pPFF) ;
  3218. PFF *pPFF; // placeholder for the returned PFF
  3219. if (pffMMInst.bValid())
  3220. {
  3221. // need to initialize the private PFT if it is NULL, these on the fly
  3222. // instances are always added to private table
  3223. if (gpPFTPrivate == NULL)
  3224. {
  3225. if (!bInitPrivatePFT())
  3226. {
  3227. return ppfeRet;
  3228. }
  3229. }
  3230. // temp instances go to private table
  3231. PUBLIC_PFTOBJ pfto(gpPFTPrivate);
  3232. if (!pffMMInst.bMemFont())
  3233. {
  3234. if (!pfto.bLoadFonts( pffMMInst.pwszPathname(),
  3235. pffMMInst.cSizeofPaths(),
  3236. pffMMInst.cNumFiles(),
  3237. pdvWish, cjDV,
  3238. &cFonts,
  3239. PFF_STATE_SYNTH_FONT, // flPFF
  3240. &pPFF,
  3241. (FR_PRIVATE | FR_NOT_ENUM), // always
  3242. TRUE, // skip the check if already loaded
  3243. NULL ) ) // peudc
  3244. {
  3245. cFonts = 0;
  3246. }
  3247. if (cFonts)
  3248. {
  3249. GreQuerySystemTime( &PFTOBJ::FontChangeTime );
  3250. }
  3251. }
  3252. }
  3253. else // memory fonts
  3254. {
  3255. RIP("MEMORY FONT CASE NOT IMPLEMENTED\n");
  3256. }
  3257. // now need to get to the pfe of the font that we just added:
  3258. if (cFonts)
  3259. {
  3260. PFFOBJ pffoNewInst(pPFF);
  3261. if (pffoNewInst.bValid())
  3262. {
  3263. if (cFonts == 1)
  3264. {
  3265. ppfeRet = pffoNewInst.ppfe(0);
  3266. }
  3267. else
  3268. {
  3269. // this is either an mm font which has a weight axis,
  3270. // so that normal and bold faces are returned or this is a
  3271. // also a FE mm font, in which case there may be
  3272. // horiz and vertical variances as well. Therefore, in this case
  3273. // we shall have to do mini-mapping process in order to decide which
  3274. // face to return among those returned by by DrvLoadFontFile.
  3275. ULONG iFound = 0;
  3276. ULONG iFace = 0;
  3277. LONG lMinSoFar = LONG_MAX;
  3278. for (iFace = 0; iFace < cFonts; iFace++)
  3279. {
  3280. IFIMETRICS *pifi = pffoNewInst.ppfe(iFace)->pifi;
  3281. IFIOBJ ifio(pifi);
  3282. LONG lDiff = (LONG)pifi->usWinWeight - lWishWeight;
  3283. if (lDiff < 0)
  3284. lDiff = -lDiff;
  3285. // <= on the next line is important because foo and @foo have the same weight
  3286. if (lDiff <= lMinSoFar)
  3287. {
  3288. lMinSoFar = lDiff;
  3289. // If requested font is vertlcal face font, We have to map it to vertical
  3290. // face font
  3291. if (fl & FM_BIT_VERT_FACE_REQUEST)
  3292. {
  3293. if (*ifio.pwszFamilyName() == U_COMMERCIAL_AT)
  3294. {
  3295. iFound = iFace;
  3296. }
  3297. }
  3298. else
  3299. {
  3300. if (*ifio.pwszFamilyName() != U_COMMERCIAL_AT)
  3301. {
  3302. iFound = iFace;
  3303. }
  3304. }
  3305. }
  3306. }
  3307. ppfeRet = pffoNewInst.ppfe(iFound);
  3308. }
  3309. // now that we know that we are returning ok we need to
  3310. // fill in other output fields:
  3311. *pflSim = 0;
  3312. IFIOBJ ifio(ppfeRet->pifi);
  3313. // next check for italic simulations
  3314. if (pelfwWish->elfEnumLogfontEx.elfLogFont.lfItalic)
  3315. {
  3316. // if you get here then the application wants an italicized font
  3317. if (!ifio.bNonSimItalic() && ifio.bSimItalic())
  3318. {
  3319. *pflSim |= FO_SIM_ITALIC;
  3320. }
  3321. }
  3322. // bold simulations
  3323. LONG lPen;
  3324. lPen = ifio.lfNonSimWeight() - lWishWeight;
  3325. if (!(fl & FM_BIT_FW_DONTCARE) && (lPen < 0 ))
  3326. {
  3327. // non simulated font isn't bold enough -> try a simulation
  3328. lPen = -lPen;
  3329. if( (WIN31_BITMAP_EMBOLDEN_CRITERIA(lPen)) &&
  3330. (ifio.pvSimBold() != NULL) )
  3331. {
  3332. *pflSim |= FO_SIM_BOLD;
  3333. }
  3334. }
  3335. UINT CharSet = pelfwWish->elfEnumLogfontEx.elfLogFont.lfCharSet;
  3336. *pflAboutMatch = (FLONG)(CharSet << 24);
  3337. *pflAboutMatch |= (ulCharsetToCodePage(CharSet) << 8);
  3338. pptlSim->x = pptlSim->y = 1;
  3339. }
  3340. }
  3341. }
  3342. return ppfeRet;
  3343. }