问题
How can I obtain kerning information for GDI to then use in GetKerningPairs? The documentation states that
The number of pairs in the lpkrnpair array. If the font has more than nNumPairs kerning pairs, the function returns an error.
However, I do not know how many pairs to pass in, and I don't see a way to query for it.
EDIT #2
Here is my fill application that I have also tried, this is always producing 0 for any font for the number of pairs. GetLastError will always return 0 also.
#include <windows.h>
#include <Gdiplus.h>
#include <iostream>
using namespace std;
using namespace Gdiplus;
int main(void)
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
Font* myFont = new Font(L"Times New Roman", 12);
Bitmap* bitmap = new Bitmap(256, 256, PixelFormat32bppARGB);
Graphics* g = new Graphics(bitmap);
//HDC hdc = g->GetHDC();
HDC hdc = GetDC(NULL);
SelectObject(hdc, myFont->Clone());
DWORD numberOfKerningPairs = GetKerningPairs(hdc, INT_MAX, NULL );
cout << GetLastError() << endl;
cout << numberOfKerningPairs << endl;
GdiplusShutdown(gdiplusToken);
return 0;
}
EDIT I tried to do the following, however, it still gave me 0.
Font* myFont = new Font(L"Times New Roman", 10);
Bitmap* bitmap = new Bitmap(256, 256, PixelFormat32bppARGB);
Graphics* g = new Graphics(bitmap);
SelectObject(g->GetHDC(), myFont);
//DWORD numberOfKerningPairs = GetKerningPairs( g->GetHDC(), -1, NULL );
DWORD numberOfKerningPairs = GetKerningPairs( g->GetHDC(), INT_MAX, NULL );
回答1:
The problem lies in the fact that you are passing in a Gdiplus::Font
and not a HFONT for SelectObject
. You need to convert Font* myFont
into a HFONT
, then pass that HFONT
into SelectObject.
First, to convert a Gdiplus::Font
into a HFONT
, you need to get the LOGFONT from the Gdiplus::Font
. Once you do this, the rest is simple. The working solution to get number of kerning pairs is
Font* gdiFont = new Font(L"Times New Roman", 12);
Bitmap* bitmap = new Bitmap(256, 256, PixelFormat32bppARGB);
Graphics* g = new Graphics(bitmap);
LOGFONT logFont;
gdiFont->GetLogFontA(g, &logFont);
HFONT hfont = CreateFontIndirect(&logFont);
HDC hdc = GetDC(NULL);
SelectObject(hdc, hfont);
DWORD numberOfKerningPairs = GetKerningPairs(hdc, INT_MAX, NULL );
As you can tell, the only functional change I gave was to creating a FONT
.
回答2:
You first call it with the third parameter set to NULL, in which case it returns the number of kerning pairs for the font. You then allocate memory, and call it again passing that buffer:
int num_pairs = GetKerningPairs(your_dc, -1, NULL);
KERNINGPAIR *pairs = malloc(sizeof(*pairs) * num_pairs);
GetKernningPairs(your_dc, num_pairs, pairs);
Edit: I did a quick test (using MFC by not GDI+) and got what seemed like reasonable results. The code I used was:
CFont font;
font.CreatePointFont(120, "Times New Roman", pDC);
pDC->SelectObject(&font);
int pairs = pDC->GetKerningPairs(1000, NULL);
CString result;
result.Format("%d", pairs);
pDC->TextOut(10, 10, result);
This printed out 116
as the result.
来源:https://stackoverflow.com/questions/10082825/obtaining-kerning-information