Signed-off-by: Dmitry Timoshkov dmitry@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 cc366eb4d7..4006da98a9 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.@] * @@ -3310,6 +3359,7 @@ GetCharacterPlacementW( SIZE size; UINT i, nSet; WCHAR *norm = NULL; + int *kern = NULL, kern_total = 0;
TRACE("%s, %d, %d, 0x%08x\n", debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags); @@ -3326,7 +3376,7 @@ GetCharacterPlacementW( lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass, lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
- if (dwFlags & ~(GCP_REORDER | GCP_LIGATE)) + if (dwFlags & ~(GCP_REORDER | GCP_LIGATE | GCP_USEKERNING)) FIXME("flags 0x%08x ignored\n", dwFlags); if(lpResults->lpClass) FIXME("classes not implemented\n"); @@ -3378,6 +3428,17 @@ GetCharacterPlacementW( nSet, lpResults->lpOrder, NULL, NULL ); }
+ if (dwFlags & GCP_USEKERNING) + { + kern = kern_string(hdc, lpString, nSet, &kern_total); + if (!kern) + { + heap_free(norm); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + } + /* FIXME: Will use the placement chars */ if (lpResults->lpDx) { @@ -3385,7 +3446,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]; + } } }
@@ -3395,17 +3460,23 @@ 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(norm); + heap_free(kern);
return ret; }