Another coordinate transformation change. Fixes final problem with bug 1201.
[reactos.git] / reactos / subsys / win32k / objects / text.c
index d3977d7..13fb957 100644 (file)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 /* $Id$ */
+
 #include <w32k.h>
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
 #include <freetype/tttables.h>
 
+#define NDEBUG
+#include <debug.h>
+
 FT_Library  library;
 
 typedef struct _FONT_ENTRY {
@@ -110,7 +114,7 @@ static CHARSETINFO FontTci[MAXTCIINDEX] = {
   { DEFAULT_CHARSET, 0, FS(0)},
   /* reserved for system */
   { DEFAULT_CHARSET, 0, FS(0)},
-  { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
+  { SYMBOL_CHARSET, 42 /* CP_SYMBOL */, FS(31)},
 };
 
 VOID FASTCALL
@@ -185,7 +189,7 @@ IntLoadSystemFonts(VOID)
          return;
       }
 
-      FileName.Buffer = ExAllocatePool(PagedPool, MAX_PATH);
+      FileName.Buffer = ExAllocatePool(PagedPool, MAX_PATH * sizeof(WCHAR));
       if (FileName.Buffer == NULL)
       {
          ExFreePool(DirInfoBuffer);
@@ -193,7 +197,7 @@ IntLoadSystemFonts(VOID)
          return;
       }
       FileName.Length = 0;
-      FileName.MaximumLength = MAX_PATH;
+      FileName.MaximumLength = MAX_PATH * sizeof(WCHAR);
 
       while (1)
       {
@@ -251,23 +255,24 @@ IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
    NTSTATUS Status;
    HANDLE FileHandle;
    OBJECT_ATTRIBUTES ObjectAttributes;
-   FILE_STANDARD_INFORMATION FileStdInfo;
-   PVOID Buffer;
+   PVOID Buffer = NULL;
    IO_STATUS_BLOCK Iosb;
    INT Error;
    FT_Face Face;
    ANSI_STRING AnsiFaceName;
    PFONT_ENTRY Entry;
+   PSECTION_OBJECT SectionObject;
+   ULONG ViewSize = 0;
 
    /* Open the font file */
 
    InitializeObjectAttributes(&ObjectAttributes, FileName, 0, NULL, NULL);
    Status = ZwOpenFile(
       &FileHandle,
-      GENERIC_READ | SYNCHRONIZE,
+      FILE_GENERIC_READ | SYNCHRONIZE,
       &ObjectAttributes,
       &Iosb,
-      0,
+      FILE_SHARE_READ,
       FILE_SYNCHRONOUS_IO_NONALERT);
 
    if (!NT_SUCCESS(Status))
@@ -276,64 +281,30 @@ IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
       return 0;
    }
 
-   /* Get the size of the file */
-
-   Status = NtQueryInformationFile(
-      FileHandle,
-      &Iosb,
-      &FileStdInfo,
-      sizeof(FileStdInfo),
-      FileStandardInformation);
-
+   Status = MmCreateSection(&SectionObject, SECTION_ALL_ACCESS,
+                            NULL, NULL, PAGE_READONLY,
+                            0, FileHandle, NULL);
    if (!NT_SUCCESS(Status))
    {
-      DPRINT("Could not get file size\n");
+      DPRINT("Could not map file: %wZ\n", FileName);
       ZwClose(FileHandle);
       return 0;
    }
 
-   /* Allocate pageable memory for the font */
-
-   Buffer = ExAllocatePoolWithTag(
-      PagedPool,
-      FileStdInfo.EndOfFile.u.LowPart,
-      TAG_FNTFILE);
-
-   if (Buffer == NULL)
-   {
-      DPRINT("Could not allocate memory for font");
-      ZwClose(FileHandle);
-      return 0;
-   }
-
-   /* Load the font into memory chunk */
-
-   Status = ZwReadFile(
-      FileHandle,
-      NULL,
-      NULL,
-      NULL,
-      &Iosb,
-      Buffer,
-      FileStdInfo.EndOfFile.u.LowPart,
-      NULL,
-      NULL);
+   ZwClose(FileHandle);
 
+   Status = MmMapViewInSystemSpace(SectionObject, &Buffer, &ViewSize);
    if (!NT_SUCCESS(Status))
    {
-      DPRINT("Could not read the font file into memory");
-      ExFreePool(Buffer);
-      ZwClose(FileHandle);
-      return 0;
+      DPRINT("Could not map file: %wZ\n", FileName);
+      return Status;
    }
 
-   ZwClose(FileHandle);
-
    IntLockFreeType;
    Error = FT_New_Memory_Face(
       library,
       Buffer,
-      FileStdInfo.EndOfFile.u.LowPart,
+      ViewSize,
       0,
       &Face);
    IntUnLockFreeType;
@@ -344,7 +315,7 @@ IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
          DPRINT("Unknown font file format\n");
       else
          DPRINT("Error reading font file (error code: %u)\n", Error);
-      ExFreePool(Buffer);
+      ObDereferenceObject(SectionObject);
       return 0;
    }
 
