jung-kurt / gofpdf

A PDF document generator with high level support for text, drawing and images
http://godoc.org/github.com/jung-kurt/gofpdf
MIT License
4.34k stars 787 forks source link

Text with upper case in the center of the document #224

Open Jinfaa opened 5 years ago

Jinfaa commented 5 years ago

Greetings to all! Thanks to the developers for this great library! I really liked how pdf creation was implemented and I started making a template. In the process of creating, I had a problem with creating a string with upper case. How can you do the same as in the picture? I want to note that the text should also be in the center. screenshot 2018-12-26 at 08 49 30

jung-kurt commented 5 years ago

You can render subscripted and superscripted text with the SubWrite() method. (This is a recent addition.) However, you'll need to make some small manual adjustments in order to center the text on a line. For example, you may want to measure the text without subscripts or superscripts using GetStringWidth(), then adjust it based on the width of the subscripted and superscripted text.

Jinfaa commented 5 years ago

Thanks for the answer! I'll try!

Jinfaa commented 5 years ago

@jung-kurt Some problems I have. I mean an array of names and to it is superscripted text. I stopped at this:

  1. I get the width of the string. Unmarked: 1,2,3 ...
  2. I divide the string using ",".
  3. Next, I'll give the code better:
func writeAuthors(textArr []string, lineHeight float64, f *gofpdf.Fpdf) {
    lMargin, _, rMargin, _ := f.GetMargins()

    pageWidth, _ := f.GetPageSize()
    width := pageWidth - (lMargin + rMargin)

    textStr := strings.Join(textArr, ", ")
    lines := f.SplitLines([]byte(textStr), width)

    for _, lineBt := range lines {
        lineStr := string(lineBt)
        lineWidth := f.GetStringWidth(lineStr)
        lineWidth += f.GetStringWidth("2")

        f.SetLeftMargin(lMargin + ((width - lineWidth) / 2))
        for _, author := range strings.Split(lineStr, ",") {
            f.Write(lineHeight, author)
            f.Write(lineHeight, ", ")
            f.SubWrite(lineHeight, "2", 14, 4, 0, "")
        }
        f.SetLeftMargin(lMargin)
    }
}

But I’m getting something completely different from what I wanted. All due to the fact that I do not know how to properly divided into lines. screenshot 2018-12-28 at 15 55 48

Jinfaa commented 5 years ago

Tell me is it possible to somehow modify the function html2pdf, so that it supports superscript?

jung-kurt commented 5 years ago

It may be easier not to join the reference items at first. Here is an example:

package main

import (
    "fmt"
    "os"

    "github.com/jung-kurt/gofpdf"
)

type refType struct {
    name, super string
}

var refList = []refType{
    {"D. K. Brenner", "2"},
    {"N. J. Benavidez", "1, 2"},
    {"P. L. Villa", "2"},
    {"M. R. Lentz", "1"},
    {"M. C. Hunt", "1, 3"},
    {"C. R. Harris", "2"},
    {"R. J. Gonzalez", "2, 3, 4"},
    {"R. E. Perez", "2"},
    {"D. A. Taylor", "2"},
    {"K. B. Reeder", "2"},
    {"C. A. Hurley", "2"},
    {"J. C. Rosenberg", "3"},
    {"E. G. Urban", "2"},
}

func main() {

    const (
        fontSize  = 12
        scale     = 1.2
        superSize = fontSize / scale
    )

    pdf := gofpdf.New("P", "mm", "A4", "") // 210mm x 297mm
    pdf.AddPage()
    pdf.SetFont("Times", "I", fontSize)
    _, lineHt := pdf.GetFontSize()
    lineHt *= 1.2 // Pad for superscript
    lf, rt, _, _ := pdf.GetMargins()
    pageWidth, _ := pdf.GetPageSize()
    width := pageWidth - (lf + rt)

    // Approximate width of reference item
    refWidth := func(ref refType) float64 {
        return pdf.GetStringWidth(ref.name) + pdf.GetStringWidth(" "+ref.super)/scale
    }

    refWrite := func(ref refType) {
        pdf.Write(lineHt, ref.name)
        pdf.SubWrite(lineHt, " "+ref.super, superSize, 4, 0, "")
    }

    sep := ", "
    sepWd := pdf.GetStringWidth(sep)
    accum := 0.0
    for j, ref := range refList {
        if j == 0 {
            refWrite(ref)
            accum = refWidth(ref)
        } else {
            addWd := sepWd + refWidth(ref)
            if accum+addWd <= width {
                pdf.Write(lineHt, sep)
                refWrite(ref)
                accum += addWd
            } else {
                pdf.Ln(lineHt)
                refWrite(ref)
                accum = refWidth(ref)
            }
        }
    }

    err := pdf.OutputFileAndClose("example.pdf")
    if err != nil {
        fmt.Fprintf(os.Stderr, "%s\n", err)
    }

}

This example does not center the lines, but you have all the information needed to do so.

Tell me is it possible to somehow modify the function html2pdf, so that it supports superscript?

This would be an excellent enhancement. I will make a note about this.

Jinfaa commented 5 years ago

@jung-kurt thanks for the help. I remembered html2pdf because it is well implemented, and I have mixed text, with many different tags, such as italics, underscores, and superscripts. so I look forward to this improvement! Thanks for your beautiful library.