A font file can allow the character to have glyf data, but it does not necessarily have to have a cmap mapping. (no codepoint)
Therefore, I want to know if there is a system API that can render character in this situation.
I know that I can get all the point set data of this contours and the flags (onCurve,...) information from the glyf raw data, so that I can draw the glyph myself.
However, I am seeking a solution using a system API (preferably Windows, but solutions for other platforms are also welcome).
If it has a code point, I can directly use TextOutW to draw the character, but if there is no code point and I only know the glyphIndex, is there a way to achieve that?
ExtTextOut combined with
ETO_GLYPH_INDEX
seems to be able to do it, but I'm not very sure.
Indeed, using ExtTextOut can accomplish it. The options
should be set to ETO_GLYPH_INDEX
(0x10
). The content that lpString
points to should be filled according to the glyph index.
ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, nil, []uint16{49, 50, 51}) // glyphIndex: 49, 50, 51
ExtTextOut(hdc, 0, 0, 0, nil, utf16.Encode([]rune("Hello world 世界")) // draw string
func main() {
lf := w32.LogFont{
Height: -64,
Width: 0,
Escapement: 0,
Orientation: 0,
Weight: 400,
Italic: 0,
Underline: 0,
StrikeOut: 0,
CharSet: w32.DEFAULT_CHARSET,
OutPrecision: w32.OUT_TT_PRECIS,
ClipPrecision: w32.CLIP_DEFAULT_PRECIS,
Quality: w32.ANTIALIASED_QUALITY,
PitchAndFamily: w32.FF_DONTCARE,
}
hFont := gdiDll.CreateFont(
lf.Height,
lf.Width,
lf.Escapement,
lf.Orientation,
lf.Weight,
uint32(lf.Italic),
uint32(lf.Underline),
uint32(lf.StrikeOut),
uint32(lf.CharSet),
uint32(lf.OutPrecision),
uint32(lf.ClipPrecision),
uint32(lf.Quality),
uint32(lf.PitchAndFamily),
"Arial",
)
defer gdiDll.DeleteObject(w32.HGDIOBJ(hFont))
hdc := userDll.GetDC(0)
defer userDll.ReleaseDC(0, hdc)
hMemDC := gdiDll.CreateCompatibleDC(hdc)
defer gdiDll.DeleteObject(w32.HGDIOBJ(hMemDC))
const width = 1000
const height = 500
hBitmap := gdiDll.CreateCompatibleBitmap(hdc, width, height)
hObjOld := gdiDll.SelectObject(hMemDC, w32.HGDIOBJ(hBitmap))
defer gdiDll.SelectObject(hMemDC, hObjOld)
oldFont := gdiDll.SelectObject(hMemDC, w32.HGDIOBJ(hFont))
defer gdiDll.SelectObject(hMemDC, oldFont)
gdiDll.SetTextColor(hMemDC, w32.RGB(255, 0, 0))
gdiDll.ExtTextOut(hMemDC, 20, 20, w32.ETO_GLYPH_INDEX, nil, []uint16{49, 50, 51}) // GlyphIndex 49, 50, 51
gdiDll.ExtTextOut(hMemDC, 500, 300, 0, nil, utf16.Encode([]rune("Hello world 世界")))
_ = userDll.OpenClipboard(0)
_ = userDll.EmptyClipboard()
_, _ = userDll.SetClipboardData(w32.CF_BITMAP, w32.HANDLE(hBitmap))
_ = userDll.CloseClipboard()
}