- Move functions out of freetype. Implemented FT: GetKerningPairs and RealizationInfo...
authorJames Tabor <james.tabor@reactos.org>
Sun, 2 Nov 2008 12:17:15 +0000 (12:17 +0000)
committerJames Tabor <james.tabor@reactos.org>
Sun, 2 Nov 2008 12:17:15 +0000 (12:17 +0000)
svn path=/trunk/; revision=37148

reactos/subsystems/win32/win32k/eng/objects.h
reactos/subsystems/win32/win32k/include/text.h
reactos/subsystems/win32/win32k/objects/font.c
reactos/subsystems/win32/win32k/objects/freetype.c
reactos/subsystems/win32/win32k/stubs/stubs.c

index 16947e7..f2a93d9 100644 (file)
@@ -67,8 +67,18 @@ typedef struct _FLOATGDI {
   ULONG Dummy;
 } FLOATGDI;
 
+
+#define FDM_TYPE_TEXT_METRIC  0x80000000
+
 typedef struct _FONTGDI {
   FONTOBJ     FontObj;
+  ULONG       iUnique;
+  FLONG       flType;
+  union{
+  DHPDEV      dhpdev;
+  FT_Face     face;
+  };
+  FLONG       flRealizedType;
 
   LONG        lMaxNegA;
   LONG        lMaxNegC;
@@ -76,7 +86,6 @@ typedef struct _FONTGDI {
 
   TEXTMETRICW TextMetric;
   LPWSTR      Filename;
-  FT_Face     face;
   BYTE        Underline;
   BYTE        StrikeOut;
 } FONTGDI, *PFONTGDI;
index 52d950c..ef2c211 100644 (file)
@@ -94,6 +94,10 @@ BOOL FASTCALL ftGdiGetTextMetricsW(HDC,PTMW_INTERNAL);
 DWORD FASTCALL ftGetFontLanguageInfo(PDC);
 INT FASTCALL ftGdiGetTextCharsetInfo(PDC,PFONTSIGNATURE,DWORD);
 DWORD FASTCALL ftGetFontUnicodeRanges(PFONTGDI, PGLYPHSET);
+DWORD FASTCALL ftGdiGetFontData(PFONTGDI,DWORD,DWORD,PVOID,DWORD);
+BOOL FASTCALL IntGdiGetFontResourceInfo(PUNICODE_STRING,PVOID,DWORD*,DWORD);
+BOOL FASTCALL ftGdiRealizationInfo(PFONTGDI,PREALIZATION_INFO);
+DWORD FASTCALL ftGdiGetKerningPairs(PFONTGDI,DWORD,LPKERNINGPAIR);
 
 #define IntLockProcessPrivateFonts(W32Process) \
   ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&W32Process->PrivateFontListLock)
index fea123c..b7370a4 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
+/** Internal ******************************************************************/
+
+INT
+FASTCALL
+FontGetObject(PTEXTOBJ TFont, INT Count, PVOID Buffer)
+{
+  if( Buffer == NULL ) return sizeof(LOGFONTW);
+
+  switch (Count)
+  {
+
+     case sizeof(ENUMLOGFONTEXDVW):
+        RtlCopyMemory( (LPENUMLOGFONTEXDVW) Buffer,
+                                            &TFont->logfont,
+                                            sizeof(ENUMLOGFONTEXDVW));
+        break;
+     case sizeof(ENUMLOGFONTEXW):
+        RtlCopyMemory( (LPENUMLOGFONTEXW) Buffer,
+                                          &TFont->logfont.elfEnumLogfontEx,
+                                          sizeof(ENUMLOGFONTEXW));
+        break;
+
+     case sizeof(EXTLOGFONTW):
+     case sizeof(ENUMLOGFONTW):
+        RtlCopyMemory((LPENUMLOGFONTW) Buffer,
+                                    &TFont->logfont.elfEnumLogfontEx.elfLogFont,
+                                       sizeof(ENUMLOGFONTW));
+        break;
+
+     case sizeof(LOGFONTW):
+        RtlCopyMemory((LPLOGFONTW) Buffer,
+                                   &TFont->logfont.elfEnumLogfontEx.elfLogFont,
+                                   sizeof(LOGFONTW));
+        break;
+
+     default:
+        SetLastWin32Error(ERROR_BUFFER_OVERFLOW);
+        return 0;
+  }
+  return Count;
+}
+
 /** Functions ******************************************************************/
 
 INT
@@ -62,6 +104,66 @@ NtGdiAddFontResourceW(
   return Ret;
 }
 
