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

/*++
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