diff options
Diffstat (limited to 'fpdf.go')
-rw-r--r-- | fpdf.go | 104 |
1 files changed, 92 insertions, 12 deletions
@@ -36,6 +36,7 @@ import ( "math" "os" "path" + "strconv" "strings" "time" ) @@ -312,6 +313,17 @@ func (f *Fpdf) SetFontLocation(fontDirStr string) { f.fontpath = fontDirStr } +// SetFontLoader sets a loader used to read font files (.json and .z) from an +// arbitrary source. If a font loader has been specified, it is used to load +// the named font resources when AddFont() is called. If this operation fails, +// an attempt is made to load the resources from the configured font directory +// (see SetFontLocation()). +// +// See tutorial 29 for an example of this method. +func (f *Fpdf) SetFontLoader(loader FontLoader) { + f.fontLoader = loader +} + // SetHeaderFunc sets the function that lets the application render the page // header. The specified function is automatically called by AddPage() and // should not be called directly by the application. The implementation in Fpdf @@ -565,6 +577,10 @@ func (f *Fpdf) AddPageFormat(orientationStr string, size SizeType) { // Set line width f.lineWidth = lw f.outf("%.2f w", lw*f.k) + // Set dash pattern + if len(f.dashArray) > 0 { + f.outputDashPattern() + } // Set font if familyStr != "" { f.SetFont(familyStr, style, fontsize) @@ -775,6 +791,44 @@ func (f *Fpdf) SetLineCapStyle(styleStr string) { } } +// SetDashPattern sets the dash pattern that is used to draw lines. The +// dashArray elements are numbers that specify the lengths, in units +// established in New(), of alternating dashes and gaps. The dash phase +// specifies the distance into the dash pattern at which to start the dash. The +// dash pattern is retained from page to page. Call this method with an empty +// array to restore solid line drawing. +// +// See tutorial 28 for an example of this function. +func (f *Fpdf) SetDashPattern(dashArray []float64, dashPhase float64) { + scaled := make([]float64, len(dashArray)) + for i, value := range dashArray { + scaled[i] = value * f.k + } + dashPhase *= f.k + if !slicesEqual(scaled, f.dashArray) || dashPhase != f.dashPhase { + f.dashArray = scaled + f.dashPhase = dashPhase + if f.page > 0 { + f.outputDashPattern() + } + } +} + +func (f *Fpdf) outputDashPattern() { + var buf bytes.Buffer + buf.WriteByte('[') + for i, value := range f.dashArray { + if i > 0 { + buf.WriteByte(' ') + } + buf.WriteString(strconv.FormatFloat(value, 'f', 2, 64)) + } + buf.WriteString("] ") + buf.WriteString(strconv.FormatFloat(f.dashPhase, 'f', 2, 64)) + buf.WriteString(" d") + f.outbuf(&buf) +} + // Line draws a line between points (x1, y1) and (x2, y2) using the current // draw color, line width and cap style. func (f *Fpdf) Line(x1, y1, x2, y2 float64) { @@ -1319,8 +1373,19 @@ func (f *Fpdf) AddFont(familyStr, styleStr, fileStr string) { if fileStr == "" { fileStr = strings.Replace(familyStr, " ", "", -1) + strings.ToLower(styleStr) + ".json" } - fileStr = path.Join(f.fontpath, fileStr) + if f.fontLoader != nil { + reader, err := f.fontLoader.Open(fileStr) + if err == nil { + f.AddFontFromReader(familyStr, styleStr, reader) + if closer, ok := reader.(io.Closer); ok { + closer.Close() + } + return + } + } + + fileStr = path.Join(f.fontpath, fileStr) file, err := os.Open(fileStr) if err != nil { f.err = err @@ -2932,7 +2997,7 @@ func (f *Fpdf) putfonts() { f.newobj() info.n = f.n f.fontFiles[file] = info - font, err := ioutil.ReadFile(path.Join(f.fontpath, file)) + font, err := f.loadFontFile(file) if err != nil { f.err = err return @@ -3032,6 +3097,20 @@ func (f *Fpdf) putfonts() { return } +func (f *Fpdf) loadFontFile(name string) ([]byte, error) { + if f.fontLoader != nil { + reader, err := f.fontLoader.Open(name) + if err == nil { + data, err := ioutil.ReadAll(reader) + if closer, ok := reader.(io.Closer); ok { + closer.Close() + } + return data, err + } + } + return ioutil.ReadFile(path.Join(f.fontpath, name)) +} + func (f *Fpdf) putimages() { for _, img := range f.images { f.putimage(img) @@ -3385,16 +3464,17 @@ func (f *Fpdf) enddoc() { } // Path Drawing +// // Create a "path" by moving a virtual stylus around the page, then draw it or // fill it in. The main advantage of using the path drawing routines rather // than multiple Fpdf.Line is that PDF creates nice line joins at the angles, // rather than just overlaying the lines. + +// MoveTo moves the stylus to (x, y) without drawing the path from the previous +// point. Paths must start with a MoveTo to set the original stylus location or +// the result is undefined. // -// MoveTo moves the stylus to (x, y) without drawing the path from the -// previous point. Paths must start with a MoveTo to set the original stylus -// location or the result is undefined. -// -// See tutorial 29 for an example of this function. +// See tutorial 30 for an example of this function. func (f *Fpdf) MoveTo(x, y float64) { f.point(x, y) // rename? } @@ -3403,7 +3483,7 @@ func (f *Fpdf) MoveTo(x, y float64) { // becomes the new stylus location. Note that this only creates the line in // the path; it does not actually draw the line on the page. // -// See tutorial 29 for an example of this function. +// See tutorial 30 for an example of this function. func (f *Fpdf) LineTo(x, y float64) { f.outf("%.2f %.2f l", x*f.k, (f.h-y)*f.k) } @@ -3415,7 +3495,7 @@ func (f *Fpdf) LineTo(x, y float64) { // point. At the end point, the curve is tangent to the straight line between // the end point and the control point. // -// See tutorial 29 for an example of this function. +// See tutorial 30 for an example of this function. func (f *Fpdf) CurveTo(cx, cy, x, y float64) { f.outf("%.5f %.5f %.5f %.5f v", cx*f.k, (f.h-cy)*f.k, x*f.k, (f.h-y)*f.k) } @@ -3428,7 +3508,7 @@ func (f *Fpdf) CurveTo(cx, cy, x, y float64) { // the curve is tangent to the straight line between the end point and the // control point (cx1, cy1). // -// See tutorial 29 for examples of this function. +// See tutorial 30 for examples of this function. func (f *Fpdf) CurveBezierCubicTo(cx0, cy0, cx1, cy1, x, y float64) { f.curve(cx0, cy0, cx1, cy1, x, y) // rename? } @@ -3437,7 +3517,7 @@ func (f *Fpdf) CurveBezierCubicTo(cx0, cy0, cx1, cy1, x, y float64) { // (if not the same) and mark the path as closed so the first and last lines // join nicely. // -// See tutorial 29 for an example of this function. +// See tutorial 30 for an example of this function. func (f *Fpdf) ClosePath() { f.outf("h") } @@ -3449,7 +3529,7 @@ func (f *Fpdf) ClosePath() { // the current draw color, line width, and cap style centered on the // path. Filling uses the current fill color. // -// See tutorial 29 for an example of this function. +// See tutorial 30 for an example of this function. func (f *Fpdf) DrawPath(styleStr string) { f.outf(fillDrawOp(styleStr)) } |