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.

1272 lines
38 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: cfont.c
  3. *
  4. * Created: 28-May-1991 13:01:27
  5. * Author: Gilman Wong [gilmanw]
  6. *
  7. * Copyright (c) 1990-1999 Microsoft Corporation
  8. *
  9. *
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. CFONT *pcfCreateCFONT(HDC hdc,PDC_ATTR pDcAttr,UINT iFirst,PVOID pch,UINT c,BOOL bAnsi);
  14. BOOL bFillWidthTableForGTE( HDC, CFONT *, PVOID, UINT, BOOL);
  15. BOOL bFillWidthTableForGCW( HDC, CFONT *, UINT, UINT);
  16. VOID vFreeCFONTCrit(CFONT *pcf);
  17. // If the app deletes a LOCALFONT but one or more of the CFONTs hanging
  18. // of the local font are in use then they will be added to this list.
  19. // anytime we try to allocate a new CFONT we will check the list and
  20. // if there entries on that list we will free them up.
  21. CFONT *pcfDeleteList = (CFONT*) NULL;
  22. /******************************Public*Routine******************************\
  23. * pcfAllocCFONT () *
  24. * *
  25. * Allocates a CFONT. Tries to get one off the free list first. Does not *
  26. * do any initialization. *
  27. * *
  28. * Sun 10-Jan-1993 01:16:04 -by- Charles Whitmer [chuckwh] *
  29. * Wrote it. *
  30. \**************************************************************************/
  31. #ifdef DBGCFONT
  32. int cCfontAlloc = 0;
  33. int cCfontMax = 0;
  34. #endif
  35. int cCfontFree = 0;
  36. CFONT *pcfFreeListCFONT = (CFONT *) NULL;
  37. CFONT *pcfAllocCFONT()
  38. {
  39. CFONT *pcf;
  40. CFONT **ppcf;
  41. // first lets walk the list of deleted fonts and delete any that
  42. ppcf = &pcfDeleteList;
  43. while (*ppcf)
  44. {
  45. if ((*ppcf)->cRef == 0)
  46. {
  47. pcf = (*ppcf);
  48. *ppcf = pcf->pcfNext;
  49. vFreeCFONTCrit(pcf);
  50. }
  51. else
  52. {
  53. ppcf = &(*ppcf)->pcfNext;
  54. }
  55. }
  56. // Try to get one off the free list.
  57. pcf = pcfFreeListCFONT;
  58. if (pcf != (CFONT *) NULL)
  59. {
  60. pcfFreeListCFONT = *((CFONT **) pcf);
  61. --cCfontFree;
  62. }
  63. // Otherwise allocate new memory.
  64. if (pcf == (CFONT *) NULL)
  65. {
  66. pcf = (CFONT *) LOCALALLOC(sizeof(CFONT));
  67. if (pcf == (CFONT *) NULL)
  68. {
  69. GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  70. }
  71. #ifdef DBGCFONT
  72. cCfontAlloc++;
  73. if (cCfontAlloc > cCfontMax)
  74. {
  75. cCfontMax = cCfontAlloc;
  76. DbgPrint("\n\n******************* cCfontMax = %ld\n\n",cCfontMax);
  77. }
  78. #endif
  79. }
  80. return(pcf);
  81. }
  82. /******************************Public*Routine******************************\
  83. * vFreeCFONTCrit (pcf) *
  84. * *
  85. * Frees a CFONT. Actually just puts it on the free list. We assume that *
  86. * we are already in a critical section. *
  87. * *
  88. * Sun 10-Jan-1993 01:20:36 -by- Charles Whitmer [chuckwh] *
  89. * Wrote it. *
  90. \**************************************************************************/
  91. #define MAX_FREE_CFONT 10
  92. VOID vFreeCFONTCrit(CFONT *pcf)
  93. {
  94. ASSERTGDI(pcf != (CFONT *) NULL,"Trying to free NULL CFONT.\n");
  95. if(cCfontFree > MAX_FREE_CFONT)
  96. {
  97. LOCALFREE(pcf);
  98. #ifdef DBGCFONT
  99. cCfontAlloc--;
  100. #endif
  101. }
  102. else
  103. {
  104. *((CFONT **) pcf) = pcfFreeListCFONT;
  105. pcfFreeListCFONT = pcf;
  106. ++cCfontFree;
  107. }
  108. }
  109. /******************************Public*Routine******************************\
  110. * bComputeCharWidths *
  111. * *
  112. * Client side version of GetCharWidth. *
  113. * *
  114. * Sat 16-Jan-1993 04:27:19 -by- Charles Whitmer [chuckwh] *
  115. * Wrote it. *
  116. \**************************************************************************/
  117. BOOL bComputeCharWidths
  118. (
  119. CFONT *pcf,
  120. UINT iFirst,
  121. UINT iLast,
  122. ULONG fl,
  123. PVOID pv
  124. )
  125. {
  126. USHORT *ps;
  127. UINT ii;
  128. switch (fl & (GCW_INT | GCW_16BIT))
  129. {
  130. case GCW_INT: // Get LONG widths.
  131. {
  132. LONG *pl = (LONG *) pv;
  133. LONG fxOverhang = 0;
  134. // Check for Win 3.1 compatibility.
  135. if (fl & GCW_WIN3)
  136. fxOverhang = pcf->wd.sOverhang;
  137. // Do the trivial no-transform case.
  138. if (bIsOneSixteenthEFLOAT(pcf->efDtoWBaseline))
  139. {
  140. fxOverhang += 8; // To round the final result.
  141. // for (ii=iFirst; ii<=iLast; ii++)
  142. // *pl++ = (pcf->sWidth[ii] + fxOverhang) >> 4;
  143. ps = &pcf->sWidth[iFirst];
  144. ii = iLast - iFirst;
  145. unroll_1:
  146. switch(ii)
  147. {
  148. default:
  149. pl[4] = (ps[4] + fxOverhang) >> 4;
  150. case 3:
  151. pl[3] = (ps[3] + fxOverhang) >> 4;
  152. case 2:
  153. pl[2] = (ps[2] + fxOverhang) >> 4;
  154. case 1:
  155. pl[1] = (ps[1] + fxOverhang) >> 4;
  156. case 0:
  157. pl[0] = (ps[0] + fxOverhang) >> 4;
  158. }
  159. if (ii > 4)
  160. {
  161. ii -= 5;
  162. pl += 5;
  163. ps += 5;
  164. goto unroll_1;
  165. }
  166. return(TRUE);
  167. }
  168. // Otherwise use the back transform.
  169. else
  170. {
  171. for (ii=iFirst; ii<=iLast; ii++)
  172. *pl++ = lCvt(pcf->efDtoWBaseline,pcf->sWidth[ii] + fxOverhang);
  173. return(TRUE);
  174. }
  175. }
  176. case GCW_INT+GCW_16BIT: // Get SHORT widths.
  177. {
  178. USHORT *psDst = (USHORT *) pv;
  179. USHORT fsOverhang = 0;
  180. // Check for Win 3.1 compatibility.
  181. if (fl & GCW_WIN3)
  182. fsOverhang = pcf->wd.sOverhang;
  183. // Do the trivial no-transform case.
  184. if (bIsOneSixteenthEFLOAT(pcf->efDtoWBaseline))
  185. {
  186. fsOverhang += 8; // To round the final result.
  187. // for (ii=iFirst; ii<=iLast; ii++)
  188. // *psDst++ = (pcf->sWidth[ii] + fsOverhang) >> 4;
  189. ps = &pcf->sWidth[iFirst];
  190. ii = iLast - iFirst;
  191. unroll_2:
  192. switch(ii)
  193. {
  194. default:
  195. psDst[4] = (ps[4] + fsOverhang) >> 4;
  196. case 3:
  197. psDst[3] = (ps[3] + fsOverhang) >> 4;
  198. case 2:
  199. psDst[2] = (ps[2] + fsOverhang) >> 4;
  200. case 1:
  201. psDst[1] = (ps[1] + fsOverhang) >> 4;
  202. case 0:
  203. psDst[0] = (ps[0] + fsOverhang) >> 4;
  204. }
  205. if (ii > 4)
  206. {
  207. ii -= 5;
  208. psDst += 5;
  209. ps += 5;
  210. goto unroll_2;
  211. }
  212. return(TRUE);
  213. }
  214. // Otherwise use the back transform.
  215. else
  216. {
  217. for (ii=iFirst; ii<=iLast; ii++)
  218. {
  219. *psDst++ = (USHORT)
  220. lCvt
  221. (
  222. pcf->efDtoWBaseline,
  223. (LONG) (pcf->sWidth[ii] + fsOverhang)
  224. );
  225. }
  226. return(TRUE);
  227. }
  228. }
  229. case 0: // Get FLOAT widths.
  230. {
  231. LONG *pe = (LONG *) pv; // Cheat to avoid expensive copies.
  232. EFLOAT_S efWidth,efWidthLogical;
  233. for (ii=iFirst; ii<=iLast; ii++)
  234. {
  235. vFxToEf((LONG) pcf->sWidth[ii],efWidth);
  236. vMulEFLOAT(efWidthLogical,efWidth,pcf->efDtoWBaseline);
  237. *pe++ = lEfToF(efWidthLogical);
  238. }
  239. return(TRUE);
  240. }
  241. }
  242. RIP("bComputeCharWidths: Don't come here!\n");
  243. return(FALSE);
  244. }
  245. /******************************Public*Routine******************************\
  246. * bComputeTextExtent (pldc,pcf,psz,cc,fl,psizl,btype) *
  247. * *
  248. * A quick function to compute text extents on the client side. *
  249. * *
  250. * Thu 14-Jan-1993 04:00:57 -by- Charles Whitmer [chuckwh] *
  251. * Wrote it. *
  252. \**************************************************************************/
  253. BOOL bComputeTextExtent
  254. (
  255. PDC_ATTR pDcAttr,
  256. CFONT *pcf,
  257. LPVOID psz,
  258. int cc,
  259. UINT fl,
  260. SIZE *psizl,
  261. BOOL bAnsi // TRUE is for ANSI, FALSE is for Unicode
  262. )
  263. {
  264. LONG fxBasicExtent;
  265. INT lTextExtra,lBreakExtra,cBreak;
  266. int ii;
  267. BYTE * pc;
  268. LONG fxCharExtra = 0;
  269. LONG fxBreakExtra;
  270. LONG fxExtra = 0;
  271. BOOL bRet = TRUE;
  272. WCHAR * pwc;
  273. lTextExtra = pDcAttr->lTextExtra;
  274. lBreakExtra = pDcAttr->lBreakExtra;
  275. cBreak = pDcAttr->cBreak;
  276. // Compute the basic extent.
  277. if (pcf->wd.sCharInc == 0)
  278. {
  279. fxBasicExtent = 0;
  280. if(bAnsi)
  281. pc = (BYTE *) psz;
  282. else
  283. pwc = (WCHAR *) psz;
  284. ii = cc;
  285. unroll_here:
  286. if(bAnsi)
  287. {
  288. switch (ii)
  289. {
  290. default:
  291. fxBasicExtent += pcf->sWidth[pc[9]];
  292. case 9:
  293. fxBasicExtent += pcf->sWidth[pc[8]];
  294. case 8:
  295. fxBasicExtent += pcf->sWidth[pc[7]];
  296. case 7:
  297. fxBasicExtent += pcf->sWidth[pc[6]];
  298. case 6:
  299. fxBasicExtent += pcf->sWidth[pc[5]];
  300. case 5:
  301. fxBasicExtent += pcf->sWidth[pc[4]];
  302. case 4:
  303. fxBasicExtent += pcf->sWidth[pc[3]];
  304. case 3:
  305. fxBasicExtent += pcf->sWidth[pc[2]];
  306. case 2:
  307. fxBasicExtent += pcf->sWidth[pc[1]];
  308. case 1:
  309. fxBasicExtent += pcf->sWidth[pc[0]];
  310. }
  311. }
  312. else
  313. {
  314. switch (ii)
  315. {
  316. default:
  317. fxBasicExtent += pcf->sWidth[pwc[9]];
  318. case 9:
  319. fxBasicExtent += pcf->sWidth[pwc[8]];
  320. case 8:
  321. fxBasicExtent += pcf->sWidth[pwc[7]];
  322. case 7:
  323. fxBasicExtent += pcf->sWidth[pwc[6]];
  324. case 6:
  325. fxBasicExtent += pcf->sWidth[pwc[5]];
  326. case 5:
  327. fxBasicExtent += pcf->sWidth[pwc[4]];
  328. case 4:
  329. fxBasicExtent += pcf->sWidth[pwc[3]];
  330. case 3:
  331. fxBasicExtent += pcf->sWidth[pwc[2]];
  332. case 2:
  333. fxBasicExtent += pcf->sWidth[pwc[1]];
  334. case 1:
  335. fxBasicExtent += pcf->sWidth[pwc[0]];
  336. }
  337. }
  338. ii -= 10;
  339. if (ii > 0)
  340. {
  341. if(bAnsi)
  342. pc += 10;
  343. else
  344. pwc += 10;
  345. goto unroll_here;
  346. }
  347. }
  348. else
  349. {
  350. // Fixed pitch case.
  351. fxBasicExtent = cc * (LONG) pcf->wd.sCharInc;
  352. }
  353. // Adjust for CharExtra.
  354. if (lTextExtra)
  355. {
  356. int cNoBackup = 0;
  357. fxCharExtra = lCvt(pcf->efM11,lTextExtra);
  358. if (fxCharExtra < 0)
  359. {
  360. // the layout code won't backup a characters past it's origin regardless
  361. // of the value of iTextCharExtra so figure out for how many values
  362. // we will need to ignore fxCharExtra
  363. if (pcf->wd.sCharInc == 0)
  364. {
  365. if(bAnsi)
  366. {
  367. pc = (BYTE *) psz;
  368. for (ii = 0; ii < cc; ii++)
  369. {
  370. if (pcf->sWidth[pc[ii]] + fxCharExtra <= 0)
  371. {
  372. cNoBackup += 1;
  373. }
  374. }
  375. }
  376. else
  377. {
  378. pwc = (WCHAR *) psz;
  379. for (ii = 0; ii < cc; ii++)
  380. {
  381. if (pcf->sWidth[pwc[ii]] + fxCharExtra <= 0)
  382. {
  383. cNoBackup += 1;
  384. }
  385. }
  386. }
  387. }
  388. else if (pcf->wd.sCharInc + fxCharExtra <= 0)
  389. {
  390. cNoBackup = cc;
  391. }
  392. }
  393. if ( (fl & GGTE_WIN3_EXTENT) && (pcf->hdc == 0) // hdc of zero is display DC
  394. && (!(pcf->flInfo & FM_INFO_TECH_STROKE)) )
  395. fxExtra = fxCharExtra * ((lTextExtra > 0) ? cc : (cc - 1));
  396. else
  397. fxExtra = fxCharExtra * (cc - cNoBackup);
  398. }
  399. // Adjust for lBreakExtra.
  400. if (lBreakExtra && cBreak)
  401. {
  402. fxBreakExtra = lCvt(pcf->efM11,lBreakExtra) / cBreak;
  403. // Windows won't let us back up over a break. Set up the BreakExtra
  404. // to just cancel out what we've already got.
  405. if (fxBreakExtra + pcf->wd.sBreak + fxCharExtra < 0)
  406. fxBreakExtra = -(pcf->wd.sBreak + fxCharExtra);
  407. // Add it up for all breaks.
  408. if(bAnsi)
  409. {
  410. pc = (BYTE *) psz;
  411. for (ii=0; ii<cc; ii++)
  412. {
  413. if (*pc++ == pcf->wd.iBreak)
  414. fxExtra += fxBreakExtra;
  415. }
  416. }
  417. else
  418. {
  419. pwc = (WCHAR *) psz;
  420. for (ii=0; ii<cc; ii++)
  421. {
  422. if (*pwc++ == pcf->wd.iBreak)
  423. fxExtra += fxBreakExtra;
  424. }
  425. }
  426. }
  427. // Add in the extra stuff.
  428. fxBasicExtent += fxExtra;
  429. // Add in the overhang for font simulations.
  430. if (fl & GGTE_WIN3_EXTENT)
  431. fxBasicExtent += pcf->wd.sOverhang;
  432. // Transform the result to logical coordinates.
  433. if (bIsOneSixteenthEFLOAT(pcf->efDtoWBaseline))
  434. psizl->cx = (fxBasicExtent + 8) >> 4;
  435. else
  436. psizl->cx = lCvt(pcf->efDtoWBaseline,fxBasicExtent);
  437. psizl->cy = pcf->lHeight;
  438. return bRet;
  439. }
  440. /******************************Public*Routine******************************\
  441. * pcfLocateCFONT (hdc,pDcAttr,iFirst,pch,c)
  442. *
  443. * Locates a CFONT for the given LDC. First we try the CFONT last used by
  444. * the LDC. Then we try to do a mapping ourselves through the LOCALFONT.
  445. * If that fails we create a new one.
  446. *
  447. * Mon 11-Jan-1993 16:18:43 -by- Charles Whitmer [chuckwh]
  448. * Wrote it.
  449. \**************************************************************************/
  450. CFONT *pcfLocateCFONT(
  451. HDC hdc,
  452. PDC_ATTR pDcAttr,
  453. UINT iFirst,
  454. PVOID pch,
  455. UINT c,
  456. BOOL bAnsi)
  457. {
  458. CFONT *pcf = NULL;
  459. LOCALFONT *plf;
  460. ULONG fl;
  461. HANDLE hf;
  462. int i;
  463. WCHAR *pwc;
  464. BYTE *pchar;
  465. if (fFontAssocStatus)
  466. return(pcf);
  467. fl = pDcAttr->ulDirty_;
  468. hf = pDcAttr->hlfntNew;
  469. // Check to make sure that the XFORM is okay. If not return FALSE and
  470. // mark this DC as having slow widths.
  471. if ((fl & SLOW_WIDTHS) || USER_XFORM_DIRTY(pDcAttr) ||
  472. !(pDcAttr->mxWtoD.flAccel & XFORM_SCALE))
  473. {
  474. if (!(fl & SLOW_WIDTHS))
  475. {
  476. if (!NtGdiComputeXformCoefficients(hdc))
  477. pDcAttr->ulDirty_ |= SLOW_WIDTHS;
  478. }
  479. if (pDcAttr->ulDirty_ & SLOW_WIDTHS)
  480. return(pcf);
  481. }
  482. if(guintDBCScp != 0xFFFFFFFF)
  483. {
  484. DWORD dwCodePage = GetCodePage(hdc);
  485. //If this is a DBCS charset but not our native one then we can not
  486. //compute widths and extent quickly, because gpwcDBCSCharSet[]
  487. //array is computed based on our NATIVE_CODEPAGE using IsDBCSLeadByte()
  488. //function.
  489. if ((guintDBCScp != dwCodePage) && IS_ANY_DBCS_CODEPAGE(dwCodePage))
  490. {
  491. pDcAttr->ulDirty_ |= SLOW_WIDTHS;
  492. return pcf;
  493. }
  494. }
  495. // now find the font
  496. PSHARED_GET_VALIDATE(plf,hf,LFONT_TYPE);
  497. if (plf == NULL)
  498. {
  499. // If there is no local font then this must be a public font or one
  500. // that's been deleted while still being selected into a DC. If it's a
  501. // stockfont let's try to find it.
  502. if ((hf != NULL) &&
  503. !(pGdiSharedHandleTable[HANDLE_TO_INDEX(hf)].Flags & HMGR_ENTRY_LAZY_DEL) &&
  504. (pDcAttr->iMapMode == MM_TEXT) &&
  505. (fl & DC_PRIMARY_DISPLAY))
  506. {
  507. for (i = 0; i < MAX_PUBLIC_CFONT; ++i)
  508. if (pGdiSharedMemory->acfPublic[i].hf == hf)
  509. break;
  510. // if we didn't find one, try to set one up
  511. if (i == MAX_PUBLIC_CFONT)
  512. {
  513. // this will fill in both the text metrics and widths
  514. i = NtGdiSetupPublicCFONT(hdc,NULL,0);
  515. }
  516. // have we found one yet
  517. if ((i >= 0) && (i < MAX_PUBLIC_CFONT))
  518. {
  519. // make sure mapping table is initialized before we give out a
  520. // public CFONT
  521. if ((gpwcANSICharSet == (WCHAR *) NULL) && !bGetANSISetMap())
  522. {
  523. return((CFONT *) NULL);
  524. }
  525. pcf = &pGdiSharedMemory->acfPublic[i];
  526. }
  527. }
  528. else
  529. {
  530. pDcAttr->ulDirty_ |= SLOW_WIDTHS;
  531. }
  532. }
  533. else if (plf->fl & LF_HARDWAY)
  534. {
  535. // If the logfont has non-zero escapement or orientation then bail out.
  536. // Stock fonts will never have non-zero escapments or orientation so we can do
  537. // this now.
  538. pDcAttr->ulDirty_ |= SLOW_WIDTHS;
  539. }
  540. else
  541. {
  542. BOOL bRet = FALSE;
  543. // next loop through all the CFONTs associated with this LOGFONT to see if
  544. // we can find a match.
  545. for (pcf = plf->pcf; pcf ; pcf = pcf->pcfNext)
  546. {
  547. // if the DC's are both display DC's or the same printer DC and the
  548. // transform's coefficients match then we've got a winner.
  549. if ((((pcf->hdc == 0) && (fl & DC_PRIMARY_DISPLAY)) || (pcf->hdc == hdc)) &&
  550. bEqualEFLOAT(pcf->efM11, pDcAttr->mxWtoD.efM11) &&
  551. bEqualEFLOAT(pcf->efM22, pDcAttr->mxWtoD.efM22))
  552. {
  553. // update the refcount so we don't accidentally delete this CFONT while
  554. // we are using it.
  555. INC_CFONT_REF(pcf);
  556. break;
  557. }
  558. }
  559. if (pcf == NULL)
  560. {
  561. // don't do this under semaphore because pcfCreateCFONT will call off to
  562. // font drivers which in turn could access a file on the net and take a
  563. // very long time
  564. pcf = pcfCreateCFONT(hdc,pDcAttr,iFirst,pch,c,bAnsi);
  565. if (pcf)
  566. {
  567. // next update the REFCOUNT of the CFONT
  568. pcf->hf = hf;
  569. pcf->hdc = (fl & DC_PRIMARY_DISPLAY) ? (HDC) 0 : (HDC) hdc;
  570. // now that we have a CFONT link it in to the chain off of this
  571. // LOCALFONT
  572. pcf->pcfNext = plf->pcf;
  573. plf->pcf = pcf;
  574. }
  575. }
  576. else
  577. {
  578. // At this point we have a non-NULL pcf which is referenced by the LDC.
  579. // We must check it to see if it contains the widths we need.
  580. if (pcf->fl & CFONT_COMPLETE)
  581. return(pcf);
  582. if (pch != NULL)
  583. {
  584. // Make sure we have widths for all the chars in the string.
  585. if (pcf->fl & CFONT_CACHED_WIDTHS)
  586. {
  587. if(bAnsi)
  588. {
  589. INT ic = (INT)c;
  590. pchar = (BYTE *) pch;
  591. if (pcf->fl & CFONT_DBCS)
  592. {
  593. // we won't have local width cache for DBCS chars in sWidth[] array.
  594. for (;ic > 0; ic--,pchar++)
  595. {
  596. if (gpwcDBCSCharSet[*pchar] == 0xffff)
  597. {
  598. // skip DBCS chars
  599. if (ic > 0)
  600. {
  601. ic--;
  602. pchar++;
  603. }
  604. }
  605. else if (pcf->sWidth[*pchar] == NO_WIDTH)
  606. {
  607. break;
  608. }
  609. }
  610. if (ic < 0)
  611. c = 0;
  612. else
  613. c = (UINT)ic;
  614. }
  615. else
  616. {
  617. for (; c && (pcf->sWidth[*pchar] != NO_WIDTH); c--,pchar++)
  618. {}
  619. }
  620. pch = (PVOID) pchar;
  621. }
  622. else
  623. {
  624. pwc = (WCHAR *) pch;
  625. for (; c && (pcf->sWidth[*pwc] != NO_WIDTH); c--,pwc++)
  626. {}
  627. pch = (PVOID) pwc;
  628. }
  629. }
  630. if (c)
  631. {
  632. bRet = bFillWidthTableForGTE(hdc, pcf, pch, c, bAnsi);
  633. }
  634. }
  635. else
  636. {
  637. // Make sure we have widths for the array requested.
  638. if (pcf->fl & CFONT_CACHED_WIDTHS)
  639. {
  640. if (!(iFirst & 0xffffff00) && !((iFirst + c) & 0xffffff00))
  641. {
  642. for (; c && (pcf->sWidth[iFirst] != NO_WIDTH); c--,iFirst++)
  643. {}
  644. }
  645. }
  646. if (c)
  647. {
  648. bRet = bFillWidthTableForGCW(hdc, pcf, iFirst, c);
  649. }
  650. }
  651. if (bRet == GDI_ERROR)
  652. {
  653. // Something bad happened while trying to fill. To avoid hitting this
  654. // problem again on the next call, we mark the LDC as slow.
  655. DEC_CFONT_REF(pcf);
  656. pDcAttr->ulDirty_ |= SLOW_WIDTHS;
  657. pcf = NULL;
  658. }
  659. }
  660. }
  661. return(pcf);
  662. }
  663. /******************************Public*Routine******************************\
  664. * pcfCreateCFONT (pldc,iFirst,pch,c) *
  665. * *
  666. * Allocate and initialize a new CFONT. *
  667. * *
  668. * History: *
  669. * Tue 19-Jan-1993 16:16:03 -by- Charles Whitmer [chuckwh] *
  670. * Wrote it. *
  671. \**************************************************************************/
  672. EFLOAT_S ef_1 = EFLOAT_1;
  673. CFONT *pcfCreateCFONT(
  674. HDC hdc,
  675. PDC_ATTR pDcAttr,
  676. UINT iFirst,
  677. PVOID pch,
  678. UINT c,
  679. BOOL bAnsi)
  680. {
  681. CFONT *pcfNew;
  682. BOOL bRet;
  683. // Make sure we have the UNICODE translation of the ANSI character set.
  684. // We'll create this once and keep it around to avoid lots of conversion.
  685. if ((gpwcANSICharSet == (WCHAR *) NULL) && !bGetANSISetMap())
  686. return((CFONT *) NULL);
  687. // Allocate a new CFONT to hold the results.
  688. pcfNew = pcfAllocCFONT();
  689. if (pcfNew != (CFONT *) NULL)
  690. {
  691. pcfNew->timeStamp = pGdiSharedMemory->timeStamp;
  692. pcfNew->fl = 0;
  693. // if the default code page is a DBCS code page then we may need to mark this
  694. // as a DBCS font
  695. if(guintDBCScp != 0xFFFFFFFF)
  696. {
  697. DWORD dwCodePage = GetCodePage(hdc);
  698. //If this is a DBCS charset but not our native one then we can not
  699. //compute widths and extent quickly, because gpwcDBCSCharSet[]
  700. //array is computed based on our NATIVE_CODEPAGE using IsDBCSLeadByte()
  701. //function. We should never get here because we will be doing a check
  702. //higher up to make sure the codepage of the font in the DC is matches
  703. //the current DBCS code page
  704. if(guintDBCScp == dwCodePage)
  705. {
  706. pcfNew->fl = CFONT_DBCS;
  707. }
  708. ASSERTGDI(guintDBCScp == dwCodePage || !IS_ANY_DBCS_CODEPAGE(dwCodePage),
  709. "pcfLocateCFONT called on non-native DBCS font\n");
  710. }
  711. pcfNew->cRef = 1;
  712. // Compute the back transforms.
  713. pcfNew->efM11 = pDcAttr->mxWtoD.efM11;
  714. pcfNew->efM22 = pDcAttr->mxWtoD.efM22;
  715. efDivEFLOAT(pcfNew->efDtoWBaseline,ef_1,pcfNew->efM11);
  716. vAbsEFLOAT(pcfNew->efDtoWBaseline);
  717. efDivEFLOAT(pcfNew->efDtoWAscent,ef_1,pcfNew->efM22);
  718. vAbsEFLOAT(pcfNew->efDtoWAscent);
  719. // Send over a request.
  720. if (pch != NULL)
  721. {
  722. bRet = bFillWidthTableForGTE(hdc,pcfNew,pch,c,bAnsi);
  723. }
  724. else if (c)
  725. {
  726. bRet = bFillWidthTableForGCW(hdc,pcfNew,iFirst,c);
  727. }
  728. else
  729. {
  730. // probably just creating a cache entry for text metrics.
  731. // FALSE just means haven't gotten all the widths. Note
  732. // that GDI_ERROR is actualy -1
  733. bRet = FALSE;
  734. }
  735. // Clean up failed requests.
  736. if (bRet == GDI_ERROR)
  737. {
  738. // we will not attempt to create cfont if this failed once in the
  739. // past, because the chances are it will fail again with this logfont.
  740. // It turns out it is costly to figure out that cfont creation is going to fail
  741. // so we record this by setting LF_NO_CFONT flag to avoid another attempt at
  742. // creating cfont.
  743. pDcAttr->ulDirty_ |= SLOW_WIDTHS;
  744. vFreeCFONTCrit(pcfNew);
  745. pcfNew = NULL;
  746. }
  747. }
  748. return(pcfNew);
  749. }
  750. /******************************Public*Routine******************************\
  751. * bFillWidthTableForGCW *
  752. * *
  753. * Requests ANSI character widths from the server for a call to *
  754. * GetCharWidthA. iFirst and c specify the characters needed by the API *
  755. * call, the server must return these. In addition, it may be prudent to *
  756. * fill in a whole table of 256 widths at psWidthCFONT. We will fill in *
  757. * the whole table and a WIDTHDATA structure if the pointer pwd is non-NULL.*
  758. * *
  759. * History: *
  760. * Tue 19-Jan-1993 14:29:31 -by- Charles Whitmer [chuckwh] *
  761. * Wrote it. *
  762. \**************************************************************************/
  763. BOOL bFillWidthTableForGCW
  764. (
  765. HDC hdc,
  766. CFONT *pcf,
  767. UINT iFirst,
  768. UINT c
  769. )
  770. {
  771. BOOL bRet = GDI_ERROR;
  772. BOOL bDBCS = pcf->fl & CFONT_DBCS;
  773. WCHAR *pwcBuf;
  774. UINT c1,c2;
  775. WIDTHDATA *pwd;
  776. if(iFirst > 256)
  777. {
  778. // this is possible for DBCS fonts, just get all the widths
  779. iFirst = 0;
  780. c = 256;
  781. }
  782. if (pcf->fl & CFONT_CACHED_WIDTHS)
  783. {
  784. // Not the first time. Just get the important widths.
  785. c1 = c;
  786. c2 = 0;
  787. pwd = NULL;
  788. }
  789. else
  790. {
  791. // Get the whole table, but put the important widths at the start.
  792. c2 = iFirst;
  793. c1 = 256 - c2; // only c of those are "important"
  794. pwd = &pcf->wd;
  795. }
  796. pwcBuf = (WCHAR *)LocalAlloc(LMEM_FIXED,
  797. (c1+c2) * (sizeof(WCHAR)+sizeof(USHORT)));
  798. if (pwcBuf)
  799. {
  800. USHORT *psWidths = pwcBuf + c1+c2;
  801. RtlCopyMemory(pwcBuf,
  802. (bDBCS) ? (PBYTE) &gpwcDBCSCharSet[iFirst] :
  803. (PBYTE) &gpwcANSICharSet[iFirst],
  804. c1*sizeof(WCHAR));
  805. if (c2)
  806. {
  807. RtlCopyMemory(&pwcBuf[c1],
  808. (bDBCS) ? (PBYTE) &gpwcDBCSCharSet[0] :
  809. (PBYTE) &gpwcANSICharSet[0],
  810. c2*sizeof(WCHAR));
  811. }
  812. LEAVECRITICALSECTION(&semLocal);
  813. bRet = NtGdiGetWidthTable( hdc, // The DC
  814. c, // Number of special characters
  815. pwcBuf, // Unicode characters requested
  816. c1+c2, // Number of non-special chars
  817. psWidths, // Buffer to get widths returned
  818. pwd, // Width data
  819. &pcf->flInfo); // Font info flags
  820. ENTERCRITICALSECTION(&semLocal);
  821. if (bRet != GDI_ERROR)
  822. {
  823. if (!(pcf->fl & CFONT_CACHED_WIDTHS))
  824. {
  825. // mark this cfont as having some widths
  826. pcf->fl |= CFONT_CACHED_WIDTHS;
  827. // Precompute the height.
  828. pcf->lHeight = lCvt(pcf->efDtoWAscent,(LONG) pcf->wd.sHeight);
  829. }
  830. if (bRet && ((c1+c2) >= 256))
  831. pcf->fl |= CFONT_COMPLETE;
  832. // Copy the widths into the CFONT table.
  833. RtlCopyMemory(
  834. &pcf->sWidth[iFirst], psWidths, c1 * sizeof(USHORT));
  835. if (c2)
  836. {
  837. RtlCopyMemory (
  838. pcf->sWidth, &psWidths[c1], c2 * sizeof(USHORT));
  839. }
  840. }
  841. LocalFree(pwcBuf);
  842. }
  843. return(bRet);
  844. }
  845. /******************************Public*Routine******************************\
  846. * bFillWidthTableForGTE
  847. *
  848. * Requests ANSI character widths from the server for a call to
  849. * GetTextExtentA. pch specifies the string from the API call. The
  850. * server must return widths for these characters. In addition, it may be
  851. * prudent to fill in a whole table of 256 widths at psWidthCFONT. We will
  852. * fill in the whole table and a WIDTHDATA structure if the pointer pwd is
  853. * non-NULL.
  854. *
  855. * History:
  856. * Tue 13-Jun-1995 14:29:31 -by- Gerrit van Wingerden [gerritv]
  857. * Converted for kernel mode.
  858. * Tue 19-Jan-1993 14:29:31 -by- Charles Whitmer [chuckwh]
  859. * Wrote it.
  860. \**************************************************************************/
  861. BOOL bFillWidthTableForGTE
  862. (
  863. HDC hdc,
  864. CFONT *pcf,
  865. PVOID pch,
  866. UINT c,
  867. BOOL bAnsi
  868. )
  869. {
  870. BOOL bRet = GDI_ERROR;
  871. BOOL bDBCS = pcf->fl & CFONT_DBCS;
  872. UINT ii;
  873. UINT c1;
  874. WCHAR *pwcBuf;
  875. WCHAR *pwcXlat = (bDBCS) ? gpwcDBCSCharSet : gpwcANSICharSet;
  876. WIDTHDATA *pwd;
  877. if (pcf->fl & CFONT_CACHED_WIDTHS)
  878. {
  879. c1 = c;
  880. pwd = NULL;
  881. }
  882. else
  883. {
  884. c1 = c+256;
  885. pwd = &pcf->wd;
  886. }
  887. pwcBuf = LocalAlloc(LMEM_FIXED,c1*(sizeof(WCHAR)+sizeof(USHORT)));
  888. if( pwcBuf )
  889. {
  890. WCHAR *pwc = pwcBuf;
  891. USHORT *psWidths = pwcBuf + c1;
  892. if(bAnsi)
  893. {
  894. for( ii = 0; ii < c; ii++ )
  895. {
  896. *pwc++ = pwcXlat[((BYTE *)pch)[ii]];
  897. }
  898. }
  899. else
  900. {
  901. RtlCopyMemory((PBYTE)pwc, (PBYTE) pch, c * sizeof(WCHAR));
  902. pwc += c;
  903. }
  904. if (pwd != (WIDTHDATA *) NULL)
  905. {
  906. // Request the whole table, too.
  907. RtlCopyMemory((PBYTE)pwc,
  908. (bDBCS) ? (PBYTE) &gpwcDBCSCharSet[0] :
  909. (PBYTE) &gpwcANSICharSet[0],
  910. 256*sizeof(WCHAR));
  911. }
  912. LEAVECRITICALSECTION(&semLocal);
  913. bRet = NtGdiGetWidthTable( hdc, // the DC
  914. c, // number of special characters
  915. pwcBuf, // the requested chars in Unicode
  916. c1, // total number of characters
  917. psWidths, // the actual width
  918. pwd, // useful width data
  919. &pcf->flInfo);// font info flags
  920. ENTERCRITICALSECTION(&semLocal);
  921. if (bRet != GDI_ERROR)
  922. {
  923. if (!(pcf->fl & CFONT_CACHED_WIDTHS))
  924. {
  925. // mark this cfont as having some widths
  926. pcf->fl |= CFONT_CACHED_WIDTHS;
  927. // Precompute the height.
  928. pcf->lHeight = lCvt(pcf->efDtoWAscent,(LONG) pcf->wd.sHeight);
  929. if (bRet) // bFillWidthTableForGTE() tries to get width for all 0x00 to 0xff only at the first time
  930. pcf->fl |= CFONT_COMPLETE;
  931. }
  932. if( pwd != (WIDTHDATA *) NULL )
  933. RtlCopyMemory( pcf->sWidth,&psWidths[c],256 * sizeof(USHORT));
  934. // Write the hard widths into the table too.
  935. if (bAnsi)
  936. {
  937. for (ii=0; ii<c; ii++)
  938. pcf->sWidth[((BYTE *)pch)[ii]] = psWidths[ii];
  939. }
  940. else
  941. {
  942. for (ii=0; ii<c; ii++)
  943. pcf->sWidth[((WCHAR *)pch)[ii]] = psWidths[ii];
  944. }
  945. }
  946. LocalFree( pwcBuf );
  947. }
  948. return(bRet);
  949. }
  950. /***************************************************************************\
  951. * GetCharDimensions
  952. *
  953. * This function loads the Textmetrics of the font currently selected into
  954. * the hDC and returns the Average char width of the font; Pl Note that the
  955. * AveCharWidth value returned by the Text metrics call is wrong for
  956. * proportional fonts. So, we compute them On return, lpTextMetrics contains
  957. * the text metrics of the currently selected font.
  958. *
  959. * Legacy code imported from USER.
  960. *
  961. * History:
  962. * 10-Nov-1993 mikeke Created
  963. \***************************************************************************/
  964. int GdiGetCharDimensions(
  965. HDC hdc,
  966. TEXTMETRICW *lptm,
  967. LPINT lpcy)
  968. {
  969. TEXTMETRICW tm;
  970. PLDC pldc;
  971. PDC_ATTR pDcAttr;
  972. CFONT *pcf;
  973. int iAve;
  974. PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
  975. if (!pDcAttr)
  976. {
  977. WARNING("GdiGetCharDimensions: invalid DC");
  978. return(0);
  979. }
  980. // find the local font or create one
  981. if (lptm == NULL)
  982. lptm = &tm;
  983. // now find the metrics
  984. ENTERCRITICALSECTION(&semLocal);
  985. pcf = pcfLocateCFONT(hdc,pDcAttr,0,(PVOID)NULL,0, TRUE);
  986. if (!bGetTextMetricsWInternal(hdc, (TMW_INTERNAL *)lptm,sizeof(*lptm), pcf))
  987. {
  988. LEAVECRITICALSECTION(&semLocal);
  989. return(0);
  990. }
  991. LEAVECRITICALSECTION(&semLocal);
  992. if (lpcy != NULL)
  993. *lpcy = lptm->tmHeight;
  994. // If fixed width font
  995. if (lptm->tmPitchAndFamily & TMPF_FIXED_PITCH)
  996. {
  997. if (pcf && (pcf->fl & CFONT_CACHED_AVE))
  998. {
  999. iAve = (int)pcf->ulAveWidth;
  1000. }
  1001. else
  1002. {
  1003. SIZE size;
  1004. static WCHAR wszAvgChars[] =
  1005. L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  1006. // Change from tmAveCharWidth. We will calculate a true average
  1007. // as opposed to the one returned by tmAveCharWidth. This works
  1008. // better when dealing with proportional spaced fonts.
  1009. // legacy from USER so can't change this.
  1010. if(!GetTextExtentPointW(hdc, wszAvgChars,
  1011. (sizeof(wszAvgChars) / sizeof(WCHAR)) - 1,
  1012. &size))
  1013. {
  1014. WARNING("GetCharDimension: GetTextExtentPointW failed\n");
  1015. return(0);
  1016. }
  1017. ASSERTGDI(size.cx,
  1018. "GetCharDimension: GetTextExtentPointW return 0 width string\n");
  1019. iAve = ((size.cx / 26) + 1) / 2; // round up
  1020. // if we have a pcf, let's cache it
  1021. if (pcf)
  1022. {
  1023. // if it is a public font, we need to go to the kernel because
  1024. // the pcf is read only here.
  1025. if (pcf->fl & CFONT_PUBLIC)
  1026. {
  1027. NtGdiSetupPublicCFONT(NULL,(HFONT)pcf->hf,(ULONG)iAve);
  1028. }
  1029. else
  1030. {
  1031. pcf->ulAveWidth = (ULONG)iAve;
  1032. pcf->fl |= CFONT_CACHED_AVE;
  1033. }
  1034. }
  1035. }
  1036. }
  1037. else
  1038. {
  1039. iAve = lptm->tmAveCharWidth;
  1040. }
  1041. // pcfLocateCFONT added a reference so now we need to remove it
  1042. if (pcf)
  1043. {
  1044. DEC_CFONT_REF(pcf);
  1045. }
  1046. return(iAve);
  1047. }