+DWORD
+STDCALL
+NtGdiGetFontData(
+   HDC hDC,
+   DWORD Table,
+   DWORD Offset,
+   LPVOID Buffer,
+   DWORD Size)
+{
+  PDC Dc;
+  PDC_ATTR Dc_Attr;
+  HFONT hFont;
+  PTEXTOBJ TextObj;
+  PFONTGDI FontGdi;
+  DWORD Result = GDI_ERROR;
+  NTSTATUS Status = STATUS_SUCCESS;
+
+  if (Buffer && Size)
+  {
+     _SEH_TRY
+     {
+         ProbeForRead(Buffer, Size, 1);
+     }
+     _SEH_HANDLE
+     {
+         Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END
+  }
+
+  if (!NT_SUCCESS(Status)) return Result;
+
+  Dc = DC_LockDc(hDC);
+  if (Dc == NULL)
+  {
+     SetLastWin32Error(ERROR_INVALID_HANDLE);
+     return GDI_ERROR;
+  }
+  Dc_Attr = Dc->pDc_Attr;
+  if(!Dc_Attr) Dc_Attr = &Dc->Dc_Attr;
+
+  hFont = Dc_Attr->hlfntNew;
+  TextObj = TEXTOBJ_LockText(hFont);
+  DC_UnlockDc(Dc);
+
+  if (TextObj == NULL)
+  {
+     SetLastWin32Error(ERROR_INVALID_HANDLE);
+     return GDI_ERROR;
+  }
+
+  FontGdi = ObjToGDI(TextObj->Font, FONT);
+
+  Result = ftGdiGetFontData(FontGdi, Table, Offset, Buffer, Size);
+
+  TEXTOBJ_UnlockText(TextObj);
+
+  return Result;
+}
+
  /*
  * @implemented
  */
@@ -298,6 +400,107 @@ NtGdiGetOutlineTextMetricsInternalW (HDC  hDC,
   return Size;
 }
 
+W32KAPI
+BOOL
+APIENTRY
+NtGdiGetFontResourceInfoInternalW(
+    IN LPWSTR   pwszFiles,
+    IN ULONG    cwc,
+    IN ULONG    cFiles,
+    IN UINT     cjIn,
+    OUT LPDWORD pdwBytes,
+    OUT LPVOID  pvBuf,
+    IN DWORD    dwType)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    DWORD dwBytes;
+    UNICODE_STRING SafeFileNames;
+    BOOL bRet = FALSE;
+    ULONG cbStringSize;
+
+    union
+    {
+        LOGFONTW logfontw;
+        WCHAR FullName[LF_FULLFACESIZE];
+    } Buffer;
+
+    /* FIXME: handle cFiles > 0 */
+
+    /* Check for valid dwType values
+       dwType == 4 seems to be handled by gdi32 only */
+    if (dwType == 4 || dwType > 5)
+    {
+        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    /* Allocate a safe unicode string buffer */
+    cbStringSize = cwc * sizeof(WCHAR);
+    SafeFileNames.MaximumLength = SafeFileNames.Length = cbStringSize - sizeof(WCHAR);
+    SafeFileNames.Buffer = ExAllocatePoolWithTag(PagedPool,
+                                                 cbStringSize,
+                                                 TAG('R','T','S','U'));
+    if (!SafeFileNames.Buffer)
+    {
+        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
+
+    /* Check buffers and copy pwszFiles to safe unicode string */
+    _SEH_TRY
+    {
+        ProbeForRead(pwszFiles, cbStringSize, 1);
+        ProbeForWrite(pdwBytes, sizeof(DWORD), 1);
+        ProbeForWrite(pvBuf, cjIn, 1);
+
+        RtlCopyMemory(SafeFileNames.Buffer, pwszFiles, cbStringSize);
+    }
+    _SEH_HANDLE
+    {
+        Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END
+
+    if(!NT_SUCCESS(Status))
+    {
+        SetLastNtError(Status);
+        /* Free the string buffer for the safe filename */
+        ExFreePool(SafeFileNames.Buffer);
+        return FALSE;
+    }
+
+    /* Do the actual call */
+    bRet = IntGdiGetFontResourceInfo(&SafeFileNames, &Buffer, &dwBytes, dwType);
+
+    /* Check if succeeded and the buffer is big enough */
+    if (bRet && cjIn >= dwBytes)
+    {
+        /* Copy the data back to caller */
+        _SEH_TRY
+        {
+            /* Buffers are already probed */
+            RtlCopyMemory(pvBuf, &Buffer, dwBytes);
+            *pdwBytes = dwBytes;
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END
+
+        if(!NT_SUCCESS(Status))
+        {
+            SetLastNtError(Status);
+            bRet = FALSE;
+        }
+    }
+
+    /* Free the string for the safe filenames */
+    ExFreePool(SafeFileNames.Buffer);
+
+    return bRet;
+}
+
 HFONT
 STDCALL
 NtGdiHfontCreate(
index 8397340..ddd0a07 100644 (file)
@@ -40,6 +40,7 @@
 #include <ft2build.h>
 #include FT_FREETYPE_H
 #include FT_GLYPH_H
+#include FT_TYPE1_TABLES_H
 #include <freetype/tttables.h>
 #include <freetype/fttrigon.h>
 #include <freetype/ftglyph.h>
@@ -103,7 +104,7 @@ static PWCHAR ElfScripts[32] = { /* these are in the order of the fsCsb[0] bits
 };
 
 /*
- *  For NtGdiTranslateCharsetInfo
+ *  For TranslateCharsetInfo
  */
 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
 #define MAXTCIINDEX 32
@@ -784,7 +785,14 @@ IntGetOutlineTextMetrics(PFONTGDI FontGDI,
 
   Otm->otmSize = Needed;
 
-  FillTM(&Otm->otmTextMetrics, FontGDI, pOS2, pHori, !Error ? &Win : 0);
+//  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));
 
   Otm->otmFiller = 0;
   memcpy(&Otm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
@@ -1289,81 +1297,6 @@ ftGdiGetRasterizerCaps(LPRASTERIZER_STATUS lprs)
   return FALSE;
 }
 
-int STDCALL
-NtGdiGetFontFamilyInfo(HDC Dc,
-                       LPLOGFONTW UnsafeLogFont,
-                       PFONTFAMILYINFO UnsafeInfo,
-                       DWORD Size)
-{
-  NTSTATUS Status;
-  LOGFONTW LogFont;
-  PFONTFAMILYINFO Info;
-  DWORD Count;
-  PW32PROCESS Win32Process;
-
-  /* Make a safe copy */
-  Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW));
-  if (! NT_SUCCESS(Status))
-    {
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      return -1;
-    }
-
-  /* Allocate space for a safe copy */
-  Info = ExAllocatePoolWithTag(PagedPool, Size * sizeof(FONTFAMILYINFO), TAG_GDITEXT);
-  if (NULL == Info)
-    {
-      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-      return -1;
-    }
-
-  /* Enumerate font families in the global list */
-  IntLockGlobalFonts;
-  Count = 0;
-  if (! GetFontFamilyInfoForList(&LogFont, Info, &Count, Size, &FontListHead) )
-    {
-      IntUnLockGlobalFonts;
-      ExFreePool(Info);
-      return -1;
-    }
-  IntUnLockGlobalFonts;
-
-  /* Enumerate font families in the process local list */
-  Win32Process = PsGetCurrentProcessWin32Process();
-  IntLockProcessPrivateFonts(Win32Process);
-  if (! GetFontFamilyInfoForList(&LogFont, Info, &Count, Size,
-                                 &Win32Process->PrivateFontListHead))
-    {
-      IntUnLockProcessPrivateFonts(Win32Process);
-      ExFreePool(Info);
-      return -1;
-    }
-  IntUnLockProcessPrivateFonts(Win32Process);
-
-  /* Enumerate font families in the registry */
-  if (! GetFontFamilyInfoForSubstitutes(&LogFont, Info, &Count, Size))
-    {
-      ExFreePool(Info);
-      return -1;
-    }
-
-  /* Return data to caller */
-  if (0 != Count)
-    {
-      Status = MmCopyToCaller(UnsafeInfo, Info,
-                              (Count < Size ? Count : Size) * sizeof(FONTFAMILYINFO));
-      if (! NT_SUCCESS(Status))
-        {
-          ExFreePool(Info);
-          SetLastWin32Error(ERROR_INVALID_PARAMETER);
-          return -1;
-        }
-    }
-
-  ExFreePool(Info);
-
-  return Count;
-}
 
 FT_Glyph STDCALL
 ftGdiGlyphCacheGet(
@@ -1468,249 +1401,127 @@ ftGdiGlyphCacheSet(
    return GlyphCopy;
 }
 
-BOOL
-APIENTRY
-NtGdiExtTextOutW(
-    IN HDC hDC,
-    IN INT XStart,
-    IN INT YStart,
-    IN UINT fuOptions,
-    IN OPTIONAL LPRECT lprc,
-    IN LPWSTR UnsafeString,
-    IN INT Count,
-    IN OPTIONAL LPINT UnsafeDx,
-    IN DWORD dwCodePage)
+
+static
+void
+FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
 {
-   /*
-    * FIXME:
-    * Call EngTextOut, which does the real work (calling DrvTextOut where
-    * appropriate)
-    */
+    pt->x.value = vec->x >> 6;
+    pt->x.fract = (vec->x & 0x3f) << 10;
+    pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
+    pt->y.value = vec->y >> 6;
+    pt->y.fract = (vec->y & 0x3f) << 10;
+    pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
+    return;
+}
 
-   DC *dc;
-   PDC_ATTR Dc_Attr;
-   SURFOBJ *SurfObj;
-   BITMAPOBJ *BitmapObj = NULL;
-   int error, glyph_index, n, i;
-   FT_Face face;
-   FT_GlyphSlot glyph;
-   FT_Glyph realglyph;
-   FT_BitmapGlyph realglyph2;
-   LONGLONG TextLeft, RealXStart;
-   ULONG TextTop, previous, BackgroundLeft;
-   FT_Bool use_kerning;
-   RECTL DestRect, MaskRect, SpecifiedDestRect;
-   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;
-   FT_CharMap found = 0, charmap;
-   INT yoff;
-   FONTOBJ *FontObj;
-   PFONTGDI FontGDI;
-   PTEXTOBJ TextObj = NULL;
-   PPALGDI PalDestGDI;
-   XLATEOBJ *XlateObj=NULL, *XlateObj2=NULL;
-   ULONG Mode;
-   FT_Render_Mode RenderMode;
-   BOOLEAN Render;
-   NTSTATUS Status;
-   INT *Dx = NULL;
-   POINT Start;
-   BOOL DoBreak = FALSE;
-   LPCWSTR String, SafeString = NULL;
-   HPALETTE hDestPalette;
+/*
+   This function builds an FT_Fixed from a float. It puts the integer part
+   in the highest 16 bits and the decimal part in the lowest 16 bits of the FT_Fixed.
+   It fails if the integer part of the float number is greater than SHORT_MAX.
+*/
+static __inline FT_Fixed FT_FixedFromFloat(float f)
+{
+       short value = f;
+       unsigned short fract = (f - value) * 0xFFFF;
+       return (FT_Fixed)((long)value << 16 | (unsigned long)fract);
+}
 
-   // TODO: Write test-cases to exactly match real Windows in different
-   // bad parameters (e.g. does Windows check the DC or the RECT first?).
-   dc = DC_LockDc(hDC);
-   if (!dc)
+/*
+   This function builds an FT_Fixed from a FIXED. It simply put f.value
+   in the highest 16 bits and f.fract in the lowest 16 bits of the FT_Fixed.
+*/
+static __inline FT_Fixed FT_FixedFromFIXED(FIXED f)
+{
+       return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract);
+}
+
+/*
+ * Based on WineEngGetGlyphOutline
+ *
+ */
+ULONG
+FASTCALL
+ftGdiGetGlyphOutline(
+    PDC dc,
+    WCHAR wch,
+    UINT iFormat,
+    LPGLYPHMETRICS pgm,
+    ULONG cjBuf,
+    PVOID pvBuf,
+    LPMAT2 pmat2,
+    BOOL bIgnoreRotation)
+{
+  static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
+  PDC_ATTR Dc_Attr;
+  PTEXTOBJ TextObj;
+  PFONTGDI FontGDI;
+  HFONT hFont = 0;
+  GLYPHMETRICS gm;
+  ULONG Size;
+  FT_Face ft_face;
+  FT_UInt glyph_index;
+  DWORD width, height, pitch, needed = 0;
+  FT_Bitmap ft_bitmap;
+  FT_Error error;
+  INT left, right, top = 0, bottom = 0;
+  FT_Angle angle = 0;
+  FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
+  FLOAT eM11, widthRatio = 1.0;
+  FT_Matrix transMat = identityMat;
+  BOOL needsTransform = FALSE;
+  INT orientation;
+  LONG aveWidth;
+  INT adv, lsb, bbx; /* These three hold to widths of the unrotated chars */
+  OUTLINETEXTMETRICW *potm;
+  int n = 0;
+  FT_CharMap found = 0, charmap;
+  XFORM xForm;
+
+  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;
+  
+  MatrixS2XForm(&xForm, &dc->DcLevel.mxWorldToDevice);
+  eM11 = xForm.eM11;
+  
+  hFont = Dc_Attr->hlfntNew;
+  TextObj = TEXTOBJ_LockText(hFont);
+
+  if (!TextObj)
    {
       SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return FALSE;
-   }
-   if (dc->DC_Type == DC_TYPE_INFO)
-   {
-      DC_UnlockDc(dc);
-      /* Yes, Windows really returns TRUE in this case */
-      return TRUE;
+      return GDI_ERROR;
    }
+  FontGDI = ObjToGDI(TextObj->Font, FONT);
+  ft_face = FontGDI->face;
 
-   Dc_Attr = dc->pDc_Attr;
-   if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+  aveWidth = FT_IS_SCALABLE(ft_face) ? TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth: 0;
+  orientation = FT_IS_SCALABLE(ft_face) ? TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation: 0;
 
-       /* Check if String is valid */
-   if ((Count > 0xFFFF) || (Count > 0 && UnsafeString == NULL))
-   {
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      goto fail;
-   }
-   if (Count > 0)
-   {
-      SafeString = ExAllocatePoolWithTag(PagedPool, Count * sizeof(WCHAR), TAG_GDITEXT);
-      if (!SafeString)
-      {
-         goto fail;
-      }
-      Status = MmCopyFromCaller(SafeString, UnsafeString, Count * sizeof(WCHAR));
-      if (! NT_SUCCESS(Status))
-      {
-        goto fail;
-      }
-   }
-   String = SafeString;
-
-   if (lprc && (fuOptions & (ETO_OPAQUE | ETO_CLIPPED)))
-   {
-      // At least one of the two flags were specified. Copy lprc. Once.
-      Status = MmCopyFromCaller(&SpecifiedDestRect, lprc, sizeof(RECT));
-      if (!NT_SUCCESS(Status))
-      {
-         DC_UnlockDc(dc);
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         return FALSE;
-      }
-      IntLPtoDP(dc, (POINT *) &SpecifiedDestRect, 2);
-   }
-
-   if (NULL != UnsafeDx && Count > 0)
-   {
-      Dx = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), TAG_GDITEXT);
-      if (NULL == Dx)
-      {
-         goto fail;
-      }
-      Status = MmCopyFromCaller(Dx, UnsafeDx, Count * sizeof(INT));
-      if (! NT_SUCCESS(Status))
-      {
-         goto fail;
-      }
-   }
-
-   BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
-   if ( !BitmapObj )
-   {
-      goto fail;
-   }
-   SurfObj = &BitmapObj->SurfObj;
-   ASSERT(SurfObj);
-
-   Start.x = XStart; Start.y = YStart;
-   IntLPtoDP(dc, &Start, 1);
-
-   RealXStart = (Start.x + dc->ptlDCOrig.x) << 6;
-   YStart = Start.y + dc->ptlDCOrig.y;
-
-   /* Create the brushes */
-   hDestPalette = BitmapObj->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;
-   MaskRect.top = 0;
-   BrushOrigin.x = 0;
-   BrushOrigin.y = 0;
-
-   if ((fuOptions & ETO_OPAQUE) && lprc)
-   {
-      DestRect.left   = SpecifiedDestRect.left   + dc->ptlDCOrig.x;
-      DestRect.top    = SpecifiedDestRect.top    + dc->ptlDCOrig.y;
-      DestRect.right  = SpecifiedDestRect.right  + dc->ptlDCOrig.x;
-      DestRect.bottom = SpecifiedDestRect.bottom + dc->ptlDCOrig.y;
-      IntLPtoDP(dc, (LPPOINT)&DestRect, 2);
-      IntEngBitBlt(
-         &BitmapObj->SurfObj,
-         NULL,
-         NULL,
-         dc->CombinedClip,
-         NULL,
-         &DestRect,
-         &SourcePoint,
-         &SourcePoint,
-         &BrushBgInst.BrushObject,
-         &BrushOrigin,
-         ROP3_TO_ROP4(PATCOPY));
-      fuOptions &= ~ETO_OPAQUE;
-   }
-   else
-   {
-      if (Dc_Attr->jBkMode == OPAQUE)
-      {
-         fuOptions |= ETO_OPAQUE;
-      }
-   }
-
-   TextObj = TEXTOBJ_LockText(Dc_Attr->hlfntNew);
-   if(TextObj == NULL)
-   {
-      goto fail;
-   }
+  Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
+  potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
+  if (!potm)
+    {
+      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+      TEXTOBJ_UnlockText(TextObj);
+      return GDI_ERROR;
+    }
+  IntGetOutlineTextMetrics(FontGDI, Size, potm);
 
-   FontObj = TextObj->Font;
-   ASSERT(FontObj);
-   FontGDI = ObjToGDI(FontObj, FONT);
-   ASSERT(FontGDI);
+  IntLockFreeType;
 
-   IntLockFreeType;
-   face = FontGDI->face;
-   if (face->charmap == NULL)
-   {
+  /* During testing, I never saw this used. In here just incase.*/
+  if (ft_face->charmap == NULL)
+    {
       DPRINT("WARNING: No charmap selected!\n");
-      DPRINT("This font face has %d charmaps\n", face->num_charmaps);
+      DPRINT("This font face has %d charmaps\n", ft_face->num_charmaps);
 
-      for (n = 0; n < face->num_charmaps; n++)
+      for (n = 0; n < ft_face->num_charmaps; n++)
       {
-         charmap = face->charmaps[n];
+         charmap = ft_face->charmaps[n];
          DPRINT("found charmap encoding: %u\n", charmap->encoding);
          if (charmap->encoding != 0)
          {
@@ -1722,2483 +1533,2636 @@ NtGdiExtTextOutW(
       {
          DPRINT1("WARNING: Could not find desired charmap!\n");
       }
-      error = FT_Set_Charmap(face, found);
-         if (error)
-      {
-         DPRINT1("WARNING: Could not set the charmap!\n");
-      }
-   }
+      error = FT_Set_Charmap(ft_face, found);
+      if (error)
+        {
+           DPRINT1("WARNING: Could not set the charmap!\n");
+        }
+    }
 
-   Render = IntIsFontRenderingEnabled();
-   if (Render)
-      RenderMode = IntGetFontRenderMode(&TextObj->logfont.elfEnumLogfontEx.elfLogFont);
-   else
-      RenderMode = FT_RENDER_MODE_MONO;
+//  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));
 
-   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));
-   if (error)
-   {
-      DPRINT1("Error in setting pixel sizes: %u\n", error);
-      IntUnLockFreeType;
-      goto fail;
-   }
+  TEXTOBJ_UnlockText(TextObj);
 
-   /*
-    * Process the vertical alignment and determine the yoff.
-    */
+  if (iFormat & GGO_GLYPH_INDEX)
+    {
+       glyph_index = wch;
+       iFormat &= ~GGO_GLYPH_INDEX;
+    }
+  else  glyph_index = FT_Get_Char_Index(ft_face, wch);
 
-   if (Dc_Attr->lTextAlign & TA_BASELINE)
-      yoff = 0;
-   else if (Dc_Attr->lTextAlign & TA_BOTTOM)
-      yoff = -face->size->metrics.descender >> 6;
-   else /* TA_TOP */
-      yoff = face->size->metrics.ascender >> 6;
+  if (orientation || (iFormat != GGO_METRICS && iFormat != GGO_BITMAP) || aveWidth || pmat2)
+        load_flags |= FT_LOAD_NO_BITMAP;
 
-   use_kerning = FT_HAS_KERNING(face);
-   previous = 0;
+  if (iFormat & GGO_UNHINTED)
+    {
+       load_flags |= FT_LOAD_NO_HINTING;
+       iFormat &= ~GGO_UNHINTED;
+    }
 
-   /*
-    * Process the horizontal alignment and modify XStart accordingly.
-    */
+  error = FT_Load_Glyph(ft_face, glyph_index, load_flags);
+  if (error)
+    {
+         DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
+        IntUnLockFreeType;
+        if (potm) ExFreePoolWithTag(potm, TAG_GDITEXT);
+        return GDI_ERROR;
+    }
+  IntUnLockFreeType;
 
-   if (Dc_Attr->lTextAlign & (TA_RIGHT | TA_CENTER))
-   {
-      ULONGLONG TextWidth = 0;
-      LPCWSTR TempText = String;
-      int Start;
+  if (aveWidth && potm)
+    {
+       widthRatio = (FLOAT)aveWidth * eM11 /
+                                 (FLOAT) potm->otmTextMetrics.tmAveCharWidth;
+    }
 
-      /*
-       * Calculate width of the text.
-       */
+  left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64;
+  right = (INT)((ft_face->glyph->metrics.horiBearingX +
+                    ft_face->glyph->metrics.width) * widthRatio + 63) & -64;
 
-      if (NULL != Dx)
-      {
-         Start = Count < 2 ? 0 : Count - 2;
-         TextWidth = Count < 2 ? 0 : (Dx[Count - 2] << 6);
-      }
-      else
-      {
-         Start = 0;
-      }
-      TempText = String + Start;
-
-      for (i = Start; i < Count; i++)
-      {
-         if (fuOptions & ETO_GLYPH_INDEX)
-           glyph_index = *TempText;
-         else
-           glyph_index = FT_Get_Char_Index(face, *TempText);
-
-         if (!(realglyph = ftGdiGlyphCacheGet(face, glyph_index,
-         TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)))
-         {
-             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);
-             }
-
-             glyph = face->glyph;
-             realglyph = ftGdiGlyphCacheSet(face, glyph_index,
-                TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight, glyph, RenderMode);
-             if (!realglyph)
-             {
-                 DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index);
-                 IntUnLockFreeType;
-                 goto fail;
-             }
-
-         }
-         /* retrieve kerning distance */
-         if (use_kerning && previous && glyph_index)
-         {
-            FT_Vector delta;
-            FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
-            TextWidth += delta.x;
-         }
+  adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6;
+  lsb = left >> 6;
+  bbx = (right - left) >> 6;
 
-         TextWidth += realglyph->advance.x >> 10;
+  DPRINT("Advance = %d, lsb = %d, bbx = %d\n",adv, lsb, bbx);
 
-         previous = glyph_index;
-         TempText++;
-      }
+  IntLockFreeType;
 
-      previous = 0;
+   /* 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);
+        needsTransform = TRUE;
+    }
 
-      if (Dc_Attr->lTextAlign & TA_RIGHT)
-      {
-         RealXStart -= TextWidth;
-      }
-      else
-      {
-         RealXStart -= TextWidth / 2;
-      }
-   }
+    /* Slant transform */
+  if (potm->otmTextMetrics.tmItalic)
+    {
+        FT_Matrix slantMat;
+        DPRINT("Slant Trans!\n");
+        slantMat.xx = (1 << 16);
+        slantMat.xy = ((1 << 16) >> 2);
+        slantMat.yx = 0;
+        slantMat.yy = (1 << 16);
+        FT_Matrix_Multiply(&slantMat, &transMat);
+        needsTransform = TRUE;
+    }
 
-   TextLeft = RealXStart;
-   TextTop = YStart;
-   BackgroundLeft = (RealXStart + 32) >> 6;
+    /* Rotation transform */
+  if (orientation)
+    {
+        FT_Matrix rotationMat;
+        FT_Vector vecAngle;
+        DPRINT("Rotation Trans!\n");
+        angle = FT_FixedFromFloat((float)orientation / 10.0);
+        FT_Vector_Unit(&vecAngle, angle);
+        rotationMat.xx = vecAngle.x;
+        rotationMat.xy = -vecAngle.y;
+        rotationMat.yx = -rotationMat.xy;
+        rotationMat.yy = rotationMat.xx;
+        FT_Matrix_Multiply(&rotationMat, &transMat);
+        needsTransform = TRUE;
+    }
 
-   /*
-    * The main rendering loop.
-    */
+    /* Extra transformation specified by caller */
+  if (pmat2)
+    {
+        FT_Matrix extraMat;
+        DPRINT("MAT2 Matrix Trans!\n");
+        extraMat.xx = FT_FixedFromFIXED(pmat2->eM11);
+        extraMat.xy = FT_FixedFromFIXED(pmat2->eM21);
+        extraMat.yx = FT_FixedFromFIXED(pmat2->eM12);
+        extraMat.yy = FT_FixedFromFIXED(pmat2->eM22);
+        FT_Matrix_Multiply(&extraMat, &transMat);
+        needsTransform = TRUE;
+    }
 
-   for (i = 0; i < Count; i++)
-   {
-      if (fuOptions & ETO_GLYPH_INDEX)
-        glyph_index = *String;
-      else
-        glyph_index = FT_Get_Char_Index(face, *String);
+  if (potm) ExFreePoolWithTag(potm, TAG_GDITEXT); /* It looks like we are finished with potm ATM.*/
 
-      if (!(realglyph = ftGdiGlyphCacheGet(face, glyph_index,
-      TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)))
-      {
-        error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
-        if (error)
-        {
-           DPRINT1("Failed to load and render glyph! [index: %u]\n", glyph_index);
-           IntUnLockFreeType;
-           goto fail;
-        }
-        glyph = face->glyph;
-        realglyph = ftGdiGlyphCacheSet(face,
-                                       glyph_index,
-                                       TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight,
-                                       glyph,
-                                       RenderMode);
-        if (!realglyph)
+  if (!needsTransform)
+    {
+        DPRINT("No Need to be Transformed!\n");
+        top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
+        bottom = (ft_face->glyph->metrics.horiBearingY -
+                  ft_face->glyph->metrics.height) & -64;
+        gm.gmCellIncX = adv;
+        gm.gmCellIncY = 0;
+    }
+  else
+    {
+        INT xc, yc;
+        FT_Vector vec;
+        for(xc = 0; xc < 2; xc++)
         {
-            DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index);
-            IntUnLockFreeType;
-            goto fail;
+          for(yc = 0; yc < 2; yc++)
+            {
+                vec.x = (ft_face->glyph->metrics.horiBearingX +
+                  xc * ft_face->glyph->metrics.width);
+                vec.y = ft_face->glyph->metrics.horiBearingY -
+                  yc * ft_face->glyph->metrics.height;
+                DPRINT("Vec %ld,%ld\n", vec.x, vec.y);
+                FT_Vector_Transform(&vec, &transMat);
+                if(xc == 0 && yc == 0)
+                {
+                    left = right = vec.x;
+                    top = bottom = vec.y;
+                }
+                else
+                {
+                    if(vec.x < left) left = vec.x;
+                    else if(vec.x > right) right = vec.x;
+                    if(vec.y < bottom) bottom = vec.y;
+                    else if(vec.y > top) top = vec.y;
+                }
+            }
         }
-      }
-//      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)
-      {
-         FT_Vector delta;
-         FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
-         TextLeft += delta.x;
-      }
-//      DPRINT1("TextLeft: %d\n", TextLeft);
-//      DPRINT1("TextTop: %d\n", TextTop);
+        left = left & -64;
+        right = (right + 63) & -64;
+        bottom = bottom & -64;
+        top = (top + 63) & -64;
 
-      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;
+        DPRINT("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
+        vec.x = ft_face->glyph->metrics.horiAdvance;
+        vec.y = 0;
+        FT_Vector_Transform(&vec, &transMat);
+        gm.gmCellIncX = (vec.x+63) >> 6;
+        gm.gmCellIncY = -((vec.y+63) >> 6);
+    }
+  gm.gmBlackBoxX = (right - left) >> 6;
+  gm.gmBlackBoxY = (top - bottom) >> 6;
+  gm.gmptGlyphOrigin.x = left >> 6;
+  gm.gmptGlyphOrigin.y = top >> 6;
 
-//      DPRINT1("Pitch: %d\n", pitch);
-//      DPRINT1("Advance: %d\n", realglyph->advance.x);
+  DPRINT("CX %d CY %d BBX %d BBY %d GOX %d GOY %d\n",
+                           gm.gmCellIncX, gm.gmCellIncY,
+                           gm.gmBlackBoxX, gm.gmBlackBoxY,
+                           gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
 
-      if (fuOptions & ETO_OPAQUE)
-      {
-         DestRect.left = BackgroundLeft;
-         DestRect.right = (TextLeft + (realglyph->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(
-            &BitmapObj->SurfObj,
-            NULL,
-            NULL,
-            dc->CombinedClip,
-            NULL,
-            &DestRect,
-            &SourcePoint,
-            &SourcePoint,
-            &BrushBgInst.BrushObject,
-            &BrushOrigin,
-            ROP3_TO_ROP4(PATCOPY));
-         BackgroundLeft = DestRect.right;
-      }
+  IntUnLockFreeType;
 
-      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;
+  if (pgm) RtlCopyMemory(pgm, &gm, sizeof(GLYPHMETRICS));    
 
-      bitSize.cx = realglyph2->bitmap.width;
-      bitSize.cy = realglyph2->bitmap.rows;
-      MaskRect.right = realglyph2->bitmap.width;
-      MaskRect.bottom = realglyph2->bitmap.rows;
+  if (iFormat == GGO_METRICS)
+    {
+        DPRINT("GGO_METRICS Exit!\n");
+        return 1; /* FIXME */
+    }
 
-      /*
-       * 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.
-       */
+  if (ft_face->glyph->format != ft_glyph_format_outline && iFormat != GGO_BITMAP)
+    {
+        DPRINT1("loaded a bitmap\n");
+        return GDI_ERROR;
+    }
 
-      HSourceGlyph = EngCreateBitmap(bitSize, realglyph2->bitmap.pitch,
-                                     (realglyph2->bitmap.pixel_mode == ft_pixel_mode_grays) ?
-                                     BMF_8BPP : BMF_1BPP, BMF_TOPDOWN,
-                                     realglyph2->bitmap.buffer);
-      if ( !HSourceGlyph )
-      {
-        DPRINT1("WARNING: EngLockSurface() failed!\n");
-        // FT_Done_Glyph(realglyph);
-        IntUnLockFreeType;
-        goto fail;
-      }
-      SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
-      if ( !SourceGlyphSurf )
-      {
-        EngDeleteSurface((HSURF)HSourceGlyph);
-        DPRINT1("WARNING: EngLockSurface() failed!\n");
-        IntUnLockFreeType;
-        goto fail;
-      }
+  switch(iFormat)
+    {
+    case GGO_BITMAP:
+        width = gm.gmBlackBoxX;
+        height = gm.gmBlackBoxY;
+        pitch = ((width + 31) >> 5) << 2;
+        needed = pitch * height;
 
-      /*
-       * Use the font data as a mask to paint onto the DCs surface using a
-       * brush.
-       */
+        if(!pvBuf || !cjBuf) break;
 
-      if (lprc &&
-          (fuOptions & ETO_CLIPPED) &&
-          DestRect.right >= SpecifiedDestRect.right + dc->ptlDCOrig.x)
-      {
-         // We do the check '>=' instead of '>' to possibly save an iteration
-         // through this loop, since it's breaking after the drawing is done,
-         // and x is always incremented.
-         DestRect.right = SpecifiedDestRect.right + dc->ptlDCOrig.x;
-         DoBreak = TRUE;
-      }
+        switch(ft_face->glyph->format)
+        {
+          case ft_glyph_format_bitmap:
+           {
+             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
+             INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
+             INT h = ft_face->glyph->bitmap.rows;
+             while(h--)
+             {
+                RtlCopyMemory(dst, src, w);
+                src += ft_face->glyph->bitmap.pitch;
+                dst += pitch;
+             }
+             break;
+           }
 
-      IntEngMaskBlt(
-         SurfObj,
-         SourceGlyphSurf,
-         dc->CombinedClip,
-         XlateObj,
-         XlateObj2,
-         &DestRect,
-         &SourcePoint,
-         (PPOINTL)&MaskRect,
-         &BrushFgInst.BrushObject,
-         &BrushOrigin);
+          case ft_glyph_format_outline:
+            ft_bitmap.width = width;
+            ft_bitmap.rows = height;
+            ft_bitmap.pitch = pitch;
+            ft_bitmap.pixel_mode = ft_pixel_mode_mono;
+            ft_bitmap.buffer = pvBuf;
 
-      EngUnlockSurface(SourceGlyphSurf);
-      EngDeleteSurface((HSURF)HSourceGlyph);
+            IntLockFreeType;
+            if(needsTransform)
+            {
+               FT_Outline_Transform(&ft_face->glyph->outline, &transMat);
+           }
+            FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
+            /* Note: FreeType will only set 'black' bits for us. */
+            RtlZeroMemory(pvBuf, needed);
+            FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
+            IntUnLockFreeType;
+            break;
 
-      if (DoBreak)
-      {
-         break;
-      }
+          default:
+            DPRINT1("loaded glyph format %x\n", ft_face->glyph->format);
+            return GDI_ERROR;
+        }
+        break;
 
-      if (NULL == Dx)
-      {
-         TextLeft += realglyph->advance.x >> 10;
-//         DbgPrint("new TextLeft: %d\n", TextLeft);
-      }
-      else
+    case GGO_GRAY2_BITMAP:
+    case GGO_GRAY4_BITMAP:
+    case GGO_GRAY8_BITMAP:
       {
-         TextLeft += Dx[i] << 6;
-//         DbgPrint("new TextLeft2: %d\n", TextLeft);
-      }
-      previous = glyph_index;
+        unsigned int mult, row, col;
+        BYTE *start, *ptr;
 
-      String++;
-   }
+        width = gm.gmBlackBoxX;
+        height = gm.gmBlackBoxY;
+        pitch = (width + 3) / 4 * 4;
+        needed = pitch * height;
 
-   IntUnLockFreeType;
+        if(!pvBuf || !cjBuf) break;
 
-   EngDeleteXlate(XlateObj);
-   EngDeleteXlate(XlateObj2);
-   BITMAPOBJ_UnlockBitmap(BitmapObj);
-   if(TextObj != NULL)
-     TEXTOBJ_UnlockText(TextObj);
-   if (hBrushBg != NULL)
-   {
-      BRUSHOBJ_UnlockBrush(BrushBg);
-      NtGdiDeleteObject(hBrushBg);
-   }
-   BRUSHOBJ_UnlockBrush(BrushFg);
-   NtGdiDeleteObject(hBrushFg);
-   if (NULL != SafeString)
-   {
-      ExFreePool((void*)SafeString);
-   }
-   if (NULL != Dx)
-   {
-      ExFreePool(Dx);
-   }
-   DC_UnlockDc( dc );
+        switch(ft_face->glyph->format)
+        {
+          case ft_glyph_format_bitmap:
+          {
+             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
+             INT h = ft_face->glyph->bitmap.rows;
+             INT x;
+             while(h--)
+             {
+               for(x = 0; x < pitch; x++)
+               {
+                   if(x < ft_face->glyph->bitmap.width)
+                      dst[x] = (src[x / 8] & (1 << ( (7 - (x % 8))))) ? 0xff : 0;
+                   else
+                      dst[x] = 0;
+               }
+               src += ft_face->glyph->bitmap.pitch;
+               dst += pitch;
+             }
+             return needed;
+          }
+          case ft_glyph_format_outline:
+          {
+             ft_bitmap.width = width;
+             ft_bitmap.rows = height;
+             ft_bitmap.pitch = pitch;
+             ft_bitmap.pixel_mode = ft_pixel_mode_grays;
+             ft_bitmap.buffer = pvBuf;
 
-   return TRUE;
+            IntLockFreeType;
+            if (needsTransform)
+            {
+               FT_Outline_Transform(&ft_face->glyph->outline, &transMat);
+            }
+            FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
+            RtlZeroMemory(ft_bitmap.buffer, cjBuf);
+            FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
+            IntUnLockFreeType;
 
-fail:
-   if ( XlateObj2 != NULL )
-      EngDeleteXlate(XlateObj2);
-   if ( XlateObj != NULL )
-      EngDeleteXlate(XlateObj);
-   if(TextObj != NULL)
-     TEXTOBJ_UnlockText(TextObj);
-   if (BitmapObj != NULL)
-     BITMAPOBJ_UnlockBitmap(BitmapObj);
-   if (hBrushBg != NULL)
-   {
-      BRUSHOBJ_UnlockBrush(BrushBg);
-      NtGdiDeleteObject(hBrushBg);
-   }
-   if (hBrushFg != NULL)
-   {
-      BRUSHOBJ_UnlockBrush(BrushFg);
-      NtGdiDeleteObject(hBrushFg);
-   }
-   if (NULL != SafeString)
-   {
-      ExFreePool((void*)SafeString);
-   }
-   if (NULL != Dx)
-   {
-      ExFreePool(Dx);
-   }
-   DC_UnlockDc(dc);
+            if (iFormat == GGO_GRAY2_BITMAP)
+                mult = 4;
+            else if (iFormat == GGO_GRAY4_BITMAP)
+                mult = 16;
+            else if (iFormat == GGO_GRAY8_BITMAP)
+                mult = 64;
+            else
+            {
+                return GDI_ERROR;
+            }
+          }
+          default:
+            DPRINT1("loaded glyph format %x\n", ft_face->glyph->format);
+            return GDI_ERROR;
+        }
+        start = pvBuf;
+        for(row = 0; row < height; row++)
+        {
+            ptr = start;
+            for(col = 0; col < width; col++, ptr++)
+            {
+                *ptr = (((int)*ptr) * mult + 128) / 256;
+            }
+            start += pitch;
+        }
+        break;
+      }
 
-   return FALSE;
-}
+    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;
 
- /*
- * @implemented
- */
-BOOL
-STDCALL
-NtGdiGetCharABCWidthsW(
-    IN HDC hDC,
-    IN UINT FirstChar,
-    IN ULONG Count,
-    IN OPTIONAL PWCHAR pwch,
-    IN FLONG fl,
-    OUT PVOID Buffer)
-{
-   LPABC SafeBuff;
-   LPABCFLOAT SafeBuffF = NULL;
-   PDC dc;
-   PDC_ATTR Dc_Attr;
-   PTEXTOBJ TextObj;
-   PFONTGDI FontGDI;
-   FT_Face face;
-   FT_CharMap charmap, found = NULL;
-   UINT i, glyph_index, BufferSize;
-   HFONT hFont = 0;
-   NTSTATUS Status = STATUS_SUCCESS;
-
-   if(pwch)
-   {
-     _SEH_TRY
-     {
-       ProbeForRead(pwch,
-            sizeof(PWSTR),
-                       1);
-     }
-     _SEH_HANDLE
-     {
-      Status = _SEH_GetExceptionCode();
-     }
-     _SEH_END;
-   }
-   if (!NT_SUCCESS(Status))
-   {
-      SetLastWin32Error(Status);
-      return FALSE;
-   }
-
-   BufferSize = Count * sizeof(ABC); // Same size!
-   SafeBuff = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT);
-   if (!fl) SafeBuffF = (LPABCFLOAT) SafeBuff;
-   if (SafeBuff == NULL)
-   {
-      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-      return FALSE;
-   }
-
-   dc = DC_LockDc(hDC);
-   if (dc == NULL)
-   {
-      ExFreePool(SafeBuff);
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return FALSE;
-   }
-   Dc_Attr = dc->pDc_Attr;
-   if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
-   hFont = Dc_Attr->hlfntNew;
-   TextObj = TEXTOBJ_LockText(hFont);
-   DC_UnlockDc(dc);
+        if(cjBuf == 0) pvBuf = NULL; /* This is okay, need cjBuf to allocate. */
 
-   if (TextObj == NULL)
-   {
-      ExFreePool(SafeBuff);
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return FALSE;
-   }
+        IntLockFreeType;
+        if (needsTransform && pvBuf) FT_Outline_Transform(outline, &transMat);
 
-   FontGDI = ObjToGDI(TextObj->Font, FONT);
+        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_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));
 
-   face = FontGDI->face;
-   if (face->charmap == NULL)
-   {
-      for (i = 0; i < face->num_charmaps; i++)
-      {
-         charmap = face->charmaps[i];
-         if (charmap->encoding != 0)
-         {
-            found = charmap;
-            break;
-         }
+                /* 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 (!found)
+    case GGO_BEZIER:
       {
-         DPRINT1("WARNING: Could not find desired charmap!\n");
-         ExFreePool(SafeBuff);
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
-         return FALSE;
-      }
-
-      IntLockFreeType;
-      FT_Set_Charmap(face, found);
-      IntUnLockFreeType;
-   }
+        /* 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
 
-   IntLockFreeType;
-   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));
+           A quadratic Beizer has the form:
+           p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
 
-   for (i = FirstChar; i < FirstChar+Count; i++)
-   {
-      int adv, lsb, bbx, left, right;
+           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
+         */
 
-      if (pwch)
-      {
-         if (fl & GCABCW_INDICES)
-          glyph_index = pwch[i - FirstChar];
-         else
-          glyph_index = FT_Get_Char_Index(face, pwch[i - FirstChar]);
-      }
-      else
-      {
-         if (fl & GCABCW_INDICES)
-             glyph_index = i;
-         else
-             glyph_index = FT_Get_Char_Index(face, i);
-      }
-      FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
+        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;
 
-      left = (INT)face->glyph->metrics.horiBearingX  & -64;
-      right = (INT)((face->glyph->metrics.horiBearingX + face->glyph->metrics.width) + 63) & -64;
-      adv  = (face->glyph->advance.x + 32) >> 6;
+        if (needsTransform && pvBuf)
+          {
+            IntLockFreeType;
+            FT_Outline_Transform(outline, &transMat);
+            IntUnLockFreeType;
+          }
 
-//      int test = (INT)(face->glyph->metrics.horiAdvance + 63) >> 6;
-//      DPRINT1("Advance Wine %d and Advance Ros %d\n",test, adv ); /* It's the same!*/
+        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 */
 
-      lsb = left >> 6;
-      bbx = (right - left) >> 6;
-/*
-      DPRINT1("lsb %d and bbx %d\n", lsb, bbx );
- */
-      if (!fl)
-      {
-        SafeBuffF[i - FirstChar].abcfA = (FLOAT) lsb;
-        SafeBuffF[i - FirstChar].abcfB = (FLOAT) bbx;
-        SafeBuffF[i - FirstChar].abcfC = (FLOAT) (adv - lsb - bbx);
-      }
-      else
-      {
-        SafeBuff[i - FirstChar].abcA = lsb;
-        SafeBuff[i - FirstChar].abcB = bbx;
-        SafeBuff[i - FirstChar].abcC = adv - lsb - bbx;
-      }
-   }
-   IntUnLockFreeType;
-   TEXTOBJ_UnlockText(TextObj);
-   Status = MmCopyToCaller(Buffer, SafeBuff, BufferSize);
-   if (! NT_SUCCESS(Status))
-     {
-       SetLastNtError(Status);
-       ExFreePool(SafeBuff);
-       return FALSE;
-     }
-   ExFreePool(SafeBuff);
-   DPRINT("NtGdiGetCharABCWidths Worked!\n");
-   return TRUE;
-}
-
- /*
- * @implemented
- */
-BOOL
-STDCALL
-NtGdiGetCharWidthW(
-    IN HDC hDC,
-    IN UINT FirstChar,
-    IN UINT Count,
-    IN OPTIONAL PWCHAR pwc,
-    IN FLONG fl,
-    OUT PVOID Buffer)
-{
-   NTSTATUS Status = STATUS_SUCCESS;
-   LPINT SafeBuff;
-   PFLOAT SafeBuffF = NULL;
-   PDC dc;
-   PDC_ATTR Dc_Attr;
-   PTEXTOBJ TextObj;
-   PFONTGDI FontGDI;
-   FT_Face face;
-   FT_CharMap charmap, found = NULL;
-   UINT i, glyph_index, BufferSize;
-   HFONT hFont = 0;
-
-   if(pwc)
-   {
-     _SEH_TRY
-     {
-       ProbeForRead(pwc,
-           sizeof(PWSTR),
-                      1);
-     }
-     _SEH_HANDLE
-     {
-      Status = _SEH_GetExceptionCode();
-     }
-     _SEH_END;
-   }
-   if (!NT_SUCCESS(Status))
-   {
-      SetLastWin32Error(Status);
-      return FALSE;
-   }
-
-   BufferSize = Count * sizeof(INT); // Same size!
-   SafeBuff = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT);
-   if (!fl) SafeBuffF = (PFLOAT) SafeBuff;
-   if (SafeBuff == NULL)
-   {
-      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-      return FALSE;
-   }
-
-   dc = DC_LockDc(hDC);
-   if (dc == NULL)
-   {
-      ExFreePool(SafeBuff);
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return FALSE;
-   }
-   Dc_Attr = dc->pDc_Attr;
-   if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
-   hFont = Dc_Attr->hlfntNew;
-   TextObj = TEXTOBJ_LockText(hFont);
-   DC_UnlockDc(dc);
-
-   if (TextObj == NULL)
-   {
-      ExFreePool(SafeBuff);
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return FALSE;
-   }
-
-   FontGDI = ObjToGDI(TextObj->Font, FONT);
-
-   face = FontGDI->face;
-   if (face->charmap == NULL)
-   {
-      for (i = 0; i < face->num_charmaps; i++)
-      {
-         charmap = face->charmaps[i];
-         if (charmap->encoding != 0)
-         {
-            found = charmap;
-            break;
-         }
-      }
-
-      if (!found)
-      {
-         DPRINT1("WARNING: Could not find desired charmap!\n");
-         ExFreePool(SafeBuff);
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
-         return FALSE;
-      }
-
-      IntLockFreeType;
-      FT_Set_Charmap(face, found);
-      IntUnLockFreeType;
-   }
-
-   IntLockFreeType;
-   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));
-
-   for (i = FirstChar; i < FirstChar+Count; i++)
-   {
-      if (pwc)
-      {
-         if (fl & GCW_INDICES)
-          glyph_index = pwc[i - FirstChar];
-         else
-          glyph_index = FT_Get_Char_Index(face, pwc[i - FirstChar]);
-      }
-      else
-      {
-         if (fl & GCW_INDICES)
-             glyph_index = i;
-         else
-             glyph_index = FT_Get_Char_Index(face, i);
-      }
-      FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
-      if (!fl)
-        SafeBuffF[i - FirstChar] = (FLOAT) ((face->glyph->advance.x + 32) >> 6);
-      else
-        SafeBuff[i - FirstChar] = (face->glyph->advance.x + 32) >> 6;
-   }
-   IntUnLockFreeType;
-   TEXTOBJ_UnlockText(TextObj);
-   MmCopyToCaller(Buffer, SafeBuff, BufferSize);
-   ExFreePool(SafeBuff);
-   return TRUE;
-}
-
-
- /*
- * @implemented
- */
-DWORD
-STDCALL
-NtGdiGetGlyphIndicesW(
-    IN HDC hdc,
-    IN OPTIONAL LPWSTR UnSafepwc,
-    IN INT cwc,
-    OUT OPTIONAL LPWORD UnSafepgi,
-    IN DWORD iMode)
-{
-  PDC dc;
-  PDC_ATTR Dc_Attr;
-  PTEXTOBJ TextObj;
-  PFONTGDI FontGDI;
-  HFONT hFont = 0;
-  NTSTATUS Status = STATUS_SUCCESS;
-  OUTLINETEXTMETRICW *potm;
-  INT i;
-  FT_Face face;
-  WCHAR DefChar = 0xffff;
-  PWSTR Buffer = NULL;
-  ULONG Size;
-
-  if ((!UnSafepwc) && (!UnSafepgi)) return cwc;
-
-  dc = DC_LockDc(hdc);
-  if (!dc)
-   {
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return GDI_ERROR;
-   }
-  Dc_Attr = dc->pDc_Attr;
-  if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
-  hFont = Dc_Attr->hlfntNew;
-  TextObj = TEXTOBJ_LockText(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)
-     {
-        Status = ERROR_NOT_ENOUGH_MEMORY;
-        goto ErrorRet;
-     }
-     IntGetOutlineTextMetrics(FontGDI, Size, potm);
-     DefChar = potm->otmTextMetrics.tmDefaultChar; // May need this.
-     ExFreePool(potm);
-  }
-
-  _SEH_TRY
-  {
-    ProbeForRead(UnSafepwc,
-             sizeof(PWSTR),
-                         1);
-  }
-  _SEH_HANDLE
-  {
-    Status = _SEH_GetExceptionCode();
-  }
-  _SEH_END;
-
-  if (!NT_SUCCESS(Status)) goto ErrorRet;
-
-  IntLockFreeType;
-  face = FontGDI->face;
-
-  for (i = 0; i < cwc; i++)
-  {
-      Buffer[i] = FT_Get_Char_Index(face, UnSafepwc[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;
-
-  _SEH_TRY
-  {
-    ProbeForWrite(UnSafepgi,
-               sizeof(WORD),
-                          1);
-    RtlCopyMemory(UnSafepgi,
-                     Buffer,
-            cwc*sizeof(WORD));
-  }
-  _SEH_HANDLE
-  {
-    Status = _SEH_GetExceptionCode();
-  }
-  _SEH_END;
-
-ErrorRet:
-  ExFreePoolWithTag(Buffer, TAG_GDITEXT);
-  if (NT_SUCCESS(Status)) return cwc;
-  SetLastWin32Error(Status);
-  return GDI_ERROR;
-}
-
-static
-void
-FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
-{
-    pt->x.value = vec->x >> 6;
-    pt->x.fract = (vec->x & 0x3f) << 10;
-    pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
-    pt->y.value = vec->y >> 6;
-    pt->y.fract = (vec->y & 0x3f) << 10;
-    pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
-    return;
-}
+                      /* 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;
+        }
+        break;
+      }
 
-/*
-   This function builds an FT_Fixed from a float. It puts the integer part
-   in the highest 16 bits and the decimal part in the lowest 16 bits of the FT_Fixed.
-   It fails if the integer part of the float number is greater than SHORT_MAX.
-*/
-static __inline FT_Fixed FT_FixedFromFloat(float f)
-{
-       short value = f;
-       unsigned short fract = (f - value) * 0xFFFF;
-       return (FT_Fixed)((long)value << 16 | (unsigned long)fract);
-}
+    default:
+        DPRINT1("Unsupported format %d\n", iFormat);
+        return GDI_ERROR;
+    }
 
-/*
-   This function builds an FT_Fixed from a FIXED. It simply put f.value
-   in the highest 16 bits and f.fract in the lowest 16 bits of the FT_Fixed.
-*/
-static __inline FT_Fixed FT_FixedFromFIXED(FIXED f)
-{
-       return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract);
+  DPRINT("ftGdiGetGlyphOutline END and needed %d\n", needed);
+  return needed;
 }
 
