[NtGDI] Change TextOut
[reactos.git] / win32ss / gdi / ntgdi / font.c
index 01ee171..a48904c 100644 (file)
@@ -3,7 +3,9 @@
  * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            win32ss/gdi/ntgdi/font.c
  * PURPOSE:         Font
- * PROGRAMMER:
+ * PROGRAMMERS:     James Tabor <james.tabor@reactos.org>
+ *                  Timo Kreuzer <timo.kreuzer@reactos.org>
+ *                  Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
  */
 
 /** Includes ******************************************************************/
@@ -107,7 +109,7 @@ GreGetKerningPairs(
   currently selected font. If not valid, GetCharacterPlacement ignores the
   value.
 
-  M$ must use a preset "compiled in" support for each language based releases.
+  MS must use a preset "compiled in" support for each language based releases.
   ReactOS uses FreeType, this will need to be supported. ATM this is hard coded
   for GCPCLASS_LATIN!
 
@@ -117,7 +119,7 @@ DWORD
 FASTCALL
 GreGetCharacterPlacementW(
     HDC hdc,
-    LPWSTR pwsz,
+    LPCWSTR pwsz,
     INT nCount,
     INT nMaxExtent,
     LPGCP_RESULTSW pgcpw,
@@ -291,7 +293,22 @@ FASTCALL
 FontGetObject(PTEXTOBJ plfont, ULONG cjBuffer, PVOID pvBuffer)
 {
     ULONG cjMaxSize;
-    ENUMLOGFONTEXDVW *plf = &plfont->logfont;
+    ENUMLOGFONTEXDVW *plf;
+
+    ASSERT(plfont);
+    plf = &plfont->logfont;
+
+    if (!(plfont->fl & TEXTOBJECT_INIT))
+    {
+        NTSTATUS Status;
+        DPRINT1("FontGetObject font not initialized!\n");
+
+        Status = TextIntRealizeFont(plfont->BaseObject.hHmgr, plfont);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("FontGetObject(TextIntRealizeFont) Status = 0x%lx\n", Status);
+        }
+    }
 
     /* If buffer is NULL, only the size is requested */
     if (pvBuffer == NULL) return sizeof(LOGFONTW);
@@ -393,7 +410,7 @@ IntGetFontLanguageInfo(PDC Dc)
   pdcattr = Dc->pdcattr;
 
   /* This might need a test for a HEBREW- or ARABIC_CHARSET as well */
-  if ( pdcattr->lTextAlign & TA_RTLREADING )
+  if ( pdcattr->flTextAlign & TA_RTLREADING )
      if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
                     result|=GCP_REORDER;
 
@@ -441,11 +458,13 @@ NtGdiAddFontResourceW(
     DBG_UNREFERENCED_PARAMETER(dwPidTid);
     DBG_UNREFERENCED_PARAMETER(pdv);
 
+    DPRINT("NtGdiAddFontResourceW\n");
+
     /* cwc = Length + trailing zero. */
-    if (cwc <= 1 || cwc > UNICODE_STRING_MAX_CHARS)
+    if ((cwc <= 1) || (cwc > UNICODE_STRING_MAX_CHARS))
         return 0;
 
-    SafeFileName.MaximumLength = cwc * sizeof(WCHAR);
+    SafeFileName.MaximumLength = (USHORT)(cwc * sizeof(WCHAR));
     SafeFileName.Length = SafeFileName.MaximumLength - sizeof(UNICODE_NULL);
     SafeFileName.Buffer = ExAllocatePoolWithTag(PagedPool,
                                                 SafeFileName.MaximumLength,
@@ -474,6 +493,71 @@ NtGdiAddFontResourceW(
     return Ret;
 }
 
+HANDLE
+APIENTRY
+NtGdiAddFontMemResourceEx(
+    IN PVOID pvBuffer,
+    IN DWORD cjBuffer,
+    IN DESIGNVECTOR *pdv,
+    IN ULONG cjDV,
+    OUT DWORD *pNumFonts)
+{
+    _SEH2_VOLATILE PVOID Buffer = NULL;
+    HANDLE Ret;
+    DWORD NumFonts = 0;
+
+    DPRINT("NtGdiAddFontMemResourceEx\n");
+    DBG_UNREFERENCED_PARAMETER(pdv);
+    DBG_UNREFERENCED_PARAMETER(cjDV);
+
+    if (!pvBuffer || !cjBuffer)
+        return NULL;
+
+    _SEH2_TRY
+    {
+        ProbeForRead(pvBuffer, cjBuffer, sizeof(BYTE));
+        Buffer = ExAllocatePoolWithQuotaTag(PagedPool, cjBuffer, TAG_FONT);
+        RtlCopyMemory(Buffer, pvBuffer, cjBuffer);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        if (Buffer != NULL)
+        {
+            ExFreePoolWithTag(Buffer, TAG_FONT);
+        }
+        _SEH2_YIELD(return NULL);
+    }
+    _SEH2_END;
+
+    Ret = IntGdiAddFontMemResource(Buffer, cjBuffer, &NumFonts);
+    ExFreePoolWithTag(Buffer, TAG_FONT);
+
+    _SEH2_TRY
+    {
+        ProbeForWrite(pNumFonts, sizeof(NumFonts), 1);
+        *pNumFonts = NumFonts;
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* Leak it? */
+        _SEH2_YIELD(return NULL);
+    }
+    _SEH2_END;
+
+
+    return Ret;
+}
+
+
+BOOL
+APIENTRY
+NtGdiRemoveFontMemResourceEx(
+    IN HANDLE hMMFont)
+{
+    return IntGdiRemoveFontMemResource(hMMFont);
+}
+
+
  /*
  * @unimplemented
  */
@@ -823,6 +907,7 @@ NtGdiGetOutlineTextMetricsInternalW (HDC  hDC,
      return 0;
   }
   FontGDI = ObjToGDI(TextObj->Font, FONT);
+  TextIntUpdateSize(dc, TextObj, FontGDI, TRUE);
   TEXTOBJ_UnlockText(TextObj);
   Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
   if (!otm) return Size;
@@ -865,31 +950,25 @@ 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)
+    IN LPWSTR       pwszFiles,
+    IN ULONG        cwc,
+    IN ULONG        cFiles,
+    IN UINT         cjIn,
+    IN OUT LPDWORD  pdwBytes,
+    OUT LPVOID      pvBuf,
+    IN DWORD        dwType)
 {
     NTSTATUS Status = STATUS_SUCCESS;
-    DWORD dwBytes;
+    DWORD dwBytes, dwBytesRequested;
     UNICODE_STRING SafeFileNames;
     BOOL bRet = FALSE;
     ULONG cbStringSize;
-
-    union
-    {
-        LOGFONTW logfontw;
-        WCHAR FullName[LF_FULLFACESIZE];
-    } Buffer;
+    LPVOID Buffer;
 
     /* FIXME: Handle cFiles > 0 */
 
-    /* Check for valid dwType values
-       dwType == 4 seems to be handled by gdi32 only */
-    if (dwType == 4 || dwType > 5)
+    /* Check for valid dwType values */
+    if (dwType > 5)
     {
         EngSetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
@@ -900,21 +979,34 @@ NtGdiGetFontResourceInfoInternalW(
     SafeFileNames.MaximumLength = SafeFileNames.Length = (USHORT)cbStringSize - sizeof(WCHAR);
     SafeFileNames.Buffer = ExAllocatePoolWithTag(PagedPool,
                                                  cbStringSize,
-                                                 'RTSU');
+                                                 TAG_USTR);
     if (!SafeFileNames.Buffer)
     {
         EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return FALSE;
     }
+    RtlZeroMemory(SafeFileNames.Buffer, SafeFileNames.MaximumLength);
 
     /* Check buffers and copy pwszFiles to safe unicode string */
     _SEH2_TRY
     {
         ProbeForRead(pwszFiles, cbStringSize, 1);
         ProbeForWrite(pdwBytes, sizeof(DWORD), 1);
-        ProbeForWrite(pvBuf, cjIn, 1);
+        if (pvBuf)
+            ProbeForWrite(pvBuf, cjIn, 1);
+
+        dwBytes = *pdwBytes;
+        dwBytesRequested = dwBytes;
 
         RtlCopyMemory(SafeFileNames.Buffer, pwszFiles, cbStringSize);
+        if (dwBytes > 0)
+        {
+            Buffer = ExAllocatePoolWithTag(PagedPool, dwBytes, TAG_FINF);
+        }
+        else
+        {
+            Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(DWORD), TAG_FINF);
+        }
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -926,21 +1018,24 @@ NtGdiGetFontResourceInfoInternalW(
     {
         SetLastNtError(Status);
         /* Free the string buffer for the safe filename */
-        ExFreePoolWithTag(SafeFileNames.Buffer,'RTSU');
+        ExFreePoolWithTag(SafeFileNames.Buffer, TAG_USTR);
         return FALSE;
     }
 
     /* Do the actual call */
-    bRet = IntGdiGetFontResourceInfo(&SafeFileNames, &Buffer, &dwBytes, dwType);
+    bRet = IntGdiGetFontResourceInfo(&SafeFileNames,
+                                     (pvBuf ? Buffer : NULL),
+                                     &dwBytes, dwType);
 
-    /* Check if succeeded and the buffer is big enough */
-    if (bRet && cjIn >= dwBytes)
+    /* Check if succeeded */
+    if (bRet)
     {
         /* Copy the data back to caller */
         _SEH2_TRY
         {
             /* Buffers are already probed */
-            RtlCopyMemory(pvBuf, &Buffer, dwBytes);
+            if (pvBuf && dwBytesRequested > 0)
+                RtlCopyMemory(pvBuf, Buffer, min(dwBytesRequested, dwBytes));
             *pdwBytes = dwBytes;
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@@ -956,8 +1051,9 @@ NtGdiGetFontResourceInfoInternalW(
         }
     }
 
+    ExFreePoolWithTag(Buffer, TAG_FINF);
     /* Free the string for the safe filenames */
-    ExFreePoolWithTag(SafeFileNames.Buffer,'RTSU');
+    ExFreePoolWithTag(SafeFileNames.Buffer, TAG_USTR);
 
     return bRet;
 }
@@ -988,6 +1084,7 @@ NtGdiGetRealizationInfo(
   }
   pdcattr = pDc->pdcattr;
   pTextObj = RealizeFontInit(pdcattr->hlfntNew);
+  ASSERT(pTextObj != NULL);
   pFontGdi = ObjToGDI(pTextObj->Font, FONT);
   TEXTOBJ_UnlockText(pTextObj);
   DC_UnlockDc(pDc);