Implement GetFontUnicodeRanges, port from wine. Tested with wine gdi32 font crosstests.

svn path=/trunk/; revision=37099
This commit is contained in:
James Tabor 2008-10-30 13:33:08 +00:00
parent a233789dd4
commit 7bfa0b86e3
4 changed files with 144 additions and 13 deletions

View file

@ -92,6 +92,7 @@ DWORD FASTCALL IntGdiGetCharSet(HDC);
BOOL FASTCALL ftGdiGetTextMetricsW(HDC,PTMW_INTERNAL);
DWORD FASTCALL ftGetFontLanguageInfo(PDC);
INT FASTCALL ftGdiGetTextCharsetInfo(PDC,PFONTSIGNATURE,DWORD);
DWORD FASTCALL ftGetFontUnicodeRanges(PFONTGDI, PGLYPHSET);
#define IntLockProcessPrivateFonts(W32Process) \
ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&W32Process->PrivateFontListLock)

View file

@ -62,6 +62,81 @@ NtGdiAddFontResourceW(
return Ret;
}
/*
* @implemented
*/
DWORD
APIENTRY
NtGdiGetFontUnicodeRanges(
IN HDC hdc,
OUT OPTIONAL LPGLYPHSET pgs)
{
PDC pDc;
PDC_ATTR Dc_Attr;
HFONT hFont;
PTEXTOBJ TextObj;
PFONTGDI FontGdi;
DWORD Size = 0;
PGLYPHSET pgsSafe;
NTSTATUS Status = STATUS_SUCCESS;
pDc = DC_LockDc(hdc);
if (!pDc)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
}
Dc_Attr = pDc->pDc_Attr;
if(!Dc_Attr) Dc_Attr = &pDc->Dc_Attr;
hFont = Dc_Attr->hlfntNew;
TextObj = TEXTOBJ_LockText(hFont);
if ( TextObj == NULL)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
goto Exit;
}
FontGdi = ObjToGDI(TextObj->Font, FONT);
Size = ftGetFontUnicodeRanges( FontGdi, NULL);
if (Size && pgs)
{
pgsSafe = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
if (!pgsSafe)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
Size = 0;
goto Exit;
}
Size = ftGetFontUnicodeRanges( FontGdi, pgsSafe);
if (Size)
{
_SEH_TRY
{
ProbeForWrite(pgsSafe, Size, 1);
RtlCopyMemory(pgs, pgsSafe, Size);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END
if (!NT_SUCCESS(Status)) Size = 0;
}
ExFreePoolWithTag(pgsSafe, TAG_GDITEXT);
}
Exit:
TEXTOBJ_UnlockText(TextObj);
DC_UnlockDc(pDc);
return Size;
}
ULONG
APIENTRY
NtGdiGetGlyphOutline(

View file

@ -3371,6 +3371,74 @@ ftGdiGetTextCharsetInfo(
return Ret;
}
DWORD
FASTCALL
ftGetFontUnicodeRanges(PFONTGDI Font, PGLYPHSET glyphset)
{
DWORD size = 0;
DWORD num_ranges = 0;
FT_Face face = Font->face;
if (face->charmap->encoding == FT_ENCODING_UNICODE)
{
FT_UInt glyph_code = 0;
FT_ULong char_code, char_code_prev;
char_code_prev = char_code = FT_Get_First_Char(face, &glyph_code);
DPRINT("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
face->num_glyphs, glyph_code, char_code);
if (!glyph_code) return 0;
if (glyphset)
{
glyphset->ranges[0].wcLow = (USHORT)char_code;
glyphset->ranges[0].cGlyphs = 0;
glyphset->cGlyphsSupported = 0;
}
num_ranges = 1;
while (glyph_code)
{
if (char_code < char_code_prev)
{
DPRINT1("expected increasing char code from FT_Get_Next_Char\n");
return 0;
}
if (char_code - char_code_prev > 1)
{
num_ranges++;
if (glyphset)
{
glyphset->ranges[num_ranges - 1].wcLow = (USHORT)char_code;
glyphset->ranges[num_ranges - 1].cGlyphs = 1;
glyphset->cGlyphsSupported++;
}
}
else if (glyphset)
{
glyphset->ranges[num_ranges - 1].cGlyphs++;
glyphset->cGlyphsSupported++;
}
char_code_prev = char_code;
char_code = FT_Get_Next_Char(face, char_code, &glyph_code);
}
}
else
DPRINT1("encoding %u not supported\n", face->charmap->encoding);
size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
if (glyphset)
{
glyphset->cbThis = size;
glyphset->cRanges = num_ranges;
}
return size;
}
DWORD
FASTCALL
ftGetFontLanguageInfo(PDC Dc)

View file

@ -2227,19 +2227,6 @@ NtGdiQueryFontAssocInfo(
return 0;
}
/*
* @unimplemented
*/
DWORD
APIENTRY
NtGdiGetFontUnicodeRanges(
IN HDC hdc,
OUT OPTIONAL LPGLYPHSET pgs)
{
UNIMPLEMENTED;
return 0;
}
/*
* @unimplemented
*/