Open odeke-em opened 8 years ago
I tried using this font: /System/Library/Fonts/Apple Color Emoji.ttf
but then I get this error:
panic: freetype: unsupported TrueType feature: cmap encoding
I think this would involve a lot of work.
@fogleman thanks for taking a look at this and for the hint of change of font. I'll hopefully dive into this issue too soon.
@odeke-em and @fogleman, this does not appear to be font-specific. I'm able to reproduce using a number of open source fonts like Ubuntu Font Family or Xolonium, which is what I happen to be using for a project.
As a test I use unicode code point U+1F603 "Smiling Face With Open Mouth". Its []byte representation is [240 159 152 131].
Could you please confirm whether this is relevant behaviour in golang/freetype? https://github.com/golang/freetype/blob/255de57f4e681ed92b2d55a483a27194dfa2b3dc/truetype/truetype.go#L118
@htrob Modifying this freetype code with my font (Xolonium) still yields the same (blank) output.
@antzucaro Ok, so it looks like it's really a golang/freetype problem. We should check what the freetype devs say in github.com/golang/freetype
@htrob and @fogleman - looks like freetype won't implement this anytime soon according to this issue. The go-cairo library supports these emojis, so I suppose I'll have to change my renderer to that. That's a shame since I like gg's API better and it is pure Go.
@antzucaro So go-cairo uses a different/own truetype renderer? I like gg a lot better too for the same reasons you do. I was also checking nanovgo, which supports truetype glyph rendering, trying to understand how it works.
nanovgo is primarily intended for live graphics on screen, which may be more useful and a flatter API for my particular application. nanovgo uses a reduced version of Fontstash, which is a truetype atlas renderer. It caches bitmap images of pre-rendered font types for live display on screen. https://github.com/memononen/fontstash
If a reduced version of a simpler library like fontstash handles these fonts correctly, it must not be extremely complicated code, it may be possible to grab or translate the relevant parts from Fontstash and fix the Go Freetype port.
I'd personally prefer to attempt that before trying to introduce a massive dependency like Cairo as a desperate last resort measure.
In the meantime I'm going to see if I can abstract 2d drawing in such a way that I can use gg or alternatively nanovgo as a drop in replacement.
2d drawing apis inspired by HTML5 canvas are not wildly different, doing the same with Cairo would probably be a harder task as well.
UPDATE: Fontstash actually uses another C-based truetype rendering library called stb, and in particular its subset stb_truetype.h https://github.com/nothings/stb
Faced with the option of a massive and complex C dependency like Cairo or a tiny C dependency like stb_truetype just for rendering some glyphs on screen, I'll probably go with the latter until Go Freetype can be fixed, and will try to abstract 2d drawing until a definitive All-Go solution can be devised.
I haven't looked yet, but maybe stb_truetype is simple enough that I can port it more or less literally at some point.
Thanks for looking into this everyone. Maybe we can figure something out if we keep digging.
The Apple Color Emoji font has a cmap encoding that isn't listed here:
https://github.com/golang/freetype/blob/master/truetype/truetype.go#L60
It has a value of 0x00000004, which indicates:
Unicode 2.0 and onwards semantics, Unicode full repertoire (cmap subtable formats 0, 4, 6, 10, 12).
Here are some relevant pages:
https://www.microsoft.com/typography/otspec/name.htm
https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6cmap.html
I don't know much about TTF, so this is all I know so far.
@antzucaro Xolonium works just fine with nanovgo (truetype rendered by Fontstash, using stb_truetype.h), which I may be using for my GUI toolkit, in addition to gg. Not native Go, but stb_truetype is a tiny dependency. Maybe the font renderer can be made pluggable in fogleman/gg until a complete Go solution is found? https://s30.postimg.org/cfkmwjhgh/Screenshot_at_2017-04-14_20_36_57.png
Thanks for checking, @htrob! I will have to do a more thorough comparison with Cairo, which is easily installed on my system. If it could be plugged into gg, however, that would be a huge win.
@antzucaro You're welcome. I looked a little more into this, and turns out that nanovgo's truetype rendering is not done with the original Fontstash/stb_truetype, but a reduced version written in Go dubbed fontstash_mini (the almost identical project name was misleading). I didn't look too deep, but it seems to be all native Go, and it renders correctly all fonts I've used so far (as shown in previous screenshot). https://github.com/shibukawa/nanovgo/blob/master/fontstashmini/truetype/truetype.go
This definitely seems like something that could be integrated in fogleman/gg, if it deals with problematic fonts that golang/freetype is never going to be able to handle. I'm actually doing this for myself, trying to make sure I'm not going to be stuck into a dead end if I build something bigger on top of golang/freetype.
I used Antigrain in the past but that was a bit of an overkill for my most basic 2d drawing needs, and fogleman/gg is a really useful tool that in my opinion strikes the right balance of output quality, API size, and ease of use, but it's always good to make sure it's applied to the right kind of task.
Hope this helps. Cheers!
I just pushed https://github.com/golang/freetype/commit/b12e98108289d6367ecd1a819deee597b2c3fa57
Does that fix your issue?
@nigeltao Thanks! Here I rendered "\U0001F1E6\U0001F1E7\U0001F1E8"
@fogleman @nigeltao - unfortunately it does not work w/ Xolonium modifying this example.
I tried that font and indeed it produces this new error:
freetype: unsupported TrueType feature: kern nTables: 3
@fogleman, have you been able to identify whether this bug happens during font loading/interpreting or is it something that happens when attempting to render it?
I'm trying to understand what fontstash_mini does differently from golang/freetype. this seems to be the relevant part in fontstash_mini that deals with tables https://github.com/shibukawa/nanovgo/search?utf8=%E2%9C%93&q=tables&type=
This appears to be the relevant part in golang/freetype https://github.com/golang/freetype/search?utf8=%E2%9C%93&q=ntables&type=
@htrob That error occurs during font loading.
I think the comparison between two distinct font loading libraries is helpful.
For what I see in the links above, the difference between fontstash_mini and golang/freetype when loading truetype tables is that freetype doesn't want to deal with the specific case of the type of table that contains kerning information. Instead of ignoring this type of table, golang/freetype just halts execution saying that kerning tables aren't supported. fontstash_mini appears to ignore the tables it doesn't know how to peruse, and continues execution without dropping the ball.
Do you guys agree this is a correct diagnostic?
If I'm reading this correctly, all that needs to be done is to make golang/freetype ignore kerning tables (and other tables it doesn't know how to handle) without halting execution. We don't really need golang/freetype to implement advanced kerning features, we only need programmes not to halt arbitrarily. It doesn't make any sense to halt execution if you can proceed with degraded behaviour, unless you're developing a font validation tool, or some other font management tool. In which case, you would benefit from better font and rendering library capability detection anyway, instead of just halting. Or at least a poor error code as an int, but not halting.
The downside of patching golang/freetype to fix this is that it may require vendoring golang/freetype until they incorporate the behaviour change, if they ever do.
Xolonium-Regular.ttf now works for me.
@nigeltao I pulled in the latest freetype and re-ran the example code cited above, inserting unicode code point U+1F603 "Smiling Face With Open Mouth" into the the "looking glass" text snippet. It still does not render them.
@nigeltao @antzucaro Indeed the font loads and works now, for the most part. Here I rendered the first unicode plane with Xolonium-Regular:
All the other planes just render boxes.
Try it yourself with this example code:
https://github.com/fogleman/gg/blob/master/examples/unicode.go
BTW, @nigeltao I tried adding this function to gg
:
func (dc *Context) HasRune(r rune) bool {
_, _, _, _, ok := dc.fontFace.Glyph(fixp(0, 0), r)
return ok
}
But it seems to always return true even if it just renders a box or renders nothing. Is that expected behavior?
Yeah, that's more or less expected for now.
https://www.microsoft.com/typography/OTSPEC/cmap.htm says that "Character codes that do not correspond to any glyph in the font should be mapped to glyph index 0. The glyph at this location must be a special glyph representing a missing character, commonly known as .notdef."
It makes sense (to me) when considering a single font face in isolation, but I'd like to reconsider that design decision (Glyph returns ok == true) when we have a good idea of how to set text in multiple font faces, e.g. this run of text uses a Latin font, this run of text uses a Chinese font. But I don't have a good idea for how to do that yet. It probably involves a higher level "Text Layout" data structure, and API to create and manipulate them.
For your immediate problem, you might be able to check
return dc.font.Index(r) != 0
and note that that's a method on the Font, not the Face. You might need to add a dc.font field.
I still see boxes instead of Unicode symbols after go run unicode.go . How can I help to fix it?
It seems right now drawing emoji kind of works - I got it to work by simply loading emoji font using freetype:
But any idea how I could get colors to work? I'm obviously clueless about fonts. I could kind of found out that color fonts are it's own thing :-) and supported by sfnt. And there is also a library to parse sfnt which worked as well (x/image/font/sfnt). and with a recent patch https://go-review.googlesource.com/c/image/+/240897/ I was also able to get a font.Face
from it.
Unfortunately the font.Face
instance still rendered in the default color, instead of the emoji color. Any idea at which place this could go wrong? while parsing the ttf, creating the font.Face
from the sfnt.Font
when using gg dc.DrawString
? 🤔️
@hpoul Which font did you use? With Xolonium-Regular.ttf
I still get an empty box trying to print 😀
.
imgWidth := 64
imgHeight := 64
dc := gg.NewContext(imgWidth, imgHeight)
if err := dc.LoadFontFace("Xolonium-Regular.ttf", 64); err != nil {
panic(err)
}
dc.SetColor(color.Black)
dc.DrawString("😀", 0, 64)
_ = dc.SavePNG("out.png")
@devnoname120 i've tried noto emoji font and noto color emoji font https://github.com/googlefonts/noto-emoji#noto-emoji .. but i never got colors to work.. So I abandoned it completely..
@hpoul Thanks I ended up downloading all the emoji images from https://emojis.wiki/apple/ instead of generating them by myself.
When I modify a snippet
text.go
in examples/ ieI get an image and the emojis don't appear. I wanted to ask if we have emoji support and if you might have any clues for how we could go around this. Thank you.