* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: text.c,v 1.82 2004/03/23 00:18:54 gvg Exp $ */
-
-
-#undef WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <ddk/ntddk.h>
-#include <napi/win32.h>
-#include <internal/safe.h>
-#include <win32k/brush.h>
-#include <win32k/dc.h>
-#include <win32k/text.h>
-#include <win32k/kapi.h>
-#include <include/error.h>
-#include <include/desktop.h>
+/* $Id: text.c,v 1.116 2004/12/13 01:45:18 royce Exp $ */
+#include <w32k.h>
+
#include <ft2build.h>
#include FT_FREETYPE_H
#include <freetype/tttables.h>
-#include "../eng/handle.h"
-
-#include <include/inteng.h>
-#include <include/text.h>
-#include <include/eng.h>
-#include <include/palette.h>
-#include <include/tags.h>
-
-#define NDEBUG
-#include <win32k/debug1.h>
-
FT_Library library;
typedef struct _FONT_ENTRY {
LIST_ENTRY ListEntry;
- HFONT hFont;
+ FONTGDI *Font;
UNICODE_STRING FaceName;
BYTE NotEnum;
} FONT_ENTRY, *PFONT_ENTRY;
static LIST_ENTRY FontListHead;
static FAST_MUTEX FontListLock;
-static INT FontsLoaded = 0; /* number of all fonts loaded (including private fonts */
static BOOL RenderingEnabled = TRUE;
static PWCHAR ElfScripts[32] = { /* these are in the order of the fsCsb[0] bits */
{ SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
};
+VOID FASTCALL
+IntLoadSystemFonts(VOID);
+
+INT FASTCALL
+IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics);
BOOL FASTCALL
-IntIsFontRenderingEnabled(VOID)
+InitFontSupport(VOID)
{
- BOOL Ret;
- HDC hDC;
- PDC dc;
- PSURFOBJ SurfObj;
- Ret = RenderingEnabled;
- hDC = IntGetScreenDC();
- if(hDC)
- {
- dc = DC_LockDc(hDC);
- SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
- if(SurfObj)
- Ret = (SurfObj->iBitmapFormat >= BMF_8BPP);
- DC_UnlockDc(hDC);
- }
- return Ret;
+ ULONG ulError;
+
+ InitializeListHead(&FontListHead);
+ ExInitializeFastMutex(&FontListLock);
+ ExInitializeFastMutex(&FreeTypeLock);
+
+ ulError = FT_Init_FreeType(&library);
+ if (ulError) {
+ DPRINT1("FT_Init_FreeType failed with error code 0x%x\n", ulError);
+ return FALSE;
+ }
+
+ IntLoadSystemFonts();
+
+ return TRUE;
}
+/*
+ * IntLoadSystemFonts
+ *
+ * Search the system font directory and adds each font found.
+ */
+
VOID FASTCALL
-IntEnableFontRendering(BOOL Enable)
+IntLoadSystemFonts(VOID)
{
- RenderingEnabled = Enable;
-}
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING Directory, SearchPattern, FileName, TempString;
+ IO_STATUS_BLOCK Iosb;
+ HANDLE hDirectory;
+ BYTE *DirInfoBuffer;
+ PFILE_DIRECTORY_INFORMATION DirInfo;
+ BOOL bRestartScan = TRUE;
+ NTSTATUS Status;
+
+ RtlInitUnicodeString(&Directory, L"\\SystemRoot\\media\\fonts\\");
+ /* FIXME: Add support for other font types */
+ RtlInitUnicodeString(&SearchPattern, L"*.ttf");
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &Directory,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = ZwOpenFile(
+ &hDirectory,
+ SYNCHRONIZE | FILE_LIST_DIRECTORY,
+ &ObjectAttributes,
+ &Iosb,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);
+
+ if (NT_SUCCESS(Status))
+ {
+ DirInfoBuffer = ExAllocatePool(PagedPool, 0x4000);
+ if (DirInfoBuffer == NULL)
+ {
+ ZwClose(hDirectory);
+ return;
+ }
+
+ FileName.Buffer = ExAllocatePool(PagedPool, MAX_PATH);
+ if (FileName.Buffer == NULL)
+ {
+ ExFreePool(DirInfoBuffer);
+ ZwClose(hDirectory);
+ return;
+ }
+ FileName.Length = 0;
+ FileName.MaximumLength = MAX_PATH;
-FT_Render_Mode FASTCALL
-IntGetFontRenderMode(LOGFONTW *logfont)
-{
- switch(logfont->lfQuality)
- {
- //case ANTIALIASED_QUALITY:
- case DEFAULT_QUALITY:
- return FT_RENDER_MODE_NORMAL;
- case DRAFT_QUALITY:
- return FT_RENDER_MODE_LIGHT;
- //case NONANTIALIASED_QUALITY:
- case PROOF_QUALITY:
- return FT_RENDER_MODE_MONO;
- //case CLEARTYPE_QUALITY:
- // return FT_RENDER_MODE_LCD;
- }
- return FT_RENDER_MODE_MONO;
+ while (1)
+ {
+ Status = ZwQueryDirectoryFile(
+ hDirectory,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ DirInfoBuffer,
+ 0x4000,
+ FileDirectoryInformation,
+ FALSE,
+ &SearchPattern,
+ bRestartScan);
+
+ if (!NT_SUCCESS(Status) || Status == STATUS_NO_MORE_FILES)
+ {
+ break;
+ }
+
+ DirInfo = (PFILE_DIRECTORY_INFORMATION)DirInfoBuffer;
+ while (1)
+ {
+ TempString.Buffer = DirInfo->FileName;
+ TempString.Length =
+ TempString.MaximumLength = DirInfo->FileNameLength;
+ RtlCopyUnicodeString(&FileName, &Directory);
+ RtlAppendUnicodeStringToString(&FileName, &TempString);
+ IntGdiAddFontResource(&FileName, 0);
+ if (DirInfo->NextEntryOffset == 0)
+ break;
+ DirInfo = (PFILE_DIRECTORY_INFORMATION)((ULONG_PTR)DirInfo + DirInfo->NextEntryOffset);
+ }
+
+ bRestartScan = FALSE;
+ }
+
+ ExFreePool(FileName.Buffer);
+ ExFreePool(DirInfoBuffer);
+ ZwClose(hDirectory);
+ }
}
-int FASTCALL
-IntGdiAddFontResource(PUNICODE_STRING Filename, DWORD fl)
+/*
+ * IntGdiAddFontResource
+ *
+ * Adds the font resource from the specified file to the system.
+ */
+
+INT FASTCALL
+IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
{
- HFONT NewFont;
- PFONTOBJ FontObj;
- PFONTGDI FontGDI;
- NTSTATUS Status;
- HANDLE FileHandle;
- OBJECT_ATTRIBUTES ObjectAttributes;
- FILE_STANDARD_INFORMATION FileStdInfo;
- PVOID buffer;
- ULONG size;
- INT error;
- FT_Face face;
- ANSI_STRING StringA;
- IO_STATUS_BLOCK Iosb;
- PFONT_ENTRY entry;
+ FONTGDI *FontGDI;
+ NTSTATUS Status;
+ HANDLE FileHandle;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ FILE_STANDARD_INFORMATION FileStdInfo;
+ PVOID Buffer;
+ IO_STATUS_BLOCK Iosb;
+ INT Error;
+ FT_Face Face;
+ ANSI_STRING AnsiFaceName;
+ PFONT_ENTRY Entry;
+
+ /* Open the font file */
+
+ InitializeObjectAttributes(&ObjectAttributes, FileName, 0, NULL, NULL);
+ Status = ZwOpenFile(
+ &FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &Iosb,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Could not font file: %wZ\n", FileName);
+ return 0;
+ }
- NewFont = (HFONT)CreateGDIHandle(sizeof( FONTGDI ), sizeof( FONTOBJ ));
- FontObj = (PFONTOBJ) AccessUserObject( (ULONG) NewFont );
- FontGDI = (PFONTGDI) AccessInternalObject( (ULONG) NewFont );
+ /* Get the size of the file */
- // Open the Module
- InitializeObjectAttributes(&ObjectAttributes, Filename, 0, NULL, NULL);
+ Status = NtQueryInformationFile(
+ FileHandle,
+ &Iosb,
+ &FileStdInfo,
+ sizeof(FileStdInfo),
+ FileStandardInformation);
- Status = ZwOpenFile(&FileHandle,
- GENERIC_READ|SYNCHRONIZE,
- &ObjectAttributes,
- &Iosb,
- 0, //ShareAccess
- FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Could not get file size\n");
+ ZwClose(FileHandle);
+ return 0;
+ }
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Could not open module file: %wZ\n", Filename);
- return 0;
- }
+ /* Allocate pageable memory for the font */
- // Get the size of the file
- Status = NtQueryInformationFile(FileHandle, &Iosb, &FileStdInfo, sizeof(FileStdInfo), FileStandardInformation);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Could not get file size\n");
- return 0;
- }
+ Buffer = ExAllocatePoolWithTag(
+ PagedPool,
+ FileStdInfo.EndOfFile.u.LowPart,
+ TAG_FNTFILE);
- // Allocate nonpageable memory for driver
- size = FileStdInfo.EndOfFile.u.LowPart;
- buffer = ExAllocatePoolWithTag(NonPagedPool, size, TAG_GDITEXT);
+ if (Buffer == NULL)
+ {
+ DPRINT("Could not allocate memory for font");
+ ZwClose(FileHandle);
+ return 0;
+ }
- if (buffer == NULL)
- {
- DPRINT1("could not allocate memory for module");
- return 0;
- }
+ /* Load the font into memory chunk */
- // Load driver into memory chunk
- Status = ZwReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- buffer,
- FileStdInfo.EndOfFile.u.LowPart,
- NULL,
- NULL);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("could not read module file into memory");
- ExFreePool(buffer);
- return 0;
- }
+ Status = ZwReadFile(
+ FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ Buffer,
+ FileStdInfo.EndOfFile.u.LowPart,
+ NULL,
+ NULL);
- ZwClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Could not read the font file into memory");
+ ExFreePool(Buffer);
+ ZwClose(FileHandle);
+ return 0;
+ }
- IntLockFreeType;
- error = FT_New_Memory_Face(library, buffer, size, 0, &face);
- IntUnLockFreeType;
- if (error == FT_Err_Unknown_File_Format)
- {
- DPRINT1("Unknown font file format\n");
- return 0;
- }
- else if (error)
- {
- DPRINT1("Error reading font file (error code: %u)\n", error); // 48
- return 0;
- }
-
- entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(FONT_ENTRY), TAG_FONT);
- if(!entry)
- {
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
- return 0;
- }
+ ZwClose(FileHandle);
- // FontGDI->Filename = Filename; perform strcpy
- FontGDI->face = face;
+ IntLockFreeType;
+ Error = FT_New_Memory_Face(
+ library,
+ Buffer,
+ FileStdInfo.EndOfFile.u.LowPart,
+ 0,
+ &Face);
+ IntUnLockFreeType;
- // FIXME: Complete text metrics
- FontGDI->TextMetric.tmAscent = (face->size->metrics.ascender + 32) >> 6; // units above baseline
- FontGDI->TextMetric.tmDescent = (32 - face->size->metrics.descender) >> 6; // units below baseline
- FontGDI->TextMetric.tmHeight = FontGDI->TextMetric.tmAscent + FontGDI->TextMetric.tmDescent;
+ if (Error)
+ {
+ if (Error == FT_Err_Unknown_File_Format)
+ DPRINT("Unknown font file format\n");
+ else
+ DPRINT("Error reading font file (error code: %u)\n", Error);
+ ExFreePool(Buffer);
+ return 0;
+ }
- DPRINT("Font loaded: %s (%s)\n", face->family_name, face->style_name);
- DPRINT("Num glyphs: %u\n", face->num_glyphs);
+ Entry = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_ENTRY), TAG_FONT);
+ if (!Entry)
+ {
+ FT_Done_Face(Face);
+ ExFreePool(Buffer);
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
- // Add this font resource to the font table
- entry->hFont = NewFont;
- entry->NotEnum = (fl & FR_NOT_ENUM);
- RtlInitAnsiString(&StringA, (LPSTR)face->family_name);
- RtlAnsiStringToUnicodeString(&entry->FaceName, &StringA, TRUE);
-
- if(fl & FR_PRIVATE)
- {
- PW32PROCESS Win32Process = PsGetWin32Process();
-
- IntLockProcessPrivateFonts(Win32Process);
- InsertTailList(&Win32Process->PrivateFontListHead, &entry->ListEntry);
- FontsLoaded++;
- IntUnLockProcessPrivateFonts(Win32Process);
- }
- else
- {
- IntLockGlobalFonts;
- InsertTailList(&FontListHead, &entry->ListEntry);
- FontsLoaded++;
- IntUnLockGlobalFonts;
- }
+ FontGDI = EngAllocMem(0, sizeof(FONTGDI), TAG_FONTOBJ);
+ if(FontGDI == NULL)
+ {
+ FT_Done_Face(Face);
+ ExFreePool(Buffer);
+ ExFreePool(Entry);
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
- return 1;
+ /* FontGDI->Filename = FileName; perform strcpy */
+ FontGDI->face = Face;
+
+ /* FIXME: Complete text metrics */
+ FontGDI->TextMetric.tmAscent = (Face->size->metrics.ascender + 32) >> 6; /* units above baseline */
+ FontGDI->TextMetric.tmDescent = (32 - Face->size->metrics.descender) >> 6; /* units below baseline */
+ FontGDI->TextMetric.tmHeight = (Face->size->metrics.ascender -
+ Face->size->metrics.descender) >> 6;
+
+ DPRINT("Font loaded: %s (%s)\n", Face->family_name, Face->style_name);
+ DPRINT("Num glyphs: %u\n", Face->num_glyphs);
+
+ /* Add this font resource to the font table */
+
+ Entry->Font = FontGDI;
+ Entry->NotEnum = (Characteristics & FR_NOT_ENUM);
+ RtlInitAnsiString(&AnsiFaceName, (LPSTR)Face->family_name);
+ RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE);
+
+ if (Characteristics & FR_PRIVATE)
+ {
+ PW32PROCESS Win32Process = PsGetWin32Process();
+ IntLockProcessPrivateFonts(Win32Process);
+ InsertTailList(&Win32Process->PrivateFontListHead, &Entry->ListEntry);
+ IntUnLockProcessPrivateFonts(Win32Process);
+ }
+ else
+ {
+ IntLockGlobalFonts;
+ InsertTailList(&FontListHead, &Entry->ListEntry);
+ IntUnLockGlobalFonts;
+ }
+
+ return 1;
}
-BOOL FASTCALL InitFontSupport(VOID)
+BOOL FASTCALL
+IntIsFontRenderingEnabled(VOID)
{
- ULONG ulError;
- UNICODE_STRING cchDir, cchFilename, cchSearchPattern ;
- OBJECT_ATTRIBUTES obAttr;
- IO_STATUS_BLOCK Iosb;
- HANDLE hDirectory;
- NTSTATUS Status;
- PFILE_DIRECTORY_INFORMATION iFileData;
- PVOID pBuff;
- BOOLEAN bRestartScan = TRUE;
- BOOLEAN Result = FALSE;
-
- InitializeListHead(&FontListHead);
- ExInitializeFastMutex(&FontListLock);
- ExInitializeFastMutex(&FreeTypeLock);
-
- ulError = FT_Init_FreeType(&library);
-
- if(!ulError)
- {
- RtlInitUnicodeString(&cchDir, L"\\SystemRoot\\Media\\Fonts\\");
-
- RtlInitUnicodeString(&cchSearchPattern,L"*.ttf");
- InitializeObjectAttributes( &obAttr,
- &cchDir,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL );
-
- Status = ZwOpenFile( &hDirectory,
- SYNCHRONIZE | FILE_LIST_DIRECTORY,
- &obAttr,
- &Iosb,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE );
- if( NT_SUCCESS(Status) )
- {
- while(1)
- {
- if (bRestartScan)
- {
- pBuff = ExAllocatePool(NonPagedPool,0x4000);
- if (pBuff == NULL)
- {
- break;
- }
- RtlInitUnicodeString(&cchFilename,0);
- cchFilename.MaximumLength = 0x1000;
- cchFilename.Buffer = ExAllocatePoolWithTag(PagedPool,cchFilename.MaximumLength, TAG_STRING);
- if (cchFilename.Buffer == NULL)
- {
- ExFreePool(pBuff);
- break;
- }
- }
-
- Status = NtQueryDirectoryFile( hDirectory,
- NULL,
- NULL,
- NULL,
- &Iosb,
- pBuff,
- 0x4000,
- FileDirectoryInformation,
- FALSE,
- &cchSearchPattern,
- bRestartScan );
-
- if( !NT_SUCCESS(Status) || Status == STATUS_NO_MORE_FILES )
- {
- ExFreePool(pBuff);
- ExFreePool(cchFilename.Buffer);
- break;
- }
- bRestartScan = FALSE;
- iFileData = (PFILE_DIRECTORY_INFORMATION)pBuff;
- while(1)
- {
- UNICODE_STRING tmpString;
- tmpString.Buffer = iFileData->FileName;
- tmpString.Length = tmpString.MaximumLength = iFileData->FileNameLength;
- RtlCopyUnicodeString(&cchFilename, &cchDir);
- RtlAppendUnicodeStringToString(&cchFilename, &tmpString);
- cchFilename.Buffer[cchFilename.Length / sizeof(WCHAR)] = 0;
- if (0 != IntGdiAddFontResource(&cchFilename, 0))
- {
- Result = TRUE;
- }
- if (iFileData->NextEntryOffset == 0)
- {
- break;
- }
- iFileData = (PVOID)iFileData + iFileData->NextEntryOffset;
- }
- }
- }
- }
- ZwClose(hDirectory);
- return Result;
+ BOOL Ret = RenderingEnabled;
+ HDC hDC;
+
+ hDC = IntGetScreenDC();
+ if (hDC)
+ Ret = (NtGdiGetDeviceCaps(hDC, BITSPIXEL) > 8) && RenderingEnabled;
+
+ return Ret;
}
-static NTSTATUS STDCALL
-GetFontObjectsFromTextObj(PTEXTOBJ TextObj, HFONT *FontHandle, PFONTOBJ *FontObj, PFONTGDI *FontGDI)
+VOID FASTCALL
+IntEnableFontRendering(BOOL Enable)
{
- NTSTATUS Status = STATUS_SUCCESS;
+ RenderingEnabled = Enable;
+}
- ASSERT(NULL != TextObj && NULL != TextObj->GDIFontHandle);
- if (NULL != TextObj && NULL != TextObj->GDIFontHandle)
- {
- if (NT_SUCCESS(Status) && NULL != FontHandle)
- {
- *FontHandle = TextObj->GDIFontHandle;
- }
- if (NT_SUCCESS(Status) && NULL != FontObj)
- {
- *FontObj = AccessUserObject((ULONG) TextObj->GDIFontHandle);
- if (NULL == *FontObj)
- {
- ASSERT(FALSE);
- Status = STATUS_INVALID_HANDLE;
- }
- }
- if (NT_SUCCESS(Status) && NULL != FontGDI)
- {
- *FontGDI = AccessInternalObject((ULONG) TextObj->GDIFontHandle);
- if (NULL == *FontGDI)
- {
- ASSERT(FALSE);
- Status = STATUS_INVALID_HANDLE;
- }
- }
- }
- else
+FT_Render_Mode FASTCALL
+IntGetFontRenderMode(LOGFONTW *logfont)
+{
+ switch(logfont->lfQuality)
{
- Status = STATUS_INVALID_HANDLE;
+ //case ANTIALIASED_QUALITY:
+ case DEFAULT_QUALITY:
+ return FT_RENDER_MODE_NORMAL;
+ case DRAFT_QUALITY:
+ return FT_RENDER_MODE_LIGHT;
+ //case NONANTIALIASED_QUALITY:
+ case PROOF_QUALITY:
+ return FT_RENDER_MODE_MONO;
+ //case CLEARTYPE_QUALITY:
+ // return FT_RENDER_MODE_LCD;
}
-
- return Status;
+ return FT_RENDER_MODE_MONO;
}
int
SetLastNtError(Status);
return 0;
}
+
+ /* Reserve for prepending '\??\' */
+ SafeFileName.Length += 4 * sizeof(WCHAR);
+ SafeFileName.MaximumLength += 4 * sizeof(WCHAR);
src = SafeFileName.Buffer;
SafeFileName.Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, SafeFileName.MaximumLength, TAG_STRING);
return 0;
}
- Status = MmCopyFromCaller(&SafeFileName.Buffer, src, SafeFileName.MaximumLength);
+ /* Prepend '\??\' */
+ RtlCopyMemory(SafeFileName.Buffer, L"\\??\\", 4 * sizeof(WCHAR));
+
+ Status = MmCopyFromCaller(SafeFileName.Buffer + 4, src, SafeFileName.MaximumLength - (4 * sizeof(WCHAR)));
if(!NT_SUCCESS(Status))
{
ExFreePool(SafeFileName.Buffer);
LPCWSTR FontFile,
LPCWSTR CurrentPath)
{
- UNIMPLEMENTED;
+ DPRINT1("NtGdiCreateScalableFontResource - is unimplemented, have a nice day and keep going");
+ return FALSE;
}
/*************************************************************************
}
else
{
- Needed += FamilyNameW.Length + StyleNameW.Length + 2 * sizeof(WCHAR); /* family + " " + style */
+ Needed += FamilyNameW.Length + StyleNameW.Length + (sizeof(WCHAR) << 1); /* family + " " + style */
}
/* length of otmpStyleName */
Needed += StyleNameW.Length + sizeof(WCHAR);
/* length of otmpFullName */
- Needed += FamilyNameW.Length + StyleNameW.Length + 2 * sizeof(WCHAR);
+ Needed += FamilyNameW.Length + StyleNameW.Length + (sizeof(WCHAR) << 1);
if (Size < Needed)
{
}
pPost = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_post); /* we can live with this failing */
- IntUnLockFreeType;
Otm->otmSize = Needed;
Otm->otmsUnderscorePosition = (FT_MulFix(pPost->underlinePosition, YScale) + 32) >> 6;
}
+ IntUnLockFreeType;
+
/* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
Cp = (char*) Otm + sizeof(OUTLINETEXTMETRICW);
Otm->otmpFamilyName = (LPSTR)(Cp - (char*) Otm);
{
wcscat((WCHAR*) Cp, L" ");
wcscat((WCHAR*) Cp, StyleNameW.Buffer);
- Cp += FamilyNameW.Length + StyleNameW.Length + 2 * sizeof(WCHAR);
+ Cp += FamilyNameW.Length + StyleNameW.Length + (sizeof(WCHAR) << 1);
}
else
{
PFONT_ENTRY CurrentEntry;
ANSI_STRING EntryFaceNameA;
UNICODE_STRING EntryFaceNameW;
- PFONTGDI FontGDI;
+ FONTGDI *FontGDI;
Entry = Head->Flink;
while (Entry != Head)
{
CurrentEntry = (PFONT_ENTRY) CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
- if (NULL == (FontGDI = AccessInternalObject((ULONG) CurrentEntry->hFont)))
- {
- Entry = Entry->Flink;
- continue;
- }
+ FontGDI = CurrentEntry->Font;
+ ASSERT(FontGDI);
+
RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name);
RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length)
Lf->lfHeight = TM->tmHeight;
Lf->lfWidth = TM->tmAveCharWidth;
Lf->lfWeight = TM->tmWeight;
+ Lf->lfItalic = TM->tmItalic;
Lf->lfPitchAndFamily = (TM->tmPitchAndFamily & 0xf1) + 1;
Lf->lfCharSet = TM->tmCharSet;
Lf->lfOutPrecision = OUT_STROKE_PRECIS;
PFONT_ENTRY CurrentEntry;
ANSI_STRING EntryFaceNameA;
UNICODE_STRING EntryFaceNameW;
- PFONTGDI FontGDI;
+ FONTGDI *FontGDI;
Entry = Head->Flink;
while (Entry != Head)
{
CurrentEntry = (PFONT_ENTRY) CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
- if (NULL == (FontGDI = AccessInternalObject((ULONG) CurrentEntry->hFont)))
- {
- Entry = Entry->Flink;
- continue;
- }
+ FontGDI = CurrentEntry->Font;
+ ASSERT(FontGDI);
+
RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name);
RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length)
LPARAM lParam)
{
UNIMPLEMENTED;
+ return 0;
}
BOOL STDCALL
CONST RECT *lprc,
LPCWSTR String,
UINT Count,
- CONST INT *lpDx)
+ CONST INT *UnsafeDx)
{
/*
* FIXME:
DC *dc;
SURFOBJ *SurfObj;
+ BITMAPOBJ *BitmapObj;
int error, glyph_index, n, i;
FT_Face face;
FT_GlyphSlot glyph;
- ULONG TextLeft, TextTop, pitch, previous, BackgroundLeft;
+ LONGLONG TextLeft, RealXStart;
+ ULONG TextTop, pitch, previous, BackgroundLeft;
FT_Bool use_kerning;
RECTL DestRect, MaskRect;
POINTL SourcePoint, BrushOrigin;
HBRUSH hBrushFg = NULL;
- PBRUSHOBJ BrushFg = NULL;
+ PGDIBRUSHOBJ BrushFg = NULL;
+ GDIBRUSHINST BrushFgInst;
HBRUSH hBrushBg = NULL;
- PBRUSHOBJ BrushBg = NULL;
+ PGDIBRUSHOBJ BrushBg = NULL;
+ GDIBRUSHINST BrushBgInst;
HBITMAP HSourceGlyph;
- PSURFOBJ SourceGlyphSurf;
+ SURFOBJ *SourceGlyphSurf;
SIZEL bitSize;
FT_CharMap found = 0, charmap;
INT yoff;
- PFONTOBJ FontObj;
+ FONTOBJ *FontObj;
PFONTGDI FontGDI;
- PTEXTOBJ TextObj;
+ PTEXTOBJ TextObj = NULL;
PPALGDI PalDestGDI;
- PXLATEOBJ XlateObj, XlateObj2;
+ XLATEOBJ *XlateObj, *XlateObj2;
ULONG Mode;
FT_Render_Mode RenderMode;
- BOOL Render;
+ BOOLEAN Render;
+ NTSTATUS Status;
+ INT *Dx = NULL;
+ POINT Start;
dc = DC_LockDc(hDC);
if (!dc)
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
+ }
+
+ if (NULL != UnsafeDx && Count > 0)
+ {
+ Dx = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), TAG_GDITEXT);
+ if (NULL == Dx)
+ {
+ goto fail;
+ }
+ Status = MmCopyFromCaller(Dx, UnsafeDx, Count * sizeof(INT));
+ if (! NT_SUCCESS(Status))
+ {
+ goto fail;
+ }
+ }
- SurfObj = (SURFOBJ*)AccessUserObject((ULONG) dc->Surface);
+ BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
+ ASSERT(BitmapObj);
+ SurfObj = &BitmapObj->SurfObj;
- XStart += dc->w.DCOrgX;
- YStart += dc->w.DCOrgY;
+ Start.x = XStart; Start.y = YStart;
+ IntLPtoDP(dc, &Start, 1);
- TextObj = TEXTOBJ_LockText(dc->w.hFont);
+ RealXStart = (Start.x + dc->w.DCOrgX) << 6;
+ YStart = Start.y + dc->w.DCOrgY;
- if (!NT_SUCCESS(GetFontObjectsFromTextObj(TextObj, NULL, &FontObj, &FontGDI)))
+ /* Create the brushes */
+ PalDestGDI = PALETTE_LockPalette(dc->w.hPalette);
+ if ( !PalDestGDI )
+ Mode = PAL_RGB;
+ else
{
- goto fail;
+ Mode = PalDestGDI->Mode;
+ PALETTE_UnlockPalette(dc->w.hPalette);
}
-
- face = FontGDI->face;
- if (face->charmap == NULL)
+ XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
+ hBrushFg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.textColor));
+ BrushFg = BRUSHOBJ_LockBrush(hBrushFg);
+ IntGdiInitBrushInstance(&BrushFgInst, BrushFg, NULL);
+ if ((fuOptions & ETO_OPAQUE) || dc->w.backgroundMode == OPAQUE)
{
- DPRINT("WARNING: No charmap selected!\n");
- DPRINT("This font face has %d charmaps\n", face->num_charmaps);
-
- for (n = 0; n < face->num_charmaps; n++)
+ hBrushBg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.backgroundColor));
+ if (hBrushBg)
{
- charmap = face->charmaps[n];
- DPRINT("found charmap encoding: %u\n", charmap->encoding);
- if (charmap->encoding != 0)
- {
- found = charmap;
- break;
- }
- }
- if (!found)
- DPRINT1("WARNING: Could not find desired charmap!\n");
- IntLockFreeType;
- error = FT_Set_Charmap(face, found);
- IntUnLockFreeType;
- if (error)
- DPRINT1("WARNING: Could not set the charmap!\n");
- }
-
- Render = IntIsFontRenderingEnabled();
- if (Render)
- RenderMode = IntGetFontRenderMode(&TextObj->logfont);
- else
- RenderMode = FT_RENDER_MODE_MONO;
-
- IntLockFreeType;
- error = FT_Set_Pixel_Sizes(
- face,
- /* FIXME should set character height if neg */
- (TextObj->logfont.lfHeight < 0 ?
- - TextObj->logfont.lfHeight :
- TextObj->logfont.lfHeight),
- TextObj->logfont.lfWidth);
- IntUnLockFreeType;
- if (error)
- {
- DPRINT1("Error in setting pixel sizes: %u\n", error);
- goto fail;
- }
-
- /* Create the brushes */
- PalDestGDI = PALETTE_LockPalette(dc->w.hPalette);
- if ( !PalDestGDI )
- Mode = PAL_RGB;
- else
- {
- Mode = PalDestGDI->Mode;
- PALETTE_UnlockPalette(dc->w.hPalette);
- }
- XlateObj = (PXLATEOBJ)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
- hBrushFg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.textColor));
- BrushFg = BRUSHOBJ_LockBrush(hBrushFg);
- if ((fuOptions & ETO_OPAQUE) || dc->w.backgroundMode == OPAQUE)
- {
- hBrushBg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.backgroundColor));
- if (hBrushBg)
- {
- BrushBg = BRUSHOBJ_LockBrush(hBrushBg);
+ BrushBg = BRUSHOBJ_LockBrush(hBrushBg);
+ /* FIXME - Handle BrushBg == NULL !!!!! */
+ IntGdiInitBrushInstance(&BrushBgInst, BrushBg, NULL);
}
else
{
goto fail;
}
}
- XlateObj2 = (PXLATEOBJ)IntEngCreateXlate(PAL_RGB, Mode, NULL, dc->w.hPalette);
+ XlateObj2 = (XLATEOBJ*)IntEngCreateXlate(PAL_RGB, Mode, NULL, dc->w.hPalette);
SourcePoint.x = 0;
SourcePoint.y = 0;
DestRect.right += dc->w.DCOrgX;
DestRect.bottom += dc->w.DCOrgY;
IntEngBitBlt(
- SurfObj,
+ BitmapObj,
NULL,
NULL,
dc->CombinedClip,
&DestRect,
&SourcePoint,
&SourcePoint,
- BrushBg,
+ &BrushBgInst.BrushObject,
&BrushOrigin,
PATCOPY);
fuOptions &= ~ETO_OPAQUE;
}
}
+ TextObj = TEXTOBJ_LockText(dc->w.hFont);
+ if(TextObj == NULL)
+ {
+ goto fail;
+ }
+
+ FontObj = TextObj->Font;
+ FontGDI = ObjToGDI(FontObj, FONT);
+
+ face = FontGDI->face;
+ if (face->charmap == NULL)
+ {
+ DPRINT("WARNING: No charmap selected!\n");
+ DPRINT("This font face has %d charmaps\n", face->num_charmaps);
+
+ for (n = 0; n < face->num_charmaps; n++)
+ {
+ charmap = face->charmaps[n];
+ DPRINT("found charmap encoding: %u\n", charmap->encoding);
+ if (charmap->encoding != 0)
+ {
+ found = charmap;
+ break;
+ }
+ }
+ if (!found)
+ DPRINT1("WARNING: Could not find desired charmap!\n");
+ IntLockFreeType;
+ error = FT_Set_Charmap(face, found);
+ IntUnLockFreeType;
+ if (error)
+ DPRINT1("WARNING: Could not set the charmap!\n");
+ }
+
+ Render = IntIsFontRenderingEnabled();
+ if (Render)
+ RenderMode = IntGetFontRenderMode(&TextObj->logfont);
+ else
+ RenderMode = FT_RENDER_MODE_MONO;
+
+ IntLockFreeType;
+ error = FT_Set_Pixel_Sizes(
+ face,
+ /* FIXME should set character height if neg */
+ (TextObj->logfont.lfHeight < 0 ?
+ - TextObj->logfont.lfHeight :
+ TextObj->logfont.lfHeight),
+ TextObj->logfont.lfWidth);
+ IntUnLockFreeType;
+ if (error)
+ {
+ DPRINT1("Error in setting pixel sizes: %u\n", error);
+ goto fail;
+ }
+
/*
* Process the vertical alignment and determine the yoff.
*/
if (dc->w.textAlign & (TA_RIGHT | TA_CENTER))
{
- UINT TextWidth;
+ ULONGLONG TextWidth = 0;
LPCWSTR TempText = String;
+ int Start;
/*
* Calculate width of the text.
*/
- for (i = 0; i < Count; i++)
+ if (NULL != Dx)
+ {
+ Start = Count < 2 ? 0 : Count - 2;
+ TextWidth = Count < 2 ? 0 : (Dx[Count - 2] << 6);
+ }
+ else
+ {
+ Start = 0;
+ }
+ TempText = String + Start;
+
+ for (i = Start; i < Count; i++)
{
IntLockFreeType;
glyph_index = FT_Get_Char_Index(face, *TempText);
IntLockFreeType;
FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
IntUnLockFreeType;
- TextWidth += delta.x >> 6;
+ TextWidth += delta.x;
}
- TextWidth += glyph->advance.x >> 6;
+ TextWidth += glyph->advance.x;
previous = glyph_index;
TempText++;
if (dc->w.textAlign & TA_RIGHT)
{
- XStart -= TextWidth;
+ RealXStart -= TextWidth;
}
else
{
- XStart -= TextWidth >> 1;
+ RealXStart -= TextWidth / 2;
}
}
- TextLeft = XStart;
+ TextLeft = RealXStart;
TextTop = YStart;
- BackgroundLeft = XStart;
+ BackgroundLeft = (RealXStart + 32) >> 6;
/*
* The main rendering loop.
glyph = face->glyph;
/* retrieve kerning distance and move pen position */
- if (use_kerning && previous && glyph_index)
+ if (use_kerning && previous && glyph_index && NULL == Dx)
{
FT_Vector delta;
IntLockFreeType;
FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
IntUnLockFreeType;
- TextLeft += delta.x >> 6;
+ TextLeft += delta.x;
}
if (glyph->format == ft_glyph_format_outline)
if (fuOptions & ETO_OPAQUE)
{
DestRect.left = BackgroundLeft;
- DestRect.right = TextLeft + ((glyph->advance.x + 32) >> 6);
+ DestRect.right = (TextLeft + glyph->advance.x + 32) >> 6;
DestRect.top = TextTop + yoff - ((face->size->metrics.ascender + 32) >> 6);
DestRect.bottom = TextTop + yoff + ((32 - face->size->metrics.descender) >> 6);
IntEngBitBlt(
- SurfObj,
+ BitmapObj,
NULL,
NULL,
dc->CombinedClip,
&DestRect,
&SourcePoint,
&SourcePoint,
- BrushBg,
+ &BrushBgInst.BrushObject,
&BrushOrigin,
PATCOPY);
BackgroundLeft = DestRect.right;
}
- DestRect.left = TextLeft;
- DestRect.right = TextLeft + glyph->bitmap.width;
+ DestRect.left = ((TextLeft + 32) >> 6) + glyph->bitmap_left;
+ DestRect.right = DestRect.left + glyph->bitmap.width;
DestRect.top = TextTop + yoff - glyph->bitmap_top;
DestRect.bottom = DestRect.top + glyph->bitmap.rows;
* limit the work of the transbitblt.
*/
- HSourceGlyph = EngCreateBitmap(bitSize, pitch, (glyph->bitmap.pixel_mode == ft_pixel_mode_grays) ? BMF_8BPP : BMF_1BPP, 0, glyph->bitmap.buffer);
- SourceGlyphSurf = (PSURFOBJ)AccessUserObject((ULONG) HSourceGlyph);
+ HSourceGlyph = EngCreateBitmap(bitSize, pitch, (glyph->bitmap.pixel_mode == ft_pixel_mode_grays) ? BMF_8BPP : BMF_1BPP, BMF_TOPDOWN, glyph->bitmap.buffer);
+ SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
/*
* Use the font data as a mask to paint onto the DCs surface using a
&DestRect,
&SourcePoint,
(PPOINTL)&MaskRect,
- BrushFg,
+ &BrushFgInst.BrushObject,
&BrushOrigin);
- EngDeleteSurface(HSourceGlyph);
+ EngUnlockSurface(SourceGlyphSurf);
+ EngDeleteSurface((HSURF)HSourceGlyph);
- TextLeft += (glyph->advance.x + 32) >> 6;
+ if (NULL == Dx)
+ {
+ TextLeft += glyph->advance.x;
+ }
+ else
+ {
+ TextLeft += Dx[i] << 6;
+ }
previous = glyph_index;
String++;
EngDeleteXlate(XlateObj);
EngDeleteXlate(XlateObj2);
- TEXTOBJ_UnlockText(dc->w.hFont);
+ BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
+ if(TextObj != NULL)
+ TEXTOBJ_UnlockText(dc->w.hFont);
if (hBrushBg != NULL)
{
BRUSHOBJ_UnlockBrush(hBrushBg);
}
BRUSHOBJ_UnlockBrush(hBrushFg);
NtGdiDeleteObject(hBrushFg);
- DC_UnlockDc(hDC);
+ if (NULL != Dx)
+ {
+ ExFreePool(Dx);
+ }
+ DC_UnlockDc( hDC );
return TRUE;
fail:
- TEXTOBJ_UnlockText(dc->w.hFont);
+ if(TextObj != NULL)
+ TEXTOBJ_UnlockText(dc->w.hFont);
+ BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
if (hBrushBg != NULL)
{
BRUSHOBJ_UnlockBrush(hBrushBg);
BRUSHOBJ_UnlockBrush(hBrushFg);
NtGdiDeleteObject(hBrushFg);
}
+ if (NULL != Dx)
+ {
+ ExFreePool(Dx);
+ }
DC_UnlockDc(hDC);
return FALSE;
LPSIZE AspectRatio)
{
UNIMPLEMENTED;
+ return FALSE;
}
BOOL
LPABCFLOAT abcF)
{
UNIMPLEMENTED;
+ return FALSE;
}
DWORD
DWORD Flags)
{
UNIMPLEMENTED;
-}
-
-BOOL
-STDCALL
-NtGdiGetCharWidth(HDC hDC,
- UINT FirstChar,
- UINT LastChar,
- LPINT Buffer)
-{
- DPRINT1("NtGdiGetCharWidth isnt really unimplemented - keep going anyway\n");
- return 1;
+ return 0;
}
BOOL
FT_Face face;
FT_CharMap charmap, found = NULL;
UINT i, glyph_index, BufferSize;
+ HFONT hFont = 0;
if (LastChar < FirstChar)
{
return FALSE;
}
- BufferSize = (LastChar - FirstChar) * sizeof(INT);
+ BufferSize = (LastChar - FirstChar + 1) * sizeof(INT);
SafeBuffer = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT);
if (SafeBuffer == NULL)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
- TextObj = TEXTOBJ_LockText(dc->w.hFont);
+ hFont = dc->w.hFont;
+ TextObj = TEXTOBJ_LockText(hFont);
DC_UnlockDc(hDC);
- GetFontObjectsFromTextObj(TextObj, NULL, NULL, &FontGDI);
+ if (TextObj == NULL)
+ {
+ ExFreePool(SafeBuffer);
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ FontGDI = ObjToGDI(TextObj->Font, FONT);
face = FontGDI->face;
if (face->charmap == NULL)
{
glyph_index = FT_Get_Char_Index(face, i);
FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
- SafeBuffer[i] = face->glyph->advance.x >> 6;
+ SafeBuffer[i - FirstChar] = (face->glyph->advance.x + 32) >> 6;
}
IntUnLockFreeType;
- TEXTOBJ_UnlockText(dc->w.hFont);
+ TEXTOBJ_UnlockText(hFont);
MmCopyToCaller(Buffer, SafeBuffer, BufferSize);
ExFreePool(SafeBuffer);
return TRUE;
PFLOAT Buffer)
{
UNIMPLEMENTED;
+ return FALSE;
}
DWORD
NtGdiGetFontLanguageInfo(HDC hDC)
{
UNIMPLEMENTED;
+ return 0;
}
DWORD
CONST LPMAT2 mat2)
{
UNIMPLEMENTED;
-
-
+ return 0;
}
DWORD
LPKERNINGPAIR krnpair)
{
UNIMPLEMENTED;
+ return 0;
}
UINT
LPOUTLINETEXTMETRICW otm)
{
UNIMPLEMENTED;
+ return 0;
}
BOOL
UINT Size)
{
UNIMPLEMENTED;
+ return FALSE;
}
UINT
NtGdiGetTextCharset(HDC hDC)
{
UNIMPLEMENTED;
+ return 0;
}
UINT
DWORD Flags)
{
UNIMPLEMENTED;
+ return 0;
}
static BOOL
FASTCALL
-TextIntGetTextExtentPoint(HDC hDC,
+TextIntGetTextExtentPoint(PDC dc,
PTEXTOBJ TextObj,
LPCWSTR String,
int Count,
FT_Face face;
FT_GlyphSlot glyph;
INT error, n, glyph_index, i, previous;
- LONG TotalWidth = 0;
+ ULONGLONG TotalWidth = 0;
FT_CharMap charmap, found = NULL;
BOOL use_kerning;
- GetFontObjectsFromTextObj(TextObj, NULL, NULL, &FontGDI);
+ FontGDI = ObjToGDI(TextObj->Font, FONT);
+
face = FontGDI->face;
if (NULL != Fit)
{
IntLockFreeType;
FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
IntUnLockFreeType;
- TotalWidth += delta.x >> 6;
+ TotalWidth += delta.x;
}
- TotalWidth += glyph->advance.x >> 6;
+ TotalWidth += glyph->advance.x;
- if (TotalWidth <= MaxExtent && NULL != Fit)
+ if (((TotalWidth + 32) >> 6) <= MaxExtent && NULL != Fit)
{
*Fit = i + 1;
}
if (NULL != Dx)
{
- Dx[i] = TotalWidth;
+ Dx[i] = (TotalWidth + 32) >> 6;
}
previous = glyph_index;
String++;
}
- Size->cx = TotalWidth;
+ Size->cx = (TotalWidth + 32) >> 6;
Size->cy = (TextObj->logfont.lfHeight < 0 ? - TextObj->logfont.lfHeight : TextObj->logfont.lfHeight);
- Size->cy = EngMulDiv(Size->cy, NtGdiGetDeviceCaps(hDC, LOGPIXELSY), 72);
+ Size->cy = EngMulDiv(Size->cy, IntGdiGetDeviceCaps(dc, LOGPIXELSY), 72);
return TRUE;
}
return FALSE;
}
TextObj = TEXTOBJ_LockText(dc->w.hFont);
- DC_UnlockDc(hDC);
- Result = TextIntGetTextExtentPoint(hDC, TextObj, String, Count, MaxExtent,
+ if ( TextObj )
+ {
+ Result = TextIntGetTextExtentPoint(dc, TextObj, String, Count, MaxExtent,
NULL == UnsafeFit ? NULL : &Fit, Dx, &Size);
+ }
+ else
+ Result = FALSE;
TEXTOBJ_UnlockText(dc->w.hFont);
+ DC_UnlockDc(hDC);
ExFreePool(String);
if (! Result)
return FALSE;
}
TextObj = TEXTOBJ_LockText(dc->w.hFont);
- DC_UnlockDc(hDC);
- Result = TextIntGetTextExtentPoint (
- hDC, TextObj, String, Count, 0, NULL, NULL, &Size);
- dc = DC_LockDc(hDC);
- ASSERT(dc); // it succeeded earlier, it should now, too
- TEXTOBJ_UnlockText(dc->w.hFont);
+ if ( TextObj != NULL )
+ {
+ Result = TextIntGetTextExtentPoint (
+ dc, TextObj, String, Count, 0, NULL, NULL, &Size);
+ TEXTOBJ_UnlockText(dc->w.hFont);
+ }
+ else
+ Result = FALSE;
DC_UnlockDc(hDC);
ExFreePool(String);
return TRUE;
}
-int
-STDCALL
-NtGdiGetTextFace(HDC hDC,
- int Count,
- LPWSTR FaceName)
+INT STDCALL
+NtGdiGetTextFace(HDC hDC, INT Count, LPWSTR FaceName)
{
- UNIMPLEMENTED;
+ PDC Dc;
+ PTEXTOBJ TextObj;
+ NTSTATUS Status;
+
+ Dc = DC_LockDc(hDC);
+ if (Dc == NULL)
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+ TextObj = TEXTOBJ_LockText(Dc->w.hFont);
+ DC_UnlockDc(hDC);
+
+ Count = min(Count, wcslen(TextObj->logfont.lfFaceName));
+ Status = MmCopyToCaller(FaceName, TextObj->logfont.lfFaceName, Count * sizeof(WCHAR));
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ return 0;
+ }
+
+ return Count;
}
BOOL
TT_OS2 *pOS2;
ULONG Error;
- dc = DC_LockDc(hDC);
- if (NULL == dc || NULL == tm)
+ if (NULL == tm)
{
- Status = STATUS_INVALID_PARAMETER;
+ SetLastWin32Error(STATUS_INVALID_PARAMETER);
+ return FALSE;
}
- else
+
+ if(!(dc = DC_LockDc(hDC)))
{
- TextObj = TEXTOBJ_LockText(dc->w.hFont);
- if (NULL != TextObj)
- {
- Status = GetFontObjectsFromTextObj(TextObj, NULL, NULL, &FontGDI);
- if (NT_SUCCESS(Status))
- {
- Face = FontGDI->face;
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ TextObj = TEXTOBJ_LockText(dc->w.hFont);
+ if (NULL != TextObj)
+ {
+ FontGDI = ObjToGDI(TextObj->Font, FONT);
+
+ Face = FontGDI->face;
+ IntLockFreeType;
+ Error = FT_Set_Pixel_Sizes(Face,
+ /* FIXME should set character height if neg */
+ (TextObj->logfont.lfHeight < 0 ?
+ - TextObj->logfont.lfHeight :
+ TextObj->logfont.lfHeight),
+ TextObj->logfont.lfWidth);
+ IntUnLockFreeType;
+ if (0 != Error)
+ {
+ DPRINT1("Error in setting pixel sizes: %u\n", Error);
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ memcpy(&SafeTm, &FontGDI->TextMetric, sizeof(TEXTMETRICW));
IntLockFreeType;
- Error = FT_Set_Pixel_Sizes(Face,
- /* FIXME should set character height if neg */
- (TextObj->logfont.lfHeight < 0 ?
- - TextObj->logfont.lfHeight :
- TextObj->logfont.lfHeight),
- TextObj->logfont.lfWidth);
+ pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
IntUnLockFreeType;
- if (0 != Error)
- {
- DPRINT1("Error in setting pixel sizes: %u\n", Error);
- Status = STATUS_UNSUCCESSFUL;
- }
+ if (NULL == pOS2)
+ {
+ DPRINT1("Can't find OS/2 table - not TT font?\n");
+ Status = STATUS_UNSUCCESSFUL;
+ }
else
- {
- memcpy(&SafeTm, &FontGDI->TextMetric, sizeof(TEXTMETRICW));
- IntLockFreeType;
- pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
- IntUnLockFreeType;
- if (NULL == pOS2)
- {
- DPRINT1("Can't find OS/2 table - not TT font?\n");
- Status = STATUS_UNSUCCESSFUL;
- }
- else
- {
- SafeTm.tmAveCharWidth = (pOS2->xAvgCharWidth + 32) >> 6;
- }
- SafeTm.tmAscent = (Face->size->metrics.ascender + 32) >> 6; // units above baseline
- SafeTm.tmDescent = (32 - Face->size->metrics.descender) >> 6; // units below baseline
- SafeTm.tmHeight = SafeTm.tmAscent + SafeTm.tmDescent;
- SafeTm.tmMaxCharWidth = (Face->size->metrics.max_advance + 32) >> 6;
- Status = MmCopyToCaller(tm, &SafeTm, sizeof(TEXTMETRICW));
- }
- }
- TEXTOBJ_UnlockText(dc->w.hFont);
- }
- else
+ {
+ SafeTm.tmAveCharWidth = (pOS2->xAvgCharWidth + 32) >> 6;
+ }
+ SafeTm.tmAscent = (Face->size->metrics.ascender + 32) >> 6; // units above baseline
+ SafeTm.tmDescent = (32 - Face->size->metrics.descender) >> 6; // units below baseline
+ SafeTm.tmHeight = SafeTm.tmAscent + SafeTm.tmDescent;
+ SafeTm.tmMaxCharWidth = (Face->size->metrics.max_advance + 32) >> 6;
+ if (FT_IS_SFNT(FontGDI->face))
{
- ASSERT(FALSE);
- Status = STATUS_INVALID_HANDLE;
+ SafeTm.tmPitchAndFamily |= TMPF_TRUETYPE;
}
- DC_UnlockDc(hDC);
+ Status = MmCopyToCaller(tm, &SafeTm, sizeof(TEXTMETRICW));
+ }
+ TEXTOBJ_UnlockText(dc->w.hFont);
}
-
- return NT_SUCCESS(Status);
+ else
+ {
+ Status = STATUS_INVALID_HANDLE;
+ }
+ DC_UnlockDc(hDC);
+
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ return FALSE;
+ }
+
+ return TRUE;
}
BOOL
int Count)
{
UNIMPLEMENTED;
+ return FALSE;
}
BOOL
NtGdiRemoveFontResource(LPCWSTR FileName)
{
UNIMPLEMENTED;
+ return FALSE;
}
DWORD
DWORD Flag)
{
UNIMPLEMENTED;
+ return 0;
}
UINT
dc = DC_LockDc(hDC);
if (!dc)
{
- return 0;
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return GDI_ERROR;
}
prevAlign = dc->w.textAlign;
dc->w.textAlign = Mode;
{
COLORREF oldColor;
PDC dc = DC_LockDc(hDC);
+ HBRUSH hBrush;
if (!dc)
{
- return 0x80000000;
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return CLR_INVALID;
}
oldColor = dc->w.textColor;
dc->w.textColor = color;
+ hBrush = dc->w.hBrush;
DC_UnlockDc( hDC );
+ NtGdiSelectObject(hDC, hBrush);
return oldColor;
}
int BreakCount)
{
UNIMPLEMENTED;
+ return FALSE;
}
BOOL STDCALL
return NtGdiExtTextOut(hDC, XStart, YStart, 0, NULL, String, Count, NULL);
}
+DWORD STDCALL
+NtGdiGetFontData(
+ HDC hDC,
+ DWORD Table,
+ DWORD Offset,
+ LPVOID Buffer,
+ DWORD Size)
+{
+ PDC Dc;
+ HFONT hFont;
+ PTEXTOBJ TextObj;
+ PFONTGDI FontGdi;
+ DWORD Result = GDI_ERROR;
+
+ Dc = DC_LockDc(hDC);
+ if (Dc == NULL)
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return GDI_ERROR;
+ }
+ hFont = Dc->w.hFont;
+ TextObj = TEXTOBJ_LockText(hFont);
+ DC_UnlockDc(hDC);
+
+ if (TextObj == NULL)
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return GDI_ERROR;
+ }
+
+ FontGdi = ObjToGDI(TextObj->Font, FONT);
+
+ IntLockFreeType;
+
+ if (FT_IS_SFNT(FontGdi->face))
+ {
+ if (Table)
+ Table = Table >> 24 | Table << 24 | (Table >> 8 & 0xFF00) |
+ (Table << 8 & 0xFF0000);
+
+ if (Buffer == NULL)
+ Size = 0;
+
+ if (!FT_Load_Sfnt_Table(FontGdi->face, Table, Offset, Buffer, &Size))
+ Result = Size;
+ }
+
+ IntUnLockFreeType;
+
+ TEXTOBJ_UnlockText(hFont);
+
+ return Result;
+}
+
+static UINT FASTCALL
+GetFontScore(LOGFONTW *LogFont, PUNICODE_STRING FaceName, PFONTGDI FontGDI)
+{
+ ANSI_STRING EntryFaceNameA;
+ UNICODE_STRING EntryFaceNameW;
+ unsigned Size;
+ OUTLINETEXTMETRICW *Otm;
+ LONG WeightDiff;
+ NTSTATUS Status;
+ UINT Score = 1;
+
+ RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name);
+ Status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
+ if (NT_SUCCESS(Status))
+ {
+ if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length)
+ {
+ EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR);
+ EntryFaceNameW.Buffer[LF_FACESIZE - 1] = L'\0';
+ }
+ if (0 == RtlCompareUnicodeString(FaceName, &EntryFaceNameW, TRUE))
+ {
+ Score += 49;
+ }
+ RtlFreeUnicodeString(&EntryFaceNameW);
+ }
+
+ Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
+ Otm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
+ if (NULL == Otm)
+ {
+ return Score;
+ }
+ IntGetOutlineTextMetrics(FontGDI, Size, Otm);
+
+ if ((0 != LogFont->lfItalic && 0 != Otm->otmTextMetrics.tmItalic) ||
+ (0 == LogFont->lfItalic && 0 == Otm->otmTextMetrics.tmItalic))
+ {
+ Score += 25;
+ }
+ if (LogFont->lfWeight < Otm->otmTextMetrics.tmWeight)
+ {
+ WeightDiff = Otm->otmTextMetrics.tmWeight - LogFont->lfWeight;
+ }
+ else
+ {
+ WeightDiff = LogFont->lfWeight - Otm->otmTextMetrics.tmWeight;
+ }
+ Score += (1000 - WeightDiff) / (1000 / 25);
+
+ ExFreePool(Otm);
+
+ return Score;
+}
+
+static inline VOID
+FindBestFontFromList(FONTOBJ **FontObj, UINT *MatchScore, LOGFONTW *LogFont,
+ PUNICODE_STRING FaceName, PLIST_ENTRY Head)
+{
+ PLIST_ENTRY Entry;
+ PFONT_ENTRY CurrentEntry;
+ FONTGDI *FontGDI;
+ UINT Score;
+
+ Entry = Head->Flink;
+ while (Entry != Head)
+ {
+ CurrentEntry = (PFONT_ENTRY) CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
+
+ FontGDI = CurrentEntry->Font;
+ ASSERT(FontGDI);
+
+ Score = GetFontScore(LogFont, FaceName, FontGDI);
+ if (*MatchScore == 0 || *MatchScore < Score)
+ {
+ *FontObj = GDIToObj(FontGDI, FONT);
+ *MatchScore = Score;
+ }
+ Entry = Entry->Flink;
+ }
+}
+
+static inline BOOLEAN
+SubstituteFontFamilyKey(PUNICODE_STRING FaceName,
+ LPCWSTR Key)
+{
+ RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ NTSTATUS Status;
+ UNICODE_STRING Value;
+
+ RtlInitUnicodeString(&Value, NULL);
+
+ QueryTable[0].QueryRoutine = NULL;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND |
+ RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].Name = FaceName->Buffer;
+ QueryTable[0].EntryContext = &Value;
+ QueryTable[0].DefaultType = REG_NONE;
+ QueryTable[0].DefaultData = NULL;
+ QueryTable[0].DefaultLength = 0;
+
+ QueryTable[1].QueryRoutine = NULL;
+ QueryTable[1].Name = NULL;
+
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
+ Key,
+ QueryTable,
+ NULL,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ RtlFreeUnicodeString(FaceName);
+ *FaceName = Value;
+ }
+
+ return NT_SUCCESS(Status);
+}
+
+static inline void
+SubstituteFontFamily(PUNICODE_STRING FaceName, UINT Level)
+{
+ if (10 < Level) /* Enough is enough */
+ {
+ return;
+ }
+
+ if (SubstituteFontFamilyKey(FaceName, L"SysFontSubstitutes") ||
+ SubstituteFontFamilyKey(FaceName, L"FontSubstitutes"))
+ {
+ SubstituteFontFamily(FaceName, Level + 1);
+ }
+}
+
NTSTATUS FASTCALL
TextIntRealizeFont(HFONT FontHandle)
{
NTSTATUS Status = STATUS_SUCCESS;
PTEXTOBJ TextObj;
UNICODE_STRING FaceName;
- PLIST_ENTRY Entry;
- PFONT_ENTRY CurrentEntry;
PW32PROCESS Win32Process;
- BOOL Private = FALSE;
+ UINT MatchScore;
TextObj = TEXTOBJ_LockText(FontHandle);
- ASSERT(TextObj);
- if (NULL != TextObj)
+ if (NULL == TextObj)
{
- RtlInitUnicodeString(&FaceName, TextObj->logfont.lfFaceName);
-
- /* find font in private fonts */
- Win32Process = PsGetWin32Process();
-
- IntLockProcessPrivateFonts(Win32Process);
-
- Entry = Win32Process->PrivateFontListHead.Flink;
- while(Entry != &Win32Process->PrivateFontListHead)
+ return STATUS_INVALID_HANDLE;
+ }
+
+ if (! RtlCreateUnicodeString(&FaceName, TextObj->logfont.lfFaceName))
{
- CurrentEntry = (PFONT_ENTRY)CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
-
- if (0 == RtlCompareUnicodeString(&CurrentEntry->FaceName, &FaceName, TRUE))
- {
- TextObj->GDIFontHandle = CurrentEntry->hFont;
- Private = TRUE;
- goto check;
- }
- Entry = Entry->Flink;
+ TEXTOBJ_UnlockText(FontHandle);
+ return STATUS_NO_MEMORY;
}
- IntUnLockProcessPrivateFonts(Win32Process);
+ SubstituteFontFamily(&FaceName, 0);
+ MatchScore = 0;
+ TextObj->Font = NULL;
- /* find font in system fonts */
- IntLockGlobalFonts;
+ /* First search private fonts */
+ Win32Process = PsGetWin32Process();
+ IntLockProcessPrivateFonts(Win32Process);
+ FindBestFontFromList(&TextObj->Font, &MatchScore,
+ &TextObj->logfont, &FaceName,
+ &Win32Process->PrivateFontListHead);
+ IntUnLockProcessPrivateFonts(Win32Process);
- Entry = FontListHead.Flink;
- while(Entry != &FontListHead)
+ /* Search system fonts */
+ IntLockGlobalFonts;
+ FindBestFontFromList(&TextObj->Font, &MatchScore,
+ &TextObj->logfont, &FaceName,
+ &FontListHead);
+ IntUnLockGlobalFonts;
+
+ if (NULL == TextObj->Font)
{
- CurrentEntry = (PFONT_ENTRY)CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
-
- if (0 == RtlCompareUnicodeString(&CurrentEntry->FaceName, &FaceName, TRUE))
- {
- TextObj->GDIFontHandle = CurrentEntry->hFont;
- break;
- }
- Entry = Entry->Flink;
+ DPRINT1("Requested font %S not found, no fonts loaded at all\n",
+ TextObj->logfont.lfFaceName);
+ Status = STATUS_NOT_FOUND;
}
-
- check:
- if (NULL == TextObj->GDIFontHandle)
+ else
{
- Entry = (Private ? Win32Process->PrivateFontListHead.Flink : FontListHead.Flink);
-
- if(Entry != (Private ? &Win32Process->PrivateFontListHead : &FontListHead))
- {
- DPRINT("Requested font %S not found, using first available font\n",
- TextObj->logfont.lfFaceName)
- CurrentEntry = (PFONT_ENTRY)CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
- TextObj->GDIFontHandle = CurrentEntry->hFont;
- }
- else
- {
- DPRINT1("Requested font %S not found, no fonts loaded at all\n",
- TextObj->logfont.lfFaceName);
- Status = STATUS_NOT_FOUND;
- }
-
+ Status = STATUS_SUCCESS;
}
-
- if(Private)
- IntUnLockProcessPrivateFonts(Win32Process);
- else
- IntUnLockGlobalFonts;
-
- ASSERT(! NT_SUCCESS(Status) || NULL != TextObj->GDIFontHandle);
- TEXTOBJ_UnlockText(FontHandle);
- }
- else
- {
- Status = STATUS_INVALID_HANDLE;
- }
+ RtlFreeUnicodeString(&FaceName);
+ TEXTOBJ_UnlockText(FontHandle);
+
+ ASSERT((NT_SUCCESS(Status) ^ (NULL == TextObj->Font)) != 0);
return Status;
}
+INT FASTCALL
+FontGetObject(PTEXTOBJ Font, INT Count, PVOID Buffer)
+{
+ if (Count < sizeof(LOGFONTW))
+ {
+ SetLastWin32Error(ERROR_BUFFER_OVERFLOW);
+ return 0;
+ }
+
+ RtlCopyMemory(Buffer, &Font->logfont, sizeof(LOGFONTW));
+
+ return sizeof(LOGFONTW);
+}
+
/* EOF */