@@ -352,7 +323,7 @@ IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
    if (!Entry)
    {
       FT_Done_Face(Face);
-      ExFreePool(Buffer);
+      ObDereferenceObject(SectionObject);
       SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
       return 0;
    }
@@ -361,7 +332,7 @@ IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
    if(FontGDI == NULL)
    {
       FT_Done_Face(Face);
-      ExFreePool(Buffer);
+      ObDereferenceObject(SectionObject);
       ExFreePool(Entry);
       SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
       return 0;
@@ -427,18 +398,14 @@ IntGetFontRenderMode(LOGFONTW *logfont)
 {
   switch(logfont->lfQuality)
   {
-    //case ANTIALIASED_QUALITY:
-    case DEFAULT_QUALITY:
-      return FT_RENDER_MODE_NORMAL;
+    case NONANTIALIASED_QUALITY:
+      return FT_RENDER_MODE_MONO;
     case DRAFT_QUALITY:
       return FT_RENDER_MODE_LIGHT;
-    //case NONANTIALIASED_QUALITY:
-    case PROOF_QUALITY:
-      return FT_RENDER_MODE_MONO;
-    //case CLEARTYPE_QUALITY:
-    //  return FT_RENDER_MODE_LCD;
+/*    case CLEARTYPE_QUALITY:
+        return FT_RENDER_MODE_LCD; */
   }
-  return FT_RENDER_MODE_MONO;
+  return FT_RENDER_MODE_NORMAL;
 }
 
 int
@@ -505,7 +472,7 @@ TextIntCreateFontIndirect(CONST LPLOGFONTW lf, HFONT *NewFont)
        /* this should really depend on whether GM_ADVANCED is set */
        TextObj->logfont.lfOrientation = TextObj->logfont.lfEscapement;
       }