-/*
- * Based on WineEngGetGlyphOutline
- *
- */
-ULONG
+BOOL
 FASTCALL
-ftGdiGetGlyphOutline(
-    PDC dc,
-    WCHAR wch,
-    UINT iFormat,
-    LPGLYPHMETRICS pgm,
-    ULONG cjBuf,
-    PVOID pvBuf,
-    LPMAT2 pmat2,
-    BOOL bIgnoreRotation)
+TextIntGetTextExtentPoint(PDC dc,
+                          PTEXTOBJ TextObj,
+                          LPCWSTR String,
+                          int Count,
+                          int MaxExtent,
+                          LPINT Fit,
+                          LPINT Dx,
+                          LPSIZE Size)
 {
-  static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
-  PDC_ATTR Dc_Attr;
-  PTEXTOBJ TextObj;
   PFONTGDI FontGDI;
-  HFONT hFont = 0;
-  GLYPHMETRICS gm;
-  ULONG Size;
-  FT_Face ft_face;
-  FT_UInt glyph_index;
-  DWORD width, height, pitch, needed = 0;
-  FT_Bitmap ft_bitmap;
-  FT_Error error;
-  INT left, right, top = 0, bottom = 0;
-  FT_Angle angle = 0;
-  FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
-  FLOAT eM11, widthRatio = 1.0;
-  FT_Matrix transMat = identityMat;
-  BOOL needsTransform = FALSE;
-  INT orientation;
-  LONG aveWidth;
-  INT adv, lsb, bbx; /* These three hold to widths of the unrotated chars */
-  OUTLINETEXTMETRICW *potm;
-  int n = 0;
-  FT_CharMap found = 0, charmap;
-  XFORM xForm;
-
-  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;
-  
-  MatrixS2XForm(&xForm, &dc->DcLevel.mxWorldToDevice);
-  eM11 = xForm.eM11;
-  
-  hFont = Dc_Attr->hlfntNew;
-  TextObj = TEXTOBJ_LockText(hFont);
+  FT_Face face;
+  FT_GlyphSlot glyph;
+  FT_Glyph realglyph;
+  INT error, n, glyph_index, i, previous;
+  ULONGLONG TotalWidth = 0;
+  FT_CharMap charmap, found = NULL;
+  BOOL use_kerning;
+  FT_Render_Mode RenderMode;
+  BOOLEAN Render;
 
-  if (!TextObj)
-   {
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return GDI_ERROR;
-   }
   FontGDI = ObjToGDI(TextObj->Font, FONT);
-  ft_face = FontGDI->face;
-
-  aveWidth = FT_IS_SCALABLE(ft_face) ? TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth: 0;
-  orientation = FT_IS_SCALABLE(ft_face) ? TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation: 0;
 
-  Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
-  potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
-  if (!potm)
+  face = FontGDI->face;
+  if (NULL != Fit)
     {
-      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-      TEXTOBJ_UnlockText(TextObj);
-      return GDI_ERROR;
+      *Fit = 0;
     }
-  IntGetOutlineTextMetrics(FontGDI, Size, potm);
 
   IntLockFreeType;
-
-  /* During testing, I never saw this used. In here just incase.*/
-  if (ft_face->charmap == NULL)
+  if (face->charmap == NULL)
     {
       DPRINT("WARNING: No charmap selected!\n");
-      DPRINT("This font face has %d charmaps\n", ft_face->num_charmaps);
+      DPRINT("This font face has %d charmaps\n", face->num_charmaps);
 
-      for (n = 0; n < ft_face->num_charmaps; n++)
-      {
-         charmap = ft_face->charmaps[n];
-         DPRINT("found charmap encoding: %u\n", charmap->encoding);
-         if (charmap->encoding != 0)
-         {
-            found = charmap;
-            break;
-         }
-      }
-      if (!found)
-      {
-         DPRINT1("WARNING: Could not find desired charmap!\n");
-      }
-      error = FT_Set_Charmap(ft_face, found);
+      for (n = 0; n < face->num_charmaps; n++)
+       {
+         charmap = face->charmaps[n];
+         DPRINT("found charmap encoding: %u\n", charmap->encoding);
+         if (charmap->encoding != 0)
+           {
+             found = charmap;
+             break;
+           }
+       }
+
+      if (! found)
+       {
+         DPRINT1("WARNING: Could not find desired charmap!\n");
+       }
+
+      error = FT_Set_Charmap(face, found);
       if (error)
-        {
-           DPRINT1("WARNING: Could not set the charmap!\n");
-        }
+       {
+         DPRINT1("WARNING: Could not set the charmap!\n");
+       }
     }
 
-//  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));
+  Render = IntIsFontRenderingEnabled();
+  if (Render)
+    RenderMode = IntGetFontRenderMode(&TextObj->logfont.elfEnumLogfontEx.elfLogFont);
+  else
+    RenderMode = FT_RENDER_MODE_MONO;
 
-  TEXTOBJ_UnlockText(TextObj);
+  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));
+  if (error)
+    {
+      DPRINT1("Error in setting pixel sizes: %u\n", error);
+    }
 
