[WIN32K]
[reactos.git] / reactos / subsystems / win32 / win32k / objects / freetype.c
index 061c8b2..98d62eb 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>
 
@@ -75,15 +76,13 @@ static FAST_MUTEX FontListLock;
 static BOOL RenderingEnabled = TRUE;
 
 #define MAX_FONT_CACHE 256
-UINT Hits;
-UINT Misses;
 
 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;
@@ -220,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;
         }
@@ -274,8 +273,8 @@ IntLoadSystemFonts(VOID)
             bRestartScan = FALSE;
         }
 
-        ExFreePool(FileName.Buffer);
-        ExFreePool(DirInfoBuffer);
+        ExFreePoolWithTag(FileName.Buffer, TAG_FONT);
+        ExFreePoolWithTag(DirInfoBuffer, TAG_FONT);
         ZwClose(hDirectory);
     }
 }
@@ -423,7 +422,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);
@@ -568,6 +567,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)
 {
@@ -603,7 +614,7 @@ FillTM(TEXTMETRICW *TM, PFONTGDI FontGDI, TT_OS2 *pOS2, TT_HoriHeader *pHori, FT
         return;
     }
 
-    if (0  == pOS2->usWinAscent + pOS2->usWinDescent)
+    if (pOS2->usWinAscent + pOS2->usWinDescent == 0)
     {
         Ascent = pHori->Ascender;
         Descent = -pHori->Descender;
@@ -621,9 +632,9 @@ FillTM(TEXTMETRICW *TM, PFONTGDI FontGDI, TT_OS2 *pOS2, TT_HoriHeader *pHori, FT
     TM->tmAscent = (Face->size->metrics.ascender + 32) >> 6; /* units above baseline */
     TM->tmDescent = (32 - Face->size->metrics.descender) >> 6; /* units below baseline */
 #endif
-
     TM->tmInternalLeading = (FT_MulFix(Ascent + Descent - Face->units_per_EM, YScale) + 32) >> 6;
-    TM->tmHeight = TM->tmAscent + TM->tmDescent; // we need add 1 height more after scale it right
+
+    TM->tmHeight = TM->tmAscent + TM->tmDescent;
 
     /* MSDN says:
      *  el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
@@ -634,7 +645,7 @@ FillTM(TEXTMETRICW *TM, PFONTGDI FontGDI, TT_OS2 *pOS2, TT_HoriHeader *pHori, FT
                                     YScale) + 32) >> 6);
 
     TM->tmAveCharWidth = (FT_MulFix(pOS2->xAvgCharWidth, XScale) + 32) >> 6;
-    if (0 == TM->tmAveCharWidth)
+    if (TM->tmAveCharWidth == 0)
     {
         TM->tmAveCharWidth = 1;
     }
@@ -646,10 +657,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->tmLastChar = pOS2->usLastCharIndex;
-    TM->tmDefaultChar = pOS2->usDefaultChar;
-    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;
@@ -670,11 +707,15 @@ FillTM(TEXTMETRICW *TM, PFONTGDI FontGDI, TT_OS2 *pOS2, TT_HoriHeader *pHori, FT
         TM->tmPitchAndFamily |= FF_SCRIPT;
         break;
     case PAN_FAMILY_DECORATIVE:
-    case PAN_FAMILY_PICTORIAL:
         TM->tmPitchAndFamily |= FF_DECORATIVE;
         break;
+
+    case PAN_ANY:
+    case PAN_NO_FIT:
     case PAN_FAMILY_TEXT_DISPLAY:
-        if (0 == TM->tmPitchAndFamily) /* fixed */
+    case PAN_FAMILY_PICTORIAL: /* symbol fonts get treated as if they were text */
+                               /* which is clearly not what the panose spec says. */
+        if (TM->tmPitchAndFamily == 0) /* fixed */
         {
             TM->tmPitchAndFamily = FF_MODERN;
         }
@@ -682,14 +723,31 @@ FillTM(TEXTMETRICW *TM, PFONTGDI FontGDI, TT_OS2 *pOS2, TT_HoriHeader *pHori, FT
         {
             switch (pOS2->panose[PAN_SERIFSTYLE_INDEX])
             {
+            case PAN_ANY:
+            case PAN_NO_FIT:
+            default:
+                TM->tmPitchAndFamily |= FF_DONTCARE;
+                break;
+
+            case PAN_SERIF_COVE:
+            case PAN_SERIF_OBTUSE_COVE:
+            case PAN_SERIF_SQUARE_COVE:
+            case PAN_SERIF_OBTUSE_SQUARE_COVE:
+            case PAN_SERIF_SQUARE:
+            case PAN_SERIF_THIN:
+            case PAN_SERIF_BONE:
+            case PAN_SERIF_EXAGGERATED:
+            case PAN_SERIF_TRIANGLE:
+                TM->tmPitchAndFamily |= FF_ROMAN;
+                break;
+
             case PAN_SERIF_NORMAL_SANS:
             case PAN_SERIF_OBTUSE_SANS:
             case PAN_SERIF_PERP_SANS:
+            case PAN_SERIF_FLARED:
+            case PAN_SERIF_ROUNDED:
                 TM->tmPitchAndFamily |= FF_SWISS;
                 break;
-            default:
-                TM->tmPitchAndFamily |= FF_ROMAN;
-                break;
             }
         }
         break;
@@ -822,9 +880,9 @@ 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 = 0; /* where do these come from ? */
-    Otm->otmMacDescent = 0;
-    Otm->otmMacLineGap = 0;
+    Otm->otmMacAscent = FontGDI->TextMetric.tmAscent;
+    Otm->otmMacDescent = -FontGDI->TextMetric.tmDescent;
+    Otm->otmMacLineGap = Otm->otmLineGap;
     Otm->otmusMinimumPPEM = 0; /* TT Header */
     Otm->otmptSubscriptSize.x = (FT_MulFix(pOS2->ySubscriptXSize, XScale) + 32) >> 6;
     Otm->otmptSubscriptSize.y = (FT_MulFix(pOS2->ySubscriptYSize, YScale) + 32) >> 6;
@@ -836,7 +894,7 @@ IntGetOutlineTextMetrics(PFONTGDI FontGDI,
     Otm->otmptSuperscriptOffset.y = (FT_MulFix(pOS2->ySuperscriptYOffset, YScale) + 32) >> 6;
     Otm->otmsStrikeoutSize = (FT_MulFix(pOS2->yStrikeoutSize, YScale) + 32) >> 6;
     Otm->otmsStrikeoutPosition = (FT_MulFix(pOS2->yStrikeoutPosition, YScale) + 32) >> 6;
-    if (NULL == pPost)
+    if (!pPost)
     {
         Otm->otmsUnderscoreSize = 0;
         Otm->otmsUnderscorePosition = 0;
@@ -921,7 +979,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 */
@@ -1292,7 +1350,7 @@ ftGdiGetRasterizerCaps(LPRASTERIZER_STATUS lprs)
 }
 
 
-FT_Glyph APIENTRY
+FT_BitmapGlyph APIENTRY
 ftGdiGlyphCacheGet(
     FT_Face Face,
     INT GlyphIndex,
@@ -1301,8 +1359,6 @@ ftGdiGlyphCacheGet(
     PLIST_ENTRY CurrentEntry;
     PFONT_CACHE_ENTRY FontEntry;
 
-//   DbgPrint("CacheGet\n");
-
     CurrentEntry = FontCacheListHead.Flink;
     while (CurrentEntry != &FontCacheListHead)
     {
@@ -1316,33 +1372,15 @@ ftGdiGlyphCacheGet(
 
     if (CurrentEntry == &FontCacheListHead)
     {
-//      DbgPrint("Miss! %x\n", FontEntry->Glyph);
-        /*
-              Misses++;
-              if (Misses>100) {
-                 DbgPrint ("Hits: %d Misses: %d\n", Hits, Misses);
-                 Hits = Misses = 0;
-              }
-        */
         return NULL;
     }
 
     RemoveEntryList(CurrentEntry);
     InsertHeadList(&FontCacheListHead, CurrentEntry);
-
-//   DbgPrint("Hit! %x\n", FontEntry->Glyph);
-    /*
-       Hits++;
-
-          if (Hits>100) {
-             DbgPrint ("Hits: %d Misses: %d\n", Hits, Misses);
-             Hits = Misses = 0;
-          }
-    */
-    return FontEntry->Glyph;
+    return FontEntry->BitmapGlyph;
 }
 
-FT_Glyph APIENTRY
+FT_BitmapGlyph APIENTRY
 ftGdiGlyphCacheSet(
     FT_Face Face,
     INT GlyphIndex,
@@ -1353,48 +1391,59 @@ ftGdiGlyphCacheSet(
     FT_Glyph GlyphCopy;
     INT error;
     PFONT_CACHE_ENTRY NewEntry;
-
-//   DbgPrint("CacheSet.\n");
+    FT_Bitmap AlignedBitmap;
+    FT_BitmapGlyph BitmapGlyph;
 
     error = FT_Get_Glyph(GlyphSlot, &GlyphCopy);
     if (error)
     {
-        DbgPrint("Failure caching glyph.\n");
+        DPRINT1("Failure caching glyph.\n");
         return NULL;
     };
+
     error = FT_Glyph_To_Bitmap(&GlyphCopy, RenderMode, 0, 1);
     if (error)
     {
-        DbgPrint("Failure rendering glyph.\n");
+        DPRINT1("Failure rendering glyph.\n");
         return NULL;
     };
 
     NewEntry = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_CACHE_ENTRY), TAG_FONT);
     if (!NewEntry)
     {
-        DbgPrint("Alloc failure caching glyph.\n");
+        DPRINT1("Alloc failure caching glyph.\n");
         FT_Done_Glyph(GlyphCopy);
         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--;
     }
 
-//   DbgPrint("Returning the glyphcopy: %x\n", GlyphCopy);
-
-    return GlyphCopy;
+    return BitmapGlyph;
 }
 
 
@@ -1449,7 +1498,7 @@ ftGdiGetGlyphOutline(
     BOOL bIgnoreRotation)
 {
     static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
-    PDC_ATTR Dc_Attr;
+    PDC_ATTR pdcattr;
     PTEXTOBJ TextObj;
     PFONTGDI FontGDI;
     HFONT hFont = 0;
@@ -1477,13 +1526,12 @@ ftGdiGetGlyphOutline(
     DPRINT("%d, %08x, %p, %08lx, %p, %p\n", wch, iFormat, pgm,
            cjBuf, pvBuf, pmat2);
 
-    Dc_Attr = dc->pDc_Attr;
-    if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+    pdcattr = dc->pdcattr;
 
-    MatrixS2XForm(&xForm, &dc->DcLevel.mxWorldToDevice);
+    MatrixS2XForm(&xForm, &dc->dclevel.mxWorldToDevice);
     eM11 = xForm.eM11;
 
-    hFont = Dc_Attr->hlfntNew;
+    hFont = pdcattr->hlfntNew;
     TextObj = RealizeFontInit(hFont);
 
     if (!TextObj)
@@ -2080,7 +2128,7 @@ TextIntGetTextExtentPoint(PDC dc,
     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;
@@ -2176,7 +2224,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)
         {
@@ -2207,7 +2255,7 @@ ftGdiGetTextCharsetInfo(
     LPFONTSIGNATURE lpSig,
     DWORD dwFlags)
 {
-    PDC_ATTR Dc_Attr;
+    PDC_ATTR pdcattr;
     UINT Ret = DEFAULT_CHARSET, i;
     HFONT hFont;
     PTEXTOBJ TextObj;
@@ -2219,9 +2267,8 @@ ftGdiGetTextCharsetInfo(
     DWORD cp, fs0;
     USHORT usACP, usOEM;
 
-    Dc_Attr = Dc->pDc_Attr;
-    if (!Dc_Attr) Dc_Attr = &Dc->Dc_Attr;
-    hFont = Dc_Attr->hlfntNew;
+    pdcattr = Dc->pdcattr;
+    hFont = pdcattr->hlfntNew;
     TextObj = RealizeFontInit(hFont);
 
     if (!TextObj)
@@ -2386,7 +2433,7 @@ ftGdiGetTextMetricsW(
     PTMW_INTERNAL ptmwi)
 {
     PDC dc;
-    PDC_ATTR Dc_Attr;
+    PDC_ATTR pdcattr;
     PTEXTOBJ TextObj;
     PFONTGDI FontGDI;
     FT_Face Face;
@@ -2407,9 +2454,8 @@ ftGdiGetTextMetricsW(
         SetLastWin32Error(ERROR_INVALID_HANDLE);
         return FALSE;
     }
-    Dc_Attr = dc->pDc_Attr;
-    if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
-    TextObj = RealizeFontInit(Dc_Attr->hlfntNew);
+    pdcattr = dc->pdcattr;
+    TextObj = RealizeFontInit(pdcattr->hlfntNew);
     if (NULL != TextObj)
     {
         FontGDI = ObjToGDI(TextObj->Font, FONT);
@@ -2698,7 +2744,7 @@ TextIntRealizeFont(HFONT FontHandle, PTEXTOBJ pTextObj)
     NTSTATUS Status = STATUS_SUCCESS;
     PTEXTOBJ TextObj;
     UNICODE_STRING FaceName;
-    PW32PROCESS Win32Process;
+    PPROCESSINFO Win32Process;
     UINT MatchScore;
 
     if (!pTextObj)
@@ -3011,7 +3057,7 @@ NtGdiGetFontFamilyInfo(HDC Dc,
     LOGFONTW LogFont;
     PFONTFAMILYINFO Info;
     DWORD Count;
-    PW32PROCESS Win32Process;
+    PPROCESSINFO Win32Process;
 
     /* Make a safe copy */
     Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW));
@@ -3084,7 +3130,7 @@ GreExtTextOutW(
     IN INT XStart,
     IN INT YStart,
     IN UINT fuOptions,
-    IN OPTIONAL LPRECT lprc,
+    IN OPTIONAL PRECTL lprc,
     IN LPWSTR String,
     IN INT Count,
     IN OPTIONAL LPINT Dx,
@@ -3097,25 +3143,18 @@ GreExtTextOutW(
      */
 
     DC *dc;
-    PDC_ATTR Dc_Attr;
+    PDC_ATTR pdcattr;
     SURFOBJ *SurfObj;
     SURFACE *psurf = NULL;
     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;
     POINTL SourcePoint, BrushOrigin;
-    HBRUSH hBrushFg = NULL;
-    PGDIBRUSHOBJ BrushFg = NULL;
-    GDIBRUSHINST BrushFgInst;
-    HBRUSH hBrushBg = NULL;
-    PGDIBRUSHOBJ BrushBg = NULL;
-    GDIBRUSHINST BrushBgInst;
     HBITMAP HSourceGlyph;
     SURFOBJ *SourceGlyphSurf;
     SIZEL bitSize;
@@ -3124,14 +3163,13 @@ GreExtTextOutW(
     FONTOBJ *FontObj;
     PFONTGDI FontGDI;
     PTEXTOBJ TextObj = NULL;
-    PPALGDI PalDestGDI;
-    XLATEOBJ *XlateObj=NULL, *XlateObj2=NULL;
-    ULONG Mode;
+    EXLATEOBJ exloRGB2Dst, exloDst2RGB;
     FT_Render_Mode RenderMode;
     BOOLEAN Render;
     POINT Start;
     BOOL DoBreak = FALSE;
     HPALETTE hDestPalette;
+    PPALETTE ppalDst;
     USHORT DxShift;
 
     // TODO: Write test-cases to exactly match real Windows in different
@@ -3142,15 +3180,23 @@ GreExtTextOutW(
         SetLastWin32Error(ERROR_INVALID_HANDLE);
         return FALSE;
     }
-    if (dc->DC_Type == DC_TYPE_INFO)
+    if (dc->dctype == DC_TYPE_INFO)
     {
         DC_UnlockDc(dc);
         /* Yes, Windows really returns TRUE in this case */
         return TRUE;
     }
 
-    Dc_Attr = dc->pDc_Attr;
-    if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+    pdcattr = dc->pdcattr;
+
+    if (pdcattr->ulDirty_ & DIRTY_TEXT)
+        DC_vUpdateTextBrush(dc);
+
+    if ((fuOptions & ETO_OPAQUE) || pdcattr->jBkMode == OPAQUE)
+    {
+        if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
+            DC_vUpdateBackgroundBrush(dc);
+    }
 
     /* Check if String is valid */
     if ((Count > 0xFFFF) || (Count > 0 && String == NULL))
@@ -3161,13 +3207,13 @@ GreExtTextOutW(
 
     DxShift = fuOptions & ETO_PDY ? 1 : 0;
 
-    if (PATH_IsPathOpen(dc->DcLevel))
+    if (PATH_IsPathOpen(dc->dclevel))
     {
         if (!PATH_ExtTextOut( dc,
                               XStart,
                               YStart,
                               fuOptions,
-                              (const RECT *)lprc,
+                              (const RECTL *)lprc,
                               String,
                               Count,
                               (const INT *)Dx)) goto fail;
@@ -3179,13 +3225,12 @@ GreExtTextOutW(
         IntLPtoDP(dc, (POINT *)lprc, 2);
     }
 
-    psurf = SURFACE_LockSurface(dc->w.hBitmap);
+    psurf = dc->dclevel.pSurface;
     if (!psurf)
     {
         goto fail;
     }
     SurfObj = &psurf->SurfObj;
-    ASSERT(SurfObj);
 
     Start.x = XStart;
     Start.y = YStart;
@@ -3194,53 +3239,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;
-    PalDestGDI = PALETTE_LockPalette(hDestPalette);
-    if ( !PalDestGDI )
-        Mode = PAL_RGB;
-    else
-    {
-        Mode = PalDestGDI->Mode;
-        PALETTE_UnlockPalette(PalDestGDI);
-    }
-    XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, hDestPalette, NULL);
-    if ( !XlateObj )
-    {
-        goto fail;
-    }
-    hBrushFg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, Dc_Attr->crForegroundClr), 0);
-    if ( !hBrushFg )
-    {
-        goto fail;
-    }
-    BrushFg = BRUSHOBJ_LockBrush(hBrushFg);
-    if ( !BrushFg )
-    {
-        goto fail;
-    }
-    IntGdiInitBrushInstance(&BrushFgInst, BrushFg, NULL);
-    if ((fuOptions & ETO_OPAQUE) || Dc_Attr->jBkMode == OPAQUE)
-    {
-        hBrushBg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, Dc_Attr->crBackgroundClr), 0);
-        if ( !hBrushBg )
-        {
-            goto fail;
-        }
-        BrushBg = BRUSHOBJ_LockBrush(hBrushBg);
-        if ( !BrushBg )
-        {
-            goto fail;
-        }
-        IntGdiInitBrushInstance(&BrushBgInst, BrushBg, NULL);
-    }
-    XlateObj2 = (XLATEOBJ*)IntEngCreateXlate(PAL_RGB, Mode, NULL, hDestPalette);
-    if ( !XlateObj2 )
-    {
-        goto fail;
-    }
-
     SourcePoint.x = 0;
     SourcePoint.y = 0;
     MaskRect.left = 0;
@@ -3250,34 +3248,41 @@ GreExtTextOutW(
 
     if ((fuOptions & ETO_OPAQUE) && lprc)
     {
-        DestRect.left   = lprc->left   + dc->ptlDCOrig.x;
-        DestRect.top    = lprc->top    + dc->ptlDCOrig.y;
-        DestRect.right  = lprc->right  + dc->ptlDCOrig.x;
-        DestRect.bottom = lprc->bottom + dc->ptlDCOrig.y;
+        DestRect.left   = lprc->left;
+        DestRect.top    = lprc->top;
+        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;
+
         IntEngBitBlt(
             &psurf->SurfObj,
             NULL,
             NULL,
-            dc->CombinedClip,
+            dc->rosdc.CombinedClip,
             NULL,
             &DestRect,
             &SourcePoint,
             &SourcePoint,
-            &BrushBgInst.BrushObject,
+            &dc->eboBackground.BrushObject,
             &BrushOrigin,
             ROP3_TO_ROP4(PATCOPY));
         fuOptions &= ~ETO_OPAQUE;
     }
     else
     {
-        if (Dc_Attr->jBkMode == OPAQUE)
+        if (pdcattr->jBkMode == OPAQUE)
         {
             fuOptions |= ETO_OPAQUE;
         }
     }
 
-    TextObj = RealizeFontInit(Dc_Attr->hlfntNew);
+    TextObj = RealizeFontInit(pdcattr->hlfntNew);
     if (TextObj == NULL)
     {
         goto fail;
@@ -3340,9 +3345,9 @@ GreExtTextOutW(
      * Process the vertical alignment and determine the yoff.
      */
 
-    if (Dc_Attr->lTextAlign & TA_BASELINE)
+    if (pdcattr->lTextAlign & TA_BASELINE)
         yoff = 0;
-    else if (Dc_Attr->lTextAlign & TA_BOTTOM)
+    else if (pdcattr->lTextAlign & TA_BOTTOM)
         yoff = -face->size->metrics.descender >> 6;
     else /* TA_TOP */
         yoff = face->size->metrics.ascender >> 6;
@@ -3354,7 +3359,7 @@ GreExtTextOutW(
      * Process the horizontal alignment and modify XStart accordingly.
      */
 
-    if (Dc_Attr->lTextAlign & (TA_RIGHT | TA_CENTER))
+    if (pdcattr->lTextAlign & (TA_RIGHT | TA_CENTER))
     {
         ULONGLONG TextWidth = 0;
         LPCWSTR TempText = String;
@@ -3410,7 +3415,7 @@ GreExtTextOutW(
                 TextWidth += delta.x;
             }
 
-            TextWidth += realglyph->advance.x >> 10;
+            TextWidth += realglyph->root.advance.x >> 10;
 
             previous = glyph_index;
             TempText++;
@@ -3418,7 +3423,7 @@ GreExtTextOutW(
 
         previous = 0;
 
-        if (Dc_Attr->lTextAlign & TA_RIGHT)
+        if (pdcattr->lTextAlign & TA_RIGHT)
         {
             RealXStart -= TextWidth;
         }
@@ -3432,6 +3437,15 @@ GreExtTextOutW(
     TextTop = YStart;
     BackgroundLeft = (RealXStart + 32) >> 6;
 
+    /* Create the xlateobj */
+    hDestPalette = psurf->hDIBPalette;
+    if (!hDestPalette) hDestPalette = pPrimarySurface->devinfo.hpalDefault;
+    ppalDst = PALETTE_LockPalette(hDestPalette);
+    EXLATEOBJ_vInitialize(&exloRGB2Dst, &gpalRGB, ppalDst, 0, 0, 0);
+    EXLATEOBJ_vInitialize(&exloDst2RGB, ppalDst, &gpalRGB, 0, 0, 0);
+    PALETTE_UnlockPalette(ppalDst);
+
+
     /*
      * The main rendering loop.
      */
@@ -3451,7 +3465,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,
@@ -3463,11 +3477,9 @@ GreExtTextOutW(
             {
                 DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index);
                 IntUnLockFreeType;
-                goto fail;
+                goto fail2;
             }
         }
-//      DbgPrint("realglyph: %x\n", realglyph);
-//      DbgPrint("TextLeft: %d\n", TextLeft);
 
         /* retrieve kerning distance and move pen position */
         if (use_kerning && previous && glyph_index && NULL == Dx)
@@ -3476,77 +3488,56 @@ GreExtTextOutW(
             FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
             TextLeft += delta.x;
         }
-//      DPRINT1("TextLeft: %d\n", TextLeft);
-//      DPRINT1("TextTop: %d\n", TextTop);
-
-        if (realglyph->format == ft_glyph_format_outline)
-        {
-            DbgPrint("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;
-
-//      DPRINT1("Pitch: %d\n", pitch);
-//      DPRINT1("Advance: %d\n", realglyph->advance.x);
+        DPRINT("TextLeft: %d\n", TextLeft);
+        DPRINT("TextTop: %d\n", TextTop);
+        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);
             IntEngBitBlt(
                 &psurf->SurfObj,
                 NULL,
                 NULL,
-                dc->CombinedClip,
+                dc->rosdc.CombinedClip,
                 NULL,
                 &DestRect,
                 &SourcePoint,
                 &SourcePoint,
-                &BrushBgInst.BrushObject,
+                &dc->eboBackground.BrushObject,
                 &BrushOrigin,
                 ROP3_TO_ROP4(PATCOPY));
             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 )
@@ -3554,7 +3545,7 @@ GreExtTextOutW(
             EngDeleteSurface((HSURF)HSourceGlyph);
             DPRINT1("WARNING: EngLockSurface() failed!\n");
             IntUnLockFreeType;
-            goto fail;
+            goto fail2;
         }
 
         /*
@@ -3576,13 +3567,12 @@ GreExtTextOutW(
         IntEngMaskBlt(
             SurfObj,
             SourceGlyphSurf,
-            dc->CombinedClip,
-            XlateObj,
-            XlateObj2,
+            dc->rosdc.CombinedClip,
+            &exloRGB2Dst.xlo,
+            &exloDst2RGB.xlo,
             &DestRect,
-            &SourcePoint,
             (PPOINTL)&MaskRect,
-            &BrushFgInst.BrushObject,
+            &dc->eboText.BrushObject,
             &BrushOrigin);
 
         EngUnlockSurface(SourceGlyphSurf);
@@ -3595,13 +3585,13 @@ GreExtTextOutW(
 
         if (NULL == Dx)
         {
-            TextLeft += realglyph->advance.x >> 10;
-//         DbgPrint("new TextLeft: %d\n", TextLeft);
+            TextLeft += realglyph->root.advance.x >> 10;
+             DPRINT("new TextLeft: %d\n", TextLeft);
         }
         else
         {
             TextLeft += Dx[i<<DxShift] << 6;
-//         DbgPrint("new TextLeft2: %d\n", TextLeft);
+             DPRINT("new TextLeft2: %d\n", TextLeft);
         }
 
         if (DxShift)
@@ -3616,42 +3606,21 @@ GreExtTextOutW(
 
     IntUnLockFreeType;
 
-    EngDeleteXlate(XlateObj);
-    EngDeleteXlate(XlateObj2);
-    SURFACE_UnlockSurface(psurf);
+    EXLATEOBJ_vCleanup(&exloRGB2Dst);
+    EXLATEOBJ_vCleanup(&exloDst2RGB);
     if (TextObj != NULL)
         TEXTOBJ_UnlockText(TextObj);
-    if (hBrushBg != NULL)
-    {
-        BRUSHOBJ_UnlockBrush(BrushBg);
-        NtGdiDeleteObject(hBrushBg);
-    }
-    BRUSHOBJ_UnlockBrush(BrushFg);
-    NtGdiDeleteObject(hBrushFg);
 good:
     DC_UnlockDc( dc );
 
     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);
-    if (psurf != NULL)
-        SURFACE_UnlockSurface(psurf);
-    if (hBrushBg != NULL)
-    {
-        BRUSHOBJ_UnlockBrush(BrushBg);
-        NtGdiDeleteObject(hBrushBg);
-    }
-    if (hBrushFg != NULL)
-    {
-        BRUSHOBJ_UnlockBrush(BrushFg);
-        NtGdiDeleteObject(hBrushFg);
-    }
     DC_UnlockDc(dc);
 
     return FALSE;
@@ -3673,7 +3642,7 @@ NtGdiExtTextOutW(
 {
     BOOL Result = FALSE;
     NTSTATUS Status = STATUS_SUCCESS;
-    RECT SafeRect;
+    RECTL SafeRect;
     BYTE LocalBuffer[STACK_TEXT_BUFFER_SIZE];
     PVOID Buffer = LocalBuffer;
     LPWSTR SafeString = NULL;
@@ -3796,7 +3765,7 @@ NtGdiGetCharABCWidthsW(
     LPABC SafeBuff;
     LPABCFLOAT SafeBuffF = NULL;
     PDC dc;
-    PDC_ATTR Dc_Attr;
+    PDC_ATTR pdcattr;
     PTEXTOBJ TextObj;
     PFONTGDI FontGDI;
     FT_Face face;
@@ -3825,6 +3794,12 @@ NtGdiGetCharABCWidthsW(
         return FALSE;
     }
 
+    if (!Buffer)
+    {
+        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
     BufferSize = Count * sizeof(ABC); // Same size!
     SafeBuff = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT);
     if (!fl) SafeBuffF = (LPABCFLOAT) SafeBuff;
@@ -3841,9 +3816,8 @@ NtGdiGetCharABCWidthsW(
         SetLastWin32Error(ERROR_INVALID_HANDLE);
         return FALSE;
     }
-    Dc_Attr = dc->pDc_Attr;
-    if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
-    hFont = Dc_Attr->hlfntNew;
+    pdcattr = dc->pdcattr;
+    hFont = pdcattr->hlfntNew;
     TextObj = RealizeFontInit(hFont);
     DC_UnlockDc(dc);
 
@@ -3965,7 +3939,7 @@ NtGdiGetCharWidthW(
     LPINT SafeBuff;
     PFLOAT SafeBuffF = NULL;
     PDC dc;
-    PDC_ATTR Dc_Attr;
+    PDC_ATTR pdcattr;
     PTEXTOBJ TextObj;
     PFONTGDI FontGDI;
     FT_Face face;
@@ -4009,9 +3983,8 @@ NtGdiGetCharWidthW(
         SetLastWin32Error(ERROR_INVALID_HANDLE);
         return FALSE;
     }
-    Dc_Attr = dc->pDc_Attr;
-    if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
-    hFont = Dc_Attr->hlfntNew;
+    pdcattr = dc->pdcattr;
+    hFont = pdcattr->hlfntNew;
     TextObj = RealizeFontInit(hFont);
     DC_UnlockDc(dc);
 
@@ -4087,6 +4060,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)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return GDI_ERROR;
+    }
+    pdcattr = dc->pdcattr;
+    hFont = pdcattr->hlfntNew;
+    TextObj = RealizeFontInit(hFont);
+    DC_UnlockDc(dc);
+    if (!TextObj)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return GDI_ERROR;
+    }
+
+    FontGDI = ObjToGDI(TextObj->Font, FONT);
+    TEXTOBJ_UnlockText(TextObj);
+
+    Buffer = ExAllocatePoolWithTag(PagedPool, cwc*sizeof(WORD), TAG_GDITEXT);
+    if (!Buffer)
+    {
+        SetLastWin32Error(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, TAG_GDITEXT);
+        if (!potm)
+        {
+            SetLastWin32Error(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, TAG_GDITEXT);
+    return cwc;
+}
+
 
 /*
 * @implemented
@@ -4101,7 +4166,7 @@ NtGdiGetGlyphIndicesW(
     IN DWORD iMode)
 {
     PDC dc;
-    PDC_ATTR Dc_Attr;
+    PDC_ATTR pdcattr;
     PTEXTOBJ TextObj;
     PFONTGDI FontGDI;
     HFONT hFont = 0;
@@ -4121,9 +4186,8 @@ NtGdiGetGlyphIndicesW(
         SetLastWin32Error(ERROR_INVALID_HANDLE);
         return GDI_ERROR;
     }
-    Dc_Attr = dc->pDc_Attr;
-    if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
-    hFont = Dc_Attr->hlfntNew;
+    pdcattr = dc->pdcattr;
+    hFont = pdcattr->hlfntNew;
     TextObj = RealizeFontInit(hFont);
     DC_UnlockDc(dc);
     if (!TextObj)