-      TEXTOBJ_UnlockText(*NewFont);
+      TEXTOBJ_UnlockText(TextObj);
     }
     else
     {
@@ -1044,7 +1011,7 @@ FontFamilyFillInfo(PFONTFAMILYINFO Info, PCWSTR FaceName, PFONTGDI FontGDI)
   TEXTMETRICW *TM;
   NEWTEXTMETRICW *Ntm;
 
-  ZeroMemory(Info, sizeof(FONTFAMILYINFO));
+  RtlZeroMemory(Info, sizeof(FONTFAMILYINFO));
   Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
   Otm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
   if (NULL == Otm)
@@ -1486,14 +1453,14 @@ NtGdiExtTextOut(
 
    DC *dc;
    SURFOBJ *SurfObj;
-   BITMAPOBJ *BitmapObj;
+   BITMAPOBJ *BitmapObj = NULL;
    int error, glyph_index, n, i;
    FT_Face face;
    FT_GlyphSlot glyph;
    LONGLONG TextLeft, RealXStart;
-   ULONG TextTop, pitch, previous, BackgroundLeft;
+   ULONG TextTop, previous, BackgroundLeft;
    FT_Bool use_kerning;
-   RECTL DestRect, MaskRect;
+   RECTL DestRect, MaskRect, SpecifiedDestRect;
    POINTL SourcePoint, BrushOrigin;
    HBRUSH hBrushFg = NULL;
    PGDIBRUSHOBJ BrushFg = NULL;
@@ -1517,13 +1484,34 @@ NtGdiExtTextOut(
    NTSTATUS Status;
    INT *Dx = NULL;
    POINT Start;
+   BOOL DoBreak = FALSE;
 
+   // 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->IsIC)
+   {
+      DC_UnlockDc(dc);
+      /* Yes, Windows really returns TRUE in this case */
+      return TRUE;
+   }
+
+   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))
+      {
+         SetLastWin32Error(ERROR_INVALID_PARAMETER);
+         return FALSE;
+      }
+      IntLPtoDP(dc, (POINT *) &SpecifiedDestRect, 2);
+   }
 
    if (NULL != UnsafeDx && Count > 0)
    {
@@ -1560,14 +1548,14 @@ NtGdiExtTextOut(
    else
    {
       Mode = PalDestGDI->Mode;
-      PALETTE_UnlockPalette(dc->w.hPalette);
+      PALETTE_UnlockPalette(PalDestGDI);
    }
    XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
    if ( !XlateObj )
    {
       goto fail;
    }
-   hBrushFg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.textColor));
+   hBrushFg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.textColor), 0);
    if ( !hBrushFg )
    {
       goto fail;
@@ -1580,7 +1568,7 @@ NtGdiExtTextOut(
    IntGdiInitBrushInstance(&BrushFgInst, BrushFg, NULL);
    if ((fuOptions & ETO_OPAQUE) || dc->w.backgroundMode == OPAQUE)
    {
-      hBrushBg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.backgroundColor));
+      hBrushBg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.backgroundColor), 0);
       if ( !hBrushBg )
       {
          goto fail;
@@ -1607,13 +1595,13 @@ NtGdiExtTextOut(
 
    if ((fuOptions & ETO_OPAQUE) && lprc)
    {
-      MmCopyFromCaller(&DestRect, lprc, sizeof(RECT));
-      DestRect.left += dc->w.DCOrgX;
-      DestRect.top += dc->w.DCOrgY;
-      DestRect.right += dc->w.DCOrgX;
-      DestRect.bottom += dc->w.DCOrgY;
+      DestRect.left   = SpecifiedDestRect.left   + dc->w.DCOrgX;
+      DestRect.top    = SpecifiedDestRect.top    + dc->w.DCOrgY;
+      DestRect.right  = SpecifiedDestRect.right  + dc->w.DCOrgX;
+      DestRect.bottom = SpecifiedDestRect.bottom + dc->w.DCOrgY;
+      IntLPtoDP(dc, (LPPOINT)&DestRect, 2);
       IntEngBitBlt(
-         BitmapObj,
+         &BitmapObj->SurfObj,
          NULL,
          NULL,
          dc->CombinedClip,
@@ -1623,7 +1611,7 @@ NtGdiExtTextOut(
          &SourcePoint,
          &BrushBgInst.BrushObject,
          &BrushOrigin,
-         PATCOPY);
+         ROP3_TO_ROP4(PATCOPY));
       fuOptions &= ~ETO_OPAQUE;
    }
    else
@@ -1645,6 +1633,7 @@ NtGdiExtTextOut(
    FontGDI = ObjToGDI(FontObj, FONT);
    ASSERT(FontGDI);
 
+   IntLockFreeType;
    face = FontGDI->face;
    if (face->charmap == NULL)
    {
@@ -1665,10 +1654,8 @@ NtGdiExtTextOut(
       {
          DPRINT1("WARNING: Could not find desired charmap!\n");
       }
-      IntLockFreeType;
       error = FT_Set_Charmap(face, found);
-      IntUnLockFreeType;
-      if (error)
+         if (error)
       {
          DPRINT1("WARNING: Could not set the charmap!\n");
       }
@@ -1680,7 +1667,6 @@ NtGdiExtTextOut(
    else
       RenderMode = FT_RENDER_MODE_MONO;
 
-   IntLockFreeType;
    error = FT_Set_Pixel_Sizes(
       face,
       TextObj->logfont.lfWidth,
@@ -1688,10 +1674,10 @@ NtGdiExtTextOut(
       (TextObj->logfont.lfHeight < 0 ?
       - TextObj->logfont.lfHeight :
       TextObj->logfont.lfHeight == 0 ? 11 : TextObj->logfont.lfHeight));
-   IntUnLockFreeType;
    if (error)
    {
       DPRINT1("Error in setting pixel sizes: %u\n", error);
+      IntUnLockFreeType;
       goto fail;
    }
 
@@ -1736,10 +1722,8 @@ NtGdiExtTextOut(
 
       for (i = Start; i < Count; i++)
       {
-         IntLockFreeType;
          glyph_index = FT_Get_Char_Index(face, *TempText);
          error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
-         IntUnLockFreeType;
 
          if (error)
          {
@@ -1752,9 +1736,7 @@ NtGdiExtTextOut(
          if (use_kerning && previous && glyph_index)
          {
             FT_Vector delta;
-            IntLockFreeType;
             FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
-            IntUnLockFreeType;
             TextWidth += delta.x;
          }
 
@@ -1786,14 +1768,13 @@ NtGdiExtTextOut(
 
    for (i = 0; i < Count; i++)
    {
-      IntLockFreeType;
       glyph_index = FT_Get_Char_Index(face, *String);
       error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
-      IntUnLockFreeType;
 
       if (error)
       {
          DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
+        IntUnLockFreeType;
          goto fail;
       }
 
@@ -1803,25 +1784,18 @@ NtGdiExtTextOut(
       if (use_kerning && previous && glyph_index && NULL == Dx)
       {
          FT_Vector delta;
-         IntLockFreeType;
          FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
-         IntUnLockFreeType;
          TextLeft += delta.x;
       }
 
       if (glyph->format == ft_glyph_format_outline)
       {
-         IntLockFreeType;
          error = FT_Render_Glyph(glyph, RenderMode);
-         IntUnLockFreeType;
          if (error)
          {
             DPRINT1("WARNING: Failed to render glyph!\n");
             goto fail;
          }
-         pitch = glyph->bitmap.pitch;
-      } else {
-         pitch = glyph->bitmap.width;
       }
 
       if (fuOptions & ETO_OPAQUE)
@@ -1831,7 +1805,7 @@ NtGdiExtTextOut(
          DestRect.top = TextTop + yoff - ((face->size->metrics.ascender + 32) >> 6);
          DestRect.bottom = TextTop + yoff + ((32 - face->size->metrics.descender) >> 6);
          IntEngBitBlt(
-            BitmapObj,
+            &BitmapObj->SurfObj,
             NULL,
             NULL,
             dc->CombinedClip,
@@ -1841,7 +1815,7 @@ NtGdiExtTextOut(
             &SourcePoint,
             &BrushBgInst.BrushObject,
             &BrushOrigin,
-            PATCOPY);
+            ROP3_TO_ROP4(PATCOPY));
          BackgroundLeft = DestRect.right;
       }
 
@@ -1859,12 +1833,21 @@ NtGdiExtTextOut(
        * We should create the bitmap out of the loop at the biggest possible
        * glyph size. Then use memset with 0 to clear it and sourcerect to
        * limit the work of the transbitblt.
+       *
+       * FIXME: DIB bitmaps should have an lDelta which is a multiple of 4.
+       * Here we pass in the pitch from the FreeType bitmap, which is not
+       * guaranteed to be a multiple of 4. If it's not, we should expand
+       * the FreeType bitmap to a temporary bitmap.
        */
 
-      HSourceGlyph = EngCreateBitmap(bitSize, pitch, (glyph->bitmap.pixel_mode == ft_pixel_mode_grays) ? BMF_8BPP : BMF_1BPP, BMF_TOPDOWN, glyph->bitmap.buffer);
+      HSourceGlyph = EngCreateBitmap(bitSize, glyph->bitmap.pitch,
+                                     (glyph->bitmap.pixel_mode == ft_pixel_mode_grays) ?
+                                     BMF_8BPP : BMF_1BPP, BMF_TOPDOWN,
+                                     glyph->bitmap.buffer);
       if ( !HSourceGlyph )
       {
         DPRINT1("WARNING: EngLockSurface() failed!\n");
+       IntUnLockFreeType;
         goto fail;
       }
       SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
@@ -1872,6 +1855,7 @@ NtGdiExtTextOut(
       {
         EngDeleteSurface((HSURF)HSourceGlyph);
         DPRINT1("WARNING: EngLockSurface() failed!\n");
+       IntUnLockFreeType;
         goto fail;
       }
 
@@ -1880,6 +1864,17 @@ NtGdiExtTextOut(
        * brush.
        */
 
+      if (lprc &&
+          (fuOptions & ETO_CLIPPED) &&
+          DestRect.right >= SpecifiedDestRect.right + dc->w.DCOrgX)
+      {
+         // 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->w.DCOrgX;
+         DoBreak = TRUE;
+      }
+
       IntEngMaskBlt(
          SurfObj,
          SourceGlyphSurf,
@@ -1895,6 +1890,11 @@ NtGdiExtTextOut(
       EngUnlockSurface(SourceGlyphSurf);
       EngDeleteSurface((HSURF)HSourceGlyph);
 
+      if (DoBreak)
+      {
+         break;
+      }
+
       if (NULL == Dx)
       {
          TextLeft += glyph->advance.x;
@@ -1908,23 +1908,25 @@ NtGdiExtTextOut(
       String++;
    }
 
+   IntUnLockFreeType;
+
    EngDeleteXlate(XlateObj);
    EngDeleteXlate(XlateObj2);
-   BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
+   BITMAPOBJ_UnlockBitmap(BitmapObj);
    if(TextObj != NULL)
-     TEXTOBJ_UnlockText(dc->w.hFont);
+     TEXTOBJ_UnlockText(TextObj);
    if (hBrushBg != NULL)
    {
-      BRUSHOBJ_UnlockBrush(hBrushBg);
+      BRUSHOBJ_UnlockBrush(BrushBg);
       NtGdiDeleteObject(hBrushBg);
    }
-   BRUSHOBJ_UnlockBrush(hBrushFg);
+   BRUSHOBJ_UnlockBrush(BrushFg);
    NtGdiDeleteObject(hBrushFg);
    if (NULL != Dx)
    {
       ExFreePool(Dx);
    }
-   DC_UnlockDc( hDC );
+   DC_UnlockDc( dc );
 
    return TRUE;
 
@@ -1934,23 +1936,23 @@ fail:
    if ( XlateObj != NULL )
       EngDeleteXlate(XlateObj);
    if(TextObj != NULL)
-     TEXTOBJ_UnlockText(dc->w.hFont);
-   BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
+     TEXTOBJ_UnlockText(TextObj);
+   BITMAPOBJ_UnlockBitmap(BitmapObj);
    if (hBrushBg != NULL)
    {
-      BRUSHOBJ_UnlockBrush(hBrushBg);
+      BRUSHOBJ_UnlockBrush(BrushBg);
       NtGdiDeleteObject(hBrushBg);
    }
    if (hBrushFg != NULL)
    {
-      BRUSHOBJ_UnlockBrush(hBrushFg);
+      BRUSHOBJ_UnlockBrush(BrushFg);
       NtGdiDeleteObject(hBrushFg);
    }
    if (NULL != Dx)
    {
       ExFreePool(Dx);
    }
-   DC_UnlockDc(hDC);
+   DC_UnlockDc(dc);
 
    return FALSE;
 }
@@ -2038,7 +2040,7 @@ NtGdiGetCharWidth32(HDC  hDC,
    }
    hFont = dc->w.hFont;
    TextObj = TEXTOBJ_LockText(hFont);
-   DC_UnlockDc(hDC);
+   DC_UnlockDc(dc);
 
    if (TextObj == NULL)
    {
@@ -2090,7 +2092,7 @@ NtGdiGetCharWidth32(HDC  hDC,
       SafeBuffer[i - FirstChar] = (face->glyph->advance.x + 32) >> 6;
    }
    IntUnLockFreeType;
-   TEXTOBJ_UnlockText(hFont);
+   TEXTOBJ_UnlockText(TextObj);
    MmCopyToCaller(Buffer, SafeBuffer, BufferSize);
    ExFreePool(SafeBuffer);
    return TRUE;
@@ -2115,15 +2117,17 @@ NtGdiGetFontLanguageInfo(HDC  hDC)
   return 0;
 }
 
-DWORD
-STDCALL
-NtGdiGetGlyphOutline(HDC  hDC,
-                           UINT  Char,
-                           UINT  Format,
-                           LPGLYPHMETRICS  gm,
-                           DWORD  Bufsize,
-                           LPVOID  Buffer,
-                           CONST LPMAT2 mat2)
+ULONG
+APIENTRY
+NtGdiGetGlyphOutline(
+    IN HDC hdc,
+    IN WCHAR wch,
+    IN UINT iFormat,
+    OUT LPGLYPHMETRICS pgm,
+    IN ULONG cjBuf,
+    OUT OPTIONAL PVOID pvBuf,
+    IN LPMAT2 pmat2,
+    IN BOOL bIgnoreRotation)
 {
   UNIMPLEMENTED;
   return 0;
@@ -2150,9 +2154,10 @@ NtGdiGetOutlineTextMetrics(HDC  hDC,
 }
 
 BOOL
-STDCALL
-NtGdiGetRasterizerCaps(LPRASTERIZER_STATUS  rs,
-                            UINT  Size)
+APIENTRY
+NtGdiGetRasterizerCaps(
+    OUT LPRASTERIZER_STATUS praststat,
+    IN ULONG cjBytes)
 {
   UNIMPLEMENTED;
   return FALSE;
@@ -2166,11 +2171,12 @@ NtGdiGetTextCharset(HDC  hDC)
   return 0;
 }
 
-UINT
-STDCALL
-NtGdiGetTextCharsetInfo(HDC  hDC,
-                             LPFONTSIGNATURE  Sig,
-                             DWORD  Flags)
+INT
+APIENTRY
+NtGdiGetTextCharsetInfo(
+    IN HDC hdc,
+    OUT OPTIONAL LPFONTSIGNATURE lpSig,
+    IN DWORD dwFlags)
 {
   UNIMPLEMENTED;
   return 0;
@@ -2383,8 +2389,8 @@ NtGdiGetTextExtentExPoint(HDC hDC,
   }
   else
     Result = FALSE;
-  TEXTOBJ_UnlockText(dc->w.hFont);
-  DC_UnlockDc(hDC);
+  TEXTOBJ_UnlockText(TextObj);
+  DC_UnlockDc(dc);
 
   ExFreePool(String);
   if (! Result)
@@ -2507,11 +2513,11 @@ NtGdiGetTextExtentPoint32(HDC hDC,
   {
     Result = TextIntGetTextExtentPoint (
       dc, TextObj, String, Count, 0, NULL, NULL, &Size);
-    TEXTOBJ_UnlockText(dc->w.hFont);
+    TEXTOBJ_UnlockText(TextObj);
   }
   else
     Result = FALSE;
-  DC_UnlockDc(hDC);
+  DC_UnlockDc(dc);
 
   ExFreePool(String);
   if (! Result)
@@ -2533,6 +2539,7 @@ INT STDCALL
 NtGdiGetTextFace(HDC hDC, INT Count, LPWSTR FaceName)
 {
    PDC Dc;
+   HFONT hFont;
    PTEXTOBJ TextObj;
    NTSTATUS Status;
 
@@ -2542,11 +2549,14 @@ NtGdiGetTextFace(HDC hDC, INT Count, LPWSTR FaceName)
       SetLastWin32Error(ERROR_INVALID_HANDLE);
       return FALSE;
    }
-   TextObj = TEXTOBJ_LockText(Dc->w.hFont);
-   DC_UnlockDc(hDC);
+   hFont = Dc->w.hFont;
+   DC_UnlockDc(Dc);
 
+   TextObj = TEXTOBJ_LockText(hFont);
+   ASSERT(TextObj != NULL);
    Count = min(Count, wcslen(TextObj->logfont.lfFaceName));
    Status = MmCopyToCaller(FaceName, TextObj->logfont.lfFaceName, Count * sizeof(WCHAR));
+   TEXTOBJ_UnlockText(TextObj);
    if (!NT_SUCCESS(Status))
    {
       SetLastNtError(Status);
@@ -2630,13 +2640,13 @@ NtGdiGetTextMetrics(HDC hDC,
               Status = MmCopyToCaller(tm, &SafeTm, sizeof(TEXTMETRICW));
             }
        }
-      TEXTOBJ_UnlockText(dc->w.hFont);
+      TEXTOBJ_UnlockText(TextObj);
     }
   else
     {
       Status = STATUS_INVALID_HANDLE;
     }
-  DC_UnlockDc(hDC);
+  DC_UnlockDc(dc);
 
   if(!NT_SUCCESS(Status))
     {
@@ -2661,7 +2671,7 @@ BOOL
 STDCALL
 NtGdiRemoveFontResource(LPCWSTR  FileName)
 {
-  UNIMPLEMENTED;
+  DPRINT1("NtGdiRemoveFontResource is UNIMPLEMENTED\n");
   return FALSE;
 }
 
@@ -2690,7 +2700,7 @@ NtGdiSetTextAlign(HDC  hDC,
     }
   prevAlign = dc->w.textAlign;
   dc->w.textAlign = Mode;
-  DC_UnlockDc( hDC );
+  DC_UnlockDc( dc );
   return  prevAlign;
 }
 
@@ -2712,7 +2722,7 @@ NtGdiSetTextColor(HDC hDC,
   oldColor = dc->w.textColor;
   dc->w.textColor = color;
   hBrush = dc->w.hBrush;
-  DC_UnlockDc( hDC );
+  DC_UnlockDc( dc );
   NtGdiSelectObject(hDC, hBrush);
   return  oldColor;
 }
@@ -2760,7 +2770,7 @@ NtGdiGetFontData(
    }
    hFont = Dc->w.hFont;
    TextObj = TEXTOBJ_LockText(hFont);
-   DC_UnlockDc(hDC);
+   DC_UnlockDc(Dc);
 
    if (TextObj == NULL)
    {
@@ -2787,7 +2797,7 @@ NtGdiGetFontData(
 
    IntUnLockFreeType;
 
-   TEXTOBJ_UnlockText(hFont);
+   TEXTOBJ_UnlockText(TextObj);
 
    return Result;
 }
@@ -2847,7 +2857,7 @@ GetFontScore(LOGFONTW *LogFont, PUNICODE_STRING FaceName, PFONTGDI FontGDI)
   return Score;
 }
 
-static inline VOID
+static __inline VOID
 FindBestFontFromList(FONTOBJ **FontObj, UINT *MatchScore, LOGFONTW *LogFont,
                      PUNICODE_STRING FaceName, PLIST_ENTRY Head)
 {
@@ -2874,7 +2884,7 @@ FindBestFontFromList(FONTOBJ **FontObj, UINT *MatchScore, LOGFONTW *LogFont,
     }
 }
 
-static inline BOOLEAN
+static __inline BOOLEAN
 SubstituteFontFamilyKey(PUNICODE_STRING FaceName,
                         LPCWSTR Key)
 {
@@ -2910,7 +2920,7 @@ SubstituteFontFamilyKey(PUNICODE_STRING FaceName,
   return NT_SUCCESS(Status);
 }
 
-static inline void
+static __inline void
 SubstituteFontFamily(PUNICODE_STRING FaceName, UINT Level)
 {
   if (10 < Level) /* Enough is enough */
@@ -2940,9 +2950,15 @@ TextIntRealizeFont(HFONT FontHandle)
       return STATUS_INVALID_HANDLE;
     }
 
+  if (TextObj->Initialized)
+    {
+      TEXTOBJ_UnlockText(TextObj);
+      return STATUS_SUCCESS;
+    }
+
   if (! RtlCreateUnicodeString(&FaceName, TextObj->logfont.lfFaceName))
     {
-      TEXTOBJ_UnlockText(FontHandle);
+      TEXTOBJ_UnlockText(TextObj);
       return STATUS_NO_MEMORY;
     }
   SubstituteFontFamily(&FaceName, 0);
@@ -2972,11 +2988,12 @@ TextIntRealizeFont(HFONT FontHandle)
     }
   else
     {
+      TextObj->Initialized = TRUE;
       Status = STATUS_SUCCESS;
     }
 
   RtlFreeUnicodeString(&FaceName);
-  TEXTOBJ_UnlockText(FontHandle);
+  TEXTOBJ_UnlockText(TextObj);
 
   ASSERT((NT_SUCCESS(Status) ^ (NULL == TextObj->Font)) != 0);