-  if (iFormat & GGO_GLYPH_INDEX)
+  use_kerning = FT_HAS_KERNING(face);
+  previous = 0;
+
+  for (i = 0; i < Count; i++)
     {
-       glyph_index = wch;
-       iFormat &= ~GGO_GLYPH_INDEX;
+      glyph_index = FT_Get_Char_Index(face, *String);
+      if (!(realglyph = ftGdiGlyphCacheGet(face, glyph_index,
+          TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)))
+        {
+          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);
+              break;
+            }
+
+          glyph = face->glyph;
+          realglyph = ftGdiGlyphCacheSet(face, glyph_index,
+             TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight, glyph, RenderMode);
+          if (!realglyph)
+            {
+              DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index);
+              break;
+            }
+        }
+
+      /* retrieve kerning distance */
+      if (use_kerning && previous && glyph_index)
+       {
+         FT_Vector delta;
+         FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
+         TotalWidth += delta.x;
+       }
+
+      TotalWidth += realglyph->advance.x >> 10;
+
+      if (((TotalWidth + 32) >> 6) <= MaxExtent && NULL != Fit)
+       {
+         *Fit = i + 1;
+       }
+      if (NULL != Dx)
+       {
+         Dx[i] = (TotalWidth + 32) >> 6;
+       }
+
+      previous = glyph_index;
+      String++;
     }
-  else  glyph_index = FT_Get_Char_Index(ft_face, wch);
+  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);
+
+  return TRUE;
+}
+
+DWORD
+FASTCALL
+IntGdiGetCharSet(HDC  hDC)
+{
+  UINT cp = 0;
+  CHARSETINFO csi;
+  DWORD charset = NtGdiGetTextCharsetInfo(hDC,NULL,0);
+  if (IntTranslateCharsetInfo(&charset, &csi, TCI_SRCCHARSET))
+      cp = csi.ciACP;
+  else
+  {
+      switch(charset)
+      {
+         case OEM_CHARSET:
+           cp = 1;
+           break;
+         case DEFAULT_CHARSET:
+           cp = 0;
+           break;
+         default:
+           DPRINT1("Can't find codepage for charset %d\n", charset);
+           break;
+       }
+  }
+  DPRINT("charset %d => cp %d\n", charset, LOWORD(cp));
+  return (MAKELONG(cp, charset));
+}
 
-  if (orientation || (iFormat != GGO_METRICS && iFormat != GGO_BITMAP) || aveWidth || pmat2)
-        load_flags |= FT_LOAD_NO_BITMAP;
+INT
+FASTCALL
+ftGdiGetTextCharsetInfo(
+    PDC Dc,
+    LPFONTSIGNATURE lpSig,
+    DWORD dwFlags)
+{
+  PDC_ATTR Dc_Attr;
+  UINT Ret = DEFAULT_CHARSET, i = 0, fs_fsCsb0 = 0;
+  HFONT hFont;
+  PTEXTOBJ TextObj;
+  PFONTGDI FontGdi;
+  FONTSIGNATURE fs;
+  TT_OS2 *pOS2;
+  FT_Face Face;
 
-  if (iFormat & GGO_UNHINTED)
-    {
-       load_flags |= FT_LOAD_NO_HINTING;
-       iFormat &= ~GGO_UNHINTED;
-    }
+  Dc_Attr = Dc->pDc_Attr;
+  if(!Dc_Attr) Dc_Attr = &Dc->Dc_Attr;
+  hFont = Dc_Attr->hlfntNew;
+  TextObj = TEXTOBJ_LockText(hFont);
 
-  error = FT_Load_Glyph(ft_face, glyph_index, load_flags);
-  if (error)
+  if ( TextObj == NULL)
     {
-         DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
-        IntUnLockFreeType;
-        if (potm) ExFreePoolWithTag(potm, TAG_GDITEXT);
-        return GDI_ERROR;
+         SetLastWin32Error(ERROR_INVALID_HANDLE);
+         return Ret;
     }
+  FontGdi = ObjToGDI(TextObj->Font, FONT);
+  Face = FontGdi->face;
+  TEXTOBJ_UnlockText(TextObj);
+  IntLockFreeType;
+  pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
   IntUnLockFreeType;
-
-  if (aveWidth && potm)
+  memset(&fs, 0, sizeof(FONTSIGNATURE));
+  if (NULL != pOS2)
     {
-       widthRatio = (FLOAT)aveWidth * eM11 /
-                                 (FLOAT) potm->otmTextMetrics.tmAveCharWidth;
-    }
-
-  left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64;
-  right = (INT)((ft_face->glyph->metrics.horiBearingX +
-                    ft_face->glyph->metrics.width) * widthRatio + 63) & -64;
+      fs.fsCsb[0] = pOS2->ulCodePageRange1;
+      fs.fsCsb[1] = pOS2->ulCodePageRange2;
+      fs.fsUsb[0] = pOS2->ulUnicodeRange1;
+      fs.fsUsb[1] = pOS2->ulUnicodeRange2;
+      fs.fsUsb[2] = pOS2->ulUnicodeRange3;
+      fs.fsUsb[3] = pOS2->ulUnicodeRange4;
+      fs_fsCsb0   = pOS2->ulCodePageRange1;
+      if (pOS2->version == 0)
+        {
+          FT_UInt dummy;
 
-  adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6;
-  lsb = left >> 6;
-  bbx = (right - left) >> 6;
+          if(FT_Get_First_Char( Face, &dummy ) < 0x100)
+                fs_fsCsb0 |= 1;
+          else
+                fs_fsCsb0 |= 1L << 31;
+        }
+    }
+  DPRINT("Csb 1=%x  0=%x\n", fs.fsCsb[1],fs.fsCsb[0]);
+  if (lpSig)
+  {
+     RtlCopyMemory(lpSig, &fs, sizeof(FONTSIGNATURE));
+  }
+  if (0 == fs_fsCsb0)
+    { /* let's see if we can find any interesting cmaps */
+       for (i = 0; i < Face->num_charmaps; i++)
+          {
+              switch (Face->charmaps[i]->encoding)
+                {
+                  case ft_encoding_unicode:
+                  case ft_encoding_apple_roman:
+                    fs_fsCsb0 |= 1;
+                    break;
+                  case ft_encoding_symbol:
+                    fs_fsCsb0 |= 1L << 31;
+                    break;
+                  default:
+                    break;
+                }
+          }
+    }
+  while (0 == (fs_fsCsb0 >> i & 0x0001) && i < MAXTCIINDEX)
+       {
+          i++;
+       }
+  Ret = FontTci[i].ciCharset;
+  DPRINT("CharSet %d\n",Ret);
+  return Ret;
+}
 
-  DPRINT("Advance = %d, lsb = %d, bbx = %d\n",adv, lsb, bbx);
 
-  IntLockFreeType;
+DWORD
+FASTCALL
+ftGetFontUnicodeRanges(PFONTGDI Font, PGLYPHSET glyphset)
+{
+    DWORD size = 0;
+    DWORD num_ranges = 0;
+    FT_Face face = Font->face;
 
-   /* Scaling transform */
-  if (aveWidth)
+    if (face->charmap->encoding == FT_ENCODING_UNICODE)
     {
-        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);
-        needsTransform = TRUE;
-    }
+        FT_UInt glyph_code = 0;
+        FT_ULong char_code, char_code_prev;
 
-    /* Slant transform */
-  if (potm->otmTextMetrics.tmItalic)
-    {
-        FT_Matrix slantMat;
-        DPRINT("Slant Trans!\n");
-        slantMat.xx = (1 << 16);
-        slantMat.xy = ((1 << 16) >> 2);
-        slantMat.yx = 0;
-        slantMat.yy = (1 << 16);
-        FT_Matrix_Multiply(&slantMat, &transMat);
-        needsTransform = TRUE;
-    }
+        char_code_prev = char_code = FT_Get_First_Char(face, &glyph_code);
 
-    /* Rotation transform */
-  if (orientation)
-    {
-        FT_Matrix rotationMat;
-        FT_Vector vecAngle;
-        DPRINT("Rotation Trans!\n");
-        angle = FT_FixedFromFloat((float)orientation / 10.0);
-        FT_Vector_Unit(&vecAngle, angle);
-        rotationMat.xx = vecAngle.x;
-        rotationMat.xy = -vecAngle.y;
-        rotationMat.yx = -rotationMat.xy;
-        rotationMat.yy = rotationMat.xx;
-        FT_Matrix_Multiply(&rotationMat, &transMat);
-        needsTransform = TRUE;
-    }
+        DPRINT("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
+               face->num_glyphs, glyph_code, char_code);
 
-    /* Extra transformation specified by caller */
-  if (pmat2)
-    {
-        FT_Matrix extraMat;
-        DPRINT("MAT2 Matrix Trans!\n");
-        extraMat.xx = FT_FixedFromFIXED(pmat2->eM11);
-        extraMat.xy = FT_FixedFromFIXED(pmat2->eM21);
-        extraMat.yx = FT_FixedFromFIXED(pmat2->eM12);
-        extraMat.yy = FT_FixedFromFIXED(pmat2->eM22);
-        FT_Matrix_Multiply(&extraMat, &transMat);
-        needsTransform = TRUE;
-    }
+        if (!glyph_code) return 0;
 
-  if (potm) ExFreePoolWithTag(potm, TAG_GDITEXT); /* It looks like we are finished with potm ATM.*/
+        if (glyphset)
+        {
+            glyphset->ranges[0].wcLow = (USHORT)char_code;
+            glyphset->ranges[0].cGlyphs = 0;
+            glyphset->cGlyphsSupported = 0;
+        }
 
-  if (!needsTransform)
-    {
-        DPRINT("No Need to be Transformed!\n");
-        top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
-        bottom = (ft_face->glyph->metrics.horiBearingY -
-                  ft_face->glyph->metrics.height) & -64;
-        gm.gmCellIncX = adv;
-        gm.gmCellIncY = 0;
-    }
-  else
-    {
-        INT xc, yc;
-        FT_Vector vec;
-        for(xc = 0; xc < 2; xc++)
+        num_ranges = 1;
+        while (glyph_code)
         {
-          for(yc = 0; yc < 2; yc++)
+            if (char_code < char_code_prev)
             {
-                vec.x = (ft_face->glyph->metrics.horiBearingX +
-                  xc * ft_face->glyph->metrics.width);
-                vec.y = ft_face->glyph->metrics.horiBearingY -
-                  yc * ft_face->glyph->metrics.height;
-                DPRINT("Vec %ld,%ld\n", vec.x, vec.y);
-                FT_Vector_Transform(&vec, &transMat);
-                if(xc == 0 && yc == 0)
-                {
-                    left = right = vec.x;
-                    top = bottom = vec.y;
-                }
-                else
-                {
-                    if(vec.x < left) left = vec.x;
-                    else if(vec.x > right) right = vec.x;
-                    if(vec.y < bottom) bottom = vec.y;
-                    else if(vec.y > top) top = vec.y;
-                }
+                DPRINT1("expected increasing char code from FT_Get_Next_Char\n");
+                return 0;
             }
-        }
-        left = left & -64;
-        right = (right + 63) & -64;
-        bottom = bottom & -64;
-        top = (top + 63) & -64;
-
-        DPRINT("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
-        vec.x = ft_face->glyph->metrics.horiAdvance;
-        vec.y = 0;
-        FT_Vector_Transform(&vec, &transMat);
-        gm.gmCellIncX = (vec.x+63) >> 6;
-        gm.gmCellIncY = -((vec.y+63) >> 6);
-    }
-  gm.gmBlackBoxX = (right - left) >> 6;
-  gm.gmBlackBoxY = (top - bottom) >> 6;
-  gm.gmptGlyphOrigin.x = left >> 6;
-  gm.gmptGlyphOrigin.y = top >> 6;
-
-  DPRINT("CX %d CY %d BBX %d BBY %d GOX %d GOY %d\n",
-                           gm.gmCellIncX, gm.gmCellIncY,
-                           gm.gmBlackBoxX, gm.gmBlackBoxY,
-                           gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
-
-  IntUnLockFreeType;
-
-  if (pgm) RtlCopyMemory(pgm, &gm, sizeof(GLYPHMETRICS));    
-
-  if (iFormat == GGO_METRICS)
-    {
-        DPRINT("GGO_METRICS Exit!\n");
-        return 1; /* FIXME */
+            if (char_code - char_code_prev > 1)
+            {
+                num_ranges++;
+                if (glyphset)
+                {
+                    glyphset->ranges[num_ranges - 1].wcLow = (USHORT)char_code;
+                    glyphset->ranges[num_ranges - 1].cGlyphs = 1;
+                    glyphset->cGlyphsSupported++;
+                }
+            }
+            else if (glyphset)
+            {
+                glyphset->ranges[num_ranges - 1].cGlyphs++;
+                glyphset->cGlyphsSupported++;
+            }
+            char_code_prev = char_code;
+            char_code = FT_Get_Next_Char(face, char_code, &glyph_code);
+        }
     }
+    else
+        DPRINT1("encoding %u not supported\n", face->charmap->encoding);
 
-  if (ft_face->glyph->format != ft_glyph_format_outline && iFormat != GGO_BITMAP)
+    size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
+    if (glyphset)
     {
-        DPRINT1("loaded a bitmap\n");
-        return GDI_ERROR;
+        glyphset->cbThis = size;
+        glyphset->cRanges = num_ranges;
     }
+    return size;
+}
 
-  switch(iFormat)
-    {
-    case GGO_BITMAP:
-        width = gm.gmBlackBoxX;
-        height = gm.gmBlackBoxY;
-        pitch = ((width + 31) >> 5) << 2;
-        needed = pitch * height;
 
-        if(!pvBuf || !cjBuf) break;
+DWORD
+FASTCALL
+ftGetFontLanguageInfo(PDC Dc)
+{
+  PDC_ATTR Dc_Attr;
+  FONTSIGNATURE fontsig;
+  static const DWORD GCP_DBCS_MASK=0x003F0000,
+               GCP_DIACRITIC_MASK=0x00000000,
+               FLI_GLYPHS_MASK=0x00000000,
+               GCP_GLYPHSHAPE_MASK=0x00000040,
+               GCP_KASHIDA_MASK=0x00000000,
+               GCP_LIGATE_MASK=0x00000000,
+               GCP_USEKERNING_MASK=0x00000000,
+               GCP_REORDER_MASK=0x00000060;
 
-        switch(ft_face->glyph->format)
-        {
-          case ft_glyph_format_bitmap:
-           {
-             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
-             INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
-             INT h = ft_face->glyph->bitmap.rows;
-             while(h--)
-             {
-                RtlCopyMemory(dst, src, w);
-                src += ft_face->glyph->bitmap.pitch;
-                dst += pitch;
-             }
-             break;
-           }
+  DWORD result=0;
 
-          case ft_glyph_format_outline:
-            ft_bitmap.width = width;
-            ft_bitmap.rows = height;
-            ft_bitmap.pitch = pitch;
-            ft_bitmap.pixel_mode = ft_pixel_mode_mono;
-            ft_bitmap.buffer = pvBuf;
+  ftGdiGetTextCharsetInfo( Dc, &fontsig, 0 );
 
-            IntLockFreeType;
-            if(needsTransform)
-            {
-               FT_Outline_Transform(&ft_face->glyph->outline, &transMat);
-           }
-            FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
-            /* Note: FreeType will only set 'black' bits for us. */
-            RtlZeroMemory(pvBuf, needed);
-            FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
-            IntUnLockFreeType;
-            break;
+ /* We detect each flag we return using a bitmask on the Codepage Bitfields */
+  if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
+               result|=GCP_DBCS;
 
-          default:
-            DPRINT1("loaded glyph format %x\n", ft_face->glyph->format);
-            return GDI_ERROR;
-        }
-        break;
+  if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
+               result|=GCP_DIACRITIC;
 
-    case GGO_GRAY2_BITMAP:
-    case GGO_GRAY4_BITMAP:
-    case GGO_GRAY8_BITMAP:
-      {
-        unsigned int mult, row, col;
-        BYTE *start, *ptr;
+  if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
+               result|=FLI_GLYPHS;
 
-        width = gm.gmBlackBoxX;
-        height = gm.gmBlackBoxY;
-        pitch = (width + 3) / 4 * 4;
-        needed = pitch * height;
+  if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
+               result|=GCP_GLYPHSHAPE;
 
-        if(!pvBuf || !cjBuf) break;
+  if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
+               result|=GCP_KASHIDA;
 
-        switch(ft_face->glyph->format)
-        {
-          case ft_glyph_format_bitmap:
-          {
-             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
-             INT h = ft_face->glyph->bitmap.rows;
-             INT x;
-             while(h--)
-             {
-               for(x = 0; x < pitch; x++)
-               {
-                   if(x < ft_face->glyph->bitmap.width)
-                      dst[x] = (src[x / 8] & (1 << ( (7 - (x % 8))))) ? 0xff : 0;
-                   else
-                      dst[x] = 0;
-               }
-               src += ft_face->glyph->bitmap.pitch;
-               dst += pitch;
-             }
-             return needed;
-          }
-          case ft_glyph_format_outline:
-          {
-             ft_bitmap.width = width;
-             ft_bitmap.rows = height;
-             ft_bitmap.pitch = pitch;
-             ft_bitmap.pixel_mode = ft_pixel_mode_grays;
-             ft_bitmap.buffer = pvBuf;
+  if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
+               result|=GCP_LIGATE;
 
-            IntLockFreeType;
-            if (needsTransform)
-            {
-               FT_Outline_Transform(&ft_face->glyph->outline, &transMat);
-            }
-            FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
-            RtlZeroMemory(ft_bitmap.buffer, cjBuf);
-            FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
-            IntUnLockFreeType;
+  if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
+               result|=GCP_USEKERNING;
 
-            if (iFormat == GGO_GRAY2_BITMAP)
-                mult = 4;
-            else if (iFormat == GGO_GRAY4_BITMAP)
-                mult = 16;
-            else if (iFormat == GGO_GRAY8_BITMAP)
-                mult = 64;
-            else
-            {
-                return GDI_ERROR;
-            }
-          }
-          default:
-            DPRINT1("loaded glyph format %x\n", ft_face->glyph->format);
-            return GDI_ERROR;
-        }
-        start = pvBuf;
-        for(row = 0; row < height; row++)
-        {
-            ptr = start;
-            for(col = 0; col < width; col++, ptr++)
-            {
-                *ptr = (((int)*ptr) * mult + 128) / 256;
-            }
-            start += pitch;
-        }
-        break;
-      }
+  Dc_Attr = Dc->pDc_Attr;
+  if(!Dc_Attr) Dc_Attr = &Dc->Dc_Attr;
 
-    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;
+  /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
+  if ( Dc_Attr->lTextAlign & TA_RTLREADING )
+     if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
+                    result|=GCP_REORDER;
 
-        if(cjBuf == 0) pvBuf = NULL; /* This is okay, need cjBuf to allocate. */
+  return result;
+}
 
-        IntLockFreeType;
-        if (needsTransform && pvBuf) FT_Outline_Transform(outline, &transMat);
 
-        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_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));
+BOOL
+FASTCALL
+ftGdiGetTextMetricsW(
+    HDC hDC,
+    PTMW_INTERNAL ptmwi)
+{
+  PDC dc;
+  PDC_ATTR Dc_Attr;
+  PTEXTOBJ TextObj;
+  PFONTGDI FontGDI;
+  FT_Face Face;
+  TT_OS2 *pOS2;
+  TT_HoriHeader *pHori;
+  FT_WinFNT_HeaderRec Win;
+  ULONG Error;
+  NTSTATUS Status = STATUS_SUCCESS;
+
+  if (!ptmwi)
+  {
+    SetLastWin32Error(STATUS_INVALID_PARAMETER);
+    return FALSE;
+  }
+
+  if(!(dc = DC_LockDc(hDC)))
+  {
+    SetLastWin32Error(ERROR_INVALID_HANDLE);
+    return FALSE;
+  }
+  Dc_Attr = dc->pDc_Attr;
+  if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+  TextObj = TEXTOBJ_LockText(Dc_Attr->hlfntNew);
+  if (NULL != TextObj)
+    {
+      FontGDI = ObjToGDI(TextObj->Font, FONT);
+
+      Face = FontGDI->face;
+      IntLockFreeType;
+      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));
+      IntUnLockFreeType;
+      if (0 != Error)
+       {
+          DPRINT1("Error in setting pixel sizes: %u\n", Error);
+          Status = STATUS_UNSUCCESSFUL;
+       }
+      else
+       {
+          Status = STATUS_SUCCESS;
 
-                /* 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)
+          IntLockFreeType;
+          pOS2 = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_os2);
+          if (NULL == pOS2)
             {
-              /* add closing pt for bezier */
-              if(pvBuf)
-                FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
-              cpfx++;
-              point++;
+              DPRINT1("Can't find OS/2 table - not TT font?\n");
+              Status = STATUS_INTERNAL_ERROR;
             }
