func (c *Canvas) MeasureText(text string, font *Font, bounds Rectangle, format DrawTextFormat) (boundsMeasured Rectangle, runesFitted int, err error) { // HACK: We don't want to actually draw on the Canvas here, but if we use // the DT_CALCRECT flag to avoid drawing, DRAWTEXTPARAMc.UiLengthDrawn will // not contain a useful value. To work around this, we create an in-memory // metafile and draw into that instead. if c.measureTextMetafile == nil { c.measureTextMetafile, err = NewMetafile(c) if err != nil { return } } hFont := win.HGDIOBJ(font.handleForDPI(c.dpiy)) oldHandle := win.SelectObject(c.measureTextMetafile.hdc, hFont) if oldHandle == 0 { err = newError("SelectObject failed") return } defer win.SelectObject(c.measureTextMetafile.hdc, oldHandle) rect := &win.RECT{ int32(bounds.X), int32(bounds.Y), int32(bounds.X + bounds.Width), int32(bounds.Y + bounds.Height), } var params win.DRAWTEXTPARAMS params.CbSize = uint32(unsafe.Sizeof(params)) strPtr := syscall.StringToUTF16Ptr(text) dtfmt := uint32(format) | win.DT_EDITCONTROL | win.DT_WORDBREAK height := win.DrawTextEx( c.measureTextMetafile.hdc, strPtr, -1, rect, dtfmt, ¶ms) if height == 0 { err = newError("DrawTextEx failed") return } boundsMeasured = Rectangle{ int(rect.Left), int(rect.Top), int(rect.Right - rect.Left), int(height), } runesFitted = int(params.UiLengthDrawn) return }
func (c *Canvas) DrawText(text string, font *Font, color Color, bounds Rectangle, format DrawTextFormat) error { return c.withFontAndTextColor(font, color, func() error { rect := bounds.toRECT() ret := win.DrawTextEx( c.hdc, syscall.StringToUTF16Ptr(text), -1, &rect, uint32(format)|win.DT_EDITCONTROL, nil) if ret == 0 { return newError("DrawTextEx failed") } return nil }) }