|
|
/*++
Copyright (c) 1985 - 1999, Microsoft Corporation
Module Name:
foncache.c
Abstract:
This file is EUDC font cache
Author:
Kazuhiko Matsubara 21-June-1994
Revision History:
Notes:
--*/
#include "precomp.h"
#pragma hdrstop
#if defined(FE_SB)
VOID RebaseFontImageList( IN PFONT_IMAGE NewFontImage, IN PBYTE OldFontImage ) { PLIST_ENTRY ImageList; PBYTE BaseImage = (PBYTE)NewFontImage;
do { ImageList = &NewFontImage->ImageList; if (ImageList->Blink) ImageList->Blink = (PLIST_ENTRY)((PBYTE)ImageList->Blink - OldFontImage + BaseImage); if (ImageList->Flink) ImageList->Flink = (PLIST_ENTRY)((PBYTE)ImageList->Flink - OldFontImage + BaseImage); } while (NewFontImage = (PFONT_IMAGE)ImageList->Flink); }
ULONG CreateFontCache( OUT PFONT_CACHE_INFORMATION *FontCache ) { //
// allocate font cache data
//
*FontCache = ConsoleHeapAlloc(HEAP_ZERO_MEMORY,sizeof(FONT_CACHE_INFORMATION)); if (*FontCache == NULL) { return (ULONG)STATUS_NO_MEMORY; }
return (ULONG)(STATUS_SUCCESS); }
ULONG DestroyFontCache( IN PFONT_CACHE_INFORMATION FontCache ) { if (FontCache != NULL) { PFONT_HIGHLOW_OFFSET FontOffsetHighLow; PFONT_LOW_OFFSET FontOffsetLow; PFONT_IMAGE FontImage; UINT i, j, k;
for (i=0; i < sizeof(FontCache->FontTable.FontOffsetHighHigh)/sizeof(PFONT_HIGHLOW_OFFSET); i++) { if (FontOffsetHighLow = FontCache->FontTable.FontOffsetHighHigh[i]) { for (j=0; j < sizeof(FontOffsetHighLow->FontOffsetHighLow)/sizeof(PFONT_LOW_OFFSET); j++) { if (FontOffsetLow = FontOffsetHighLow->FontOffsetHighLow[j]) { for (k=0; k < sizeof(FontOffsetLow->FontOffsetLow)/sizeof(PFONT_IMAGE); k++) { if (FontImage = FontOffsetLow->FontOffsetLow[k]) { ConsoleHeapFree(FontImage); } } ConsoleHeapFree(FontOffsetLow); } } ConsoleHeapFree(FontOffsetHighLow); } } if (FontCache->BaseImageBits) { ConsoleHeapFree(FontCache->BaseImageBits); } ConsoleHeapFree(FontCache); } return (ULONG)(STATUS_SUCCESS); }
ULONG RebaseFontCache( IN PFONT_CACHE_INFORMATION FontCache, IN PBYTE OldBaseImage ) { if (FontCache != NULL) { PFONT_HIGHLOW_OFFSET FontOffsetHighLow; PFONT_LOW_OFFSET FontOffsetLow; PFONT_IMAGE FontImage; UINT i, j, k;
for (i=0; i < sizeof(FontCache->FontTable.FontOffsetHighHigh)/sizeof(PFONT_HIGHLOW_OFFSET); i++) { if (FontOffsetHighLow = FontCache->FontTable.FontOffsetHighHigh[i]) { for (j=0; j < sizeof(FontOffsetHighLow->FontOffsetHighLow)/sizeof(PFONT_LOW_OFFSET); j++) { if (FontOffsetLow = FontOffsetHighLow->FontOffsetHighLow[j]) { for (k=0; k < sizeof(FontOffsetLow->FontOffsetLow)/sizeof(PFONT_IMAGE); k++) { if (FontImage = FontOffsetLow->FontOffsetLow[k]) { LIST_ENTRY ImageList;
do { ImageList = FontImage->ImageList; if (FontImage->ImageBits) { FontImage->ImageBits = FontImage->ImageBits - OldBaseImage + FontCache->BaseImageBits; } } while (FontImage = (PFONT_IMAGE)ImageList.Flink); } } } } } } } return (ULONG)(STATUS_SUCCESS); }
#define CALC_BITMAP_BITS_FOR_X( FontSizeX, dwAlign ) \
( ( ( FontSizeX * BITMAP_BITS_PIXEL + (dwAlign-1) ) & ~(dwAlign-1)) >> BITMAP_ARRAY_BYTE )
DWORD CalcBitmapBufferSize( IN COORD FontSize, IN DWORD dwAlign ) { DWORD uiCount;
uiCount = CALC_BITMAP_BITS_FOR_X(FontSize.X, (dwAlign==BYTE_ALIGN ? BITMAP_BITS_BYTE_ALIGN : BITMAP_BITS_WORD_ALIGN)); uiCount = uiCount * BITMAP_PLANES * FontSize.Y; return uiCount; }
VOID AlignCopyMemory( OUT PBYTE pDestBits, IN DWORD dwDestAlign, IN PBYTE pSrcBits, IN DWORD dwSrcAlign, IN COORD FontSize ) { DWORD dwDestBufferSize; COORD coord;
if (dwDestAlign == dwSrcAlign) { dwDestBufferSize = CalcBitmapBufferSize(FontSize, dwDestAlign); RtlCopyMemory(pDestBits, pSrcBits, dwDestBufferSize); return; }
switch (dwDestAlign) { default: case WORD_ALIGN: switch (dwSrcAlign) { default: //
// pDest = WORD, pSrc = WORD
//
case WORD_ALIGN: dwDestBufferSize = CalcBitmapBufferSize(FontSize, dwDestAlign); RtlCopyMemory(pDestBits, pSrcBits, dwDestBufferSize); break; //
// pDest = WORD, pSrc = BYTE
//
case BYTE_ALIGN: dwDestBufferSize = CalcBitmapBufferSize(FontSize, dwDestAlign); if (((FontSize.X % BITMAP_BITS_BYTE_ALIGN) == 0) && ((FontSize.X % BITMAP_BITS_WORD_ALIGN) == 0) ) { RtlCopyMemory(pDestBits, pSrcBits, dwDestBufferSize); } else { RtlZeroMemory(pDestBits, dwDestBufferSize); for (coord.Y=0; coord.Y < FontSize.Y; coord.Y++) { for (coord.X=0; coord.X < CALC_BITMAP_BITS_FOR_X(FontSize.X, BITMAP_BITS_BYTE_ALIGN); coord.X++) { *pDestBits++ = *pSrcBits++; } if (CALC_BITMAP_BITS_FOR_X(FontSize.X, BITMAP_BITS_BYTE_ALIGN) & 1) pDestBits++; } } break; } break; case BYTE_ALIGN: switch (dwSrcAlign) { //
// pDest = BYTE, pSrc = BYTE
//
case BYTE_ALIGN: dwDestBufferSize = CalcBitmapBufferSize(FontSize, dwDestAlign); RtlCopyMemory(pDestBits, pSrcBits, dwDestBufferSize); break; default: //
// pDest = BYTE, pSrc = WORD
//
case WORD_ALIGN: dwDestBufferSize = CalcBitmapBufferSize(FontSize, dwDestAlign); if (((FontSize.X % BITMAP_BITS_BYTE_ALIGN) == 0) && ((FontSize.X % BITMAP_BITS_WORD_ALIGN) == 0) ) { RtlCopyMemory(pDestBits, pSrcBits, dwDestBufferSize); } else { RtlZeroMemory(pDestBits, dwDestBufferSize); for (coord.Y=0; coord.Y < FontSize.Y; coord.Y++) { for (coord.X=0; coord.X < CALC_BITMAP_BITS_FOR_X(FontSize.X, BITMAP_BITS_BYTE_ALIGN); coord.X++) { *pDestBits++ = *pSrcBits++; } if (CALC_BITMAP_BITS_FOR_X(FontSize.X, BITMAP_BITS_BYTE_ALIGN) & 1) pSrcBits++; } } break; } break; } }
NTSTATUS GetStretchImage( IN COORD FontSize, IN PFONT_IMAGE FontImage, OUT PFONT_IMAGE *pFontImage ) { PFONT_IMAGE NearFont; DWORD Find; COORD FontDelta; HDC hDC; HDC hSrcMemDC, hDestMemDC; HBITMAP hSrcBmp, hDestBmp; DWORD BufferSize; NTSTATUS Status = STATUS_NO_MEMORY;
Find = (DWORD)-1; NearFont = NULL; do { FontDelta.X = (SHORT) abs(FontSize.X - FontImage->FontSize.X); FontDelta.Y = (SHORT) abs(FontSize.Y - FontImage->FontSize.Y); if (Find > (DWORD)(FontDelta.X + FontDelta.Y)) { Find = (DWORD)(FontDelta.X + FontDelta.Y); NearFont = FontImage; } } while (FontImage = (PFONT_IMAGE)FontImage->ImageList.Flink);
if (NearFont == NULL) return STATUS_ACCESS_DENIED;
if ((hDC = CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL)) != NULL) { hSrcMemDC = CreateCompatibleDC(hDC); hDestMemDC = CreateCompatibleDC(hDC);
hSrcBmp = CreateBitmap(NearFont->FontSize.X, NearFont->FontSize.Y, BITMAP_PLANES, BITMAP_BITS_PIXEL, NearFont->ImageBits); hDestBmp = CreateBitmap(FontSize.X, FontSize.Y, BITMAP_PLANES, BITMAP_BITS_PIXEL, NULL); if (hSrcMemDC && hSrcBmp && hDestMemDC && hDestBmp) { SelectObject(hSrcMemDC, hSrcBmp); SelectObject(hDestMemDC, hDestBmp);
if (! StretchBlt(hDestMemDC, 0, 0, FontSize.X, FontSize.Y, hSrcMemDC, 0, 0, NearFont->FontSize.X, NearFont->FontSize.Y, SRCCOPY)) { Status = GetLastError(); } else { BufferSize = CalcBitmapBufferSize(FontSize, WORD_ALIGN); GetBitmapBits(hDestBmp, BufferSize, (*pFontImage)->ImageBits); Status = STATUS_SUCCESS; } }
if (hSrcMemDC) { DeleteDC(hSrcMemDC); } if (hDestMemDC) { DeleteDC(hDestMemDC); } if (hSrcBmp) { DeleteObject(hSrcBmp); } if (hDestBmp) { DeleteObject(hDestBmp); } DeleteDC(hDC); }
return Status; }
NTSTATUS GetFontImageInternal( IN PFONT_CACHE_INFORMATION FontCache, IN WCHAR wChar, IN COORD FontSize, OUT PFONT_IMAGE *pFontImage, IN DWORD GetFlag ) { PFONT_HIGHLOW_OFFSET FontOffsetHighLow; PFONT_LOW_OFFSET FontOffsetLow; PFONT_IMAGE FontImage; WORD HighHighIndex, HighLowIndex; WORD LowIndex; DWORD Flag;
HighHighIndex = (HIBYTE(wChar)) >> 4; HighLowIndex = (HIBYTE(wChar)) & 0x0f; LowIndex = LOBYTE(wChar);
FontOffsetHighLow = FontCache->FontTable.FontOffsetHighHigh[HighHighIndex]; if (FontOffsetHighLow == NULL) return STATUS_ACCESS_DENIED;
FontOffsetLow = FontOffsetHighLow->FontOffsetHighLow[HighLowIndex]; if (FontOffsetLow == NULL) return STATUS_ACCESS_DENIED;
FontImage = FontOffsetLow->FontOffsetLow[LowIndex]; if (FontImage == NULL) return STATUS_ACCESS_DENIED;
Flag = ADD_IMAGE; do { if (FontImage->FontSize.X == FontSize.X && FontImage->FontSize.Y == FontSize.Y ) { //
// Replace font image
//
Flag = REPLACE_IMAGE; break; } } while (FontImage = (PFONT_IMAGE)FontImage->ImageList.Flink);
switch (GetFlag) { //
// Get matched size font.
//
case FONT_MATCHED: if (Flag != REPLACE_IMAGE) return STATUS_ACCESS_DENIED;
*pFontImage = FontImage; break;
//
// Get stretched size font.
//
case FONT_STRETCHED: if (Flag == REPLACE_IMAGE && FontImage->ImageBits != NULL) {
*pFontImage = FontImage;
} else { GetStretchImage(FontSize, FontOffsetLow->FontOffsetLow[LowIndex], pFontImage ); } break; }
return STATUS_SUCCESS; }
//
// See Raid #362907, stress failure
//
VOID UnlinkAndShrinkFontImagesByOne( PFONT_IMAGE* ppFontImage, PFONT_IMAGE pFontImageRemove) { PFONT_IMAGE OldFontImage = *ppFontImage; SIZE_T OldFontSize = ConsoleHeapSize(OldFontImage); PFONT_IMAGE NewFontImage;
RIPMSG0(RIP_WARNING, "UnlinkAndShrinkFontImagesByOne entered.");
if (OldFontImage== NULL) { RIPMSG0(RIP_ERROR, "UnlinkAndShrinkFontImagesByOne: *ppFontImage is NULL."); //
// There's nothing to shrink.
//
return; }
if (OldFontImage == pFontImageRemove) { RIPMSG0(RIP_WARNING, "UnlinkAndShrinkFontImagesByOne: unshrinking just one element."); //
// There's just one entry. Let's free it and set
// ppFontImage as NULL, and bail out.
//
UserAssert(OldFontSize < sizeof(FONT_IMAGE) * 2);
*ppFontImage = NULL; ConsoleHeapFree(OldFontImage); return; }
#if DBG
//
// Double check the integrity of the linked list.
//
{ PFONT_IMAGE FontImageTmp;
//
// Search the tail element
//
for (FontImageTmp = OldFontImage; FontImageTmp->ImageList.Flink; FontImageTmp = (PFONT_IMAGE)FontImageTmp->ImageList.Flink) ;
UserAssert(FontImageTmp == pFontImageRemove); } #endif
//
// Remove the tail element
//
pFontImageRemove->ImageList.Blink->Flink = NULL;
//
// Shrink the contiguous memory chunk
//
// Note: this code assumes sizeof(FONT_IMAGE) is larger than
// HEAP_GRANULARITY. If not, the heap block actually does not
// shrink, and the assert below will hit.
//
NewFontImage = ConsoleHeapReAlloc(HEAP_ZERO_MEMORY, OldFontImage, OldFontSize - sizeof(FONT_IMAGE)); if (NewFontImage == NULL) { //
// Win32HeapRealloc firstly allocates a new memory and then
// copies the content. If the allocation fails, it leaves the
// original heap as is.
//
// Even though the realloc fails, the last element (pFontImageRemove) is
// already removed from the linked list. The next time SetImageFontInternal
// is called, a new FontImage might be added to this memory chunk, but the
// the code always links the newly extended memory.
// This leaves the sizeof(FONT_IMAGE) memory unused, but it's safe. Assuming
// sizeof(FONT_IMAGE) is small, memory waste should be minimum.
//
// It's OK for us to just bail out here.
//
RIPMSG0(RIP_WARNING, "UnlinkAndShrinkFontImagesByOne: failed to shrink ppFontImage."); return; } UserAssert(ConsoleHeapSize(NewFontImage) != OldFontSize);
if (NewFontImage != OldFontImage) { //
// Rebase Font Image Linked List
//
RebaseFontImageList(NewFontImage, (PBYTE)OldFontImage); *ppFontImage = NewFontImage; } }
NTSTATUS SetFontImageInternal( IN PFONT_CACHE_INFORMATION FontCache, IN WCHAR wChar, IN COORD FontSize, IN DWORD dwAlign, IN CONST VOID *ImageBits ) { PFONT_HIGHLOW_OFFSET FontOffsetHighLow; PFONT_LOW_OFFSET FontOffsetLow; PFONT_IMAGE FontImage; PFONT_IMAGE FontImageTmp; WORD HighHighIndex, HighLowIndex; WORD LowIndex; DWORD Flag; DWORD BufferSize;
HighHighIndex = (HIBYTE(wChar)) >> 4; HighLowIndex = (HIBYTE(wChar)) & 0x0f; LowIndex = LOBYTE(wChar);
/*
* When Console is being destroyed, all font cache information * will be freed (see DestroyFontCache), so no memory leak * is expected on those, even if we cleanup everything on * error return... */
FontOffsetHighLow = FontCache->FontTable.FontOffsetHighHigh[HighHighIndex]; if (FontOffsetHighLow == NULL) { FontOffsetHighLow = ConsoleHeapAlloc( HEAP_ZERO_MEMORY, sizeof(FONT_HIGHLOW_OFFSET)); if (FontOffsetHighLow == NULL) { RIPMSG1(RIP_WARNING, "SetFontImageInternal: cannot allocate memory (%d bytes)", sizeof(FONT_HIGHLOW_OFFSET)); return STATUS_NO_MEMORY; }
FontCache->FontTable.FontOffsetHighHigh[HighHighIndex] = FontOffsetHighLow; }
FontOffsetLow = FontOffsetHighLow->FontOffsetHighLow[HighLowIndex]; if (FontOffsetLow == NULL) { FontOffsetLow = ConsoleHeapAlloc( HEAP_ZERO_MEMORY, sizeof(FONT_LOW_OFFSET)); if (FontOffsetLow == NULL) { RIPMSG0(RIP_WARNING, "SetFontImageInternal: failed to allocate FontOffsetLow."); return STATUS_NO_MEMORY; }
FontOffsetHighLow->FontOffsetHighLow[HighLowIndex] = FontOffsetLow; }
FontImage = FontOffsetLow->FontOffsetLow[LowIndex]; if (FontImage == NULL) { FontImage = ConsoleHeapAlloc( HEAP_ZERO_MEMORY, sizeof(FONT_IMAGE)); if (FontImage == NULL) { RIPMSG0(RIP_WARNING, "SetFontImageInternal: failed to allocate FontImage"); return STATUS_NO_MEMORY; } }
if (FontSize.X == 0 && FontSize.Y == 0 ) { //
// Reset registered font
//
if (FontImage != NULL) { ConsoleHeapFree(FontImage); FontOffsetLow->FontOffsetLow[LowIndex] = NULL; } return STATUS_SUCCESS; }
Flag = ADD_IMAGE; FontImageTmp = FontImage; do { if (FontImageTmp->FontSize.X == FontSize.X && FontImageTmp->FontSize.Y == FontSize.Y ) { //
// Replace font image
//
Flag = REPLACE_IMAGE; FontImage = FontImageTmp; break; } } while (FontImageTmp = (PFONT_IMAGE)FontImageTmp->ImageList.Flink);
switch (Flag) { case ADD_IMAGE: if (FontOffsetLow->FontOffsetLow[LowIndex] != NULL) { PFONT_IMAGE OldFontImage = FontOffsetLow->FontOffsetLow[LowIndex]; SIZE_T OldFontSize = ConsoleHeapSize(OldFontImage); PFONT_IMAGE NewFontImage;
NewFontImage = ConsoleHeapReAlloc(HEAP_ZERO_MEMORY, OldFontImage, OldFontSize + sizeof(FONT_IMAGE)); if (NewFontImage == NULL) { RIPMSG0(RIP_WARNING, "SetFontImageInternal: failed to allocate NewFontImage"); return STATUS_NO_MEMORY; }
FontOffsetLow->FontOffsetLow[LowIndex] = NewFontImage;
// Rebase Font Image List
RebaseFontImageList(NewFontImage, (PBYTE)OldFontImage);
NewFontImage = (PFONT_IMAGE)((PBYTE)NewFontImage + OldFontSize);
NewFontImage->FontSize = FontSize;
//
// Connect link list.
//
(NewFontImage-1)->ImageList.Flink = (PLIST_ENTRY)NewFontImage; NewFontImage->ImageList.Blink = (PLIST_ENTRY)(NewFontImage-1);
FontImage = NewFontImage; } else { FontImage->FontSize = FontSize; FontOffsetLow->FontOffsetLow[LowIndex] = FontImage; }
//
// Allocate Image Buffer
//
BufferSize = CalcBitmapBufferSize(FontSize,WORD_ALIGN);
if (FontCache->BaseImageBits == NULL) { FontCache->BaseImageBits = ConsoleHeapAlloc( HEAP_ZERO_MEMORY, BufferSize); if (FontCache->BaseImageBits == NULL) { RIPMSG0(RIP_WARNING, "SetFontImageInternal: failed to allocate FontCache->BaseImageBits"); UnlinkAndShrinkFontImagesByOne(&FontOffsetLow->FontOffsetLow[LowIndex], FontImage); return STATUS_NO_MEMORY; }
FontImage->ImageBits = FontCache->BaseImageBits; } else { PBYTE OldBaseImage = FontCache->BaseImageBits; SIZE_T OldImageSize = ConsoleHeapSize(OldBaseImage); FontCache->BaseImageBits = ConsoleHeapReAlloc(HEAP_ZERO_MEMORY, OldBaseImage, OldImageSize + BufferSize); if (FontCache->BaseImageBits == NULL) { RIPMSG0(RIP_WARNING, "SetFontImageInternal: failed to reallocate FontCache->BaseImageBits"); //
// When reallocation fails, we preserve the old baseImageBits
// so that other FontImage->ImageBits can be still valid.
//
FontCache->BaseImageBits = OldBaseImage; //
// Remove the tail element that we failed to add image.
//
UnlinkAndShrinkFontImagesByOne(&FontOffsetLow->FontOffsetLow[LowIndex], FontImage); return STATUS_NO_MEMORY; }
// Rebase font image pointer
RebaseFontCache(FontCache, OldBaseImage);
FontImage->ImageBits = FontCache->BaseImageBits + OldImageSize; }
AlignCopyMemory(FontImage->ImageBits,// pDestBits
WORD_ALIGN, // dwDestAlign
(PVOID)ImageBits, // pSrcBits
dwAlign, // dwSrcAlign
FontSize);
break;
case REPLACE_IMAGE: if (FontImage->ImageBits == NULL) { RIPMSG0(RIP_WARNING, "SetFontImageInternal: FontImage->ImageBits is NULL."); return STATUS_NO_MEMORY; }
AlignCopyMemory(FontImage->ImageBits,// pDestBits
WORD_ALIGN, // dwDestAlign
(PVOID)ImageBits, // pSrcBits
dwAlign, // dwSrcAlign
FontSize);
break; }
return STATUS_SUCCESS; }
ULONG GetFontImage( IN PFONT_CACHE_INFORMATION FontCache, IN WCHAR wChar, IN COORD FontSize, IN DWORD dwAlign, OUT VOID *ImageBits ) { NTSTATUS Status; PFONT_IMAGE FontImage;
if (FontSize.X == 0 && FontSize.Y == 0 ) { return (ULONG)(STATUS_INVALID_PARAMETER); }
Status = GetFontImageInternal(FontCache,wChar,FontSize,&FontImage,FONT_MATCHED); if (! NT_SUCCESS(Status) ) return (ULONG)Status;
if (FontImage->ImageBits == NULL || ImageBits == NULL) return STATUS_SUCCESS;
AlignCopyMemory((PVOID)ImageBits, // pDestBits
dwAlign, // dwDestAlign
FontImage->ImageBits,// pSrcBits
WORD_ALIGN, // dwSrcAlign
FontSize);
return STATUS_SUCCESS; }
ULONG GetStretchedFontImage( IN PFONT_CACHE_INFORMATION FontCache, IN WCHAR wChar, IN COORD FontSize, IN DWORD dwAlign, OUT VOID *ImageBits ) { NTSTATUS Status; PFONT_IMAGE FontImage; FONT_IMAGE FontBuff; DWORD BufferSize;
if (FontSize.X == 0 && FontSize.Y == 0 ) { return (ULONG)(STATUS_INVALID_PARAMETER); }
FontImage = &FontBuff;
BufferSize = CalcBitmapBufferSize(FontSize,WORD_ALIGN); FontImage->ImageBits = ConsoleHeapAlloc( HEAP_ZERO_MEMORY, BufferSize); if (FontImage->ImageBits == NULL) { RIPMSG0(RIP_WARNING, "GetStretchedFontImage: failed to allocate FontImage->ImageBits"); return (ULONG)STATUS_NO_MEMORY; }
Status = GetFontImageInternal(FontCache,wChar,FontSize,&FontImage,FONT_STRETCHED); if (! NT_SUCCESS(Status) ) { ConsoleHeapFree(FontBuff.ImageBits); return (ULONG)Status; }
if (FontImage->ImageBits == NULL) { ConsoleHeapFree(FontBuff.ImageBits); return (ULONG)STATUS_SUCCESS; }
AlignCopyMemory((PVOID)ImageBits, // pDestBits
dwAlign, // dwDestAlign
FontImage->ImageBits,// pSrcBits
WORD_ALIGN, // dwSrcAlign
FontSize);
ConsoleHeapFree(FontBuff.ImageBits);
return (ULONG)STATUS_SUCCESS; }
ULONG GetFontImagePointer( IN PFONT_CACHE_INFORMATION FontCache, IN WCHAR wChar, IN COORD FontSize, OUT PFONT_IMAGE *FontImage ) { NTSTATUS Status;
if (FontSize.X == 0 && FontSize.Y == 0 ) { return (ULONG)(STATUS_INVALID_PARAMETER); }
Status = GetFontImageInternal(FontCache,wChar,FontSize,(PFONT_IMAGE*)FontImage,FONT_MATCHED); if (! NT_SUCCESS(Status) ) return (ULONG)Status;
if ((*FontImage)->ImageBits == NULL) return (ULONG)STATUS_ACCESS_DENIED;
return Status; }
ULONG SetFontImage( IN PFONT_CACHE_INFORMATION FontCache, IN WCHAR wChar, IN COORD FontSize, IN DWORD dwAlign, IN CONST VOID *ImageBits ) { return SetFontImageInternal(FontCache,wChar,FontSize,dwAlign,ImageBits); }
NTSTATUS GetExpandImage( COORD InputFontSize, PWORD InputFontImage, COORD OutputFontSize, PWORD OutputFontImage ) { NTSTATUS Status; DWORD InputRow = CALC_BITMAP_BITS_FOR_X(InputFontSize.X, BITMAP_BITS_WORD_ALIGN); DWORD OutputRow = CALC_BITMAP_BITS_FOR_X(OutputFontSize.X, BITMAP_BITS_WORD_ALIGN); DWORD InputBufferSize = CalcBitmapBufferSize(InputFontSize,WORD_ALIGN); DWORD OutputBufferSize = CalcBitmapBufferSize(OutputFontSize,WORD_ALIGN);
Status = STATUS_NO_MEMORY;
RtlZeroMemory(OutputFontImage,OutputBufferSize);
ASSERT(InputRow==OutputRow);
if (InputFontSize.Y < OutputFontSize.Y) RtlCopyMemory(OutputFontImage, InputFontImage, InputBufferSize); else RtlCopyMemory(OutputFontImage, InputFontImage, OutputBufferSize);
return STATUS_SUCCESS; }
NTSTATUS GetExpandFontImage( PFONT_CACHE_INFORMATION FontCache, WCHAR wChar, COORD InputFontSize, COORD OutputFontSize, PWORD OutputFontImage ) { NTSTATUS Status; DWORD InputBufferSize; PWORD InputFontImage;
if (InputFontSize.X == 0 && InputFontSize.Y == 0 ) { return (ULONG)(STATUS_INVALID_PARAMETER); }
if (OutputFontSize.X == 0 && OutputFontSize.Y == 0 ) { return (ULONG)(STATUS_INVALID_PARAMETER); }
InputBufferSize = CalcBitmapBufferSize(InputFontSize,WORD_ALIGN); InputFontImage = ConsoleHeapAlloc( HEAP_ZERO_MEMORY, InputBufferSize); if (InputFontImage==NULL) return STATUS_NO_MEMORY;
Status = GetFontImage(FontCache, wChar, InputFontSize, WORD_ALIGN, InputFontImage); if (! NT_SUCCESS(Status) ) { ConsoleHeapFree(InputFontImage); return Status; }
Status = GetExpandImage(InputFontSize, InputFontImage, OutputFontSize, OutputFontImage);
ConsoleHeapFree(InputFontImage);
return Status; } #endif
|