-            if(pvBuf)
+
+          pHori = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_hhea);
+          if (NULL == pHori)
             {
-               ppc->wType = type;
-               ppc->cpfx = cpfx;
+              DPRINT1("Can't find HHEA table - not TT font?\n");
+              Status = STATUS_INTERNAL_ERROR;
             }
-            needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
-          }
-          if(pvBuf) pph->cb = needed - pph_start;
-        }
-        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
-         */
+          Error = FT_Get_WinFNT_Header(FontGDI->face , &Win);
 
-        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;
+          IntUnLockFreeType;
 
-        if (needsTransform && pvBuf)
+          if (NT_SUCCESS(Status))
           {
-            IntLockFreeType;
-            FT_Outline_Transform(outline, &transMat);
-            IntUnLockFreeType;
+              if (!(FontGDI->flRealizedType & FDM_TYPE_TEXT_METRIC))
+              {
+                 FillTM(&FontGDI->TextMetric, FontGDI, pOS2, pHori, !Error ? &Win : 0);
+                 FontGDI->flRealizedType |= FDM_TYPE_TEXT_METRIC;
+              }
+
+              RtlCopyMemory(&ptmwi->TextMetric, &FontGDI->TextMetric, sizeof(TEXTMETRICW));
+              /* FIXME: Fill Diff member */
+              RtlZeroMemory(&ptmwi->Diff, sizeof(ptmwi->Diff));
           }
+       }
+      TEXTOBJ_UnlockText(TextObj);
+    }
+  else
+  {
+     Status = STATUS_INVALID_HANDLE;
+  }
+  DC_UnlockDc(dc);
 
-        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 */
+  if (!NT_SUCCESS(Status))
+  {
+     SetLastNtError(Status);
+     return FALSE;
+  }
+  return TRUE;
+}
 
-                      /* 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;
+
+DWORD
+FASTCALL
+ftGdiGetFontData(
+   PFONTGDI FontGdi,
+   DWORD Table,
+   DWORD Offset,
+   PVOID Buffer,
+   DWORD Size)
+{
+  DWORD Result = GDI_ERROR;
+
+  IntLockFreeType;
+
+  if (FT_IS_SFNT(FontGdi->face))
+  {
+     if (Table)
+        Table = Table >> 24 | Table << 24 | (Table >> 8 & 0xFF00) |
+                  (Table << 8 & 0xFF0000);
+
+     if (!Buffer) Size = 0;
+
+     if (Buffer && Size)
+     {
+        FT_Error Error;
+        FT_ULong Needed = 0;
+
+        Error = FT_Load_Sfnt_Table(FontGdi->face, Table, Offset, NULL, &Needed);
+
+        if( !Error && Needed < Size) Size = Needed;
+     }
+     if (!FT_Load_Sfnt_Table(FontGdi->face, Table, Offset, Buffer, &Size))
+        Result = Size;
+  }
+
+  IntUnLockFreeType;
+
+  return Result;
+}
+
+static UINT FASTCALL
+GetFontScore(LOGFONTW *LogFont, PUNICODE_STRING FaceName, PFONTGDI FontGDI)
+{
+  ANSI_STRING EntryFaceNameA;
+  UNICODE_STRING EntryFaceNameW;
+  unsigned Size;
+  OUTLINETEXTMETRICW *Otm;
+  LONG WeightDiff;
+  NTSTATUS Status;
+  UINT Score = 1;
+
+  RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name);
+  Status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
+  if (NT_SUCCESS(Status))
+    {
+      if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length)
+        {
+          EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR);
+          EntryFaceNameW.Buffer[LF_FACESIZE - 1] = L'\0';
         }
-        break;
-      }
+      if (0 == RtlCompareUnicodeString(FaceName, &EntryFaceNameW, TRUE))
+        {
+          Score += 49;
+        }
+      RtlFreeUnicodeString(&EntryFaceNameW);
+    }
 
-    default:
-        DPRINT1("Unsupported format %d\n", iFormat);
-        return GDI_ERROR;
+  Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
+  Otm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
+  if (NULL == Otm)
+    {
+      return Score;
+    }
+  IntGetOutlineTextMetrics(FontGDI, Size, Otm);
+
+  if ((0 != LogFont->lfItalic && 0 != Otm->otmTextMetrics.tmItalic) ||
+      (0 == LogFont->lfItalic && 0 == Otm->otmTextMetrics.tmItalic))
+    {
+      Score += 25;
+    }
+  if (LogFont->lfWeight != FW_DONTCARE)
+  {
+    if (LogFont->lfWeight < Otm->otmTextMetrics.tmWeight)
+    {
+      WeightDiff = Otm->otmTextMetrics.tmWeight - LogFont->lfWeight;
+    }
+    else
+    {
+      WeightDiff = LogFont->lfWeight - Otm->otmTextMetrics.tmWeight;
     }
+    Score += (1000 - WeightDiff) / (1000 / 25);
+  }
+  else
+  {
+    Score += 25;
+  }
 
-  DPRINT("ftGdiGetGlyphOutline END and needed %d\n", needed);
-  return needed;
+  ExFreePool(Otm);
+
+  return Score;
 }
 
-BOOL
-FASTCALL
-TextIntGetTextExtentPoint(PDC dc,
-                          PTEXTOBJ TextObj,
-                          LPCWSTR String,
-                          int Count,
-                          int MaxExtent,
-                          LPINT Fit,
-                          LPINT Dx,
-                          LPSIZE Size)
+static __inline VOID
+FindBestFontFromList(FONTOBJ **FontObj, UINT *MatchScore, LOGFONTW *LogFont,
+                     PUNICODE_STRING FaceName, PLIST_ENTRY Head)
 {
-  PFONTGDI FontGDI;
-  FT_Face face;
-  FT_GlyphSlot glyph;
-  FT_Glyph realglyph;
-  INT error, n, glyph_index, i, previous;
-  ULONGLONG TotalWidth = 0;
-  FT_CharMap charmap, found = NULL;
-  BOOL use_kerning;
-  FT_Render_Mode RenderMode;
-  BOOLEAN Render;
-
-  FontGDI = ObjToGDI(TextObj->Font, FONT);
+  PLIST_ENTRY Entry;
+  PFONT_ENTRY CurrentEntry;
+  FONTGDI *FontGDI;
+  UINT Score;
 
-  face = FontGDI->face;
-  if (NULL != Fit)
+  Entry = Head->Flink;
+  while (Entry != Head)
     {
-      *Fit = 0;
+      CurrentEntry = (PFONT_ENTRY) CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
+
+      FontGDI = CurrentEntry->Font;
+      ASSERT(FontGDI);
+
+      Score = GetFontScore(LogFont, FaceName, FontGDI);
+      if (*MatchScore == 0 || *MatchScore < Score)
+        {
+          *FontObj = GDIToObj(FontGDI, FONT);
+          *MatchScore = Score;
+        }
+      Entry = Entry->Flink;
     }
+}
 
-  IntLockFreeType;
-  if (face->charmap == NULL)
-    {
-      DPRINT("WARNING: No charmap selected!\n");
-      DPRINT("This font face has %d charmaps\n", face->num_charmaps);
+static __inline BOOLEAN
+SubstituteFontFamilyKey(PUNICODE_STRING FaceName,
+                        LPCWSTR Key)
+{
+  RTL_QUERY_REGISTRY_TABLE QueryTable[2] = {{0}};
+  NTSTATUS Status;
+  UNICODE_STRING Value;
 
-      for (n = 0; n < face->num_charmaps; n++)
-       {
-         charmap = face->charmaps[n];
-         DPRINT("found charmap encoding: %u\n", charmap->encoding);
-         if (charmap->encoding != 0)
-           {
-             found = charmap;
-             break;
-           }
-       }
+  RtlInitUnicodeString(&Value, NULL);
 
-      if (! found)
-       {
-         DPRINT1("WARNING: Could not find desired charmap!\n");
-       }
+  QueryTable[0].QueryRoutine = NULL;
+  QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND |
+                        RTL_QUERY_REGISTRY_REQUIRED;
+  QueryTable[0].Name = FaceName->Buffer;
+  QueryTable[0].EntryContext = &Value;
+  QueryTable[0].DefaultType = REG_NONE;
+  QueryTable[0].DefaultData = NULL;
+  QueryTable[0].DefaultLength = 0;
 
-      error = FT_Set_Charmap(face, found);
-      if (error)
-       {
-         DPRINT1("WARNING: Could not set the charmap!\n");
-       }
+  QueryTable[1].QueryRoutine = NULL;
+  QueryTable[1].Name = NULL;
+
+  Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
+                                  Key,
+                                  QueryTable,
+                                  NULL,
+                                  NULL);
+  if (NT_SUCCESS(Status))
+    {
+      RtlFreeUnicodeString(FaceName);
+      *FaceName = Value;
     }
 
-  Render = IntIsFontRenderingEnabled();
-  if (Render)
-    RenderMode = IntGetFontRenderMode(&TextObj->logfont.elfEnumLogfontEx.elfLogFont);
-  else
-    RenderMode = FT_RENDER_MODE_MONO;
+  return NT_SUCCESS(Status);
+}
 
-  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));
-  if (error)
+static __inline void
+SubstituteFontFamily(PUNICODE_STRING FaceName, UINT Level)
+{
+  if (10 < Level) /* Enough is enough */
     {
-      DPRINT1("Error in setting pixel sizes: %u\n", error);
+      return;
     }
 
-  use_kerning = FT_HAS_KERNING(face);
-  previous = 0;
-
-  for (i = 0; i < Count; i++)
+  if (SubstituteFontFamilyKey(FaceName, L"SysFontSubstitutes") ||
+      SubstituteFontFamilyKey(FaceName, L"FontSubstitutes"))
     {
-      glyph_index = FT_Get_Char_Index(face, *String);
-      if (!(realglyph = ftGdiGlyphCacheGet(face, glyph_index,
-          TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)))
-        {
-          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);
-              break;
-            }
+      SubstituteFontFamily(FaceName, Level + 1);
+    }
+}
 
-          glyph = face->glyph;
-          realglyph = ftGdiGlyphCacheSet(face, glyph_index,
-             TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight, glyph, RenderMode);
-          if (!realglyph)
-            {
-              DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index);
-              break;
-            }
-        }
+static
+VOID
+FASTCALL
+IntFontType(PFONTGDI Font)
+{
+   PS_FontInfoRec psfInfo;
+
+   if (FT_HAS_MULTIPLE_MASTERS(Font->face))
+      Font->FontObj.flFontType |= FO_MULTIPLEMASTER;
+   if (FT_HAS_VERTICAL( Font->face ))
+      Font->FontObj.flFontType |= FO_VERT_FACE;
+   if (FT_IS_SCALABLE( Font->face ))
+      Font->FontObj.flFontType |= FO_TYPE_RASTER;
+   if (FT_IS_SFNT(Font->face))
+   {
+      Font->FontObj.flFontType |= FO_TYPE_TRUETYPE;
+      if (FT_Get_Sfnt_Table(Font->face, ft_sfnt_post))
+         Font->FontObj.flFontType |= FO_POSTSCRIPT;
+   }
+   if (!FT_Get_PS_Font_Info(Font->face, &psfInfo ))
+   {
+      Font->FontObj.flFontType |= FO_POSTSCRIPT;
+   }
+}
 
-      /* retrieve kerning distance */
-      if (use_kerning && previous && glyph_index)
-       {
-         FT_Vector delta;
-         FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
-         TotalWidth += delta.x;
-       }
+NTSTATUS
+FASTCALL
+TextIntRealizeFont(HFONT FontHandle)
+{
+  NTSTATUS Status = STATUS_SUCCESS;
+  PTEXTOBJ TextObj;
+  UNICODE_STRING FaceName;
+  PW32PROCESS Win32Process;
+  UINT MatchScore;
 
-      TotalWidth += realglyph->advance.x >> 10;
+  TextObj = TEXTOBJ_LockText(FontHandle);
+  if (NULL == TextObj)
+    {
+      return STATUS_INVALID_HANDLE;
+    }
 
-      if (((TotalWidth + 32) >> 6) <= MaxExtent && NULL != Fit)
-       {
-         *Fit = i + 1;
-       }
-      if (NULL != Dx)
-       {
-         Dx[i] = (TotalWidth + 32) >> 6;
-       }
+  if (TextObj->Initialized)
+    {
+      TEXTOBJ_UnlockText(TextObj);
+      return STATUS_SUCCESS;
+    }
 
-      previous = glyph_index;
-      String++;
+  if (! RtlCreateUnicodeString(&FaceName, TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfFaceName))
+    {
+      TEXTOBJ_UnlockText(TextObj);
+      return STATUS_NO_MEMORY;
+    }
+  SubstituteFontFamily(&FaceName, 0);
+  MatchScore = 0;
+  TextObj->Font = NULL;
+
+  /* First search private fonts */
+  Win32Process = PsGetCurrentProcessWin32Process();
+  IntLockProcessPrivateFonts(Win32Process);
+  FindBestFontFromList(&TextObj->Font, &MatchScore,
+                       &TextObj->logfont.elfEnumLogfontEx.elfLogFont, &FaceName,
+                       &Win32Process->PrivateFontListHead);
+  IntUnLockProcessPrivateFonts(Win32Process);
+
+  /* Search system fonts */
+  IntLockGlobalFonts;
+  FindBestFontFromList(&TextObj->Font, &MatchScore,
+                       &TextObj->logfont.elfEnumLogfontEx.elfLogFont, &FaceName,
+                       &FontListHead);
+  IntUnLockGlobalFonts;
+  if (NULL == TextObj->Font)
+    {
+      DPRINT1("Requested font %S not found, no fonts loaded at all\n",
+              TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfFaceName);
+      Status = STATUS_NOT_FOUND;
+    }
+  else
+    {
+      PFONTGDI FontGdi = ObjToGDI(TextObj->Font, FONT);
+      // Need hdev, when freetype is loaded need to create DEVOBJ for
+      // Consumer and Producer.
+      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->Initialized = TRUE;
+      Status = STATUS_SUCCESS;
     }
-  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);
+  RtlFreeUnicodeString(&FaceName);
+  TEXTOBJ_UnlockText(TextObj);
 
-  return TRUE;
-}
+  ASSERT((NT_SUCCESS(Status) ^ (NULL == TextObj->Font)) != 0);
 
-DWORD
-FASTCALL
-IntGdiGetCharSet(HDC  hDC)
-{
-  UINT cp = 0;
-  CHARSETINFO csi;
-  DWORD charset = NtGdiGetTextCharsetInfo(hDC,NULL,0);
-  if (IntTranslateCharsetInfo(&charset, &csi, TCI_SRCCHARSET))
-      cp = csi.ciACP;
-  else
-  {
-      switch(charset)
-      {
-         case OEM_CHARSET:
-           cp = 1;
-           break;
-         case DEFAULT_CHARSET:
-           cp = 0;
-           break;
-         default:
-           DPRINT1("Can't find codepage for charset %d\n", charset);
-           break;
-       }
-  }
-  DPRINT("charset %d => cp %d\n", charset, LOWORD(cp));
-  return (MAKELONG(cp, charset));
+  return Status;
 }
 
-INT
+
+static
+BOOL
 FASTCALL
-ftGdiGetTextCharsetInfo(
-    PDC Dc,
-    LPFONTSIGNATURE lpSig,
-    DWORD dwFlags)
+IntGetFullFileName(
+    POBJECT_NAME_INFORMATION NameInfo,
+    ULONG Size,
+    PUNICODE_STRING FileName)
 {
-  PDC_ATTR Dc_Attr;
-  UINT Ret = DEFAULT_CHARSET, i = 0, fs_fsCsb0 = 0;
-  HFONT hFont;
-  PTEXTOBJ TextObj;
-  PFONTGDI FontGdi;
-  FONTSIGNATURE fs;
-  TT_OS2 *pOS2;
-  FT_Face Face;
+    NTSTATUS Status;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE hFile;
+    IO_STATUS_BLOCK IoStatusBlock;
+    ULONG Desired;
 
-  Dc_Attr = Dc->pDc_Attr;
-  if(!Dc_Attr) Dc_Attr = &Dc->Dc_Attr;
-  hFont = Dc_Attr->hlfntNew;
-  TextObj = TEXTOBJ_LockText(hFont);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               FileName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
 
-  if ( TextObj == NULL)
+    Status = ZwOpenFile(
+      &hFile,
+      0, //FILE_READ_ATTRIBUTES,
+      &ObjectAttributes,
+      &IoStatusBlock,
+      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+      0);
+
+    if (!NT_SUCCESS(Status))
     {
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
-         return Ret;
+        DPRINT("ZwOpenFile() failed (Status = 0x%lx)\n", Status);
+        return FALSE;
     }
-  FontGdi = ObjToGDI(TextObj->Font, FONT);
-  Face = FontGdi->face;
-  TEXTOBJ_UnlockText(TextObj);
-  IntLockFreeType;
-  pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
-  IntUnLockFreeType;
-  memset(&fs, 0, sizeof(FONTSIGNATURE));
-  if (NULL != pOS2)
-    {
-      fs.fsCsb[0] = pOS2->ulCodePageRange1;
-      fs.fsCsb[1] = pOS2->ulCodePageRange2;
-      fs.fsUsb[0] = pOS2->ulUnicodeRange1;
-      fs.fsUsb[1] = pOS2->ulUnicodeRange2;
-      fs.fsUsb[2] = pOS2->ulUnicodeRange3;
-      fs.fsUsb[3] = pOS2->ulUnicodeRange4;
-      fs_fsCsb0   = pOS2->ulCodePageRange1;
-      if (pOS2->version == 0)
-        {
-          FT_UInt dummy;
 
-          if(FT_Get_First_Char( Face, &dummy ) < 0x100)
-                fs_fsCsb0 |= 1;
-          else
-                fs_fsCsb0 |= 1L << 31;
-        }
-    }
-  DPRINT("Csb 1=%x  0=%x\n", fs.fsCsb[1],fs.fsCsb[0]);
-  if (lpSig)
-  {
-     RtlCopyMemory(lpSig, &fs, sizeof(FONTSIGNATURE));
-  }
-  if (0 == fs_fsCsb0)
-    { /* let's see if we can find any interesting cmaps */
-       for (i = 0; i < Face->num_charmaps; i++)
-          {
-              switch (Face->charmaps[i]->encoding)
-                {
-                  case ft_encoding_unicode:
-                  case ft_encoding_apple_roman:
-                    fs_fsCsb0 |= 1;
-                    break;
-                  case ft_encoding_symbol:
-                    fs_fsCsb0 |= 1L << 31;
-                    break;
-                  default:
-                    break;
-                }
-          }
+    Status = ZwQueryObject(hFile, ObjectNameInformation, NameInfo, Size, &Desired);
+    ZwClose(hFile);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("ZwQueryObject() failed (Status = %lx)\n", Status);
+        return FALSE;
     }
-  while (0 == (fs_fsCsb0 >> i & 0x0001) && i < MAXTCIINDEX)
-       {
-          i++;
-       }
-  Ret = FontTci[i].ciCharset;
-  DPRINT("CharSet %d\n",Ret);
-  return Ret;
-}
 
+    return TRUE;
+}
 
-DWORD
+BOOL
 FASTCALL
