/*
* PROJECT: ReactOS win32 kernel mode subsystem
* LICENSE: GPL - See COPYING in the top level directory
- * FILE: subsystems/win32/win32k/objects/freetype.c
+ * FILE: win32ss/gdi/ntgdi/freetype.c
* PURPOSE: FreeType font engine interface
* PROGRAMMER: Copyright 2001 Huw D M Davies for CodeWeavers.
* Copyright 2006 Dmitry Timoshkov for CodeWeavers.
#include FT_GLYPH_H
#include FT_TYPE1_TABLES_H
-#include <tttables.h>
-#include <fttrigon.h>
-#include <ftbitmap.h>
-#include <ftoutln.h>
-#include <ftwinfnt.h>
+#include FT_TRUETYPE_TABLES_H
+#include FT_TRIGONOMETRY_H
+#include FT_BITMAP_H
+#include FT_OUTLINE_H
+#include FT_WINFONTS_H
#include <gdi/eng/floatobj.h>
((DWORD)(BYTE)(ch2) << 8) | (DWORD)(BYTE)(ch3) )
#endif
+extern const MATRIX gmxWorldToDeviceDefault;
+extern const MATRIX gmxWorldToPageDefault;
+
+// HACK!! Fix XFORMOBJ then use 1:16 / 16:1
+#define gmxWorldToDeviceDefault gmxWorldToPageDefault
+
FT_Library library;
typedef struct _FONT_ENTRY
FontCacheNumEntries = 0;
/* Fast Mutexes must be allocated from non paged pool */
FontListLock = ExAllocatePoolWithTag(NonPagedPool, sizeof(FAST_MUTEX), TAG_INTERNAL_SYNC);
+ if (FontListLock == NULL)
+ {
+ return FALSE;
+ }
+
ExInitializeFastMutex(FontListLock);
FreeTypeLock = ExAllocatePoolWithTag(NonPagedPool, sizeof(FAST_MUTEX), TAG_INTERNAL_SYNC);
+ if (FreeTypeLock == NULL)
+ {
+ return FALSE;
+ }
ExInitializeFastMutex(FreeTypeLock);
ulError = FT_Init_FreeType(&library);
InitializeObjectAttributes(
&ObjectAttributes,
&Directory,
- OBJ_CASE_INSENSITIVE,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
Entry->Font = FontGDI;
Entry->NotEnum = (Characteristics & FR_NOT_ENUM);
RtlInitAnsiString(&AnsiFaceName, (LPSTR)Face->family_name);
- RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE);
+ Status = RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(FontGDI->Filename, GDITAG_PFF);
+ EngFreeMem(FontGDI);
+ FT_Done_Face(Face);
+ ExFreePoolWithTag(Entry, TAG_FONT);
+ return 0;
+ }
if (Characteristics & FR_PRIVATE)
{
{
IntLockGlobalFonts;
InsertTailList(&FontListHead, &Entry->ListEntry);
- InitializeObjectAttributes(&ObjectAttributes, &FontRegPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
+ InitializeObjectAttributes(&ObjectAttributes, &FontRegPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
Status = ZwOpenKey(&KeyHandle, KEY_WRITE, &ObjectAttributes);
if (NT_SUCCESS(Status))
{
{
switch (logfont->lfQuality)
{
+ case ANTIALIASED_QUALITY:
case NONANTIALIASED_QUALITY:
return FT_RENDER_MODE_MONO;
case DRAFT_QUALITY:
FT_WinFNT_HeaderRec Win;
FT_Error Error;
char *Cp;
+ NTSTATUS status;
Needed = sizeof(OUTLINETEXTMETRICW);
RtlInitAnsiString(&FamilyNameA, FontGDI->face->family_name);
- RtlAnsiStringToUnicodeString(&FamilyNameW, &FamilyNameA, TRUE);
+ status = RtlAnsiStringToUnicodeString(&FamilyNameW, &FamilyNameA, TRUE);
+ if (!NT_SUCCESS(status))
+ {
+ return 0;
+ }
RtlInitAnsiString(&StyleNameA, FontGDI->face->style_name);
- RtlAnsiStringToUnicodeString(&StyleNameW, &StyleNameA, TRUE);
+ status = RtlAnsiStringToUnicodeString(&StyleNameW, &StyleNameA, TRUE);
+ if (!NT_SUCCESS(status))
+ {
+ RtlFreeUnicodeString(&FamilyNameW);
+ return 0;
+ }
/* These names should be read from the TT name table */
ANSI_STRING EntryFaceNameA;
UNICODE_STRING EntryFaceNameW;
FONTGDI *FontGDI;
+ NTSTATUS status;
Entry = Head->Flink;
while (Entry != Head)
ASSERT(FontGDI);
RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name);
- RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
+ status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
+ if (!NT_SUCCESS(status))
+ {
+ break;
+ }
+
if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length)
{
EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR);
TEXTMETRICW *TM;
NEWTEXTMETRICW *Ntm;
DWORD fs0;
+ NTSTATUS status;
RtlZeroMemory(Info, sizeof(FONTFAMILYINFO));
Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
RtlInitAnsiString(&StyleA, FontGDI->face->style_name);
StyleW.Buffer = Info->EnumLogFontEx.elfStyle;
StyleW.MaximumLength = sizeof(Info->EnumLogFontEx.elfStyle);
- RtlAnsiStringToUnicodeString(&StyleW, &StyleA, FALSE);
+ status = RtlAnsiStringToUnicodeString(&StyleW, &StyleA, FALSE);
+ if (!NT_SUCCESS(status))
+ {
+ return;
+ }
Info->EnumLogFontEx.elfLogFont.lfCharSet = DEFAULT_CHARSET;
Info->EnumLogFontEx.elfScript[0] = L'\0';
ANSI_STRING EntryFaceNameA;
UNICODE_STRING EntryFaceNameW;
FONTGDI *FontGDI;
+ NTSTATUS status;
Entry = Head->Flink;
while (Entry != Head)
ASSERT(FontGDI);
RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name);
- RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
+ status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
+ if (!NT_SUCCESS(status))
+ {
+ return FALSE;
+ }
+
if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length)
{
EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR);
DWORD Size;
} FONT_FAMILY_INFO_CALLBACK_CONTEXT, *PFONT_FAMILY_INFO_CALLBACK_CONTEXT;
+_Function_class_(RTL_QUERY_REGISTRY_ROUTINE)
static NTSTATUS APIENTRY
FontFamilyInfoQueryRegistryCallback(IN PWSTR ValueName, IN ULONG ValueType,
IN PVOID ValueData, IN ULONG ValueLength,
}
-static
-void
-FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
+static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
{
pt->x.value = vec->x >> 6;
pt->x.fract = (vec->x & 0x3f) << 10;
pt->y.value = vec->y >> 6;
pt->y.fract = (vec->y & 0x3f) << 10;
pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
- return;
}
/*
for (n = 0; n < ft_face->num_charmaps; n++)
{
charmap = ft_face->charmaps[n];
- DPRINT("Found charmap encoding: %u\n", charmap->encoding);
+ DPRINT("Found charmap encoding: %i\n", charmap->encoding);
if (charmap->encoding != 0)
{
found = charmap;
IntUnLockFreeType;
- if (pgm) RtlCopyMemory(pgm, &gm, sizeof(GLYPHMETRICS));
if (iFormat == GGO_METRICS)
{
DPRINT("GGO_METRICS Exit!\n");
+ *pgm = gm;
return 1; /* FIXME */
}
needed = pitch * height;
if (!pvBuf || !cjBuf) break;
+ if (!needed) return GDI_ERROR; /* empty glyph */
+ if (needed > cjBuf)
+ return GDI_ERROR;
switch (ft_face->glyph->format)
{
case ft_glyph_format_bitmap:
{
BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
- INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
- INT h = ft_face->glyph->bitmap.rows;
+ INT w = min( pitch, (ft_face->glyph->bitmap.width + 7) >> 3 );
+ INT h = min( height, ft_face->glyph->bitmap.rows );
while (h--)
{
RtlCopyMemory(dst, src, w);
needed = pitch * height;
if (!pvBuf || !cjBuf) break;
+ if (!needed) return GDI_ERROR; /* empty glyph */
+ if (needed > cjBuf)
+ return GDI_ERROR;
switch (ft_face->glyph->format)
{
case ft_glyph_format_bitmap:
{
BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
- INT h = ft_face->glyph->bitmap.rows;
+ INT h = min( height, ft_face->glyph->bitmap.rows );
INT x;
while (h--)
{
}
DPRINT("ftGdiGetGlyphOutline END and needed %lu\n", needed);
+ *pgm = gm;
return needed;
}
for (n = 0; n < face->num_charmaps; n++)
{
charmap = face->charmaps[n];
- DPRINT("Found charmap encoding: %u\n", charmap->encoding);
+ DPRINT("Found charmap encoding: %i\n", charmap->encoding);
if (charmap->encoding != 0)
{
found = charmap;
}
}
else
- DPRINT1("Encoding %u not supported\n", face->charmap->encoding);
+ DPRINT1("Encoding %i not supported\n", face->charmap->encoding);
size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
if (glyphset)
{
glyphset->cbThis = size;
glyphset->cRanges = num_ranges;
+ glyphset->flAccel = 0;
}
return size;
}
InitializeObjectAttributes(&ObjectAttributes,
FileName,
- OBJ_CASE_INSENSITIVE,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
IN INT YStart,
IN UINT fuOptions,
IN OPTIONAL PRECTL lprc,
- IN LPWSTR String,
+ IN LPCWSTR String,
IN INT Count,
IN OPTIONAL LPINT Dx,
IN DWORD dwCodePage)
IntLPtoDP(dc, (POINT *)lprc, 2);
}
- Start.x = XStart;
- Start.y = YStart;
- IntLPtoDP(dc, &Start, 1);
+ if(pdcattr->lTextAlign & TA_UPDATECP)
+ {
+ Start.x = pdcattr->ptlCurrent.x;
+ Start.y = pdcattr->ptlCurrent.y;
+ } else {
+ Start.x = XStart;
+ Start.y = YStart;
+ IntLPtoDP(dc, &Start, 1);
+ }
- RealXStart = (Start.x + dc->ptlDCOrig.x) << 6;
+ RealXStart = ((LONGLONG)Start.x + dc->ptlDCOrig.x) << 6;
YStart = Start.y + dc->ptlDCOrig.y;
SourcePoint.x = 0;
for (n = 0; n < face->num_charmaps; n++)
{
charmap = face->charmaps[n];
- DPRINT("Found charmap encoding: %u\n", charmap->encoding);
+ DPRINT("Found charmap encoding: %i\n", charmap->encoding);
if (charmap->encoding != 0)
{
found = charmap;
goto fail;
}
- pmxWorldToDevice = DC_pmxWorldToDevice(dc);
- FtSetCoordinateTransform(face, pmxWorldToDevice);
+ if (dc->pdcattr->iGraphicsMode == GM_ADVANCED)
+ {
+ pmxWorldToDevice = DC_pmxWorldToDevice(dc);
+ FtSetCoordinateTransform(face, pmxWorldToDevice);
+
+ fixAscender = ScaleLong(face->size->metrics.ascender, &pmxWorldToDevice->efM22);
+ fixDescender = ScaleLong(face->size->metrics.descender, &pmxWorldToDevice->efM22);
+ }
+ else
+ {
+ pmxWorldToDevice = (PMATRIX)&gmxWorldToDeviceDefault;
+ FtSetCoordinateTransform(face, pmxWorldToDevice);
+
+ fixAscender = face->size->metrics.ascender;
+ fixDescender = face->size->metrics.descender;
+ }
/*
* Process the vertical alignment and determine the yoff.
*/
- fixAscender = ScaleLong(face->size->metrics.ascender, &pmxWorldToDevice->efM22);
- fixDescender = ScaleLong(face->size->metrics.descender, &pmxWorldToDevice->efM22);
-
if (pdcattr->lTextAlign & TA_BASELINE)
yoff = 0;
else if (pdcattr->lTextAlign & TA_BOTTOM)
{
ULONGLONG TextWidth = 0;
LPCWSTR TempText = String;
- int Start;
+ int iStart;
/*
* Calculate width of the text.
if (NULL != Dx)
{
- Start = Count < 2 ? 0 : Count - 2;
+ iStart = Count < 2 ? 0 : Count - 2;
TextWidth = Count < 2 ? 0 : (Dx[(Count-2)<<DxShift] << 6);
}
else
{
- Start = 0;
+ iStart = 0;
}
- TempText = String + Start;
+ TempText = String + iStart;
- for (i = Start; i < Count; i++)
+ for (i = iStart; i < Count; i++)
{
if (fuOptions & ETO_GLYPH_INDEX)
glyph_index = *TempText;
String++;
}
+
+ if (pdcattr->lTextAlign & TA_UPDATECP) {
+ pdcattr->ptlCurrent.x = DestRect.right - dc->ptlDCOrig.x;
+ }
+
IntUnLockFreeType;
DC_vFinishBlit(dc, NULL) ;
RECTL SafeRect;
BYTE LocalBuffer[STACK_TEXT_BUFFER_SIZE];
PVOID Buffer = LocalBuffer;
- LPWSTR SafeString = NULL;
+ LPCWSTR SafeString = NULL;
LPINT SafeDx = NULL;
ULONG BufSize, StringSize, DxSize = 0;
_SEH2_TRY
{
/* Put the Dx before the String to assure alignment of 4 */
- SafeString = (LPWSTR)(((ULONG_PTR)Buffer) + DxSize);
+ SafeString = (LPCWSTR)(((ULONG_PTR)Buffer) + DxSize);
/* Probe and copy the string */
ProbeForRead(UnsafeString, StringSize, 1);
return TRUE;
}
-DWORD
-FASTCALL
-GreGetGlyphIndicesW(
- HDC hdc,
- LPWSTR pwc,
- INT cwc,
- LPWORD pgi,
- DWORD iMode,
- DWORD Unknown)
-{
- PDC dc;
- PDC_ATTR pdcattr;
- PTEXTOBJ TextObj;
- PFONTGDI FontGDI;
- HFONT hFont = 0;
- OUTLINETEXTMETRICW *potm;
- INT i;
- FT_Face face;
- WCHAR DefChar = 0xffff;
- PWSTR Buffer = NULL;
- ULONG Size;
-
- if ((!pwc) && (!pgi)) return cwc;
-
- dc = DC_LockDc(hdc);
- if (!dc)
- {
- EngSetLastError(ERROR_INVALID_HANDLE);
- return GDI_ERROR;
- }
- pdcattr = dc->pdcattr;
- hFont = pdcattr->hlfntNew;
- TextObj = RealizeFontInit(hFont);
- DC_UnlockDc(dc);
- if (!TextObj)
- {
- EngSetLastError(ERROR_INVALID_HANDLE);
- return GDI_ERROR;
- }
-
- FontGDI = ObjToGDI(TextObj->Font, FONT);
- TEXTOBJ_UnlockText(TextObj);
-
- Buffer = ExAllocatePoolWithTag(PagedPool, cwc*sizeof(WORD), GDITAG_TEXT);
- if (!Buffer)
- {
- EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return GDI_ERROR;
- }
-
- if (iMode & GGI_MARK_NONEXISTING_GLYPHS) DefChar = 0x001f; /* Indicate non existence */
- else
- {
- Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
- potm = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT);
- if (!potm)
- {
- EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
- cwc = GDI_ERROR;
- goto ErrorRet;
- }
- IntGetOutlineTextMetrics(FontGDI, Size, potm);
- DefChar = potm->otmTextMetrics.tmDefaultChar; // May need this.
- ExFreePoolWithTag(potm, GDITAG_TEXT);
- }
-
- IntLockFreeType;
- face = FontGDI->face;
-
- for (i = 0; i < cwc; i++)
- {
- Buffer[i] = FT_Get_Char_Index(face, pwc[i]);
- if (Buffer[i] == 0)
- {
- if (DefChar == 0xffff && FT_IS_SFNT(face))
- {
- TT_OS2 *pOS2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
- DefChar = (pOS2->usDefaultChar ? FT_Get_Char_Index(face, pOS2->usDefaultChar) : 0);
- }
- Buffer[i] = DefChar;
- }
- }
-
- IntUnLockFreeType;
-
- RtlCopyMemory( pgi, Buffer, cwc*sizeof(WORD));
-
-ErrorRet:
- if (Buffer) ExFreePoolWithTag(Buffer, GDITAG_TEXT);
- return cwc;
-}
-
/*
* @implemented
*/
+__kernel_entry
+W32KAPI
DWORD
APIENTRY
NtGdiGetGlyphIndicesW(
- IN HDC hdc,
- IN OPTIONAL LPWSTR UnSafepwc,
- IN INT cwc,
- OUT OPTIONAL LPWORD UnSafepgi,
- IN DWORD iMode)
+ _In_ HDC hdc,
+ _In_reads_opt_(cwc) LPCWSTR pwc,
+ _In_ INT cwc,
+ _Out_writes_opt_(cwc) LPWORD pgi,
+ _In_ DWORD iMode)
{
PDC dc;
PDC_ATTR pdcattr;
NTSTATUS Status = STATUS_SUCCESS;
OUTLINETEXTMETRICW *potm;
INT i;
- FT_Face face;
WCHAR DefChar = 0xffff;
PWSTR Buffer = NULL;
ULONG Size, pwcSize;
PWSTR Safepwc = NULL;
+ LPCWSTR UnSafepwc = pwc;
+ LPWORD UnSafepgi = pgi;
if ((!UnSafepwc) && (!UnSafepgi)) return cwc;
+ if ((UnSafepwc == NULL) || (UnSafepgi == NULL))
+ {
+ DPRINT1("UnSafepwc == %p, UnSafepgi = %p\n", UnSafepwc, UnSafepgi);
+ return -1;
+ }
+
dc = DC_LockDc(hdc);
if (!dc)
{
- EngSetLastError(ERROR_INVALID_HANDLE);
return GDI_ERROR;
}
pdcattr = dc->pdcattr;
DC_UnlockDc(dc);
if (!TextObj)
{
- EngSetLastError(ERROR_INVALID_HANDLE);
return GDI_ERROR;
}
Buffer = ExAllocatePoolWithTag(PagedPool, cwc*sizeof(WORD), GDITAG_TEXT);
if (!Buffer)
{
- EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return GDI_ERROR;
}
- if (iMode & GGI_MARK_NONEXISTING_GLYPHS) DefChar = 0x001f; /* Indicate non existence */
+ if (iMode & GGI_MARK_NONEXISTING_GLYPHS)
+ {
+ DefChar = 0xffff;
+ }
else
{
- Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
- potm = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT);
- if (!potm)
+ if (FT_IS_SFNT(FontGDI->face))
{
- Status = ERROR_NOT_ENOUGH_MEMORY;
- goto ErrorRet;
+ TT_OS2 *pOS2 = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_os2);
+ DefChar = (pOS2->usDefaultChar ? FT_Get_Char_Index(FontGDI->face, pOS2->usDefaultChar) : 0);
+ }
+ else
+ {
+ Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
+ potm = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT);
+ if (!potm)
+ {
+ cwc = GDI_ERROR;
+ goto ErrorRet;
+ }
+ IntGetOutlineTextMetrics(FontGDI, Size, potm);
+ DefChar = potm->otmTextMetrics.tmDefaultChar;
+ ExFreePoolWithTag(potm, GDITAG_TEXT);
}
- IntGetOutlineTextMetrics(FontGDI, Size, potm);
- DefChar = potm->otmTextMetrics.tmDefaultChar; // May need this.
- ExFreePoolWithTag(potm, GDITAG_TEXT);
}
pwcSize = cwc * sizeof(WCHAR);
if (!Safepwc)
{
- EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return GDI_ERROR;
+ Status = STATUS_NO_MEMORY;
+ goto ErrorRet;
}
_SEH2_TRY
if (!NT_SUCCESS(Status)) goto ErrorRet;
IntLockFreeType;
- face = FontGDI->face;
-
- if (DefChar == 0xffff && FT_IS_SFNT(face))
- {
- TT_OS2 *pOS2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
- DefChar = (pOS2->usDefaultChar ? FT_Get_Char_Index(face, pOS2->usDefaultChar) : 0);
- }
for (i = 0; i < cwc; i++)
{
- Buffer[i] = FT_Get_Char_Index(face, Safepwc[i]);
+ Buffer[i] = FT_Get_Char_Index(FontGDI->face, Safepwc[i]);
if (Buffer[i] == 0)
{
Buffer[i] = DefChar;
ErrorRet:
ExFreePoolWithTag(Buffer, GDITAG_TEXT);
- ExFreePoolWithTag(Safepwc, GDITAG_TEXT);
+ if (Safepwc != NULL)
+ {
+ ExFreePoolWithTag(Safepwc, GDITAG_TEXT);
+ }
if (NT_SUCCESS(Status)) return cwc;
- EngSetLastError(Status);
return GDI_ERROR;
}