#include <win32k.h>
+#include FT_GLYPH_H
+#include FT_TYPE1_TABLES_H
+#include <freetype/tttables.h>
+#include <freetype/fttrigon.h>
+#include <freetype/ftbitmap.h>
+#include <freetype/ftoutln.h>
+#include <freetype/ftwinfnt.h>
+
#define NDEBUG
#include <debug.h>
FT_Face Face;
FT_BitmapGlyph BitmapGlyph;
int Height;
+ MATRIX mxWorldToDevice;
} FONT_CACHE_ENTRY, *PFONT_CACHE_ENTRY;
static LIST_ENTRY FontCacheListHead;
static UINT FontCacheNumEntries;
return TRUE;
}
+VOID
+FtSetCoordinateTransform(
+ FT_Face face,
+ PMATRIX pmx)
+{
+ FT_Matrix ftmatrix;
+ FLOATOBJ efTemp;
+
+ /* Create a freetype matrix, by converting to 16.16 fixpoint format */
+ efTemp = pmx->efM11;
+ FLOATOBJ_MulLong(&efTemp, 0x00010000);
+ ftmatrix.xx = FLOATOBJ_GetLong(&efTemp);
+
+ efTemp = pmx->efM12;
+ FLOATOBJ_MulLong(&efTemp, 0x00010000);
+ ftmatrix.xy = FLOATOBJ_GetLong(&efTemp);
+
+ efTemp = pmx->efM21;
+ FLOATOBJ_MulLong(&efTemp, 0x00010000);
+ ftmatrix.yx = FLOATOBJ_GetLong(&efTemp);
+
+ efTemp = pmx->efM22;
+ FLOATOBJ_MulLong(&efTemp, 0x00010000);
+ ftmatrix.yy = FLOATOBJ_GetLong(&efTemp);
+
+ /* Set the transformation matrix */
+ FT_Set_Transform(face, &ftmatrix, 0);
+}
+
/*
* IntLoadSystemFonts
*
FT_Face Face;
ANSI_STRING AnsiFaceName;
PFONT_ENTRY Entry;
- PSECTION_OBJECT SectionObject;
+ PVOID SectionObject;
ULONG ViewSize = 0;
LARGE_INTEGER SectionSize;
UNICODE_STRING FontRegPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts");
}
SectionSize.QuadPart = 0LL;
- Status = MmCreateSection((PVOID)&SectionObject, SECTION_ALL_ACCESS,
+ Status = MmCreateSection(&SectionObject, SECTION_ALL_ACCESS,
NULL, &SectionSize, PAGE_READONLY,
SEC_COMMIT, FileHandle, NULL);
if (!NT_SUCCESS(Status))
if (!NT_SUCCESS(Status))
{
DPRINT("Could not map file: %wZ\n", FileName);
- return Status;
+ ObDereferenceObject(SectionObject);
+ return 0;
}
IntLockFreeType;
0,
&Face);
IntUnLockFreeType;
+ ObDereferenceObject(SectionObject);
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);
- ObDereferenceObject(SectionObject);
+ DPRINT("Error reading font file (error code: %d)\n", Error);
return 0;
}
if (!Entry)
{
FT_Done_Face(Face);
- ObDereferenceObject(SectionObject);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
if (FontGDI == NULL)
{
FT_Done_Face(Face);
- ObDereferenceObject(SectionObject);
ExFreePoolWithTag(Entry, TAG_FONT);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
{
EngFreeMem(FontGDI);
FT_Done_Face(Face);
- ObDereferenceObject(SectionObject);
ExFreePoolWithTag(Entry, TAG_FONT);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
FontGDI->face = Face;
DPRINT("Font loaded: %s (%s)\n", Face->family_name, Face->style_name);
- DPRINT("Num glyphs: %u\n", Face->num_glyphs);
+ DPRINT("Num glyphs: %d\n", Face->num_glyphs);
/* Add this font resource to the font table */
wcscpy(Info->EnumLogFontEx.elfScript, ElfScripts[i]);
else
{
- DPRINT1("Unknown elfscript for bit %d\n", i);
+ DPRINT1("Unknown elfscript for bit %u\n", i);
}
}
}
return FALSE;
}
+static
+BOOL
+SameScaleMatrix(
+ PMATRIX pmx1,
+ PMATRIX pmx2)
+{
+ return (FLOATOBJ_Equal(&pmx1->efM11, &pmx2->efM11) &&
+ FLOATOBJ_Equal(&pmx1->efM12, &pmx2->efM12) &&
+ FLOATOBJ_Equal(&pmx1->efM21, &pmx2->efM21) &&
+ FLOATOBJ_Equal(&pmx1->efM22, &pmx2->efM22));
+}
FT_BitmapGlyph APIENTRY
ftGdiGlyphCacheGet(
FT_Face Face,
INT GlyphIndex,
- INT Height)
+ INT Height,
+ PMATRIX pmx)
{
PLIST_ENTRY CurrentEntry;
PFONT_CACHE_ENTRY FontEntry;
while (CurrentEntry != &FontCacheListHead)
{
FontEntry = (PFONT_CACHE_ENTRY)CurrentEntry;
- if (FontEntry->Face == Face &&
- FontEntry->GlyphIndex == GlyphIndex &&
- FontEntry->Height == Height)
+ if ((FontEntry->Face == Face) &&
+ (FontEntry->GlyphIndex == GlyphIndex) &&
+ (FontEntry->Height == Height) &&
+ (SameScaleMatrix(&FontEntry->mxWorldToDevice, pmx)))
break;
CurrentEntry = CurrentEntry->Flink;
}
FT_Face Face,
INT GlyphIndex,
INT Height,
+ PMATRIX pmx,
FT_GlyphSlot GlyphSlot,
FT_Render_Mode RenderMode)
{
NewEntry->Face = Face;
NewEntry->BitmapGlyph = BitmapGlyph;
NewEntry->Height = Height;
+ NewEntry->mxWorldToDevice = *pmx;
InsertHeadList(&FontCacheListHead, &NewEntry->ListEntry);
if (FontCacheNumEntries++ > MAX_FONT_CACHE)
FT_CharMap found = 0, charmap;
XFORM xForm;
- DPRINT("%d, %08x, %p, %08lx, %p, %p\n", wch, iFormat, pgm,
+ DPRINT("%u, %08x, %p, %08lx, %p, %p\n", wch, iFormat, pgm,
cjBuf, pvBuf, pmat2);
pdcattr = dc->pdcattr;
/* FIXME: Should set character height if neg */
// (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ?
// dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));
+// FtSetCoordinateTransform(face, DC_pmxWorldToDevice(dc));
TEXTOBJ_UnlockText(TextObj);
IntLockFreeType;
/* Scaling transform */
- if (aveWidth)
- {
- FT_Matrix scaleMat;
- DPRINT("Scaling Trans!\n");
- scaleMat.xx = FT_FixedFromFloat(widthRatio);
- scaleMat.xy = 0;
- scaleMat.yx = 0;
- scaleMat.yy = (1 << 16);
- FT_Matrix_Multiply(&scaleMat, &transMat);
+ /*if (aveWidth)*/
+ {
+
+ FT_Matrix ftmatrix;
+ FLOATOBJ efTemp;
+
+ PMATRIX pmx = DC_pmxWorldToDevice(dc);
+
+ /* Create a freetype matrix, by converting to 16.16 fixpoint format */
+ efTemp = pmx->efM11;
+ FLOATOBJ_MulLong(&efTemp, 0x00010000);
+ ftmatrix.xx = FLOATOBJ_GetLong(&efTemp);
+
+ efTemp = pmx->efM12;
+ FLOATOBJ_MulLong(&efTemp, 0x00010000);
+ ftmatrix.xy = FLOATOBJ_GetLong(&efTemp);
+
+ efTemp = pmx->efM21;
+ FLOATOBJ_MulLong(&efTemp, 0x00010000);
+ ftmatrix.yx = FLOATOBJ_GetLong(&efTemp);
+
+ efTemp = pmx->efM22;
+ FLOATOBJ_MulLong(&efTemp, 0x00010000);
+ ftmatrix.yy = FLOATOBJ_GetLong(&efTemp);
+
+ FT_Matrix_Multiply(&ftmatrix, &transMat);
needsTransform = TRUE;
}
gm.gmptGlyphOrigin.x = left >> 6;
gm.gmptGlyphOrigin.y = top >> 6;
- DPRINT("CX %d CY %d BBX %d BBY %d GOX %d GOY %d\n",
+ DPRINT("CX %d CY %d BBX %u BBY %u GOX %d GOY %d\n",
gm.gmCellIncX, gm.gmCellIncY,
gm.gmBlackBoxX, gm.gmBlackBoxY,
gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
}
default:
- DPRINT1("Unsupported format %d\n", iFormat);
+ DPRINT1("Unsupported format %u\n", iFormat);
return GDI_ERROR;
}
- DPRINT("ftGdiGetGlyphOutline END and needed %d\n", needed);
+ DPRINT("ftGdiGetGlyphOutline END and needed %lu\n", needed);
return needed;
}
BOOL use_kerning;
FT_Render_Mode RenderMode;
BOOLEAN Render;
+ PMATRIX pmxWorldToDevice;
FontGDI = ObjToGDI(TextObj->Font, FONT);
dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));
if (error)
{
- DPRINT1("Error in setting pixel sizes: %u\n", error);
+ DPRINT1("Error in setting pixel sizes: %d\n", error);
}
+ /* Get the DC's world-to-device transformation matrix */
+ pmxWorldToDevice = DC_pmxWorldToDevice(dc);
+ FtSetCoordinateTransform(face, pmxWorldToDevice);
+
use_kerning = FT_HAS_KERNING(face);
previous = 0;
glyph_index = FT_Get_Char_Index(face, *String);
if (!(realglyph = ftGdiGlyphCacheGet(face, glyph_index,
- TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)))
+ TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight,
+ pmxWorldToDevice)))
{
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if (error)
{
- DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
+ DPRINT1("WARNING: Failed to load and render glyph! [index: %d]\n", glyph_index);
break;
}
glyph = face->glyph;
- realglyph = ftGdiGlyphCacheSet(face, glyph_index,
- TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight, glyph, RenderMode);
+ realglyph = ftGdiGlyphCacheSet(face,
+ glyph_index,
+ TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight,
+ pmxWorldToDevice,
+ glyph,
+ RenderMode);
if (!realglyph)
{
- DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index);
+ DPRINT1("Failed to render glyph! [index: %d]\n", glyph_index);
break;
}
}
}
}
Exit:
- DPRINT("CharSet %d CodePage %d\n",csi.ciCharset, csi.ciACP);
+ DPRINT("CharSet %u CodePage %u\n", csi.ciCharset, csi.ciACP);
return (MAKELONG(csi.ciACP, csi.ciCharset));
}
/* FIXME: Should set character height if neg */
(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ?
dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));
+ FtSetCoordinateTransform(Face, DC_pmxWorldToDevice(dc));
IntUnLockFreeType;
if (0 != Error)
{
return;
}
- if (SubstituteFontFamilyKey(FaceName, L"FontSubstitutes") ||
- SubstituteFontFamilyKey(FaceName, L"FontSubstitutes"))
+ if (SubstituteFontFamilyKey(FaceName, L"FontSubstitutes"))
{
SubstituteFontFamily(FaceName, Level + 1);
}
return Count;
}
+LONG
+FORCEINLINE
+ScaleLong(LONG lValue, PFLOATOBJ pef)
+{
+ FLOATOBJ efTemp;
+
+ /* Check if we have scaling different from 1 */
+ if (!FLOATOBJ_Equal(pef, (PFLOATOBJ)&gef1))
+ {
+ /* Need to multiply */
+ FLOATOBJ_SetLong(&efTemp, lValue);
+ FLOATOBJ_Mul(&efTemp, pef);
+ lValue = FLOATOBJ_GetLong(&efTemp);
+ }
+
+ return lValue;
+}
+
BOOL
APIENTRY
GreExtTextOutW(
POINT Start;
BOOL DoBreak = FALSE;
USHORT DxShift;
+ PMATRIX pmxWorldToDevice;
+ LONG fixAscender, fixDescender;
// 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->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));
if (error)
{
- DPRINT1("Error in setting pixel sizes: %u\n", error);
+ DPRINT1("Error in setting pixel sizes: %d\n", error);
IntUnLockFreeType;
goto fail;
}
+ pmxWorldToDevice = DC_pmxWorldToDevice(dc);
+ FtSetCoordinateTransform(face, pmxWorldToDevice);
+
/*
* 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)
- yoff = -face->size->metrics.descender >> 6;
+ yoff = -fixDescender >> 6;
else /* TA_TOP */
- yoff = face->size->metrics.ascender >> 6;
+ yoff = fixAscender >> 6;
use_kerning = FT_HAS_KERNING(face);
previous = 0;
glyph_index = FT_Get_Char_Index(face, *TempText);
if (!(realglyph = ftGdiGlyphCacheGet(face, glyph_index,
- TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)))
+ TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight,
+ pmxWorldToDevice)))
{
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if (error)
{
- DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
+ DPRINT1("WARNING: Failed to load and render glyph! [index: %d]\n", glyph_index);
}
glyph = face->glyph;
- realglyph = ftGdiGlyphCacheSet(face, glyph_index,
- TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight, glyph, RenderMode);
+ realglyph = ftGdiGlyphCacheSet(face,
+ glyph_index,
+ TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight,
+ pmxWorldToDevice,
+ glyph,
+ RenderMode);
if (!realglyph)
{
- DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index);
+ DPRINT1("Failed to render glyph! [index: %d]\n", glyph_index);
IntUnLockFreeType;
goto fail;
}
glyph_index = FT_Get_Char_Index(face, *String);
if (!(realglyph = ftGdiGlyphCacheGet(face, glyph_index,
- TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)))
+ TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight,
+ pmxWorldToDevice)))
{
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if (error)
{
- DPRINT1("Failed to load and render glyph! [index: %u]\n", glyph_index);
+ DPRINT1("Failed to load and render glyph! [index: %d]\n", glyph_index);
IntUnLockFreeType;
goto fail2;
}
realglyph = ftGdiGlyphCacheSet(face,
glyph_index,
TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight,
+ pmxWorldToDevice,
glyph,
RenderMode);
if (!realglyph)
{
- DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index);
+ DPRINT1("Failed to render glyph! [index: %d]\n", glyph_index);
IntUnLockFreeType;
goto fail2;
}
FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
TextLeft += delta.x;
}
- DPRINT("TextLeft: %d\n", TextLeft);
- DPRINT("TextTop: %d\n", TextTop);
+ DPRINT("TextLeft: %I64d\n", TextLeft);
+ DPRINT("TextTop: %lu\n", TextTop);
DPRINT("Advance: %d\n", realglyph->root.advance.x);
if (fuOptions & ETO_OPAQUE)
{
DestRect.left = BackgroundLeft;
DestRect.right = (TextLeft + (realglyph->root.advance.x >> 10) + 32) >> 6;
- DestRect.top = TextTop + yoff - ((face->size->metrics.ascender + 32) >> 6);
- DestRect.bottom = TextTop + yoff + ((32 - face->size->metrics.descender) >> 6);
+ DestRect.top = TextTop + yoff - ((fixAscender + 32) >> 6);
+ DestRect.bottom = TextTop + yoff + ((32 - fixDescender) >> 6);
MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
IntEngBitBlt(
&psurf->SurfObj,
if (NULL == Dx)
{
TextLeft += realglyph->root.advance.x >> 10;
- DPRINT("New TextLeft: %d\n", TextLeft);
+ DPRINT("New TextLeft: %I64d\n", TextLeft);
}
else
{
TextLeft += Dx[i<<DxShift] << 6;
- DPRINT("New TextLeft2: %d\n", TextLeft);
+ DPRINT("New TextLeft2: %I64d\n", TextLeft);
}
if (DxShift)
UINT i, glyph_index, BufferSize;
HFONT hFont = 0;
NTSTATUS Status = STATUS_SUCCESS;
+ PMATRIX pmxWorldToDevice;
if (pwch)
{
pdcattr = dc->pdcattr;
hFont = pdcattr->hlfntNew;
TextObj = RealizeFontInit(hFont);
+
+ /* Get the DC's world-to-device transformation matrix */
+ pmxWorldToDevice = DC_pmxWorldToDevice(dc);
DC_UnlockDc(dc);
if (TextObj == NULL)
/* FIXME: Should set character height if neg */
(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ?
dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));
+ FtSetCoordinateTransform(face, pmxWorldToDevice);
for (i = FirstChar; i < FirstChar+Count; i++)
{
FT_CharMap charmap, found = NULL;
UINT i, glyph_index, BufferSize;
HFONT hFont = 0;
+ PMATRIX pmxWorldToDevice;
if (pwc)
{
pdcattr = dc->pdcattr;
hFont = pdcattr->hlfntNew;
TextObj = RealizeFontInit(hFont);
+ /* Get the DC's world-to-device transformation matrix */
+ pmxWorldToDevice = DC_pmxWorldToDevice(dc);
DC_UnlockDc(dc);
if (TextObj == NULL)
/* FIXME: Should set character height if neg */
(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ?
dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));
+ FtSetCoordinateTransform(face, pmxWorldToDevice);
for (i = FirstChar; i < FirstChar+Count; i++)
{