-ftGetFontUnicodeRanges(PFONTGDI Font, PGLYPHSET glyphset)
+IntGdiGetFontResourceInfo(
+    PUNICODE_STRING FileName,
+    PVOID pBuffer,
+    DWORD *pdwBytes,
+    DWORD dwType)
 {
-    DWORD size = 0;
-    DWORD num_ranges = 0;
-    FT_Face face = Font->face;
+    UNICODE_STRING EntryFileName;
+    POBJECT_NAME_INFORMATION NameInfo1, NameInfo2;
+    PLIST_ENTRY ListEntry;
+    PFONT_ENTRY FontEntry;
+    FONTFAMILYINFO Info;
+    ULONG Size;
+    BOOL bFound = FALSE;
 
-    if (face->charmap->encoding == FT_ENCODING_UNICODE)
+    /* Create buffer for full path name */
+    Size = sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR);
+    NameInfo1 = ExAllocatePoolWithTag(PagedPool, Size, TAG_FINF);
+    if (!NameInfo1)
     {
-        FT_UInt glyph_code = 0;
-        FT_ULong char_code, char_code_prev;
-
-        char_code_prev = char_code = FT_Get_First_Char(face, &glyph_code);
-
-        DPRINT("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
-               face->num_glyphs, glyph_code, char_code);
+        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
 
-        if (!glyph_code) return 0;
+    /* Get the full path name */
+    if (!IntGetFullFileName(NameInfo1, Size, FileName))
+    {
+        ExFreePool(NameInfo1);
+        return FALSE;
+    }
 
-        if (glyphset)
-        {
-            glyphset->ranges[0].wcLow = (USHORT)char_code;
-            glyphset->ranges[0].cGlyphs = 0;
-            glyphset->cGlyphsSupported = 0;
-        }
+    /* Create a buffer for the entries' names */
+    NameInfo2 = ExAllocatePoolWithTag(PagedPool, Size, TAG_FINF);
+    if (!NameInfo2)
+    {
+        ExFreePool(NameInfo1);
+        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
 
-        num_ranges = 1;
-        while (glyph_code)
+    /* Try to find the pathname in the global font list */
+    IntLockGlobalFonts;
+    for (ListEntry = FontListHead.Flink;
+         ListEntry != &FontListHead;
+         ListEntry = ListEntry->Flink)
+    {
+        FontEntry = CONTAINING_RECORD(ListEntry, FONT_ENTRY, ListEntry);
+        if (FontEntry->Font->Filename != NULL)
         {
-            if (char_code < char_code_prev)
-            {
-                DPRINT1("expected increasing char code from FT_Get_Next_Char\n");
-                return 0;
-            }
-            if (char_code - char_code_prev > 1)
+            RtlInitUnicodeString(&EntryFileName , FontEntry->Font->Filename);
+            if (IntGetFullFileName(NameInfo2, Size, &EntryFileName))
             {
-                num_ranges++;
-                if (glyphset)
+                if (RtlEqualUnicodeString(&NameInfo1->Name, &NameInfo2->Name, FALSE))
                 {
-                    glyphset->ranges[num_ranges - 1].wcLow = (USHORT)char_code;
-                    glyphset->ranges[num_ranges - 1].cGlyphs = 1;
-                    glyphset->cGlyphsSupported++;
+                    /* found */
+                    FontFamilyFillInfo(&Info, FontEntry->FaceName.Buffer, FontEntry->Font);
+                    bFound = TRUE;
+                    break;
                 }
             }
-            else if (glyphset)
-            {
-                glyphset->ranges[num_ranges - 1].cGlyphs++;
-                glyphset->cGlyphsSupported++;
-            }
-            char_code_prev = char_code;
-            char_code = FT_Get_Next_Char(face, char_code, &glyph_code);
         }
     }
-    else
-        DPRINT1("encoding %u not supported\n", face->charmap->encoding);
+    IntUnLockGlobalFonts;
+
+    /* Free the buffers */
+    ExFreePool(NameInfo1);
+    ExFreePool(NameInfo2);
+
+    if (!bFound && dwType != 5)
+    {
+        /* Font could not be found in system table
+           dwType == 5 will still handle this */
+        return FALSE;
+    }
+
+    switch(dwType)
+    {
+        case 0: /* FIXME: returns 1 or 2, don't know what this is atm */
+            *(DWORD*)pBuffer = 1;
+            *pdwBytes = sizeof(DWORD);
+            break;
+
+        case 1: /* Copy the full font name */
+            Size = wcslen(Info.EnumLogFontEx.elfFullName) + 1;
+            Size = min(Size , LF_FULLFACESIZE) * sizeof(WCHAR);
+            memcpy(pBuffer, Info.EnumLogFontEx.elfFullName, Size);
+            // FIXME: Do we have to zeroterminate?
+            *pdwBytes = Size;
+            break;
 
-    size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
-    if (glyphset)
-    {
-        glyphset->cbThis = size;
-        glyphset->cRanges = num_ranges;
+        case 2: /* Copy a LOGFONTW structure */
+            Info.EnumLogFontEx.elfLogFont.lfWidth = 0;
+            memcpy(pBuffer, &Info.EnumLogFontEx.elfLogFont, sizeof(LOGFONTW));
+            *pdwBytes = sizeof(LOGFONTW);
+            break;
+
+        case 3: /* FIXME: What exactly is copied here? */
+            *(DWORD*)pBuffer = 1;
+            *pdwBytes = sizeof(DWORD*);
+            break;
+
+        case 5: /* Looks like a BOOL that is copied, TRUE, if the font was not found */
+            *(BOOL*)pBuffer = !bFound;
+            *pdwBytes = sizeof(BOOL);
+            break;
+
+        default:
+            return FALSE;
     }
-    return size;
+
+    return TRUE;
 }
 
 
+BOOL
+FASTCALL
+ftGdiRealizationInfo(PFONTGDI Font, PREALIZATION_INFO Info)
+{  
+  if (FT_HAS_FIXED_SIZES(Font->face))
+      Info->iTechnology = RI_TECH_BITMAP;
+  else
+  {
+     if (FT_IS_SCALABLE(Font->face))
+        Info->iTechnology = RI_TECH_SCALABLE;
+     else
+        Info->iTechnology = RI_TECH_FIXED;
+  }
+  Info->iUniq = Font->FontObj.iUniq;
+  Info->dwUnknown = -1;
+  return TRUE;
+}
+
 DWORD
 FASTCALL
-ftGetFontLanguageInfo(PDC Dc)
+ftGdiGetKerningPairs( PFONTGDI Font,
+                      DWORD cPairs,
+                      LPKERNINGPAIR pKerningPair)
 {
-  PDC_ATTR Dc_Attr;
-  FONTSIGNATURE fontsig;
-  static const DWORD GCP_DBCS_MASK=0x003F0000,
-               GCP_DIACRITIC_MASK=0x00000000,
-               FLI_GLYPHS_MASK=0x00000000,
-               GCP_GLYPHSHAPE_MASK=0x00000040,
-               GCP_KASHIDA_MASK=0x00000000,
-               GCP_LIGATE_MASK=0x00000000,
-               GCP_USEKERNING_MASK=0x00000000,
-               GCP_REORDER_MASK=0x00000060;
+  DWORD Count = 0;
+  FT_Face face;
 
-  DWORD result=0;
+  face = Font->face;
 
-  ftGdiGetTextCharsetInfo( Dc, &fontsig, 0 );
+  if (FT_HAS_KERNING(face) && face->charmap->encoding == FT_ENCODING_UNICODE)
+  {
+     FT_UInt previous_index = 0, glyph_index = 0;
+     FT_ULong char_code, char_previous;
+     FT_Vector delta;
+     int i;
+        
+     char_previous = char_code = FT_Get_First_Char(face, &glyph_index);
 
- /* We detect each flag we return using a bitmask on the Codepage Bitfields */
-  if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
-               result|=GCP_DBCS;
+     IntUnLockFreeType;
 
-  if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
-               result|=GCP_DIACRITIC;
+     for (i = 0; i < face->num_glyphs; i++)
+     {
+         if (previous_index && glyph_index)
+         {
+            FT_Get_Kerning(face, previous_index, glyph_index, FT_KERNING_DEFAULT, &delta);
+        
+            if (pKerningPair && cPairs)
+            {
+               pKerningPair[i].wFirst      = char_previous;
+               pKerningPair[i].wSecond     = char_code;
+               pKerningPair[i].iKernAmount = delta.x;
+            }
+            Count++;
+         }
+         previous_index = glyph_index;
+         char_previous = char_code;
+         char_code = FT_Get_Next_Char(face, char_code, &glyph_index);
+     }
+     IntUnLockFreeType;
+  }
+  return Count;
+}
 
-  if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
-               result|=FLI_GLYPHS;
 
-  if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
-               result|=GCP_GLYPHSHAPE;
+////////////////
+//
+// Functions needing sorting.
+//
+///////////////
+int STDCALL
+NtGdiGetFontFamilyInfo(HDC Dc,
+                       LPLOGFONTW UnsafeLogFont,
+                       PFONTFAMILYINFO UnsafeInfo,
+                       DWORD Size)
+{
+  NTSTATUS Status;
+  LOGFONTW LogFont;
+  PFONTFAMILYINFO Info;
+  DWORD Count;
+  PW32PROCESS Win32Process;
 
-  if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
-               result|=GCP_KASHIDA;
+  /* Make a safe copy */
+  Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW));
+  if (! NT_SUCCESS(Status))
+    {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      return -1;
+    }
 
-  if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
-               result|=GCP_LIGATE;
+  /* Allocate space for a safe copy */
+  Info = ExAllocatePoolWithTag(PagedPool, Size * sizeof(FONTFAMILYINFO), TAG_GDITEXT);
+  if (NULL == Info)
+    {
+      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+      return -1;
+    }
 
-  if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
-               result|=GCP_USEKERNING;
+  /* Enumerate font families in the global list */
+  IntLockGlobalFonts;
+  Count = 0;
+  if (! GetFontFamilyInfoForList(&LogFont, Info, &Count, Size, &FontListHead) )
+    {
+      IntUnLockGlobalFonts;
+      ExFreePool(Info);
+      return -1;
+    }
+  IntUnLockGlobalFonts;
 
-  Dc_Attr = Dc->pDc_Attr;
-  if(!Dc_Attr) Dc_Attr = &Dc->Dc_Attr;
+  /* Enumerate font families in the process local list */
+  Win32Process = PsGetCurrentProcessWin32Process();
+  IntLockProcessPrivateFonts(Win32Process);
+  if (! GetFontFamilyInfoForList(&LogFont, Info, &Count, Size,
+                                 &Win32Process->PrivateFontListHead))
+    {
+      IntUnLockProcessPrivateFonts(Win32Process);
+      ExFreePool(Info);
+      return -1;
+    }
+  IntUnLockProcessPrivateFonts(Win32Process);
 
-  /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
-  if ( Dc_Attr->lTextAlign & TA_RTLREADING )
-     if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
-                    result|=GCP_REORDER;
+  /* Enumerate font families in the registry */
+  if (! GetFontFamilyInfoForSubstitutes(&LogFont, Info, &Count, Size))
+    {
+      ExFreePool(Info);
+      return -1;
+    }
 
-  return result;
-}
+  /* Return data to caller */
+  if (0 != Count)
+    {
+      Status = MmCopyToCaller(UnsafeInfo, Info,
+                              (Count < Size ? Count : Size) * sizeof(FONTFAMILYINFO));
+      if (! NT_SUCCESS(Status))
+        {
+          ExFreePool(Info);
+          SetLastWin32Error(ERROR_INVALID_PARAMETER);
+          return -1;
+        }
+    }
+
+  ExFreePool(Info);
 
+  return Count;
+}
 
 BOOL
-FASTCALL
-ftGdiGetTextMetricsW(
-    HDC hDC,
-    PTMW_INTERNAL ptmwi)
+APIENTRY
+NtGdiExtTextOutW(
+    IN HDC hDC,
+    IN INT XStart,
+    IN INT YStart,
+    IN UINT fuOptions,
+    IN OPTIONAL LPRECT lprc,
+    IN LPWSTR UnsafeString,
+    IN INT Count,
+    IN OPTIONAL LPINT UnsafeDx,
+    IN DWORD dwCodePage)
 {
-  PDC dc;
-  PDC_ATTR Dc_Attr;
-  PTEXTOBJ TextObj;
-  PFONTGDI FontGDI;
-  FT_Face Face;
-  TT_OS2 *pOS2;
-  TT_HoriHeader *pHori;
-  FT_WinFNT_HeaderRec Win;
-  ULONG Error;
-  NTSTATUS Status = STATUS_SUCCESS;
+   /*
+    * FIXME:
+    * Call EngTextOut, which does the real work (calling DrvTextOut where
+    * appropriate)
+    */
 
-  if (!ptmwi)
-  {
-    SetLastWin32Error(STATUS_INVALID_PARAMETER);
-    return FALSE;
-  }
+   DC *dc;
+   PDC_ATTR Dc_Attr;
+   SURFOBJ *SurfObj;
+   BITMAPOBJ *BitmapObj = NULL;
+   int error, glyph_index, n, i;
+   FT_Face face;
+   FT_GlyphSlot glyph;
+   FT_Glyph realglyph;
+   FT_BitmapGlyph realglyph2;
+   LONGLONG TextLeft, RealXStart;
+   ULONG TextTop, previous, BackgroundLeft;
+   FT_Bool use_kerning;
+   RECTL DestRect, MaskRect, SpecifiedDestRect;
+   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;
+   FT_CharMap found = 0, charmap;
+   INT yoff;
+   FONTOBJ *FontObj;
+   PFONTGDI FontGDI;
+   PTEXTOBJ TextObj = NULL;
+   PPALGDI PalDestGDI;
+   XLATEOBJ *XlateObj=NULL, *XlateObj2=NULL;
+   ULONG Mode;
+   FT_Render_Mode RenderMode;
+   BOOLEAN Render;
+   NTSTATUS Status;
+   INT *Dx = NULL;
+   POINT Start;
+   BOOL DoBreak = FALSE;
+   LPCWSTR String, SafeString = NULL;
+   HPALETTE hDestPalette;
+
+   // TODO: Write test-cases to exactly match real Windows in different
+   // bad parameters (e.g. does Windows check the DC or the RECT first?).
+   dc = DC_LockDc(hDC);
+   if (!dc)
+   {
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return FALSE;
+   }
+   if (dc->DC_Type == 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;
+
+       /* Check if String is valid */
+   if ((Count > 0xFFFF) || (Count > 0 && UnsafeString == NULL))
+   {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      goto fail;
+   }
+   if (Count > 0)
+   {
+      SafeString = ExAllocatePoolWithTag(PagedPool, Count * sizeof(WCHAR), TAG_GDITEXT);
+      if (!SafeString)
+      {
+         goto fail;
+      }
+      Status = MmCopyFromCaller(SafeString, UnsafeString, Count * sizeof(WCHAR));
+      if (! NT_SUCCESS(Status))
+      {
+        goto fail;
+      }
+   }
+   String = SafeString;
 
-  if(!(dc = DC_LockDc(hDC)))
-  {
-    SetLastWin32Error(ERROR_INVALID_HANDLE);
-    return FALSE;
-  }
-  Dc_Attr = dc->pDc_Attr;
-  if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
-  TextObj = TEXTOBJ_LockText(Dc_Attr->hlfntNew);
-  if (NULL != TextObj)
-    {
-      FontGDI = ObjToGDI(TextObj->Font, FONT);
+   if (lprc && (fuOptions & (ETO_OPAQUE | ETO_CLIPPED)))
+   {
+      // At least one of the two flags were specified. Copy lprc. Once.
+      Status = MmCopyFromCaller(&SpecifiedDestRect, lprc, sizeof(RECT));
+      if (!NT_SUCCESS(Status))
+      {
+         DC_UnlockDc(dc);
+         SetLastWin32Error(ERROR_INVALID_PARAMETER);
+         return FALSE;
+      }
+      IntLPtoDP(dc, (POINT *) &SpecifiedDestRect, 2);
+   }
 
-      Face = FontGDI->face;
-      IntLockFreeType;
-      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));
-      IntUnLockFreeType;
-      if (0 != Error)
-       {
-          DPRINT1("Error in setting pixel sizes: %u\n", Error);
-          Status = STATUS_UNSUCCESSFUL;
-       }
-      else
-       {
-          memcpy(&ptmwi->TextMetric, &FontGDI->TextMetric, sizeof(TEXTMETRICW));
-          /* FIXME: Fill Diff member */
-          RtlZeroMemory(&ptmwi->Diff, sizeof(ptmwi->Diff));
+   if (NULL != UnsafeDx && Count > 0)
+   {
+      Dx = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), TAG_GDITEXT);
+      if (NULL == Dx)
+      {
+         goto fail;
+      }
+      Status = MmCopyFromCaller(Dx, UnsafeDx, Count * sizeof(INT));
+      if (! NT_SUCCESS(Status))
+      {
+         goto fail;
+      }
+   }
 
-          Status = STATUS_SUCCESS;
-          IntLockFreeType;
-          pOS2 = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_os2);
-          if (NULL == pOS2)
-            {
-              DPRINT1("Can't find OS/2 table - not TT font?\n");
-              Status = STATUS_INTERNAL_ERROR;
-            }
+   BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
+   if ( !BitmapObj )
+   {
+      goto fail;
+   }
+   SurfObj = &BitmapObj->SurfObj;
+   ASSERT(SurfObj);
 
-          pHori = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_hhea);
-          if (NULL == pHori)
-            {
-              DPRINT1("Can't find HHEA table - not TT font?\n");
-              Status = STATUS_INTERNAL_ERROR;
-            }
+   Start.x = XStart; Start.y = YStart;
+   IntLPtoDP(dc, &Start, 1);
 
-          Error = FT_Get_WinFNT_Header(FontGDI->face , &Win);
+   RealXStart = (Start.x + dc->ptlDCOrig.x) << 6;
+   YStart = Start.y + dc->ptlDCOrig.y;
 
-          IntUnLockFreeType;
+   /* Create the brushes */
+   hDestPalette = BitmapObj->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;
+   }
 
-          if (NT_SUCCESS(Status))
-          {
-              FillTM(&ptmwi->TextMetric, FontGDI, pOS2, pHori, !Error ? &Win : 0);
-          }
-       }
-      TEXTOBJ_UnlockText(TextObj);
-    }
-  else
-  {
-     Status = STATUS_INVALID_HANDLE;
-  }
-  DC_UnlockDc(dc);
+   SourcePoint.x = 0;
+   SourcePoint.y = 0;
+   MaskRect.left = 0;
+   MaskRect.top = 0;
+   BrushOrigin.x = 0;
+   BrushOrigin.y = 0;
 
-  if (!NT_SUCCESS(Status))
-  {
-     SetLastNtError(Status);
-     return FALSE;
-  }
-  return TRUE;
-}
+   if ((fuOptions & ETO_OPAQUE) && lprc)
+   {
+      DestRect.left   = SpecifiedDestRect.left   + dc->ptlDCOrig.x;
+      DestRect.top    = SpecifiedDestRect.top    + dc->ptlDCOrig.y;
+      DestRect.right  = SpecifiedDestRect.right  + dc->ptlDCOrig.x;
+      DestRect.bottom = SpecifiedDestRect.bottom + dc->ptlDCOrig.y;
+      IntLPtoDP(dc, (LPPOINT)&DestRect, 2);
+      IntEngBitBlt(
+         &BitmapObj->SurfObj,
+         NULL,
+         NULL,
+         dc->CombinedClip,
+         NULL,
+         &DestRect,
+         &SourcePoint,
+         &SourcePoint,
+         &BrushBgInst.BrushObject,
+         &BrushOrigin,
+         ROP3_TO_ROP4(PATCOPY));
+      fuOptions &= ~ETO_OPAQUE;
+   }
+   else
+   {
+      if (Dc_Attr->jBkMode == OPAQUE)
+      {
+         fuOptions |= ETO_OPAQUE;
+      }
+   }
 
+   TextObj = TEXTOBJ_LockText(Dc_Attr->hlfntNew);
+   if(TextObj == NULL)
+   {
+      goto fail;
+   }
 
