From 2903ca1bbb531a57c2aaf942e31e7c9832806b55 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@codeweavers.com>
Date: Wed, 3 Apr 2002 20:41:14 +0000
Subject: [PATCH] Implement GetGlyphIndices. Tweak GetCharacterPlacement to use
 it.

---
 dlls/gdi/freetype.c |  22 ++++++++
 dlls/gdi/gdi32.spec |   2 +
 include/font.h      |   2 +
 include/wingdi.h    |   6 +++
 objects/font.c      | 129 ++++++++++++++++++++++++++++++--------------
 5 files changed, 120 insertions(+), 41 deletions(-)

diff --git a/dlls/gdi/freetype.c b/dlls/gdi/freetype.c
index 4bcf6f5641..2b6f2d3c43 100644
--- a/dlls/gdi/freetype.c
+++ b/dlls/gdi/freetype.c
@@ -1008,6 +1008,22 @@ static FT_UInt get_glyph_index(GdiFont font, UINT glyph)
     return pFT_Get_Char_Index(font->ft_face, glyph);
 }
 
+/*************************************************************
+ * WineEngGetGlyphIndices
+ *
+ * FIXME: add support for GGI_MARK_NONEXISTING_GLYPHS
+ */
+DWORD WineEngGetGlyphIndices(GdiFont font, LPCWSTR lpstr, INT count,
+				LPWORD pgi, DWORD flags)
+{
+    INT i;
+
+    for(i = 0; i < count; i++)
+        pgi[i] = get_glyph_index(font, lpstr[i]);
+
+    return count;
+}
+
 /*************************************************************
  * WineEngGetGlyphOutline
  *
@@ -1603,6 +1619,12 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, DEVICEFONTENUMPROC proc, LPARAM lparam)
     return 1;
 }
 
+DWORD WineEngGetGlyphIndices(GdiFont font, LPCWSTR lpstr, INT count,
+				LPWORD pgi, DWORD flags)
+{
+    return GDI_ERROR;
+}
+
 DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
 			     LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
 			     const MAT2* lpmat)
diff --git a/dlls/gdi/gdi32.spec b/dlls/gdi/gdi32.spec
index 3f15020929..256db66e3d 100644
--- a/dlls/gdi/gdi32.spec
+++ b/dlls/gdi/gdi32.spec
@@ -223,6 +223,8 @@ debug_channels (bitblt bitmap clipping dc ddraw driver enhmetafile font gdi
 @ stdcall GetFontLanguageInfo(long) GetFontLanguageInfo
 @ stub GetFontResourceInfo
 @ stub GetFontResourceInfoW
+@ stdcall GetGlyphIndicesA(long ptr long ptr long) GetGlyphIndicesA
+@ stdcall GetGlyphIndicesW(long ptr long ptr long) GetGlyphIndicesW
 @ stub GetGlyphOutline
 @ stdcall GetGlyphOutlineA(long long long ptr long ptr ptr) GetGlyphOutlineA
 @ stdcall GetGlyphOutlineW(long long long ptr long ptr ptr) GetGlyphOutlineW
diff --git a/include/font.h b/include/font.h
index 93a754976f..d6e6495eb6 100644
--- a/include/font.h
+++ b/include/font.h
@@ -92,6 +92,8 @@ extern BOOL WineEngDestroyFontInstance(HFONT handle);
 extern DWORD WineEngEnumFonts(LPLOGFONTW, DEVICEFONTENUMPROC, LPARAM);
 extern BOOL WineEngGetCharWidth(GdiFont, UINT, UINT, LPINT);
 extern DWORD WineEngGetFontData(GdiFont, DWORD, DWORD, LPVOID, DWORD);
+extern DWORD WineEngGetGlyphIndices(GdiFont font, LPCWSTR lpstr, INT count,
+				    LPWORD pgi, DWORD flags);
 extern DWORD WineEngGetGlyphOutline(GdiFont, UINT glyph, UINT format,
 				    LPGLYPHMETRICS, DWORD buflen, LPVOID buf,
 				    const MAT2*);
diff --git a/include/wingdi.h b/include/wingdi.h
index be65455d85..47eb2a98c8 100644
--- a/include/wingdi.h
+++ b/include/wingdi.h
@@ -1219,6 +1219,9 @@ typedef VOID    (CALLBACK *LINEDDAPROC)(INT,INT,LPARAM);
 
 #define ASPECT_FILTERING    0x0001
 
+  /* for GetGlyphIndices() */
+#define GGI_MARK_NONEXISTING_GLYPHS  0x0001
+
 typedef struct
 {
     UINT	gmBlackBoxX;
@@ -3214,6 +3217,9 @@ UINT      WINAPI GetEnhMetaFileHeader(HENHMETAFILE,UINT,LPENHMETAHEADER);
 UINT      WINAPI GetEnhMetaFilePaletteEntries(HENHMETAFILE,UINT,LPPALETTEENTRY);
 DWORD     WINAPI GetFontData(HDC,DWORD,DWORD,LPVOID,DWORD);
 DWORD     WINAPI GetFontLanguageInfo(HDC);
+DWORD     WINAPI GetGlyphIndicesA(HDC,LPCSTR,INT,LPWORD,DWORD);
+DWORD     WINAPI GetGlyphIndicesW(HDC,LPCWSTR,INT,LPWORD,DWORD);
+#define   GetGlyphIndices WINELIB_NAME_AW(GetGlyphIndices)
 DWORD     WINAPI GetGlyphOutlineA(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*);
 DWORD     WINAPI GetGlyphOutlineW(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*);
 #define     GetGlyphOutline WINELIB_NAME_AW(GetGlyphOutline)
diff --git a/objects/font.c b/objects/font.c
index 924d74af5c..f61f416594 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -1776,7 +1776,7 @@ DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
     DC *dc = DC_GetDCPtr(hdc);
     DWORD ret;
 
-    TRACE("(%04x, '%c', %04x, %p, %ld, %p, %p)\n",
+    TRACE("(%04x, %04x, %04x, %p, %ld, %p, %p)\n",
 	  hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
 
     if(!dc) return GDI_ERROR;
@@ -1999,6 +1999,47 @@ DWORD WINAPI GetFontData16(HDC16 hdc, DWORD dwTable, DWORD dwOffset,
     return GetFontData(hdc, dwTable, dwOffset, lpvBuffer, cbData);
 }
 
+/*************************************************************************
+ * GetGlyphIndicesA [GDI32.@]
+ */
+DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
+			      LPWORD pgi, DWORD flags)
+{
+    DWORD ret;
+    WCHAR *lpstrW;
+    INT countW;
+
+    TRACE("(%04x, %s, %d, %p, 0x%lx)\n",
+	hdc, debugstr_an(lpstr, count), count, pgi, flags);
+
+    lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
+    ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
+    HeapFree(GetProcessHeap(), 0, lpstrW);
+
+    return ret;
+}
+
+/*************************************************************************
+ * GetGlyphIndicesW [GDI32.@]
+ */
+DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
+			      LPWORD pgi, DWORD flags)
+{
+    DC *dc = DC_GetDCPtr(hdc);
+    DWORD ret = GDI_ERROR;
+
+    TRACE("(%04x, %s, %d, %p, 0x%lx)\n",
+	hdc, debugstr_wn(lpstr, count), count, pgi, flags);
+
+    if(!dc) return GDI_ERROR;
+
+    if(dc->gdiFont)
+	ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
+
+    GDI_ReleaseObj(hdc);
+    return ret;
+}
+
 /*************************************************************************
  * GetCharacterPlacementA [GDI32.@]
  *
@@ -2010,41 +2051,32 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
 			 INT nMaxExtent, GCP_RESULTSA *lpResults,
 			 DWORD dwFlags)
 {
-    DWORD ret=0;
-    SIZE size;
+    WCHAR *lpStringW;
+    INT uCountW;
+    GCP_RESULTSW resultsW;
+    DWORD ret;
+    UINT font_cp;
 
-    TRACE("%s 0x%08x 0x%08x 0x%08lx:stub!\n",
-          debugstr_a(lpString), uCount, nMaxExtent, dwFlags);
+    TRACE("%s, %d, %d, 0x%08lx\n",
+          debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
 
-    TRACE("lpOrder=%p lpDx=%p lpCaretPos=%p lpClass=%p "
-          "lpOutString=%p lpGlyphs=%p\n",
-          lpResults->lpOrder, lpResults->lpDx, lpResults->lpCaretPos,
-          lpResults->lpClass, lpResults->lpOutString, lpResults->lpGlyphs);
+    /* both structs are equal in size */
+    memcpy(&resultsW, lpResults, sizeof(resultsW));
 
-    if(dwFlags)			FIXME("flags 0x%08lx ignored\n", dwFlags);
-    if(lpResults->lpOrder)	FIXME("reordering not implemented\n");
-    if(lpResults->lpCaretPos)	FIXME("caret positions not implemented\n");
-    if(lpResults->lpClass)	FIXME("classes not implemented\n");
-    if(lpResults->lpGlyphs)	FIXME("glyphs not implemented\n");
-
-    /* copy will do if the GCP_REORDER flag is not set */
+    lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
     if(lpResults->lpOutString)
-    {
-      lstrcpynA(lpResults->lpOutString, lpString, uCount);
-    }
+	resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, uCountW);
+    else
+	resultsW.lpOutString = NULL;
 
