* 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.97 2004/06/20 00:45:37 navaraf Exp $ */
+/* $Id$ */
+
#include <w32k.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <freetype/tttables.h>
+#define NDEBUG
+#include <debug.h>
+
FT_Library library;
typedef struct _FONT_ENTRY {
LIST_ENTRY ListEntry;
- HFONT hFont;
+ FONTGDI *Font;
UNICODE_STRING FaceName;
BYTE NotEnum;
} FONT_ENTRY, *PFONT_ENTRY;
{ DEFAULT_CHARSET, 0, FS(0)},
/* reserved for system */
{ DEFAULT_CHARSET, 0, FS(0)},
- { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
+ { SYMBOL_CHARSET, 42 /* CP_SYMBOL */, FS(31)},
};
VOID FASTCALL
ExInitializeFastMutex(&FreeTypeLock);
ulError = FT_Init_FreeType(&library);
- if (ulError)
+ if (ulError) {
+ DPRINT1("FT_Init_FreeType failed with error code 0x%x\n", ulError);
return FALSE;
+ }
IntLoadSystemFonts();
BOOL bRestartScan = TRUE;
NTSTATUS Status;
- RtlInitUnicodeString(&Directory, L"\\SystemRoot\\Media\\Fonts\\");
+ RtlInitUnicodeString(&Directory, L"\\SystemRoot\\media\\fonts\\");
/* FIXME: Add support for other font types */
RtlInitUnicodeString(&SearchPattern, L"*.ttf");
ZwClose(hDirectory);
return;
}
-
- FileName.Buffer = ExAllocatePool(PagedPool, MAX_PATH);
+
+ FileName.Buffer = ExAllocatePool(PagedPool, MAX_PATH * sizeof(WCHAR));
if (FileName.Buffer == NULL)
{
ExFreePool(DirInfoBuffer);
return;
}
FileName.Length = 0;
- FileName.MaximumLength = MAX_PATH;
+ FileName.MaximumLength = MAX_PATH * sizeof(WCHAR);
while (1)
{
break;
}
- for (DirInfo = (PFILE_DIRECTORY_INFORMATION)DirInfoBuffer;
- DirInfo->NextEntryOffset != 0;
- DirInfo = (PFILE_DIRECTORY_INFORMATION)((ULONG_PTR)DirInfo + DirInfo->NextEntryOffset))
+ DirInfo = (PFILE_DIRECTORY_INFORMATION)DirInfoBuffer;
+ while (1)
{
TempString.Buffer = DirInfo->FileName;
TempString.Length =
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;
INT FASTCALL
IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
{
- HFONT NewFont;
- FONTOBJ *FontObj;
- PFONTGDI FontGDI;
+ FONTGDI *FontGDI;
NTSTATUS Status;
HANDLE FileHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
- FILE_STANDARD_INFORMATION FileStdInfo;
- PVOID Buffer;
+ PVOID Buffer = NULL;
IO_STATUS_BLOCK Iosb;
INT Error;
FT_Face Face;
ANSI_STRING AnsiFaceName;
PFONT_ENTRY Entry;
-
- /* Create handle for the font */
-
- NewFont = (HFONT)CreateGDIHandle(
- sizeof(FONTGDI),
- sizeof(FONTOBJ),
- (PVOID*)&FontGDI,
- (PVOID*)&FontObj);
-
- if (NewFont == 0)
- {
- DPRINT("Could not allocate a new GDI font object\n");
- return 0;
- }
+ PSECTION_OBJECT SectionObject;
+ ULONG ViewSize = 0;
/* Open the font file */
InitializeObjectAttributes(&ObjectAttributes, FileName, 0, NULL, NULL);
Status = ZwOpenFile(
&FileHandle,
- GENERIC_READ | SYNCHRONIZE,
+ FILE_GENERIC_READ | SYNCHRONIZE,
&ObjectAttributes,
&Iosb,
- 0,
+ FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(Status))
{
- DPRINT("Could not font file: %wZ\n", Filename);
- NtGdiDeleteObject(NewFont);
+ DPRINT("Could not font file: %wZ\n", FileName);
return 0;
}
- /* Get the size of the file */
-
- Status = NtQueryInformationFile(
- FileHandle,
- &Iosb,
- &FileStdInfo,
- sizeof(FileStdInfo),
- FileStandardInformation);
-
+ Status = MmCreateSection(&SectionObject, SECTION_ALL_ACCESS,
+ NULL, NULL, PAGE_READONLY,
+ 0, FileHandle, NULL);
if (!NT_SUCCESS(Status))
{
- DPRINT("Could not get file size\n");
- NtGdiDeleteObject(NewFont);
+ DPRINT("Could not map file: %wZ\n", FileName);
ZwClose(FileHandle);
return 0;
}
- /* Allocate pageable memory for the font */
-
- Buffer = ExAllocatePoolWithTag(
- PagedPool,
- FileStdInfo.EndOfFile.u.LowPart,
- TAG_GDITEXT);
-
- if (Buffer == NULL)
- {
- DPRINT("Could not allocate memory for font");
- NtGdiDeleteObject(NewFont);
- ZwClose(FileHandle);
- return 0;
- }
-
- /* Load the font into memory chunk */
-
- Status = ZwReadFile(
- FileHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- Buffer,
- FileStdInfo.EndOfFile.u.LowPart,
- NULL,
- NULL);
+ ZwClose(FileHandle);
+ Status = MmMapViewInSystemSpace(SectionObject, &Buffer, &ViewSize);
if (!NT_SUCCESS(Status))
{
- DPRINT("Could not read the font file into memory");
- ExFreePool(Buffer);
- NtGdiDeleteObject(NewFont);
- ZwClose(FileHandle);
- return 0;
+ DPRINT("Could not map file: %wZ\n", FileName);
+ return Status;
}
- ZwClose(FileHandle);
-
IntLockFreeType;
Error = FT_New_Memory_Face(
library,
Buffer,
- FileStdInfo.EndOfFile.u.LowPart,
+ ViewSize,
0,
&Face);
IntUnLockFreeType;
DPRINT("Unknown font file format\n");
else
DPRINT("Error reading font file (error code: %u)\n", Error);
- ExFreePool(Buffer);
- NtGdiDeleteObject(NewFont);
+ ObDereferenceObject(SectionObject);
return 0;
}
if (!Entry)
{
FT_Done_Face(Face);
- ExFreePool(Buffer);
+ ObDereferenceObject(SectionObject);
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
+
+ FontGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(FONTGDI), TAG_FONTOBJ);
+ if(FontGDI == NULL)
+ {
+ FT_Done_Face(Face);
+ ObDereferenceObject(SectionObject);
+ ExFreePool(Entry);
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
/* 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;
+ 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);
+ 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->hFont = NewFont;
+ Entry->Font = FontGDI;
Entry->NotEnum = (Characteristics & FR_NOT_ENUM);
RtlInitAnsiString(&AnsiFaceName, (LPSTR)Face->family_name);
RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE);
BOOL FASTCALL
IntIsFontRenderingEnabled(VOID)
{
- BOOL Ret;
- HDC hDC;
- PDC dc;
- SURFOBJ *SurfObj;
- Ret = RenderingEnabled;
- hDC = IntGetScreenDC();
- if(hDC)
- {
- dc = DC_LockDc(hDC);
- SurfObj = (SURFOBJ*)AccessUserObject((ULONG) dc->Surface);
- if(SurfObj)
- Ret = (SurfObj->iBitmapFormat >= BMF_8BPP);
- DC_UnlockDc(hDC);
- }
- return Ret;
+ BOOL Ret = RenderingEnabled;
+ HDC hDC;
+
+ hDC = IntGetScreenDC();
+ if (hDC)
+ Ret = (NtGdiGetDeviceCaps(hDC, BITSPIXEL) > 8) && RenderingEnabled;
+
+ return Ret;
}
VOID FASTCALL
FT_Render_Mode FASTCALL
IntGetFontRenderMode(LOGFONTW *logfont)
-{
+{
switch(logfont->lfQuality)
{
- //case ANTIALIASED_QUALITY:
- case DEFAULT_QUALITY:
- return FT_RENDER_MODE_NORMAL;
+ case NONANTIALIASED_QUALITY:
+ return FT_RENDER_MODE_MONO;
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;
-}
-static NTSTATUS STDCALL
-GetFontObjectsFromTextObj(PTEXTOBJ TextObj, HFONT *FontHandle, FONTOBJ **FontObj, PFONTGDI *FontGDI)
-{
- FONTOBJ *FntObj;
- NTSTATUS Status = STATUS_SUCCESS;
-
- ASSERT(NULL != TextObj && NULL != TextObj->GDIFontHandle);
- if (NULL != TextObj && NULL != TextObj->GDIFontHandle)
- {
- if (NULL != FontHandle)
- {
- *FontHandle = TextObj->GDIFontHandle;
- }
- FntObj = (FONTOBJ*)AccessUserObject((ULONG) TextObj->GDIFontHandle);
- if (NULL != FontObj)
- {
- *FontObj = FntObj;
- if (NULL == *FontObj)
- {
- ASSERT(FALSE);
- Status = STATUS_INVALID_HANDLE;
- }
- }
- if (NT_SUCCESS(Status) && NULL != FontGDI)
- {
- *FontGDI = AccessInternalObjectFromUserObject(FntObj);
- }
-
- return Status;
+/* case CLEARTYPE_QUALITY:
+ return FT_RENDER_MODE_LCD; */
}
-
- return STATUS_INVALID_HANDLE;
+ return FT_RENDER_MODE_NORMAL;
}
int
PWSTR src;
NTSTATUS Status;
int Ret;
-
+
/* Copy the UNICODE_STRING structure */
Status = MmCopyFromCaller(&SafeFileName, Filename, sizeof(UNICODE_STRING));
if(!NT_SUCCESS(Status))
/* 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);
if(!SafeFileName.Buffer)
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
-
+
/* Prepend '\??\' */
RtlCopyMemory(SafeFileName.Buffer, L"\\??\\", 4 * sizeof(WCHAR));
SetLastNtError(Status);
return 0;
}
-
+
Ret = IntGdiAddFontResource(&SafeFileName, fl);
-
+
ExFreePool(SafeFileName.Buffer);
return Ret;
}
/* this should really depend on whether GM_ADVANCED is set */
TextObj->logfont.lfOrientation = TextObj->logfont.lfEscapement;
}
- TEXTOBJ_UnlockText(*NewFont);
+ TEXTOBJ_UnlockText(TextObj);
}
else
{
/* FIXME */
/* ASSERT(FALSE);*/
- Status = STATUS_INVALID_HANDLE;
+ Status = STATUS_INVALID_HANDLE;
}
}
else
LPCWSTR FontFile,
LPCWSTR CurrentPath)
{
- UNIMPLEMENTED;
+ DPRINT1("NtGdiCreateScalableFontResource - is unimplemented, have a nice day and keep going");
+ return FALSE;
}
/*************************************************************************
return (BOOL) Ret;
}
-
-/*************************************************************
- * IntGetOutlineTextMetrics
- *
- */
-static unsigned FASTCALL
-IntGetOutlineTextMetrics(PFONTGDI FontGDI, UINT Size,
- OUTLINETEXTMETRICW *Otm)
+static void FASTCALL
+FillTM(TEXTMETRICW *TM, FT_Face Face, TT_OS2 *pOS2, TT_HoriHeader *pHori)
{
- unsigned Needed;
- TT_OS2 *pOS2;
- TT_HoriHeader *pHori;
- TT_Postscript *pPost;
FT_Fixed XScale, YScale;
- ANSI_STRING FamilyNameA, StyleNameA;
- UNICODE_STRING FamilyNameW, StyleNameW, Regular;
- char *Cp;
int Ascent, Descent;
- TEXTMETRICW *TM;
-
- Needed = sizeof(OUTLINETEXTMETRICW);
-
- RtlInitAnsiString(&FamilyNameA, FontGDI->face->family_name);
- RtlAnsiStringToUnicodeString(&FamilyNameW, &FamilyNameA, TRUE);
-
- RtlInitAnsiString(&StyleNameA, FontGDI->face->style_name);
- RtlAnsiStringToUnicodeString(&StyleNameW, &StyleNameA, TRUE);
-
- /* These names should be read from the TT name table */
-
- /* length of otmpFamilyName */
- Needed += FamilyNameW.Length + sizeof(WCHAR);
-
- RtlInitUnicodeString(&Regular, L"regular");
- /* length of otmpFaceName */
- if (0 == RtlCompareUnicodeString(&StyleNameW, &Regular, TRUE))
- {
- Needed += FamilyNameW.Length + sizeof(WCHAR); /* just the family name */
- }
- else
- {
- 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 + (sizeof(WCHAR) << 1);
-
- if (Size < Needed)
- {
- RtlFreeUnicodeString(&FamilyNameW);
- RtlFreeUnicodeString(&StyleNameW);
- return Needed;
- }
-
- XScale = FontGDI->face->size->metrics.x_scale;
- YScale = FontGDI->face->size->metrics.y_scale;
-
- IntLockFreeType;
- pOS2 = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_os2);
- if (NULL == pOS2)
- {
- IntUnLockFreeType;
- DPRINT1("Can't find OS/2 table - not TT font?\n");
- RtlFreeUnicodeString(&StyleNameW);
- RtlFreeUnicodeString(&FamilyNameW);
- return 0;
- }
-
- pHori = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_hhea);
- if (NULL == pHori)
- {
- IntUnLockFreeType;
- DPRINT1("Can't find HHEA table - not TT font?\n");
- RtlFreeUnicodeString(&StyleNameW);
- RtlFreeUnicodeString(&FamilyNameW);
- return 0;
- }
-
- pPost = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_post); /* we can live with this failing */
- IntUnLockFreeType;
- Otm->otmSize = Needed;
+ XScale = Face->size->metrics.x_scale;
+ YScale = Face->size->metrics.y_scale;
if (0 == pOS2->usWinAscent + pOS2->usWinDescent)
{
Descent = pOS2->usWinDescent;
}
- TM = &Otm->otmTextMetrics;
+#if 0 /* This (Wine) code doesn't seem to work correctly for us */
TM->tmAscent = (FT_MulFix(Ascent, YScale) + 32) >> 6;
TM->tmDescent = (FT_MulFix(Descent, YScale) + 32) >> 6;
+#else
+ TM->tmAscent = (Face->size->metrics.ascender + 32) >> 6; /* units above baseline */
+ TM->tmDescent = (32 - Face->size->metrics.descender) >> 6; /* units below baseline */
+#endif
TM->tmInternalLeading = (FT_MulFix(Ascent + Descent
- - FontGDI->face->units_per_EM, YScale) + 32) >> 6;
+ - Face->units_per_EM, YScale) + 32) >> 6;
TM->tmHeight = TM->tmAscent + TM->tmDescent;
TM->tmAveCharWidth = (FT_MulFix(pOS2->xAvgCharWidth, XScale) + 32) >> 6;
if (0 == TM->tmAveCharWidth)
{
- TM->tmAveCharWidth = 1;
+ TM->tmAveCharWidth = 1;
}
- TM->tmMaxCharWidth = (FT_MulFix(FontGDI->face->bbox.xMax - FontGDI->face->bbox.xMin,
- XScale) + 32) >> 6;
+ TM->tmMaxCharWidth = (FT_MulFix(Face->bbox.xMax - Face->bbox.xMin,
+ XScale) + 32) >> 6;
TM->tmWeight = pOS2->usWeightClass;
TM->tmOverhang = 0;
TM->tmDigitizedAspectX = 300;
TM->tmLastChar = pOS2->usLastCharIndex;
TM->tmDefaultChar = pOS2->usDefaultChar;
TM->tmBreakChar = L'\0' != pOS2->usBreakChar ? pOS2->usBreakChar : ' ';
- TM->tmItalic = (FontGDI->face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0;
+ TM->tmItalic = (Face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0;
TM->tmUnderlined = 0; /* entry in OS2 table */
TM->tmStruckOut = 0; /* entry in OS2 table */
/* Yes TPMF_FIXED_PITCH is correct; braindead api */
- if (! FT_IS_FIXED_WIDTH(FontGDI->face))
+ if (! FT_IS_FIXED_WIDTH(Face))
{
TM->tmPitchAndFamily = TMPF_FIXED_PITCH;
}
TM->tmPitchAndFamily |= FF_DONTCARE;
}
- if (FT_IS_SCALABLE(FontGDI->face))
+ if (FT_IS_SCALABLE(Face))
{
TM->tmPitchAndFamily |= TMPF_VECTOR;
}
- if (FT_IS_SFNT(FontGDI->face))
+ if (FT_IS_SFNT(Face))
{
TM->tmPitchAndFamily |= TMPF_TRUETYPE;
}
-#ifndef TODO
TM->tmCharSet = DEFAULT_CHARSET;
-#endif
+}
+
+/*************************************************************
+ * IntGetOutlineTextMetrics
+ *
+ */
+static unsigned FASTCALL
+IntGetOutlineTextMetrics(PFONTGDI FontGDI, UINT Size,
+ OUTLINETEXTMETRICW *Otm)
+{
+ unsigned Needed;
+ TT_OS2 *pOS2;
+ TT_HoriHeader *pHori;
+ TT_Postscript *pPost;
+ FT_Fixed XScale, YScale;
+ ANSI_STRING FamilyNameA, StyleNameA;
+ UNICODE_STRING FamilyNameW, StyleNameW, Regular;
+ char *Cp;
+
+ Needed = sizeof(OUTLINETEXTMETRICW);
+
+ RtlInitAnsiString(&FamilyNameA, FontGDI->face->family_name);
+ RtlAnsiStringToUnicodeString(&FamilyNameW, &FamilyNameA, TRUE);
+
+ RtlInitAnsiString(&StyleNameA, FontGDI->face->style_name);
+ RtlAnsiStringToUnicodeString(&StyleNameW, &StyleNameA, TRUE);
+
+ /* These names should be read from the TT name table */
+
+ /* length of otmpFamilyName */
+ Needed += FamilyNameW.Length + sizeof(WCHAR);
+
+ RtlInitUnicodeString(&Regular, L"regular");
+ /* length of otmpFaceName */
+ if (0 == RtlCompareUnicodeString(&StyleNameW, &Regular, TRUE))
+ {
+ Needed += FamilyNameW.Length + sizeof(WCHAR); /* just the family name */
+ }
+ else
+ {
+ 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 + (sizeof(WCHAR) << 1);
+
+ if (Size < Needed)
+ {
+ RtlFreeUnicodeString(&FamilyNameW);
+ RtlFreeUnicodeString(&StyleNameW);
+ return Needed;
+ }
+
+ XScale = FontGDI->face->size->metrics.x_scale;
+ YScale = FontGDI->face->size->metrics.y_scale;
+
+ IntLockFreeType;
+ pOS2 = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_os2);
+ if (NULL == pOS2)
+ {
+ IntUnLockFreeType;
+ DPRINT1("Can't find OS/2 table - not TT font?\n");
+ RtlFreeUnicodeString(&StyleNameW);
+ RtlFreeUnicodeString(&FamilyNameW);
+ return 0;
+ }
+
+ pHori = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_hhea);
+ if (NULL == pHori)
+ {
+ IntUnLockFreeType;
+ DPRINT1("Can't find HHEA table - not TT font?\n");
+ RtlFreeUnicodeString(&StyleNameW);
+ RtlFreeUnicodeString(&FamilyNameW);
+ return 0;
+ }
+
+ pPost = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_post); /* we can live with this failing */
+
+ Otm->otmSize = Needed;
+
+ FillTM(&Otm->otmTextMetrics, FontGDI->face, pOS2, pHori);
Otm->otmFiller = 0;
memcpy(&Otm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
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);
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)
LOGFONTW *Lf;
TEXTMETRICW *TM;
NEWTEXTMETRICW *Ntm;
-
- ZeroMemory(Info, sizeof(FONTFAMILYINFO));
+
+ RtlZeroMemory(Info, sizeof(FONTFAMILYINFO));
Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
Otm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
if (NULL == Otm)
if (0 == pOS2->version)
{
FT_UInt Dummy;
-
+
if (FT_Get_First_Char(FontGDI->face, &Dummy) < 0x100)
{
fs_fsCsb0 |= 1;
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)
/* Enumerate font families in the process local list */
Win32Process = PsGetWin32Process();
IntLockProcessPrivateFonts(Win32Process);
- if (! GetFontFamilyInfoForList(&LogFont, Info, &Count, Size,
+ if (! GetFontFamilyInfoForList(&LogFont, Info, &Count, Size,
&Win32Process->PrivateFontListHead))
{
IntUnLockProcessPrivateFonts(Win32Process);
LPARAM lParam)
{
UNIMPLEMENTED;
+ return 0;
}
BOOL STDCALL
DC *dc;
SURFOBJ *SurfObj;
+ BITMAPOBJ *BitmapObj = NULL;
int error, glyph_index, n, i;
FT_Face face;
FT_GlyphSlot glyph;
- ULONG TextLeft, TextTop, pitch, previous, BackgroundLeft;
+ LONGLONG TextLeft, RealXStart;
+ ULONG TextTop, previous, BackgroundLeft;
FT_Bool use_kerning;
- RECTL DestRect, MaskRect;
+ RECTL DestRect, MaskRect, SpecifiedDestRect;
POINTL SourcePoint, BrushOrigin;
HBRUSH hBrushFg = NULL;
PGDIBRUSHOBJ BrushFg = NULL;
+ GDIBRUSHINST BrushFgInst;
HBRUSH hBrushBg = NULL;
PGDIBRUSHOBJ BrushBg = NULL;
+ GDIBRUSHINST BrushBgInst;
HBITMAP HSourceGlyph;
SURFOBJ *SourceGlyphSurf;
SIZEL bitSize;
INT yoff;
FONTOBJ *FontObj;
PFONTGDI FontGDI;
- PTEXTOBJ TextObj;
+ PTEXTOBJ TextObj = NULL;
PPALGDI PalDestGDI;
- XLATEOBJ *XlateObj, *XlateObj2;
+ XLATEOBJ *XlateObj=NULL, *XlateObj2=NULL;
ULONG Mode;
FT_Render_Mode RenderMode;
BOOLEAN Render;
NTSTATUS Status;
INT *Dx = NULL;
POINT Start;
+ BOOL DoBreak = FALSE;
+ // TODO: Write test-cases to exactly match real Windows in different
+ // bad parameters (e.g. does Windows check the DC or the RECT first?).
dc = DC_LockDc(hDC);
if (!dc)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
-
- if (NULL != UnsafeDx && Count > 0)
+ if (dc->IsIC)
{
- Dx = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), TAG_GDITEXT);
+ DC_UnlockDc(dc);
+ /* Yes, Windows really returns TRUE in this case */
+ return TRUE;
+ }
+
+ if (lprc && (fuOptions & (ETO_OPAQUE | ETO_CLIPPED)))
+ {
+ // At least one of the two flags were specified. Copy lprc. Once.
+ Status = MmCopyFromCaller(&SpecifiedDestRect, lprc, sizeof(RECT));
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ IntLPtoDP(dc, (POINT *) &SpecifiedDestRect, 2);
+ }
+
+ if (NULL != UnsafeDx && Count > 0)
+ {
+ Dx = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), TAG_GDITEXT);
if (NULL == Dx)
{
goto fail;
goto fail;
}
}
-
- SurfObj = (SURFOBJ*)AccessUserObject((ULONG) dc->Surface);
-
- Start.x = XStart; Start.y = YStart;
- IntLPtoDP(dc, &Start, 1);
-
- XStart = Start.x + dc->w.DCOrgX;
- YStart = Start.y + dc->w.DCOrgY;
- TextObj = TEXTOBJ_LockText(dc->w.hFont);
-
- if (!NT_SUCCESS(GetFontObjectsFromTextObj(TextObj, NULL, &FontObj, &FontGDI)))
+ BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
+ if ( !BitmapObj )
{
goto fail;
}
+ SurfObj = &BitmapObj->SurfObj;
+ ASSERT(SurfObj);
- 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");
- }
+ Start.x = XStart; Start.y = YStart;
+ IntLPtoDP(dc, &Start, 1);
- 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;
- }
+ RealXStart = (Start.x + dc->w.DCOrgX) << 6;
+ YStart = Start.y + dc->w.DCOrgY;
/* Create the brushes */
PalDestGDI = PALETTE_LockPalette(dc->w.hPalette);
if ( !PalDestGDI )
- Mode = PAL_RGB;
+ Mode = PAL_RGB;
else
{
- Mode = PalDestGDI->Mode;
- PALETTE_UnlockPalette(dc->w.hPalette);
+ Mode = PalDestGDI->Mode;
+ PALETTE_UnlockPalette(PalDestGDI);
}
XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
- hBrushFg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.textColor));
+ if ( !XlateObj )
+ {
+ goto fail;
+ }
+ hBrushFg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.textColor), 0);
+ if ( !hBrushFg )
+ {
+ goto fail;
+ }
BrushFg = BRUSHOBJ_LockBrush(hBrushFg);
+ if ( !BrushFg )
+ {
+ goto fail;
+ }
+ IntGdiInitBrushInstance(&BrushFgInst, BrushFg, NULL);
if ((fuOptions & ETO_OPAQUE) || dc->w.backgroundMode == OPAQUE)
{
- hBrushBg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.backgroundColor));
- if (hBrushBg)
+ hBrushBg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.backgroundColor), 0);
+ if ( !hBrushBg )
{
- BrushBg = BRUSHOBJ_LockBrush(hBrushBg);
+ goto fail;
}
- else
+ BrushBg = BRUSHOBJ_LockBrush(hBrushBg);
+ if ( !BrushBg )
{
- EngDeleteXlate(XlateObj);
goto fail;
}
+ IntGdiInitBrushInstance(&BrushBgInst, BrushBg, NULL);
}
XlateObj2 = (XLATEOBJ*)IntEngCreateXlate(PAL_RGB, Mode, NULL, dc->w.hPalette);
-
+ if ( !XlateObj2 )
+ {
+ goto fail;
+ }
+
SourcePoint.x = 0;
SourcePoint.y = 0;
MaskRect.left = 0;
if ((fuOptions & ETO_OPAQUE) && lprc)
{
- MmCopyFromCaller(&DestRect, lprc, sizeof(RECT));
- DestRect.left += dc->w.DCOrgX;
- DestRect.top += dc->w.DCOrgY;
- DestRect.right += dc->w.DCOrgX;
- DestRect.bottom += dc->w.DCOrgY;
+ DestRect.left = SpecifiedDestRect.left + dc->w.DCOrgX;
+ DestRect.top = SpecifiedDestRect.top + dc->w.DCOrgY;
+ DestRect.right = SpecifiedDestRect.right + dc->w.DCOrgX;
+ DestRect.bottom = SpecifiedDestRect.bottom + dc->w.DCOrgY;
+ IntLPtoDP(dc, (LPPOINT)&DestRect, 2);
IntEngBitBlt(
- SurfObj,
+ &BitmapObj->SurfObj,
NULL,
NULL,
dc->CombinedClip,
&DestRect,
&SourcePoint,
&SourcePoint,
- &BrushBg->BrushObject,
+ &BrushBgInst.BrushObject,
&BrushOrigin,
- PATCOPY);
+ ROP3_TO_ROP4(PATCOPY));
fuOptions &= ~ETO_OPAQUE;
}
else
}
}
+ TextObj = TEXTOBJ_LockText(dc->w.hFont);
+ if(TextObj == NULL)
+ {
+ goto fail;
+ }
+
+ FontObj = TextObj->Font;
+ ASSERT(FontObj);
+ FontGDI = ObjToGDI(FontObj, FONT);
+ ASSERT(FontGDI);
+
+ IntLockFreeType;
+ 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");
+ }
+ error = FT_Set_Charmap(face, found);
+ if (error)
+ {
+ DPRINT1("WARNING: Could not set the charmap!\n");
+ }
+ }
+
+ Render = IntIsFontRenderingEnabled();
+ if (Render)
+ RenderMode = IntGetFontRenderMode(&TextObj->logfont);
+ else
+ RenderMode = FT_RENDER_MODE_MONO;
+
+ error = FT_Set_Pixel_Sizes(
+ face,
+ TextObj->logfont.lfWidth,
+ /* FIXME should set character height if neg */
+ (TextObj->logfont.lfHeight < 0 ?
+ - TextObj->logfont.lfHeight :
+ TextObj->logfont.lfHeight == 0 ? 11 : TextObj->logfont.lfHeight));
+ if (error)
+ {
+ DPRINT1("Error in setting pixel sizes: %u\n", error);
+ IntUnLockFreeType;
+ goto fail;
+ }
+
/*
* Process the vertical alignment and determine the yoff.
*/
if (dc->w.textAlign & (TA_RIGHT | TA_CENTER))
{
- UINT TextWidth = 0;
+ ULONGLONG TextWidth = 0;
LPCWSTR TempText = String;
int Start;
if (NULL != Dx)
{
Start = Count < 2 ? 0 : Count - 2;
- TextWidth = Count < 2 ? 0 : Dx[Count - 2];
+ TextWidth = Count < 2 ? 0 : (Dx[Count - 2] << 6);
}
else
{
for (i = Start; i < Count; i++)
{
- IntLockFreeType;
glyph_index = FT_Get_Char_Index(face, *TempText);
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
- IntUnLockFreeType;
-
+
if (error)
{
DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
if (use_kerning && previous && glyph_index)
{
FT_Vector delta;
- 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 / 2;
+ RealXStart -= TextWidth / 2;
}
}
- TextLeft = XStart;
+ TextLeft = RealXStart;
TextTop = YStart;
- BackgroundLeft = XStart;
+ BackgroundLeft = (RealXStart + 32) >> 6;
/*
* The main rendering loop.
for (i = 0; i < Count; i++)
{
- IntLockFreeType;
glyph_index = FT_Get_Char_Index(face, *String);
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
- IntUnLockFreeType;
if (error)
{
- EngDeleteXlate(XlateObj);
- EngDeleteXlate(XlateObj2);
DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
+ IntUnLockFreeType;
goto fail;
}
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)
{
- IntLockFreeType;
error = FT_Render_Glyph(glyph, RenderMode);
- IntUnLockFreeType;
if (error)
{
- EngDeleteXlate(XlateObj);
- EngDeleteXlate(XlateObj2);
DPRINT1("WARNING: Failed to render glyph!\n");
goto fail;
}
- pitch = glyph->bitmap.pitch;
- } else {
- pitch = glyph->bitmap.width;
}
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->SurfObj,
NULL,
NULL,
dc->CombinedClip,
&DestRect,
&SourcePoint,
&SourcePoint,
- &BrushBg->BrushObject,
+ &BrushBgInst.BrushObject,
&BrushOrigin,
- PATCOPY);
+ ROP3_TO_ROP4(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;
-
+
bitSize.cx = glyph->bitmap.width;
bitSize.cy = glyph->bitmap.rows;
MaskRect.right = glyph->bitmap.width;
MaskRect.bottom = glyph->bitmap.rows;
-
+
/*
* We should create the bitmap out of the loop at the biggest possible
* glyph size. Then use memset with 0 to clear it and sourcerect to
* limit the work of the transbitblt.
+ *
+ * FIXME: DIB bitmaps should have an lDelta which is a multiple of 4.
+ * Here we pass in the pitch from the FreeType bitmap, which is not
+ * guaranteed to be a multiple of 4. If it's not, we should expand
+ * the FreeType bitmap to a temporary bitmap.
*/
- HSourceGlyph = EngCreateBitmap(bitSize, pitch, (glyph->bitmap.pixel_mode == ft_pixel_mode_grays) ? BMF_8BPP : BMF_1BPP, 0, glyph->bitmap.buffer);
- SourceGlyphSurf = (SURFOBJ*)AccessUserObject((ULONG) HSourceGlyph);
-
+ HSourceGlyph = EngCreateBitmap(bitSize, glyph->bitmap.pitch,
+ (glyph->bitmap.pixel_mode == ft_pixel_mode_grays) ?
+ BMF_8BPP : BMF_1BPP, BMF_TOPDOWN,
+ glyph->bitmap.buffer);
+ if ( !HSourceGlyph )
+ {
+ DPRINT1("WARNING: EngLockSurface() failed!\n");
+ IntUnLockFreeType;
+ goto fail;
+ }
+ SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
+ if ( !SourceGlyphSurf )
+ {
+ EngDeleteSurface((HSURF)HSourceGlyph);
+ DPRINT1("WARNING: EngLockSurface() failed!\n");
+ IntUnLockFreeType;
+ goto fail;
+ }
+
/*
* Use the font data as a mask to paint onto the DCs surface using a
* brush.
*/
+ if (lprc &&
+ (fuOptions & ETO_CLIPPED) &&
+ DestRect.right >= SpecifiedDestRect.right + dc->w.DCOrgX)
+ {
+ // We do the check '>=' instead of '>' to possibly save an iteration
+ // through this loop, since it's breaking after the drawing is done,
+ // and x is always incremented.
+ DestRect.right = SpecifiedDestRect.right + dc->w.DCOrgX;
+ DoBreak = TRUE;
+ }
+
IntEngMaskBlt(
SurfObj,
SourceGlyphSurf,
&DestRect,
&SourcePoint,
(PPOINTL)&MaskRect,
- &BrushFg->BrushObject,
+ &BrushFgInst.BrushObject,
&BrushOrigin);
+ EngUnlockSurface(SourceGlyphSurf);
EngDeleteSurface((HSURF)HSourceGlyph);
+ if (DoBreak)
+ {
+ break;
+ }
+
if (NULL == Dx)
{
- TextLeft += (glyph->advance.x + 32) >> 6;
+ TextLeft += glyph->advance.x;
}
else
{
- TextLeft += Dx[i];
+ TextLeft += Dx[i] << 6;
}
previous = glyph_index;
String++;
}
+ IntUnLockFreeType;
+
EngDeleteXlate(XlateObj);
EngDeleteXlate(XlateObj2);
- TEXTOBJ_UnlockText(dc->w.hFont);
+ BITMAPOBJ_UnlockBitmap(BitmapObj);
+ if(TextObj != NULL)
+ TEXTOBJ_UnlockText(TextObj);
if (hBrushBg != NULL)
{
- BRUSHOBJ_UnlockBrush(hBrushBg);
+ BRUSHOBJ_UnlockBrush(BrushBg);
NtGdiDeleteObject(hBrushBg);
}
- BRUSHOBJ_UnlockBrush(hBrushFg);
+ BRUSHOBJ_UnlockBrush(BrushFg);
NtGdiDeleteObject(hBrushFg);
if (NULL != Dx)
{
ExFreePool(Dx);
}
- DC_UnlockDc(hDC);
-
+ DC_UnlockDc( dc );
+
return TRUE;
fail:
- TEXTOBJ_UnlockText(dc->w.hFont);
+ if ( XlateObj2 != NULL )
+ EngDeleteXlate(XlateObj2);
+ if ( XlateObj != NULL )
+ EngDeleteXlate(XlateObj);
+ if(TextObj != NULL)
+ TEXTOBJ_UnlockText(TextObj);
+ BITMAPOBJ_UnlockBitmap(BitmapObj);
if (hBrushBg != NULL)
{
- BRUSHOBJ_UnlockBrush(hBrushBg);
+ BRUSHOBJ_UnlockBrush(BrushBg);
NtGdiDeleteObject(hBrushBg);
}
if (hBrushFg != NULL)
{
- BRUSHOBJ_UnlockBrush(hBrushFg);
+ BRUSHOBJ_UnlockBrush(BrushFg);
NtGdiDeleteObject(hBrushFg);
}
if (NULL != Dx)
{
ExFreePool(Dx);
}
- DC_UnlockDc(hDC);
+ DC_UnlockDc(dc);
return FALSE;
}
LPSIZE AspectRatio)
{
UNIMPLEMENTED;
+ return FALSE;
}
BOOL
LPABCFLOAT abcF)
{
UNIMPLEMENTED;
+ return FALSE;
}
DWORD
DWORD Flags)
{
UNIMPLEMENTED;
+ return 0;
}
BOOL
FT_Face face;
FT_CharMap charmap, found = NULL;
UINT i, glyph_index, BufferSize;
+ HFONT hFont = 0;
if (LastChar < FirstChar)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
- TextObj = TEXTOBJ_LockText(dc->w.hFont);
- DC_UnlockDc(hDC);
+ hFont = dc->w.hFont;
+ TextObj = TEXTOBJ_LockText(hFont);
+ DC_UnlockDc(dc);
+
+ if (TextObj == NULL)
+ {
+ ExFreePool(SafeBuffer);
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ FontGDI = ObjToGDI(TextObj->Font, FONT);
- GetFontObjectsFromTextObj(TextObj, NULL, NULL, &FontGDI);
-
face = FontGDI->face;
if (face->charmap == NULL)
{
IntLockFreeType;
FT_Set_Pixel_Sizes(face,
+ TextObj->logfont.lfWidth,
/* FIXME should set character height if neg */
(TextObj->logfont.lfHeight < 0 ?
- TextObj->logfont.lfHeight :
- TextObj->logfont.lfHeight),
- TextObj->logfont.lfWidth);
+ TextObj->logfont.lfHeight == 0 ? 11 : TextObj->logfont.lfHeight));
for (i = FirstChar; i <= LastChar; i++)
{
glyph_index = FT_Get_Char_Index(face, i);
FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
- SafeBuffer[i - FirstChar] = face->glyph->advance.x >> 6;
+ SafeBuffer[i - FirstChar] = (face->glyph->advance.x + 32) >> 6;
}
IntUnLockFreeType;
- TEXTOBJ_UnlockText(dc->w.hFont);
+ TEXTOBJ_UnlockText(TextObj);
MmCopyToCaller(Buffer, SafeBuffer, BufferSize);
ExFreePool(SafeBuffer);
return TRUE;
PFLOAT Buffer)
{
UNIMPLEMENTED;
+ return FALSE;
}
DWORD
NtGdiGetFontLanguageInfo(HDC hDC)
{
UNIMPLEMENTED;
+ return 0;
}
-DWORD
-STDCALL
-NtGdiGetGlyphOutline(HDC hDC,
- UINT Char,
- UINT Format,
- LPGLYPHMETRICS gm,
- DWORD Bufsize,
- LPVOID Buffer,
- CONST LPMAT2 mat2)
+ULONG
+APIENTRY
+NtGdiGetGlyphOutline(
+ IN HDC hdc,
+ IN WCHAR wch,
+ IN UINT iFormat,
+ OUT LPGLYPHMETRICS pgm,
+ IN ULONG cjBuf,
+ OUT OPTIONAL PVOID pvBuf,
+ IN LPMAT2 pmat2,
+ IN BOOL bIgnoreRotation)
{
UNIMPLEMENTED;
-
-
+ return 0;
}
DWORD
LPKERNINGPAIR krnpair)
{
UNIMPLEMENTED;
+ return 0;
}
UINT
LPOUTLINETEXTMETRICW otm)
{
UNIMPLEMENTED;
+ return 0;
}
BOOL
-STDCALL
-NtGdiGetRasterizerCaps(LPRASTERIZER_STATUS rs,
- UINT Size)
+APIENTRY
+NtGdiGetRasterizerCaps(
+ OUT LPRASTERIZER_STATUS praststat,
+ IN ULONG cjBytes)
{
UNIMPLEMENTED;
+ return FALSE;
}
UINT
NtGdiGetTextCharset(HDC hDC)
{
UNIMPLEMENTED;
+ return 0;
}
-UINT
-STDCALL
-NtGdiGetTextCharsetInfo(HDC hDC,
- LPFONTSIGNATURE Sig,
- DWORD Flags)
+INT
+APIENTRY
+NtGdiGetTextCharsetInfo(
+ IN HDC hdc,
+ OUT OPTIONAL LPFONTSIGNATURE lpSig,
+ IN DWORD dwFlags)
{
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;
error = FT_Set_Pixel_Sizes(face,
+ TextObj->logfont.lfWidth,
/* FIXME should set character height if neg */
(TextObj->logfont.lfHeight < 0 ?
- TextObj->logfont.lfHeight :
- TextObj->logfont.lfHeight),
- TextObj->logfont.lfWidth);
+ TextObj->logfont.lfHeight == 0 ? 11 : TextObj->logfont.lfHeight));
IntUnLockFreeType;
if (error)
{
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);
- TEXTOBJ_UnlockText(dc->w.hFont);
+ }
+ else
+ Result = FALSE;
+ TEXTOBJ_UnlockText(TextObj);
+ DC_UnlockDc(dc);
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);
- DC_UnlockDc(hDC);
+ if ( TextObj != NULL )
+ {
+ Result = TextIntGetTextExtentPoint (
+ dc, TextObj, String, Count, 0, NULL, NULL, &Size);
+ TEXTOBJ_UnlockText(TextObj);
+ }
+ else
+ Result = FALSE;
+ DC_UnlockDc(dc);
ExFreePool(String);
if (! Result)
return TRUE;
}
-int
-STDCALL
-NtGdiGetTextFace(HDC hDC,
- int Count,
- LPWSTR FaceName)
+INT STDCALL
+NtGdiGetTextFace(HDC hDC, INT Count, LPWSTR FaceName)
{
- UNIMPLEMENTED;
+ PDC Dc;
+ HFONT hFont;
+ PTEXTOBJ TextObj;
+ NTSTATUS Status;
+
+ Dc = DC_LockDc(hDC);
+ if (Dc == NULL)
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+ hFont = Dc->w.hFont;
+ DC_UnlockDc(Dc);
+
+ TextObj = TEXTOBJ_LockText(hFont);
+ ASSERT(TextObj != NULL);
+ Count = min(Count, wcslen(TextObj->logfont.lfFaceName));
+ Status = MmCopyToCaller(FaceName, TextObj->logfont.lfFaceName, Count * sizeof(WCHAR));
+ TEXTOBJ_UnlockText(TextObj);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ return 0;
+ }
+
+ return Count;
}
BOOL
STDCALL
NtGdiGetTextMetrics(HDC hDC,
- LPTEXTMETRICW tm)
+ LPTEXTMETRICW tm)
{
PDC dc;
PTEXTOBJ TextObj;
TEXTMETRICW SafeTm;
FT_Face Face;
TT_OS2 *pOS2;
+ TT_HoriHeader *pHori;
ULONG Error;
if (NULL == tm)
SetLastWin32Error(STATUS_INVALID_PARAMETER);
return FALSE;
}
-
+
if(!(dc = DC_LockDc(hDC)))
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
TextObj = TEXTOBJ_LockText(dc->w.hFont);
if (NULL != TextObj)
- {
- Status = GetFontObjectsFromTextObj(TextObj, NULL, NULL, &FontGDI);
- if (NT_SUCCESS(Status))
{
+ FontGDI = ObjToGDI(TextObj->Font, FONT);
+
Face = FontGDI->face;
IntLockFreeType;
Error = FT_Set_Pixel_Sizes(Face,
+ TextObj->logfont.lfWidth,
/* FIXME should set character height if neg */
- (TextObj->logfont.lfHeight < 0 ?
- - TextObj->logfont.lfHeight :
- TextObj->logfont.lfHeight),
- TextObj->logfont.lfWidth);
+ (TextObj->logfont.lfHeight < 0 ?
+ - TextObj->logfont.lfHeight :
+ TextObj->logfont.lfHeight == 0 ? 11 : TextObj->logfont.lfHeight));
IntUnLockFreeType;
if (0 != Error)
{
- DPRINT1("Error in setting pixel sizes: %u\n", Error);
- Status = STATUS_UNSUCCESSFUL;
+ DPRINT1("Error in setting pixel sizes: %u\n", Error);
+ 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));
+ memcpy(&SafeTm, &FontGDI->TextMetric, sizeof(TEXTMETRICW));
+
+ Status = STATUS_SUCCESS;
+ IntLockFreeType;
+ pOS2 = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_os2);
+ if (NULL == pOS2)
+ {
+ DPRINT1("Can't find OS/2 table - not TT font?\n");
+ Status = STATUS_INTERNAL_ERROR;
+ }
+
+ pHori = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_hhea);
+ if (NULL == pHori)
+ {
+ DPRINT1("Can't find HHEA table - not TT font?\n");
+ Status = STATUS_INTERNAL_ERROR;
+ }
+
+ IntUnLockFreeType;
+
+ if (NT_SUCCESS(Status))
+ {
+ FillTM(&SafeTm, FontGDI->face, pOS2, pHori);
+ Status = MmCopyToCaller(tm, &SafeTm, sizeof(TEXTMETRICW));
+ }
}
+ TEXTOBJ_UnlockText(TextObj);
}
- TEXTOBJ_UnlockText(dc->w.hFont);
- }
else
- {
- ASSERT(FALSE);
- Status = STATUS_INVALID_HANDLE;
- }
- DC_UnlockDc(hDC);
-
+ {
+ Status = STATUS_INVALID_HANDLE;
+ }
+ DC_UnlockDc(dc);
+
if(!NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- return FALSE;
- }
-
+ {
+ SetLastNtError(Status);
+ return FALSE;
+ }
+
return TRUE;
}
int Count)
{
UNIMPLEMENTED;
+ return FALSE;
}
BOOL
STDCALL
NtGdiRemoveFontResource(LPCWSTR FileName)
{
- UNIMPLEMENTED;
+ DPRINT1("NtGdiRemoveFontResource is UNIMPLEMENTED\n");
+ return FALSE;
}
DWORD
DWORD Flag)
{
UNIMPLEMENTED;
+ return 0;
}
UINT
}
prevAlign = dc->w.textAlign;
dc->w.textAlign = Mode;
- DC_UnlockDc( hDC );
+ DC_UnlockDc( dc );
return prevAlign;
}
oldColor = dc->w.textColor;
dc->w.textColor = color;
hBrush = dc->w.hBrush;
- DC_UnlockDc( hDC );
+ DC_UnlockDc( dc );
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(Dc);
+
+ 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(TextObj);
+
+ return Result;
+}
+
static UINT FASTCALL
GetFontScore(LOGFONTW *LogFont, PUNICODE_STRING FaceName, PFONTGDI FontGDI)
{
LONG WeightDiff;
NTSTATUS Status;
UINT Score = 1;
-
+
RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name);
Status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
if (NT_SUCCESS(Status))
return Score;
}
-static VOID FASTCALL
-FindBestFontFromList(HFONT *Font, UINT *MatchScore, LOGFONTW *LogFont,
+static __inline VOID
+FindBestFontFromList(FONTOBJ **FontObj, UINT *MatchScore, LOGFONTW *LogFont,
PUNICODE_STRING FaceName, PLIST_ENTRY Head)
{
PLIST_ENTRY Entry;
PFONT_ENTRY CurrentEntry;
- PFONTGDI FontGDI;
+ FONTGDI *FontGDI;
UINT Score;
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);
+
Score = GetFontScore(LogFont, FaceName, FontGDI);
- if (*MatchScore < Score)
+ if (*MatchScore == 0 || *MatchScore < Score)
{
- *Font = CurrentEntry->hFont;
+ *FontObj = GDIToObj(FontGDI, FONT);
*MatchScore = Score;
}
Entry = Entry->Flink;
}
}
-static BOOLEAN FASTCALL
+static __inline BOOLEAN
SubstituteFontFamilyKey(PUNICODE_STRING FaceName,
LPCWSTR Key)
{
return NT_SUCCESS(Status);
}
-static void FASTCALL
+static __inline void
SubstituteFontFamily(PUNICODE_STRING FaceName, UINT Level)
{
if (10 < Level) /* Enough is enough */
return STATUS_INVALID_HANDLE;
}
+ if (TextObj->Initialized)
+ {
+ TEXTOBJ_UnlockText(TextObj);
+ return STATUS_SUCCESS;
+ }
+
if (! RtlCreateUnicodeString(&FaceName, TextObj->logfont.lfFaceName))
{
- TEXTOBJ_UnlockText(FontHandle);
+ TEXTOBJ_UnlockText(TextObj);
return STATUS_NO_MEMORY;
}
SubstituteFontFamily(&FaceName, 0);
MatchScore = 0;
- TextObj->GDIFontHandle = NULL;
-
+ TextObj->Font = NULL;
+
/* First search private fonts */
Win32Process = PsGetWin32Process();
IntLockProcessPrivateFonts(Win32Process);
- FindBestFontFromList(&TextObj->GDIFontHandle, &MatchScore,
+ FindBestFontFromList(&TextObj->Font, &MatchScore,
&TextObj->logfont, &FaceName,
&Win32Process->PrivateFontListHead);
IntUnLockProcessPrivateFonts(Win32Process);
-
+
/* Search system fonts */
IntLockGlobalFonts;
- FindBestFontFromList(&TextObj->GDIFontHandle, &MatchScore,
+ FindBestFontFromList(&TextObj->Font, &MatchScore,
&TextObj->logfont, &FaceName,
&FontListHead);
IntUnLockGlobalFonts;
- if (NULL == TextObj->GDIFontHandle)
+ if (NULL == TextObj->Font)
{
DPRINT1("Requested font %S not found, no fonts loaded at all\n",
TextObj->logfont.lfFaceName);
Status = STATUS_NOT_FOUND;
}
+ else
+ {
+ TextObj->Initialized = TRUE;
+ Status = STATUS_SUCCESS;
+ }
RtlFreeUnicodeString(&FaceName);
- TEXTOBJ_UnlockText(FontHandle);
- ASSERT(! NT_SUCCESS(Status) || NULL != TextObj->GDIFontHandle);
+ TEXTOBJ_UnlockText(TextObj);
+
+ ASSERT((NT_SUCCESS(Status) ^ (NULL == TextObj->Font)) != 0);
return Status;
}