-DWORD STDCALL
-NtGdiGetFontData(
-   HDC hDC,
-   DWORD Table,
-   DWORD Offset,
-   LPVOID Buffer,
-   DWORD Size)
-{
-   PDC Dc;
-   PDC_ATTR Dc_Attr;
-   HFONT hFont;
-   PTEXTOBJ TextObj;
-   PFONTGDI FontGdi;
-   DWORD Result = GDI_ERROR;
+   FontObj = TextObj->Font;
+   ASSERT(FontObj);
+   FontGDI = ObjToGDI(FontObj, FONT);
+   ASSERT(FontGDI);
 
-   Dc = DC_LockDc(hDC);
-   if (Dc == NULL)
+   IntLockFreeType;
+   face = FontGDI->face;
+   if (face->charmap == NULL)
    {
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return GDI_ERROR;
+      DPRINT("WARNING: No charmap selected!\n");
+      DPRINT("This font face has %d charmaps\n", face->num_charmaps);
+
+      for (n = 0; n < face->num_charmaps; n++)
+      {
+         charmap = face->charmaps[n];
+         DPRINT("found charmap encoding: %u\n", charmap->encoding);
+         if (charmap->encoding != 0)
+         {
+            found = charmap;
+            break;
+         }
+      }
+      if (!found)
+      {
+         DPRINT1("WARNING: Could not find desired charmap!\n");
+      }
+      error = FT_Set_Charmap(face, found);
+         if (error)
+      {
+         DPRINT1("WARNING: Could not set the charmap!\n");
+      }
    }
-   Dc_Attr = Dc->pDc_Attr;
-   if(!Dc_Attr) Dc_Attr = &Dc->Dc_Attr;
-   hFont = Dc_Attr->hlfntNew;
-   TextObj = TEXTOBJ_LockText(hFont);
-   DC_UnlockDc(Dc);
 
-   if (TextObj == NULL)
+   Render = IntIsFontRenderingEnabled();
+   if (Render)
+      RenderMode = IntGetFontRenderMode(&TextObj->logfont.elfEnumLogfontEx.elfLogFont);
+   else
+      RenderMode = FT_RENDER_MODE_MONO;
+
+   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));
+   if (error)
    {
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return GDI_ERROR;
+      DPRINT1("Error in setting pixel sizes: %u\n", error);
+      IntUnLockFreeType;
+      goto fail;
    }
 
-   FontGdi = ObjToGDI(TextObj->Font, FONT);
+   /*
+    * Process the vertical alignment and determine the yoff.
+    */
+
+   if (Dc_Attr->lTextAlign & TA_BASELINE)
+      yoff = 0;
+   else if (Dc_Attr->lTextAlign & TA_BOTTOM)
+      yoff = -face->size->metrics.descender >> 6;
+   else /* TA_TOP */
+      yoff = face->size->metrics.ascender >> 6;
+
+   use_kerning = FT_HAS_KERNING(face);
+   previous = 0;
 
-   IntLockFreeType;
+   /*
+    * Process the horizontal alignment and modify XStart accordingly.
+    */
 
-   if (FT_IS_SFNT(FontGdi->face))
+   if (Dc_Attr->lTextAlign & (TA_RIGHT | TA_CENTER))
    {
-       if (Table)
-          Table = Table >> 24 | Table << 24 | (Table >> 8 & 0xFF00) |
-                  (Table << 8 & 0xFF0000);
-
-       if (Buffer == NULL)
-          Size = 0;
+      ULONGLONG TextWidth = 0;
+      LPCWSTR TempText = String;
+      int Start;
 
-       if (!FT_Load_Sfnt_Table(FontGdi->face, Table, Offset, Buffer, &Size))
-          Result = Size;
-   }
+      /*
+       * Calculate width of the text.
+       */
 
-   IntUnLockFreeType;
+      if (NULL != Dx)
+      {
+         Start = Count < 2 ? 0 : Count - 2;
+         TextWidth = Count < 2 ? 0 : (Dx[Count - 2] << 6);
+      }
+      else
+      {
+         Start = 0;
+      }
+      TempText = String + Start;
 
-   TEXTOBJ_UnlockText(TextObj);
+      for (i = Start; i < Count; i++)
+      {
+         if (fuOptions & ETO_GLYPH_INDEX)
+           glyph_index = *TempText;
+         else
+           glyph_index = FT_Get_Char_Index(face, *TempText);
 
-   return Result;
-}
+         if (!(realglyph = ftGdiGlyphCacheGet(face, glyph_index,
+         TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)))
+         {
+             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);
+             }
 
-static UINT FASTCALL
-GetFontScore(LOGFONTW *LogFont, PUNICODE_STRING FaceName, PFONTGDI FontGDI)
-{
-  ANSI_STRING EntryFaceNameA;
-  UNICODE_STRING EntryFaceNameW;
-  unsigned Size;
-  OUTLINETEXTMETRICW *Otm;
-  LONG WeightDiff;
-  NTSTATUS Status;
-  UINT Score = 1;
+             glyph = face->glyph;
+             realglyph = ftGdiGlyphCacheSet(face, glyph_index,
+                TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight, glyph, RenderMode);
+             if (!realglyph)
+             {
+                 DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index);
+                 IntUnLockFreeType;
+                 goto fail;
+             }
 
-  RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name);
-  Status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
-  if (NT_SUCCESS(Status))
-    {
-      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))
-        {
-          Score += 49;
-        }
-      RtlFreeUnicodeString(&EntryFaceNameW);
-    }
+         }
+         /* retrieve kerning distance */
+         if (use_kerning && previous && glyph_index)
+         {
+            FT_Vector delta;
+            FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
+            TextWidth += delta.x;
+         }
 
-  Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
-  Otm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
-  if (NULL == Otm)
-    {
-      return Score;
-    }
-  IntGetOutlineTextMetrics(FontGDI, Size, Otm);
+         TextWidth += realglyph->advance.x >> 10;
 
-  if ((0 != LogFont->lfItalic && 0 != Otm->otmTextMetrics.tmItalic) ||
-      (0 == LogFont->lfItalic && 0 == Otm->otmTextMetrics.tmItalic))
-    {
-      Score += 25;
-    }
-  if (LogFont->lfWeight != FW_DONTCARE)
-  {
-    if (LogFont->lfWeight < Otm->otmTextMetrics.tmWeight)
-    {
-      WeightDiff = Otm->otmTextMetrics.tmWeight - LogFont->lfWeight;
-    }
-    else
-    {
-      WeightDiff = LogFont->lfWeight - Otm->otmTextMetrics.tmWeight;
-    }
-    Score += (1000 - WeightDiff) / (1000 / 25);
-  }
-  else
-  {
-    Score += 25;
-  }
+         previous = glyph_index;
+         TempText++;
+      }
 
-  ExFreePool(Otm);
+      previous = 0;
 
-  return Score;
-}
+      if (Dc_Attr->lTextAlign & TA_RIGHT)
+      {
+         RealXStart -= TextWidth;
+      }
+      else
+      {
+         RealXStart -= TextWidth / 2;
+      }
+   }
 
-static __inline VOID
-FindBestFontFromList(FONTOBJ **FontObj, UINT *MatchScore, LOGFONTW *LogFont,
-                     PUNICODE_STRING FaceName, PLIST_ENTRY Head)
-{
-  PLIST_ENTRY Entry;
-  PFONT_ENTRY CurrentEntry;
-  FONTGDI *FontGDI;
-  UINT Score;
+   TextLeft = RealXStart;
+   TextTop = YStart;
+   BackgroundLeft = (RealXStart + 32) >> 6;
 
-  Entry = Head->Flink;
-  while (Entry != Head)
-    {
-      CurrentEntry = (PFONT_ENTRY) CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
+   /*
+    * The main rendering loop.
+    */
 
-      FontGDI = CurrentEntry->Font;
-      ASSERT(FontGDI);
+   for (i = 0; i < Count; i++)
+   {
+      if (fuOptions & ETO_GLYPH_INDEX)
+        glyph_index = *String;
+      else
+        glyph_index = FT_Get_Char_Index(face, *String);
 
-      Score = GetFontScore(LogFont, FaceName, FontGDI);
-      if (*MatchScore == 0 || *MatchScore < Score)
+      if (!(realglyph = ftGdiGlyphCacheGet(face, glyph_index,
+      TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)))
+      {
+        error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
+        if (error)
         {
-          *FontObj = GDIToObj(FontGDI, FONT);
-          *MatchScore = Score;
+           DPRINT1("Failed to load and render glyph! [index: %u]\n", glyph_index);
+           IntUnLockFreeType;
+           goto fail;
         }
-      Entry = Entry->Flink;
-    }
-}
+        glyph = face->glyph;
+        realglyph = ftGdiGlyphCacheSet(face,
+                                       glyph_index,
+                                       TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight,
+                                       glyph,
+                                       RenderMode);
+        if (!realglyph)
+        {
+            DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index);
+            IntUnLockFreeType;
+            goto fail;
+        }
+      }
+//      DbgPrint("realglyph: %x\n", realglyph);
+//      DbgPrint("TextLeft: %d\n", TextLeft);
 
-static __inline BOOLEAN
-SubstituteFontFamilyKey(PUNICODE_STRING FaceName,
-                        LPCWSTR Key)
-{
-  RTL_QUERY_REGISTRY_TABLE QueryTable[2] = {{0}};
-  NTSTATUS Status;
-  UNICODE_STRING Value;
+      /* retrieve kerning distance and move pen position */
+      if (use_kerning && previous && glyph_index && NULL == Dx)
+      {
+         FT_Vector delta;
+         FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
+         TextLeft += delta.x;
+      }
+//      DPRINT1("TextLeft: %d\n", TextLeft);
+//      DPRINT1("TextTop: %d\n", TextTop);
 
-  RtlInitUnicodeString(&Value, NULL);
+      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;
 
-  QueryTable[0].QueryRoutine = NULL;
-  QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND |
-                        RTL_QUERY_REGISTRY_REQUIRED;
-  QueryTable[0].Name = FaceName->Buffer;
-  QueryTable[0].EntryContext = &Value;
-  QueryTable[0].DefaultType = REG_NONE;
-  QueryTable[0].DefaultData = NULL;
-  QueryTable[0].DefaultLength = 0;
+//      DPRINT1("Pitch: %d\n", pitch);
+//      DPRINT1("Advance: %d\n", realglyph->advance.x);
+
+      if (fuOptions & ETO_OPAQUE)
+      {
+         DestRect.left = BackgroundLeft;
+         DestRect.right = (TextLeft + (realglyph->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(
+            &BitmapObj->SurfObj,
+            NULL,
+            NULL,
+            dc->CombinedClip,
+            NULL,
+            &DestRect,
+            &SourcePoint,
+            &SourcePoint,
+            &BrushBgInst.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;
 
-  QueryTable[1].QueryRoutine = NULL;
-  QueryTable[1].Name = NULL;
+      bitSize.cx = realglyph2->bitmap.width;
+      bitSize.cy = realglyph2->bitmap.rows;
+      MaskRect.right = realglyph2->bitmap.width;
+      MaskRect.bottom = realglyph2->bitmap.rows;
 
-  Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
-                                  Key,
-                                  QueryTable,
-                                  NULL,
-                                  NULL);
-  if (NT_SUCCESS(Status))
-    {
-      RtlFreeUnicodeString(FaceName);
-      *FaceName = Value;
-    }
+      /*
+       * 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.
+       */
 
-  return NT_SUCCESS(Status);
-}
+      HSourceGlyph = EngCreateBitmap(bitSize, realglyph2->bitmap.pitch,
+                                     (realglyph2->bitmap.pixel_mode == ft_pixel_mode_grays) ?
+                                     BMF_8BPP : BMF_1BPP, BMF_TOPDOWN,
+                                     realglyph2->bitmap.buffer);
+      if ( !HSourceGlyph )
+      {
+        DPRINT1("WARNING: EngLockSurface() failed!\n");
+        // FT_Done_Glyph(realglyph);
+        IntUnLockFreeType;
+        goto fail;
+      }
+      SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
+      if ( !SourceGlyphSurf )
+      {
+        EngDeleteSurface((HSURF)HSourceGlyph);
+        DPRINT1("WARNING: EngLockSurface() failed!\n");
+        IntUnLockFreeType;
+        goto fail;
+      }
 
-static __inline void
-SubstituteFontFamily(PUNICODE_STRING FaceName, UINT Level)
-{
-  if (10 < Level) /* Enough is enough */
-    {
-      return;
-    }
+      /*
+       * Use the font data as a mask to paint onto the DCs surface using a
+       * brush.
+       */
 
-  if (SubstituteFontFamilyKey(FaceName, L"SysFontSubstitutes") ||
-      SubstituteFontFamilyKey(FaceName, L"FontSubstitutes"))
-    {
-      SubstituteFontFamily(FaceName, Level + 1);
-    }
-}
+      if (lprc &&
+          (fuOptions & ETO_CLIPPED) &&
+          DestRect.right >= SpecifiedDestRect.right + dc->ptlDCOrig.x)
+      {
+         // We do the check '>=' instead of '>' to possibly save an iteration
+         // through this loop, since it's breaking after the drawing is done,
+         // and x is always incremented.
+         DestRect.right = SpecifiedDestRect.right + dc->ptlDCOrig.x;
+         DoBreak = TRUE;
+      }
 
-NTSTATUS FASTCALL
-TextIntRealizeFont(HFONT FontHandle)
-{
-  NTSTATUS Status = STATUS_SUCCESS;
-  PTEXTOBJ TextObj;
-  UNICODE_STRING FaceName;
-  PW32PROCESS Win32Process;
-  UINT MatchScore;
+      IntEngMaskBlt(
+         SurfObj,
+         SourceGlyphSurf,
+         dc->CombinedClip,
+         XlateObj,
+         XlateObj2,
+         &DestRect,
+         &SourcePoint,
+         (PPOINTL)&MaskRect,
+         &BrushFgInst.BrushObject,
+         &BrushOrigin);
 
-  TextObj = TEXTOBJ_LockText(FontHandle);
-  if (NULL == TextObj)
-    {
-      return STATUS_INVALID_HANDLE;
-    }
+      EngUnlockSurface(SourceGlyphSurf);
+      EngDeleteSurface((HSURF)HSourceGlyph);
 
-  if (TextObj->Initialized)
-    {
-      TEXTOBJ_UnlockText(TextObj);
-      return STATUS_SUCCESS;
-    }
+      if (DoBreak)
+      {
+         break;
+      }
 
-  if (! RtlCreateUnicodeString(&FaceName, TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfFaceName))
-    {
-      TEXTOBJ_UnlockText(TextObj);
-      return STATUS_NO_MEMORY;
-    }
-  SubstituteFontFamily(&FaceName, 0);
-  MatchScore = 0;
-  TextObj->Font = NULL;
+      if (NULL == Dx)
+      {
+         TextLeft += realglyph->advance.x >> 10;
+//         DbgPrint("new TextLeft: %d\n", TextLeft);
+      }
+      else
+      {
+         TextLeft += Dx[i] << 6;
+//         DbgPrint("new TextLeft2: %d\n", TextLeft);
+      }
+      previous = glyph_index;
 
-  /* First search private fonts */
-  Win32Process = PsGetCurrentProcessWin32Process();
-  IntLockProcessPrivateFonts(Win32Process);
-  FindBestFontFromList(&TextObj->Font, &MatchScore,
-                       &TextObj->logfont.elfEnumLogfontEx.elfLogFont, &FaceName,
-                       &Win32Process->PrivateFontListHead);
-  IntUnLockProcessPrivateFonts(Win32Process);
+      String++;
+   }
 
-  /* Search system fonts */
-  IntLockGlobalFonts;
-  FindBestFontFromList(&TextObj->Font, &MatchScore,
-                       &TextObj->logfont.elfEnumLogfontEx.elfLogFont, &FaceName,
-                       &FontListHead);
-  IntUnLockGlobalFonts;
-  if (NULL == TextObj->Font)
-    {
-      DPRINT1("Requested font %S not found, no fonts loaded at all\n",
-              TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfFaceName);
-      Status = STATUS_NOT_FOUND;
-    }
-  else
-    {
-      PFONTGDI FontGdi = ObjToGDI(TextObj->Font, FONT);
-      TextObj->Font->iUniq = 1; // Now it can be cached.
-      FontGdi->Underline = TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfUnderline ? 0xff : 0;
-      FontGdi->StrikeOut = TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfStrikeOut ? 0xff : 0;
-      TextObj->Initialized = TRUE;
-      Status = STATUS_SUCCESS;
-    }
+   IntUnLockFreeType;
 
-  RtlFreeUnicodeString(&FaceName);
-  TEXTOBJ_UnlockText(TextObj);
+   EngDeleteXlate(XlateObj);
+   EngDeleteXlate(XlateObj2);
+   BITMAPOBJ_UnlockBitmap(BitmapObj);
+   if(TextObj != NULL)
+     TEXTOBJ_UnlockText(TextObj);
+   if (hBrushBg != NULL)
+   {
+      BRUSHOBJ_UnlockBrush(BrushBg);
+      NtGdiDeleteObject(hBrushBg);
+   }
+   BRUSHOBJ_UnlockBrush(BrushFg);
+   NtGdiDeleteObject(hBrushFg);
+   if (NULL != SafeString)
+   {
+      ExFreePool((void*)SafeString);
+   }
+   if (NULL != Dx)
+   {
+      ExFreePool(Dx);
+   }
+   DC_UnlockDc( dc );
 
-  ASSERT((NT_SUCCESS(Status) ^ (NULL == TextObj->Font)) != 0);
+   return TRUE;
 
-  return Status;
+fail:
+   if ( XlateObj2 != NULL )
+      EngDeleteXlate(XlateObj2);
+   if ( XlateObj != NULL )
+      EngDeleteXlate(XlateObj);
+   if(TextObj != NULL)
+     TEXTOBJ_UnlockText(TextObj);
+   if (BitmapObj != NULL)
+     BITMAPOBJ_UnlockBitmap(BitmapObj);
+   if (hBrushBg != NULL)
+   {
+      BRUSHOBJ_UnlockBrush(BrushBg);
+      NtGdiDeleteObject(hBrushBg);
+   }
+   if (hBrushFg != NULL)
+   {
+      BRUSHOBJ_UnlockBrush(BrushFg);
+      NtGdiDeleteObject(hBrushFg);
+   }
+   if (NULL != SafeString)
+   {
+      ExFreePool((void*)SafeString);
+   }
+   if (NULL != Dx)
+   {
+      ExFreePool(Dx);
+   }
+   DC_UnlockDc(dc);
+
+   return FALSE;
 }
 
-INT FASTCALL
-FontGetObject(PTEXTOBJ TFont, INT Count, PVOID Buffer)
-{
-  if( Buffer == NULL ) return sizeof(LOGFONTW);
+ /*
+ * @implemented
+ */
+BOOL
+STDCALL
+NtGdiGetCharABCWidthsW(
+    IN HDC hDC,
+    IN UINT FirstChar,
+    IN ULONG Count,
+    IN OPTIONAL PWCHAR pwch,
+    IN FLONG fl,
+    OUT PVOID Buffer)
+{
+   LPABC SafeBuff;
+   LPABCFLOAT SafeBuffF = NULL;
+   PDC dc;
+   PDC_ATTR Dc_Attr;
+   PTEXTOBJ TextObj;
+   PFONTGDI FontGDI;
+   FT_Face face;
+   FT_CharMap charmap, found = NULL;
+   UINT i, glyph_index, BufferSize;
+   HFONT hFont = 0;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   if(pwch)
+   {
+     _SEH_TRY
+     {
+       ProbeForRead(pwch,
+            sizeof(PWSTR),
+                       1);
+     }
+     _SEH_HANDLE
+     {
+      Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+   }
+   if (!NT_SUCCESS(Status))
+   {
+      SetLastWin32Error(Status);
+      return FALSE;
+   }
+
+   BufferSize = Count * sizeof(ABC); // Same size!
+   SafeBuff = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT);
+   if (!fl) SafeBuffF = (LPABCFLOAT) SafeBuff;
+   if (SafeBuff == NULL)
+   {
+      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+      return FALSE;
+   }
 
-  switch (Count)
-  {
+   dc = DC_LockDc(hDC);
+   if (dc == NULL)
+   {
+      ExFreePool(SafeBuff);
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return FALSE;
+   }
+   Dc_Attr = dc->pDc_Attr;
+   if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+   hFont = Dc_Attr->hlfntNew;
+   TextObj = TEXTOBJ_LockText(hFont);
+   DC_UnlockDc(dc);
 
-     case sizeof(ENUMLOGFONTEXDVW):
-        RtlCopyMemory( (LPENUMLOGFONTEXDVW) Buffer,
-                                            &TFont->logfont,
-                                            sizeof(ENUMLOGFONTEXDVW));
-        break;
-     case sizeof(ENUMLOGFONTEXW):
-        RtlCopyMemory( (LPENUMLOGFONTEXW) Buffer,
-                                          &TFont->logfont.elfEnumLogfontEx,
-                                          sizeof(ENUMLOGFONTEXW));
-        break;
+   if (TextObj == NULL)
+   {
+      ExFreePool(SafeBuff);
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return FALSE;
+   }
 
-     case sizeof(EXTLOGFONTW):
-     case sizeof(ENUMLOGFONTW):
-        RtlCopyMemory((LPENUMLOGFONTW) Buffer,
-                                    &TFont->logfont.elfEnumLogfontEx.elfLogFont,
-                                       sizeof(ENUMLOGFONTW));
-        break;
+   FontGDI = ObjToGDI(TextObj->Font, FONT);
 
-     case sizeof(LOGFONTW):
-        RtlCopyMemory((LPLOGFONTW) Buffer,
-                                   &TFont->logfont.elfEnumLogfontEx.elfLogFont,
-                                   sizeof(LOGFONTW));
-        break;
+   face = FontGDI->face;
+   if (face->charmap == NULL)
+   {
+      for (i = 0; i < face->num_charmaps; i++)
+      {
+         charmap = face->charmaps[i];
+         if (charmap->encoding != 0)
+         {
+            found = charmap;
+            break;
+         }
+      }
 
-     default:
-        SetLastWin32Error(ERROR_BUFFER_OVERFLOW);
-        return 0;
-  }
-  return Count;
-}
+      if (!found)
+      {
+         DPRINT1("WARNING: Could not find desired charmap!\n");
+         ExFreePool(SafeBuff);
+         SetLastWin32Error(ERROR_INVALID_HANDLE);
+         return FALSE;
+      }
 
+      IntLockFreeType;
+      FT_Set_Charmap(face, found);
+      IntUnLockFreeType;
+   }
 
-static BOOL FASTCALL
-IntGetFullFileName(
-    POBJECT_NAME_INFORMATION NameInfo,
-    ULONG Size,
-    PUNICODE_STRING FileName)
-{
-    NTSTATUS Status;
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    HANDLE hFile;
-    IO_STATUS_BLOCK IoStatusBlock;
-    ULONG Desired;
+   IntLockFreeType;
+   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));
 
-    InitializeObjectAttributes(&ObjectAttributes,
-                               FileName,
-                               OBJ_CASE_INSENSITIVE,
-                               NULL,
-                               NULL);
+   for (i = FirstChar; i < FirstChar+Count; i++)
+   {
+      int adv, lsb, bbx, left, right;
 
-    Status = ZwOpenFile(
-      &hFile,
-      0, //FILE_READ_ATTRIBUTES,
-      &ObjectAttributes,
-      &IoStatusBlock,
-      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-      0);
+      if (pwch)
+      {
+         if (fl & GCABCW_INDICES)
+          glyph_index = pwch[i - FirstChar];
+         else
+          glyph_index = FT_Get_Char_Index(face, pwch[i - FirstChar]);
+      }
+      else
+      {
+         if (fl & GCABCW_INDICES)
+             glyph_index = i;
+         else
+             glyph_index = FT_Get_Char_Index(face, i);
+      }
+      FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
 
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT("ZwOpenFile() failed (Status = 0x%lx)\n", Status);
-        return FALSE;
-    }
+      left = (INT)face->glyph->metrics.horiBearingX  & -64;
+      right = (INT)((face->glyph->metrics.horiBearingX + face->glyph->metrics.width) + 63) & -64;
+      adv  = (face->glyph->advance.x + 32) >> 6;
 
-    Status = ZwQueryObject(hFile, ObjectNameInformation, NameInfo, Size, &Desired);
-    ZwClose(hFile);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT("ZwQueryObject() failed (Status = %lx)\n", Status);
-        return FALSE;
-    }
+//      int test = (INT)(face->glyph->metrics.horiAdvance + 63) >> 6;
+//      DPRINT1("Advance Wine %d and Advance Ros %d\n",test, adv ); /* It's the same!*/
 
-    return TRUE;
+      lsb = left >> 6;
+      bbx = (right - left) >> 6;
+/*
+      DPRINT1("lsb %d and bbx %d\n", lsb, bbx );
+ */
+      if (!fl)
+      {
+        SafeBuffF[i - FirstChar].abcfA = (FLOAT) lsb;
+        SafeBuffF[i - FirstChar].abcfB = (FLOAT) bbx;
+        SafeBuffF[i - FirstChar].abcfC = (FLOAT) (adv - lsb - bbx);
+      }
+      else
+      {
+        SafeBuff[i - FirstChar].abcA = lsb;
+        SafeBuff[i - FirstChar].abcB = bbx;
+        SafeBuff[i - FirstChar].abcC = adv - lsb - bbx;
+      }
+   }
+   IntUnLockFreeType;
+   TEXTOBJ_UnlockText(TextObj);
+   Status = MmCopyToCaller(Buffer, SafeBuff, BufferSize);
+   if (! NT_SUCCESS(Status))
+     {
+       SetLastNtError(Status);
+       ExFreePool(SafeBuff);
+       return FALSE;
+     }
+   ExFreePool(SafeBuff);
+   DPRINT("NtGdiGetCharABCWidths Worked!\n");
+   return TRUE;
 }
 