-    if (lpResults->lpDx)
-    {
-      int i, c;
-      for (i=0; i<uCount;i++)
-      { 
-        if (GetCharWidth32A(hdc, lpString[i], lpString[i], &c))
-          lpResults->lpDx[i]= c;
-      }
-    }
+    ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
 
-    if (GetTextExtentPoint32A(hdc, lpString, uCount, &size))
-      ret = MAKELONG(size.cx, size.cy);
+    if(lpResults->lpOutString)
+	WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
+			    lpResults->lpOutString, uCount, NULL, NULL );
+
+    HeapFree(GetProcessHeap(), 0, lpStringW);
+    HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
 
     return ret;
 }
@@ -2059,37 +2091,52 @@ GetCharacterPlacementW(HDC hdc, LPCWSTR lpString, INT uCount,
 {
     DWORD ret=0;
     SIZE size;
+    UINT i, nSet;
 
-    TRACE("%s 0x%08x 0x%08x 0x%08lx:partial stub!\n",
-          debugstr_w(lpString), uCount, nMaxExtent, dwFlags);
+    TRACE("%s, %d, %d, 0x%08lx\n",
+          debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
 
-    TRACE("lpOrder=%p lpDx=%p lpCaretPos=%p lpClass=%p "
-          "lpOutString=%p lpGlyphs=%p\n",
-          lpResults->lpOrder, lpResults->lpDx, lpResults->lpCaretPos,
-          lpResults->lpClass, lpResults->lpOutString, lpResults->lpGlyphs);
+    TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
+	  "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
+	    lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
+	    lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
+	    lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
 
     if(dwFlags)			FIXME("flags 0x%08lx ignored\n", dwFlags);
-    if(lpResults->lpOrder)	FIXME("reordering not implemented\n");
     if(lpResults->lpCaretPos)	FIXME("caret positions not implemented\n");
     if(lpResults->lpClass)	FIXME("classes not implemented\n");
-    if(lpResults->lpGlyphs)	FIXME("glyphs not implemented\n");
 
+    /* FIXME: reordering not implemented */
     /* copy will do if the GCP_REORDER flag is not set */
     if(lpResults->lpOutString)
-    {
       lstrcpynW(lpResults->lpOutString, lpString, uCount);
+
+    nSet = (UINT)uCount;
+    if(nSet > lpResults->nGlyphs)
+	nSet = lpResults->nGlyphs;
+
+    /* return number of initialized fields */
+    lpResults->nGlyphs = nSet;
+
+    if(lpResults->lpOrder)
+    {
+	for(i = 0; i < nSet; i++)
+	    lpResults->lpOrder[i] = i;
     }
 
     if (lpResults->lpDx)
     {
-      int i, c;
-      for (i=0; i<uCount;i++)
+      int c;
+      for (i = 0; i < nSet; i++)
       { 
         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
           lpResults->lpDx[i]= c;
       }
     }
 
+    if(lpResults->lpGlyphs)
+	GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
+
     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
       ret = MAKELONG(size.cx, size.cy);
 
-- 
2.32.0.93.g670b81a890