1/*
2 * Copyright (c) 2013-2014 Kurt Jung (Gmail: kurt.w.jung)
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17package gofpdf
18
19import (
20	"bytes"
21	"crypto/sha1"
22	"encoding/gob"
23	"encoding/json"
24	"fmt"
25	"io"
26	"time"
27)
28
29// Version of FPDF from which this package is derived
30const (
31	cnFpdfVersion = "1.7"
32)
33
34type blendModeType struct {
35	strokeStr, fillStr, modeStr string
36	objNum                      int
37}
38
39type gradientType struct {
40	tp                int // 2: linear, 3: radial
41	clr1Str, clr2Str  string
42	x1, y1, x2, y2, r float64
43	objNum            int
44}
45
46const (
47	// OrientationPortrait represents the portrait orientation.
48	OrientationPortrait = "portrait"
49
50	// OrientationLandscape represents the landscape orientation.
51	OrientationLandscape = "landscape"
52)
53
54const (
55	// UnitPoint represents the size unit point
56	UnitPoint = "pt"
57	// UnitMillimeter represents the size unit millimeter
58	UnitMillimeter = "mm"
59	// UnitCentimeter represents the size unit centimeter
60	UnitCentimeter = "cm"
61	// UnitInch represents the size unit inch
62	UnitInch = "inch"
63)
64
65const (
66	// PageSizeA3 represents DIN/ISO A3 page size
67	PageSizeA3 = "A3"
68	// PageSizeA4 represents DIN/ISO A4 page size
69	PageSizeA4 = "A4"
70	// PageSizeA5 represents DIN/ISO A5 page size
71	PageSizeA5 = "A5"
72	// PageSizeLetter represents US Letter page size
73	PageSizeLetter = "Letter"
74	// PageSizeLegal represents US Legal page size
75	PageSizeLegal = "Legal"
76)
77
78const (
79	// BorderNone set no border
80	BorderNone = ""
81	// BorderFull sets a full border
82	BorderFull = "1"
83	// BorderLeft sets the border on the left side
84	BorderLeft = "L"
85	// BorderTop sets the border at the top
86	BorderTop = "T"
87	// BorderRight sets the border on the right side
88	BorderRight = "R"
89	// BorderBottom sets the border on the bottom
90	BorderBottom = "B"
91)
92
93const (
94	// LineBreakNone disables linebreak
95	LineBreakNone = 0
96	// LineBreakNormal enables normal linebreak
97	LineBreakNormal = 1
98	// LineBreakBelow enables linebreak below
99	LineBreakBelow = 2
100)
101
102const (
103	// AlignLeft left aligns the cell
104	AlignLeft = "L"
105	// AlignRight right aligns the cell
106	AlignRight = "R"
107	// AlignCenter centers the cell
108	AlignCenter = "C"
109	// AlignTop aligns the cell to the top
110	AlignTop = "T"
111	// AlignBottom aligns the cell to the bottom
112	AlignBottom = "B"
113	// AlignMiddle aligns the cell to the middle
114	AlignMiddle = "M"
115	// AlignBaseline aligns the cell to the baseline
116	AlignBaseline = "B"
117)
118
119type colorMode int
120
121const (
122	colorModeRGB colorMode = iota
123	colorModeSpot
124	colorModeCMYK
125)
126
127type colorType struct {
128	r, g, b    float64
129	ir, ig, ib int
130	mode       colorMode
131	spotStr    string // name of current spot color
132	gray       bool
133	str        string
134}
135
136// SpotColorType specifies a named spot color value
137type spotColorType struct {
138	id, objID int
139	val       cmykColorType
140}
141
142// CMYKColorType specifies an ink-based CMYK color value
143type cmykColorType struct {
144	c, m, y, k byte // 0% to 100%
145}
146
147// SizeType fields Wd and Ht specify the horizontal and vertical extents of a
148// document element such as a page.
149type SizeType struct {
150	Wd, Ht float64
151}
152
153// PointType fields X and Y specify the horizontal and vertical coordinates of
154// a point, typically used in drawing.
155type PointType struct {
156	X, Y float64
157}
158
159// XY returns the X and Y components of the receiver point.
160func (p PointType) XY() (float64, float64) {
161	return p.X, p.Y
162}
163
164// ImageInfoType contains size, color and other information about an image.
165// Changes to this structure should be reflected in its GobEncode and GobDecode
166// methods.
167type ImageInfoType struct {
168	data  []byte  // Raw image data
169	smask []byte  // Soft Mask, an 8bit per-pixel transparency mask
170	n     int     // Image object number
171	w     float64 // Width
172	h     float64 // Height
173	cs    string  // Color space
174	pal   []byte  // Image color palette
175	bpc   int     // Bits Per Component
176	f     string  // Image filter
177	dp    string  // DecodeParms
178	trns  []int   // Transparency mask
179	scale float64 // Document scale factor
180	dpi   float64 // Dots-per-inch found from image file (png only)
181	i     string  // SHA-1 checksum of the above values.
182}
183
184func generateImageID(info *ImageInfoType) (string, error) {
185	b, err := info.GobEncode()
186	return fmt.Sprintf("%x", sha1.Sum(b)), err
187}
188
189// GobEncode encodes the receiving image to a byte slice.
190func (info *ImageInfoType) GobEncode() (buf []byte, err error) {
191	fields := []interface{}{info.data, info.smask, info.n, info.w, info.h, info.cs,
192		info.pal, info.bpc, info.f, info.dp, info.trns, info.scale, info.dpi}
193	w := new(bytes.Buffer)
194	encoder := gob.NewEncoder(w)
195	for j := 0; j < len(fields) && err == nil; j++ {
196		err = encoder.Encode(fields[j])
197	}
198	if err == nil {
199		buf = w.Bytes()
200	}
201	return
202}
203
204// GobDecode decodes the specified byte buffer (generated by GobEncode) into
205// the receiving image.
206func (info *ImageInfoType) GobDecode(buf []byte) (err error) {
207	fields := []interface{}{&info.data, &info.smask, &info.n, &info.w, &info.h,
208		&info.cs, &info.pal, &info.bpc, &info.f, &info.dp, &info.trns, &info.scale, &info.dpi}
209	r := bytes.NewBuffer(buf)
210	decoder := gob.NewDecoder(r)
211	for j := 0; j < len(fields) && err == nil; j++ {
212		err = decoder.Decode(fields[j])
213	}
214
215	info.i, err = generateImageID(info)
216	return
217}
218
219// PointConvert returns the value of pt, expressed in points (1/72 inch), as a
220// value expressed in the unit of measure specified in New(). Since font
221// management in Fpdf uses points, this method can help with line height
222// calculations and other methods that require user units.
223func (f *Fpdf) PointConvert(pt float64) (u float64) {
224	return pt / f.k
225}
226
227// PointToUnitConvert is an alias for PointConvert.
228func (f *Fpdf) PointToUnitConvert(pt float64) (u float64) {
229	return pt / f.k
230}
231
232// UnitToPointConvert returns the value of u, expressed in the unit of measure
233// specified in New(), as a value expressed in points (1/72 inch). Since font
234// management in Fpdf uses points, this method can help with setting font sizes
235// based on the sizes of other non-font page elements.
236func (f *Fpdf) UnitToPointConvert(u float64) (pt float64) {
237	return u * f.k
238}
239
240// Extent returns the width and height of the image in the units of the Fpdf
241// object.
242func (info *ImageInfoType) Extent() (wd, ht float64) {
243	return info.Width(), info.Height()
244}
245
246// Width returns the width of the image in the units of the Fpdf object.
247func (info *ImageInfoType) Width() float64 {
248	return info.w / (info.scale * info.dpi / 72)
249}
250
251// Height returns the height of the image in the units of the Fpdf object.
252func (info *ImageInfoType) Height() float64 {
253	return info.h / (info.scale * info.dpi / 72)
254}
255
256// SetDpi sets the dots per inch for an image. PNG images MAY have their dpi
257// set automatically, if the image specifies it. DPI information is not
258// currently available automatically for JPG and GIF images, so if it's
259// important to you, you can set it here. It defaults to 72 dpi.
260func (info *ImageInfoType) SetDpi(dpi float64) {
261	info.dpi = dpi
262}
263
264type fontFileType struct {
265	length1, length2 int64
266	n                int
267	embedded         bool
268	content          []byte
269	fontType         string
270}
271
272type linkType struct {
273	x, y, wd, ht float64
274	link         int    // Auto-generated internal link ID or...
275	linkStr      string // ...application-provided external link string
276}
277
278type intLinkType struct {
279	page int
280	y    float64
281}
282
283// outlineType is used for a sidebar outline of bookmarks
284type outlineType struct {
285	text                                   string
286	level, parent, first, last, next, prev int
287	y                                      float64
288	p                                      int
289}
290
291// InitType is used with NewCustom() to customize an Fpdf instance.
292// OrientationStr, UnitStr, SizeStr and FontDirStr correspond to the arguments
293// accepted by New(). If the Wd and Ht fields of Size are each greater than
294// zero, Size will be used to set the default page size rather than SizeStr. Wd
295// and Ht are specified in the units of measure indicated by UnitStr.
296type InitType struct {
297	OrientationStr string
298	UnitStr        string
299	SizeStr        string
300	Size           SizeType
301	FontDirStr     string
302}
303
304// FontLoader is used to read fonts (JSON font specification and zlib compressed font binaries)
305// from arbitrary locations (e.g. files, zip files, embedded font resources).
306//
307// Open provides an io.Reader for the specified font file (.json or .z). The file name
308// never includes a path. Open returns an error if the specified file cannot be opened.
309type FontLoader interface {
310	Open(name string) (io.Reader, error)
311}
312
313// Pdf defines the interface used for various methods. It is implemented by the
314// main FPDF instance as well as templates.
315type Pdf interface {
316	AddFont(familyStr, styleStr, fileStr string)
317	AddFontFromBytes(familyStr, styleStr string, jsonFileBytes, zFileBytes []byte)
318	AddFontFromReader(familyStr, styleStr string, r io.Reader)
319	AddLayer(name string, visible bool) (layerID int)
320	AddLink() int
321	AddPage()
322	AddPageFormat(orientationStr string, size SizeType)
323	AddSpotColor(nameStr string, c, m, y, k byte)
324	AliasNbPages(aliasStr string)
325	ArcTo(x, y, rx, ry, degRotate, degStart, degEnd float64)
326	Arc(x, y, rx, ry, degRotate, degStart, degEnd float64, styleStr string)
327	BeginLayer(id int)
328	Beziergon(points []PointType, styleStr string)
329	Bookmark(txtStr string, level int, y float64)
330	CellFormat(w, h float64, txtStr, borderStr string, ln int, alignStr string, fill bool, link int, linkStr string)
331	Cellf(w, h float64, fmtStr string, args ...interface{})
332	Cell(w, h float64, txtStr string)
333	Circle(x, y, r float64, styleStr string)
334	ClearError()
335	ClipCircle(x, y, r float64, outline bool)
336	ClipEllipse(x, y, rx, ry float64, outline bool)
337	ClipEnd()
338	ClipPolygon(points []PointType, outline bool)
339	ClipRect(x, y, w, h float64, outline bool)
340	ClipRoundedRect(x, y, w, h, r float64, outline bool)
341	ClipText(x, y float64, txtStr string, outline bool)
342	Close()
343	ClosePath()
344	CreateTemplateCustom(corner PointType, size SizeType, fn func(*Tpl)) Template
345	CreateTemplate(fn func(*Tpl)) Template
346	CurveBezierCubicTo(cx0, cy0, cx1, cy1, x, y float64)
347	CurveBezierCubic(x0, y0, cx0, cy0, cx1, cy1, x1, y1 float64, styleStr string)
348	CurveCubic(x0, y0, cx0, cy0, x1, y1, cx1, cy1 float64, styleStr string)
349	CurveTo(cx, cy, x, y float64)
350	Curve(x0, y0, cx, cy, x1, y1 float64, styleStr string)
351	DrawPath(styleStr string)
352	Ellipse(x, y, rx, ry, degRotate float64, styleStr string)
353	EndLayer()
354	Err() bool
355	Error() error
356	GetAlpha() (alpha float64, blendModeStr string)
357	GetAutoPageBreak() (auto bool, margin float64)
358	GetCellMargin() float64
359	GetConversionRatio() float64
360	GetDrawColor() (int, int, int)
361	GetDrawSpotColor() (name string, c, m, y, k byte)
362	GetFillColor() (int, int, int)
363	GetFillSpotColor() (name string, c, m, y, k byte)
364	GetFontDesc(familyStr, styleStr string) FontDescType
365	GetFontSize() (ptSize, unitSize float64)
366	GetImageInfo(imageStr string) (info *ImageInfoType)
367	GetLineWidth() float64
368	GetMargins() (left, top, right, bottom float64)
369	GetPageSizeStr(sizeStr string) (size SizeType)
370	GetPageSize() (width, height float64)
371	GetStringWidth(s string) float64
372	GetTextColor() (int, int, int)
373	GetTextSpotColor() (name string, c, m, y, k byte)
374	GetX() float64
375	GetXY() (float64, float64)
376	GetY() float64
377	HTMLBasicNew() (html HTMLBasicType)
378	Image(imageNameStr string, x, y, w, h float64, flow bool, tp string, link int, linkStr string)
379	ImageOptions(imageNameStr string, x, y, w, h float64, flow bool, options ImageOptions, link int, linkStr string)
380	ImageTypeFromMime(mimeStr string) (tp string)
381	LinearGradient(x, y, w, h float64, r1, g1, b1, r2, g2, b2 int, x1, y1, x2, y2 float64)
382	LineTo(x, y float64)
383	Line(x1, y1, x2, y2 float64)
384	LinkString(x, y, w, h float64, linkStr string)
385	Link(x, y, w, h float64, link int)
386	Ln(h float64)
387	MoveTo(x, y float64)
388	MultiCell(w, h float64, txtStr, borderStr, alignStr string, fill bool)
389	Ok() bool
390	OpenLayerPane()
391	OutputAndClose(w io.WriteCloser) error
392	OutputFileAndClose(fileStr string) error
393	Output(w io.Writer) error
394	PageCount() int
395	PageNo() int
396	PageSize(pageNum int) (wd, ht float64, unitStr string)
397	PointConvert(pt float64) (u float64)
398	PointToUnitConvert(pt float64) (u float64)
399	Polygon(points []PointType, styleStr string)
400	RadialGradient(x, y, w, h float64, r1, g1, b1, r2, g2, b2 int, x1, y1, x2, y2, r float64)
401	RawWriteBuf(r io.Reader)
402	RawWriteStr(str string)
403	Rect(x, y, w, h float64, styleStr string)
404	RegisterAlias(alias, replacement string)
405	RegisterImage(fileStr, tp string) (info *ImageInfoType)
406	RegisterImageOptions(fileStr string, options ImageOptions) (info *ImageInfoType)
407	RegisterImageOptionsReader(imgName string, options ImageOptions, r io.Reader) (info *ImageInfoType)
408	RegisterImageReader(imgName, tp string, r io.Reader) (info *ImageInfoType)
409	SetAcceptPageBreakFunc(fnc func() bool)
410	SetAlpha(alpha float64, blendModeStr string)
411	SetAuthor(authorStr string, isUTF8 bool)
412	SetAutoPageBreak(auto bool, margin float64)
413	SetCatalogSort(flag bool)
414	SetCellMargin(margin float64)
415	SetCompression(compress bool)
416	SetCreationDate(tm time.Time)
417	SetCreator(creatorStr string, isUTF8 bool)
418	SetDashPattern(dashArray []float64, dashPhase float64)
419	SetDisplayMode(zoomStr, layoutStr string)
420	SetDrawColor(r, g, b int)
421	SetDrawSpotColor(nameStr string, tint byte)
422	SetError(err error)
423	SetErrorf(fmtStr string, args ...interface{})
424	SetFillColor(r, g, b int)
425	SetFillSpotColor(nameStr string, tint byte)
426	SetFont(familyStr, styleStr string, size float64)
427	SetFontLoader(loader FontLoader)
428	SetFontLocation(fontDirStr string)
429	SetFontSize(size float64)
430	SetFontStyle(styleStr string)
431	SetFontUnitSize(size float64)
432	SetFooterFunc(fnc func())
433	SetFooterFuncLpi(fnc func(lastPage bool))
434	SetHeaderFunc(fnc func())
435	SetHeaderFuncMode(fnc func(), homeMode bool)
436	SetHomeXY()
437	SetJavascript(script string)
438	SetKeywords(keywordsStr string, isUTF8 bool)
439	SetLeftMargin(margin float64)
440	SetLineCapStyle(styleStr string)
441	SetLineJoinStyle(styleStr string)
442	SetLineWidth(width float64)
443	SetLink(link int, y float64, page int)
444	SetMargins(left, top, right float64)
445	SetPageBoxRec(t string, pb PageBox)
446	SetPageBox(t string, x, y, wd, ht float64)
447	SetPage(pageNum int)
448	SetProtection(actionFlag byte, userPassStr, ownerPassStr string)
449	SetRightMargin(margin float64)
450	SetSubject(subjectStr string, isUTF8 bool)
451	SetTextColor(r, g, b int)
452	SetTextSpotColor(nameStr string, tint byte)
453	SetTitle(titleStr string, isUTF8 bool)
454	SetTopMargin(margin float64)
455	SetUnderlineThickness(thickness float64)
456	SetXmpMetadata(xmpStream []byte)
457	SetX(x float64)
458	SetXY(x, y float64)
459	SetY(y float64)
460	SplitLines(txt []byte, w float64) [][]byte
461	String() string
462	SVGBasicWrite(sb *SVGBasicType, scale float64)
463	Text(x, y float64, txtStr string)
464	TransformBegin()
465	TransformEnd()
466	TransformMirrorHorizontal(x float64)
467	TransformMirrorLine(angle, x, y float64)
468	TransformMirrorPoint(x, y float64)
469	TransformMirrorVertical(y float64)
470	TransformRotate(angle, x, y float64)
471	TransformScale(scaleWd, scaleHt, x, y float64)
472	TransformScaleX(scaleWd, x, y float64)
473	TransformScaleXY(s, x, y float64)
474	TransformScaleY(scaleHt, x, y float64)
475	TransformSkew(angleX, angleY, x, y float64)
476	TransformSkewX(angleX, x, y float64)
477	TransformSkewY(angleY, x, y float64)
478	Transform(tm TransformMatrix)
479	TransformTranslate(tx, ty float64)
480	TransformTranslateX(tx float64)
481	TransformTranslateY(ty float64)
482	UnicodeTranslatorFromDescriptor(cpStr string) (rep func(string) string)
483	UnitToPointConvert(u float64) (pt float64)
484	UseTemplateScaled(t Template, corner PointType, size SizeType)
485	UseTemplate(t Template)
486	WriteAligned(width, lineHeight float64, textStr, alignStr string)
487	Writef(h float64, fmtStr string, args ...interface{})
488	Write(h float64, txtStr string)
489	WriteLinkID(h float64, displayStr string, linkID int)
490	WriteLinkString(h float64, displayStr, targetStr string)
491}
492
493// PageBox defines the coordinates and extent of the various page box types
494type PageBox struct {
495	SizeType
496	PointType
497}
498
499// Fpdf is the principal structure for creating a single PDF document
500type Fpdf struct {
501	isCurrentUTF8    bool                       // is current font used in utf-8 mode
502	isRTL            bool                       // is is right to left mode enabled
503	page             int                        // current page number
504	n                int                        // current object number
505	offsets          []int                      // array of object offsets
506	templates        map[string]Template        // templates used in this document
507	templateObjects  map[string]int             // template object IDs within this document
508	importedObjs     map[string][]byte          // imported template objects (gofpdi)
509	importedObjPos   map[string]map[int]string  // imported template objects hashes and their positions (gofpdi)
510	importedTplObjs  map[string]string          // imported template names and IDs (hashed) (gofpdi)
511	importedTplIDs   map[string]int             // imported template ids hash to object id int (gofpdi)
512	buffer           fmtBuffer                  // buffer holding in-memory PDF
513	pages            []*bytes.Buffer            // slice[page] of page content; 1-based
514	state            int                        // current document state
515	compress         bool                       // compression flag
516	k                float64                    // scale factor (number of points in user unit)
517	defOrientation   string                     // default orientation
518	curOrientation   string                     // current orientation
519	stdPageSizes     map[string]SizeType        // standard page sizes
520	defPageSize      SizeType                   // default page size
521	defPageBoxes     map[string]PageBox         // default page size
522	curPageSize      SizeType                   // current page size
523	pageSizes        map[int]SizeType           // used for pages with non default sizes or orientations
524	pageBoxes        map[int]map[string]PageBox // used to define the crop, trim, bleed and art boxes
525	unitStr          string                     // unit of measure for all rendered objects except fonts
526	wPt, hPt         float64                    // dimensions of current page in points
527	w, h             float64                    // dimensions of current page in user unit
528	lMargin          float64                    // left margin
529	tMargin          float64                    // top margin
530	rMargin          float64                    // right margin
531	bMargin          float64                    // page break margin
532	cMargin          float64                    // cell margin
533	x, y             float64                    // current position in user unit
534	lasth            float64                    // height of last printed cell
535	lineWidth        float64                    // line width in user unit
536	fontpath         string                     // path containing fonts
537	fontLoader       FontLoader                 // used to load font files from arbitrary locations
538	coreFonts        map[string]bool            // array of core font names
539	fonts            map[string]fontDefType     // array of used fonts
540	fontFiles        map[string]fontFileType    // array of font files
541	diffs            []string                   // array of encoding differences
542	fontFamily       string                     // current font family
543	fontStyle        string                     // current font style
544	underline        bool                       // underlining flag
545	strikeout        bool                       // strike out flag
546	currentFont      fontDefType                // current font info
547	fontSizePt       float64                    // current font size in points
548	fontSize         float64                    // current font size in user unit
549	ws               float64                    // word spacing
550	images           map[string]*ImageInfoType  // array of used images
551	aliasMap         map[string]string          // map of alias->replacement
552	pageLinks        [][]linkType               // pageLinks[page][link], both 1-based
553	links            []intLinkType              // array of internal links
554	attachments      []Attachment               // slice of content to embed globally
555	pageAttachments  [][]annotationAttach       // 1-based array of annotation for file attachments (per page)
556	outlines         []outlineType              // array of outlines
557	outlineRoot      int                        // root of outlines
558	autoPageBreak    bool                       // automatic page breaking
559	acceptPageBreak  func() bool                // returns true to accept page break
560	pageBreakTrigger float64                    // threshold used to trigger page breaks
561	inHeader         bool                       // flag set when processing header
562	headerFnc        func()                     // function provided by app and called to write header
563	headerHomeMode   bool                       // set position to home after headerFnc is called
564	inFooter         bool                       // flag set when processing footer
565	footerFnc        func()                     // function provided by app and called to write footer
566	footerFncLpi     func(bool)                 // function provided by app and called to write footer with last page flag
567	zoomMode         string                     // zoom display mode
568	layoutMode       string                     // layout display mode
569	xmp              []byte                     // XMP metadata
570	producer         string                     // producer
571	title            string                     // title
572	subject          string                     // subject
573	author           string                     // author
574	keywords         string                     // keywords
575	creator          string                     // creator
576	creationDate     time.Time                  // override for document CreationDate value
577	modDate          time.Time                  // override for document ModDate value
578	aliasNbPagesStr  string                     // alias for total number of pages
579	pdfVersion       string                     // PDF version number
580	fontDirStr       string                     // location of font definition files
581	capStyle         int                        // line cap style: butt 0, round 1, square 2
582	joinStyle        int                        // line segment join style: miter 0, round 1, bevel 2
583	dashArray        []float64                  // dash array
584	dashPhase        float64                    // dash phase
585	blendList        []blendModeType            // slice[idx] of alpha transparency modes, 1-based
586	blendMap         map[string]int             // map into blendList
587	blendMode        string                     // current blend mode
588	alpha            float64                    // current transpacency
589	gradientList     []gradientType             // slice[idx] of gradient records
590	clipNest         int                        // Number of active clipping contexts
591	transformNest    int                        // Number of active transformation contexts
592	err              error                      // Set if error occurs during life cycle of instance
593	protect          protectType                // document protection structure
594	layer            layerRecType               // manages optional layers in document
595	catalogSort      bool                       // sort resource catalogs in document
596	nJs              int                        // JavaScript object number
597	javascript       *string                    // JavaScript code to include in the PDF
598	colorFlag        bool                       // indicates whether fill and text colors are different
599	color            struct {
600		// Composite values of colors
601		draw, fill, text colorType
602	}
603	spotColorMap           map[string]spotColorType // Map of named ink-based colors
604	userUnderlineThickness float64                  // A custom user underline thickness multiplier.
605}
606
607type encType struct {
608	uv   int
609	name string
610}
611
612type encListType [256]encType
613
614type fontBoxType struct {
615	Xmin, Ymin, Xmax, Ymax int
616}
617
618// Font flags for FontDescType.Flags as defined in the pdf specification.
619const (
620	// FontFlagFixedPitch is set if all glyphs have the same width (as
621	// opposed to proportional or variable-pitch fonts, which have
622	// different widths).
623	FontFlagFixedPitch = 1 << 0
624	// FontFlagSerif is set if glyphs have serifs, which are short
625	// strokes drawn at an angle on the top and bottom of glyph stems.
626	// (Sans serif fonts do not have serifs.)
627	FontFlagSerif = 1 << 1
628	// FontFlagSymbolic is set if font contains glyphs outside the
629	// Adobe standard Latin character set. This flag and the
630	// Nonsymbolic flag shall not both be set or both be clear.
631	FontFlagSymbolic = 1 << 2
632	// FontFlagScript is set if glyphs resemble cursive handwriting.
633	FontFlagScript = 1 << 3
634	// FontFlagNonsymbolic is set if font uses the Adobe standard
635	// Latin character set or a subset of it.
636	FontFlagNonsymbolic = 1 << 5
637	// FontFlagItalic is set if glyphs have dominant vertical strokes
638	// that are slanted.
639	FontFlagItalic = 1 << 6
640	// FontFlagAllCap is set if font contains no lowercase letters;
641	// typically used for display purposes, such as for titles or
642	// headlines.
643	FontFlagAllCap = 1 << 16
644	// SmallCap is set if font contains both uppercase and lowercase
645	// letters. The uppercase letters are similar to those in the
646	// regular version of the same typeface family. The glyphs for the
647	// lowercase letters have the same shapes as the corresponding
648	// uppercase letters, but they are sized and their proportions
649	// adjusted so that they have the same size and stroke weight as
650	// lowercase glyphs in the same typeface family.
651	SmallCap = 1 << 18
652	// ForceBold determines whether bold glyphs shall be painted with
653	// extra pixels even at very small text sizes by a conforming
654	// reader. If the ForceBold flag is set, features of bold glyphs
655	// may be thickened at small text sizes.
656	ForceBold = 1 << 18
657)
658
659// FontDescType (font descriptor) specifies metrics and other
660// attributes of a font, as distinct from the metrics of individual
661// glyphs (as defined in the pdf specification).
662type FontDescType struct {
663	// The maximum height above the baseline reached by glyphs in this
664	// font (for example for "S"). The height of glyphs for accented
665	// characters shall be excluded.
666	Ascent int
667	// The maximum depth below the baseline reached by glyphs in this
668	// font. The value shall be a negative number.
669	Descent int
670	// The vertical coordinate of the top of flat capital letters,
671	// measured from the baseline (for example "H").
672	CapHeight int
673	// A collection of flags defining various characteristics of the
674	// font. (See the FontFlag* constants.)
675	Flags int
676	// A rectangle, expressed in the glyph coordinate system, that
677	// shall specify the font bounding box. This should be the smallest
678	// rectangle enclosing the shape that would result if all of the
679	// glyphs of the font were placed with their origins coincident
680	// and then filled.
681	FontBBox fontBoxType
682	// The angle, expressed in degrees counterclockwise from the
683	// vertical, of the dominant vertical strokes of the font. (The
684	// 9-o’clock position is 90 degrees, and the 3-o’clock position
685	// is –90 degrees.) The value shall be negative for fonts that
686	// slope to the right, as almost all italic fonts do.
687	ItalicAngle int
688	// The thickness, measured horizontally, of the dominant vertical
689	// stems of glyphs in the font.
690	StemV int
691	// The width to use for character codes whose widths are not
692	// specified in a font dictionary’s Widths array. This shall have
693	// a predictable effect only if all such codes map to glyphs whose
694	// actual widths are the same as the value of the MissingWidth
695	// entry. (Default value: 0.)
696	MissingWidth int
697}
698
699type fontDefType struct {
700	Tp           string        // "Core", "TrueType", ...
701	Name         string        // "Courier-Bold", ...
702	Desc         FontDescType  // Font descriptor
703	Up           int           // Underline position
704	Ut           int           // Underline thickness
705	Cw           []int         // Character width by ordinal
706	Enc          string        // "cp1252", ...
707	Diff         string        // Differences from reference encoding
708	File         string        // "Redressed.z"
709	Size1, Size2 int           // Type1 values
710	OriginalSize int           // Size of uncompressed font file
711	N            int           // Set by font loader
712	DiffN        int           // Position of diff in app array, set by font loader
713	i            string        // 1-based position in font list, set by font loader, not this program
714	utf8File     *utf8FontFile // UTF-8 font
715	usedRunes    map[int]int   // Array of used runes
716}
717
718// generateFontID generates a font Id from the font definition
719func generateFontID(fdt fontDefType) (string, error) {
720	// file can be different if generated in different instance
721	fdt.File = ""
722	b, err := json.Marshal(&fdt)
723	return fmt.Sprintf("%x", sha1.Sum(b)), err
724}
725
726type fontInfoType struct {
727	Data               []byte
728	File               string
729	OriginalSize       int
730	FontName           string
731	Bold               bool
732	IsFixedPitch       bool
733	UnderlineThickness int
734	UnderlinePosition  int
735	Widths             []int
736	Size1, Size2       uint32
737	Desc               FontDescType
738}
739