You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Question] How to use the latest FillString() and AddFont()? #693
Hi, I am new to plot. I used some old version in the past and it's working very well.
Today, when I try to upgrade to the latest version (using go module), There are two problems in the code. I think it might because the API methods have been upgraded.
The error shows: cannot use font (variable of type *truetype.Font) as *sfnt.Font value in argument to vg.AddFont
I don't know how to use the latest API.
How to convert fs to font.Face? I tried fs.FontFace(96), but it didn't work.
How to add truetype.Font to vg.AddFont? How to convert truetype.Font to sfnt.Font?
Can anyone plese help?
@kortschak Thank you very much for your quick reply. The sfnt.Parse(ttfBytes) solution is clear. But I still don't know how to get font face. I am new to font coding. I tried to google some example code online, but failed to find any. Can you please show me a complete example how to get font face if that is not too much? OR show me some complete example code URLs? Thank you very much.
It has error message: cannot use face (variable of type font.Face) as font.Face value in argument to c.FillString
I am very confused. I can not use font.Face as font.Face?
That's a pretty funny error. There are two font.Face types in your program, opentype.NewFace returns this and FillString wants this. Unfortunately, there are only so many names, and sometime we have to share.
BTW It's easier to help if you provide full code. You can paste the code at https://play.golang.org.
fs.Width line will give me invalid memory address or nil pointer dereference error.
It worked before when I use the old plot version.
If I change the fontName to the built-in font name such as "Courier", the error will be gone. But I want to use the system font instead of FontMap list.
In the old version, I simply use c.FillString(fs, ...).
But in the new version, If I use fnt := plot.DefaultTextHandler.Cache().Lookup(plot.DefaultFont, fontInchSize) and then c.FillString(fnt, ...), How can I use the custom ttc font?
I have read the example link provided by @sbinet. But I am still very lost.
I have the variable fs created by vg.MakeFont. Why can't I use it somehow in c.FillString like before?
Sorry that I made one mistake above that I should NOT use ttc font collection file, instead, I should use ttf file. I should check the error in the line sfnt.Parse which will produce a reasonable error message instead of a nil pointer error. This is my bad.
Btw, the new font system is way more complicated than before.
In the past, I just need to add the font once in vg.AddFont(). That's all. I can then use the font in all methods such as vg.MakeFont() and vgimg.Canvas.FillString(),
But in the new version, I have to add the fonts twice. One by vg.AddFont() so that I can call vg.MakeFont(). Another by creating a font.Face, so that I can use vgimg.Canvas.FillString().
Anyway, thank you very much again and closing this question.
I believe that, as the example shown above might indicate, one doesn't need to use bothvg.AddFont and the "font cache" to add a new 3rd-party font to the gonum/plot font system.
could you please open another issue if that's not the case?
thanks.
Note to self: probably consider a migration path and delete vg.AddFont, vg.MakeFont and vg.Font altogether (which were IIRC kept only for embedding fonts in PDF documents while there was no way to get back at the raw []bytes)
@sbinet Thanks a lot for your reply. I was not saying that the font needs to add to "font cache" too. I mean the ttfBytes need to pass to both vg.AddFont and font.Face object. Maybe I am concerning too much. I just feel weird that I need to pass the same ttfBytes to two different places.
I used some of the codes from this gist: https://gist.github.com/linw1995/41e103f29e7dd97679c577a6f4830be8
Cheers.
and what I am saying is that no call to vg.AddFont (nor vg.MakeFont) should be needed.
so the raw []byte representing the TTF font needs only to be passed once to the font cache.
one can then retrieve a font face (with the expected size) via plot/font.Cache.Lookup as Dan wrote earlier.
@sbinet I posted the gist code that I studied from. (I am not using the same code, but they are similar). From the gist code, you can see that it needs to calculate the following:
Activity
kortschak commentedon May 31, 2021
To get the font face, use
fnt := hdlr.Fonts.Lookup(sty.Font, sty.Font.Size)wherehdlris atext.Handlerandstyis your text style.Rather than using
truetype.Parse(ttfBytes), trysfnt.Parse(ttfBytes)sgon00 commentedon May 31, 2021
@kortschak Thank you very much for your quick reply. The
sfnt.Parse(ttfBytes)solution is clear. But I still don't know how to get font face. I am new to font coding. I tried to google some example code online, but failed to find any. Can you please show me a complete example how to get font face if that is not too much? OR show me some complete example code URLs? Thank you very much.sgon00 commentedon May 31, 2021
PS: I tried something stupid:
It has error message:
cannot use face (variable of type font.Face) as font.Face value in argument to c.FillStringI am very confused. I can not use font.Face as font.Face?
kortschak commentedon May 31, 2021
Yeah, no worries. The API is new, I think we may need to have some more examples for how to use it effectively.
This is a basic use.
If you look in the liberation.go file, you can see the fonts that are provided in the repo and also how the collection is constructed.
kortschak commentedon May 31, 2021
That's a pretty funny error. There are two
font.Facetypes in your program,opentype.NewFacereturns this andFillStringwants this. Unfortunately, there are only so many names, and sometime we have to share.BTW It's easier to help if you provide full code. You can paste the code at https://play.golang.org.
sbinet commentedon May 31, 2021
Here's an example of using a 3rd-party font:
https://pkg.go.dev/gonum.org/v1/plot@v0.9.0/vg#example-package-AddFont
sgon00 commentedon May 31, 2021
I am very sorry that I still can not make 0.9.0 work.
Some of my current code:
fs.Widthline will give meinvalid memory address or nil pointer dereferenceerror.It worked before when I use the old plot version.
If I change the
fontNameto the built-in font name such as"Courier", the error will be gone. But I want to use the system font instead of FontMap list.In the old version, I simply use
c.FillString(fs, ...).But in the new version, If I use
fnt := plot.DefaultTextHandler.Cache().Lookup(plot.DefaultFont, fontInchSize)and thenc.FillString(fnt, ...), How can I use the custom ttc font?I have read the example link provided by @sbinet. But I am still very lost.
I have the variable
fscreated byvg.MakeFont. Why can't I use it somehow inc.FillStringlike before?Thank you very much for your help.
sbinet commentedon May 31, 2021
as always in Go, please check the returned error values (that's why you get a
nilpointer asfs.)the new font system was put in place to allow for a much finer control of fonts (and to use
golang.org/x/image/font/sfntinstead offreetype)as hinted in the example, the way to add a new font is to populate the "font cache":
ie: one adds a
plot/font.Facevalue to the default font cache, which can then be used by the whole set ofgonum/plotpackages.one can use that
plot/font.Facevalue with theplot/vg.Canvas.FillStringmethod, as before:sgon00 commentedon May 31, 2021
Thank you both very much for the help.
Finally, I made it work.
Sorry that I made one mistake above that I should NOT use
ttcfont collection file, instead, I should usettffile. I should check the error in the linesfnt.Parsewhich will produce a reasonable error message instead of a nil pointer error. This is my bad.Btw, the new font system is way more complicated than before.
In the past, I just need to add the font once in
vg.AddFont(). That's all. I can then use the font in all methods such asvg.MakeFont()andvgimg.Canvas.FillString(),But in the new version, I have to add the fonts twice. One by
vg.AddFont()so that I can callvg.MakeFont(). Another by creating a font.Face, so that I can usevgimg.Canvas.FillString().Anyway, thank you very much again and closing this question.
sbinet commentedon May 31, 2021
I believe that, as the example shown above might indicate, one doesn't need to use both
vg.AddFontand the "font cache" to add a new 3rd-party font to the gonum/plot font system.could you please open another issue if that's not the case?
thanks.
Note to self: probably consider a migration path and delete
vg.AddFont,vg.MakeFontandvg.Fontaltogether (which were IIRC kept only for embedding fonts in PDF documents while there was no way to get back at the raw[]bytes)sgon00 commentedon May 31, 2021
@sbinet Thanks a lot for your reply. I was not saying that the font needs to add to "font cache" too. I mean the ttfBytes need to pass to both
vg.AddFontandfont.Faceobject. Maybe I am concerning too much. I just feel weird that I need to pass the same ttfBytes to two different places.I used some of the codes from this gist: https://gist.github.com/linw1995/41e103f29e7dd97679c577a6f4830be8
Cheers.
sbinet commentedon May 31, 2021
and what I am saying is that no call to
vg.AddFont(norvg.MakeFont) should be needed.so the raw
[]byterepresenting the TTF font needs only to be passed once to the font cache.one can then retrieve a font face (with the expected size) via plot/font.Cache.Lookup as Dan wrote earlier.
earlier on, I wrote:
but this could as well be written like:
sgon00 commentedon May 31, 2021
@sbinet I posted the gist code that I studied from. (I am not using the same code, but they are similar). From the gist code, you can see that it needs to calculate the following:
I don't know how to achieve the same if I don't call
vg.AddFontandvg.MakeFont.Thanks a lot.
sbinet commentedon May 31, 2021
The 'font.Face' type has the methods you are looking for:
sgon00 commentedon May 31, 2021
@sbinet Thank you very much. I will try to replace the old code with font.Face methods then. :)