-static BOOL FASTCALL
-IntGdiGetFontResourceInfo(
-    IN  PUNICODE_STRING FileName,
-    OUT void *pBuffer,
-    OUT DWORD *pdwBytes,
-    IN  DWORD dwType)
+ /*
+ * @implemented
+ */
+BOOL
+STDCALL
+NtGdiGetCharWidthW(
+    IN HDC hDC,
+    IN UINT FirstChar,
+    IN UINT Count,
+    IN OPTIONAL PWCHAR pwc,
+    IN FLONG fl,
+    OUT PVOID Buffer)
 {
-    UNICODE_STRING EntryFileName;
-    POBJECT_NAME_INFORMATION NameInfo1, NameInfo2;
-    PLIST_ENTRY ListEntry;
-    PFONT_ENTRY FontEntry;
-    FONTFAMILYINFO Info;
-    ULONG Size;
-    BOOL bFound = FALSE;
-
-    /* Create buffer for full path name */
-    Size = sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR);
-    NameInfo1 = ExAllocatePoolWithTag(PagedPool, Size, TAG_FINF);
-    if (!NameInfo1)
-    {
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-        return FALSE;
-    }
-
-    /* Get the full path name */
-    if (!IntGetFullFileName(NameInfo1, Size, FileName))
-    {
-        ExFreePool(NameInfo1);
-        return FALSE;
-    }
-
-    /* Create a buffer for the entries' names */
-    NameInfo2 = ExAllocatePoolWithTag(PagedPool, Size, TAG_FINF);
-    if (!NameInfo2)
-    {
-        ExFreePool(NameInfo1);
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-        return FALSE;
-    }
+   NTSTATUS Status = STATUS_SUCCESS;
+   LPINT SafeBuff;
+   PFLOAT SafeBuffF = NULL;
+   PDC dc;
+   PDC_ATTR Dc_Attr;
+   PTEXTOBJ TextObj;
+   PFONTGDI FontGDI;
+   FT_Face face;
+   FT_CharMap charmap, found = NULL;
+   UINT i, glyph_index, BufferSize;
+   HFONT hFont = 0;
 
-    /* Try to find the pathname in the global font list */
-    IntLockGlobalFonts;
-    for (ListEntry = FontListHead.Flink;
-         ListEntry != &FontListHead;
-         ListEntry = ListEntry->Flink)
-    {
-        FontEntry = CONTAINING_RECORD(ListEntry, FONT_ENTRY, ListEntry);
-        if (FontEntry->Font->Filename != NULL)
-        {
-            RtlInitUnicodeString(&EntryFileName , FontEntry->Font->Filename);
-            if (IntGetFullFileName(NameInfo2, Size, &EntryFileName))
-            {
-                if (RtlEqualUnicodeString(&NameInfo1->Name, &NameInfo2->Name, FALSE))
-                {
-                    /* found */
-                    FontFamilyFillInfo(&Info, FontEntry->FaceName.Buffer, FontEntry->Font);
-                    bFound = TRUE;
-                    break;
-                }
-            }
-        }
-    }
-    IntUnLockGlobalFonts;
+   if(pwc)
+   {
+     _SEH_TRY
+     {
+       ProbeForRead(pwc,
+           sizeof(PWSTR),
+                      1);
+     }
+     _SEH_HANDLE
+     {
+      Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+   }
+   if (!NT_SUCCESS(Status))
+   {
+      SetLastWin32Error(Status);
+      return FALSE;
+   }
 
-    /* Free the buffers */
-    ExFreePool(NameInfo1);
-    ExFreePool(NameInfo2);
+   BufferSize = Count * sizeof(INT); // Same size!
+   SafeBuff = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT);
+   if (!fl) SafeBuffF = (PFLOAT) SafeBuff;
+   if (SafeBuff == NULL)
+   {
+      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+      return FALSE;
+   }
 
-    if (!bFound && dwType != 5)
-    {
-        /* Font could not be found in system table
-           dwType == 5 will still handle this */
-        return FALSE;
-    }
+   dc = DC_LockDc(hDC);
+   if (dc == NULL)
+   {
+      ExFreePool(SafeBuff);
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return FALSE;
+   }
+   Dc_Attr = dc->pDc_Attr;
+   if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+   hFont = Dc_Attr->hlfntNew;
+   TextObj = TEXTOBJ_LockText(hFont);
+   DC_UnlockDc(dc);
 
-    switch(dwType)
-    {
-        case 0: /* FIXME: returns 1 or 2, don't know what this is atm */
-            *(DWORD*)pBuffer = 1;
-            *pdwBytes = sizeof(DWORD);
-            break;
+   if (TextObj == NULL)
+   {
+      ExFreePool(SafeBuff);
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return FALSE;
+   }
 
-        case 1: /* Copy the full font name */
-            Size = wcslen(Info.EnumLogFontEx.elfFullName) + 1;
-            Size = min(Size , LF_FULLFACESIZE) * sizeof(WCHAR);
-            memcpy(pBuffer, Info.EnumLogFontEx.elfFullName, Size);
-            // FIXME: Do we have to zeroterminate?
-            *pdwBytes = Size;
-            break;
+   FontGDI = ObjToGDI(TextObj->Font, FONT);
 
-        case 2: /* Copy a LOGFONTW structure */
-            Info.EnumLogFontEx.elfLogFont.lfWidth = 0;
-            memcpy(pBuffer, &Info.EnumLogFontEx.elfLogFont, sizeof(LOGFONTW));
-            *pdwBytes = sizeof(LOGFONTW);
+   face = FontGDI->face;
+   if (face->charmap == NULL)
+   {
+      for (i = 0; i < face->num_charmaps; i++)
+      {
+         charmap = face->charmaps[i];
+         if (charmap->encoding != 0)
+         {
+            found = charmap;
             break;
+         }
+      }
 
-        case 3: /* FIXME: What exactly is copied here? */
-            *(DWORD*)pBuffer = 1;
-            *pdwBytes = sizeof(DWORD*);
-            break;
+      if (!found)
+      {
+         DPRINT1("WARNING: Could not find desired charmap!\n");
+         ExFreePool(SafeBuff);
+         SetLastWin32Error(ERROR_INVALID_HANDLE);
+         return FALSE;
+      }
 
-        case 5: /* Looks like a BOOL that is copied, TRUE, if the font was not found */
-            *(BOOL*)pBuffer = !bFound;
-            *pdwBytes = sizeof(BOOL);
-            break;
+      IntLockFreeType;
+      FT_Set_Charmap(face, found);
+      IntUnLockFreeType;
+   }
 
-        default:
-            return FALSE;
-    }
+   IntLockFreeType;
+   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));
 
-    return TRUE;
+   for (i = FirstChar; i < FirstChar+Count; i++)
+   {
+      if (pwc)
+      {
+         if (fl & GCW_INDICES)
+          glyph_index = pwc[i - FirstChar];
+         else
+          glyph_index = FT_Get_Char_Index(face, pwc[i - FirstChar]);
+      }
+      else
+      {
+         if (fl & GCW_INDICES)
+             glyph_index = i;
+         else
+             glyph_index = FT_Get_Char_Index(face, i);
+      }
+      FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
+      if (!fl)
+        SafeBuffF[i - FirstChar] = (FLOAT) ((face->glyph->advance.x + 32) >> 6);
+      else
+        SafeBuff[i - FirstChar] = (face->glyph->advance.x + 32) >> 6;
+   }
+   IntUnLockFreeType;
+   TEXTOBJ_UnlockText(TextObj);
+   MmCopyToCaller(Buffer, SafeBuff, BufferSize);
+   ExFreePool(SafeBuff);
+   return TRUE;
 }
 
-W32KAPI BOOL APIENTRY
-NtGdiGetFontResourceInfoInternalW(
-    IN LPWSTR   pwszFiles,
-    IN ULONG    cwc,
-    IN ULONG    cFiles,
-    IN UINT     cjIn,
-    OUT LPDWORD pdwBytes,
-    OUT LPVOID  pvBuf,
-    IN DWORD    dwType)
+
+ /*
+ * @implemented
+ */
+DWORD
+STDCALL
+NtGdiGetGlyphIndicesW(
+    IN HDC hdc,
+    IN OPTIONAL LPWSTR UnSafepwc,
+    IN INT cwc,
+    OUT OPTIONAL LPWORD UnSafepgi,
+    IN DWORD iMode)
 {
-    NTSTATUS Status = STATUS_SUCCESS;
-    DWORD dwBytes;
-    UNICODE_STRING SafeFileNames;
-    BOOL bRet = FALSE;
-    ULONG cbStringSize;
+  PDC dc;
+  PDC_ATTR Dc_Attr;
+  PTEXTOBJ TextObj;
+  PFONTGDI FontGDI;
+  HFONT hFont = 0;
+  NTSTATUS Status = STATUS_SUCCESS;
+  OUTLINETEXTMETRICW *potm;
+  INT i;
+  FT_Face face;
+  WCHAR DefChar = 0xffff;
+  PWSTR Buffer = NULL;
+  ULONG Size;
 
-    union
-    {
-        LOGFONTW logfontw;
-        WCHAR FullName[LF_FULLFACESIZE];
-    } Buffer;
+  if ((!UnSafepwc) && (!UnSafepgi)) return cwc;
 
-    /* FIXME: handle cFiles > 0 */
+  dc = DC_LockDc(hdc);
+  if (!dc)
+   {
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return GDI_ERROR;
+   }
+  Dc_Attr = dc->pDc_Attr;
+  if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+  hFont = Dc_Attr->hlfntNew;
+  TextObj = TEXTOBJ_LockText(hFont);
+  DC_UnlockDc(dc);
+  if (!TextObj)
+   {
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return GDI_ERROR;
+   }
 
-    /* Check for valid dwType values
-       dwType == 4 seems to be handled by gdi32 only */
-    if (dwType == 4 || dwType > 5)
-    {
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
-        return FALSE;
-    }
+  FontGDI = ObjToGDI(TextObj->Font, FONT);
+  TEXTOBJ_UnlockText(TextObj);
 
-    /* Allocate a safe unicode string buffer */
-    cbStringSize = cwc * sizeof(WCHAR);
-    SafeFileNames.MaximumLength = SafeFileNames.Length = cbStringSize - sizeof(WCHAR);
-    SafeFileNames.Buffer = ExAllocatePoolWithTag(PagedPool,
-                                                 cbStringSize,
-                                                 TAG('R','T','S','U'));
-    if (!SafeFileNames.Buffer)
-    {
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-        return FALSE;
-    }
+  Buffer = ExAllocatePoolWithTag(PagedPool, cwc*sizeof(WORD), TAG_GDITEXT);
+  if (!Buffer)
+  {
+     SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+     return GDI_ERROR;
+  }
 
-    /* Check buffers and copy pwszFiles to safe unicode string */
-    _SEH_TRY
-    {
-        ProbeForRead(pwszFiles, cbStringSize, 1);
-        ProbeForWrite(pdwBytes, sizeof(DWORD), 1);
-        ProbeForWrite(pvBuf, cjIn, 1);
+  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)
+     {
+        Status = ERROR_NOT_ENOUGH_MEMORY;
+        goto ErrorRet;
+     }
+     IntGetOutlineTextMetrics(FontGDI, Size, potm);
+     DefChar = potm->otmTextMetrics.tmDefaultChar; // May need this.
+     ExFreePool(potm);
+  }
 
-        RtlCopyMemory(SafeFileNames.Buffer, pwszFiles, cbStringSize);
-    }
-    _SEH_HANDLE
-    {
-        Status = _SEH_GetExceptionCode();
-    }
-    _SEH_END
+  _SEH_TRY
+  {
+    ProbeForRead(UnSafepwc,
+             sizeof(PWSTR),
+                         1);
+  }
+  _SEH_HANDLE
+  {
+    Status = _SEH_GetExceptionCode();
+  }
+  _SEH_END;
 
-    if(!NT_SUCCESS(Status))
-    {
-        SetLastNtError(Status);
-        /* Free the string buffer for the safe filename */
-        ExFreePool(SafeFileNames.Buffer);
-        return FALSE;
-    }
+  if (!NT_SUCCESS(Status)) goto ErrorRet;
 
-    /* Do the actual call */
-    bRet = IntGdiGetFontResourceInfo(&SafeFileNames, &Buffer, &dwBytes, dwType);
+  IntLockFreeType;
+  face = FontGDI->face;
 
-    /* Check if succeeded and the buffer is big enough */
-    if (bRet && cjIn >= dwBytes)
-    {
-        /* Copy the data back to caller */
-        _SEH_TRY
-        {
-            /* Buffers are already probed */
-            RtlCopyMemory(pvBuf, &Buffer, dwBytes);
-            *pdwBytes = dwBytes;
-        }
-        _SEH_HANDLE
-        {
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END
+  for (i = 0; i < cwc; i++)
+  {
+      Buffer[i] = FT_Get_Char_Index(face, UnSafepwc[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;
+      }
+  }
 
-        if(!NT_SUCCESS(Status))
-        {
-            SetLastNtError(Status);
-            bRet = FALSE;
-        }
-    }
+  IntUnLockFreeType;
 
-    /* Free the string for the safe filenames */
-    ExFreePool(SafeFileNames.Buffer);
+  _SEH_TRY
+  {
+    ProbeForWrite(UnSafepgi,
+               sizeof(WORD),
+                          1);
+    RtlCopyMemory(UnSafepgi,
+                     Buffer,
+            cwc*sizeof(WORD));
+  }
+  _SEH_HANDLE
+  {
+    Status = _SEH_GetExceptionCode();
+  }
+  _SEH_END;
 
-    return bRet;
+ErrorRet:
+  ExFreePoolWithTag(Buffer, TAG_GDITEXT);
+  if (NT_SUCCESS(Status)) return cwc;
+  SetLastWin32Error(Status);
+  return GDI_ERROR;
 }
 
+
 /* EOF */
index e39e980..d0b6cba 100644 (file)
@@ -750,21 +750,34 @@ EngDitherColor(
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL APIENTRY
 EngQuerySystemAttribute(
    IN ENG_SYSTEM_ATTRIBUTE CapNum,
    OUT PDWORD pCapability)
 {
+  SYSTEM_BASIC_INFORMATION sbi;
+  SYSTEM_PROCESSOR_INFORMATION spi;
+
    switch (CapNum)
    {
       case EngNumberOfProcessors:
-         *pCapability = 1;
+         NtQuerySystemInformation(
+                SystemBasicInformation,
+               &sbi,
+                sizeof(SYSTEM_BASIC_INFORMATION),
+                NULL);
+         *pCapability = sbi.NumberOfProcessors;
          return TRUE;
 
       case EngProcessorFeature:
-         *pCapability = 0;
+         NtQuerySystemInformation(
+                SystemProcessorInformation,
+               &spi,
+                sizeof(SYSTEM_PROCESSOR_INFORMATION),
+                NULL);
+         *pCapability = spi.ProcessorFeatureBits;
          return TRUE;
 
       default: