// The PDF package of PrintDraftFast creates a PDF out of the Lex markdown parsetree. package pdf import ( "git.kiefte.eu/lapingvino/printdraftfast/lex" "git.kiefte.eu/lapingvino/printdraftfast/rules" "git.kiefte.eu/lapingvino/printdraftfast/font" "strconv" "strings" "regexp" "github.com/phpdave11/gofpdf" ) type Tree struct { PDF *gofpdf.Fpdf Rules rules.Set F lex.Document HTML gofpdf.HTMLBasicType } func (t Tree) pr(a string, text string) { line(t.PDF, t.Rules.Get(a), t.HTML, t.Rules.Get(a).Prefix+text+t.Rules.Get(a).Postfix) } func (t Tree) Render() { var block string var lastsection int for _, row := range t.F { switch row.Type { case "newpage": block = "" t.PDF.AddPage() t.PDF.SetHeaderFuncMode(func() { t.PDF.SetFont("CourierPrime", "", 12) t.PDF.SetXY(-1, 0.5) t.PDF.Cell(0, 0, strconv.Itoa(t.PDF.PageNo())+".") }, true) continue case "titlepage": block = "title" t.PDF.SetY(4) case "title", "Title": t.PDF.SetTitle(row.Contents, true) case "metasection": block = "meta" t.PDF.SetY(-2) } var contents string var level int if row.Type == "section" { contents = strings.TrimLeft(row.Contents, "#") level = len(row.Contents) - len(contents) contents = strings.TrimLeft(contents, " ") lastsection = level } else if row.Type == "scene" { level = lastsection + 1 contents = row.Contents } if contents != "" { t.PDF.Bookmark(contents, level, -1) } if t.Rules.Get(row.Type).Hide && block == "" { continue } if block != "" { row.Type = block } t.pr(row.Type, row.Contents) } } var ( bolditalic = regexp.MustCompile("\\*{3}([^\\*\n]+)\\*{3}") bold = regexp.MustCompile("\\*{2}([^\\*\n]+)\\*{2}") italic = regexp.MustCompile("\\*{1}([^\\*\n]+)\\*{1}") underline = regexp.MustCompile("_{1}([^\\*\n]+)_{1}") ) func line(pdf *gofpdf.Fpdf, format rules.Format, html gofpdf.HTMLBasicType, text string) { pdf.SetFont(format.Font, format.Style, format.Size) pdf.SetX(0) pdf.SetLeftMargin(format.Left) pdf.SetRightMargin(format.Right) text = strings.TrimRight(text, "\r\n") if strings.ContainsAny(text, "*_") { text = bolditalic.ReplaceAllString(text, "$1") text = bold.ReplaceAllString(text, "$1") text = italic.ReplaceAllString(text, "$1") text = underline.ReplaceAllString(text, "$1") if format.Align == "C" { text = "
"+text+"
" } html.Write(0.165, text) pdf.SetY(pdf.GetY()+0.165) return } pdf.MultiCell(0, 0.165, text, "", format.Align, false) } func Create(file string, format rules.Set, contents lex.Screenplay) { pdf := gofpdf.New("P", "in", "Letter", "") pdf.AddUTF8FontFromBytes("CourierPrime", "", font.MustAsset("Courier-Prime.ttf")) pdf.AddUTF8FontFromBytes("CourierPrime", "B", font.MustAsset("Courier-Prime-Bold.ttf")) pdf.AddUTF8FontFromBytes("CourierPrime", "I", font.MustAsset("Courier-Prime-Italic.ttf")) pdf.AddUTF8FontFromBytes("CourierPrime", "BI", font.MustAsset("Courier-Prime-Bold-Italic.ttf")) pdf.AddPage() pdf.SetMargins(1, 1, 1) pdf.SetXY(1, 1) f := Tree{ PDF: pdf, Rules: format, F: contents, HTML: pdf.HTMLBasicNew(), } f.Render() err := pdf.OutputFileAndClose(file) if err != nil { panic(err) } }