#include <win32k.h>
+#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 <gdi/eng/floatobj.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 */
switch (Flags)
{
case TCI_SRCFONTSIG:
- while (0 == (*Src >> Index & 0x0001) && Index < MAXTCIINDEX)
+ while (Index < MAXTCIINDEX && 0 == (*Src >> Index & 0x0001))
{
Index++;
}
break;
case TCI_SRCCODEPAGE:
- while ( *Src != FontTci[Index].ciACP && Index < MAXTCIINDEX)
+ while (Index < MAXTCIINDEX && *Src != FontTci[Index].ciACP)
{
Index++;
}
break;
case TCI_SRCCHARSET:
- while ( *Src != FontTci[Index].ciCharset && Index < MAXTCIINDEX)
+ while (Index < MAXTCIINDEX && *Src != FontTci[Index].ciCharset)
{
Index++;
}
wcscpy(Info->EnumLogFontEx.elfScript, ElfScripts[i]);
else
{
- DPRINT1("Unknown elfscript for bit %d\n", i);
+ DPRINT1("Unknown elfscript for bit %u\n", i);
}
}
}
FONT_FAMILY_INFO_CALLBACK_CONTEXT Context;
NTSTATUS Status;
- /* Enumerate font families found in HKLM\Software\Microsoft\Windows NT\CurrentVersion\SysFontSubstitutes
+ /* Enumerate font families found in HKLM\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes
The real work is done in the registry callback function */
Context.LogFont = LogFont;
Context.Info = Info;
QueryTable[1].Name = NULL;
Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
- L"SysFontSubstitutes",
+ L"FontSubstitutes",
QueryTable,
&Context,
NULL);
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)
NewEntry = (PFONT_CACHE_ENTRY)FontCacheListHead.Blink;
FT_Done_Glyph((FT_Glyph)NewEntry->BitmapGlyph);
RemoveTailList(&FontCacheListHead);
- ExFreePool(NewEntry);
+ ExFreePoolWithTag(NewEntry, TAG_FONT);
FontCacheNumEntries--;
}
return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract);
}
+static unsigned int get_native_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
+{
+ TTPOLYGONHEADER *pph;
+ TTPOLYCURVE *ppc;
+ unsigned int needed = 0, point = 0, contour, first_pt;
+ unsigned int pph_start, cpfx;
+ DWORD type;
+
+ for (contour = 0; contour < outline->n_contours; contour++)
+ {
+ /* Ignore contours containing one point */
+ if (point == outline->contours[contour])
+ {
+ point++;
+ continue;
+ }
+
+ pph_start = needed;
+ pph = (TTPOLYGONHEADER *)(buf + needed);
+ first_pt = point;
+ if (buf)
+ {
+ pph->dwType = TT_POLYGON_TYPE;
+ FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
+ }
+ needed += sizeof(*pph);
+ point++;
+ while (point <= outline->contours[contour])
+ {
+ ppc = (TTPOLYCURVE *)(buf + needed);
+ type = outline->tags[point] & FT_Curve_Tag_On ?
+ TT_PRIM_LINE : TT_PRIM_QSPLINE;
+ cpfx = 0;
+ do
+ {
+ if (buf)
+ FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
+ cpfx++;
+ point++;
+ } while (point <= outline->contours[contour] &&
+ (outline->tags[point] & FT_Curve_Tag_On) ==
+ (outline->tags[point-1] & FT_Curve_Tag_On));
+ /* At the end of a contour Windows adds the start point, but
+ only for Beziers */
+ if (point > outline->contours[contour] &&
+ !(outline->tags[point-1] & FT_Curve_Tag_On))
+ {
+ if (buf)
+ FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
+ cpfx++;
+ }
+ else if (point <= outline->contours[contour] &&
+ outline->tags[point] & FT_Curve_Tag_On)
+ {
+ /* add closing pt for bezier */
+ if (buf)
+ FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
+ cpfx++;
+ point++;
+ }
+ if (buf)
+ {
+ ppc->wType = type;
+ ppc->cpfx = cpfx;
+ }
+ needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
+ }
+ if (buf)
+ pph->cb = needed - pph_start;
+ }
+ return needed;
+}
+
+static unsigned int get_bezier_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
+{
+ /* Convert the quadratic Beziers to cubic Beziers.
+ The parametric eqn for a cubic Bezier is, from PLRM:
+ r(t) = at^3 + bt^2 + ct + r0
+ with the control points:
+ r1 = r0 + c/3
+ r2 = r1 + (c + b)/3
+ r3 = r0 + c + b + a
+
+ A quadratic Bezier has the form:
+ p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
+
+ So equating powers of t leads to:
+ r1 = 2/3 p1 + 1/3 p0
+ r2 = 2/3 p1 + 1/3 p2
+ and of course r0 = p0, r3 = p2
+ */
+ int contour, point = 0, first_pt;
+ TTPOLYGONHEADER *pph;
+ TTPOLYCURVE *ppc;
+ DWORD pph_start, cpfx, type;
+ FT_Vector cubic_control[4];
+ unsigned int needed = 0;
+
+ for (contour = 0; contour < outline->n_contours; contour++)
+ {
+ pph_start = needed;
+ pph = (TTPOLYGONHEADER *)(buf + needed);
+ first_pt = point;
+ if (buf)
+ {
+ pph->dwType = TT_POLYGON_TYPE;
+ FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
+ }
+ needed += sizeof(*pph);
+ point++;
+ while (point <= outline->contours[contour])
+ {
+ ppc = (TTPOLYCURVE *)(buf + needed);
+ type = outline->tags[point] & FT_Curve_Tag_On ?
+ TT_PRIM_LINE : TT_PRIM_CSPLINE;
+ cpfx = 0;
+ do
+ {
+ if (type == TT_PRIM_LINE)
+ {
+ if (buf)
+ FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
+ cpfx++;
+ point++;
+ }
+ else
+ {
+ /* Unlike QSPLINEs, CSPLINEs always have their endpoint
+ so cpfx = 3n */
+
+ /* FIXME: Possible optimization in endpoint calculation
+ if there are two consecutive curves */
+ cubic_control[0] = outline->points[point-1];
+ if (!(outline->tags[point-1] & FT_Curve_Tag_On))
+ {
+ cubic_control[0].x += outline->points[point].x + 1;
+ cubic_control[0].y += outline->points[point].y + 1;
+ cubic_control[0].x >>= 1;
+ cubic_control[0].y >>= 1;
+ }
+ if (point+1 > outline->contours[contour])
+ cubic_control[3] = outline->points[first_pt];
+ else
+ {
+ cubic_control[3] = outline->points[point+1];
+ if (!(outline->tags[point+1] & FT_Curve_Tag_On))
+ {
+ cubic_control[3].x += outline->points[point].x + 1;
+ cubic_control[3].y += outline->points[point].y + 1;
+ cubic_control[3].x >>= 1;
+ cubic_control[3].y >>= 1;
+ }
+ }
+ /* r1 = 1/3 p0 + 2/3 p1
+ r2 = 1/3 p2 + 2/3 p1 */
+ cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
+ cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
+ cubic_control[2] = cubic_control[1];
+ cubic_control[1].x += (cubic_control[0].x + 1) / 3;
+ cubic_control[1].y += (cubic_control[0].y + 1) / 3;
+ cubic_control[2].x += (cubic_control[3].x + 1) / 3;
+ cubic_control[2].y += (cubic_control[3].y + 1) / 3;
+ if (buf)
+ {
+ FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
+ FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
+ FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
+ }
+ cpfx += 3;
+ point++;
+ }
+ } while (point <= outline->contours[contour] &&
+ (outline->tags[point] & FT_Curve_Tag_On) ==
+ (outline->tags[point-1] & FT_Curve_Tag_On));
+ /* At the end of a contour Windows adds the start point,
+ but only for Beziers and we've already done that.
+ */
+ if (point <= outline->contours[contour] &&
+ outline->tags[point] & FT_Curve_Tag_On)
+ {
+ /* This is the closing pt of a bezier, but we've already
+ added it, so just inc point and carry on */
+ point++;
+ }
+ if (buf)
+ {
+ ppc->wType = type;
+ ppc->cpfx = cpfx;
+ }
+ needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
+ }
+ if (buf)
+ pph->cb = needed - pph_start;
+ }
+ return needed;
+}
+
/*
* Based on WineEngGetGlyphOutline
*
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;
}
}
-// FT_Set_Pixel_Sizes(ft_face,
-// TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth,
+ FT_Set_Pixel_Sizes(ft_face,
+ abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth),
/* FIXME: Should set character height if neg */
-// (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ?
-// dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));
+ (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ?
+ dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));
+ FtSetCoordinateTransform(ft_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);
case GGO_NATIVE:
{
- int contour, point = 0, first_pt;
FT_Outline *outline = &ft_face->glyph->outline;
- TTPOLYGONHEADER *pph;
- TTPOLYCURVE *ppc;
- DWORD pph_start, cpfx, type;
if (cjBuf == 0) pvBuf = NULL; /* This is okay, need cjBuf to allocate. */
IntLockFreeType;
if (needsTransform && pvBuf) FT_Outline_Transform(outline, &transMat);
- for (contour = 0; contour < outline->n_contours; contour++)
+ needed = get_native_glyph_outline(outline, cjBuf, NULL);
+
+ if (!pvBuf || !cjBuf)
{
- pph_start = needed;
- pph = (TTPOLYGONHEADER *)((char *)pvBuf + needed);
- first_pt = point;
- if (pvBuf)
- {
- pph->dwType = TT_POLYGON_TYPE;
- FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
- }
- needed += sizeof(*pph);
- point++;
- while (point <= outline->contours[contour])
- {
- ppc = (TTPOLYCURVE *)((char *)pvBuf + needed);
- type = (outline->tags[point] & FT_Curve_Tag_On) ?
- TT_PRIM_LINE : TT_PRIM_QSPLINE;
- cpfx = 0;
- do
- {
- if (pvBuf)
- FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
- cpfx++;
- point++;
- }
- while (point <= outline->contours[contour] &&
- (outline->tags[point] & FT_Curve_Tag_On) ==
- (outline->tags[point-1] & FT_Curve_Tag_On));
-
- /* At the end of a contour Windows adds the start point, but
- only for Beziers */
- if (point > outline->contours[contour] &&
- !(outline->tags[point-1] & FT_Curve_Tag_On))
- {
- if (pvBuf)
- FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
- cpfx++;
- }
- else if (point <= outline->contours[contour] &&
- outline->tags[point] & FT_Curve_Tag_On)
- {
- /* Add closing pt for bezier */
- if (pvBuf)
- FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
- cpfx++;
- point++;
- }
- if (pvBuf)
- {
- ppc->wType = type;
- ppc->cpfx = cpfx;
- }
- needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
- }
- if (pvBuf) pph->cb = needed - pph_start;
+ IntUnLockFreeType;
+ break;
}
+ if (needed > cjBuf)
+ {
+ IntUnLockFreeType;
+ return GDI_ERROR;
+ }
+ get_native_glyph_outline(outline, cjBuf, pvBuf);
IntUnLockFreeType;
break;
}
case GGO_BEZIER:
{
- /* Convert the quadratic Beziers to cubic Beziers.
- The parametric eqn for a cubic Bezier is, from PLRM:
- r(t) = at^3 + bt^2 + ct + r0
- with the control points:
- r1 = r0 + c/3
- r2 = r1 + (c + b)/3
- r3 = r0 + c + b + a
-
- A quadratic Beizer has the form:
- p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
-
- So equating powers of t leads to:
- r1 = 2/3 p1 + 1/3 p0
- r2 = 2/3 p1 + 1/3 p2
- and of course r0 = p0, r3 = p2
- */
-
- int contour, point = 0, first_pt;
FT_Outline *outline = &ft_face->glyph->outline;
- TTPOLYGONHEADER *pph;
- TTPOLYCURVE *ppc;
- DWORD pph_start, cpfx, type;
- FT_Vector cubic_control[4];
if (cjBuf == 0) pvBuf = NULL;
if (needsTransform && pvBuf)
FT_Outline_Transform(outline, &transMat);
IntUnLockFreeType;
}
+ needed = get_bezier_glyph_outline(outline, cjBuf, NULL);
- for (contour = 0; contour < outline->n_contours; contour++)
- {
- pph_start = needed;
- pph = (TTPOLYGONHEADER *)((char *)pvBuf + needed);
- first_pt = point;
- if (pvBuf)
- {
- pph->dwType = TT_POLYGON_TYPE;
- FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
- }
- needed += sizeof(*pph);
- point++;
- while (point <= outline->contours[contour])
- {
- ppc = (TTPOLYCURVE *)((char *)pvBuf + needed);
- type = (outline->tags[point] & FT_Curve_Tag_On) ?
- TT_PRIM_LINE : TT_PRIM_CSPLINE;
- cpfx = 0;
- do
- {
- if (type == TT_PRIM_LINE)
- {
- if (pvBuf)
- FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
- cpfx++;
- point++;
- }
- else
- {
- /* Unlike QSPLINEs, CSPLINEs always have their endpoint
- so cpfx = 3n */
-
- /* FIXME: Possible optimization in endpoint calculation
- if there are two consecutive curves */
- cubic_control[0] = outline->points[point-1];
- if (!(outline->tags[point-1] & FT_Curve_Tag_On))
- {
- cubic_control[0].x += outline->points[point].x + 1;
- cubic_control[0].y += outline->points[point].y + 1;
- cubic_control[0].x >>= 1;
- cubic_control[0].y >>= 1;
- }
- if (point+1 > outline->contours[contour])
- cubic_control[3] = outline->points[first_pt];
- else
- {
- cubic_control[3] = outline->points[point+1];
- if (!(outline->tags[point+1] & FT_Curve_Tag_On))
- {
- cubic_control[3].x += outline->points[point].x + 1;
- cubic_control[3].y += outline->points[point].y + 1;
- cubic_control[3].x >>= 1;
- cubic_control[3].y >>= 1;
- }
- }
- /* r1 = 1/3 p0 + 2/3 p1
- r2 = 1/3 p2 + 2/3 p1 */
- cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
- cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
- cubic_control[2] = cubic_control[1];
- cubic_control[1].x += (cubic_control[0].x + 1) / 3;
- cubic_control[1].y += (cubic_control[0].y + 1) / 3;
- cubic_control[2].x += (cubic_control[3].x + 1) / 3;
- cubic_control[2].y += (cubic_control[3].y + 1) / 3;
- if (pvBuf)
- {
- FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
- FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
- FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
- }
- cpfx += 3;
- point++;
- }
- }
- while (point <= outline->contours[contour] &&
- (outline->tags[point] & FT_Curve_Tag_On) ==
- (outline->tags[point-1] & FT_Curve_Tag_On));
- /* At the end of a contour Windows adds the start point,
- but only for Beziers and we've already done that. */
- if (point <= outline->contours[contour] &&
- outline->tags[point] & FT_Curve_Tag_On)
- {
- /* This is the closing pt of a bezier, but we've already
- added it, so just inc point and carry on */
- point++;
- }
- if (pvBuf)
- {
- ppc->wType = type;
- ppc->cpfx = cpfx;
- }
- needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
- }
- if (pvBuf) pph->cb = needed - pph_start;
- }
+ if (!pvBuf || !cjBuf)
+ break;
+ if (needed > cjBuf)
+ return GDI_ERROR;
+
+ get_bezier_glyph_outline(outline, cjBuf, pvBuf);
break;
}
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)
{
Status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
if (NT_SUCCESS(Status))
{
+ static const UNICODE_STRING MarlettFaceNameW = RTL_CONSTANT_STRING(L"Marlett");
+ static const UNICODE_STRING SymbolFaceNameW = RTL_CONSTANT_STRING(L"Symbol");
+ static const UNICODE_STRING VGAFaceNameW = RTL_CONSTANT_STRING(L"VGA");
+
if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length)
{
EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR);
EntryFaceNameW.Buffer[LF_FACESIZE - 1] = L'\0';
}
- if (0 == RtlCompareUnicodeString(FaceName, &EntryFaceNameW, TRUE))
+
+ if (!RtlCompareUnicodeString(FaceName, &EntryFaceNameW, TRUE))
{
Score += 49;
}
+
+ /* FIXME: this is a work around to counter weird fonts on weird places.
+ A proper fix would be to score fonts on more attributes than
+ the ones in this function */
+ if (!RtlCompareUnicodeString(&MarlettFaceNameW, &EntryFaceNameW, TRUE) &&
+ RtlCompareUnicodeString(&MarlettFaceNameW, FaceName, TRUE))
+ {
+ Score = 0;
+ }
+
+ if (!RtlCompareUnicodeString(&SymbolFaceNameW, &EntryFaceNameW, TRUE) &&
+ RtlCompareUnicodeString(&SymbolFaceNameW, FaceName, TRUE))
+ {
+ Score = 0;
+ }
+
+ if (!RtlCompareUnicodeString(&VGAFaceNameW, &EntryFaceNameW, TRUE) &&
+ RtlCompareUnicodeString(&VGAFaceNameW, FaceName, TRUE))
+ {
+ Score = 0;
+ }
+
RtlFreeUnicodeString(&EntryFaceNameW);
}
Score += 25;
}
- ExFreePool(Otm);
+ ExFreePoolWithTag(Otm, GDITAG_TEXT);
return Score;
}
return;
}
- if (SubstituteFontFamilyKey(FaceName, L"SysFontSubstitutes") ||
- SubstituteFontFamilyKey(FaceName, L"FontSubstitutes"))
+ if (SubstituteFontFamilyKey(FaceName, L"FontSubstitutes"))
{
SubstituteFontFamily(FaceName, Level + 1);
}
/* Get the full path name */
if (!IntGetFullFileName(NameInfo1, Size, FileName))
{
- ExFreePool(NameInfo1);
+ ExFreePoolWithTag(NameInfo1, TAG_FINF);
return FALSE;
}
NameInfo2 = ExAllocatePoolWithTag(PagedPool, Size, TAG_FINF);
if (!NameInfo2)
{
- ExFreePool(NameInfo1);
+ ExFreePoolWithTag(NameInfo1, TAG_FINF);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
IntUnLockGlobalFonts;
/* Free the buffers */
- ExFreePool(NameInfo1);
+ ExFreePoolWithTag(NameInfo1, TAG_FINF);
ExFreePool(NameInfo2);
if (!bFound && dwType != 5)
if (! GetFontFamilyInfoForList(&LogFont, Info, &Count, Size, &FontListHead) )
{
IntUnLockGlobalFonts;
- ExFreePool(Info);
+ ExFreePoolWithTag(Info, GDITAG_TEXT);
return -1;
}
IntUnLockGlobalFonts;
&Win32Process->PrivateFontListHead))
{
IntUnLockProcessPrivateFonts(Win32Process);
- ExFreePool(Info);
+ ExFreePoolWithTag(Info, GDITAG_TEXT);
return -1;
}
IntUnLockProcessPrivateFonts(Win32Process);
/* Enumerate font families in the registry */
if (! GetFontFamilyInfoForSubstitutes(&LogFont, Info, &Count, Size))
{
- ExFreePool(Info);
+ ExFreePoolWithTag(Info, GDITAG_TEXT);
return -1;
}
(Count < Size ? Count : Size) * sizeof(FONTFAMILYINFO));
if (! NT_SUCCESS(Status))
{
- ExFreePool(Info);
+ ExFreePoolWithTag(Info, GDITAG_TEXT);
EngSetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
}
- ExFreePool(Info);
+ ExFreePoolWithTag(Info, GDITAG_TEXT);
return Count;
}
+FORCEINLINE
+LONG
+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(
LONGLONG TextLeft, RealXStart;
ULONG TextTop, previous, BackgroundLeft;
FT_Bool use_kerning;
- RECTL DestRect, MaskRect, DummyRect = {0, 0, 0, 0};
+ RECTL DestRect, MaskRect;
POINTL SourcePoint, BrushOrigin;
HBITMAP HSourceGlyph;
SURFOBJ *SourceGlyphSurf;
POINT Start;
BOOL DoBreak = FALSE;
USHORT DxShift;
+ PMATRIX pmxWorldToDevice;
+ LONG fixAscender, fixDescender;
+ FLOATOBJ Scale;
// TODO: Write test-cases to exactly match real Windows in different
// bad parameters (e.g. does Windows check the DC or the RECT first?).
DestRect.right += dc->ptlDCOrig.x;
DestRect.bottom += dc->ptlDCOrig.y;
- DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect);
+ DC_vPrepareDCsForBlit(dc, &DestRect, NULL, NULL);
if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
DC_vUpdateBackgroundBrush(dc);
&dc->dclevel.pSurface->SurfObj,
NULL,
NULL,
- dc->rosdc.CombinedClip,
+ &dc->co.ClipObj,
NULL,
&DestRect,
&SourcePoint,
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;
}
BackgroundLeft = (RealXStart + 32) >> 6;
/* Lock blit with a dummy rect */
- DC_vPrepareDCsForBlit(dc, DummyRect, NULL, DummyRect);
+ DC_vPrepareDCsForBlit(dc, NULL, NULL, NULL);
psurf = dc->dclevel.pSurface ;
if(!psurf) psurf = psurfDefaultBitmap;
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;
+ DC_vFinishBlit(dc, NULL);
goto fail2;
}
glyph = face->glyph;
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;
+ DC_vFinishBlit(dc, NULL);
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,
NULL,
NULL,
- dc->rosdc.CombinedClip,
+ &dc->co.ClipObj,
NULL,
&DestRect,
&SourcePoint,
DPRINT1("WARNING: EngLockSurface() failed!\n");
// FT_Done_Glyph(realglyph);
IntUnLockFreeType;
+ DC_vFinishBlit(dc, NULL);
goto fail2;
}
SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
EngDeleteSurface((HSURF)HSourceGlyph);
DPRINT1("WARNING: EngLockSurface() failed!\n");
IntUnLockFreeType;
+ DC_vFinishBlit(dc, NULL);
goto fail2;
}
IntEngMaskBlt(
SurfObj,
SourceGlyphSurf,
- dc->rosdc.CombinedClip,
+ &dc->co.ClipObj,
&exloRGB2Dst.xlo,
&exloDst2RGB.xlo,
&DestRect,
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);
+ // FIXME this should probably be a matrix transform with TextTop as well.
+ Scale = pdcattr->mxWorldToDevice.efM11;
+ if (_FLOATOBJ_Equal0(&Scale))
+ FLOATOBJ_Set1(&Scale);
+
+ FLOATOBJ_MulLong(&Scale, Dx[i<<DxShift] << 6); // do the shift before multiplying to preserve precision
+ TextLeft += FLOATOBJ_GetLong(&Scale);
+ DPRINT("New TextLeft2: %I64d\n", TextLeft);
}
if (DxShift)
UINT i, glyph_index, BufferSize;
HFONT hFont = 0;
NTSTATUS Status = STATUS_SUCCESS;
+ PMATRIX pmxWorldToDevice;
if (pwch)
{
dc = DC_LockDc(hDC);
if (dc == NULL)
{
- ExFreePool(SafeBuff);
+ ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
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)
{
- ExFreePool(SafeBuff);
+ ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (!found)
{
DPRINT1("WARNING: Could not find desired charmap!\n");
- ExFreePool(SafeBuff);
+ ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
/* 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++)
{
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
- ExFreePool(SafeBuff);
+ ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
return FALSE;
}
- ExFreePool(SafeBuff);
+ ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
DPRINT("NtGdiGetCharABCWidths Worked!\n");
return TRUE;
}
FT_CharMap charmap, found = NULL;
UINT i, glyph_index, BufferSize;
HFONT hFont = 0;
+ PMATRIX pmxWorldToDevice;
if (pwc)
{
dc = DC_LockDc(hDC);
if (dc == NULL)
{
- ExFreePool(SafeBuff);
+ ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
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)
{
- ExFreePool(SafeBuff);
+ ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
/* 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++)
{
IntUnLockFreeType;
TEXTOBJ_UnlockText(TextObj);
MmCopyToCaller(Buffer, SafeBuff, BufferSize);
- ExFreePool(SafeBuff);
+ ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
return TRUE;
}
}
IntGetOutlineTextMetrics(FontGDI, Size, potm);
DefChar = potm->otmTextMetrics.tmDefaultChar; // May need this.
- ExFreePool(potm);
+ ExFreePoolWithTag(potm, GDITAG_TEXT);
}
IntLockFreeType;
}
IntGetOutlineTextMetrics(FontGDI, Size, potm);
DefChar = potm->otmTextMetrics.tmDefaultChar; // May need this.
- ExFreePool(potm);
+ ExFreePoolWithTag(potm, GDITAG_TEXT);
}
_SEH2_TRY