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.

938 lines
28 KiB

  1. /*++
  2. Copyright (c) 1985 - 1999, Microsoft Corporation
  3. Module Name:
  4. foncache.c
  5. Abstract:
  6. This file is EUDC font cache
  7. Author:
  8. Kazuhiko Matsubara 21-June-1994
  9. Revision History:
  10. Notes:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #if defined(FE_SB)
  15. VOID
  16. RebaseFontImageList(
  17. IN PFONT_IMAGE NewFontImage,
  18. IN PBYTE OldFontImage
  19. )
  20. {
  21. PLIST_ENTRY ImageList;
  22. PBYTE BaseImage = (PBYTE)NewFontImage;
  23. do {
  24. ImageList = &NewFontImage->ImageList;
  25. if (ImageList->Blink)
  26. ImageList->Blink = (PLIST_ENTRY)((PBYTE)ImageList->Blink - OldFontImage + BaseImage);
  27. if (ImageList->Flink)
  28. ImageList->Flink = (PLIST_ENTRY)((PBYTE)ImageList->Flink - OldFontImage + BaseImage);
  29. } while (NewFontImage = (PFONT_IMAGE)ImageList->Flink);
  30. }
  31. ULONG
  32. CreateFontCache(
  33. OUT PFONT_CACHE_INFORMATION *FontCache
  34. )
  35. {
  36. //
  37. // allocate font cache data
  38. //
  39. *FontCache = ConsoleHeapAlloc(HEAP_ZERO_MEMORY,sizeof(FONT_CACHE_INFORMATION));
  40. if (*FontCache == NULL) {
  41. return (ULONG)STATUS_NO_MEMORY;
  42. }
  43. return (ULONG)(STATUS_SUCCESS);
  44. }
  45. ULONG
  46. DestroyFontCache(
  47. IN PFONT_CACHE_INFORMATION FontCache
  48. )
  49. {
  50. if (FontCache != NULL)
  51. {
  52. PFONT_HIGHLOW_OFFSET FontOffsetHighLow;
  53. PFONT_LOW_OFFSET FontOffsetLow;
  54. PFONT_IMAGE FontImage;
  55. UINT i, j, k;
  56. for (i=0;
  57. i < sizeof(FontCache->FontTable.FontOffsetHighHigh)/sizeof(PFONT_HIGHLOW_OFFSET);
  58. i++)
  59. {
  60. if (FontOffsetHighLow = FontCache->FontTable.FontOffsetHighHigh[i])
  61. {
  62. for (j=0;
  63. j < sizeof(FontOffsetHighLow->FontOffsetHighLow)/sizeof(PFONT_LOW_OFFSET);
  64. j++)
  65. {
  66. if (FontOffsetLow = FontOffsetHighLow->FontOffsetHighLow[j])
  67. {
  68. for (k=0;
  69. k < sizeof(FontOffsetLow->FontOffsetLow)/sizeof(PFONT_IMAGE);
  70. k++)
  71. {
  72. if (FontImage = FontOffsetLow->FontOffsetLow[k])
  73. {
  74. ConsoleHeapFree(FontImage);
  75. }
  76. }
  77. ConsoleHeapFree(FontOffsetLow);
  78. }
  79. }
  80. ConsoleHeapFree(FontOffsetHighLow);
  81. }
  82. }
  83. if (FontCache->BaseImageBits) {
  84. ConsoleHeapFree(FontCache->BaseImageBits);
  85. }
  86. ConsoleHeapFree(FontCache);
  87. }
  88. return (ULONG)(STATUS_SUCCESS);
  89. }
  90. ULONG
  91. RebaseFontCache(
  92. IN PFONT_CACHE_INFORMATION FontCache,
  93. IN PBYTE OldBaseImage
  94. )
  95. {
  96. if (FontCache != NULL)
  97. {
  98. PFONT_HIGHLOW_OFFSET FontOffsetHighLow;
  99. PFONT_LOW_OFFSET FontOffsetLow;
  100. PFONT_IMAGE FontImage;
  101. UINT i, j, k;
  102. for (i=0;
  103. i < sizeof(FontCache->FontTable.FontOffsetHighHigh)/sizeof(PFONT_HIGHLOW_OFFSET);
  104. i++)
  105. {
  106. if (FontOffsetHighLow = FontCache->FontTable.FontOffsetHighHigh[i])
  107. {
  108. for (j=0;
  109. j < sizeof(FontOffsetHighLow->FontOffsetHighLow)/sizeof(PFONT_LOW_OFFSET);
  110. j++)
  111. {
  112. if (FontOffsetLow = FontOffsetHighLow->FontOffsetHighLow[j])
  113. {
  114. for (k=0;
  115. k < sizeof(FontOffsetLow->FontOffsetLow)/sizeof(PFONT_IMAGE);
  116. k++)
  117. {
  118. if (FontImage = FontOffsetLow->FontOffsetLow[k])
  119. {
  120. LIST_ENTRY ImageList;
  121. do {
  122. ImageList = FontImage->ImageList;
  123. if (FontImage->ImageBits) {
  124. FontImage->ImageBits = FontImage->ImageBits - OldBaseImage
  125. + FontCache->BaseImageBits;
  126. }
  127. } while (FontImage = (PFONT_IMAGE)ImageList.Flink);
  128. }
  129. }
  130. }
  131. }
  132. }
  133. }
  134. }
  135. return (ULONG)(STATUS_SUCCESS);
  136. }
  137. #define CALC_BITMAP_BITS_FOR_X( FontSizeX, dwAlign ) \
  138. ( ( ( FontSizeX * BITMAP_BITS_PIXEL + (dwAlign-1) ) & ~(dwAlign-1)) >> BITMAP_ARRAY_BYTE )
  139. DWORD
  140. CalcBitmapBufferSize(
  141. IN COORD FontSize,
  142. IN DWORD dwAlign
  143. )
  144. {
  145. DWORD uiCount;
  146. uiCount = CALC_BITMAP_BITS_FOR_X(FontSize.X,
  147. (dwAlign==BYTE_ALIGN ? BITMAP_BITS_BYTE_ALIGN : BITMAP_BITS_WORD_ALIGN));
  148. uiCount = uiCount * BITMAP_PLANES * FontSize.Y;
  149. return uiCount;
  150. }
  151. VOID
  152. AlignCopyMemory(
  153. OUT PBYTE pDestBits,
  154. IN DWORD dwDestAlign,
  155. IN PBYTE pSrcBits,
  156. IN DWORD dwSrcAlign,
  157. IN COORD FontSize
  158. )
  159. {
  160. DWORD dwDestBufferSize;
  161. COORD coord;
  162. if (dwDestAlign == dwSrcAlign) {
  163. dwDestBufferSize = CalcBitmapBufferSize(FontSize, dwDestAlign);
  164. RtlCopyMemory(pDestBits, pSrcBits, dwDestBufferSize);
  165. return;
  166. }
  167. switch (dwDestAlign) {
  168. default:
  169. case WORD_ALIGN:
  170. switch (dwSrcAlign) {
  171. default:
  172. //
  173. // pDest = WORD, pSrc = WORD
  174. //
  175. case WORD_ALIGN:
  176. dwDestBufferSize = CalcBitmapBufferSize(FontSize, dwDestAlign);
  177. RtlCopyMemory(pDestBits, pSrcBits, dwDestBufferSize);
  178. break;
  179. //
  180. // pDest = WORD, pSrc = BYTE
  181. //
  182. case BYTE_ALIGN:
  183. dwDestBufferSize = CalcBitmapBufferSize(FontSize, dwDestAlign);
  184. if (((FontSize.X % BITMAP_BITS_BYTE_ALIGN) == 0) &&
  185. ((FontSize.X % BITMAP_BITS_WORD_ALIGN) == 0) ) {
  186. RtlCopyMemory(pDestBits, pSrcBits, dwDestBufferSize);
  187. }
  188. else {
  189. RtlZeroMemory(pDestBits, dwDestBufferSize);
  190. for (coord.Y=0; coord.Y < FontSize.Y; coord.Y++) {
  191. for (coord.X=0;
  192. coord.X < CALC_BITMAP_BITS_FOR_X(FontSize.X, BITMAP_BITS_BYTE_ALIGN);
  193. coord.X++) {
  194. *pDestBits++ = *pSrcBits++;
  195. }
  196. if (CALC_BITMAP_BITS_FOR_X(FontSize.X, BITMAP_BITS_BYTE_ALIGN) & 1)
  197. pDestBits++;
  198. }
  199. }
  200. break;
  201. }
  202. break;
  203. case BYTE_ALIGN:
  204. switch (dwSrcAlign) {
  205. //
  206. // pDest = BYTE, pSrc = BYTE
  207. //
  208. case BYTE_ALIGN:
  209. dwDestBufferSize = CalcBitmapBufferSize(FontSize, dwDestAlign);
  210. RtlCopyMemory(pDestBits, pSrcBits, dwDestBufferSize);
  211. break;
  212. default:
  213. //
  214. // pDest = BYTE, pSrc = WORD
  215. //
  216. case WORD_ALIGN:
  217. dwDestBufferSize = CalcBitmapBufferSize(FontSize, dwDestAlign);
  218. if (((FontSize.X % BITMAP_BITS_BYTE_ALIGN) == 0) &&
  219. ((FontSize.X % BITMAP_BITS_WORD_ALIGN) == 0) ) {
  220. RtlCopyMemory(pDestBits, pSrcBits, dwDestBufferSize);
  221. }
  222. else {
  223. RtlZeroMemory(pDestBits, dwDestBufferSize);
  224. for (coord.Y=0; coord.Y < FontSize.Y; coord.Y++) {
  225. for (coord.X=0;
  226. coord.X < CALC_BITMAP_BITS_FOR_X(FontSize.X, BITMAP_BITS_BYTE_ALIGN);
  227. coord.X++) {
  228. *pDestBits++ = *pSrcBits++;
  229. }
  230. if (CALC_BITMAP_BITS_FOR_X(FontSize.X, BITMAP_BITS_BYTE_ALIGN) & 1)
  231. pSrcBits++;
  232. }
  233. }
  234. break;
  235. }
  236. break;
  237. }
  238. }
  239. NTSTATUS
  240. GetStretchImage(
  241. IN COORD FontSize,
  242. IN PFONT_IMAGE FontImage,
  243. OUT PFONT_IMAGE *pFontImage
  244. )
  245. {
  246. PFONT_IMAGE NearFont;
  247. DWORD Find;
  248. COORD FontDelta;
  249. HDC hDC;
  250. HDC hSrcMemDC, hDestMemDC;
  251. HBITMAP hSrcBmp, hDestBmp;
  252. DWORD BufferSize;
  253. NTSTATUS Status = STATUS_NO_MEMORY;
  254. Find = (DWORD)-1;
  255. NearFont = NULL;
  256. do {
  257. FontDelta.X = (SHORT) abs(FontSize.X - FontImage->FontSize.X);
  258. FontDelta.Y = (SHORT) abs(FontSize.Y - FontImage->FontSize.Y);
  259. if (Find > (DWORD)(FontDelta.X + FontDelta.Y))
  260. {
  261. Find = (DWORD)(FontDelta.X + FontDelta.Y);
  262. NearFont = FontImage;
  263. }
  264. }
  265. while (FontImage = (PFONT_IMAGE)FontImage->ImageList.Flink);
  266. if (NearFont == NULL)
  267. return STATUS_ACCESS_DENIED;
  268. if ((hDC = CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL)) != NULL) {
  269. hSrcMemDC = CreateCompatibleDC(hDC);
  270. hDestMemDC = CreateCompatibleDC(hDC);
  271. hSrcBmp = CreateBitmap(NearFont->FontSize.X,
  272. NearFont->FontSize.Y,
  273. BITMAP_PLANES, BITMAP_BITS_PIXEL,
  274. NearFont->ImageBits);
  275. hDestBmp = CreateBitmap(FontSize.X,
  276. FontSize.Y,
  277. BITMAP_PLANES, BITMAP_BITS_PIXEL,
  278. NULL);
  279. if (hSrcMemDC && hSrcBmp && hDestMemDC && hDestBmp) {
  280. SelectObject(hSrcMemDC, hSrcBmp);
  281. SelectObject(hDestMemDC, hDestBmp);
  282. if (! StretchBlt(hDestMemDC, 0, 0, FontSize.X, FontSize.Y,
  283. hSrcMemDC, 0, 0, NearFont->FontSize.X, NearFont->FontSize.Y,
  284. SRCCOPY)) {
  285. Status = GetLastError();
  286. } else {
  287. BufferSize = CalcBitmapBufferSize(FontSize, WORD_ALIGN);
  288. GetBitmapBits(hDestBmp, BufferSize, (*pFontImage)->ImageBits);
  289. Status = STATUS_SUCCESS;
  290. }
  291. }
  292. if (hSrcMemDC) {
  293. DeleteDC(hSrcMemDC);
  294. }
  295. if (hDestMemDC) {
  296. DeleteDC(hDestMemDC);
  297. }
  298. if (hSrcBmp) {
  299. DeleteObject(hSrcBmp);
  300. }
  301. if (hDestBmp) {
  302. DeleteObject(hDestBmp);
  303. }
  304. DeleteDC(hDC);
  305. }
  306. return Status;
  307. }
  308. NTSTATUS
  309. GetFontImageInternal(
  310. IN PFONT_CACHE_INFORMATION FontCache,
  311. IN WCHAR wChar,
  312. IN COORD FontSize,
  313. OUT PFONT_IMAGE *pFontImage,
  314. IN DWORD GetFlag
  315. )
  316. {
  317. PFONT_HIGHLOW_OFFSET FontOffsetHighLow;
  318. PFONT_LOW_OFFSET FontOffsetLow;
  319. PFONT_IMAGE FontImage;
  320. WORD HighHighIndex, HighLowIndex;
  321. WORD LowIndex;
  322. DWORD Flag;
  323. HighHighIndex = (HIBYTE(wChar)) >> 4;
  324. HighLowIndex = (HIBYTE(wChar)) & 0x0f;
  325. LowIndex = LOBYTE(wChar);
  326. FontOffsetHighLow = FontCache->FontTable.FontOffsetHighHigh[HighHighIndex];
  327. if (FontOffsetHighLow == NULL)
  328. return STATUS_ACCESS_DENIED;
  329. FontOffsetLow = FontOffsetHighLow->FontOffsetHighLow[HighLowIndex];
  330. if (FontOffsetLow == NULL)
  331. return STATUS_ACCESS_DENIED;
  332. FontImage = FontOffsetLow->FontOffsetLow[LowIndex];
  333. if (FontImage == NULL)
  334. return STATUS_ACCESS_DENIED;
  335. Flag = ADD_IMAGE;
  336. do {
  337. if (FontImage->FontSize.X == FontSize.X &&
  338. FontImage->FontSize.Y == FontSize.Y ) {
  339. //
  340. // Replace font image
  341. //
  342. Flag = REPLACE_IMAGE;
  343. break;
  344. }
  345. }
  346. while (FontImage = (PFONT_IMAGE)FontImage->ImageList.Flink);
  347. switch (GetFlag)
  348. {
  349. //
  350. // Get matched size font.
  351. //
  352. case FONT_MATCHED:
  353. if (Flag != REPLACE_IMAGE)
  354. return STATUS_ACCESS_DENIED;
  355. *pFontImage = FontImage;
  356. break;
  357. //
  358. // Get stretched size font.
  359. //
  360. case FONT_STRETCHED:
  361. if (Flag == REPLACE_IMAGE &&
  362. FontImage->ImageBits != NULL) {
  363. *pFontImage = FontImage;
  364. }
  365. else {
  366. GetStretchImage(FontSize,
  367. FontOffsetLow->FontOffsetLow[LowIndex],
  368. pFontImage
  369. );
  370. }
  371. break;
  372. }
  373. return STATUS_SUCCESS;
  374. }
  375. //
  376. // See Raid #362907, stress failure
  377. //
  378. VOID UnlinkAndShrinkFontImagesByOne(
  379. PFONT_IMAGE* ppFontImage,
  380. PFONT_IMAGE pFontImageRemove)
  381. {
  382. PFONT_IMAGE OldFontImage = *ppFontImage;
  383. SIZE_T OldFontSize = ConsoleHeapSize(OldFontImage);
  384. PFONT_IMAGE NewFontImage;
  385. RIPMSG0(RIP_WARNING, "UnlinkAndShrinkFontImagesByOne entered.");
  386. if (OldFontImage== NULL) {
  387. RIPMSG0(RIP_ERROR, "UnlinkAndShrinkFontImagesByOne: *ppFontImage is NULL.");
  388. //
  389. // There's nothing to shrink.
  390. //
  391. return;
  392. }
  393. if (OldFontImage == pFontImageRemove) {
  394. RIPMSG0(RIP_WARNING, "UnlinkAndShrinkFontImagesByOne: unshrinking just one element.");
  395. //
  396. // There's just one entry. Let's free it and set
  397. // ppFontImage as NULL, and bail out.
  398. //
  399. UserAssert(OldFontSize < sizeof(FONT_IMAGE) * 2);
  400. *ppFontImage = NULL;
  401. ConsoleHeapFree(OldFontImage);
  402. return;
  403. }
  404. #if DBG
  405. //
  406. // Double check the integrity of the linked list.
  407. //
  408. {
  409. PFONT_IMAGE FontImageTmp;
  410. //
  411. // Search the tail element
  412. //
  413. for (FontImageTmp = OldFontImage; FontImageTmp->ImageList.Flink; FontImageTmp = (PFONT_IMAGE)FontImageTmp->ImageList.Flink)
  414. ;
  415. UserAssert(FontImageTmp == pFontImageRemove);
  416. }
  417. #endif
  418. //
  419. // Remove the tail element
  420. //
  421. pFontImageRemove->ImageList.Blink->Flink = NULL;
  422. //
  423. // Shrink the contiguous memory chunk
  424. //
  425. // Note: this code assumes sizeof(FONT_IMAGE) is larger than
  426. // HEAP_GRANULARITY. If not, the heap block actually does not
  427. // shrink, and the assert below will hit.
  428. //
  429. NewFontImage = ConsoleHeapReAlloc(HEAP_ZERO_MEMORY,
  430. OldFontImage,
  431. OldFontSize - sizeof(FONT_IMAGE));
  432. if (NewFontImage == NULL) {
  433. //
  434. // Win32HeapRealloc firstly allocates a new memory and then
  435. // copies the content. If the allocation fails, it leaves the
  436. // original heap as is.
  437. //
  438. // Even though the realloc fails, the last element (pFontImageRemove) is
  439. // already removed from the linked list. The next time SetImageFontInternal
  440. // is called, a new FontImage might be added to this memory chunk, but the
  441. // the code always links the newly extended memory.
  442. // This leaves the sizeof(FONT_IMAGE) memory unused, but it's safe. Assuming
  443. // sizeof(FONT_IMAGE) is small, memory waste should be minimum.
  444. //
  445. // It's OK for us to just bail out here.
  446. //
  447. RIPMSG0(RIP_WARNING, "UnlinkAndShrinkFontImagesByOne: failed to shrink ppFontImage.");
  448. return;
  449. }
  450. UserAssert(ConsoleHeapSize(NewFontImage) != OldFontSize);
  451. if (NewFontImage != OldFontImage) {
  452. //
  453. // Rebase Font Image Linked List
  454. //
  455. RebaseFontImageList(NewFontImage, (PBYTE)OldFontImage);
  456. *ppFontImage = NewFontImage;
  457. }
  458. }
  459. NTSTATUS
  460. SetFontImageInternal(
  461. IN PFONT_CACHE_INFORMATION FontCache,
  462. IN WCHAR wChar,
  463. IN COORD FontSize,
  464. IN DWORD dwAlign,
  465. IN CONST VOID *ImageBits
  466. )
  467. {
  468. PFONT_HIGHLOW_OFFSET FontOffsetHighLow;
  469. PFONT_LOW_OFFSET FontOffsetLow;
  470. PFONT_IMAGE FontImage;
  471. PFONT_IMAGE FontImageTmp;
  472. WORD HighHighIndex, HighLowIndex;
  473. WORD LowIndex;
  474. DWORD Flag;
  475. DWORD BufferSize;
  476. HighHighIndex = (HIBYTE(wChar)) >> 4;
  477. HighLowIndex = (HIBYTE(wChar)) & 0x0f;
  478. LowIndex = LOBYTE(wChar);
  479. /*
  480. * When Console is being destroyed, all font cache information
  481. * will be freed (see DestroyFontCache), so no memory leak
  482. * is expected on those, even if we cleanup everything on
  483. * error return...
  484. */
  485. FontOffsetHighLow = FontCache->FontTable.FontOffsetHighHigh[HighHighIndex];
  486. if (FontOffsetHighLow == NULL) {
  487. FontOffsetHighLow = ConsoleHeapAlloc( HEAP_ZERO_MEMORY, sizeof(FONT_HIGHLOW_OFFSET));
  488. if (FontOffsetHighLow == NULL) {
  489. RIPMSG1(RIP_WARNING, "SetFontImageInternal: cannot allocate memory (%d bytes)",
  490. sizeof(FONT_HIGHLOW_OFFSET));
  491. return STATUS_NO_MEMORY;
  492. }
  493. FontCache->FontTable.FontOffsetHighHigh[HighHighIndex] = FontOffsetHighLow;
  494. }
  495. FontOffsetLow = FontOffsetHighLow->FontOffsetHighLow[HighLowIndex];
  496. if (FontOffsetLow == NULL) {
  497. FontOffsetLow = ConsoleHeapAlloc( HEAP_ZERO_MEMORY, sizeof(FONT_LOW_OFFSET));
  498. if (FontOffsetLow == NULL) {
  499. RIPMSG0(RIP_WARNING, "SetFontImageInternal: failed to allocate FontOffsetLow.");
  500. return STATUS_NO_MEMORY;
  501. }
  502. FontOffsetHighLow->FontOffsetHighLow[HighLowIndex] = FontOffsetLow;
  503. }
  504. FontImage = FontOffsetLow->FontOffsetLow[LowIndex];
  505. if (FontImage == NULL) {
  506. FontImage = ConsoleHeapAlloc( HEAP_ZERO_MEMORY, sizeof(FONT_IMAGE));
  507. if (FontImage == NULL) {
  508. RIPMSG0(RIP_WARNING, "SetFontImageInternal: failed to allocate FontImage");
  509. return STATUS_NO_MEMORY;
  510. }
  511. }
  512. if (FontSize.X == 0 &&
  513. FontSize.Y == 0 ) {
  514. //
  515. // Reset registered font
  516. //
  517. if (FontImage != NULL)
  518. {
  519. ConsoleHeapFree(FontImage);
  520. FontOffsetLow->FontOffsetLow[LowIndex] = NULL;
  521. }
  522. return STATUS_SUCCESS;
  523. }
  524. Flag = ADD_IMAGE;
  525. FontImageTmp = FontImage;
  526. do {
  527. if (FontImageTmp->FontSize.X == FontSize.X &&
  528. FontImageTmp->FontSize.Y == FontSize.Y ) {
  529. //
  530. // Replace font image
  531. //
  532. Flag = REPLACE_IMAGE;
  533. FontImage = FontImageTmp;
  534. break;
  535. }
  536. }
  537. while (FontImageTmp = (PFONT_IMAGE)FontImageTmp->ImageList.Flink);
  538. switch (Flag) {
  539. case ADD_IMAGE:
  540. if (FontOffsetLow->FontOffsetLow[LowIndex] != NULL)
  541. {
  542. PFONT_IMAGE OldFontImage = FontOffsetLow->FontOffsetLow[LowIndex];
  543. SIZE_T OldFontSize = ConsoleHeapSize(OldFontImage);
  544. PFONT_IMAGE NewFontImage;
  545. NewFontImage = ConsoleHeapReAlloc(HEAP_ZERO_MEMORY,
  546. OldFontImage,
  547. OldFontSize + sizeof(FONT_IMAGE));
  548. if (NewFontImage == NULL) {
  549. RIPMSG0(RIP_WARNING, "SetFontImageInternal: failed to allocate NewFontImage");
  550. return STATUS_NO_MEMORY;
  551. }
  552. FontOffsetLow->FontOffsetLow[LowIndex] = NewFontImage;
  553. // Rebase Font Image List
  554. RebaseFontImageList(NewFontImage, (PBYTE)OldFontImage);
  555. NewFontImage = (PFONT_IMAGE)((PBYTE)NewFontImage + OldFontSize);
  556. NewFontImage->FontSize = FontSize;
  557. //
  558. // Connect link list.
  559. //
  560. (NewFontImage-1)->ImageList.Flink = (PLIST_ENTRY)NewFontImage;
  561. NewFontImage->ImageList.Blink = (PLIST_ENTRY)(NewFontImage-1);
  562. FontImage = NewFontImage;
  563. }
  564. else
  565. {
  566. FontImage->FontSize = FontSize;
  567. FontOffsetLow->FontOffsetLow[LowIndex] = FontImage;
  568. }
  569. //
  570. // Allocate Image Buffer
  571. //
  572. BufferSize = CalcBitmapBufferSize(FontSize,WORD_ALIGN);
  573. if (FontCache->BaseImageBits == NULL)
  574. {
  575. FontCache->BaseImageBits = ConsoleHeapAlloc( HEAP_ZERO_MEMORY, BufferSize);
  576. if (FontCache->BaseImageBits == NULL) {
  577. RIPMSG0(RIP_WARNING, "SetFontImageInternal: failed to allocate FontCache->BaseImageBits");
  578. UnlinkAndShrinkFontImagesByOne(&FontOffsetLow->FontOffsetLow[LowIndex], FontImage);
  579. return STATUS_NO_MEMORY;
  580. }
  581. FontImage->ImageBits = FontCache->BaseImageBits;
  582. }
  583. else
  584. {
  585. PBYTE OldBaseImage = FontCache->BaseImageBits;
  586. SIZE_T OldImageSize = ConsoleHeapSize(OldBaseImage);
  587. FontCache->BaseImageBits = ConsoleHeapReAlloc(HEAP_ZERO_MEMORY,
  588. OldBaseImage,
  589. OldImageSize + BufferSize);
  590. if (FontCache->BaseImageBits == NULL) {
  591. RIPMSG0(RIP_WARNING, "SetFontImageInternal: failed to reallocate FontCache->BaseImageBits");
  592. //
  593. // When reallocation fails, we preserve the old baseImageBits
  594. // so that other FontImage->ImageBits can be still valid.
  595. //
  596. FontCache->BaseImageBits = OldBaseImage;
  597. //
  598. // Remove the tail element that we failed to add image.
  599. //
  600. UnlinkAndShrinkFontImagesByOne(&FontOffsetLow->FontOffsetLow[LowIndex], FontImage);
  601. return STATUS_NO_MEMORY;
  602. }
  603. // Rebase font image pointer
  604. RebaseFontCache(FontCache, OldBaseImage);
  605. FontImage->ImageBits = FontCache->BaseImageBits + OldImageSize;
  606. }
  607. AlignCopyMemory(FontImage->ImageBits,// pDestBits
  608. WORD_ALIGN, // dwDestAlign
  609. (PVOID)ImageBits, // pSrcBits
  610. dwAlign, // dwSrcAlign
  611. FontSize);
  612. break;
  613. case REPLACE_IMAGE:
  614. if (FontImage->ImageBits == NULL) {
  615. RIPMSG0(RIP_WARNING, "SetFontImageInternal: FontImage->ImageBits is NULL.");
  616. return STATUS_NO_MEMORY;
  617. }
  618. AlignCopyMemory(FontImage->ImageBits,// pDestBits
  619. WORD_ALIGN, // dwDestAlign
  620. (PVOID)ImageBits, // pSrcBits
  621. dwAlign, // dwSrcAlign
  622. FontSize);
  623. break;
  624. }
  625. return STATUS_SUCCESS;
  626. }
  627. ULONG
  628. GetFontImage(
  629. IN PFONT_CACHE_INFORMATION FontCache,
  630. IN WCHAR wChar,
  631. IN COORD FontSize,
  632. IN DWORD dwAlign,
  633. OUT VOID *ImageBits
  634. )
  635. {
  636. NTSTATUS Status;
  637. PFONT_IMAGE FontImage;
  638. if (FontSize.X == 0 &&
  639. FontSize.Y == 0 ) {
  640. return (ULONG)(STATUS_INVALID_PARAMETER);
  641. }
  642. Status = GetFontImageInternal(FontCache,wChar,FontSize,&FontImage,FONT_MATCHED);
  643. if (! NT_SUCCESS(Status) )
  644. return (ULONG)Status;
  645. if (FontImage->ImageBits == NULL ||
  646. ImageBits == NULL)
  647. return STATUS_SUCCESS;
  648. AlignCopyMemory((PVOID)ImageBits, // pDestBits
  649. dwAlign, // dwDestAlign
  650. FontImage->ImageBits,// pSrcBits
  651. WORD_ALIGN, // dwSrcAlign
  652. FontSize);
  653. return STATUS_SUCCESS;
  654. }
  655. ULONG
  656. GetStretchedFontImage(
  657. IN PFONT_CACHE_INFORMATION FontCache,
  658. IN WCHAR wChar,
  659. IN COORD FontSize,
  660. IN DWORD dwAlign,
  661. OUT VOID *ImageBits
  662. )
  663. {
  664. NTSTATUS Status;
  665. PFONT_IMAGE FontImage;
  666. FONT_IMAGE FontBuff;
  667. DWORD BufferSize;
  668. if (FontSize.X == 0 &&
  669. FontSize.Y == 0 ) {
  670. return (ULONG)(STATUS_INVALID_PARAMETER);
  671. }
  672. FontImage = &FontBuff;
  673. BufferSize = CalcBitmapBufferSize(FontSize,WORD_ALIGN);
  674. FontImage->ImageBits = ConsoleHeapAlloc( HEAP_ZERO_MEMORY, BufferSize);
  675. if (FontImage->ImageBits == NULL) {
  676. RIPMSG0(RIP_WARNING, "GetStretchedFontImage: failed to allocate FontImage->ImageBits");
  677. return (ULONG)STATUS_NO_MEMORY;
  678. }
  679. Status = GetFontImageInternal(FontCache,wChar,FontSize,&FontImage,FONT_STRETCHED);
  680. if (! NT_SUCCESS(Status) )
  681. {
  682. ConsoleHeapFree(FontBuff.ImageBits);
  683. return (ULONG)Status;
  684. }
  685. if (FontImage->ImageBits == NULL)
  686. {
  687. ConsoleHeapFree(FontBuff.ImageBits);
  688. return (ULONG)STATUS_SUCCESS;
  689. }
  690. AlignCopyMemory((PVOID)ImageBits, // pDestBits
  691. dwAlign, // dwDestAlign
  692. FontImage->ImageBits,// pSrcBits
  693. WORD_ALIGN, // dwSrcAlign
  694. FontSize);
  695. ConsoleHeapFree(FontBuff.ImageBits);
  696. return (ULONG)STATUS_SUCCESS;
  697. }
  698. ULONG
  699. GetFontImagePointer(
  700. IN PFONT_CACHE_INFORMATION FontCache,
  701. IN WCHAR wChar,
  702. IN COORD FontSize,
  703. OUT PFONT_IMAGE *FontImage
  704. )
  705. {
  706. NTSTATUS Status;
  707. if (FontSize.X == 0 &&
  708. FontSize.Y == 0 ) {
  709. return (ULONG)(STATUS_INVALID_PARAMETER);
  710. }
  711. Status = GetFontImageInternal(FontCache,wChar,FontSize,(PFONT_IMAGE*)FontImage,FONT_MATCHED);
  712. if (! NT_SUCCESS(Status) )
  713. return (ULONG)Status;
  714. if ((*FontImage)->ImageBits == NULL)
  715. return (ULONG)STATUS_ACCESS_DENIED;
  716. return Status;
  717. }
  718. ULONG
  719. SetFontImage(
  720. IN PFONT_CACHE_INFORMATION FontCache,
  721. IN WCHAR wChar,
  722. IN COORD FontSize,
  723. IN DWORD dwAlign,
  724. IN CONST VOID *ImageBits
  725. )
  726. {
  727. return SetFontImageInternal(FontCache,wChar,FontSize,dwAlign,ImageBits);
  728. }
  729. NTSTATUS
  730. GetExpandImage(
  731. COORD InputFontSize,
  732. PWORD InputFontImage,
  733. COORD OutputFontSize,
  734. PWORD OutputFontImage
  735. )
  736. {
  737. NTSTATUS Status;
  738. DWORD InputRow = CALC_BITMAP_BITS_FOR_X(InputFontSize.X, BITMAP_BITS_WORD_ALIGN);
  739. DWORD OutputRow = CALC_BITMAP_BITS_FOR_X(OutputFontSize.X, BITMAP_BITS_WORD_ALIGN);
  740. DWORD InputBufferSize = CalcBitmapBufferSize(InputFontSize,WORD_ALIGN);
  741. DWORD OutputBufferSize = CalcBitmapBufferSize(OutputFontSize,WORD_ALIGN);
  742. Status = STATUS_NO_MEMORY;
  743. RtlZeroMemory(OutputFontImage,OutputBufferSize);
  744. ASSERT(InputRow==OutputRow);
  745. if (InputFontSize.Y < OutputFontSize.Y)
  746. RtlCopyMemory(OutputFontImage, InputFontImage, InputBufferSize);
  747. else
  748. RtlCopyMemory(OutputFontImage, InputFontImage, OutputBufferSize);
  749. return STATUS_SUCCESS;
  750. }
  751. NTSTATUS
  752. GetExpandFontImage(
  753. PFONT_CACHE_INFORMATION FontCache,
  754. WCHAR wChar,
  755. COORD InputFontSize,
  756. COORD OutputFontSize,
  757. PWORD OutputFontImage
  758. )
  759. {
  760. NTSTATUS Status;
  761. DWORD InputBufferSize;
  762. PWORD InputFontImage;
  763. if (InputFontSize.X == 0 &&
  764. InputFontSize.Y == 0 ) {
  765. return (ULONG)(STATUS_INVALID_PARAMETER);
  766. }
  767. if (OutputFontSize.X == 0 &&
  768. OutputFontSize.Y == 0 ) {
  769. return (ULONG)(STATUS_INVALID_PARAMETER);
  770. }
  771. InputBufferSize = CalcBitmapBufferSize(InputFontSize,WORD_ALIGN);
  772. InputFontImage = ConsoleHeapAlloc( HEAP_ZERO_MEMORY, InputBufferSize);
  773. if (InputFontImage==NULL)
  774. return STATUS_NO_MEMORY;
  775. Status = GetFontImage(FontCache,
  776. wChar,
  777. InputFontSize,
  778. WORD_ALIGN,
  779. InputFontImage);
  780. if (! NT_SUCCESS(Status) )
  781. {
  782. ConsoleHeapFree(InputFontImage);
  783. return Status;
  784. }
  785. Status = GetExpandImage(InputFontSize,
  786. InputFontImage,
  787. OutputFontSize,
  788. OutputFontImage);
  789. ConsoleHeapFree(InputFontImage);
  790. return Status;
  791. }
  792. #endif