signintech / gopdf

A simple library for generating PDF written in Go lang
MIT License
2.45k stars 269 forks source link

Strange spacing behavior when adding text followed by a change of font. #149

Open mazzegi opened 3 years ago

mazzegi commented 3 years ago

Given the following code

package main

import "github.com/signintech/gopdf"

var fontDir = "/usr/share/fonts/truetype/"

func main() {
    pdf := &gopdf.GoPdf{}
    pdf.Start(gopdf.Config{
        PageSize: *gopdf.PageSizeA4,
    })

    pdf.AddTTFFont("sans", fontDir+"dejavu/DejaVuSans.ttf")
    pdf.AddTTFFontWithOption("sans", fontDir+"dejavu/DejaVuSans-Bold.ttf", gopdf.TtfOption{Style: gopdf.Bold})
    pdf.SetMargins(30, 30, 40, 40)
    pdf.AddPage()

    x0 := pdf.GetX()
    pdf.SetFont("sans", "", 14)
    pdf.Text("lorem ")
    pdf.SetFont("sans", "B", 14)
    pdf.Text("amet")

    pdf.SetX(x0)
    pdf.SetY(pdf.GetY() + 20)
    pdf.SetFont("sans", "", 14)
    pdf.Text("lorem ")
    pdf.Text("ipsum ")
    pdf.SetFont("sans", "B", 14)
    pdf.Text("amet")

    pdf.SetX(x0)
    pdf.SetY(pdf.GetY() + 20)
    pdf.SetFont("sans", "", 14)
    pdf.Text("lorem ")
    pdf.Text("ipsum ")
    pdf.Text("dolor ")
    pdf.SetFont("sans", "B", 14)
    pdf.Text("amet")

    pdf.WritePdf("foo.pdf")
}

... produces that strange result: image

It seems, that with every single call to pdf.Text() the spacing before the final bold amet get's bigger.

You may ask, why not combining several calls of pdf.Text() into one, but in reality this happens in a kind of automatism, where it's hard to avoid.

Any clues? Thanks

nmaupu commented 1 year ago

Same here just changing color bunch of times. Anybody has an idea on how to solve this ?

nmaupu commented 1 year ago

Here is an illustration of the problem. DeepinScreenshot_select-area_20220905193640

I iterate over each char of the word Geisha and change the color of one given char. I do that 6 times. The later I change the color, wider is the space 🤷

nmaupu commented 1 year ago

After debug, the problem seems to be here: https://github.com/signintech/gopdf/blob/master/list_cache_content.go#L53

When adding char, it creates one "boxes" of chars per font configuration. When the font config is different (bold vs normal, new color, etc.), it creates a new "box". The coordinate x,y of the next "box" is calculated on the line above.

If I understand correctly the code, it adds the width of the "box" to x to float the box to the left. But in our case, the next box should be just behind the previous box and not x+previous_box_width if that make sense.

nmaupu commented 1 year ago

I fixed it https://github.com/signintech/gopdf/pull/232

vantaboard commented 2 weeks ago

@oneplus1000 can you close this issue if it has been resolved?