I've written a Windows program in Delphi that places and wraps text very precisely to both the screen and printer using GetCharWidth and Em-Square. This has worked well with ANSI text where you only need to retrieve and calculate the widths of 255 characters but when you go to Unicode with 65535 characters its too slow. The problem is made worse by having to create 2 arrays of width, one for normal and one for bold.
//Setup a reference canvas for measuring purposes
RefDC := CreateCompatibleDC ( FCanvas.Handle ) ;
DPI := GetDeviceCaps ( RefDC , LOGPIXELSY ) ;
//find EmSquare
GetOutlineTextMetrics ( RefDC , sizeof(otm) , @otm[0] ) ;
EmSq := otm[0].otmEmSquare ;
//calc NORMAL char sizes
GetObject ( FCanvas.Font.Handle , SizeOf ( lf ) , @lf ) ;
lf.lfHeight := -EmSq ;
lf.lfWidth := 0 ;
lf.lfWeight := FW_NORMAL ;
hf := CreateFontIndirect ( lf ) ;
hold := SelectObject ( RefDC , hf ) ;
GetCharWidth ( RefDC , 0 , $FFFF , nCharWidth ) ;
for a := 0 to $FFFF do
fCharWidth[a] := nCharWidth[a]* PixelSize / EmSq ;
SelectObject ( RefDC , hold ) ;
DeleteObject ( hf ) ;
//calculate line height
PixelSize := abs ( fCanvas.Font.Size * DPI / 72 ) ;
GetOutlineTextMetrics ( RefDC , sizeof(otm) , @otm[0] ) ;
LineHt := round ( ( otm[0].otmTextMetrics.tmHeight +
otm[0].otmTextMetrics.tmExternalLeading ) *
PixelSize / EmSq ) ;
//calculate Bold char sizes
lf.lfWeight := FW_BOLD ;
hf := CreateFontIndirect ( lf ) ;
hold := SelectObject ( RefDC , hf ) ;
GetCharWidth ( RefDC , 0 , $FFFF , nCharWidth ) ;
for a := 0 to $FFFF do
fBoldWidth[a] := nCharWidth[a] * PixelSize / EmSq ;
SelectObject ( RefDC , hold ) ;
DeleteObject ( hf ) ;
DeleteDC ( RefDC ) ;`