[win32k]
[reactos.git] / reactos / subsystems / win32 / win32k / objects / freetype.c
index 63ea4ee..2315b90 100644 (file)
@@ -35,7 +35,7 @@
 
 /** Includes ******************************************************************/
 
-#include <w32k.h>
+#include <win32k.h>
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -44,6 +44,7 @@
 #include <freetype/tttables.h>
 #include <freetype/fttrigon.h>
 #include <freetype/ftglyph.h>
+#include <freetype/ftbitmap.h>
 #include <freetype/ftoutln.h>
 #include <freetype/ftwinfnt.h>
 
@@ -81,7 +82,7 @@ typedef struct _FONT_CACHE_ENTRY
     LIST_ENTRY ListEntry;
     int GlyphIndex;
     FT_Face Face;
-    FT_Glyph Glyph;
+    FT_BitmapGlyph BitmapGlyph;
     int Height;
 } FONT_CACHE_ENTRY, *PFONT_CACHE_ENTRY;
 static LIST_ENTRY FontCacheListHead;
@@ -218,17 +219,17 @@ IntLoadSystemFonts(VOID)
 
     if (NT_SUCCESS(Status))
     {
-        DirInfoBuffer = ExAllocatePool(PagedPool, 0x4000);
+        DirInfoBuffer = ExAllocatePoolWithTag(PagedPool, 0x4000, TAG_FONT);
         if (DirInfoBuffer == NULL)
         {
             ZwClose(hDirectory);
             return;
         }
 
-        FileName.Buffer = ExAllocatePool(PagedPool, MAX_PATH * sizeof(WCHAR));
+        FileName.Buffer = ExAllocatePoolWithTag(PagedPool, MAX_PATH * sizeof(WCHAR), TAG_FONT);
         if (FileName.Buffer == NULL)
         {
-            ExFreePool(DirInfoBuffer);
+            ExFreePoolWithTag(DirInfoBuffer, TAG_FONT);
             ZwClose(hDirectory);
             return;
         }
@@ -272,8 +273,8 @@ IntLoadSystemFonts(VOID)
             bRestartScan = FALSE;
         }
 
-        ExFreePool(FileName.Buffer);
-        ExFreePool(DirInfoBuffer);
+        ExFreePoolWithTag(FileName.Buffer, TAG_FONT);
+        ExFreePoolWithTag(DirInfoBuffer, TAG_FONT);
         ZwClose(hDirectory);
     }
 }
@@ -301,7 +302,6 @@ IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
     PSECTION_OBJECT SectionObject;
     ULONG ViewSize = 0;
     LARGE_INTEGER SectionSize;
-    FT_Fixed XScale, YScale;
     UNICODE_STRING FontRegPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts");
 
     /* Open the font file */
@@ -365,50 +365,34 @@ IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
     {
         FT_Done_Face(Face);
         ObDereferenceObject(SectionObject);
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return 0;
     }
 
-    FontGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(FONTGDI), TAG_FONTOBJ);
+    FontGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(FONTGDI), GDITAG_RFONT);
     if (FontGDI == NULL)
     {
         FT_Done_Face(Face);
         ObDereferenceObject(SectionObject);
         ExFreePoolWithTag(Entry, TAG_FONT);
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return 0;
     }
 
-    FontGDI->Filename = ExAllocatePoolWithTag(PagedPool, FileName->Length + sizeof(WCHAR), TAG_PFF);
+    FontGDI->Filename = ExAllocatePoolWithTag(PagedPool, FileName->Length + sizeof(WCHAR), GDITAG_PFF);
     if (FontGDI->Filename == NULL)
     {
         EngFreeMem(FontGDI);
         FT_Done_Face(Face);
         ObDereferenceObject(SectionObject);
         ExFreePoolWithTag(Entry, TAG_FONT);
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return 0;
     }
     RtlCopyMemory(FontGDI->Filename, FileName->Buffer, FileName->Length);
     FontGDI->Filename[FileName->Length / sizeof(WCHAR)] = L'\0';
     FontGDI->face = Face;
 
-    /* FIXME: Complete text metrics */
-    XScale = Face->size->metrics.x_scale;
-    YScale = Face->size->metrics.y_scale;
-#if 0 /* This (Wine) code doesn't seem to work correctly for us */
-    FontGDI->TextMetric.tmAscent =  (FT_MulFix(Face->ascender, YScale) + 32) >> 6;
-    FontGDI->TextMetric.tmDescent = (FT_MulFix(Face->descender, YScale) + 32) >> 6;
-    FontGDI->TextMetric.tmHeight =  (FT_MulFix(Face->ascender, YScale) -
-                                     FT_MulFix(Face->descender, YScale)) >> 6;
-#else
-    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 = (Face->size->metrics.ascender - Face->size->metrics.descender) >> 6;
-#endif
-
-
-
     DPRINT("Font loaded: %s (%s)\n", Face->family_name, Face->style_name);
     DPRINT("Num glyphs: %u\n", Face->num_glyphs);
 
