Closed ajstarks closed 5 years ago
I'm really stumped on this one. It looks like the glyph widths are properly indexed, but the glyphs themselves are not. The Unicode values are close to 64K which makes me wonder about an int16/uint16 issue, but I can't find anything along these lines either in gofpdf and makefont.
While I am tracking this down, you may be interested in a recent pull request (#237) that supports UTF-8 fonts. Licensing issues will keep that work from being merged into gofpdf, but if you're OK with the GPL, you may want to work with that package.
Not a bug after all. It looks like the font map you used is inaccurate.
If you examine the font (FontDrop! is very informative) you can get a list of glyph names in the data/names section. From that, you can construct an accurate font map. Here is a excerpt:
!20 U+0020 space
!41 U+F000 uniF000
!42 U+F001 uniF001
!43 U+F002 uniF002
With this, you can use makefont
to construct the JSON descriptor file. Then the following program shows the icons as expected:
package main
import (
"fmt"
"os"
"github.com/jung-kurt/gofpdf/v2"
)
func main() {
pdf := gofpdf.New("P", "mm", "A4", "")
fontSize := 32.0
pdf.AddFont("weather", "", "weather.json")
pdf.SetFont("weather", "", fontSize)
ht := pdf.PointConvert(fontSize)
pdf.AddPage()
pdf.CellFormat(190, ht, "ABC", "", 1, "C", false, 0, "")
fileStr := "w.pdf"
err := pdf.OutputFileAndClose(fileStr)
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
}
}
wonderful, thank you.
I'm wondering now, given my broken map, how it worked at all?
Not sure. When I view the PDF you posted above, I see only the standard CP1252 glyphs even though I can see that the document embeds the weather font. On your reader, are the weather icons actually rendered?
yes, they are rendered, just in the wrong place. Perhaps there should be some code in makefont does some validation of the glyph names.
This is curious! My PDF reader is the native Chrome OS viewer, and I don't see any weather icons at all in the PDF linked above.
Another thing: I downloaded weathericons-regular-webfont.ttf directly from the weather-icons repository. When I examine the glyph name listing at the end of the file with a hex viewer, the names I see look like "uniF0E2", not "wi-moon-alt-waning-gibbous-5". The map and PDF I generated from this file all use the "uniXXXX" name format. However, your PDF shows the "wi-*" name format. Where did you get the TTF and map files? Given that your TTF has the descriptive glyph names, maybe the problem you encountered is simply one of ordering, that is, irregularly mapping code page positions 0 through 255 to the Unicode weather glyphs. But that doesn't explain why I don't see any weather icons at all in the PDF you posted. I'm currently at a loss to explain that.
thanks for your help, I will correct my map as you specified. Probably ok to close.
I think the issue is this. When a Unicode rune with a multibyte utf-8 encoding is read by Go's standard library (in this case, by the for _, r := range str
expression), it is reported to gofpdf as the scalar Unicode value (a rune), not as a byte slice. gofpdf looks this rune up in a map to find the corresponding code page byte position (0 - 255).
With the weather font, we have created a font map that associates code page positions with glyphs. Consequently, it is easier for us to dispense with utf-8 encoding entirely and simply use byte values in our strings. Here is a truncated example.
weather.map
!20 U+0020 space
!41 U+F000 uniF000
!42 U+F001 uniF001
!43 U+F002 uniF002
!99 U+F0CB uniF0CB
!9A U+F0C5 uniF0C5
!9B U+F0C6 uniF0C6
makefont -embed -enc weather.map weather.ttf
weather.go
package main
import (
"fmt"
"os"
"github.com/jung-kurt/gofpdf/v2"
)
func main() {
pdf := gofpdf.New("P", "mm", "A4", "")
fontSize := 32.0
pdf.AddFont("weather", "", "weather.json")
pdf.SetFont("weather", "", fontSize)
ht := pdf.PointConvert(fontSize)
pdf.AddPage()
pdf.CellFormat(190, ht, "ABC\x99\x9A\x9B", "", 1, "C", false, 0, "")
fileStr := "w.pdf"
err := pdf.OutputFileAndClose(fileStr)
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
}
}
This generates a PDF with 6 icons properly rendered. Notice that it skips the UnicodeTranslator
entirely. In order to use the automatic translation, the source string would have to embed the utf-8 encoding for Unicode values like 0xF0C6. This is the sequence 0xEF 0x83 0x86, not the same as the two bytes that make up the value 0xF0C6.
I'm attempting to encode the weather icon font (https://erikflowers.github.io/weather-icons/) which contains 222 glyphs which I assume will fit into the 255 limit.
When rendered, the glyphs are not on the expected places (see attached PDF)
weather.pdf
The font encodes with makefont with no error:
Here is the weather-icons.map