[PATCH] gdi32: Add support for GCP_USEKERNING to GetCharacterPlacement.
Dmitry Timoshkov
dmitry at baikal.ru
Thu Jun 18 22:13:02 CDT 2020
Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
dlls/gdi32/font.c | 77 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 74 insertions(+), 3 deletions(-)
diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index 8788426a2c..0ad6502a9c 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -3278,6 +3278,55 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
return ret;
}
+static int kern_pair(const KERNINGPAIR *kern, int count, WCHAR c1, WCHAR c2)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ {
+ if (kern[i].wFirst == c1 && kern[i].wSecond == c2)
+ return kern[i].iKernAmount;
+ }
+
+ return 0;
+}
+
+static int *kern_string(HDC hdc, const WCHAR *str, int len, int *kern_total)
+{
+ int i, count;
+ KERNINGPAIR *kern = NULL;
+ int *ret;
+
+ *kern_total = 0;
+
+ ret = heap_alloc(len * sizeof(*ret));
+ if (!ret) return NULL;
+
+ count = GetKerningPairsW(hdc, 0, NULL);
+ if (count)
+ {
+ kern = heap_alloc(count * sizeof(*kern));
+ if (!kern)
+ {
+ heap_free(ret);
+ return NULL;
+ }
+
+ GetKerningPairsW(hdc, count, kern);
+ }
+
+ for (i = 0; i < len - 1; i++)
+ {
+ ret[i] = kern_pair(kern, count, str[i], str[i + 1]);
+ *kern_total += ret[i];
+ }
+
+ ret[len - 1] = 0; /* no kerning for last element */
+
+ heap_free(kern);
+ return ret;
+}
+
/*************************************************************************
* GetCharacterPlacementW [GDI32.@]
*
@@ -3309,6 +3358,7 @@ GetCharacterPlacementW(
DWORD ret=0;
SIZE size;
UINT i, nSet;
+ int *kern = NULL, kern_total = 0;
TRACE("%s, %d, %d, 0x%08x\n",
debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
@@ -3325,7 +3375,7 @@ GetCharacterPlacementW(
lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
- if(dwFlags&(~GCP_REORDER))
+ if (dwFlags & ~(GCP_REORDER | GCP_USEKERNING))
FIXME("flags 0x%08x ignored\n", dwFlags);
if(lpResults->lpClass)
FIXME("classes not implemented\n");
@@ -3358,6 +3408,16 @@ GetCharacterPlacementW(
nSet, lpResults->lpOrder, NULL, NULL );
}
+ if (dwFlags & GCP_USEKERNING)
+ {
+ kern = kern_string(hdc, lpString, nSet, &kern_total);
+ if (!kern)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
+ }
+
/* FIXME: Will use the placement chars */
if (lpResults->lpDx)
{
@@ -3365,7 +3425,11 @@ GetCharacterPlacementW(
for (i = 0; i < nSet; i++)
{
if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
- lpResults->lpDx[i]= c;
+ {
+ lpResults->lpDx[i] = c;
+ if (dwFlags & GCP_USEKERNING)
+ lpResults->lpDx[i] += kern[i];
+ }
}
}
@@ -3375,15 +3439,22 @@ GetCharacterPlacementW(
lpResults->lpCaretPos[0] = 0;
for (i = 1; i < nSet; i++)
+ {
+ if (dwFlags & GCP_USEKERNING)
+ pos += kern[i];
+
if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
lpResults->lpCaretPos[i] = (pos += size.cx);
+ }
}
if(lpResults->lpGlyphs)
GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
- ret = MAKELONG(size.cx, size.cy);
+ ret = MAKELONG(size.cx + kern_total, size.cy);
+
+ heap_free(kern);
return ret;
}
--
2.26.2
More information about the wine-devel
mailing list