@@ -421,7 +405,7 @@ IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
 
     if (Characteristics & FR_PRIVATE)
     {
-        PW32PROCESS Win32Process = PsGetCurrentProcessWin32Process();
+        PPROCESSINFO Win32Process = PsGetCurrentProcessWin32Process();
         IntLockProcessPrivateFonts(Win32Process);
         InsertTailList(&Win32Process->PrivateFontListHead, &Entry->ListEntry);
         IntUnLockProcessPrivateFonts(Win32Process);
@@ -566,6 +550,18 @@ IntTranslateCharsetInfo(PDWORD Src, /* [in]
 }
 
 
+static BOOL face_has_symbol_charmap(FT_Face ft_face)
+{
+    int i;
+
+    for(i = 0; i < ft_face->num_charmaps; i++)
+    {
+        if(ft_face->charmaps[i]->encoding == FT_ENCODING_MS_SYMBOL)
+            return TRUE;
+    }
+    return FALSE;
+}
+
 static void FASTCALL
 FillTM(TEXTMETRICW *TM, PFONTGDI FontGDI, TT_OS2 *pOS2, TT_HoriHeader *pHori, FT_WinFNT_HeaderRec *pWin)
 {
@@ -644,10 +640,36 @@ FillTM(TEXTMETRICW *TM, PFONTGDI FontGDI, TT_OS2 *pOS2, TT_HoriHeader *pHori, FT
     TM->tmOverhang = 0;
     TM->tmDigitizedAspectX = 96;
     TM->tmDigitizedAspectY = 96;
-    TM->tmFirstChar = pOS2->usFirstCharIndex;
-    TM->tmDefaultChar = pOS2->usDefaultChar ? pOS2->usDefaultChar : 0xffff;
-    TM->tmLastChar = pOS2->usLastCharIndex;
-    TM->tmBreakChar = L'\0' != pOS2->usBreakChar ? pOS2->usBreakChar : ' ';
+    if (face_has_symbol_charmap(Face) || (pOS2->usFirstCharIndex >= 0xf000 && pOS2->usFirstCharIndex < 0xf100))
+    {
+        USHORT cpOEM, cpAnsi;
+
+        EngGetCurrentCodePage(&cpOEM, &cpAnsi);
+        TM->tmFirstChar = 0;
+        switch(cpAnsi)
+        {
+        case 1257: /* Baltic */
+            TM->tmLastChar = 0xf8fd;
+            break;
+        default:
+            TM->tmLastChar = 0xf0ff;
+        }
+        TM->tmBreakChar = 0x20;
+        TM->tmDefaultChar = 0x1f;
+    }
+    else
+    {
+        TM->tmFirstChar = pOS2->usFirstCharIndex; /* Should be the first char in the cmap */
+        TM->tmLastChar = pOS2->usLastCharIndex;   /* Should be min(cmap_last, os2_last) */
+
+        if(pOS2->usFirstCharIndex <= 1)
+            TM->tmBreakChar = pOS2->usFirstCharIndex + 2;
+        else if (pOS2->usFirstCharIndex > 0xff)
+            TM->tmBreakChar = 0x20;
+        else
+            TM->tmBreakChar = pOS2->usFirstCharIndex;
+        TM->tmDefaultChar = TM->tmBreakChar - 1;
+    }
     TM->tmItalic = (Face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0;
     TM->tmUnderlined = FontGDI->Underline;
     TM->tmStruckOut  = FontGDI->StrikeOut;
@@ -815,14 +837,7 @@ IntGetOutlineTextMetrics(PFONTGDI FontGDI,
 
     Otm->otmSize = Needed;
 
-//  FillTM(&Otm->otmTextMetrics, FontGDI, pOS2, pHori, !Error ? &Win : 0);
-    if (!(FontGDI->flRealizedType & FDM_TYPE_TEXT_METRIC))
-    {
-        FillTM(&FontGDI->TextMetric, FontGDI, pOS2, pHori, !Error ? &Win : 0);
-        FontGDI->flRealizedType |= FDM_TYPE_TEXT_METRIC;
-    }
-
-    RtlCopyMemory(&Otm->otmTextMetrics, &FontGDI->TextMetric, sizeof(TEXTMETRICW));
+    FillTM(&Otm->otmTextMetrics, FontGDI, pOS2, pHori, !Error ? &Win : 0);
 
     Otm->otmFiller = 0;
     RtlCopyMemory(&Otm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
@@ -841,8 +856,8 @@ IntGetOutlineTextMetrics(PFONTGDI FontGDI,
     Otm->otmrcFontBox.right = (FT_MulFix(FontGDI->face->bbox.xMax, XScale) + 32) >> 6;
     Otm->otmrcFontBox.top = (FT_MulFix(FontGDI->face->bbox.yMax, YScale) + 32) >> 6;
     Otm->otmrcFontBox.bottom = (FT_MulFix(FontGDI->face->bbox.yMin, YScale) + 32) >> 6;
-    Otm->otmMacAscent = FontGDI->TextMetric.tmAscent;
-    Otm->otmMacDescent = -FontGDI->TextMetric.tmDescent;
+    Otm->otmMacAscent = Otm->otmTextMetrics.tmAscent;
+    Otm->otmMacDescent = -Otm->otmTextMetrics.tmDescent;
     Otm->otmMacLineGap = Otm->otmLineGap;
     Otm->otmusMinimumPPEM = 0; /* TT Header */
     Otm->otmptSubscriptSize.x = (FT_MulFix(pOS2->ySubscriptXSize, XScale) + 32) >> 6;
@@ -940,7 +955,7 @@ FindFaceNameInList(PUNICODE_STRING FaceName, PLIST_ENTRY Head)
 static PFONTGDI FASTCALL
 FindFaceNameInLists(PUNICODE_STRING FaceName)
 {
-    PW32PROCESS Win32Process;
+    PPROCESSINFO Win32Process;
     PFONTGDI Font;
 
     /* Search the process local list */
@@ -978,7 +993,7 @@ FontFamilyFillInfo(PFONTFAMILYINFO Info, PCWSTR FaceName, PFONTGDI FontGDI)
 
     RtlZeroMemory(Info, sizeof(FONTFAMILYINFO));
     Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
-    Otm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
+    Otm = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT);
     if (!Otm)
     {
         return;
@@ -1035,14 +1050,18 @@ FontFamilyFillInfo(PFONTFAMILYINFO Info, PCWSTR FaceName, PFONTGDI FontGDI)
     if (0 == (TM->tmPitchAndFamily & TMPF_VECTOR))
         Info->FontType |= RASTER_FONTTYPE;
 
-    ExFreePoolWithTag(Otm, TAG_GDITEXT);
+    ExFreePoolWithTag(Otm, GDITAG_TEXT);
 
-    wcsncpy(Info->EnumLogFontEx.elfLogFont.lfFaceName, FaceName, LF_FACESIZE);
-    wcsncpy(Info->EnumLogFontEx.elfFullName, FaceName, LF_FULLFACESIZE);
+    RtlStringCbCopyW(Info->EnumLogFontEx.elfLogFont.lfFaceName,
+                     sizeof(Info->EnumLogFontEx.elfLogFont.lfFaceName),
+                     FaceName);
+    RtlStringCbCopyW(Info->EnumLogFontEx.elfFullName,
+                     sizeof(Info->EnumLogFontEx.elfFullName),
+                     FaceName);
     RtlInitAnsiString(&StyleA, FontGDI->face->style_name);
-    RtlAnsiStringToUnicodeString(&StyleW, &StyleA, TRUE);
-    wcsncpy(Info->EnumLogFontEx.elfStyle, StyleW.Buffer, LF_FACESIZE);
-    RtlFreeUnicodeString(&StyleW);
+    StyleW.Buffer = Info->EnumLogFontEx.elfStyle;
+    StyleW.MaximumLength = sizeof(Info->EnumLogFontEx.elfStyle);
+    RtlAnsiStringToUnicodeString(&StyleW, &StyleA, FALSE);
 
     Info->EnumLogFontEx.elfLogFont.lfCharSet = DEFAULT_CHARSET;
     Info->EnumLogFontEx.elfScript[0] = L'\0';
@@ -1226,8 +1245,10 @@ FontFamilyInfoQueryRegistryCallback(IN PWSTR ValueName, IN ULONG ValueType,
             if (InfoContext->Count < InfoContext->Size)
             {
                 InfoContext->Info[InfoContext->Count] = InfoContext->Info[Existing];
-                wcsncpy(InfoContext->Info[InfoContext->Count].EnumLogFontEx.elfLogFont.lfFaceName,
-                        RegistryName.Buffer, LF_FACESIZE);
+                RtlStringCbCopyNW(InfoContext->Info[InfoContext->Count].EnumLogFontEx.elfLogFont.lfFaceName,
+                                  sizeof(InfoContext->Info[InfoContext->Count].EnumLogFontEx.elfLogFont.lfFaceName),
+                                  RegistryName.Buffer,
+                                  RegistryName.Length);
             }
             InfoContext->Count++;
             return STATUS_SUCCESS;
@@ -1306,12 +1327,12 @@ ftGdiGetRasterizerCaps(LPRASTERIZER_STATUS lprs)
         lprs->nLanguageID = gusLanguageID;
         return TRUE;
     }
-    SetLastWin32Error(ERROR_INVALID_PARAMETER);
+    EngSetLastError(ERROR_INVALID_PARAMETER);
     return FALSE;
 }
 
 
-FT_Glyph APIENTRY
+FT_BitmapGlyph APIENTRY
 ftGdiGlyphCacheGet(
     FT_Face Face,
     INT GlyphIndex,
@@ -1338,10 +1359,10 @@ ftGdiGlyphCacheGet(
 
     RemoveEntryList(CurrentEntry);
     InsertHeadList(&FontCacheListHead, CurrentEntry);
-    return FontEntry->Glyph;
+    return FontEntry->BitmapGlyph;
 }
 
-FT_Glyph APIENTRY
+FT_BitmapGlyph APIENTRY
 ftGdiGlyphCacheSet(
     FT_Face Face,
     INT GlyphIndex,
@@ -1352,6 +1373,8 @@ ftGdiGlyphCacheSet(
     FT_Glyph GlyphCopy;
     INT error;
     PFONT_CACHE_ENTRY NewEntry;
+    FT_Bitmap AlignedBitmap;
+    FT_BitmapGlyph BitmapGlyph;
 
     error = FT_Get_Glyph(GlyphSlot, &GlyphCopy);
     if (error)
@@ -1359,6 +1382,7 @@ ftGdiGlyphCacheSet(
         DPRINT1("Failure caching glyph.\n");
         return NULL;
     };
+
     error = FT_Glyph_To_Bitmap(&GlyphCopy, RenderMode, 0, 1);
     if (error)
     {
@@ -1374,22 +1398,34 @@ ftGdiGlyphCacheSet(
         return NULL;
     }
 
+    BitmapGlyph = (FT_BitmapGlyph)GlyphCopy;
+    FT_Bitmap_New(&AlignedBitmap);
+    if(FT_Bitmap_Convert(GlyphSlot->library, &BitmapGlyph->bitmap, &AlignedBitmap, 4))
+    {
+        DPRINT1("Conversion failed\n");
+        FT_Done_Glyph((FT_Glyph)BitmapGlyph);
+        return NULL;
+    }
+
+    FT_Bitmap_Done(GlyphSlot->library, &BitmapGlyph->bitmap);
+    BitmapGlyph->bitmap = AlignedBitmap;
+
     NewEntry->GlyphIndex = GlyphIndex;
     NewEntry->Face = Face;
-    NewEntry->Glyph = GlyphCopy;
+    NewEntry->BitmapGlyph = BitmapGlyph;
     NewEntry->Height = Height;
 
     InsertHeadList(&FontCacheListHead, &NewEntry->ListEntry);
     if (FontCacheNumEntries++ > MAX_FONT_CACHE)
     {
         NewEntry = (PFONT_CACHE_ENTRY)FontCacheListHead.Blink;
-        FT_Done_Glyph(NewEntry->Glyph);
+        FT_Done_Glyph((FT_Glyph)NewEntry->BitmapGlyph);
         RemoveTailList(&FontCacheListHead);
         ExFreePool(NewEntry);
         FontCacheNumEntries--;
     }
 
-    return GlyphCopy;
+    return BitmapGlyph;
 }
 
 
@@ -1482,7 +1518,7 @@ ftGdiGetGlyphOutline(
 
     if (!TextObj)
     {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         return GDI_ERROR;
     }
     FontGDI = ObjToGDI(TextObj->Font, FONT);
@@ -1492,10 +1528,10 @@ ftGdiGetGlyphOutline(
     orientation = FT_IS_SCALABLE(ft_face) ? TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation: 0;
 
     Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
-    potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
+    potm = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT);
     if (!potm)
     {
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         TEXTOBJ_UnlockText(TextObj);
         return GDI_ERROR;
     }
@@ -1533,8 +1569,8 @@ ftGdiGetGlyphOutline(
 //  FT_Set_Pixel_Sizes(ft_face,
 //                     TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth,
     /* FIXME should set character height if neg */
-//                     (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight :
-//                      TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight));
+//                     (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ?
+//                      dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));
 
     TEXTOBJ_UnlockText(TextObj);
 
@@ -1559,7 +1595,7 @@ ftGdiGetGlyphOutline(
     {
         DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
         IntUnLockFreeType;
-        if (potm) ExFreePoolWithTag(potm, TAG_GDITEXT);
+        if (potm) ExFreePoolWithTag(potm, GDITAG_TEXT);
         return GDI_ERROR;
     }
     IntUnLockFreeType;
@@ -1637,7 +1673,7 @@ ftGdiGetGlyphOutline(
         needsTransform = TRUE;
     }
 
-    if (potm) ExFreePoolWithTag(potm, TAG_GDITEXT); /* It looks like we are finished with potm ATM.*/
+    if (potm) ExFreePoolWithTag(potm, GDITAG_TEXT); /* It looks like we are finished with potm ATM.*/
 
     if (!needsTransform)
     {
@@ -2065,16 +2101,17 @@ FASTCALL
 TextIntGetTextExtentPoint(PDC dc,
                           PTEXTOBJ TextObj,
                           LPCWSTR String,
-                          int Count,
-                          int MaxExtent,
+                          INT Count,
+                          ULONG MaxExtent,
                           LPINT Fit,
                           LPINT Dx,
-                          LPSIZE Size)
+                          LPSIZE Size,
+                          FLONG fl)
 {
     PFONTGDI FontGDI;
     FT_Face face;
     FT_GlyphSlot glyph;
-    FT_Glyph realglyph;
+    FT_BitmapGlyph realglyph;
     INT error, n, glyph_index, i, previous;
     ULONGLONG TotalWidth = 0;
     FT_CharMap charmap, found = NULL;
@@ -2128,9 +2165,8 @@ TextIntGetTextExtentPoint(PDC dc,
     error = FT_Set_Pixel_Sizes(face,
                                TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth,
                                /* FIXME should set character height if neg */
-                               (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ?
-                                - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight :
-                                TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight));
+                               (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 
+                                                          dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));                                                       
     if (error)
     {
         DPRINT1("Error in setting pixel sizes: %u\n", error);
@@ -2141,7 +2177,11 @@ TextIntGetTextExtentPoint(PDC dc,
 
     for (i = 0; i < Count; i++)
     {
-        glyph_index = FT_Get_Char_Index(face, *String);
+        if (fl & GTEF_INDICES)
+            glyph_index = *String;
+        else
+            glyph_index = FT_Get_Char_Index(face, *String);
+
         if (!(realglyph = ftGdiGlyphCacheGet(face, glyph_index,
                                              TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)))
         {
@@ -2170,7 +2210,7 @@ TextIntGetTextExtentPoint(PDC dc,
             TotalWidth += delta.x;
         }
 
-        TotalWidth += realglyph->advance.x >> 10;
+        TotalWidth += realglyph->root.advance.x >> 10;
 
         if (((TotalWidth + 32) >> 6) <= MaxExtent && NULL != Fit)
         {
@@ -2187,8 +2227,9 @@ TextIntGetTextExtentPoint(PDC dc,
     IntUnLockFreeType;
 
     Size->cx = (TotalWidth + 32) >> 6;
-    Size->cy = (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight);
-    Size->cy = EngMulDiv(Size->cy, IntGdiGetDeviceCaps(dc, LOGPIXELSY), 72);
+    Size->cy = (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ?
+                   dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight));
+    Size->cy = EngMulDiv(Size->cy, dc->ppdev->gdiinfo.ulLogPixelsY, 72);
 
     return TRUE;
 }
@@ -2219,7 +2260,7 @@ ftGdiGetTextCharsetInfo(
 
     if (!TextObj)
     {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         return Ret;
     }
     FontGdi = ObjToGDI(TextObj->Font, FONT);
@@ -2391,13 +2432,13 @@ ftGdiGetTextMetricsW(
 
     if (!ptmwi)
     {
-        SetLastWin32Error(STATUS_INVALID_PARAMETER);
+        EngSetLastError(STATUS_INVALID_PARAMETER);
         return FALSE;
     }
 
     if (!(dc = DC_LockDc(hDC)))
     {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
     pdcattr = dc->pdcattr;
@@ -2411,9 +2452,8 @@ ftGdiGetTextMetricsW(
         Error = FT_Set_Pixel_Sizes(Face,
                                    TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth,
                                    /* FIXME should set character height if neg */
-                                   (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ?
-                                    - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight :
-                                    TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight));
+                                   (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ?
+                                   dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));
         IntUnLockFreeType;
         if (0 != Error)
         {
@@ -2445,13 +2485,8 @@ ftGdiGetTextMetricsW(
 
             if (NT_SUCCESS(Status))
             {
-                if (!(FontGDI->flRealizedType & FDM_TYPE_TEXT_METRIC))
-                {
-                    FillTM(&FontGDI->TextMetric, FontGDI, pOS2, pHori, !Error ? &Win : 0);
-                    FontGDI->flRealizedType |= FDM_TYPE_TEXT_METRIC;
-                }
+                FillTM(&ptmwi->TextMetric, FontGDI, pOS2, pHori, !Error ? &Win : 0);
 
-                RtlCopyMemory(&ptmwi->TextMetric, &FontGDI->TextMetric, sizeof(TEXTMETRICW));
                 /* FIXME: Fill Diff member */
                 RtlZeroMemory(&ptmwi->Diff, sizeof(ptmwi->Diff));
             }
@@ -2540,7 +2575,7 @@ GetFontScore(LOGFONTW *LogFont, PUNICODE_STRING FaceName, PFONTGDI FontGDI)
     }
 
     Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
-    Otm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
+    Otm = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT);
     if (NULL == Otm)
     {
         return Score;
@@ -2582,7 +2617,7 @@ FindBestFontFromList(FONTOBJ **FontObj, UINT *MatchScore, LOGFONTW *LogFont,
     PFONT_ENTRY CurrentEntry;
     FONTGDI *FontGDI;
     UINT Score;
-
+ASSERT(FontObj && MatchScore && LogFont && FaceName && Head);
     Entry = Head->Flink;
     while (Entry != Head)
     {
@@ -2690,7 +2725,7 @@ TextIntRealizeFont(HFONT FontHandle, PTEXTOBJ pTextObj)
     NTSTATUS Status = STATUS_SUCCESS;
     PTEXTOBJ TextObj;
     UNICODE_STRING FaceName;
-    PW32PROCESS Win32Process;
+    PPROCESSINFO Win32Process;
     UINT MatchScore;
 
     if (!pTextObj)
@@ -2747,7 +2782,6 @@ TextIntRealizeFont(HFONT FontHandle, PTEXTOBJ pTextObj)
         TextObj->Font->iUniq = 1; // Now it can be cached.
         IntFontType(FontGdi);
         FontGdi->flType = TextObj->Font->flFontType;
-        FontGdi->flRealizedType = 0;
         FontGdi->Underline = TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfUnderline ? 0xff : 0;
         FontGdi->StrikeOut = TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfStrikeOut ? 0xff : 0;
         TextObj->fl |= TEXTOBJECT_INIT;
@@ -2829,7 +2863,7 @@ IntGdiGetFontResourceInfo(
     NameInfo1 = ExAllocatePoolWithTag(PagedPool, Size, TAG_FINF);
     if (!NameInfo1)
     {
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return FALSE;
     }
 
@@ -2845,7 +2879,7 @@ IntGdiGetFontResourceInfo(
     if (!NameInfo2)
     {
         ExFreePool(NameInfo1);
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return FALSE;
     }
 
@@ -3003,21 +3037,21 @@ NtGdiGetFontFamilyInfo(HDC Dc,
     LOGFONTW LogFont;
     PFONTFAMILYINFO Info;
     DWORD Count;
-    PW32PROCESS Win32Process;
+    PPROCESSINFO Win32Process;
 
     /* Make a safe copy */
     Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW));
     if (! NT_SUCCESS(Status))
     {
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
         return -1;
     }
 
     /* Allocate space for a safe copy */
-    Info = ExAllocatePoolWithTag(PagedPool, Size * sizeof(FONTFAMILYINFO), TAG_GDITEXT);
+    Info = ExAllocatePoolWithTag(PagedPool, Size * sizeof(FONTFAMILYINFO), GDITAG_TEXT);
     if (NULL == Info)
     {
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return -1;
     }
 
@@ -3059,7 +3093,7 @@ NtGdiGetFontFamilyInfo(HDC Dc,
         if (! NT_SUCCESS(Status))
         {
             ExFreePool(Info);
-            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            EngSetLastError(ERROR_INVALID_PARAMETER);
             return -1;
         }
     }
@@ -3095,12 +3129,11 @@ GreExtTextOutW(
     int error, glyph_index, n, i;
     FT_Face face;
     FT_GlyphSlot glyph;
-    FT_Glyph realglyph;
-    FT_BitmapGlyph realglyph2;
+    FT_BitmapGlyph realglyph;
     LONGLONG TextLeft, RealXStart;
     ULONG TextTop, previous, BackgroundLeft;
     FT_Bool use_kerning;
-    RECTL DestRect, MaskRect;
+    RECTL DestRect, MaskRect, DummyRect = {0, 0, 0, 0};
     POINTL SourcePoint, BrushOrigin;
     HBITMAP HSourceGlyph;
     SURFOBJ *SourceGlyphSurf;
@@ -3110,12 +3143,11 @@ GreExtTextOutW(
     FONTOBJ *FontObj;
     PFONTGDI FontGDI;
     PTEXTOBJ TextObj = NULL;
-    XLATEOBJ *XlateObj=NULL, *XlateObj2=NULL;
+    EXLATEOBJ exloRGB2Dst, exloDst2RGB;
     FT_Render_Mode RenderMode;
     BOOLEAN Render;
     POINT Start;
     BOOL DoBreak = FALSE;
-    HPALETTE hDestPalette;
     USHORT DxShift;
 
     // TODO: Write test-cases to exactly match real Windows in different
@@ -3123,7 +3155,7 @@ GreExtTextOutW(
     dc = DC_LockDc(hDC);
     if (!dc)
     {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
     if (dc->dctype == DC_TYPE_INFO)
@@ -3135,9 +3167,6 @@ GreExtTextOutW(
 
     pdcattr = dc->pdcattr;
 
-    if (pdcattr->ulDirty_ & DIRTY_TEXT)
-        DC_vUpdateTextBrush(dc);
-
     if ((fuOptions & ETO_OPAQUE) || pdcattr->jBkMode == OPAQUE)
     {
         if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
@@ -3147,7 +3176,7 @@ GreExtTextOutW(
     /* Check if String is valid */
     if ((Count > 0xFFFF) || (Count > 0 && String == NULL))
     {
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
         goto fail;
     }
 
@@ -3171,13 +3200,6 @@ GreExtTextOutW(
         IntLPtoDP(dc, (POINT *)lprc, 2);
     }
 
-    psurf = dc->dclevel.pSurface;
-    if (!psurf)
-    {
-        goto fail;
-    }
-    SurfObj = &psurf->SurfObj;
-
     Start.x = XStart;
     Start.y = YStart;
     IntLPtoDP(dc, &Start, 1);
@@ -3185,20 +3207,6 @@ GreExtTextOutW(
     RealXStart = (Start.x + dc->ptlDCOrig.x) << 6;
     YStart = Start.y + dc->ptlDCOrig.y;
 
-    /* Create the brushes */
-    hDestPalette = psurf->hDIBPalette;
-    if (!hDestPalette) hDestPalette = pPrimarySurface->DevInfo.hpalDefault;
-    XlateObj = (XLATEOBJ*)IntEngCreateXlate(0, PAL_RGB, hDestPalette, NULL);
-    if ( !XlateObj )
-    {
-        goto fail;
-    }
-    XlateObj2 = (XLATEOBJ*)IntEngCreateXlate(PAL_RGB, 0, NULL, hDestPalette);
-    if ( !XlateObj2 )
-    {
-        goto fail;
-    }
-
     SourcePoint.x = 0;
     SourcePoint.y = 0;
     MaskRect.left = 0;
@@ -3213,15 +3221,18 @@ GreExtTextOutW(
         DestRect.right  = lprc->right;
         DestRect.bottom = lprc->bottom;
 
-        IntLPtoDP(dc, (LPPOINT)&DestRect, 2);
-
         DestRect.left   += dc->ptlDCOrig.x;
         DestRect.top    += dc->ptlDCOrig.y;
         DestRect.right  += dc->ptlDCOrig.x;
         DestRect.bottom += dc->ptlDCOrig.y;
 
+        DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect);
+
+        if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
+            DC_vUpdateBackgroundBrush(dc);
+
         IntEngBitBlt(
-            &psurf->SurfObj,
+            &dc->dclevel.pSurface->SurfObj,
             NULL,
             NULL,
             dc->rosdc.CombinedClip,
@@ -3231,8 +3242,9 @@ GreExtTextOutW(
             &SourcePoint,
             &dc->eboBackground.BrushObject,
             &BrushOrigin,
-            ROP3_TO_ROP4(PATCOPY));
+            ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY));
         fuOptions &= ~ETO_OPAQUE;
+        DC_vFinishBlit(dc, NULL);
     }
     else
     {
@@ -3291,9 +3303,8 @@ GreExtTextOutW(
                 face,
                 TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth,
                 /* FIXME should set character height if neg */
-                (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ?
-                 - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight :
-                 TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight));
+                (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ?
+                dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));
     if (error)
     {
         DPRINT1("Error in setting pixel sizes: %u\n", error);
@@ -3375,7 +3386,7 @@ GreExtTextOutW(
                 TextWidth += delta.x;
             }
 
-            TextWidth += realglyph->advance.x >> 10;
+            TextWidth += realglyph->root.advance.x >> 10;
 
             previous = glyph_index;
             TempText++;
@@ -3397,10 +3408,24 @@ GreExtTextOutW(
     TextTop = YStart;
     BackgroundLeft = (RealXStart + 32) >> 6;
 
+    /* Lock blit with a dummy rect */
+    DC_vPrepareDCsForBlit(dc, DummyRect, NULL, DummyRect);
+
+    psurf = dc->dclevel.pSurface ;
+    SurfObj = &psurf->SurfObj ;
+
+    EXLATEOBJ_vInitialize(&exloRGB2Dst, &gpalRGB, psurf->ppal, 0, 0, 0);
+    EXLATEOBJ_vInitialize(&exloDst2RGB, psurf->ppal, &gpalRGB, 0, 0, 0);
+
+       if ((fuOptions & ETO_OPAQUE) && (dc->pdcattr->ulDirty_ & DIRTY_BACKGROUND))
+        DC_vUpdateBackgroundBrush(dc) ;
+
+    if(dc->pdcattr->ulDirty_ & DIRTY_TEXT)
+        DC_vUpdateTextBrush(dc) ;
+
     /*
      * The main rendering loop.
      */
-
     for (i = 0; i < Count; i++)
     {
         if (fuOptions & ETO_GLYPH_INDEX)
@@ -3416,7 +3441,7 @@ GreExtTextOutW(
             {
                 DPRINT1("Failed to load and render glyph! [index: %u]\n", glyph_index);
                 IntUnLockFreeType;
-                goto fail;
+                goto fail2;
             }
             glyph = face->glyph;
             realglyph = ftGdiGlyphCacheSet(face,
@@ -3428,7 +3453,7 @@ GreExtTextOutW(
             {
                 DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index);
                 IntUnLockFreeType;
-                goto fail;
+                goto fail2;
             }
         }
 
@@ -3441,28 +3466,15 @@ GreExtTextOutW(
         }
         DPRINT("TextLeft: %d\n", TextLeft);
         DPRINT("TextTop: %d\n", TextTop);
-
-        if (realglyph->format == ft_glyph_format_outline)
-        {
-            DPRINT1("Should already be done\n");
-//         error = FT_Render_Glyph(glyph, RenderMode);
-            error = FT_Glyph_To_Bitmap(&realglyph, RenderMode, 0, 0);
-            if (error)
-            {
-                DPRINT1("WARNING: Failed to render glyph!\n");
-                goto fail;
-            }
-        }
-        realglyph2 = (FT_BitmapGlyph)realglyph;
-
-        DPRINT("Advance: %d\n", realglyph->advance.x);
+        DPRINT("Advance: %d\n", realglyph->root.advance.x);
 
         if (fuOptions & ETO_OPAQUE)
         {
             DestRect.left = BackgroundLeft;
-            DestRect.right = (TextLeft + (realglyph->advance.x >> 10) + 32) >> 6;
+            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);
+            MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
             IntEngBitBlt(
                 &psurf->SurfObj,
                 NULL,
@@ -3474,41 +3486,37 @@ GreExtTextOutW(
                 &SourcePoint,
                 &dc->eboBackground.BrushObject,
                 &BrushOrigin,
-                ROP3_TO_ROP4(PATCOPY));
+                ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY));
+            MouseSafetyOnDrawEnd(dc->ppdev);
             BackgroundLeft = DestRect.right;
+
         }
 
-        DestRect.left = ((TextLeft + 32) >> 6) + realglyph2->left;
-        DestRect.right = DestRect.left + realglyph2->bitmap.width;
-        DestRect.top = TextTop + yoff - realglyph2->top;
-        DestRect.bottom = DestRect.top + realglyph2->bitmap.rows;
+        DestRect.left = ((TextLeft + 32) >> 6) + realglyph->left;
+        DestRect.right = DestRect.left + realglyph->bitmap.width;
+        DestRect.top = TextTop + yoff - realglyph->top;
+        DestRect.bottom = DestRect.top + realglyph->bitmap.rows;
 
-        bitSize.cx = realglyph2->bitmap.width;
-        bitSize.cy = realglyph2->bitmap.rows;
-        MaskRect.right = realglyph2->bitmap.width;
-        MaskRect.bottom = realglyph2->bitmap.rows;
+        bitSize.cx = realglyph->bitmap.width;
+        bitSize.cy = realglyph->bitmap.rows;
+        MaskRect.right = realglyph->bitmap.width;
+        MaskRect.bottom = realglyph->bitmap.rows;
 
         /*
          * We should create the bitmap out of the loop at the biggest possible
          * glyph size. Then use memset with 0 to clear it and sourcerect to
          * limit the work of the transbitblt.
-         *
-         * FIXME: DIB bitmaps should have an lDelta which is a multiple of 4.
-         * Here we pass in the pitch from the FreeType bitmap, which is not
-         * guaranteed to be a multiple of 4. If it's not, we should expand
-         * the FreeType bitmap to a temporary bitmap.
          */
 
-        HSourceGlyph = EngCreateBitmap(bitSize, realglyph2->bitmap.pitch,
-                                       (realglyph2->bitmap.pixel_mode == ft_pixel_mode_grays) ?
-                                       BMF_8BPP : BMF_1BPP, BMF_TOPDOWN,
-                                       realglyph2->bitmap.buffer);
+        HSourceGlyph = EngCreateBitmap(bitSize, realglyph->bitmap.pitch,
+                                       BMF_8BPP, BMF_TOPDOWN,
+                                       realglyph->bitmap.buffer);
         if ( !HSourceGlyph )
         {
             DPRINT1("WARNING: EngLockSurface() failed!\n");
             // FT_Done_Glyph(realglyph);
             IntUnLockFreeType;
-            goto fail;
+            goto fail2;
         }
         SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
         if ( !SourceGlyphSurf )
@@ -3516,7 +3524,7 @@ GreExtTextOutW(
             EngDeleteSurface((HSURF)HSourceGlyph);
             DPRINT1("WARNING: EngLockSurface() failed!\n");
             IntUnLockFreeType;
-            goto fail;
+            goto fail2;
         }
 
         /*
@@ -3534,17 +3542,18 @@ GreExtTextOutW(
             DestRect.right = lprc->right + dc->ptlDCOrig.x;
             DoBreak = TRUE;
         }
-
+        MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
         IntEngMaskBlt(
             SurfObj,
             SourceGlyphSurf,
             dc->rosdc.CombinedClip,
-            XlateObj,
-            XlateObj2,
+            &exloRGB2Dst.xlo,
+            &exloDst2RGB.xlo,
             &DestRect,
             (PPOINTL)&MaskRect,
             &dc->eboText.BrushObject,
             &BrushOrigin);
+        MouseSafetyOnDrawEnd(dc->ppdev) ;
 
         EngUnlockSurface(SourceGlyphSurf);
         EngDeleteSurface((HSURF)HSourceGlyph);
@@ -3556,7 +3565,7 @@ GreExtTextOutW(
 
         if (NULL == Dx)
         {
-            TextLeft += realglyph->advance.x >> 10;
+            TextLeft += realglyph->root.advance.x >> 10;
              DPRINT("new TextLeft: %d\n", TextLeft);
         }
         else
@@ -3574,11 +3583,11 @@ GreExtTextOutW(
 
         String++;
     }
-
     IntUnLockFreeType;
 
-    EngDeleteXlate(XlateObj);
-    EngDeleteXlate(XlateObj2);
+    DC_vFinishBlit(dc, NULL) ;
+    EXLATEOBJ_vCleanup(&exloRGB2Dst);
+    EXLATEOBJ_vCleanup(&exloDst2RGB);
     if (TextObj != NULL)
         TEXTOBJ_UnlockText(TextObj);
 good:
@@ -3586,13 +3595,13 @@ good:
 
     return TRUE;
 
+fail2:
+    EXLATEOBJ_vCleanup(&exloRGB2Dst);
+    EXLATEOBJ_vCleanup(&exloDst2RGB);
 fail:
-    if ( XlateObj2 != NULL )
-        EngDeleteXlate(XlateObj2);
-    if ( XlateObj != NULL )
-        EngDeleteXlate(XlateObj);
     if (TextObj != NULL)
         TEXTOBJ_UnlockText(TextObj);
+
     DC_UnlockDc(dc);
 
     return FALSE;
@@ -3624,7 +3633,7 @@ NtGdiExtTextOutW(
     /* Check if String is valid */
     if ((Count > 0xFFFF) || (Count > 0 && UnsafeString == NULL))
     {
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
@@ -3643,7 +3652,7 @@ NtGdiExtTextOutW(
         if (BufSize > STACK_TEXT_BUFFER_SIZE)
         {
             /* It's not, allocate a temp buffer */
-            Buffer = ExAllocatePoolWithTag(PagedPool, BufSize, TAG_GDITEXT);
+            Buffer = ExAllocatePoolWithTag(PagedPool, BufSize, GDITAG_TEXT);
             if (!Buffer)
             {
                 return FALSE;
@@ -3714,7 +3723,7 @@ cleanup:
     /* If we allocated a buffer, free it */
     if (Buffer != LocalBuffer)
     {
-        ExFreePoolWithTag(Buffer, TAG_GDITEXT);
+        ExFreePoolWithTag(Buffer, GDITAG_TEXT);
     }
 
     return Result;
@@ -3762,16 +3771,22 @@ NtGdiGetCharABCWidthsW(
     }
     if (!NT_SUCCESS(Status))
     {
-        SetLastWin32Error(Status);
+        EngSetLastError(Status);
+        return FALSE;
+    }
+
+    if (!Buffer)
+    {
+        EngSetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
     BufferSize = Count * sizeof(ABC); // Same size!
-    SafeBuff = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT);
+    SafeBuff = ExAllocatePoolWithTag(PagedPool, BufferSize, GDITAG_TEXT);
     if (!fl) SafeBuffF = (LPABCFLOAT) SafeBuff;
     if (SafeBuff == NULL)
     {
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return FALSE;
     }
 
@@ -3779,7 +3794,7 @@ NtGdiGetCharABCWidthsW(
     if (dc == NULL)
     {
         ExFreePool(SafeBuff);
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
     pdcattr = dc->pdcattr;
@@ -3790,7 +3805,7 @@ NtGdiGetCharABCWidthsW(
     if (TextObj == NULL)
     {
         ExFreePool(SafeBuff);
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
 
@@ -3813,7 +3828,7 @@ NtGdiGetCharABCWidthsW(
         {
             DPRINT1("WARNING: Could not find desired charmap!\n");
             ExFreePool(SafeBuff);
-            SetLastWin32Error(ERROR_INVALID_HANDLE);
+            EngSetLastError(ERROR_INVALID_HANDLE);
             return FALSE;
         }
 
@@ -3826,8 +3841,8 @@ NtGdiGetCharABCWidthsW(
     FT_Set_Pixel_Sizes(face,
                        TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth,
                        /* FIXME should set character height if neg */
-                       (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight :
-                        TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight));
+                       (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ?
+                       dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));
 
     for (i = FirstChar; i < FirstChar+Count; i++)
     {
@@ -3929,16 +3944,16 @@ NtGdiGetCharWidthW(
     }
     if (!NT_SUCCESS(Status))
     {
-        SetLastWin32Error(Status);
+        EngSetLastError(Status);
         return FALSE;
     }
 
     BufferSize = Count * sizeof(INT); // Same size!
-    SafeBuff = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT);
+    SafeBuff = ExAllocatePoolWithTag(PagedPool, BufferSize, GDITAG_TEXT);
     if (!fl) SafeBuffF = (PFLOAT) SafeBuff;
     if (SafeBuff == NULL)
     {
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return FALSE;
     }
 
@@ -3946,7 +3961,7 @@ NtGdiGetCharWidthW(
     if (dc == NULL)
     {
         ExFreePool(SafeBuff);
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
     pdcattr = dc->pdcattr;
@@ -3957,7 +3972,7 @@ NtGdiGetCharWidthW(
     if (TextObj == NULL)
     {
         ExFreePool(SafeBuff);
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
 
@@ -3980,7 +3995,7 @@ NtGdiGetCharWidthW(
         {
             DPRINT1("WARNING: Could not find desired charmap!\n");
             ExFreePool(SafeBuff);
-            SetLastWin32Error(ERROR_INVALID_HANDLE);
+            EngSetLastError(ERROR_INVALID_HANDLE);
             return FALSE;
         }
 
@@ -3993,9 +4008,8 @@ NtGdiGetCharWidthW(
     FT_Set_Pixel_Sizes(face,
                        TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth,
                        /* FIXME should set character height if neg */
-                       (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ?
-                        - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight :
-                        TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight));
+                       (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ?
+                       dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));
 
     for (i = FirstChar; i < FirstChar+Count; i++)
     {
@@ -4026,6 +4040,98 @@ NtGdiGetCharWidthW(
     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.
+        ExFreePool(potm);
+    }
+
+    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
@@ -4057,7 +4163,7 @@ NtGdiGetGlyphIndicesW(
     dc = DC_LockDc(hdc);
     if (!dc)
     {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         return GDI_ERROR;
     }
     pdcattr = dc->pdcattr;
@@ -4066,17 +4172,17 @@ NtGdiGetGlyphIndicesW(
     DC_UnlockDc(dc);
     if (!TextObj)
     {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         return GDI_ERROR;
     }
 
     FontGDI = ObjToGDI(TextObj->Font, FONT);
     TEXTOBJ_UnlockText(TextObj);
 
-    Buffer = ExAllocatePoolWithTag(PagedPool, cwc*sizeof(WORD), TAG_GDITEXT);
+    Buffer = ExAllocatePoolWithTag(PagedPool, cwc*sizeof(WORD), GDITAG_TEXT);
     if (!Buffer)
     {
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return GDI_ERROR;
     }
 
@@ -4084,7 +4190,7 @@ NtGdiGetGlyphIndicesW(
     else
     {
         Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
-        potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
+        potm = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT);
         if (!potm)
         {
             Status = ERROR_NOT_ENOUGH_MEMORY;
@@ -4112,16 +4218,17 @@ NtGdiGetGlyphIndicesW(
     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, UnSafepwc[i]);
+        Buffer[i] = FT_Get_Char_Index(face, UnSafepwc[i]); // FIXME: unsafe!
         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;
         }
     }
@@ -4144,9 +4251,9 @@ NtGdiGetGlyphIndicesW(
     _SEH2_END;
 
 ErrorRet:
-    ExFreePoolWithTag(Buffer, TAG_GDITEXT);
+    ExFreePoolWithTag(Buffer, GDITAG_TEXT);
     if (NT_SUCCESS(Status)) return cwc;
-    SetLastWin32Error(Status);
+    EngSetLastError(Status);
     return GDI_ERROR;
 }