From 4aa4a931b57c01e39ef920dce28cf8210e2c4cb0 Mon Sep 17 00:00:00 2001 From: Stani Date: Sun, 12 Jul 2015 14:34:34 +0200 Subject: added Fpdf.GetFontDesc method and documentation for FontDescType --- .gitignore | 1 + def.go | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------- fpdf.go | 9 +++++++ 3 files changed, 90 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index d23e6cd..91bef76 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ pdf/*.pdf look open pdf.txt +private *.sublime* font/Ubuntu-* *.0 diff --git a/def.go b/def.go index 15836d0..3973351 100644 --- a/def.go +++ b/def.go @@ -246,21 +246,91 @@ type fontBoxType struct { Xmin, Ymin, Xmax, Ymax int } -type fontDescType struct { - Ascent int - Descent int - CapHeight int - Flags int - FontBBox fontBoxType - ItalicAngle int - StemV int +// Font flags for FontDescType.Flags as defined in the pdf specification. +const ( + // FontFlagFixedPitch is set if all glyphs have the same width (as + // opposed to proportional or variable-pitch fonts, which have + // different widths). + FontFlagFixedPitch = 1 << 0 + // FontFlagSerif is set if glyphs have serifs, which are short + // strokes drawn at an angle on the top and bottom of glyph stems. + // (Sans serif fonts do not have serifs.) + FontFlagSerif = 1 << 1 + // FontFlagSymbolic is set if font contains glyphs outside the + // Adobe standard Latin character set. This flag and the + // Nonsymbolic flag shall not both be set or both be clear. + FontFlagSymbolic = 1 << 2 + // FontFlagScript is set if glyphs resemble cursive handwriting. + FontFlagScript = 1 << 3 + // FontFlagNonsymbolic is set if font uses the Adobe standard + // Latin character set or a subset of it. + FontFlagNonsymbolic = 1 << 5 + // FontFlagItalic is set if glyphs have dominant vertical strokes + // that are slanted. + FontFlagItalic = 1 << 6 + // FontFlagAllCap is set if font contains no lowercase letters; + // typically used for display purposes, such as for titles or + // headlines. + FontFlagAllCap = 1 << 16 + // SmallCap is set if font contains both uppercase and lowercase + // letters. The uppercase letters are similar to those in the + // regular version of the same typeface family. The glyphs for the + // lowercase letters have the same shapes as the corresponding + // uppercase letters, but they are sized and their proportions + // adjusted so that they have the same size and stroke weight as + // lowercase glyphs in the same typeface family. + SmallCap = 1 << 18 + // ForceBold determines whether bold glyphs shall be painted with + // extra pixels even at very small text sizes by a conforming + // reader. If the ForceBold flag is set, features of bold glyphs + // may be thickened at small text sizes. + ForceBold = 1 << 18 +) + +// FontDescType (font descriptor) specifies metrics and other +// attributes of a font, as distinct from the metrics of individual +// glyphs (as defined in the pdf specification). +type FontDescType struct { + // The maximum height above the baseline reached by glyphs in this + // font (for example for "S"). The height of glyphs for accented + // characters shall be excluded. + Ascent int + // The maximum depth below the baseline reached by glyphs in this + // font. The value shall be a negative number. + Descent int + // The vertical coordinate of the top of flat capital letters, + // measured from the baseline (for example "H"). + CapHeight int + // A collection of flags defining various characteristics of the + // font. (See the FontFlag* constants.) + Flags int + // A rectangle, expressed in the glyph coordinate system, that + // shall specify the font bounding box. This should be the smallest + // rectangle enclosing the shape that would result if all of the + // glyphs of the font were placed with their origins coincident + // and then filled. + FontBBox fontBoxType + // The angle, expressed in degrees counterclockwise from the + // vertical, of the dominant vertical strokes of the font. (The + // 9-o’clock position is 90 degrees, and the 3-o’clock position + // is –90 degrees.) The value shall be negative for fonts that + // slope to the right, as almost all italic fonts do. + ItalicAngle int + // The thickness, measured horizontally, of the dominant vertical + // stems of glyphs in the font. + StemV int + // The width to use for character codes whose widths are not + // specified in a font dictionary’s Widths array. This shall have + // a predictable effect only if all such codes map to glyphs whose + // actual widths are the same as the value of the MissingWidth + // entry. (Default value: 0.) MissingWidth int } type fontDefType struct { Tp string // "Core", "TrueType", ... Name string // "Courier-Bold", ... - Desc fontDescType // Font descriptor + Desc FontDescType // Font descriptor Up int // Underline position Ut int // Underline thickness Cw [256]int // Character width by ordinal @@ -285,5 +355,5 @@ type fontInfoType struct { UnderlinePosition int Widths [256]int Size1, Size2 uint32 - Desc fontDescType + Desc FontDescType } diff --git a/fpdf.go b/fpdf.go index 1fe9b1b..6eae426 100644 --- a/fpdf.go +++ b/fpdf.go @@ -1429,6 +1429,15 @@ func (f *Fpdf) AddFontFromReader(familyStr, styleStr string, r io.Reader) { return } +// GetFontDesc returns the font descriptor, which can be used for +// example to find the baseline of a font. See FontDescType for +// documentation about the font descriptor. +// See AddFont for details about familyStr and styleStr. +func (f *Fpdf) GetFontDesc(familyStr, styleStr string) FontDescType { + fontkey := familyStr + styleStr // see AddFontFromReader + return f.fonts[fontkey].Desc +} + // SetFont sets the font used to print character strings. It is mandatory to // call this method at least once before printing text or the resulting // document will not be valid. -- cgit v1.2.1-24-ge1ad From f00c0a597be2dca589bdd7bd6ba5937b19ebdcfe Mon Sep 17 00:00:00 2001 From: Stani Date: Sun, 12 Jul 2015 17:03:33 +0200 Subject: implement vertical baseline alignment for text --- fpdf.go | 34 ++++++++++++++++++++++++---------- fpdf_test.go | 42 +++++++++++++++++++++++++++++------------- 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/fpdf.go b/fpdf.go index 6eae426..fd0c91f 100644 --- a/fpdf.go +++ b/fpdf.go @@ -1376,6 +1376,16 @@ func (f *Fpdf) AddFont(familyStr, styleStr, fileStr string) { f.AddFontFromReader(familyStr, styleStr, file) } +// getFontKey is used by AddFontFromReader and GetFontDesc +func getFontKey(familyStr, styleStr string) string { + familyStr = strings.ToLower(familyStr) + styleStr = strings.ToUpper(styleStr) + if styleStr == "IB" { + styleStr = "BI" + } + return familyStr + styleStr +} + // AddFontFromReader imports a TrueType, OpenType or Type1 font and makes it // available using a reader that satisifies the io.Reader interface. See // AddFont for details about familyStr and styleStr. @@ -1385,12 +1395,7 @@ func (f *Fpdf) AddFontFromReader(familyStr, styleStr string, r io.Reader) { } // dbg("Adding family [%s], style [%s]", familyStr, styleStr) var ok bool - familyStr = strings.ToLower(familyStr) - styleStr = strings.ToUpper(styleStr) - if styleStr == "IB" { - styleStr = "BI" - } - fontkey := familyStr + styleStr + fontkey := getFontKey(familyStr, styleStr) _, ok = f.fonts[fontkey] if ok { return @@ -1434,8 +1439,7 @@ func (f *Fpdf) AddFontFromReader(familyStr, styleStr string, r io.Reader) { // documentation about the font descriptor. // See AddFont for details about familyStr and styleStr. func (f *Fpdf) GetFontDesc(familyStr, styleStr string) FontDescType { - fontkey := familyStr + styleStr // see AddFontFromReader - return f.fonts[fontkey].Desc + return f.fonts[getFontKey(familyStr, styleStr)].Desc } // SetFont sets the font used to print character strings. It is mandatory to @@ -1686,8 +1690,8 @@ func (f *Fpdf) SetAcceptPageBreakFunc(fnc func() bool) { // alignStr specifies how the text is to be positionined within the cell. // Horizontal alignment is controlled by including "L", "C" or "R" (left, // center, right) in alignStr. Vertical alignment is controlled by including -// "T", "M" or "B" (top, middle, bottom) in alignStr. The default alignment is -// left middle. +// "T", "M", "B" or "A" (top, middle, bottom, baseline) in alignStr. The default +// alignment is left middle. // // fill is true to paint the cell background or false to leave it transparent. // @@ -1778,6 +1782,16 @@ func (f *Fpdf) CellFormat(w, h float64, txtStr string, borderStr string, ln int, dy = (f.fontSize - h) / 2.0 } else if strings.Index(alignStr, "B") != -1 { dy = (h - f.fontSize) / 2.0 + } else if strings.Index(alignStr, "A") != -1 { + var descent float64 + d := f.currentFont.Desc + if d.Descent == 0 { + // not defined (standard font?), use average of 19% + descent = -0.19 * f.fontSize + } else { + descent = float64(d.Descent) * f.fontSize / float64(d.Ascent-d.Descent) + } + dy = (h-f.fontSize)/2.0 - descent } else { dy = 0 } diff --git a/fpdf_test.go b/fpdf_test.go index fdc3334..63d4655 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -1175,25 +1175,41 @@ func ExampleFpdf_CellFormat_2() { recType{"BC", "bottom center"}, recType{"BR", "bottom right"}, } - pdf := gofpdf.New("P", "mm", "A4", "") // A4 210.0 x 297.0 - pdf.SetFont("Helvetica", "", 16) - linkStr := "" - for pageJ := 0; pageJ < 2; pageJ++ { - pdf.AddPage() - pdf.SetMargins(10, 10, 10) - pdf.SetAutoPageBreak(false, 0) - borderStr := "1" - for _, rec := range recList { - pdf.SetXY(20, 20) - pdf.CellFormat(170, 257, rec.txt, borderStr, 0, rec.align, false, 0, linkStr) - borderStr = "" + recListBaseline := []recType{ + recType{"AL", "baseline left"}, + recType{"AC", "baseline center"}, + recType{"AR", "baseline right"}, + } + var formatRect = func(pdf *gofpdf.Fpdf, recList []recType) { + linkStr := "" + for pageJ := 0; pageJ < 2; pageJ++ { + pdf.AddPage() + pdf.SetMargins(10, 10, 10) + pdf.SetAutoPageBreak(false, 0) + borderStr := "1" + for _, rec := range recList { + pdf.SetXY(20, 20) + pdf.CellFormat(170, 257, rec.txt, borderStr, 0, rec.align, false, 0, linkStr) + borderStr = "" + } + linkStr = "https://github.com/jung-kurt/gofpdf" } - linkStr = "https://github.com/jung-kurt/gofpdf" } + pdf := gofpdf.New("P", "mm", "A4", "") // A4 210.0 x 297.0 + pdf.SetFont("Helvetica", "", 16) + formatRect(pdf, recList) + formatRect(pdf, recListBaseline) + var fr fontResourceType + pdf.SetFontLoader(fr) + pdf.AddFont("Calligrapher", "", "calligra.json") + pdf.SetFont("Calligrapher", "", 16) + formatRect(pdf, recListBaseline) fileStr := exampleFilename("Fpdf_CellFormat_2_align") err := pdf.OutputFileAndClose(fileStr) summary(err, fileStr) // Output: + // Generalized font loader reading calligra.json + // Generalized font loader reading calligra.z // Successfully generated pdf/Fpdf_CellFormat_2_align.pdf } -- cgit v1.2.1-24-ge1ad