* 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.107 2004/07/29 12:03:47 weiden Exp $ */
+/* $Id: text.c,v 1.116 2004/12/13 01:45:18 royce Exp $ */
#include <w32k.h>
#include <ft2build.h>
typedef struct _FONT_ENTRY {
LIST_ENTRY ListEntry;
- HFONT hFont;
+ FONTGDI *Font;
UNICODE_STRING FaceName;
BYTE NotEnum;
} FONT_ENTRY, *PFONT_ENTRY;
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");
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;
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;
- }
-
/* Open the font file */
InitializeObjectAttributes(&ObjectAttributes, FileName, 0, NULL, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT("Could not font file: %wZ\n", FileName);
- NtGdiDeleteObject(NewFont);
return 0;
}
if (!NT_SUCCESS(Status))
{
DPRINT("Could not get file size\n");
- NtGdiDeleteObject(NewFont);
ZwClose(FileHandle);
return 0;
}
Buffer = ExAllocatePoolWithTag(
PagedPool,
FileStdInfo.EndOfFile.u.LowPart,
- TAG_GDITEXT);
+ TAG_FNTFILE);
if (Buffer == NULL)
{
DPRINT("Could not allocate memory for font");
- NtGdiDeleteObject(NewFont);
ZwClose(FileHandle);
return 0;
}
{
DPRINT("Could not read the font file into memory");
ExFreePool(Buffer);
- NtGdiDeleteObject(NewFont);
ZwClose(FileHandle);
return 0;
}
else
DPRINT("Error reading font file (error code: %u)\n", Error);
ExFreePool(Buffer);
- NtGdiDeleteObject(NewFont);
return 0;
}
return 0;
}
+ 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;
+ }
+
/* 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 = 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);
/* 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);
}
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;
- }
-
- return STATUS_INVALID_HANDLE;
-}
int
STDCALL
LPCWSTR FontFile,
LPCWSTR CurrentPath)
{
- UNIMPLEMENTED;
+ DPRINT1("NtGdiCreateScalableFontResource - is unimplemented, have a nice day and keep going");
return FALSE;
}
}
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);
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)
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)
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;
INT yoff;
FONTOBJ *FontObj;
PFONTGDI FontGDI;
- PTEXTOBJ TextObj;
+ PTEXTOBJ TextObj = NULL;
PPALGDI PalDestGDI;
XLATEOBJ *XlateObj, *XlateObj2;
ULONG Mode;
Start.x = XStart; Start.y = YStart;
IntLPtoDP(dc, &Start, 1);
- XStart = Start.x + dc->w.DCOrgX;
+ RealXStart = (Start.x + dc->w.DCOrgX) << 6;
YStart = Start.y + dc->w.DCOrgY;
/* Create the brushes */
if (hBrushBg)
{
BrushBg = BRUSHOBJ_LockBrush(hBrushBg);
+ /* FIXME - Handle BrushBg == NULL !!!!! */
IntGdiInitBrushInstance(&BrushBgInst, BrushBg, NULL);
}
else
}
TextObj = TEXTOBJ_LockText(dc->w.hFont);
-
- if (!NT_SUCCESS(GetFontObjectsFromTextObj(TextObj, NULL, &FontObj, &FontGDI)))
+ if(TextObj == NULL)
{
- goto fail;
+ goto fail;
}
+ FontObj = TextObj->Font;
+ FontGDI = ObjToGDI(FontObj, FONT);
+
face = FontGDI->face;
if (face->charmap == NULL)
{
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
{
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.
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(
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;
if (NULL == Dx)
{
- TextLeft += (glyph->advance.x + 32) >> 6;
+ TextLeft += glyph->advance.x;
}
else
{
- TextLeft += Dx[i];
+ TextLeft += Dx[i] << 6;
}
previous = glyph_index;
EngDeleteXlate(XlateObj);
EngDeleteXlate(XlateObj2);
BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
- TEXTOBJ_UnlockText(dc->w.hFont);
+ if(TextObj != NULL)
+ TEXTOBJ_UnlockText(dc->w.hFont);
if (hBrushBg != NULL)
{
BRUSHOBJ_UnlockBrush(hBrushBg);
{
ExFreePool(Dx);
}
- DC_UnlockDc(hDC);
+ 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)
{
return FALSE;
}
- if (!NT_SUCCESS(GetFontObjectsFromTextObj(TextObj, NULL, NULL, &FontGDI)))
- {
- ExFreePool(SafeBuffer);
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- TEXTOBJ_UnlockText(hFont);
- 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 - FirstChar] = face->glyph->advance.x >> 6;
+ SafeBuffer[i - FirstChar] = (face->glyph->advance.x + 32) >> 6;
}
IntUnLockFreeType;
TEXTOBJ_UnlockText(hFont);
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;
- if (!NT_SUCCESS(GetFontObjectsFromTextObj(TextObj, NULL, NULL, &FontGDI)))
- {
- return FALSE;
- }
+ 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);
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,
}
Status = MmCopyToCaller(tm, &SafeTm, sizeof(TEXTMETRICW));
}
- }
TEXTOBJ_UnlockText(dc->w.hFont);
}
else
{
- ASSERT(FALSE);
Status = STATUS_INVALID_HANDLE;
}
DC_UnlockDc(hDC);
PTEXTOBJ TextObj;
PFONTGDI FontGdi;
DWORD Result = GDI_ERROR;
- NTSTATUS Status;
Dc = DC_LockDc(hDC);
if (Dc == NULL)
return GDI_ERROR;
}
- Status = GetFontObjectsFromTextObj(TextObj, NULL, NULL, &FontGdi);
- if (NT_SUCCESS(Status))
- {
- IntLockFreeType;
-
- if (FT_IS_SFNT(FontGdi->face))
- {
- if (Table)
- Table = Table >> 24 | Table << 24 | (Table >> 8 & 0xFF00) |
- (Table << 8 & 0xFF0000);
+ FontGdi = ObjToGDI(TextObj->Font, FONT);
+
+ IntLockFreeType;
- if (Buffer == NULL)
- Size = 0;
+ if (FT_IS_SFNT(FontGdi->face))
+ {
+ if (Table)
+ Table = Table >> 24 | Table << 24 | (Table >> 8 & 0xFF00) |
+ (Table << 8 & 0xFF0000);
- if (!FT_Load_Sfnt_Table(FontGdi->face, Table, Offset, Buffer, &Size))
- Result = Size;
- }
+ if (Buffer == NULL)
+ Size = 0;
- IntUnLockFreeType;
+ if (!FT_Load_Sfnt_Table(FontGdi->face, Table, Offset, Buffer, &Size))
+ Result = Size;
}
+ IntUnLockFreeType;
+
TEXTOBJ_UnlockText(hFont);
return Result;
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 */
}
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
+ {
+ Status = STATUS_SUCCESS;
+ }
RtlFreeUnicodeString(&FaceName);
TEXTOBJ_UnlockText(FontHandle);
- ASSERT(! NT_SUCCESS(Status) && NULL != TextObj->GDIFontHandle);
+
+ ASSERT((NT_SUCCESS(Status) ^ (NULL == TextObj->Font)) != 0);
return Status;
}