Pango is indeed not easy. Initially I had some trouble to get the PangoFontMetrics object at all, which is required for Pango.FontMetrics. Luckily your initial example shows us already how we can get it. My next problem is to exactly understand what you desire: From your initial post, you just desire that your returned height variable is exactly 144? Well it is easy to fix, in my code below the fix is
# now fix so that height is exactly 144
let fixFactor = FontHeight / height
desc.setAbsoluteSize(FontHeight.float * pango.SCALE.float * fixFactor)
No trial and error needed.
But I would assume that your real intent is to position a text exactly into an existing rectangle? So we have additionally care for offsets?
As I had some trouble to remember pango stuff, I started with A python example of how to create png images with text through pangocairo · GitHub. That is my test1 proc in the code below. Then I created test2 proc, which used your initial code to create the PangoFontMetrics. With the fixed size, the second echo output prints exactly 144 as requested. But indeed all that is a bit difficult. I guess with Blend2d it will be not easy too, but at least Blend2d is still an active project, so maybe I should switch soon to Blend2D?
#https://gist.github.com/dov/ae4b889acb3659ca58fba1dba103ad49
import gintro/[cairo, pango, pangocairo]
const
Width = 256
Height=256
Font = "Serif" # font name
proc test1 =
let surface = cairo.imageSurfaceCreate(cairo.Format.argb32, Width, Height)
let cr = cairo.newContext(surface)
cr.rectangle(0,0,Width,Height)
cr.setSource(0, 0, 0.5)
cr.fill
let layout = pangocairo.createLayout(cr)
let desc = pango.newFontDescription(Font)
desc.set_family("Serif")
desc.set_size(48 * pango.SCALE)
layout.set_font_description(desc)
layout.setMarkup("A <b>bold</b>\nidea", "A <b>bold</b>\nidea".len)
layout.setAlignment(pango.Alignment.center)
var incRectangle, logRectangle: pango.Rectangle
layout.getExtents(incRectangle, logRectangle)
var (textWidth, textHeight) = (logRectangle.width / pango.SCALE, logRectangle.height / pango.SCALE)
cr.moveto(Width / 2 - textWidth / 2, Height / 2 - textHeight / 2)
cr.setSource(1,1,1)
pangocairo.showLayout(cr,layout)
# cr.fill # not needed
let status = surface.writeToPng("example1.png")
proc test2 =
const FontHeight = 144
const Width = 1024
let surface = cairo.imageSurfaceCreate(cairo.Format.argb32, Width, Height)
let cr = cairo.newContext(surface)
let layout = pangocairo.createLayout(cr)
let desc = pango.newFontDescription(Font)
desc.setFamily("Serif")
desc.setAbsoluteSize(FontHeight.float * pango.SCALE.float)
layout.set_font_description(desc)
let fontmap = pangocairo.newFontMap()
let pangoContext = createContext(fontmap)
var font = fontMap.loadFont(pangoContext, desc)
var m = font.getMetrics()
var height = m.getHeight / pango.SCALE;
echo height
# now fix so that height is exactly 144
let fixFactor = FontHeight / height
desc.setAbsoluteSize(FontHeight.float * pango.SCALE.float * fixFactor)
layout.set_font_description(desc)
font = fontMap.loadFont(pangoContext, desc)
m = font.getMetrics()
height = m.getHeight / pango.SCALE;
echo height # now this is 144!
layout.setText("Your Font")
layout.setAlignment(pango.Alignment.center)
var incRectangle, logRectangle: pango.Rectangle
layout.getExtents(incRectangle, logRectangle)
var (textWidth, textHeight) = (logRectangle.width / pango.SCALE, logRectangle.height / pango.SCALE)
cr.moveto(Width / 2 - textWidth / 2, Height / 2 - textHeight / 2)
cr.rectangle(0,0,Width,incRectangle.height / pango.SCALE)
cr.setSource(0, 0, 0.5)
cr.fill
cr.setSource(1,1,1)
pangocairo.showLayout(cr,layout)
#cr.fill
let status = surface.writeToPng("example2.png")
test1()
test2()
salewski@hx90 ~/pango $ ./font
168.0
144.0
[EDIT]
Finally I found the example with rotated text again: PangoCairo – 1.0: Rendering with Cairo