diff options
| author | Felix Hanley <felix@userspace.com.au> | 2016-11-21 15:56:46 +0000 |
|---|---|---|
| committer | Felix Hanley <felix@userspace.com.au> | 2016-11-21 15:56:46 +0000 |
| commit | 411565dc3c87851017376545383d4afa65d9f833 (patch) | |
| tree | 44733ff8242c193a95115b27f9e4e88ad3eadde1 /vendor/github.com/jung-kurt/gofpdf | |
| parent | 98da73fe927ee67b62c1f286b0adb649a20c373c (diff) | |
| download | crjw-maps-411565dc3c87851017376545383d4afa65d9f833.tar.gz crjw-maps-411565dc3c87851017376545383d4afa65d9f833.tar.bz2 | |
Add vendor code
Diffstat (limited to 'vendor/github.com/jung-kurt/gofpdf')
29 files changed, 10301 insertions, 0 deletions
diff --git a/vendor/github.com/jung-kurt/gofpdf/compare.go b/vendor/github.com/jung-kurt/gofpdf/compare.go new file mode 100644 index 0000000..416e545 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/compare.go @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2015 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gofpdf + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "sort" +) + +type sortType struct { + length int + less func(int, int) bool + swap func(int, int) +} + +func (s *sortType) Len() int { + return s.length +} + +func (s *sortType) Less(i, j int) bool { + return s.less(i, j) +} + +func (s *sortType) Swap(i, j int) { + s.swap(i, j) +} + +func gensort(Len int, Less func(int, int) bool, Swap func(int, int)) { + sort.Sort(&sortType{length: Len, less: Less, swap: Swap}) +} + +func writeBytes(leadStr string, startPos int, sl []byte) { + var pos, max int + var b byte + fmt.Printf("%s %07x", leadStr, startPos) + max = len(sl) + for pos < max { + fmt.Printf(" ") + for k := 0; k < 8; k++ { + if pos < max { + fmt.Printf(" %02x", sl[pos]) + } else { + fmt.Printf(" ") + } + pos++ + } + } + fmt.Printf(" |") + pos = 0 + for pos < max { + b = sl[pos] + if b < 32 || b >= 128 { + b = '.' + } + fmt.Printf("%c", b) + pos++ + } + fmt.Printf("|\n") +} + +func checkBytes(pos int, sl1, sl2 []byte) (eq bool) { + eq = bytes.Equal(sl1, sl2) + if !eq { + writeBytes("<", pos, sl1) + writeBytes(">", pos, sl2) + } + return +} + +// CompareBytes compares the bytes referred to by sl1 with those referred to by +// sl2. Nil is returned if the buffers are equal, otherwise an error. +func CompareBytes(sl1, sl2 []byte) (err error) { + var posStart, posEnd, len1, len2, length int + var diffs bool + + len1 = len(sl1) + len2 = len(sl2) + length = len1 + if length > len2 { + length = len2 + } + for posStart < length-1 { + posEnd = posStart + 16 + if posEnd > length { + posEnd = length + } + if !checkBytes(posStart, sl1[posStart:posEnd], sl2[posStart:posEnd]) { + diffs = true + } + posStart = posEnd + } + if diffs { + err = fmt.Errorf("documents are different") + } + return +} + +// ComparePDFs reads and compares the full contents of the two specified +// readers byte-for-byte. Nil is returned if the buffers are equal, otherwise +// an error. +func ComparePDFs(rdr1, rdr2 io.Reader) (err error) { + var b1, b2 *bytes.Buffer + _, err = b1.ReadFrom(rdr1) + if err == nil { + _, err = b2.ReadFrom(rdr2) + if err == nil { + err = CompareBytes(b1.Bytes(), b2.Bytes()) + } + } + return +} + +// ComparePDFFiles reads and compares the full contents of the two specified +// files byte-for-byte. Nil is returned if the file contents are equal, or if +// the second file is missing, otherwise an error. +func ComparePDFFiles(file1Str, file2Str string) (err error) { + var sl1, sl2 []byte + sl1, err = ioutil.ReadFile(file1Str) + if err == nil { + sl2, err = ioutil.ReadFile(file2Str) + if err == nil { + err = CompareBytes(sl1, sl2) + } else { + // Second file is missing; treat this as success + err = nil + } + } + return +} diff --git a/vendor/github.com/jung-kurt/gofpdf/contrib/barcode/barcode.go b/vendor/github.com/jung-kurt/gofpdf/contrib/barcode/barcode.go new file mode 100644 index 0000000..0649564 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/contrib/barcode/barcode.go @@ -0,0 +1,238 @@ +// Copyright (c) 2015 Jelmer Snoeck (Gmail: jelmer.snoeck) +// +// Permission to use, copy, modify, and distribute this software for any purpose +// with or without fee is hereby granted, provided that the above copyright notice +// and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +// Package barcode provides helper methods for adding barcodes of different +// types to your pdf document. It relies on the github.com/boombuler/barcode +// package for the barcode creation. +package barcode + +import ( + "bytes" + "errors" + "github.com/boombuler/barcode" + "github.com/boombuler/barcode/codabar" + "github.com/boombuler/barcode/code128" + "github.com/boombuler/barcode/code39" + "github.com/boombuler/barcode/datamatrix" + "github.com/boombuler/barcode/ean" + "github.com/boombuler/barcode/qr" + "github.com/boombuler/barcode/twooffive" + "github.com/jung-kurt/gofpdf" + "github.com/ruudk/golang-pdf417" + "image/jpeg" + "io" + "strconv" + "sync" +) + +// barcodes represents the barcodes that have been registered through this +// package. They will later be used to be scaled and put on the page. +// RubenN: made this a struct with a mutex to prevent race condition +var barcodes struct { + sync.Mutex + cache map[string]barcode.Barcode +} + +// barcodePdf is a partial PDF implementation that only implements a subset of +// functions that are required to add the barcode to the PDF. +type barcodePdf interface { + GetConversionRatio() float64 + GetImageInfo(imageStr string) *gofpdf.ImageInfoType + Image(imageNameStr string, x, y, w, h float64, flow bool, tp string, link int, linkStr string) + RegisterImageReader(imgName, tp string, r io.Reader) *gofpdf.ImageInfoType + SetError(err error) +} + +// Barcode puts a registered barcode in the current page. +// +// The size should be specified in the units used to create the PDF document. +// +// Positioning with x, y and flow is inherited from Fpdf.Image(). +func Barcode(pdf barcodePdf, code string, x, y, w, h float64, flow bool) { + barcodes.Lock() + unscaled, ok := barcodes.cache[code] + barcodes.Unlock() + + if !ok { + err := errors.New("Barcode not found") + pdf.SetError(err) + return + } + + bname := uniqueBarcodeName(code, x, y) + info := pdf.GetImageInfo(bname) + + if info == nil { + bcode, err := barcode.Scale( + unscaled, + int(convertTo96Dpi(pdf, w)), + int(convertTo96Dpi(pdf, h)), + ) + + if err != nil { + pdf.SetError(err) + return + } + + err = registerScaledBarcode(pdf, bname, bcode) + if err != nil { + pdf.SetError(err) + return + } + } + + pdf.Image(bname, x, y, 0, 0, flow, "jpg", 0, "") +} + +// Register registers a barcode but does not put it on the page. Use Barcode() +// with the same code to put the barcode on the PDF page. +func Register(bcode barcode.Barcode) string { + barcodes.Lock() + if len(barcodes.cache) == 0 { + barcodes.cache = make(map[string]barcode.Barcode) + } + + key := barcodeKey(bcode) + barcodes.cache[key] = bcode + barcodes.Unlock() + + return key +} + +// RegisterCodabar registers a barcode of type Codabar to the PDF, but not to +// the page. Use Barcode() with the return value to put the barcode on the page. +func RegisterCodabar(pdf barcodePdf, code string) string { + bcode, err := codabar.Encode(code) + return registerBarcode(pdf, bcode, err) +} + +// RegisterCode128 registers a barcode of type Code128 to the PDF, but not to +// the page. Use Barcode() with the return value to put the barcode on the page. +func RegisterCode128(pdf barcodePdf, code string) string { + bcode, err := code128.Encode(code) + return registerBarcode(pdf, bcode, err) +} + +// RegisterCode39 registers a barcode of type Code39 to the PDF, but not to +// the page. Use Barcode() with the return value to put the barcode on the page. +// +// includeChecksum and fullASCIIMode are inherited from code39.Encode(). +func RegisterCode39(pdf barcodePdf, code string, includeChecksum, fullASCIIMode bool) string { + bcode, err := code39.Encode(code, includeChecksum, fullASCIIMode) + return registerBarcode(pdf, bcode, err) +} + +// RegisterDataMatrix registers a barcode of type DataMatrix to the PDF, but not +// to the page. Use Barcode() with the return value to put the barcode on the +// page. +func RegisterDataMatrix(pdf barcodePdf, code string) string { + bcode, err := datamatrix.Encode(code) + return registerBarcode(pdf, bcode, err) +} + +// RegisterPdf417 registers a barcode of type Pdf417 to the PDF, but not to the +// page. code is the string to be encoded. columns specifies the number of +// barcode columns; this should be a value between 1 and 30 inclusive. +// securityLevel specifies an error correction level between zero and 8 +// inclusive. Barcodes for use with FedEx must set columns to 10 and +// securityLevel to 5. Use Barcode() with the return value to put the barcode +// on the page. +func RegisterPdf417(pdf barcodePdf, code string, columns int, securityLevel int) string { + bcode := pdf417.Encode(code, columns, securityLevel) + return registerBarcode(pdf, bcode, nil) +} + +// RegisterEAN registers a barcode of type EAN to the PDF, but not to the page. +// It will automatically detect if the barcode is EAN8 or EAN13. Use Barcode() +// with the return value to put the barcode on the page. +func RegisterEAN(pdf barcodePdf, code string) string { + bcode, err := ean.Encode(code) + return registerBarcode(pdf, bcode, err) +} + +// RegisterQR registers a barcode of type QR to the PDF, but not to the page. +// Use Barcode() with the return value to put the barcode on the page. +// +// The ErrorCorrectionLevel and Encoding mode are inherited from qr.Encode(). +func RegisterQR(pdf barcodePdf, code string, ecl qr.ErrorCorrectionLevel, mode qr.Encoding) string { + bcode, err := qr.Encode(code, ecl, mode) + return registerBarcode(pdf, bcode, err) +} + +// RegisterTwoOfFive registers a barcode of type TwoOfFive to the PDF, but not +// to the page. Use Barcode() with the return value to put the barcode on the +// page. +// +// The interleaved bool is inherited from twooffive.Encode(). +func RegisterTwoOfFive(pdf barcodePdf, code string, interleaved bool) string { + bcode, err := twooffive.Encode(code, interleaved) + return registerBarcode(pdf, bcode, err) +} + +// registerBarcode registers a barcode internally using the Register() function. +// In case of an error generating the barcode it will not be registered and will +// set an error on the PDF. It will return a unique key for the barcode type and +// content that can be used to put the barcode on the page. +func registerBarcode(pdf barcodePdf, bcode barcode.Barcode, err error) string { + if err != nil { + pdf.SetError(err) + } + + return Register(bcode) +} + +// uniqueBarcodeName makes sure every barcode has a unique name for its +// dimensions. Scaling a barcode image results in quality loss, which could be +// a problem for barcode readers. +func uniqueBarcodeName(code string, x, y float64) string { + xStr := strconv.FormatFloat(x, 'E', -1, 64) + yStr := strconv.FormatFloat(y, 'E', -1, 64) + + return "barcode-" + code + "-" + xStr + yStr +} + +// barcodeKey combines the code type and code value into a unique identifier for +// a barcode type. This is so that we can store several barcodes with the same +// code but different type in the barcodes map. +func barcodeKey(bcode barcode.Barcode) string { + return bcode.Metadata().CodeKind + bcode.Content() +} + +// registerScaledBarcode registers a barcode with its exact dimensions to the +// PDF but does not put it on the page. Use Fpdf.Image() with the same code to +// add the barcode to the page. +func registerScaledBarcode(pdf barcodePdf, code string, bcode barcode.Barcode) error { + buf := new(bytes.Buffer) + err := jpeg.Encode(buf, bcode, nil) + + if err != nil { + return err + } + + reader := bytes.NewReader(buf.Bytes()) + pdf.RegisterImageReader(code, "jpg", reader) + + return nil +} + +// convertTo96DPI converts the given value, which is based on a 72 DPI value +// like the rest of the PDF document, to a 96 DPI value that is required for +// an Image. +// +// Doing this through the Fpdf.Image() function would mean that it uses a 72 DPI +// value and stretches it to a 96 DPI value. This results in quality loss which +// could be problematic for barcode scanners. +func convertTo96Dpi(pdf barcodePdf, value float64) float64 { + return value * pdf.GetConversionRatio() / 72 * 96 +} diff --git a/vendor/github.com/jung-kurt/gofpdf/contrib/ghostscript/ghostscript.go b/vendor/github.com/jung-kurt/gofpdf/contrib/ghostscript/ghostscript.go new file mode 100644 index 0000000..3196c34 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/contrib/ghostscript/ghostscript.go @@ -0,0 +1,68 @@ +package main + +// This command demonstrates the use of ghotscript to reduce the size +// of generated PDFs. This is based on a comment made by farkerhaiku: +// https://github.com/jung-kurt/gofpdf/issues/57#issuecomment-185843315 + +import ( + "fmt" + "os" + "os/exec" + + "github.com/jung-kurt/gofpdf" +) + +func report(fileStr string, err error) { + if err == nil { + var info os.FileInfo + info, err = os.Stat(fileStr) + if err == nil { + fmt.Printf("%s: OK, size %d\n", fileStr, info.Size()) + } else { + fmt.Printf("%s: bad stat\n", fileStr) + } + } else { + fmt.Printf("%s: %s\n", fileStr, err) + } +} + +func newPdf() (pdf *gofpdf.Fpdf) { + pdf = gofpdf.New("P", "mm", "A4", "../../font") + pdf.SetCompression(false) + pdf.AddFont("Calligrapher", "", "calligra.json") + pdf.AddPage() + pdf.SetFont("Calligrapher", "", 35) + pdf.Cell(0, 10, "Enjoy new fonts with FPDF!") + return +} + +func full(name string) { + report(name, newPdf().OutputFileAndClose(name)) +} + +func min(name string) { + cmd := exec.Command("gs", "-sDEVICE=pdfwrite", + "-dCompatibilityLevel=1.4", + "-dPDFSETTINGS=/screen", "-dNOPAUSE", "-dQUIET", + "-dBATCH", "-sOutputFile="+name, "-") + inPipe, err := cmd.StdinPipe() + if err == nil { + errChan := make(chan error, 1) + go func() { + errChan <- cmd.Start() + }() + err = newPdf().Output(inPipe) + if err == nil { + report(name, <-errChan) + } else { + report(name, err) + } + } else { + report(name, err) + } +} + +func main() { + full("full.pdf") + min("min.pdf") +} diff --git a/vendor/github.com/jung-kurt/gofpdf/contrib/httpimg/httpimg.go b/vendor/github.com/jung-kurt/gofpdf/contrib/httpimg/httpimg.go new file mode 100644 index 0000000..7cbf281 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/contrib/httpimg/httpimg.go @@ -0,0 +1,43 @@ +package httpimg + +import ( + "io" + "net/http" + + "github.com/jung-kurt/gofpdf" +) + +// httpimgPdf is a partial interface that only implements the functions we need +// from the PDF generator to put the HTTP images on the PDF. +type httpimgPdf interface { + GetImageInfo(imageStr string) *gofpdf.ImageInfoType + ImageTypeFromMime(mimeStr string) string + RegisterImageReader(imgName, tp string, r io.Reader) *gofpdf.ImageInfoType + SetError(err error) +} + +// Register registers a HTTP image. Downloading the image from the provided URL +// and adding it to the PDF but not adding it to the page. Use Image() with the +// same URL to add the image to the page. +func Register(f httpimgPdf, urlStr, tp string) (info *gofpdf.ImageInfoType) { + info = f.GetImageInfo(urlStr) + + if info != nil { + return + } + + resp, err := http.Get(urlStr) + + if err != nil { + f.SetError(err) + return + } + + defer resp.Body.Close() + + if tp == "" { + tp = f.ImageTypeFromMime(resp.Header["Content-Type"][0]) + } + + return f.RegisterImageReader(urlStr, tp, resp.Body) +} diff --git a/vendor/github.com/jung-kurt/gofpdf/contrib/tiff/tiff.go b/vendor/github.com/jung-kurt/gofpdf/contrib/tiff/tiff.go new file mode 100644 index 0000000..3f13a38 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/contrib/tiff/tiff.go @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +// Package tiff allows standard (LZW-compressed) TIFF images to be used in +// documents generated with gofpdf. +package tiff + +import ( + "bytes" + "fmt" + "image" + "image/png" + "io" + "os" + + "github.com/jung-kurt/gofpdf" + "golang.org/x/image/tiff" +) + +// RegisterReader registers a TIFF image, adding it to the PDF file but not +// adding it to the page. imgName specifies the name that will be used in the +// call to Image() that actually places the image in the document. options +// specifies various image properties; in this case, the ImageType property +// should be set to "tiff". The TIFF image is a reader from the reader +// specified by r. +func RegisterReader(fpdf *gofpdf.Fpdf, imgName string, options gofpdf.ImageOptions, r io.Reader) (info *gofpdf.ImageInfoType) { + var err error + var img image.Image + var buf bytes.Buffer + if fpdf.Ok() { + if options.ImageType == "tiff" || options.ImageType == "tif" { + img, err = tiff.Decode(r) + if err == nil { + err = png.Encode(&buf, img) + if err == nil { + options.ImageType = "png" + info = fpdf.RegisterImageOptionsReader(imgName, options, &buf) + } + } + } else { + err = fmt.Errorf("expecting \"tiff\" or \"tif\" as image type, got \"%s\"", options.ImageType) + } + if err != nil { + fpdf.SetError(err) + } + } + return +} + +// RegisterFile registers a TIFF image, adding it to the PDF file but not +// adding it to the page. imgName specifies the name that will be used in the +// call to Image() that actually places the image in the document. options +// specifies various image properties; in this case, the ImageType property +// should be set to "tiff". The TIFF image is read from the file specified by +// tiffFileStr. +func RegisterFile(fpdf *gofpdf.Fpdf, imgName string, options gofpdf.ImageOptions, tiffFileStr string) (info *gofpdf.ImageInfoType) { + var f *os.File + var err error + + if fpdf.Ok() { + f, err = os.Open(tiffFileStr) + if err == nil { + info = RegisterReader(fpdf, imgName, options, f) + f.Close() + } else { + fpdf.SetError(err) + } + } + return +} diff --git a/vendor/github.com/jung-kurt/gofpdf/def.go b/vendor/github.com/jung-kurt/gofpdf/def.go new file mode 100644 index 0000000..54abbd1 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/def.go @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2013-2014 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gofpdf + +import ( + "bytes" + "io" + "time" +) + +// Version of FPDF from which this package is derived +const ( + cnFpdfVersion = "1.7" +) + +type blendModeType struct { + strokeStr, fillStr, modeStr string + objNum int +} + +type gradientType struct { + tp int // 2: linear, 3: radial + clr1Str, clr2Str string + x1, y1, x2, y2, r float64 + objNum int +} + +// SizeType fields Wd and Ht specify the horizontal and vertical extents of a +// document element such as a page. +type SizeType struct { + Wd, Ht float64 +} + +// PointType fields X and Y specify the horizontal and vertical coordinates of +// a point, typically used in drawing. +type PointType struct { + X, Y float64 +} + +// XY returns the X and Y components of the receiver point. +func (p PointType) XY() (float64, float64) { + return p.X, p.Y +} + +// ImageInfoType contains size, color and other information about an image +type ImageInfoType struct { + data []byte + smask []byte + i int + n int + w float64 + h float64 + cs string + pal []byte + bpc int + f string + dp string + trns []int + scale float64 // document scaling factor + dpi float64 +} + +// PointConvert returns the value of pt, expressed in points (1/72 inch), as a +// value expressed in the unit of measure specified in New(). Since font +// management in Fpdf uses points, this method can help with line height +// calculations and other methods that require user units. +func (f *Fpdf) PointConvert(pt float64) (u float64) { + return pt / f.k +} + +// PointToUnitConvert is an alias for PointConvert. +func (f *Fpdf) PointToUnitConvert(pt float64) (u float64) { + return pt / f.k +} + +// UnitToPointConvert returns the value of u, expressed in the unit of measure +// specified in New(), as a value expressed in points (1/72 inch). Since font +// management in Fpdf uses points, this method can help with setting font sizes +// based on the sizes of other non-font page elements. +func (f *Fpdf) UnitToPointConvert(u float64) (pt float64) { + return u * f.k +} + +// Extent returns the width and height of the image in the units of the Fpdf +// object. +func (info *ImageInfoType) Extent() (wd, ht float64) { + return info.Width(), info.Height() +} + +// Width returns the width of the image in the units of the Fpdf object. +func (info *ImageInfoType) Width() float64 { + return info.w / (info.scale * info.dpi / 72) +} + +// Height returns the height of the image in the units of the Fpdf object. +func (info *ImageInfoType) Height() float64 { + return info.h / (info.scale * info.dpi / 72) +} + +// SetDpi sets the dots per inch for an image. PNG images MAY have their dpi +// set automatically, if the image specifies it. DPI information is not +// currently available automatically for JPG and GIF images, so if it's +// important to you, you can set it here. It defaults to 72 dpi. +func (info *ImageInfoType) SetDpi(dpi float64) { + info.dpi = dpi +} + +type fontFileType struct { + length1, length2 int64 + n int + embedded bool + content []byte +} + +type linkType struct { + x, y, wd, ht float64 + link int // Auto-generated internal link ID or... + linkStr string // ...application-provided external link string +} + +type intLinkType struct { + page int + y float64 +} + +// outlineType is used for a sidebar outline of bookmarks +type outlineType struct { + text string + level, parent, first, last, next, prev int + y float64 + p int +} + +// InitType is used with NewCustom() to customize an Fpdf instance. +// OrientationStr, UnitStr, SizeStr and FontDirStr correspond to the arguments +// accepted by New(). If the Wd and Ht fields of Size are each greater than +// zero, Size will be used to set the default page size rather than SizeStr. Wd +// and Ht are specified in the units of measure indicated by UnitStr. +type InitType struct { + OrientationStr string + UnitStr string + SizeStr string + Size SizeType + FontDirStr string +} + +// FontLoader is used to read fonts (JSON font specification and zlib compressed font binaries) +// from arbitrary locations (e.g. files, zip files, embedded font resources). +// +// Open provides an io.Reader for the specified font file (.json or .z). The file name +// never includes a path. Open returns an error if the specified file cannot be opened. +type FontLoader interface { + Open(name string) (io.Reader, error) +} + +// Fpdf is the principal structure for creating a single PDF document +type Fpdf struct { + page int // current page number + n int // current object number + offsets []int // array of object offsets + templates map[int64]Template // templates used in this document + templateObjects map[int64]int // template object IDs within this document + buffer fmtBuffer // buffer holding in-memory PDF + pages []*bytes.Buffer // slice[page] of page content; 1-based + state int // current document state + compress bool // compression flag + k float64 // scale factor (number of points in user unit) + defOrientation string // default orientation + curOrientation string // current orientation + stdPageSizes map[string]SizeType // standard page sizes + defPageSize SizeType // default page size + curPageSize SizeType // current page size + pageSizes map[int]SizeType // used for pages with non default sizes or orientations + unitStr string // unit of measure for all rendered objects except fonts + wPt, hPt float64 // dimensions of current page in points + w, h float64 // dimensions of current page in user unit + lMargin float64 // left margin + tMargin float64 // top margin + rMargin float64 // right margin + bMargin float64 // page break margin + cMargin float64 // cell margin + x, y float64 // current position in user unit + lasth float64 // height of last printed cell + lineWidth float64 // line width in user unit + fontpath string // path containing fonts + fontLoader FontLoader // used to load font files from arbitrary locations + coreFonts map[string]bool // array of core font names + fonts map[string]fontDefType // array of used fonts + fontFiles map[string]fontFileType // array of font files + diffs []string // array of encoding differences + fontFamily string // current font family + fontStyle string // current font style + underline bool // underlining flag + currentFont fontDefType // current font info + fontSizePt float64 // current font size in points + fontSize float64 // current font size in user unit + ws float64 // word spacing + images map[string]*ImageInfoType // array of used images + pageLinks [][]linkType // pageLinks[page][link], both 1-based + links []intLinkType // array of internal links + outlines []outlineType // array of outlines + outlineRoot int // root of outlines + autoPageBreak bool // automatic page breaking + acceptPageBreak func() bool // returns true to accept page break + pageBreakTrigger float64 // threshold used to trigger page breaks + inHeader bool // flag set when processing header + headerFnc func() // function provided by app and called to write header + inFooter bool // flag set when processing footer + footerFnc func() // function provided by app and called to write footer + zoomMode string // zoom display mode + layoutMode string // layout display mode + title string // title + subject string // subject + author string // author + keywords string // keywords + creator string // creator + creationDate time.Time // override for dcoument CreationDate value + aliasNbPagesStr string // alias for total number of pages + pdfVersion string // PDF version number + fontDirStr string // location of font definition files + capStyle int // line cap style: butt 0, round 1, square 2 + joinStyle int // line segment join style: miter 0, round 1, bevel 2 + dashArray []float64 // dash array + dashPhase float64 // dash phase + blendList []blendModeType // slice[idx] of alpha transparency modes, 1-based + blendMap map[string]int // map into blendList + blendMode string // current blend mode + alpha float64 // current transpacency + gradientList []gradientType // slice[idx] of gradient records + clipNest int // Number of active clipping contexts + transformNest int // Number of active transformation contexts + err error // Set if error occurs during life cycle of instance + protect protectType // document protection structure + layer layerRecType // manages optional layers in document + catalogSort bool // sort resource catalogs in document + colorFlag bool // indicates whether fill and text colors are different + color struct { + // Composite values of colors + draw, fill, text clrType + } +} + +type encType struct { + uv int + name string +} + +type encListType [256]encType + +type fontBoxType struct { + Xmin, Ymin, Xmax, Ymax 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 + Up int // Underline position + Ut int // Underline thickness + Cw [256]int // Character width by ordinal + Enc string // "cp1252", ... + Diff string // Differences from reference encoding + File string // "Redressed.z" + Size1, Size2 int // Type1 values + OriginalSize int // Size of uncompressed font file + I int // 1-based position in font list, set by font loader, not this program + N int // Set by font loader + DiffN int // Position of diff in app array, set by font loader +} + +type fontInfoType struct { + Data []byte + File string + OriginalSize int + FontName string + Bold bool + IsFixedPitch bool + UnderlineThickness int + UnderlinePosition int + Widths [256]int + Size1, Size2 uint32 + Desc FontDescType +} diff --git a/vendor/github.com/jung-kurt/gofpdf/doc.go b/vendor/github.com/jung-kurt/gofpdf/doc.go new file mode 100644 index 0000000..a0af537 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/doc.go @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2013-2014 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* +Package gofpdf implements a PDF document generator with high level support for +text, drawing and images. + +Features + +• Choice of measurement unit, page format and margins + +• Page header and footer management + +• Automatic page breaks, line breaks, and text justification + +• Inclusion of JPEG, PNG, GIF, TIFF and basic path-only SVG images + +• Colors, gradients and alpha channel transparency + +• Outline bookmarks + +• Internal and external links + +• TrueType, Type1 and encoding support + +• Page compression + +• Lines, Bézier curves, arcs, and ellipses + +• Rotation, scaling, skewing, translation, and mirroring + +• Clipping + +• Document protection + +• Layers + +• Templates + +gofpdf has no dependencies other than the Go standard library. All tests pass +on Linux, Mac and Windows platforms. Like FPDF version 1.7, from which gofpdf +is derived, this package does not yet support UTF-8 fonts. However, support is +provided to translate UTF-8 runes to code page encodings. + +Installation + +To install the package on your system, run + + go get github.com/jung-kurt/gofpdf + +Later, to receive updates, run + + go get -u -v github.com/jung-kurt/gofpdf/... + +Quick Start + +The following Go code generates a simple PDF file. + + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + pdf.SetFont("Arial", "B", 16) + pdf.Cell(40, 10, "Hello, world") + err := pdf.OutputFileAndClose("hello.pdf") + +See the functions in the fpdf_test.go file (shown as examples in this +documentation) for more advanced PDF examples. + +Errors + +If an error occurs in an Fpdf method, an internal error field is set. After +this occurs, Fpdf method calls typically return without performing any +operations and the error state is retained. This error management scheme +facilitates PDF generation since individual method calls do not need to be +examined for failure; it is generally sufficient to wait until after Output() +is called. For the same reason, if an error occurs in the calling application +during PDF generation, it may be desirable for the application to transfer the +error to the Fpdf instance by calling the SetError() method or the SetErrorf() +method. At any time during the life cycle of the Fpdf instance, the error state +can be determined with a call to Ok() or Err(). The error itself can be +retrieved with a call to Error(). + +Conversion Notes + +This package is a relatively straightforward translation from the original FPDF +library written in PHP (despite the caveat in the introduction to Effective +Go). The API names have been retained even though the Go idiom would suggest +otherwise (for example, pdf.GetX() is used rather than simply pdf.X()). The +similarity of the two libraries makes the original FPDF website a good source +of information. It includes a forum and FAQ. + +However, some internal changes have been made. Page content is built up using +buffers (of type bytes.Buffer) rather than repeated string concatenation. +Errors are handled as explained above rather than panicking. Output is +generated through an interface of type io.Writer or io.WriteCloser. A number of +the original PHP methods behave differently based on the type of the arguments +that are passed to them; in these cases additional methods have been exported +to provide similar functionality. Font definition files are produced in JSON +rather than PHP. + +Example PDFs + +A side effect of running "go test ./..." is the production of a number of +example PDFs. These can be found in the gofpdf/pdf directory after the tests +complete. + +Please note that these examples run in the context of a test. In order run an +example as a standalone application, you'll need to examine fpdf_test.go for +some helper routines, for example exampleFilename() and summary(). + +Example PDFs can be compared with reference copies in order to verify that they +have been generated as expected. This comparison will be performed if a PDF +with the same name as the example PDF is placed in the gofpdf/pdf/reference +directory. The routine that summarizes an example will look for this file and, +if found, will call ComparePDFFiles() to check the example PDF for equality +with its reference PDF. If differences exist between the two files they will be +printed to standard output and the test will fail. If the reference file is +missing, the comparison is considered to succeed. In order to successfully +compare two PDFs, the placement of internal resources must be consistent and +the internal creation timestamps must be the same. To do this, the methods +SetCatalogSort() and SetCreationDate() need to be called for both files. This +is done automatically for all examples. + +Nonstandard Fonts + +Nothing special is required to use the standard PDF fonts (courier, helvetica, +times, zapfdingbats) in your documents other than calling SetFont(). + +In order to use a different TrueType or Type1 font, you will need to generate a +font definition file and, if the font will be embedded into PDFs, a compressed +version of the font file. This is done by calling the MakeFont function or +using the included makefont command line utility. To create the utility, cd +into the makefont subdirectory and run "go build". This will produce a +standalone executable named makefont. Select the appropriate encoding file from +the font subdirectory and run the command as in the following example. + + ./makefont --embed --enc=../font/cp1252.map --dst=../font ../font/calligra.ttf + +In your PDF generation code, call AddFont() to load the font and, as with the +standard fonts, SetFont() to begin using it. Most examples, including the +package example, demonstrate this method. Good sources of free, open-source +fonts include http://www.google.com/fonts/ and http://dejavu-fonts.org/. + +Related Packages + +The draw2d package (https://github.com/llgcode/draw2d) is a two dimensional +vector graphics library that can generate output in different forms. It uses +gofpdf for its document production mode. + +Contributing Changes + +gofpdf is a global community effort and you are invited to make it even better. +If you have implemented a new feature or corrected a problem, please consider +contributing your change to the project. A contribution that does not directly +pertain to the core functionality of gofpdf should be placed in its own +directory directly beneath the `contrib` directory. + +Here are guidelines for making submissions. Your change should + +• be compatible with the MIT License + +• be properly documented + +• be formatted with `go fmt` + +• include an example in fpdf_test.go if appropriate + +• conform to the standards of golint (https://github.com/golang/lint) and +go vet (https://godoc.org/golang.org/x/tools/cmd/vet), that is, `golint .` and +`go vet .` should not generate any warnings + +• not diminish test coverage (https://blog.golang.org/cover) + +Pull requests (https://help.github.com/articles/using-pull-requests/) work +nicely as a means of contributing your changes. + +License + +gofpdf is released under the MIT License. It is copyrighted by Kurt Jung and +the contributors acknowledged below. + +Acknowledgments + +This package's code and documentation are closely derived from the FPDF library +(http://www.fpdf.org/) created by Olivier Plathey, and a number of font and +image resources are copied directly from it. Drawing support is adapted from +the FPDF geometric figures script by David Hernández Sanz. Transparency +support is adapted from the FPDF transparency script by Martin Hall-May. +Support for gradients and clipping is adapted from FPDF scripts by Andreas +Würmser. Support for outline bookmarks is adapted from Olivier Plathey by +Manuel Cornes. Layer support is adapted from Olivier Plathey. Support for +transformations is adapted from the FPDF transformation script by Moritz Wagner +and Andreas Würmser. PDF protection is adapted from the work of Klemen +Vodopivec for the FPDF product. Lawrence Kesteloot provided code to allow an +image's extent to be determined prior to placement. Support for vertical +alignment within a cell was provided by Stefan Schroeder. Ivan Daniluk +generalized the font and image loading code to use the Reader interface while +maintaining backward compatibility. Anthony Starks provided code for the +Polygon function. Robert Lillack provided the Beziergon function and corrected +some naming issues with the internal curve function. Claudio Felber provided +implementations for dashed line drawing and generalized font loading. Stani +Michiels provided support for multi-segment path drawing with smooth line +joins, line join styles, enhanced fill modes, and has helped greatly with +package presentation and tests. Templating is adapted by Marcus Downing from +the FPDF_Tpl library created by Jan Slabon and Setasign. Jelmer Snoeck +contributed packages that generate a variety of barcodes and help with +registering images on the web. Additionally, he augmented the basic HTML +functionality with aligned text. Kent Quirk implemented backwards-compatible +support for reading DPI from images that support it, and for setting DPI +manually and then having it properly taken into account when calculating image +size. Paulo Coutinho provided support for static embedded fonts. Bruno Michel +has provided valuable assistance with the code. + +Roadmap + +• Handle UTF-8 source text natively. Until then, automatic translation of +UTF-8 runes to code page bytes is provided. + +• Improve test coverage as reported by the coverage tool. + +*/ +package gofpdf diff --git a/vendor/github.com/jung-kurt/gofpdf/embedded.go b/vendor/github.com/jung-kurt/gofpdf/embedded.go new file mode 100644 index 0000000..1d947b0 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/embedded.go @@ -0,0 +1,559 @@ +/* + * Copyright (c) 2014 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gofpdf + +// Embedded standard fonts + +import ( + "strings" +) + +var embeddedFontList = map[string]string{ + "courierBI": `{"Tp":"Core","Name":"Courier-BoldOblique","Up":-100,"Ut":50,"I":256,"Cw":[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600]}`, + "courierB": `{"Tp":"Core","Name":"Courier-Bold","Up":-100,"Ut":50,"I":256,"Cw":[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600]}`, + "courierI": `{"Tp":"Core","Name":"Courier-Oblique","Up":-100,"Ut":50,"I":256,"Cw":[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600]}`, + "courier": `{"Tp":"Core","Name":"Courier","Up":-100,"Ut":50,"I":256,"Cw":[600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600]}`, + "helveticaBI": `{"Tp":"Core","Name":"Helvetica-BoldOblique","Up":-100,"Ut":50,"Cw":[278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,333,474,556,556,889,722,238,333,333,389,584,278,333,278,278,556,556,556,556,556,556,556,556,556,556,333,333,584,584,584,611,975,722,722,722,722,667,611,778,722,278,556,722,611,833,722,778,667,778,722,667,611,722,667,944,667,667,611,333,278,333,584,556,333,556,611,556,611,556,333,611,611,278,278,556,278,889,611,611,611,611,389,556,333,611,556,778,556,556,500,389,280,389,584,350,556,350,278,556,500,1000,556,556,333,1000,667,333,1000,350,611,350,350,278,278,500,500,350,556,1000,333,1000,556,333,944,350,500,667,278,333,556,556,556,556,280,556,333,737,370,556,584,333,737,333,400,584,333,333,333,611,556,278,333,333,365,556,834,834,834,611,722,722,722,722,722,722,1000,722,667,667,667,667,278,278,278,278,722,722,778,778,778,778,778,584,778,722,722,722,722,667,667,611,556,556,556,556,556,556,889,556,556,556,556,556,278,278,278,278,611,611,611,611,611,611,611,584,611,611,611,611,611,556,611,556]}`, + "helveticaB": `{"Tp":"Core","Name":"Helvetica-Bold","Up":-100,"Ut":50,"Cw":[278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,333,474,556,556,889,722,238,333,333,389,584,278,333,278,278,556,556,556,556,556,556,556,556,556,556,333,333,584,584,584,611,975,722,722,722,722,667,611,778,722,278,556,722,611,833,722,778,667,778,722,667,611,722,667,944,667,667,611,333,278,333,584,556,333,556,611,556,611,556,333,611,611,278,278,556,278,889,611,611,611,611,389,556,333,611,556,778,556,556,500,389,280,389,584,350,556,350,278,556,500,1000,556,556,333,1000,667,333,1000,350,611,350,350,278,278,500,500,350,556,1000,333,1000,556,333,944,350,500,667,278,333,556,556,556,556,280,556,333,737,370,556,584,333,737,333,400,584,333,333,333,611,556,278,333,333,365,556,834,834,834,611,722,722,722,722,722,722,1000,722,667,667,667,667,278,278,278,278,722,722,778,778,778,778,778,584,778,722,722,722,722,667,667,611,556,556,556,556,556,556,889,556,556,556,556,556,278,278,278,278,611,611,611,611,611,611,611,584,611,611,611,611,611,556,611,556]}`, + "helveticaI": `{"Tp":"Core","Name":"Helvetica-Oblique","Up":-100,"Ut":50,"Cw":[278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,355,556,556,889,667,191,333,333,389,584,278,333,278,278,556,556,556,556,556,556,556,556,556,556,278,278,584,584,584,556,1015,667,667,722,722,667,611,778,722,278,500,667,556,833,722,778,667,778,722,667,611,722,667,944,667,667,611,278,278,278,469,556,333,556,556,500,556,556,278,556,556,222,222,500,222,833,556,556,556,556,333,500,278,556,500,722,500,500,500,334,260,334,584,350,556,350,222,556,333,1000,556,556,333,1000,667,333,1000,350,611,350,350,222,222,333,333,350,556,1000,333,1000,500,333,944,350,500,667,278,333,556,556,556,556,260,556,333,737,370,556,584,333,737,333,400,584,333,333,333,556,537,278,333,333,365,556,834,834,834,611,667,667,667,667,667,667,1000,722,667,667,667,667,278,278,278,278,722,722,778,778,778,778,778,584,778,722,722,722,722,667,667,611,556,556,556,556,556,556,889,500,556,556,556,556,278,278,278,278,556,556,556,556,556,556,556,584,611,556,556,556,556,500,556,500]}`, + "helvetica": `{"Tp":"Core","Name":"Helvetica","Up":-100,"Ut":50,"Cw":[278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,355,556,556,889,667,191,333,333,389,584,278,333,278,278,556,556,556,556,556,556,556,556,556,556,278,278,584,584,584,556,1015,667,667,722,722,667,611,778,722,278,500,667,556,833,722,778,667,778,722,667,611,722,667,944,667,667,611,278,278,278,469,556,333,556,556,500,556,556,278,556,556,222,222,500,222,833,556,556,556,556,333,500,278,556,500,722,500,500,500,334,260,334,584,350,556,350,222,556,333,1000,556,556,333,1000,667,333,1000,350,611,350,350,222,222,333,333,350,556,1000,333,1000,500,333,944,350,500,667,278,333,556,556,556,556,260,556,333,737,370,556,584,333,737,333,400,584,333,333,333,556,537,278,333,333,365,556,834,834,834,611,667,667,667,667,667,667,1000,722,667,667,667,667,278,278,278,278,722,722,778,778,778,778,778,584,778,722,722,722,722,667,667,611,556,556,556,556,556,556,889,500,556,556,556,556,278,278,278,278,556,556,556,556,556,556,556,584,611,556,556,556,556,500,556,500]}`, + "timesBI": `{"Tp":"Core","Name":"Times-BoldItalic","Up":-100,"Ut":50,"Cw":[250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,389,555,500,500,833,778,278,333,333,500,570,250,333,250,278,500,500,500,500,500,500,500,500,500,500,333,333,570,570,570,500,832,667,667,667,722,667,667,722,778,389,500,667,611,889,722,722,611,722,667,556,611,722,667,889,667,611,611,333,278,333,570,500,333,500,500,444,500,444,333,500,556,278,278,500,278,778,556,500,500,500,389,389,278,556,444,667,500,444,389,348,220,348,570,350,500,350,333,500,500,1000,500,500,333,1000,556,333,944,350,611,350,350,333,333,500,500,350,500,1000,333,1000,389,333,722,350,389,611,250,389,500,500,500,500,220,500,333,747,266,500,606,333,747,333,400,570,300,300,333,576,500,250,333,300,300,500,750,750,750,500,667,667,667,667,667,667,944,667,667,667,667,667,389,389,389,389,722,722,722,722,722,722,722,570,722,722,722,722,722,611,611,500,500,500,500,500,500,500,722,444,444,444,444,444,278,278,278,278,500,556,500,500,500,500,500,570,500,556,556,556,556,444,500,444]}`, + "timesB": `{"Tp":"Core","Name":"Times-Bold","Up":-100,"Ut":50,"Cw":[250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,333,555,500,500,1000,833,278,333,333,500,570,250,333,250,278,500,500,500,500,500,500,500,500,500,500,333,333,570,570,570,500,930,722,667,722,722,667,611,778,778,389,500,778,667,944,722,778,611,778,722,556,667,722,722,1000,722,722,667,333,278,333,581,500,333,500,556,444,556,444,333,500,556,278,333,556,278,833,556,500,556,556,444,389,333,556,500,722,500,500,444,394,220,394,520,350,500,350,333,500,500,1000,500,500,333,1000,556,333,1000,350,667,350,350,333,333,500,500,350,500,1000,333,1000,389,333,722,350,444,722,250,333,500,500,500,500,220,500,333,747,300,500,570,333,747,333,400,570,300,300,333,556,540,250,333,300,330,500,750,750,750,500,722,722,722,722,722,722,1000,722,667,667,667,667,389,389,389,389,722,722,778,778,778,778,778,570,778,722,722,722,722,722,611,556,500,500,500,500,500,500,722,444,444,444,444,444,278,278,278,278,500,556,500,500,500,500,500,570,500,556,556,556,556,500,556,500]}`, + "timesI": `{"Tp":"Core","Name":"Times-Italic","Up":-100,"Ut":50,"Cw":[250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,333,420,500,500,833,778,214,333,333,500,675,250,333,250,278,500,500,500,500,500,500,500,500,500,500,333,333,675,675,675,500,920,611,611,667,722,611,611,722,722,333,444,667,556,833,667,722,611,722,611,500,556,722,611,833,611,556,556,389,278,389,422,500,333,500,500,444,500,444,278,500,500,278,278,444,278,722,500,500,500,500,389,389,278,500,444,667,444,444,389,400,275,400,541,350,500,350,333,500,556,889,500,500,333,1000,500,333,944,350,556,350,350,333,333,556,556,350,500,889,333,980,389,333,667,350,389,556,250,389,500,500,500,500,275,500,333,760,276,500,675,333,760,333,400,675,300,300,333,500,523,250,333,300,310,500,750,750,750,500,611,611,611,611,611,611,889,667,611,611,611,611,333,333,333,333,722,667,722,722,722,722,722,675,722,722,722,722,722,556,611,500,500,500,500,500,500,500,667,444,444,444,444,444,278,278,278,278,500,500,500,500,500,500,500,675,500,500,500,500,500,444,500,444]}`, + "times": `{"Tp":"Core","Name":"Times-Roman","Up":-100,"Ut":50,"Cw":[250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,333,408,500,500,833,778,180,333,333,500,564,250,333,250,278,500,500,500,500,500,500,500,500,500,500,278,278,564,564,564,444,921,722,667,667,722,611,556,722,722,333,389,722,611,889,722,722,556,722,667,556,611,722,722,944,722,722,611,333,278,333,469,500,333,444,500,444,500,444,333,500,500,278,278,500,278,778,500,500,500,500,333,389,278,500,500,722,500,500,444,480,200,480,541,350,500,350,333,500,444,1000,500,500,333,1000,556,333,889,350,611,350,350,333,333,444,444,350,500,1000,333,980,389,333,722,350,444,722,250,333,500,500,500,500,200,500,333,760,276,500,564,333,760,333,400,564,300,300,333,500,453,250,333,300,310,500,750,750,750,444,722,722,722,722,722,722,889,667,611,611,611,611,333,333,333,333,722,722,722,722,722,722,722,564,722,722,722,722,722,722,556,500,444,444,444,444,444,444,667,444,444,444,444,444,278,278,278,278,500,500,500,500,500,500,500,564,500,500,500,500,500,500,500,500]}`, + "zapfdingbats": `{"Tp":"Core","Name":"ZapfDingbats","Up":-100,"Ut":50,"Cw":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,278,974,961,974,980,719,789,790,791,690,960,939,549,855,911,933,911,945,974,755,846,762,761,571,677,763,760,759,754,494,552,537,577,692,786,788,788,790,793,794,816,823,789,841,823,833,816,831,923,744,723,749,790,792,695,776,768,792,759,707,708,682,701,826,815,789,789,707,687,696,689,786,787,713,791,785,791,873,761,762,762,759,759,892,892,788,784,438,138,277,415,392,392,668,668,0,390,390,317,317,276,276,509,509,410,410,234,234,334,334,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,732,544,544,910,667,760,760,776,595,694,626,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,894,838,1016,458,748,924,748,918,927,928,928,834,873,828,924,924,917,930,931,463,883,836,836,867,867,696,696,874,0,874,760,946,771,865,771,888,967,888,831,873,927,970,918,0]}`, +} + +func (f *Fpdf) coreFontReader(familyStr, styleStr string) (r *strings.Reader) { + key := familyStr + styleStr + str, ok := embeddedFontList[key] + if ok { + r = strings.NewReader(str) + } else { + f.SetErrorf("could not locate \"%s\" among embedded core font definition files", key) + } + return +} + +var embeddedMapList = map[string]string{ + "cp1250": ` +!00 U+0000 .notdef +!01 U+0001 .notdef +!02 U+0002 .notdef +!03 U+0003 .notdef +!04 U+0004 .notdef +!05 U+0005 .notdef +!06 U+0006 .notdef +!07 U+0007 .notdef +!08 U+0008 .notdef +!09 U+0009 .notdef +!0A U+000A .notdef +!0B U+000B .notdef +!0C U+000C .notdef +!0D U+000D .notdef +!0E U+000E .notdef +!0F U+000F .notdef +!10 U+0010 .notdef +!11 U+0011 .notdef +!12 U+0012 .notdef +!13 U+0013 .notdef +!14 U+0014 .notdef +!15 U+0015 .notdef +!16 U+0016 .notdef +!17 U+0017 .notdef +!18 U+0018 .notdef +!19 U+0019 .notdef +!1A U+001A .notdef +!1B U+001B .notdef +!1C U+001C .notdef +!1D U+001D .notdef +!1E U+001E .notdef +!1F U+001F .notdef +!20 U+0020 space +!21 U+0021 exclam +!22 U+0022 quotedbl +!23 U+0023 numbersign +!24 U+0024 dollar +!25 U+0025 percent +!26 U+0026 ampersand +!27 U+0027 quotesingle +!28 U+0028 parenleft +!29 U+0029 parenright +!2A U+002A asterisk +!2B U+002B plus +!2C U+002C comma +!2D U+002D hyphen +!2E U+002E period +!2F U+002F slash +!30 U+0030 zero +!31 U+0031 one +!32 U+0032 two +!33 U+0033 three +!34 U+0034 four +!35 U+0035 five +!36 U+0036 six +!37 U+0037 seven +!38 U+0038 eight +!39 U+0039 nine +!3A U+003A colon +!3B U+003B semicolon +!3C U+003C less +!3D U+003D equal +!3E U+003E greater +!3F U+003F question +!40 U+0040 at +!41 U+0041 A +!42 U+0042 B +!43 U+0043 C +!44 U+0044 D +!45 U+0045 E +!46 U+0046 F +!47 U+0047 G +!48 U+0048 H +!49 U+0049 I +!4A U+004A J +!4B U+004B K +!4C U+004C L +!4D U+004D M +!4E U+004E N +!4F U+004F O +!50 U+0050 P +!51 U+0051 Q +!52 U+0052 R +!53 U+0053 S +!54 U+0054 T +!55 U+0055 U +!56 U+0056 V +!57 U+0057 W +!58 U+0058 X +!59 U+0059 Y +!5A U+005A Z +!5B U+005B bracketleft +!5C U+005C backslash +!5D U+005D bracketright +!5E U+005E asciicircum +!5F U+005F underscore +!60 U+0060 grave +!61 U+0061 a +!62 U+0062 b +!63 U+0063 c +!64 U+0064 d +!65 U+0065 e +!66 U+0066 f +!67 U+0067 g +!68 U+0068 h +!69 U+0069 i +!6A U+006A j +!6B U+006B k +!6C U+006C l +!6D U+006D m +!6E U+006E n +!6F U+006F o +!70 U+0070 p +!71 U+0071 q +!72 U+0072 r +!73 U+0073 s +!74 U+0074 t +!75 U+0075 u +!76 U+0076 v +!77 U+0077 w +!78 U+0078 x +!79 U+0079 y +!7A U+007A z +!7B U+007B braceleft +!7C U+007C bar +!7D U+007D braceright +!7E U+007E asciitilde +!7F U+007F .notdef +!80 U+20AC Euro +!82 U+201A quotesinglbase +!84 U+201E quotedblbase +!85 U+2026 ellipsis +!86 U+2020 dagger +!87 U+2021 daggerdbl +!89 U+2030 perthousand +!8A U+0160 Scaron +!8B U+2039 guilsinglleft +!8C U+015A Sacute +!8D U+0164 Tcaron +!8E U+017D Zcaron +!8F U+0179 Zacute +!91 U+2018 quoteleft +!92 U+2019 quoteright +!93 U+201C quotedblleft +!94 U+201D quotedblright +!95 U+2022 bullet +!96 U+2013 endash +!97 U+2014 emdash +!99 U+2122 trademark +!9A U+0161 scaron +!9B U+203A guilsinglright +!9C U+015B sacute +!9D U+0165 tcaron +!9E U+017E zcaron +!9F U+017A zacute +!A0 U+00A0 space +!A1 U+02C7 caron +!A2 U+02D8 breve +!A3 U+0141 Lslash +!A4 U+00A4 currency +!A5 U+0104 Aogonek +!A6 U+00A6 brokenbar +!A7 U+00A7 section +!A8 U+00A8 dieresis +!A9 U+00A9 copyright +!AA U+015E Scedilla +!AB U+00AB guillemotleft +!AC U+00AC logicalnot +!AD U+00AD hyphen +!AE U+00AE registered +!AF U+017B Zdotaccent +!B0 U+00B0 degree +!B1 U+00B1 plusminus +!B2 U+02DB ogonek +!B3 U+0142 lslash +!B4 U+00B4 acute +!B5 U+00B5 mu +!B6 U+00B6 paragraph +!B7 U+00B7 periodcentered +!B8 U+00B8 cedilla +!B9 U+0105 aogonek +!BA U+015F scedilla +!BB U+00BB guillemotright +!BC U+013D Lcaron +!BD U+02DD hungarumlaut +!BE U+013E lcaron +!BF U+017C zdotaccent +!C0 U+0154 Racute +!C1 U+00C1 Aacute +!C2 U+00C2 Acircumflex +!C3 U+0102 Abreve +!C4 U+00C4 Adieresis +!C5 U+0139 Lacute +!C6 U+0106 Cacute +!C7 U+00C7 Ccedilla +!C8 U+010C Ccaron +!C9 U+00C9 Eacute +!CA U+0118 Eogonek +!CB U+00CB Edieresis +!CC U+011A Ecaron +!CD U+00CD Iacute +!CE U+00CE Icircumflex +!CF U+010E Dcaron +!D0 U+0110 Dcroat +!D1 U+0143 Nacute +!D2 U+0147 Ncaron +!D3 U+00D3 Oacute +!D4 U+00D4 Ocircumflex +!D5 U+0150 Ohungarumlaut +!D6 U+00D6 Odieresis +!D7 U+00D7 multiply +!D8 U+0158 Rcaron +!D9 U+016E Uring +!DA U+00DA Uacute +!DB U+0170 Uhungarumlaut +!DC U+00DC Udieresis +!DD U+00DD Yacute +!DE U+0162 Tcommaaccent +!DF U+00DF germandbls +!E0 U+0155 racute +!E1 U+00E1 aacute +!E2 U+00E2 acircumflex +!E3 U+0103 abreve +!E4 U+00E4 adieresis +!E5 U+013A lacute +!E6 U+0107 cacute +!E7 U+00E7 ccedilla +!E8 U+010D ccaron +!E9 U+00E9 eacute +!EA U+0119 eogonek +!EB U+00EB edieresis +!EC U+011B ecaron +!ED U+00ED iacute +!EE U+00EE icircumflex +!EF U+010F dcaron +!F0 U+0111 dcroat +!F1 U+0144 nacute +!F2 U+0148 ncaron +!F3 U+00F3 oacute +!F4 U+00F4 ocircumflex +!F5 U+0151 ohungarumlaut +!F6 U+00F6 odieresis +!F7 U+00F7 divide +!F8 U+0159 rcaron +!F9 U+016F uring +!FA U+00FA uacute +!FB U+0171 uhungarumlaut +!FC U+00FC udieresis +!FD U+00FD yacute +!FE U+0163 tcommaaccent +!FF U+02D9 dotaccent + `, + "cp1252": ` +!00 U+0000 .notdef +!01 U+0001 .notdef +!02 U+0002 .notdef +!03 U+0003 .notdef +!04 U+0004 .notdef +!05 U+0005 .notdef +!06 U+0006 .notdef +!07 U+0007 .notdef +!08 U+0008 .notdef +!09 U+0009 .notdef +!0A U+000A .notdef +!0B U+000B .notdef +!0C U+000C .notdef +!0D U+000D .notdef +!0E U+000E .notdef +!0F U+000F .notdef +!10 U+0010 .notdef +!11 U+0011 .notdef +!12 U+0012 .notdef +!13 U+0013 .notdef +!14 U+0014 .notdef +!15 U+0015 .notdef +!16 U+0016 .notdef +!17 U+0017 .notdef +!18 U+0018 .notdef +!19 U+0019 .notdef +!1A U+001A .notdef +!1B U+001B .notdef +!1C U+001C .notdef +!1D U+001D .notdef +!1E U+001E .notdef +!1F U+001F .notdef +!20 U+0020 space +!21 U+0021 exclam +!22 U+0022 quotedbl +!23 U+0023 numbersign +!24 U+0024 dollar +!25 U+0025 percent +!26 U+0026 ampersand +!27 U+0027 quotesingle +!28 U+0028 parenleft +!29 U+0029 parenright +!2A U+002A asterisk +!2B U+002B plus +!2C U+002C comma +!2D U+002D hyphen +!2E U+002E period +!2F U+002F slash +!30 U+0030 zero +!31 U+0031 one +!32 U+0032 two +!33 U+0033 three +!34 U+0034 four +!35 U+0035 five +!36 U+0036 six +!37 U+0037 seven +!38 U+0038 eight +!39 U+0039 nine +!3A U+003A colon +!3B U+003B semicolon +!3C U+003C less +!3D U+003D equal +!3E U+003E greater +!3F U+003F question +!40 U+0040 at +!41 U+0041 A +!42 U+0042 B +!43 U+0043 C +!44 U+0044 D +!45 U+0045 E +!46 U+0046 F +!47 U+0047 G +!48 U+0048 H +!49 U+0049 I +!4A U+004A J +!4B U+004B K +!4C U+004C L +!4D U+004D M +!4E U+004E N +!4F U+004F O +!50 U+0050 P +!51 U+0051 Q +!52 U+0052 R +!53 U+0053 S +!54 U+0054 T +!55 U+0055 U +!56 U+0056 V +!57 U+0057 W +!58 U+0058 X +!59 U+0059 Y +!5A U+005A Z +!5B U+005B bracketleft +!5C U+005C backslash +!5D U+005D bracketright +!5E U+005E asciicircum +!5F U+005F underscore +!60 U+0060 grave +!61 U+0061 a +!62 U+0062 b +!63 U+0063 c +!64 U+0064 d +!65 U+0065 e +!66 U+0066 f +!67 U+0067 g +!68 U+0068 h +!69 U+0069 i +!6A U+006A j +!6B U+006B k +!6C U+006C l +!6D U+006D m +!6E U+006E n +!6F U+006F o +!70 U+0070 p +!71 U+0071 q +!72 U+0072 r +!73 U+0073 s +!74 U+0074 t +!75 U+0075 u +!76 U+0076 v +!77 U+0077 w +!78 U+0078 x +!79 U+0079 y +!7A U+007A z +!7B U+007B braceleft +!7C U+007C bar +!7D U+007D braceright +!7E U+007E asciitilde +!7F U+007F .notdef +!80 U+20AC Euro +!82 U+201A quotesinglbase +!83 U+0192 florin +!84 U+201E quotedblbase +!85 U+2026 ellipsis +!86 U+2020 dagger +!87 U+2021 daggerdbl +!88 U+02C6 circumflex +!89 U+2030 perthousand +!8A U+0160 Scaron +!8B U+2039 guilsinglleft +!8C U+0152 OE +!8E U+017D Zcaron +!91 U+2018 quoteleft +!92 U+2019 quoteright +!93 U+201C quotedblleft +!94 U+201D quotedblright +!95 U+2022 bullet +!96 U+2013 endash +!97 U+2014 emdash +!98 U+02DC tilde +!99 U+2122 trademark +!9A U+0161 scaron +!9B U+203A guilsinglright +!9C U+0153 oe +!9E U+017E zcaron +!9F U+0178 Ydieresis +!A0 U+00A0 space +!A1 U+00A1 exclamdown +!A2 U+00A2 cent +!A3 U+00A3 sterling +!A4 U+00A4 currency +!A5 U+00A5 yen +!A6 U+00A6 brokenbar +!A7 U+00A7 section +!A8 U+00A8 dieresis +!A9 U+00A9 copyright +!AA U+00AA ordfeminine +!AB U+00AB guillemotleft +!AC U+00AC logicalnot +!AD U+00AD hyphen +!AE U+00AE registered +!AF U+00AF macron +!B0 U+00B0 degree +!B1 U+00B1 plusminus +!B2 U+00B2 twosuperior +!B3 U+00B3 threesuperior +!B4 U+00B4 acute +!B5 U+00B5 mu +!B6 U+00B6 paragraph +!B7 U+00B7 periodcentered +!B8 U+00B8 cedilla +!B9 U+00B9 onesuperior +!BA U+00BA ordmasculine +!BB U+00BB guillemotright +!BC U+00BC onequarter +!BD U+00BD onehalf +!BE U+00BE threequarters +!BF U+00BF questiondown +!C0 U+00C0 Agrave +!C1 U+00C1 Aacute +!C2 U+00C2 Acircumflex +!C3 U+00C3 Atilde +!C4 U+00C4 Adieresis +!C5 U+00C5 Aring +!C6 U+00C6 AE +!C7 U+00C7 Ccedilla +!C8 U+00C8 Egrave +!C9 U+00C9 Eacute +!CA U+00CA Ecircumflex +!CB U+00CB Edieresis +!CC U+00CC Igrave +!CD U+00CD Iacute +!CE U+00CE Icircumflex +!CF U+00CF Idieresis +!D0 U+00D0 Eth +!D1 U+00D1 Ntilde +!D2 U+00D2 Ograve +!D3 U+00D3 Oacute +!D4 U+00D4 Ocircumflex +!D5 U+00D5 Otilde +!D6 U+00D6 Odieresis +!D7 U+00D7 multiply +!D8 U+00D8 Oslash +!D9 U+00D9 Ugrave +!DA U+00DA Uacute +!DB U+00DB Ucircumflex +!DC U+00DC Udieresis +!DD U+00DD Yacute +!DE U+00DE Thorn +!DF U+00DF germandbls +!E0 U+00E0 agrave +!E1 U+00E1 aacute +!E2 U+00E2 acircumflex +!E3 U+00E3 atilde +!E4 U+00E4 adieresis +!E5 U+00E5 aring +!E6 U+00E6 ae +!E7 U+00E7 ccedilla +!E8 U+00E8 egrave +!E9 U+00E9 eacute +!EA U+00EA ecircumflex +!EB U+00EB edieresis +!EC U+00EC igrave +!ED U+00ED iacute +!EE U+00EE icircumflex +!EF U+00EF idieresis +!F0 U+00F0 eth +!F1 U+00F1 ntilde +!F2 U+00F2 ograve +!F3 U+00F3 oacute +!F4 U+00F4 ocircumflex +!F5 U+00F5 otilde +!F6 U+00F6 odieresis +!F7 U+00F7 divide +!F8 U+00F8 oslash +!F9 U+00F9 ugrave +!FA U+00FA uacute +!FB U+00FB ucircumflex +!FC U+00FC udieresis +!FD U+00FD yacute +!FE U+00FE thorn +!FF U+00FF ydieresis + `, +} diff --git a/vendor/github.com/jung-kurt/gofpdf/font.go b/vendor/github.com/jung-kurt/gofpdf/font.go new file mode 100644 index 0000000..35f59f1 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/font.go @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2013 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gofpdf + +// Utility to generate font definition files + +// Version: 1.2 +// Date: 2011-06-18 +// Author: Olivier PLATHEY +// Port to Go: Kurt Jung, 2013-07-15 + +import ( + "bufio" + "compress/zlib" + "encoding/binary" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" +) + +func baseNoExt(fileStr string) string { + str := filepath.Base(fileStr) + extLen := len(filepath.Ext(str)) + if extLen > 0 { + str = str[:len(str)-extLen] + } + return str +} + +func loadMap(encodingFileStr string) (encList encListType, err error) { + // printf("Encoding file string [%s]\n", encodingFileStr) + var f *os.File + // f, err = os.Open(encodingFilepath(encodingFileStr)) + f, err = os.Open(encodingFileStr) + if err == nil { + defer f.Close() + for j := range encList { + encList[j].uv = -1 + encList[j].name = ".notdef" + } + scanner := bufio.NewScanner(f) + var enc encType + var pos int + for scanner.Scan() { + // "!3F U+003F question" + _, err = fmt.Sscanf(scanner.Text(), "!%x U+%x %s", &pos, &enc.uv, &enc.name) + if err == nil { + if pos < 256 { + encList[pos] = enc + } else { + err = fmt.Errorf("map position 0x%2X exceeds 0xFF", pos) + return + } + } else { + return + } + } + if err = scanner.Err(); err != nil { + return + } + } + return +} + +// Return informations from a TrueType font +func getInfoFromTrueType(fileStr string, msgWriter io.Writer, embed bool, encList encListType) (info fontInfoType, err error) { + var ttf TtfType + ttf, err = TtfParse(fileStr) + if err != nil { + return + } + if embed { + if !ttf.Embeddable { + err = fmt.Errorf("font license does not allow embedding") + return + } + info.Data, err = ioutil.ReadFile(fileStr) + if err != nil { + return + } + info.OriginalSize = len(info.Data) + } + k := 1000.0 / float64(ttf.UnitsPerEm) + info.FontName = ttf.PostScriptName + info.Bold = ttf.Bold + info.Desc.ItalicAngle = int(ttf.ItalicAngle) + info.IsFixedPitch = ttf.IsFixedPitch + info.Desc.Ascent = round(k * float64(ttf.TypoAscender)) + info.Desc.Descent = round(k * float64(ttf.TypoDescender)) + info.UnderlineThickness = round(k * float64(ttf.UnderlineThickness)) + info.UnderlinePosition = round(k * float64(ttf.UnderlinePosition)) + info.Desc.FontBBox = fontBoxType{ + round(k * float64(ttf.Xmin)), + round(k * float64(ttf.Ymin)), + round(k * float64(ttf.Xmax)), + round(k * float64(ttf.Ymax)), + } + // printf("FontBBox\n") + // dump(info.Desc.FontBBox) + info.Desc.CapHeight = round(k * float64(ttf.CapHeight)) + info.Desc.MissingWidth = round(k * float64(ttf.Widths[0])) + var wd int + for j := 0; j < len(info.Widths); j++ { + wd = info.Desc.MissingWidth + if encList[j].name != ".notdef" { + uv := encList[j].uv + pos, ok := ttf.Chars[uint16(uv)] + if ok { + wd = round(k * float64(ttf.Widths[pos])) + } else { + fmt.Fprintf(msgWriter, "Character %s is missing\n", encList[j].name) + } + } + info.Widths[j] = wd + } + // printf("getInfoFromTrueType/FontBBox\n") + // dump(info.Desc.FontBBox) + return +} + +type segmentType struct { + marker uint8 + tp uint8 + size uint32 + data []byte +} + +func segmentRead(f *os.File) (s segmentType, err error) { + if err = binary.Read(f, binary.LittleEndian, &s.marker); err != nil { + return + } + if s.marker != 128 { + err = fmt.Errorf("font file is not a valid binary Type1") + return + } + if err = binary.Read(f, binary.LittleEndian, &s.tp); err != nil { + return + } + if err = binary.Read(f, binary.LittleEndian, &s.size); err != nil { + return + } + s.data = make([]byte, s.size) + _, err = f.Read(s.data) + return +} + +// -rw-r--r-- 1 root root 9532 2010-04-22 11:27 /usr/share/fonts/type1/mathml/Symbol.afm +// -rw-r--r-- 1 root root 37744 2010-04-22 11:27 /usr/share/fonts/type1/mathml/Symbol.pfb + +// Return informations from a Type1 font +func getInfoFromType1(fileStr string, msgWriter io.Writer, embed bool, encList encListType) (info fontInfoType, err error) { + if embed { + var f *os.File + f, err = os.Open(fileStr) + if err != nil { + return + } + defer f.Close() + // Read first segment + var s1, s2 segmentType + s1, err = segmentRead(f) + if err != nil { + return + } + s2, err = segmentRead(f) + if err != nil { + return + } + info.Data = s1.data + info.Data = append(info.Data, s2.data...) + info.Size1 = s1.size + info.Size2 = s2.size + } + afmFileStr := fileStr[0:len(fileStr)-3] + "afm" + size, ok := fileSize(afmFileStr) + if !ok { + err = fmt.Errorf("font file (ATM) %s not found", afmFileStr) + return + } else if size == 0 { + err = fmt.Errorf("font file (AFM) %s empty or not readable", afmFileStr) + return + } + var f *os.File + f, err = os.Open(afmFileStr) + if err != nil { + return + } + defer f.Close() + scanner := bufio.NewScanner(f) + var fields []string + var wd int + var wt, name string + wdMap := make(map[string]int) + for scanner.Scan() { + fields = strings.Fields(strings.TrimSpace(scanner.Text())) + // Comment Generated by FontForge 20080203 + // FontName Symbol + // C 32 ; WX 250 ; N space ; B 0 0 0 0 ; + if len(fields) >= 2 { + switch fields[0] { + case "C": + if wd, err = strconv.Atoi(fields[4]); err == nil { + name = fields[7] + wdMap[name] = wd + } + case "FontName": + info.FontName = fields[1] + case "Weight": + wt = strings.ToLower(fields[1]) + case "ItalicAngle": + info.Desc.ItalicAngle, err = strconv.Atoi(fields[1]) + case "Ascender": + info.Desc.Ascent, err = strconv.Atoi(fields[1]) + case "Descender": + info.Desc.Descent, err = strconv.Atoi(fields[1]) + case "UnderlineThickness": + info.UnderlineThickness, err = strconv.Atoi(fields[1]) + case "UnderlinePosition": + info.UnderlinePosition, err = strconv.Atoi(fields[1]) + case "IsFixedPitch": + info.IsFixedPitch = fields[1] == "true" + case "FontBBox": + if info.Desc.FontBBox.Xmin, err = strconv.Atoi(fields[1]); err == nil { + if info.Desc.FontBBox.Ymin, err = strconv.Atoi(fields[2]); err == nil { + if info.Desc.FontBBox.Xmax, err = strconv.Atoi(fields[3]); err == nil { + info.Desc.FontBBox.Ymax, err = strconv.Atoi(fields[4]) + } + } + } + case "CapHeight": + info.Desc.CapHeight, err = strconv.Atoi(fields[1]) + case "StdVW": + info.Desc.StemV, err = strconv.Atoi(fields[1]) + } + } + if err != nil { + return + } + } + if err = scanner.Err(); err != nil { + return + } + if info.FontName == "" { + err = fmt.Errorf("the field FontName missing in AFM file %s", afmFileStr) + return + } + info.Bold = wt == "bold" || wt == "black" + var missingWd int + missingWd, ok = wdMap[".notdef"] + if ok { + info.Desc.MissingWidth = missingWd + } + for j := 0; j < len(info.Widths); j++ { + info.Widths[j] = info.Desc.MissingWidth + } + for j := 0; j < len(info.Widths); j++ { + name = encList[j].name + if name != ".notdef" { + wd, ok = wdMap[name] + if ok { + info.Widths[j] = wd + } else { + fmt.Fprintf(msgWriter, "Character %s is missing\n", name) + } + } + } + // printf("getInfoFromType1/FontBBox\n") + // dump(info.Desc.FontBBox) + return +} + +func makeFontDescriptor(info *fontInfoType) { + if info.Desc.CapHeight == 0 { + info.Desc.CapHeight = info.Desc.Ascent + } + info.Desc.Flags = 1 << 5 + if info.IsFixedPitch { + info.Desc.Flags |= 1 + } + if info.Desc.ItalicAngle != 0 { + info.Desc.Flags |= 1 << 6 + } + if info.Desc.StemV == 0 { + if info.Bold { + info.Desc.StemV = 120 + } else { + info.Desc.StemV = 70 + } + } + // printf("makeFontDescriptor/FontBBox\n") + // dump(info.Desc.FontBBox) +} + +// Build differences from reference encoding +func makeFontEncoding(encList encListType, refEncFileStr string) (diffStr string, err error) { + var refList encListType + if refList, err = loadMap(refEncFileStr); err != nil { + return + } + var buf fmtBuffer + last := 0 + for j := 32; j < 256; j++ { + if encList[j].name != refList[j].name { + if j != last+1 { + buf.printf("%d ", j) + } + last = j + buf.printf("/%s ", encList[j].name) + } + } + diffStr = strings.TrimSpace(buf.String()) + return +} + +func makeDefinitionFile(fileStr, tpStr, encodingFileStr string, embed bool, encList encListType, info fontInfoType) (err error) { + var def fontDefType + def.Tp = tpStr + def.Name = info.FontName + makeFontDescriptor(&info) + def.Desc = info.Desc + // printf("makeDefinitionFile/FontBBox\n") + // dump(def.Desc.FontBBox) + def.Up = info.UnderlinePosition + def.Ut = info.UnderlineThickness + def.Cw = info.Widths + def.Enc = baseNoExt(encodingFileStr) + // fmt.Printf("encodingFileStr [%s], def.Enc [%s]\n", encodingFileStr, def.Enc) + // fmt.Printf("reference [%s]\n", filepath.Join(filepath.Dir(encodingFileStr), "cp1252.map")) + def.Diff, err = makeFontEncoding(encList, filepath.Join(filepath.Dir(encodingFileStr), "cp1252.map")) + if err != nil { + return + } + def.File = info.File + def.Size1 = int(info.Size1) + def.Size2 = int(info.Size2) + def.OriginalSize = info.OriginalSize + // printf("Font definition file [%s]\n", fileStr) + var buf []byte + buf, err = json.Marshal(def) + if err != nil { + return + } + var f *os.File + f, err = os.Create(fileStr) + if err != nil { + return + } + defer f.Close() + f.Write(buf) + return +} + +// MakeFont generates a font definition file in JSON format. A definition file +// of this type is required to use non-core fonts in the PDF documents that +// gofpdf generates. See the makefont utility in the gofpdf package for a +// command line interface to this function. +// +// fontFileStr is the name of the TrueType file (extension .ttf), OpenType file +// (extension .otf) or binary Type1 file (extension .pfb) from which to +// generate a definition file. If an OpenType file is specified, it must be one +// that is based on TrueType outlines, not PostScript outlines; this cannot be +// determined from the file extension alone. If a Type1 file is specified, a +// metric file with the same pathname except with the extension .afm must be +// present. +// +// encodingFileStr is the name of the encoding file that corresponds to the +// font. +// +// dstDirStr is the name of the directory in which to save the definition file +// and, if embed is true, the compressed font file. +// +// msgWriter is the writer that is called to display messages throughout the +// process. Use nil to turn off messages. +// +// embed is true if the font is to be embedded in the PDF files. +func MakeFont(fontFileStr, encodingFileStr, dstDirStr string, msgWriter io.Writer, embed bool) (err error) { + if msgWriter == nil { + msgWriter = ioutil.Discard + } + if !fileExist(fontFileStr) { + err = fmt.Errorf("font file not found: %s", fontFileStr) + return + } + extStr := strings.ToLower(fontFileStr[len(fontFileStr)-3:]) + // printf("Font file extension [%s]\n", extStr) + var tpStr string + if extStr == "ttf" || extStr == "otf" { + tpStr = "TrueType" + } else if extStr == "pfb" { + tpStr = "Type1" + } else { + err = fmt.Errorf("unrecognized font file extension: %s", extStr) + return + } + var encList encListType + var info fontInfoType + encList, err = loadMap(encodingFileStr) + if err != nil { + return + } + // printf("Encoding table\n") + // dump(encList) + if tpStr == "TrueType" { + info, err = getInfoFromTrueType(fontFileStr, msgWriter, embed, encList) + if err != nil { + return + } + } else { + info, err = getInfoFromType1(fontFileStr, msgWriter, embed, encList) + if err != nil { + return + } + } + baseStr := baseNoExt(fontFileStr) + // fmt.Printf("Base [%s]\n", baseStr) + if embed { + var f *os.File + info.File = baseStr + ".z" + zFileStr := filepath.Join(dstDirStr, info.File) + f, err = os.Create(zFileStr) + if err != nil { + return + } + defer f.Close() + cmp := zlib.NewWriter(f) + cmp.Write(info.Data) + cmp.Close() + fmt.Fprintf(msgWriter, "Font file compressed: %s\n", zFileStr) + } + defFileStr := filepath.Join(dstDirStr, baseStr+".json") + err = makeDefinitionFile(defFileStr, tpStr, encodingFileStr, embed, encList, info) + if err != nil { + return + } + fmt.Fprintf(msgWriter, "Font definition file successfully generated: %s\n", defFileStr) + return +} diff --git a/vendor/github.com/jung-kurt/gofpdf/fpdf.go b/vendor/github.com/jung-kurt/gofpdf/fpdf.go new file mode 100644 index 0000000..66cff72 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/fpdf.go @@ -0,0 +1,3856 @@ +/* + * Copyright (c) 2013-2014 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gofpdf + +// Version: 1.7 +// Date: 2011-06-18 +// Author: Olivier PLATHEY +// Port to Go: Kurt Jung, 2013-07-15 + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "fmt" + "image" + "image/color" + "image/gif" + "image/jpeg" + "image/png" + "io" + "io/ioutil" + "math" + "os" + "path" + "sort" + "strconv" + "strings" + "time" +) + +var gl struct { + catalogSort bool + noCompress bool // Initial zero value indicates compression + creationDate time.Time +} + +type fmtBuffer struct { + bytes.Buffer +} + +func (b *fmtBuffer) printf(fmtStr string, args ...interface{}) { + b.Buffer.WriteString(fmt.Sprintf(fmtStr, args...)) +} + +func fpdfNew(orientationStr, unitStr, sizeStr, fontDirStr string, size SizeType) (f *Fpdf) { + f = new(Fpdf) + if orientationStr == "" { + orientationStr = "P" + } + if unitStr == "" { + unitStr = "mm" + } + if sizeStr == "" { + sizeStr = "A4" + } + if fontDirStr == "" { + fontDirStr = "." + } + f.page = 0 + f.n = 2 + f.pages = make([]*bytes.Buffer, 0, 8) + f.pages = append(f.pages, bytes.NewBufferString("")) // pages[0] is unused (1-based) + f.pageSizes = make(map[int]SizeType) + f.state = 0 + f.fonts = make(map[string]fontDefType) + f.fontFiles = make(map[string]fontFileType) + f.diffs = make([]string, 0, 8) + f.templates = make(map[int64]Template) + f.templateObjects = make(map[int64]int) + f.images = make(map[string]*ImageInfoType) + f.pageLinks = make([][]linkType, 0, 8) + f.pageLinks = append(f.pageLinks, make([]linkType, 0, 0)) // pageLinks[0] is unused (1-based) + f.links = make([]intLinkType, 0, 8) + f.links = append(f.links, intLinkType{}) // links[0] is unused (1-based) + f.inHeader = false + f.inFooter = false + f.lasth = 0 + f.fontFamily = "" + f.fontStyle = "" + f.SetFontSize(12) + f.underline = false + f.SetDrawColor(0, 0, 0) + f.SetFillColor(0, 0, 0) + f.SetTextColor(0, 0, 0) + f.colorFlag = false + f.ws = 0 + f.fontpath = fontDirStr + // Core fonts + f.coreFonts = map[string]bool{ + "courier": true, + "helvetica": true, + "times": true, + "symbol": true, + "zapfdingbats": true, + } + // Scale factor + switch unitStr { + case "pt", "point": + f.k = 1.0 + case "mm": + f.k = 72.0 / 25.4 + case "cm": + f.k = 72.0 / 2.54 + case "in", "inch": + f.k = 72.0 + default: + f.err = fmt.Errorf("incorrect unit %s", unitStr) + return + } + f.unitStr = unitStr + // Page sizes + f.stdPageSizes = make(map[string]SizeType) + f.stdPageSizes["a3"] = SizeType{841.89, 1190.55} + f.stdPageSizes["a4"] = SizeType{595.28, 841.89} + f.stdPageSizes["a5"] = SizeType{420.94, 595.28} + f.stdPageSizes["letter"] = SizeType{612, 792} + f.stdPageSizes["legal"] = SizeType{612, 1008} + if size.Wd > 0 && size.Ht > 0 { + f.defPageSize = size + } else { + f.defPageSize = f.getpagesizestr(sizeStr) + if f.err != nil { + return + } + } + f.curPageSize = f.defPageSize + // Page orientation + orientationStr = strings.ToLower(orientationStr) + switch orientationStr { + case "p", "portrait": + f.defOrientation = "P" + f.w = f.defPageSize.Wd + f.h = f.defPageSize.Ht + // dbg("Assign h: %8.2f", f.h) + case "l", "landscape": + f.defOrientation = "L" + f.w = f.defPageSize.Ht + f.h = f.defPageSize.Wd + default: + f.err = fmt.Errorf("incorrect orientation: %s", orientationStr) + return + } + f.curOrientation = f.defOrientation + f.wPt = f.w * f.k + f.hPt = f.h * f.k + // Page margins (1 cm) + margin := 28.35 / f.k + f.SetMargins(margin, margin, margin) + // Interior cell margin (1 mm) + f.cMargin = margin / 10 + // Line width (0.2 mm) + f.lineWidth = 0.567 / f.k + // Automatic page break + f.SetAutoPageBreak(true, 2*margin) + // Default display mode + f.SetDisplayMode("default", "default") + if f.err != nil { + return + } + f.acceptPageBreak = func() bool { + return f.autoPageBreak + } + // Enable compression + f.SetCompression(!gl.noCompress) + f.blendList = make([]blendModeType, 0, 8) + f.blendList = append(f.blendList, blendModeType{}) // blendList[0] is unused (1-based) + f.blendMap = make(map[string]int) + f.blendMode = "Normal" + f.alpha = 1 + f.gradientList = make([]gradientType, 0, 8) + f.gradientList = append(f.gradientList, gradientType{}) // gradientList[0] is unused + // Set default PDF version number + f.pdfVersion = "1.3" + f.layerInit() + f.catalogSort = gl.catalogSort + f.creationDate = gl.creationDate + return +} + +// NewCustom returns a pointer to a new Fpdf instance. Its methods are +// subsequently called to produce a single PDF document. NewCustom() is an +// alternative to New() that provides additional customization. The PageSize() +// example demonstrates this method. +func NewCustom(init *InitType) (f *Fpdf) { + return fpdfNew(init.OrientationStr, init.UnitStr, init.SizeStr, init.FontDirStr, init.Size) +} + +// New returns a pointer to a new Fpdf instance. Its methods are subsequently +// called to produce a single PDF document. +// +// orientationStr specifies the default page orientation. For portrait mode, +// specify "P" or "Portrait". For landscape mode, specify "L" or "Landscape". +// An empty string will be replaced with "P". +// +// unitStr specifies the unit of length used in size parameters for elements +// other than fonts, which are always measured in points. Specify "pt" for +// point, "mm" for millimeter, "cm" for centimeter, or "in" for inch. An empty +// string will be replaced with "mm". +// +// sizeStr specifies the page size. Acceptable values are "A3", "A4", "A5", +// "Letter", or "Legal". An empty string will be replaced with "A4". +// +// fontDirStr specifies the file system location in which font resources will +// be found. An empty string is replaced with ".". This argument only needs to +// reference an actual directory if a font other than one of the core +// fonts is used. The core fonts are "courier", "helvetica" (also called +// "arial"), "times", and "zapfdingbats" (also called "symbol"). +func New(orientationStr, unitStr, sizeStr, fontDirStr string) (f *Fpdf) { + return fpdfNew(orientationStr, unitStr, sizeStr, fontDirStr, SizeType{0, 0}) +} + +// Ok returns true if no processing errors have occurred. +func (f *Fpdf) Ok() bool { + return f.err == nil +} + +// Err returns true if a processing error has occurred. +func (f *Fpdf) Err() bool { + return f.err != nil +} + +// ClearError unsets the internal Fpdf error. This method should be used with +// care, as an internal error condition usually indicates an unrecoverable +// problem with the generation of a document. It is intended to deal with cases +// in which an error is used to select an alternate form of the document. +func (f *Fpdf) ClearError() { + f.err = nil +} + +// SetErrorf sets the internal Fpdf error with formatted text to halt PDF +// generation; this may facilitate error handling by application. If an error +// condition is already set, this call is ignored. +// +// See the documentation for printing in the standard fmt package for details +// about fmtStr and args. +func (f *Fpdf) SetErrorf(fmtStr string, args ...interface{}) { + if f.err == nil { + f.err = fmt.Errorf(fmtStr, args...) + } +} + +// String satisfies the fmt.Stringer interface and summarizes the Fpdf +// instance. +func (f *Fpdf) String() string { + return "Fpdf " + cnFpdfVersion +} + +// SetError sets an error to halt PDF generation. This may facilitate error +// handling by application. See also Ok(), Err() and Error(). +func (f *Fpdf) SetError(err error) { + if f.err == nil && err != nil { + f.err = err + } +} + +// Error returns the internal Fpdf error; this will be nil if no error has occurred. +func (f *Fpdf) Error() error { + return f.err +} + +// GetPageSize returns the current page's width and height. This is the paper's +// size. To compute the size of the area being used, subtract the margins (see +// GetMargins()). +func (f *Fpdf) GetPageSize() (width, height float64) { + width = f.w + height = f.h + return +} + +// GetMargins returns the left, top, right, and bottom margins. The first three +// are set with the SetMargins() method. The bottom margin is set with the +// SetAutoPageBreak() method. +func (f *Fpdf) GetMargins() (left, top, right, bottom float64) { + left = f.lMargin + top = f.tMargin + right = f.rMargin + bottom = f.bMargin + return +} + +// SetMargins defines the left, top and right margins. By default, they equal 1 +// cm. Call this method to change them. If the value of the right margin is +// less than zero, it is set to the same as the left margin. +func (f *Fpdf) SetMargins(left, top, right float64) { + f.lMargin = left + f.tMargin = top + if right < 0 { + right = left + } + f.rMargin = right +} + +// SetLeftMargin defines the left margin. The method can be called before +// creating the first page. If the current abscissa gets out of page, it is +// brought back to the margin. +func (f *Fpdf) SetLeftMargin(margin float64) { + f.lMargin = margin + if f.page > 0 && f.x < margin { + f.x = margin + } +} + +// GetCellMargin returns the cell margin. This is the amount of space before +// and after the text within a cell that's left blank, and is in units passed +// to New(). It defaults to 1mm. +func (f *Fpdf) GetCellMargin() float64 { + return f.cMargin +} + +// SetCellMargin sets the cell margin. This is the amount of space before and +// after the text within a cell that's left blank, and is in units passed to +// New(). +func (f *Fpdf) SetCellMargin(margin float64) { + f.cMargin = margin +} + +// SetFontLocation sets the location in the file system of the font and font +// definition files. +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()). +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 +// is empty, so you have to provide an appropriate function if you want page +// headers. fnc will typically be a closure that has access to the Fpdf +// instance and other document generation variables. +// +// This method is demonstrated in the example for AddPage(). +func (f *Fpdf) SetHeaderFunc(fnc func()) { + f.headerFnc = fnc +} + +// SetFooterFunc sets the function that lets the application render the page +// footer. The specified function is automatically called by AddPage() and +// Close() and should not be called directly by the application. The +// implementation in Fpdf is empty, so you have to provide an appropriate +// function if you want page footers. fnc will typically be a closure that has +// access to the Fpdf instance and other document generation variables. +// +// This method is demonstrated in the example for AddPage(). +func (f *Fpdf) SetFooterFunc(fnc func()) { + f.footerFnc = fnc +} + +// SetTopMargin defines the top margin. The method can be called before +// creating the first page. +func (f *Fpdf) SetTopMargin(margin float64) { + f.tMargin = margin +} + +// SetRightMargin defines the right margin. The method can be called before +// creating the first page. +func (f *Fpdf) SetRightMargin(margin float64) { + f.rMargin = margin +} + +// SetAutoPageBreak enables or disables the automatic page breaking mode. When +// enabling, the second parameter is the distance from the bottom of the page +// that defines the triggering limit. By default, the mode is on and the margin +// is 2 cm. +func (f *Fpdf) SetAutoPageBreak(auto bool, margin float64) { + f.autoPageBreak = auto + f.bMargin = margin + f.pageBreakTrigger = f.h - margin +} + +// SetDisplayMode sets advisory display directives for the document viewer. +// Pages can be displayed entirely on screen, occupy the full width of the +// window, use real size, be scaled by a specific zooming factor or use viewer +// default (configured in the Preferences menu of Adobe Reader). The page +// layout can be specified so that pages are displayed individually or in +// pairs. +// +// zoomStr can be "fullpage" to display the entire page on screen, "fullwidth" +// to use maximum width of window, "real" to use real size (equivalent to 100% +// zoom) or "default" to use viewer default mode. +// +// layoutStr can be "single" (or "SinglePage") to display one page at once, +// "continuous" (or "OneColumn") to display pages continuously, "two" (or +// "TwoColumnLeft") to display two pages on two columns with odd-numbered pages +// on the left, or "TwoColumnRight" to display two pages on two columns with +// odd-numbered pages on the right, or "TwoPageLeft" to display pages two at a +// time with odd-numbered pages on the left, or "TwoPageRight" to display pages +// two at a time with odd-numbered pages on the right, or "default" to use +// viewer default mode. +func (f *Fpdf) SetDisplayMode(zoomStr, layoutStr string) { + if f.err != nil { + return + } + if layoutStr == "" { + layoutStr = "default" + } + switch zoomStr { + case "fullpage", "fullwidth", "real", "default": + f.zoomMode = zoomStr + default: + f.err = fmt.Errorf("incorrect zoom display mode: %s", zoomStr) + return + } + switch layoutStr { + case "single", "continuous", "two", "default", "SinglePage", "OneColumn", + "TwoColumnLeft", "TwoColumnRight", "TwoPageLeft", "TwoPageRight": + f.layoutMode = layoutStr + default: + f.err = fmt.Errorf("incorrect layout display mode: %s", layoutStr) + return + } +} + +// SetDefaultCompression controls the default setting of the internal +// compression flag. See SetCompression() for more details. Compression is on +// by default. +func SetDefaultCompression(compress bool) { + gl.noCompress = !compress +} + +// SetCompression activates or deactivates page compression with zlib. When +// activated, the internal representation of each page is compressed, which +// leads to a compression ratio of about 2 for the resulting document. +// Compression is on by default. +func (f *Fpdf) SetCompression(compress bool) { + f.compress = compress +} + +// SetTitle defines the title of the document. isUTF8 indicates if the string +// is encoded in ISO-8859-1 (false) or UTF-8 (true). +func (f *Fpdf) SetTitle(titleStr string, isUTF8 bool) { + if isUTF8 { + titleStr = utf8toutf16(titleStr) + } + f.title = titleStr +} + +// SetSubject defines the subject of the document. isUTF8 indicates if the +// string is encoded in ISO-8859-1 (false) or UTF-8 (true). +func (f *Fpdf) SetSubject(subjectStr string, isUTF8 bool) { + if isUTF8 { + subjectStr = utf8toutf16(subjectStr) + } + f.subject = subjectStr +} + +// SetAuthor defines the author of the document. isUTF8 indicates if the string +// is encoded in ISO-8859-1 (false) or UTF-8 (true). +func (f *Fpdf) SetAuthor(authorStr string, isUTF8 bool) { + if isUTF8 { + authorStr = utf8toutf16(authorStr) + } + f.author = authorStr +} + +// SetKeywords defines the keywords of the document. keywordStr is a +// space-delimited string, for example "invoice August". isUTF8 indicates if +// the string is encoded +func (f *Fpdf) SetKeywords(keywordsStr string, isUTF8 bool) { + if isUTF8 { + keywordsStr = utf8toutf16(keywordsStr) + } + f.keywords = keywordsStr +} + +// SetCreator defines the creator of the document. isUTF8 indicates if the +// string is encoded in ISO-8859-1 (false) or UTF-8 (true). +func (f *Fpdf) SetCreator(creatorStr string, isUTF8 bool) { + if isUTF8 { + creatorStr = utf8toutf16(creatorStr) + } + f.creator = creatorStr +} + +// AliasNbPages defines an alias for the total number of pages. It will be +// substituted as the document is closed. An empty string is replaced with the +// string "{nb}". +// +// See the example for AddPage() for a demonstration of this method. +func (f *Fpdf) AliasNbPages(aliasStr string) { + if aliasStr == "" { + aliasStr = "{nb}" + } + f.aliasNbPagesStr = aliasStr +} + +// Begin document +func (f *Fpdf) open() { + f.state = 1 +} + +// Close terminates the PDF document. It is not necessary to call this method +// explicitly because Output(), OutputAndClose() and OutputFileAndClose() do it +// automatically. If the document contains no page, AddPage() is called to +// prevent the generation of an invalid document. +func (f *Fpdf) Close() { + if f.err == nil { + if f.clipNest > 0 { + f.err = fmt.Errorf("clip procedure must be explicitly ended") + } else if f.transformNest > 0 { + f.err = fmt.Errorf("transformation procedure must be explicitly ended") + } + } + if f.err != nil { + return + } + if f.state == 3 { + return + } + if f.page == 0 { + f.AddPage() + if f.err != nil { + return + } + } + // Page footer + if f.footerFnc != nil { + f.inFooter = true + f.footerFnc() + f.inFooter = false + } + // Close page + f.endpage() + // Close document + f.enddoc() + return +} + +// PageSize returns the width and height of the specified page in the units +// established in New(). These return values are followed by the unit of +// measure itself. If pageNum is zero or otherwise out of bounds, it returns +// the default page size, that is, the size of the page that would be added by +// AddPage(). +func (f *Fpdf) PageSize(pageNum int) (wd, ht float64, unitStr string) { + sz, ok := f.pageSizes[pageNum] + if ok { + sz.Wd, sz.Ht = sz.Wd/f.k, sz.Ht/f.k + } else { + sz = f.defPageSize // user units + } + return sz.Wd, sz.Ht, f.unitStr +} + +// AddPageFormat adds a new page with non-default orientation or size. See +// AddPage() for more details. +// +// See New() for a description of orientationStr. +// +// size specifies the size of the new page in the units established in New(). +// +// The PageSize() example demonstrates this method. +func (f *Fpdf) AddPageFormat(orientationStr string, size SizeType) { + if f.err != nil { + return + } + if f.state == 0 { + f.open() + } + familyStr := f.fontFamily + style := f.fontStyle + if f.underline { + style += "U" + } + fontsize := f.fontSizePt + lw := f.lineWidth + dc := f.color.draw + fc := f.color.fill + tc := f.color.text + cf := f.colorFlag + if f.page > 0 { + // Page footer + if f.footerFnc != nil { + f.inFooter = true + f.footerFnc() + f.inFooter = false + } + // Close page + f.endpage() + } + // Start new page + f.beginpage(orientationStr, size) + // Set line cap style to current value + // f.out("2 J") + f.outf("%d J", f.capStyle) + // Set line join style to current value + f.outf("%d j", f.joinStyle) + // 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) + if f.err != nil { + return + } + } + // Set colors + f.color.draw = dc + if dc.str != "0 G" { + f.out(dc.str) + } + f.color.fill = fc + if fc.str != "0 g" { + f.out(fc.str) + } + f.color.text = tc + f.colorFlag = cf + // Page header + if f.headerFnc != nil { + f.inHeader = true + f.headerFnc() + f.inHeader = false + } + // Restore line width + if f.lineWidth != lw { + f.lineWidth = lw + f.outf("%.2f w", lw*f.k) + } + // Restore font + if familyStr != "" { + f.SetFont(familyStr, style, fontsize) + if f.err != nil { + return + } + } + // Restore colors + if f.color.draw.str != dc.str { + f.color.draw = dc + f.out(dc.str) + } + if f.color.fill.str != fc.str { + f.color.fill = fc + f.out(fc.str) + } + f.color.text = tc + f.colorFlag = cf + return +} + +// AddPage adds a new page to the document. If a page is already present, the +// Footer() method is called first to output the footer. Then the page is +// added, the current position set to the top-left corner according to the left +// and top margins, and Header() is called to display the header. +// +// The font which was set before calling is automatically restored. There is no +// need to call SetFont() again if you want to continue with the same font. The +// same is true for colors and line width. +// +// The origin of the coordinate system is at the top-left corner and increasing +// ordinates go downwards. +// +// See AddPageFormat() for a version of this method that allows the page size +// and orientation to be different than the default. +func (f *Fpdf) AddPage() { + if f.err != nil { + return + } + // dbg("AddPage") + f.AddPageFormat(f.defOrientation, f.defPageSize) + return +} + +// PageNo returns the current page number. +// +// See the example for AddPage() for a demonstration of this method. +func (f *Fpdf) PageNo() int { + return f.page +} + +type clrType struct { + r, g, b float64 + ir, ig, ib int + gray bool + str string +} + +func colorComp(v int) (int, float64) { + if v < 0 { + v = 0 + } else if v > 255 { + v = 255 + } + return v, float64(v) / 255.0 +} + +func colorValue(r, g, b int, grayStr, fullStr string) (clr clrType) { + clr.ir, clr.r = colorComp(r) + clr.ig, clr.g = colorComp(g) + clr.ib, clr.b = colorComp(b) + clr.gray = clr.ir == clr.ig && clr.r == clr.b + if len(grayStr) > 0 { + if clr.gray { + clr.str = sprintf("%.3f %s", clr.r, grayStr) + } else { + clr.str = sprintf("%.3f %.3f %.3f %s", clr.r, clr.g, clr.b, fullStr) + } + } else { + clr.str = sprintf("%.3f %.3f %.3f", clr.r, clr.g, clr.b) + } + return +} + +// SetDrawColor defines the color used for all drawing operations (lines, +// rectangles and cell borders). It is expressed in RGB components (0 - 255). +// The method can be called before the first page is created. The value is +// retained from page to page. +func (f *Fpdf) SetDrawColor(r, g, b int) { + f.color.draw = colorValue(r, g, b, "G", "RG") + if f.page > 0 { + f.out(f.color.draw.str) + } +} + +// GetDrawColor returns the current draw color as RGB components (0 - 255). +func (f *Fpdf) GetDrawColor() (int, int, int) { + return f.color.draw.ir, f.color.draw.ig, f.color.draw.ib +} + +// SetFillColor defines the color used for all filling operations (filled +// rectangles and cell backgrounds). It is expressed in RGB components (0 +// -255). The method can be called before the first page is created and the +// value is retained from page to page. +func (f *Fpdf) SetFillColor(r, g, b int) { + f.color.fill = colorValue(r, g, b, "g", "rg") + f.colorFlag = f.color.fill.str != f.color.text.str + if f.page > 0 { + f.out(f.color.fill.str) + } +} + +// GetFillColor returns the current fill color as RGB components (0 - 255). +func (f *Fpdf) GetFillColor() (int, int, int) { + return f.color.fill.ir, f.color.fill.ig, f.color.fill.ib +} + +// SetTextColor defines the color used for text. It is expressed in RGB +// components (0 - 255). The method can be called before the first page is +// created. The value is retained from page to page. +func (f *Fpdf) SetTextColor(r, g, b int) { + f.color.text = colorValue(r, g, b, "g", "rg") + f.colorFlag = f.color.fill.str != f.color.text.str +} + +// GetTextColor returns the current text color as RGB components (0 - 255). +func (f *Fpdf) GetTextColor() (int, int, int) { + return f.color.text.ir, f.color.text.ig, f.color.text.ib +} + +// GetStringWidth returns the length of a string in user units. A font must be +// currently selected. +func (f *Fpdf) GetStringWidth(s string) float64 { + if f.err != nil { + return 0 + } + w := 0 + for _, ch := range []byte(s) { + if ch == 0 { + break + } + w += f.currentFont.Cw[ch] + } + return float64(w) * f.fontSize / 1000 +} + +// SetLineWidth defines the line width. By default, the value equals 0.2 mm. +// The method can be called before the first page is created. The value is +// retained from page to page. +func (f *Fpdf) SetLineWidth(width float64) { + f.lineWidth = width + if f.page > 0 { + f.outf("%.2f w", width*f.k) + } +} + +// GetLineWidth returns the current line thickness. +func (f *Fpdf) GetLineWidth() float64 { + return f.lineWidth +} + +// SetLineCapStyle defines the line cap style. styleStr should be "butt", +// "round" or "square". A square style projects from the end of the line. The +// method can be called before the first page is created. The value is +// retained from page to page. +func (f *Fpdf) SetLineCapStyle(styleStr string) { + var capStyle int + switch styleStr { + case "round": + capStyle = 1 + case "square": + capStyle = 2 + default: + capStyle = 0 + } + if capStyle != f.capStyle { + f.capStyle = capStyle + if f.page > 0 { + f.outf("%d J", f.capStyle) + } + } +} + +// SetLineJoinStyle defines the line cap style. styleStr should be "miter", +// "round" or "bevel". The method can be called before the first page +// is created. The value is retained from page to page. +func (f *Fpdf) SetLineJoinStyle(styleStr string) { + var joinStyle int + switch styleStr { + case "round": + joinStyle = 1 + case "bevel": + joinStyle = 2 + default: + joinStyle = 0 + } + if joinStyle != f.joinStyle { + f.joinStyle = joinStyle + if f.page > 0 { + f.outf("%d j", f.joinStyle) + } + } +} + +// 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. +// +// The Beziergon() example demonstrates this method. +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) { + f.outf("%.2f %.2f m %.2f %.2f l S", x1*f.k, (f.h-y1)*f.k, x2*f.k, (f.h-y2)*f.k) +} + +// fillDrawOp corrects path painting operators +func fillDrawOp(styleStr string) (opStr string) { + switch strings.ToUpper(styleStr) { + case "", "D": + // Stroke the path. + opStr = "S" + case "F": + // fill the path, using the nonzero winding number rule + opStr = "f" + case "F*": + // fill the path, using the even-odd rule + opStr = "f*" + case "FD", "DF": + // fill and then stroke the path, using the nonzero winding number rule + opStr = "B" + case "FD*", "DF*": + // fill and then stroke the path, using the even-odd rule + opStr = "B*" + default: + opStr = styleStr + } + return +} + +// Rect outputs a rectangle of width w and height h with the upper left corner +// positioned at point (x, y). +// +// It can be drawn (border only), filled (with no border) or both. styleStr can +// be "F" for filled, "D" for outlined only, or "DF" or "FD" for outlined and +// filled. An empty string will be replaced with "D". Drawing uses the current +// draw color and line width centered on the rectangle's perimeter. Filling +// uses the current fill color. +func (f *Fpdf) Rect(x, y, w, h float64, styleStr string) { + f.outf("%.2f %.2f %.2f %.2f re %s", x*f.k, (f.h-y)*f.k, w*f.k, -h*f.k, fillDrawOp(styleStr)) +} + +// Circle draws a circle centered on point (x, y) with radius r. +// +// styleStr can be "F" for filled, "D" for outlined only, or "DF" or "FD" for +// outlined and filled. An empty string will be replaced with "D". Drawing uses +// the current draw color and line width centered on the circle's perimeter. +// Filling uses the current fill color. +func (f *Fpdf) Circle(x, y, r float64, styleStr string) { + f.Ellipse(x, y, r, r, 0, styleStr) +} + +// Ellipse draws an ellipse centered at point (x, y). rx and ry specify its +// horizontal and vertical radii. +// +// degRotate specifies the counter-clockwise angle in degrees that the ellipse +// will be rotated. +// +// styleStr can be "F" for filled, "D" for outlined only, or "DF" or "FD" for +// outlined and filled. An empty string will be replaced with "D". Drawing uses +// the current draw color and line width centered on the ellipse's perimeter. +// Filling uses the current fill color. +// +// The Circle() example demonstrates this method. +func (f *Fpdf) Ellipse(x, y, rx, ry, degRotate float64, styleStr string) { + f.arc(x, y, rx, ry, degRotate, 0, 360, styleStr, false) +} + +// Polygon draws a closed figure defined by a series of vertices specified by +// points. The x and y fields of the points use the units established in New(). +// The last point in the slice will be implicitly joined to the first to close +// the polygon. +// +// styleStr can be "F" for filled, "D" for outlined only, or "DF" or "FD" for +// outlined and filled. An empty string will be replaced with "D". Drawing uses +// the current draw color and line width centered on the ellipse's perimeter. +// Filling uses the current fill color. +func (f *Fpdf) Polygon(points []PointType, styleStr string) { + if len(points) > 2 { + for j, pt := range points { + if j == 0 { + f.point(pt.X, pt.Y) + } else { + f.outf("%.5f %.5f l ", pt.X*f.k, (f.h-pt.Y)*f.k) + } + } + f.outf("%.5f %.5f l ", points[0].X*f.k, (f.h-points[0].Y)*f.k) + f.DrawPath(styleStr) + } +} + +// Beziergon draws a closed figure defined by a series of cubic Bézier curve +// segments. The first point in the slice defines the starting point of the +// figure. Each three following points p1, p2, p3 represent a curve segment to +// the point p3 using p1 and p2 as the Bézier control points. +// +// The x and y fields of the points use the units established in New(). +// +// styleStr can be "F" for filled, "D" for outlined only, or "DF" or "FD" for +// outlined and filled. An empty string will be replaced with "D". Drawing uses +// the current draw color and line width centered on the ellipse's perimeter. +// Filling uses the current fill color. +func (f *Fpdf) Beziergon(points []PointType, styleStr string) { + + // Thanks, Robert Lillack, for contributing this function. + + if len(points) < 4 { + return + } + f.point(points[0].XY()) + + points = points[1:] + for len(points) >= 3 { + cx0, cy0 := points[0].XY() + cx1, cy1 := points[1].XY() + x1, y1 := points[2].XY() + f.curve(cx0, cy0, cx1, cy1, x1, y1) + points = points[3:] + } + + f.DrawPath(styleStr) +} + +// Outputs current point +func (f *Fpdf) point(x, y float64) { + f.outf("%.2f %.2f m", x*f.k, (f.h-y)*f.k) +} + +// Outputs a single cubic Bézier curve segment from current point +func (f *Fpdf) curve(cx0, cy0, cx1, cy1, x, y float64) { + // Thanks, Robert Lillack, for straightening this out + f.outf("%.5f %.5f %.5f %.5f %.5f %.5f c", cx0*f.k, (f.h-cy0)*f.k, cx1*f.k, + (f.h-cy1)*f.k, x*f.k, (f.h-y)*f.k) +} + +// Curve draws a single-segment quadratic Bézier curve. The curve starts at +// the point (x0, y0) and ends at the point (x1, y1). The control point (cx, +// cy) specifies the curvature. At the start point, the curve is tangent to the +// straight line between the start point and the control point. At the end +// point, the curve is tangent to the straight line between the end point and +// the control point. +// +// styleStr can be "F" for filled, "D" for outlined only, or "DF" or "FD" for +// outlined and filled. An empty string will be replaced with "D". Drawing uses +// the current draw color, line width, and cap style centered on the curve's +// path. Filling uses the current fill color. +// +// The Circle() example demonstrates this method. +func (f *Fpdf) Curve(x0, y0, cx, cy, x1, y1 float64, styleStr string) { + f.point(x0, y0) + f.outf("%.5f %.5f %.5f %.5f v %s", cx*f.k, (f.h-cy)*f.k, x1*f.k, (f.h-y1)*f.k, + fillDrawOp(styleStr)) +} + +// CurveCubic draws a single-segment cubic Bézier curve. This routine performs +// the same function as CurveBezierCubic() but has a nonstandard argument order. +// It is retained to preserve backward compatibility. +func (f *Fpdf) CurveCubic(x0, y0, cx0, cy0, x1, y1, cx1, cy1 float64, styleStr string) { + // f.point(x0, y0) + // f.outf("%.5f %.5f %.5f %.5f %.5f %.5f c %s", cx0*f.k, (f.h-cy0)*f.k, + // cx1*f.k, (f.h-cy1)*f.k, x1*f.k, (f.h-y1)*f.k, fillDrawOp(styleStr)) + f.CurveBezierCubic(x0, y0, cx0, cy0, cx1, cy1, x1, y1, styleStr) +} + +// CurveBezierCubic draws a single-segment cubic Bézier curve. The curve starts at +// the point (x0, y0) and ends at the point (x1, y1). The control points (cx0, +// cy0) and (cx1, cy1) specify the curvature. At the start point, the curve is +// tangent to the straight line between the start point and the control point +// (cx0, cy0). At the end point, the curve is tangent to the straight line +// between the end point and the control point (cx1, cy1). +// +// styleStr can be "F" for filled, "D" for outlined only, or "DF" or "FD" for +// outlined and filled. An empty string will be replaced with "D". Drawing uses +// the current draw color, line width, and cap style centered on the curve's +// path. Filling uses the current fill color. +// +// This routine performs the same function as CurveCubic() but uses standard +// argument order. +// +// The Circle() example demonstrates this method. +func (f *Fpdf) CurveBezierCubic(x0, y0, cx0, cy0, cx1, cy1, x1, y1 float64, styleStr string) { + f.point(x0, y0) + f.outf("%.5f %.5f %.5f %.5f %.5f %.5f c %s", cx0*f.k, (f.h-cy0)*f.k, + cx1*f.k, (f.h-cy1)*f.k, x1*f.k, (f.h-y1)*f.k, fillDrawOp(styleStr)) +} + +// Arc draws an elliptical arc centered at point (x, y). rx and ry specify its +// horizontal and vertical radii. +// +// degRotate specifies the angle that the arc will be rotated. degStart and +// degEnd specify the starting and ending angle of the arc. All angles are +// specified in degrees and measured counter-clockwise from the 3 o'clock +// position. +// +// styleStr can be "F" for filled, "D" for outlined only, or "DF" or "FD" for +// outlined and filled. An empty string will be replaced with "D". Drawing uses +// the current draw color, line width, and cap style centered on the arc's +// path. Filling uses the current fill color. +// +// The Circle() example demonstrates this method. +func (f *Fpdf) Arc(x, y, rx, ry, degRotate, degStart, degEnd float64, styleStr string) { + f.arc(x, y, rx, ry, degRotate, degStart, degEnd, styleStr, false) +} + +// GetAlpha returns the alpha blending channel, which consists of the +// alpha transparency value and the blend mode. See SetAlpha for more +// details. +func (f *Fpdf) GetAlpha() (alpha float64, blendModeStr string) { + return f.alpha, f.blendMode +} + +// SetAlpha sets the alpha blending channel. The blending effect applies to +// text, drawings and images. +// +// alpha must be a value between 0.0 (fully transparent) to 1.0 (fully opaque). +// Values outside of this range result in an error. +// +// blendModeStr must be one of "Normal", "Multiply", "Screen", "Overlay", +// "Darken", "Lighten", "ColorDodge", "ColorBurn","HardLight", "SoftLight", +// "Difference", "Exclusion", "Hue", "Saturation", "Color", or "Luminosity". An +// empty string is replaced with "Normal". +// +// To reset normal rendering after applying a blending mode, call this method +// with alpha set to 1.0 and blendModeStr set to "Normal". +func (f *Fpdf) SetAlpha(alpha float64, blendModeStr string) { + if f.err != nil || (alpha == f.alpha && blendModeStr == f.blendMode) { + return + } + var bl blendModeType + switch blendModeStr { + case "Normal", "Multiply", "Screen", "Overlay", + "Darken", "Lighten", "ColorDodge", "ColorBurn", "HardLight", "SoftLight", + "Difference", "Exclusion", "Hue", "Saturation", "Color", "Luminosity": + bl.modeStr = blendModeStr + case "": + bl.modeStr = "Normal" + default: + f.err = fmt.Errorf("unrecognized blend mode \"%s\"", blendModeStr) + return + } + if alpha < 0.0 || alpha > 1.0 { + f.err = fmt.Errorf("alpha value (0.0 - 1.0) is out of range: %.3f", alpha) + return + } + f.alpha = alpha + f.blendMode = blendModeStr + alphaStr := sprintf("%.3f", alpha) + keyStr := sprintf("%s %s", alphaStr, blendModeStr) + pos, ok := f.blendMap[keyStr] + if !ok { + pos = len(f.blendList) // at least 1 + f.blendList = append(f.blendList, blendModeType{alphaStr, alphaStr, blendModeStr, 0}) + f.blendMap[keyStr] = pos + } + f.outf("/GS%d gs", pos) +} + +func (f *Fpdf) gradientClipStart(x, y, w, h float64) { + // Save current graphic state and set clipping area + f.outf("q %.2f %.2f %.2f %.2f re W n", x*f.k, (f.h-y)*f.k, w*f.k, -h*f.k) + // Set up transformation matrix for gradient + f.outf("%.5f 0 0 %.5f %.5f %.5f cm", w*f.k, h*f.k, x*f.k, (f.h-(y+h))*f.k) +} + +func (f *Fpdf) gradientClipEnd() { + // Restore previous graphic state + f.out("Q") +} + +func (f *Fpdf) gradient(tp int, r1, g1, b1 int, r2, g2, b2 int, x1, y1 float64, x2, y2 float64, r float64) { + pos := len(f.gradientList) + clr1 := colorValue(r1, g1, b1, "", "") + clr2 := colorValue(r2, g2, b2, "", "") + f.gradientList = append(f.gradientList, gradientType{tp, clr1.str, clr2.str, + x1, y1, x2, y2, r, 0}) + f.outf("/Sh%d sh", pos) +} + +// LinearGradient draws a rectangular area with a blending of one color to +// another. The rectangle is of width w and height h. Its upper left corner is +// positioned at point (x, y). +// +// Each color is specified with three component values, one each for red, green +// and blue. The values range from 0 to 255. The first color is specified by +// (r1, g1, b1) and the second color by (r2, g2, b2). +// +// The blending is controlled with a gradient vector that uses normalized +// coordinates in which the lower left corner is position (0, 0) and the upper +// right corner is (1, 1). The vector's origin and destination are specified by +// the points (x1, y1) and (x2, y2). In a linear gradient, blending occurs +// perpendicularly to the vector. The vector does not necessarily need to be +// anchored on the rectangle edge. Color 1 is used up to the origin of the +// vector and color 2 is used beyond the vector's end point. Between the points +// the colors are gradually blended. +func (f *Fpdf) LinearGradient(x, y, w, h float64, r1, g1, b1 int, r2, g2, b2 int, x1, y1, x2, y2 float64) { + f.gradientClipStart(x, y, w, h) + f.gradient(2, r1, g1, b1, r2, g2, b2, x1, y1, x2, y2, 0) + f.gradientClipEnd() +} + +// RadialGradient draws a rectangular area with a blending of one color to +// another. The rectangle is of width w and height h. Its upper left corner is +// positioned at point (x, y). +// +// Each color is specified with three component values, one each for red, green +// and blue. The values range from 0 to 255. The first color is specified by +// (r1, g1, b1) and the second color by (r2, g2, b2). +// +// The blending is controlled with a point and a circle, both specified with +// normalized coordinates in which the lower left corner of the rendered +// rectangle is position (0, 0) and the upper right corner is (1, 1). Color 1 +// begins at the origin point specified by (x1, y1). Color 2 begins at the +// circle specified by the center point (x2, y2) and radius r. Colors are +// gradually blended from the origin to the circle. The origin and the circle's +// center do not necessarily have to coincide, but the origin must be within +// the circle to avoid rendering problems. +// +// The LinearGradient() example demonstrates this method. +func (f *Fpdf) RadialGradient(x, y, w, h float64, r1, g1, b1 int, r2, g2, b2 int, x1, y1, x2, y2, r float64) { + f.gradientClipStart(x, y, w, h) + f.gradient(3, r1, g1, b1, r2, g2, b2, x1, y1, x2, y2, r) + f.gradientClipEnd() +} + +// ClipRect begins a rectangular clipping operation. The rectangle is of width +// w and height h. Its upper left corner is positioned at point (x, y). outline +// is true to draw a border with the current draw color and line width centered +// on the rectangle's perimeter. Only the outer half of the border will be +// shown. After calling this method, all rendering operations (for example, +// Image(), LinearGradient(), etc) will be clipped by the specified rectangle. +// Call ClipEnd() to restore unclipped operations. +// +// This ClipText() example demonstrates this method. +func (f *Fpdf) ClipRect(x, y, w, h float64, outline bool) { + f.clipNest++ + f.outf("q %.2f %.2f %.2f %.2f re W %s", x*f.k, (f.h-y)*f.k, w*f.k, -h*f.k, strIf(outline, "S", "n")) +} + +// ClipText begins a clipping operation in which rendering is confined to the +// character string specified by txtStr. The origin (x, y) is on the left of +// the first character at the baseline. The current font is used. outline is +// true to draw a border with the current draw color and line width centered on +// the perimeters of the text characters. Only the outer half of the border +// will be shown. After calling this method, all rendering operations (for +// example, Image(), LinearGradient(), etc) will be clipped. Call ClipEnd() to +// restore unclipped operations. +func (f *Fpdf) ClipText(x, y float64, txtStr string, outline bool) { + f.clipNest++ + f.outf("q BT %.5f %.5f Td %d Tr (%s) Tj ET", x*f.k, (f.h-y)*f.k, intIf(outline, 5, 7), f.escape(txtStr)) +} + +func (f *Fpdf) clipArc(x1, y1, x2, y2, x3, y3 float64) { + h := f.h + f.outf("%.5f %.5f %.5f %.5f %.5f %.5f c ", x1*f.k, (h-y1)*f.k, + x2*f.k, (h-y2)*f.k, x3*f.k, (h-y3)*f.k) +} + +// ClipRoundedRect begins a rectangular clipping operation. The rectangle is of +// width w and height h. Its upper left corner is positioned at point (x, y). +// The rounded corners of the rectangle are specified by radius r. outline is +// true to draw a border with the current draw color and line width centered on +// the rectangle's perimeter. Only the outer half of the border will be shown. +// After calling this method, all rendering operations (for example, Image(), +// LinearGradient(), etc) will be clipped by the specified rectangle. Call +// ClipEnd() to restore unclipped operations. +// +// This ClipText() example demonstrates this method. +func (f *Fpdf) ClipRoundedRect(x, y, w, h, r float64, outline bool) { + f.clipNest++ + k := f.k + hp := f.h + myArc := (4.0 / 3.0) * (math.Sqrt2 - 1.0) + f.outf("q %.5f %.5f m", (x+r)*k, (hp-y)*k) + xc := x + w - r + yc := y + r + f.outf("%.5f %.5f l", xc*k, (hp-y)*k) + f.clipArc(xc+r*myArc, yc-r, xc+r, yc-r*myArc, xc+r, yc) + xc = x + w - r + yc = y + h - r + f.outf("%.5f %.5f l", (x+w)*k, (hp-yc)*k) + f.clipArc(xc+r, yc+r*myArc, xc+r*myArc, yc+r, xc, yc+r) + xc = x + r + yc = y + h - r + f.outf("%.5f %.5f l", xc*k, (hp-(y+h))*k) + f.clipArc(xc-r*myArc, yc+r, xc-r, yc+r*myArc, xc-r, yc) + xc = x + r + yc = y + r + f.outf("%.5f %.5f l", x*k, (hp-yc)*k) + f.clipArc(xc-r, yc-r*myArc, xc-r*myArc, yc-r, xc, yc-r) + f.outf(" W %s", strIf(outline, "S", "n")) +} + +// ClipEllipse begins an elliptical clipping operation. The ellipse is centered +// at (x, y). Its horizontal and vertical radii are specified by rx and ry. +// outline is true to draw a border with the current draw color and line width +// centered on the ellipse's perimeter. Only the outer half of the border will +// be shown. After calling this method, all rendering operations (for example, +// Image(), LinearGradient(), etc) will be clipped by the specified ellipse. +// Call ClipEnd() to restore unclipped operations. +// +// This ClipText() example demonstrates this method. +func (f *Fpdf) ClipEllipse(x, y, rx, ry float64, outline bool) { + f.clipNest++ + lx := (4.0 / 3.0) * rx * (math.Sqrt2 - 1) + ly := (4.0 / 3.0) * ry * (math.Sqrt2 - 1) + k := f.k + h := f.h + f.outf("q %.5f %.5f m %.5f %.5f %.5f %.5f %.5f %.5f c", + (x+rx)*k, (h-y)*k, + (x+rx)*k, (h-(y-ly))*k, + (x+lx)*k, (h-(y-ry))*k, + x*k, (h-(y-ry))*k) + f.outf("%.5f %.5f %.5f %.5f %.5f %.5f c", + (x-lx)*k, (h-(y-ry))*k, + (x-rx)*k, (h-(y-ly))*k, + (x-rx)*k, (h-y)*k) + f.outf("%.5f %.5f %.5f %.5f %.5f %.5f c", + (x-rx)*k, (h-(y+ly))*k, + (x-lx)*k, (h-(y+ry))*k, + x*k, (h-(y+ry))*k) + f.outf("%.5f %.5f %.5f %.5f %.5f %.5f c W %s", + (x+lx)*k, (h-(y+ry))*k, + (x+rx)*k, (h-(y+ly))*k, + (x+rx)*k, (h-y)*k, + strIf(outline, "S", "n")) +} + +// ClipCircle begins a circular clipping operation. The circle is centered at +// (x, y) and has radius r. outline is true to draw a border with the current +// draw color and line width centered on the circle's perimeter. Only the outer +// half of the border will be shown. After calling this method, all rendering +// operations (for example, Image(), LinearGradient(), etc) will be clipped by +// the specified circle. Call ClipEnd() to restore unclipped operations. +// +// The ClipText() example demonstrates this method. +func (f *Fpdf) ClipCircle(x, y, r float64, outline bool) { + f.ClipEllipse(x, y, r, r, outline) +} + +// ClipPolygon begins a clipping operation within a polygon. The figure is +// defined by a series of vertices specified by points. The x and y fields of +// the points use the units established in New(). The last point in the slice +// will be implicitly joined to the first to close the polygon. outline is true +// to draw a border with the current draw color and line width centered on the +// polygon's perimeter. Only the outer half of the border will be shown. After +// calling this method, all rendering operations (for example, Image(), +// LinearGradient(), etc) will be clipped by the specified polygon. Call +// ClipEnd() to restore unclipped operations. +// +// The ClipText() example demonstrates this method. +func (f *Fpdf) ClipPolygon(points []PointType, outline bool) { + f.clipNest++ + var s fmtBuffer + h := f.h + k := f.k + s.printf("q ") + for j, pt := range points { + s.printf("%.5f %.5f %s ", pt.X*k, (h-pt.Y)*k, strIf(j == 0, "m", "l")) + } + s.printf("h W %s", strIf(outline, "S", "n")) + f.out(s.String()) +} + +// ClipEnd ends a clipping operation that was started with a call to +// ClipRect(), ClipRoundedRect(), ClipText(), ClipEllipse(), ClipCircle() or +// ClipPolygon(). Clipping operations can be nested. The document cannot be +// successfully output while a clipping operation is active. +// +// The ClipText() example demonstrates this method. +func (f *Fpdf) ClipEnd() { + if f.err == nil { + if f.clipNest > 0 { + f.clipNest-- + f.out("Q") + } else { + f.err = fmt.Errorf("error attempting to end clip operation out of sequence") + } + } +} + +// AddFont imports a TrueType, OpenType or Type1 font and makes it available. +// It is necessary to generate a font definition file first with the makefont +// utility. It is not necessary to call this function for the core PDF fonts +// (courier, helvetica, times, zapfdingbats). +// +// The JSON definition file (and the font file itself when embedding) must be +// present in the font directory. If it is not found, the error "Could not +// include font definition file" is set. +// +// family specifies the font family. The name can be chosen arbitrarily. If it +// is a standard family name, it will override the corresponding font. This +// string is used to subsequently set the font with the SetFont method. +// +// style specifies the font style. Acceptable values are (case insensitive) the +// empty string for regular style, "B" for bold, "I" for italic, or "BI" or +// "IB" for bold and italic combined. +// +// fileStr specifies the base name with ".json" extension of the font +// definition file to be added. The file will be loaded from the font directory +// specified in the call to New() or SetFontLocation(). +func (f *Fpdf) AddFont(familyStr, styleStr, fileStr string) { + if fileStr == "" { + fileStr = strings.Replace(familyStr, " ", "", -1) + strings.ToLower(styleStr) + ".json" + } + + 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 + return + } + defer file.Close() + + f.AddFontFromReader(familyStr, styleStr, file) +} + +// AddFontFromBytes imports a TrueType, OpenType or Type1 font from static +// bytes within the executable and makes it available for use in the generated +// document. +// +// family specifies the font family. The name can be chosen arbitrarily. If it +// is a standard family name, it will override the corresponding font. This +// string is used to subsequently set the font with the SetFont method. +// +// style specifies the font style. Acceptable values are (case insensitive) the +// empty string for regular style, "B" for bold, "I" for italic, or "BI" or +// "IB" for bold and italic combined. +// +// jsonFileBytes contain all bytes of JSON file. +// +// zFileBytes contain all bytes of Z file. +func (f *Fpdf) AddFontFromBytes(familyStr string, styleStr string, jsonFileBytes []byte, zFileBytes []byte) { + if f.err != nil { + return + } + + // load font key + var ok bool + fontkey := getFontKey(familyStr, styleStr) + _, ok = f.fonts[fontkey] + + if ok { + return + } + + // load font definitions + var info fontDefType + err := json.Unmarshal(jsonFileBytes, &info) + + if err != nil { + f.err = err + } + + if f.err != nil { + return + } + + // search existing encodings + info.I = len(f.fonts) + + if len(info.Diff) > 0 { + n := -1 + + for j, str := range f.diffs { + if str == info.Diff { + n = j + 1 + break + } + } + + if n < 0 { + f.diffs = append(f.diffs, info.Diff) + n = len(f.diffs) + } + + info.DiffN = n + } + + // embed font + if len(info.File) > 0 { + if info.Tp == "TrueType" { + f.fontFiles[info.File] = fontFileType{ + length1: int64(info.OriginalSize), + embedded: true, + content: zFileBytes, + } + } else { + f.fontFiles[info.File] = fontFileType{ + length1: int64(info.Size1), + length2: int64(info.Size2), + embedded: true, + content: zFileBytes, + } + } + } + + f.fonts[fontkey] = info +} + +// 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. +func (f *Fpdf) AddFontFromReader(familyStr, styleStr string, r io.Reader) { + if f.err != nil { + return + } + // dbg("Adding family [%s], style [%s]", familyStr, styleStr) + var ok bool + fontkey := getFontKey(familyStr, styleStr) + _, ok = f.fonts[fontkey] + if ok { + return + } + var info fontDefType + info = f.loadfont(r) + if f.err != nil { + return + } + info.I = len(f.fonts) + if len(info.Diff) > 0 { + // Search existing encodings + n := -1 + for j, str := range f.diffs { + if str == info.Diff { + n = j + 1 + break + } + } + if n < 0 { + f.diffs = append(f.diffs, info.Diff) + n = len(f.diffs) + } + info.DiffN = n + } + // dbg("font [%s], type [%s]", info.File, info.Tp) + if len(info.File) > 0 { + // Embedded font + if info.Tp == "TrueType" { + f.fontFiles[info.File] = fontFileType{length1: int64(info.OriginalSize)} + } else { + f.fontFiles[info.File] = fontFileType{length1: int64(info.Size1), length2: int64(info.Size2)} + } + } + f.fonts[fontkey] = info + return +} + +// GetFontDesc returns the font descriptor, which can be used for +// example to find the baseline of a font. If familyStr is empty +// current font descriptor will be returned. +// See FontDescType for documentation about the font descriptor. +// See AddFont for details about familyStr and styleStr. +func (f *Fpdf) GetFontDesc(familyStr, styleStr string) FontDescType { + if familyStr == "" { + return f.currentFont.Desc + } + return f.fonts[getFontKey(familyStr, styleStr)].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. +// +// The font can be either a standard one or a font added via the AddFont() +// method or AddFontFromReader() method. Standard fonts use the Windows +// encoding cp1252 (Western Europe). +// +// The method can be called before the first page is created and the font is +// kept from page to page. If you just wish to change the current font size, it +// is simpler to call SetFontSize(). +// +// Note: the font definition file must be accessible. An error is set if the +// file cannot be read. +// +// familyStr specifies the font family. It can be either a name defined by +// AddFont(), AddFontFromReader() or one of the standard families (case +// insensitive): "Courier" for fixed-width, "Helvetica" or "Arial" for sans +// serif, "Times" for serif, "Symbol" or "ZapfDingbats" for symbolic. +// +// styleStr can be "B" (bold), "I" (italic), "U" (underscore) or any +// combination. The default value (specified with an empty string) is regular. +// Bold and italic styles do not apply to Symbol and ZapfDingbats. +// +// size is the font size measured in points. The default value is the current +// size. If no size has been specified since the beginning of the document, the +// value taken is 12. +func (f *Fpdf) SetFont(familyStr, styleStr string, size float64) { + // dbg("SetFont x %.2f, lMargin %.2f", f.x, f.lMargin) + + if f.err != nil { + return + } + // dbg("SetFont") + var ok bool + if familyStr == "" { + familyStr = f.fontFamily + } else { + familyStr = strings.ToLower(familyStr) + } + styleStr = strings.ToUpper(styleStr) + f.underline = strings.Contains(styleStr, "U") + if f.underline { + styleStr = strings.Replace(styleStr, "U", "", -1) + } + if styleStr == "IB" { + styleStr = "BI" + } + if size == 0.0 { + size = f.fontSizePt + } + // Test if font is already selected + if f.fontFamily == familyStr && f.fontStyle == styleStr && f.fontSizePt == size { + return + } + // Test if font is already loaded + fontkey := familyStr + styleStr + _, ok = f.fonts[fontkey] + if !ok { + // Test if one of the core fonts + if familyStr == "arial" { + familyStr = "helvetica" + } + _, ok = f.coreFonts[familyStr] + if ok { + if familyStr == "symbol" { + familyStr = "zapfdingbats" + } + if familyStr == "zapfdingbats" { + styleStr = "" + } + fontkey = familyStr + styleStr + _, ok = f.fonts[fontkey] + if !ok { + rdr := f.coreFontReader(familyStr, styleStr) + if f.err == nil { + f.AddFontFromReader(familyStr, styleStr, rdr) + } + if f.err != nil { + return + } + } + } else { + f.err = fmt.Errorf("undefined font: %s %s", familyStr, styleStr) + return + } + } + // Select it + f.fontFamily = familyStr + f.fontStyle = styleStr + f.fontSizePt = size + f.fontSize = size / f.k + f.currentFont = f.fonts[fontkey] + if f.page > 0 { + f.outf("BT /F%d %.2f Tf ET", f.currentFont.I, f.fontSizePt) + } + return +} + +// SetFontSize defines the size of the current font. Size is specified in +// points (1/ 72 inch). See also SetFontUnitSize(). +func (f *Fpdf) SetFontSize(size float64) { + if f.fontSizePt == size { + return + } + f.fontSizePt = size + f.fontSize = size / f.k + if f.page > 0 { + f.outf("BT /F%d %.2f Tf ET", f.currentFont.I, f.fontSizePt) + } +} + +// SetFontUnitSize defines the size of the current font. Size is specified in +// the unit of measure specified in New(). See also SetFontSize(). +func (f *Fpdf) SetFontUnitSize(size float64) { + if f.fontSize == size { + return + } + f.fontSizePt = size * f.k + f.fontSize = size + if f.page > 0 { + f.outf("BT /F%d %.2f Tf ET", f.currentFont.I, f.fontSizePt) + } +} + +// GetFontSize returns the size of the current font in points followed by the +// size in the unit of measure specified in New(). The second value can be used +// as a line height value in drawing operations. +func (f *Fpdf) GetFontSize() (ptSize, unitSize float64) { + return f.fontSizePt, f.fontSize +} + +// AddLink creates a new internal link and returns its identifier. An internal +// link is a clickable area which directs to another place within the document. +// The identifier can then be passed to Cell(), Write(), Image() or Link(). The +// destination is defined with SetLink(). +func (f *Fpdf) AddLink() int { + f.links = append(f.links, intLinkType{}) + return len(f.links) - 1 +} + +// SetLink defines the page and position a link points to. See AddLink(). +func (f *Fpdf) SetLink(link int, y float64, page int) { + if y == -1 { + y = f.y + } + if page == -1 { + page = f.page + } + f.links[link] = intLinkType{page, y} +} + +// Add a new clickable link on current page +func (f *Fpdf) newLink(x, y, w, h float64, link int, linkStr string) { + // linkList, ok := f.pageLinks[f.page] + // if !ok { + // linkList = make([]linkType, 0, 8) + // f.pageLinks[f.page] = linkList + // } + f.pageLinks[f.page] = append(f.pageLinks[f.page], + linkType{x * f.k, f.hPt - y*f.k, w * f.k, h * f.k, link, linkStr}) +} + +// Link puts a link on a rectangular area of the page. Text or image links are +// generally put via Cell(), Write() or Image(), but this method can be useful +// for instance to define a clickable area inside an image. link is the value +// returned by AddLink(). +func (f *Fpdf) Link(x, y, w, h float64, link int) { + f.newLink(x, y, w, h, link, "") +} + +// LinkString puts a link on a rectangular area of the page. Text or image +// links are generally put via Cell(), Write() or Image(), but this method can +// be useful for instance to define a clickable area inside an image. linkStr +// is the target URL. +func (f *Fpdf) LinkString(x, y, w, h float64, linkStr string) { + f.newLink(x, y, w, h, 0, linkStr) +} + +// Bookmark sets a bookmark that will be displayed in a sidebar outline. txtStr +// is the title of the bookmark. level specifies the level of the bookmark in +// the outline; 0 is the top level, 1 is just below, and so on. y specifies the +// vertical position of the bookmark destination in the current page; -1 +// indicates the current position. +func (f *Fpdf) Bookmark(txtStr string, level int, y float64) { + if y == -1 { + y = f.y + } + f.outlines = append(f.outlines, outlineType{text: txtStr, level: level, y: y, p: f.PageNo(), prev: -1, last: -1, next: -1, first: -1}) +} + +// Text prints a character string. The origin (x, y) is on the left of the +// first character at the baseline. This method permits a string to be placed +// precisely on the page, but it is usually easier to use Cell(), MultiCell() +// or Write() which are the standard methods to print text. +func (f *Fpdf) Text(x, y float64, txtStr string) { + s := sprintf("BT %.2f %.2f Td (%s) Tj ET", x*f.k, (f.h-y)*f.k, f.escape(txtStr)) + if f.underline && txtStr != "" { + s += " " + f.dounderline(x, y, txtStr) + } + if f.colorFlag { + s = sprintf("q %s %s Q", f.color.text.str, s) + } + f.out(s) +} + +// SetAcceptPageBreakFunc allows the application to control where page breaks +// occur. +// +// fnc is an application function (typically a closure) that is called by the +// library whenever a page break condition is met. The break is issued if true +// is returned. The default implementation returns a value according to the +// mode selected by SetAutoPageBreak. The function provided should not be +// called by the application. +// +// See the example for SetLeftMargin() to see how this function can be used to +// manage multiple columns. +func (f *Fpdf) SetAcceptPageBreakFunc(fnc func() bool) { + f.acceptPageBreak = fnc +} + +// CellFormat prints a rectangular cell with optional borders, background color +// and character string. The upper-left corner of the cell corresponds to the +// current position. The text can be aligned or centered. After the call, the +// current position moves to the right or to the next line. It is possible to +// put a link on the text. +// +// If automatic page breaking is enabled and the cell goes beyond the limit, a +// page break is done before outputting. +// +// w and h specify the width and height of the cell. If w is 0, the cell +// extends up to the right margin. Specifying 0 for h will result in no output, +// but the current position will be advanced by w. +// +// txtStr specifies the text to display. +// +// borderStr specifies how the cell border will be drawn. An empty string +// indicates no border, "1" indicates a full border, and one or more of "L", +// "T", "R" and "B" indicate the left, top, right and bottom sides of the +// border. +// +// ln indicates where the current position should go after the call. Possible +// values are 0 (to the right), 1 (to the beginning of the next line), and 2 +// (below). Putting 1 is equivalent to putting 0 and calling Ln() just after. +// +// alignStr specifies how the text is to be positioned 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", "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. +// +// link is the identifier returned by AddLink() or 0 for no internal link. +// +// linkStr is a target URL or empty for no external link. A non--zero value for +// link takes precedence over linkStr. +func (f *Fpdf) CellFormat(w, h float64, txtStr string, borderStr string, ln int, alignStr string, fill bool, link int, linkStr string) { + // dbg("CellFormat. h = %.2f, borderStr = %s", h, borderStr) + if f.err != nil { + return + } + borderStr = strings.ToUpper(borderStr) + k := f.k + if f.y+h > f.pageBreakTrigger && !f.inHeader && !f.inFooter && f.acceptPageBreak() { + // Automatic page break + x := f.x + ws := f.ws + // dbg("auto page break, x %.2f, ws %.2f", x, ws) + if ws > 0 { + f.ws = 0 + f.out("0 Tw") + } + f.AddPageFormat(f.curOrientation, f.curPageSize) + if f.err != nil { + return + } + f.x = x + if ws > 0 { + f.ws = ws + f.outf("%.3f Tw", ws*k) + } + } + if w == 0 { + w = f.w - f.rMargin - f.x + } + var s fmtBuffer + if fill || borderStr == "1" { + var op string + if fill { + if borderStr == "1" { + op = "B" + // dbg("border is '1', fill") + } else { + op = "f" + // dbg("border is empty, fill") + } + } else { + // dbg("border is '1', no fill") + op = "S" + } + /// dbg("(CellFormat) f.x %.2f f.k %.2f", f.x, f.k) + s.printf("%.2f %.2f %.2f %.2f re %s ", f.x*k, (f.h-f.y)*k, w*k, -h*k, op) + } + if len(borderStr) > 0 && borderStr != "1" { + // fmt.Printf("border is '%s', no fill\n", borderStr) + x := f.x + y := f.y + left := x * k + top := (f.h - y) * k + right := (x + w) * k + bottom := (f.h - (y + h)) * k + if strings.Contains(borderStr, "L") { + s.printf("%.2f %.2f m %.2f %.2f l S ", left, top, left, bottom) + } + if strings.Contains(borderStr, "T") { + s.printf("%.2f %.2f m %.2f %.2f l S ", left, top, right, top) + } + if strings.Contains(borderStr, "R") { + s.printf("%.2f %.2f m %.2f %.2f l S ", right, top, right, bottom) + } + if strings.Contains(borderStr, "B") { + s.printf("%.2f %.2f m %.2f %.2f l S ", left, bottom, right, bottom) + } + } + if len(txtStr) > 0 { + var dx, dy float64 + // Horizontal alignment + if strings.Index(alignStr, "R") != -1 { + dx = w - f.cMargin - f.GetStringWidth(txtStr) + } else if strings.Index(alignStr, "C") != -1 { + dx = (w - f.GetStringWidth(txtStr)) / 2 + } else { + dx = f.cMargin + } + // Vertical alignment + if strings.Index(alignStr, "T") != -1 { + 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 + } + if f.colorFlag { + s.printf("q %s ", f.color.text.str) + } + txt2 := strings.Replace(txtStr, "\\", "\\\\", -1) + txt2 = strings.Replace(txt2, "(", "\\(", -1) + txt2 = strings.Replace(txt2, ")", "\\)", -1) + // if strings.Contains(txt2, "end of excerpt") { + // dbg("f.h %.2f, f.y %.2f, h %.2f, f.fontSize %.2f, k %.2f", f.h, f.y, h, f.fontSize, k) + // } + s.printf("BT %.2f %.2f Td (%s) Tj ET", (f.x+dx)*k, (f.h-(f.y+dy+.5*h+.3*f.fontSize))*k, txt2) + //BT %.2F %.2F Td (%s) Tj ET',($this->x+$dx)*$k,($this->h-($this->y+.5*$h+.3*$this->FontSize))*$k,$txt2); + if f.underline { + s.printf(" %s", f.dounderline(f.x+dx, f.y+dy+.5*h+.3*f.fontSize, txtStr)) + } + if f.colorFlag { + s.printf(" Q") + } + if link > 0 || len(linkStr) > 0 { + f.newLink(f.x+dx, f.y+dy+.5*h-.5*f.fontSize, f.GetStringWidth(txtStr), f.fontSize, link, linkStr) + } + } + str := s.String() + if len(str) > 0 { + f.out(str) + } + f.lasth = h + if ln > 0 { + // Go to next line + f.y += h + if ln == 1 { + f.x = f.lMargin + } + } else { + f.x += w + } + return +} + +// Cell is a simpler version of CellFormat with no fill, border, links or +// special alignment. +func (f *Fpdf) Cell(w, h float64, txtStr string) { + f.CellFormat(w, h, txtStr, "", 0, "L", false, 0, "") +} + +// Cellf is a simpler printf-style version of CellFormat with no fill, border, +// links or special alignment. See documentation for the fmt package for +// details on fmtStr and args. +func (f *Fpdf) Cellf(w, h float64, fmtStr string, args ...interface{}) { + f.CellFormat(w, h, sprintf(fmtStr, args...), "", 0, "L", false, 0, "") +} + +// SplitLines splits text into several lines using the current font. Each line +// has its length limited to a maximum width given by w. This function can be +// used to determine the total height of wrapped text for vertical placement +// purposes. +// +// You can use MultiCell if you want to print a text on several lines in a +// simple way. +func (f *Fpdf) SplitLines(txt []byte, w float64) [][]byte { + // Function contributed by Bruno Michel + lines := [][]byte{} + cw := &f.currentFont.Cw + wmax := int(math.Ceil((w - 2*f.cMargin) * 1000 / f.fontSize)) + s := bytes.Replace(txt, []byte("\r"), []byte{}, -1) + nb := len(s) + for nb > 0 && s[nb-1] == '\n' { + nb-- + } + s = s[0:nb] + sep := -1 + i := 0 + j := 0 + l := 0 + for i < nb { + c := s[i] + l += cw[c] + if c == ' ' || c == '\t' || c == '\n' { + sep = i + } + if c == '\n' || l > wmax { + if sep == -1 { + if i == j { + i++ + } + sep = i + } else { + i = sep + 1 + } + lines = append(lines, s[j:sep]) + sep = -1 + j = i + l = 0 + } else { + i++ + } + } + if i != j { + lines = append(lines, s[j:i]) + } + return lines +} + +// MultiCell supports printing text with line breaks. They can be automatic (as +// soon as the text reaches the right border of the cell) or explicit (via the +// \n character). As many cells as necessary are output, one below the other. +// +// Text can be aligned, centered or justified. The cell block can be framed and +// the background painted. See CellFormat() for more details. +// +// w is the width of the cells. A value of zero indicates cells that reach to +// the right margin. +// +// h indicates the line height of each cell in the unit of measure specified in New(). +func (f *Fpdf) MultiCell(w, h float64, txtStr, borderStr, alignStr string, fill bool) { + // dbg("MultiCell") + if alignStr == "" { + alignStr = "J" + } + cw := &f.currentFont.Cw + if w == 0 { + w = f.w - f.rMargin - f.x + } + wmax := (w - 2*f.cMargin) * 1000 / f.fontSize + s := strings.Replace(txtStr, "\r", "", -1) + nb := len(s) + // if nb > 0 && s[nb-1:nb] == "\n" { + if nb > 0 && []byte(s)[nb-1] == '\n' { + nb-- + s = s[0:nb] + } + // dbg("[%s]\n", s) + var b, b2 string + b = "0" + if len(borderStr) > 0 { + if borderStr == "1" { + borderStr = "LTRB" + b = "LRT" + b2 = "LR" + } else { + b2 = "" + if strings.Contains(borderStr, "L") { + b2 += "L" + } + if strings.Contains(borderStr, "R") { + b2 += "R" + } + if strings.Contains(borderStr, "T") { + b = b2 + "T" + } else { + b = b2 + } + } + } + sep := -1 + i := 0 + j := 0 + l := 0.0 + ls := 0.0 + ns := 0 + nl := 1 + for i < nb { + // Get next character + c := []byte(s)[i] + if c == '\n' { + // Explicit line break + if f.ws > 0 { + f.ws = 0 + f.out("0 Tw") + } + f.CellFormat(w, h, s[j:i], b, 2, alignStr, fill, 0, "") + i++ + sep = -1 + j = i + l = 0 + ns = 0 + nl++ + if len(borderStr) > 0 && nl == 2 { + b = b2 + } + continue + } + if c == ' ' { + sep = i + ls = l + ns++ + } + l += float64(cw[c]) + if l > wmax { + // Automatic line break + if sep == -1 { + if i == j { + i++ + } + if f.ws > 0 { + f.ws = 0 + f.out("0 Tw") + } + f.CellFormat(w, h, s[j:i], b, 2, alignStr, fill, 0, "") + } else { + if alignStr == "J" { + if ns > 1 { + f.ws = (wmax - ls) / 1000 * f.fontSize / float64(ns-1) + } else { + f.ws = 0 + } + f.outf("%.3f Tw", f.ws*f.k) + } + f.CellFormat(w, h, s[j:sep], b, 2, alignStr, fill, 0, "") + i = sep + 1 + } + sep = -1 + j = i + l = 0 + ns = 0 + nl++ + if len(borderStr) > 0 && nl == 2 { + b = b2 + } + } else { + i++ + } + } + // Last chunk + if f.ws > 0 { + f.ws = 0 + f.out("0 Tw") + } + if len(borderStr) > 0 && strings.Contains(borderStr, "B") { + b += "B" + } + f.CellFormat(w, h, s[j:i], b, 2, alignStr, fill, 0, "") + f.x = f.lMargin +} + +// Output text in flowing mode +func (f *Fpdf) write(h float64, txtStr string, link int, linkStr string) { + // dbg("Write") + cw := &f.currentFont.Cw + w := f.w - f.rMargin - f.x + wmax := (w - 2*f.cMargin) * 1000 / f.fontSize + s := strings.Replace(txtStr, "\r", "", -1) + nb := len(s) + sep := -1 + i := 0 + j := 0 + l := 0.0 + nl := 1 + for i < nb { + // Get next character + c := []byte(s)[i] + if c == '\n' { + // Explicit line break + f.CellFormat(w, h, s[j:i], "", 2, "", false, link, linkStr) + i++ + sep = -1 + j = i + l = 0.0 + if nl == 1 { + f.x = f.lMargin + w = f.w - f.rMargin - f.x + wmax = (w - 2*f.cMargin) * 1000 / f.fontSize + } + nl++ + continue + } + if c == ' ' { + sep = i + } + l += float64(cw[c]) + if l > wmax { + // Automatic line break + if sep == -1 { + if f.x > f.lMargin { + // Move to next line + f.x = f.lMargin + f.y += h + w = f.w - f.rMargin - f.x + wmax = (w - 2*f.cMargin) * 1000 / f.fontSize + i++ + nl++ + continue + } + if i == j { + i++ + } + f.CellFormat(w, h, s[j:i], "", 2, "", false, link, linkStr) + } else { + f.CellFormat(w, h, s[j:sep], "", 2, "", false, link, linkStr) + i = sep + 1 + } + sep = -1 + j = i + l = 0.0 + if nl == 1 { + f.x = f.lMargin + w = f.w - f.rMargin - f.x + wmax = (w - 2*f.cMargin) * 1000 / f.fontSize + } + nl++ + } else { + i++ + } + } + // Last chunk + if i != j { + f.CellFormat(l/1000*f.fontSize, h, s[j:], "", 0, "", false, link, linkStr) + } +} + +// Write prints text from the current position. When the right margin is +// reached (or the \n character is met) a line break occurs and text continues +// from the left margin. Upon method exit, the current position is left just at +// the end of the text. +// +// It is possible to put a link on the text. +// +// h indicates the line height in the unit of measure specified in New(). +func (f *Fpdf) Write(h float64, txtStr string) { + f.write(h, txtStr, 0, "") +} + +// Writef is like Write but uses printf-style formatting. See the documentation +// for package fmt for more details on fmtStr and args. +func (f *Fpdf) Writef(h float64, fmtStr string, args ...interface{}) { + f.write(h, sprintf(fmtStr, args...), 0, "") +} + +// WriteLinkString writes text that when clicked launches an external URL. See +// Write() for argument details. +func (f *Fpdf) WriteLinkString(h float64, displayStr, targetStr string) { + f.write(h, displayStr, 0, targetStr) +} + +// WriteLinkID writes text that when clicked jumps to another location in the +// PDF. linkID is an identifier returned by AddLink(). See Write() for argument +// details. +func (f *Fpdf) WriteLinkID(h float64, displayStr string, linkID int) { + f.write(h, displayStr, linkID, "") +} + +// WriteAligned is an implementation of Write that makes it possible to align +// text. +// +// width indicates the width of the box the text will be drawn in. This is in +// the unit of measure specified in New(). If it is set to 0, the bounding box +//of the page will be taken (pageWidth - leftMargin - rightMargin). +// +// lineHeight indicates the line height in the unit of measure specified in +// New(). +// +// alignStr sees to horizontal alignment of the given textStr. The options are +// "L", "C" and "R" (Left, Center, Right). The default is "L". +func (f *Fpdf) WriteAligned(width, lineHeight float64, textStr, alignStr string) { + lMargin, _, rMargin, _ := f.GetMargins() + + if width == 0 { + pageWidth, _ := f.GetPageSize() + width = pageWidth - (lMargin + rMargin) + } + + lines := f.SplitLines([]byte(textStr), width) + + for _, lineBt := range lines { + lineStr := string(lineBt[:]) + lineWidth := f.GetStringWidth(lineStr) + + switch alignStr { + case "C": + f.SetLeftMargin(lMargin + ((width - lineWidth) / 2)) + f.Write(lineHeight, lineStr) + f.SetLeftMargin(lMargin) + case "R": + f.SetLeftMargin(lMargin + (width - lineWidth) - rMargin) + f.Write(lineHeight, lineStr) + f.SetLeftMargin(lMargin) + default: + f.Write(lineHeight, lineStr) + } + } +} + +// Ln performs a line break. The current abscissa goes back to the left margin +// and the ordinate increases by the amount passed in parameter. A negative +// value of h indicates the height of the last printed cell. +// +// This method is demonstrated in the example for MultiCell. +func (f *Fpdf) Ln(h float64) { + f.x = f.lMargin + if h < 0 { + f.y += f.lasth + } else { + f.y += h + } +} + +// ImageTypeFromMime returns the image type used in various image-related +// functions (for example, Image()) that is associated with the specified MIME +// type. For example, "jpg" is returned if mimeStr is "image/jpeg". An error is +// set if the specified MIME type is not supported. +func (f *Fpdf) ImageTypeFromMime(mimeStr string) (tp string) { + switch mimeStr { + case "image/png": + tp = "png" + case "image/jpg": + tp = "jpg" + case "image/jpeg": + tp = "jpg" + case "image/gif": + tp = "gif" + default: + f.SetErrorf("unsupported image type: %s", mimeStr) + } + return +} + +func (f *Fpdf) imageOut(info *ImageInfoType, x, y, w, h float64, flow bool, link int, linkStr string) { + // Automatic width and height calculation if needed + if w == 0 && h == 0 { + // Put image at 96 dpi + w = -96 + h = -96 + } + if w == -1 { + // Set image width to whatever value for dpi we read + // from the image or that was set manually + w = -info.dpi + } + if h == -1 { + // Set image height to whatever value for dpi we read + // from the image or that was set manually + h = -info.dpi + } + if w < 0 { + w = -info.w * 72.0 / w / f.k + } + if h < 0 { + h = -info.h * 72.0 / h / f.k + } + if w == 0 { + w = h * info.w / info.h + } + if h == 0 { + h = w * info.h / info.w + } + // Flowing mode + if flow { + if f.y+h > f.pageBreakTrigger && !f.inHeader && !f.inFooter && f.acceptPageBreak() { + // Automatic page break + x2 := f.x + f.AddPageFormat(f.curOrientation, f.curPageSize) + if f.err != nil { + return + } + f.x = x2 + } + y = f.y + f.y += h + } + if x < 0 { + x = f.x + } + // dbg("h %.2f", h) + // q 85.04 0 0 NaN 28.35 NaN cm /I2 Do Q + f.outf("q %.5f 0 0 %.5f %.5f %.5f cm /I%d Do Q", w*f.k, h*f.k, x*f.k, (f.h-(y+h))*f.k, info.i) + if link > 0 || len(linkStr) > 0 { + f.newLink(x, y, w, h, link, linkStr) + } +} + +// Image puts a JPEG, PNG or GIF image in the current page. +// +// Deprecated in favor of ImageOptions -- see that function for +// details on the behavior of arguments +func (f *Fpdf) Image(imageNameStr string, x, y, w, h float64, flow bool, tp string, link int, linkStr string) { + options := ImageOptions{ + ReadDpi: false, + ImageType: tp, + } + f.ImageOptions(imageNameStr, x, y, w, h, flow, options, link, linkStr) +} + +// ImageOptions puts a JPEG, PNG or GIF image in the current page. The size it +// will take on the page can be specified in different ways. If both w and h +// are 0, the image is rendered at 96 dpi. If either w or h is zero, it will be +// calculated from the other dimension so that the aspect ratio is maintained. +// If w and/or h are -1, the dpi for that dimension will be read from the +// ImageInfoType object. PNG files can contain dpi information, and if present, +// this information will be populated in the ImageInfoType object and used in +// Width, Height, and Extent calculations. Otherwise, the SetDpi function can +// be used to change the dpi from the default of 72. +// +// If w and h are any other negative value, their absolute values +// indicate their dpi extents. +// +// Supported JPEG formats are 24 bit, 32 bit and gray scale. Supported PNG +// formats are 24 bit, indexed color, and 8 bit indexed gray scale. If a GIF +// image is animated, only the first frame is rendered. Transparency is +// supported. It is possible to put a link on the image. +// +// imageNameStr may be the name of an image as registered with a call to either +// RegisterImageReader() or RegisterImage(). In the first case, the image is +// loaded using an io.Reader. This is generally useful when the image is +// obtained from some other means than as a disk-based file. In the second +// case, the image is loaded as a file. Alternatively, imageNameStr may +// directly specify a sufficiently qualified filename. +// +// However the image is loaded, if it is used more than once only one copy is +// embedded in the file. +// +// If x is negative, the current abscissa is used. +// +// If flow is true, the current y value is advanced after placing the image and +// a page break may be made if necessary. +// +// If link refers to an internal page anchor (that is, it is non-zero; see +// AddLink()), the image will be a clickable internal link. Otherwise, if +// linkStr specifies a URL, the image will be a clickable external link. +func (f *Fpdf) ImageOptions(imageNameStr string, x, y, w, h float64, flow bool, options ImageOptions, link int, linkStr string) { + if f.err != nil { + return + } + info := f.RegisterImageOptions(imageNameStr, options) + if f.err != nil { + return + } + f.imageOut(info, x, y, w, h, flow, link, linkStr) + return +} + +// RegisterImageReader registers an image, reading it from Reader r, adding it +// to the PDF file but not adding it to the page. +// +// This function is now deprecated in favor of RegisterImageOptionsReader +func (f *Fpdf) RegisterImageReader(imgName, tp string, r io.Reader) (info *ImageInfoType) { + options := ImageOptions{ + ReadDpi: false, + ImageType: tp, + } + return f.RegisterImageOptionsReader(imgName, options, r) +} + +// ImageOptions provides a place to hang any options we want to use while +// parsing an image. +// +// ImageType's possible values are (case insensitive): +// "JPG", "JPEG", "PNG" and "GIF". If empty, the type is inferred from +// the file extension. +// +// ReadDpi defines whether to attempt to automatically read the image +// dpi information from the image file. Normally, this should be set +// to true (understanding that not all images will have this info +// available). However, for backwards compatibility with previous +// versions of the API, it defaults to false. +type ImageOptions struct { + ImageType string + ReadDpi bool +} + +// RegisterImageOptionsReader registers an image, reading it from Reader r, adding it +// to the PDF file but not adding it to the page. Use Image() with the same +// name to add the image to the page. Note that tp should be specified in this +// case. +// +// See Image() for restrictions on the image and the options parameters. +func (f *Fpdf) RegisterImageOptionsReader(imgName string, options ImageOptions, r io.Reader) (info *ImageInfoType) { + // Thanks, Ivan Daniluk, for generalizing this code to use the Reader interface. + if f.err != nil { + return + } + info, ok := f.images[imgName] + if ok { + return + } + + // First use of this image, get info + if options.ImageType == "" { + f.err = fmt.Errorf("image type should be specified if reading from custom reader") + return + } + options.ImageType = strings.ToLower(options.ImageType) + if options.ImageType == "jpeg" { + options.ImageType = "jpg" + } + switch options.ImageType { + case "jpg": + info = f.parsejpg(r) + case "png": + info = f.parsepng(r, options.ReadDpi) + case "gif": + info = f.parsegif(r) + default: + f.err = fmt.Errorf("unsupported image type: %s", options.ImageType) + } + if f.err != nil { + return + } + info.i = len(f.images) + 1 + f.images[imgName] = info + + return +} + +// RegisterImage registers an image, adding it to the PDF file but not adding +// it to the page. Use Image() with the same filename to add the image to the +// page. Note that Image() calls this function, so this function is only +// necessary if you need information about the image before placing it. +// +// This function is now deprecated in favor of RegisterImageOptions. +// See Image() for restrictions on the image and the "tp" parameters. +func (f *Fpdf) RegisterImage(fileStr, tp string) (info *ImageInfoType) { + options := ImageOptions{ + ReadDpi: false, + ImageType: tp, + } + return f.RegisterImageOptions(fileStr, options) +} + +// RegisterImageOptions registers an image, adding it to the PDF file but not +// adding it to the page. Use Image() with the same filename to add the image +// to the page. Note that Image() calls this function, so this function is only +// necessary if you need information about the image before placing it. See +// Image() for restrictions on the image and the "tp" parameters. +func (f *Fpdf) RegisterImageOptions(fileStr string, options ImageOptions) (info *ImageInfoType) { + info, ok := f.images[fileStr] + if ok { + return + } + + file, err := os.Open(fileStr) + if err != nil { + f.err = err + return + } + defer file.Close() + + // First use of this image, get info + if options.ImageType == "" { + pos := strings.LastIndex(fileStr, ".") + if pos < 0 { + f.err = fmt.Errorf("image file has no extension and no type was specified: %s", fileStr) + return + } + options.ImageType = fileStr[pos+1:] + } + + return f.RegisterImageOptionsReader(fileStr, options, file) +} + +// GetImageInfo returns information about the registered image specified by +// imageStr. If the image has not been registered, nil is returned. The +// internal error is not modified by this method. +func (f *Fpdf) GetImageInfo(imageStr string) (info *ImageInfoType) { + return f.images[imageStr] +} + +// GetConversionRatio returns the conversion ratio based on the unit given when +// creating the PDF. +func (f *Fpdf) GetConversionRatio() float64 { + return f.k +} + +// GetXY returns the abscissa and ordinate of the current position. +// +// Note: the value returned for the abscissa will be affected by the current +// cell margin. To account for this, you may need to either add the value +// returned by GetCellMargin() to it or call SetCellMargin(0) to remove the +// cell margin. +func (f *Fpdf) GetXY() (float64, float64) { + return f.x, f.y +} + +// GetX returns the abscissa of the current position. +// +// Note: the value returned will be affected by the current cell margin. To +// account for this, you may need to either add the value returned by +// GetCellMargin() to it or call SetCellMargin(0) to remove the cell margin. +func (f *Fpdf) GetX() float64 { + return f.x +} + +// SetX defines the abscissa of the current position. If the passed value is +// negative, it is relative to the right of the page. +func (f *Fpdf) SetX(x float64) { + if x >= 0 { + f.x = x + } else { + f.x = f.w + x + } +} + +// GetY returns the ordinate of the current position. +func (f *Fpdf) GetY() float64 { + return f.y +} + +// SetY moves the current abscissa back to the left margin and sets the +// ordinate. If the passed value is negative, it is relative to the bottom of +// the page. +func (f *Fpdf) SetY(y float64) { + // dbg("SetY x %.2f, lMargin %.2f", f.x, f.lMargin) + f.x = f.lMargin + if y >= 0 { + f.y = y + } else { + f.y = f.h + y + } +} + +// SetXY defines the abscissa and ordinate of the current position. If the +// passed values are negative, they are relative respectively to the right and +// bottom of the page. +func (f *Fpdf) SetXY(x, y float64) { + f.SetY(y) + f.SetX(x) +} + +// SetProtection applies certain constraints on the finished PDF document. +// +// actionFlag is a bitflag that controls various document operations. +// CnProtectPrint allows the document to be printed. CnProtectModify allows a +// document to be modified by a PDF editor. CnProtectCopy allows text and +// images to be copied into the system clipboard. CnProtectAnnotForms allows +// annotations and forms to be added by a PDF editor. These values can be +// combined by or-ing them together, for example, +// CnProtectCopy|CnProtectModify. This flag is advisory; not all PDF readers +// implement the constraints that this argument attempts to control. +// +// userPassStr specifies the password that will need to be provided to view the +// contents of the PDF. The permissions specified by actionFlag will apply. +// +// ownerPassStr specifies the password that will need to be provided to gain +// full access to the document regardless of the actionFlag value. An empty +// string for this argument will be replaced with a random value, effectively +// prohibiting full access to the document. +func (f *Fpdf) SetProtection(actionFlag byte, userPassStr, ownerPassStr string) { + if f.err != nil { + return + } + f.protect.setProtection(actionFlag, userPassStr, ownerPassStr) +} + +// OutputAndClose sends the PDF document to the writer specified by w. This +// method will close both f and w, even if an error is detected and no document +// is produced. +func (f *Fpdf) OutputAndClose(w io.WriteCloser) error { + f.Output(w) + w.Close() + return f.err +} + +// OutputFileAndClose creates or truncates the file specified by fileStr and +// writes the PDF document to it. This method will close f and the newly +// written file, even if an error is detected and no document is produced. +// +// Most examples demonstrate the use of this method. +func (f *Fpdf) OutputFileAndClose(fileStr string) error { + if f.err == nil { + pdfFile, err := os.Create(fileStr) + if err == nil { + f.Output(pdfFile) + pdfFile.Close() + } else { + f.err = err + } + } + return f.err +} + +// Output sends the PDF document to the writer specified by w. No output will +// take place if an error has occurred in the document generation process. w +// remains open after this function returns. After returning, f is in a closed +// state and its methods should not be called. +func (f *Fpdf) Output(w io.Writer) error { + if f.err != nil { + return f.err + } + // dbg("Output") + if f.state < 3 { + f.Close() + } + _, err := f.buffer.WriteTo(w) + if err != nil { + f.err = err + } + return f.err +} + +func (f *Fpdf) getpagesizestr(sizeStr string) (size SizeType) { + if f.err != nil { + return + } + sizeStr = strings.ToLower(sizeStr) + // dbg("Size [%s]", sizeStr) + var ok bool + size, ok = f.stdPageSizes[sizeStr] + if ok { + // dbg("found %s", sizeStr) + size.Wd /= f.k + size.Ht /= f.k + + } else { + f.err = fmt.Errorf("unknown page size %s", sizeStr) + } + return +} + +func (f *Fpdf) _getpagesize(size SizeType) SizeType { + if size.Wd > size.Ht { + size.Wd, size.Ht = size.Ht, size.Wd + } + return size +} + +func (f *Fpdf) beginpage(orientationStr string, size SizeType) { + if f.err != nil { + return + } + f.page++ + f.pages = append(f.pages, bytes.NewBufferString("")) + f.pageLinks = append(f.pageLinks, make([]linkType, 0, 0)) + f.state = 2 + f.x = f.lMargin + f.y = f.tMargin + f.fontFamily = "" + // Check page size and orientation + if orientationStr == "" { + orientationStr = f.defOrientation + } else { + orientationStr = strings.ToUpper(orientationStr[0:1]) + } + if orientationStr != f.curOrientation || size.Wd != f.curPageSize.Wd || size.Ht != f.curPageSize.Ht { + // New size or orientation + if orientationStr == "P" { + f.w = size.Wd + f.h = size.Ht + } else { + f.w = size.Ht + f.h = size.Wd + } + f.wPt = f.w * f.k + f.hPt = f.h * f.k + f.pageBreakTrigger = f.h - f.bMargin + f.curOrientation = orientationStr + f.curPageSize = size + } + if orientationStr != f.defOrientation || size.Wd != f.defPageSize.Wd || size.Ht != f.defPageSize.Ht { + f.pageSizes[f.page] = SizeType{f.wPt, f.hPt} + } + return +} + +func (f *Fpdf) endpage() { + f.EndLayer() + f.state = 1 +} + +// Load a font definition file from the given Reader +func (f *Fpdf) loadfont(r io.Reader) (def fontDefType) { + if f.err != nil { + return + } + // dbg("Loading font [%s]", fontStr) + var buf bytes.Buffer + _, err := buf.ReadFrom(r) + if err != nil { + f.err = err + return + } + err = json.Unmarshal(buf.Bytes(), &def) + if err != nil { + f.err = err + } + // dump(def) + return +} + +// Escape special characters in strings +func (f *Fpdf) escape(s string) string { + s = strings.Replace(s, "\\", "\\\\", -1) + s = strings.Replace(s, "(", "\\(", -1) + s = strings.Replace(s, ")", "\\)", -1) + s = strings.Replace(s, "\r", "\\r", -1) + return s +} + +// Format a text string +func (f *Fpdf) textstring(s string) string { + if f.protect.encrypted { + b := []byte(s) + f.protect.rc4(uint32(f.n), &b) + s = string(b) + } + return "(" + f.escape(s) + ")" +} + +func blankCount(str string) (count int) { + l := len(str) + for j := 0; j < l; j++ { + if byte(' ') == str[j] { + count++ + } + } + return +} + +// Underline text +func (f *Fpdf) dounderline(x, y float64, txt string) string { + up := float64(f.currentFont.Up) + ut := float64(f.currentFont.Ut) + w := f.GetStringWidth(txt) + f.ws*float64(blankCount(txt)) + return sprintf("%.2f %.2f %.2f %.2f re f", x*f.k, + (f.h-(y-up/1000*f.fontSize))*f.k, w*f.k, -ut/1000*f.fontSizePt) +} + +func bufEqual(buf []byte, str string) bool { + return string(buf[0:len(str)]) == str +} + +func be16(buf []byte) int { + return 256*int(buf[0]) + int(buf[1]) +} + +func (f *Fpdf) newImageInfo() *ImageInfoType { + // default dpi to 72 unless told otherwise + return &ImageInfoType{scale: f.k, dpi: 72} +} + +// Extract info from io.Reader with JPEG data +// Thank you, Bruno Michel, for providing this code. +func (f *Fpdf) parsejpg(r io.Reader) (info *ImageInfoType) { + info = f.newImageInfo() + var ( + data bytes.Buffer + err error + ) + _, err = data.ReadFrom(r) + if err != nil { + f.err = err + return + } + info.data = data.Bytes() + + config, err := jpeg.DecodeConfig(bytes.NewReader(info.data)) + if err != nil { + f.err = err + return + } + info.w = float64(config.Width) + info.h = float64(config.Height) + info.f = "DCTDecode" + info.bpc = 8 + switch config.ColorModel { + case color.GrayModel: + info.cs = "DeviceGray" + case color.YCbCrModel: + info.cs = "DeviceRGB" + case color.CMYKModel: + info.cs = "DeviceCMYK" + default: + f.err = fmt.Errorf("image JPEG buffer has unsupported color space (%v)", config.ColorModel) + return + } + return +} + +// Extract info from a PNG data +func (f *Fpdf) parsepng(r io.Reader, readdpi bool) (info *ImageInfoType) { + buf, err := bufferFromReader(r) + if err != nil { + f.err = err + return + } + return f.parsepngstream(buf, readdpi) +} + +func (f *Fpdf) readBeInt32(buf *bytes.Buffer) (val int32) { + err := binary.Read(buf, binary.BigEndian, &val) + if err != nil { + f.err = err + } + return +} + +func (f *Fpdf) readByte(buf *bytes.Buffer) (val byte) { + err := binary.Read(buf, binary.BigEndian, &val) + if err != nil { + f.err = err + } + return +} + +// Extract info from a GIF data (via PNG conversion) +func (f *Fpdf) parsegif(r io.Reader) (info *ImageInfoType) { + data, err := bufferFromReader(r) + if err != nil { + f.err = err + return + } + var img image.Image + img, err = gif.Decode(data) + if err != nil { + f.err = err + return + } + pngBuf := new(bytes.Buffer) + err = png.Encode(pngBuf, img) + if err != nil { + f.err = err + return + } + return f.parsepngstream(pngBuf, false) +} + +// Begin a new object +func (f *Fpdf) newobj() { + // dbg("newobj") + f.n++ + for j := len(f.offsets); j <= f.n; j++ { + f.offsets = append(f.offsets, 0) + } + f.offsets[f.n] = f.buffer.Len() + f.outf("%d 0 obj", f.n) +} + +func (f *Fpdf) putstream(b []byte) { + // dbg("putstream") + if f.protect.encrypted { + f.protect.rc4(uint32(f.n), &b) + } + f.out("stream") + f.out(string(b)) + f.out("endstream") +} + +// Add a line to the document +func (f *Fpdf) out(s string) { + if f.state == 2 { + f.pages[f.page].WriteString(s) + f.pages[f.page].WriteString("\n") + } else { + f.buffer.WriteString(s) + f.buffer.WriteString("\n") + } +} + +// Add a buffered line to the document +func (f *Fpdf) outbuf(b *bytes.Buffer) { + if f.state == 2 { + f.pages[f.page].ReadFrom(b) + f.pages[f.page].WriteString("\n") + } else { + f.buffer.ReadFrom(b) + f.buffer.WriteString("\n") + } +} + +// RawWriteStr writes a string directly to the PDF generation buffer. This is a +// low-level function that is not required for normal PDF construction. An +// understanding of the PDF specification is needed to use this method +// correctly. +func (f *Fpdf) RawWriteStr(str string) { + f.out(str) +} + +// RawWriteBuf writes the contents of the specified buffer directly to the PDF +// generation buffer. This is a low-level function that is not required for +// normal PDF construction. An understanding of the PDF specification is needed +// to use this method correctly. +func (f *Fpdf) RawWriteBuf(buf *bytes.Buffer) { + f.outbuf(buf) +} + +// Add a formatted line to the document +func (f *Fpdf) outf(fmtStr string, args ...interface{}) { + f.out(sprintf(fmtStr, args...)) +} + +// SetDefaultCatalogSort sets the default value of the catalog sort flag that +// will be used when initializing a new Fpdf instance. See SetCatalogSort() for +// more details. +func SetDefaultCatalogSort(flag bool) { + gl.catalogSort = flag +} + +// SetCatalogSort sets a flag that will be used, if true, to consistently order +// the document's internal resource catalogs. This method is typically only +// used for test purposes to facilitate PDF comparison. +func (f *Fpdf) SetCatalogSort(flag bool) { + f.catalogSort = flag +} + +// SetDefaultCreationDate sets the default value of the document creation date +// that will be used when initializing a new Fpdf instance. See +// SetCreationDate() for more details. +func SetDefaultCreationDate(tm time.Time) { + gl.creationDate = tm +} + +// SetCreationDate fixes the document's internal CreationDate value. By +// default, the time when the document is generated is used for this value. +// This method is typically only used for testing purposes to facilitate PDF +// comparsion. Specify a zero-value time to revert to the default behavior. +func (f *Fpdf) SetCreationDate(tm time.Time) { + f.creationDate = tm +} + +func (f *Fpdf) putpages() { + var wPt, hPt float64 + var pageSize SizeType + // var linkList []linkType + var ok bool + nb := f.page + if len(f.aliasNbPagesStr) > 0 { + // Replace number of pages + nbStr := sprintf("%d", nb) + for n := 1; n <= nb; n++ { + s := f.pages[n].String() + if strings.Contains(s, f.aliasNbPagesStr) { + s = strings.Replace(s, f.aliasNbPagesStr, nbStr, -1) + f.pages[n].Truncate(0) + f.pages[n].WriteString(s) + } + } + } + if f.defOrientation == "P" { + wPt = f.defPageSize.Wd * f.k + hPt = f.defPageSize.Ht * f.k + } else { + wPt = f.defPageSize.Ht * f.k + hPt = f.defPageSize.Wd * f.k + } + for n := 1; n <= nb; n++ { + // Page + f.newobj() + f.out("<</Type /Page") + f.out("/Parent 1 0 R") + pageSize, ok = f.pageSizes[n] + if ok { + f.outf("/MediaBox [0 0 %.2f %.2f]", pageSize.Wd, pageSize.Ht) + } + f.out("/Resources 2 0 R") + // Links + if len(f.pageLinks[n]) > 0 { + var annots fmtBuffer + annots.printf("/Annots [") + for _, pl := range f.pageLinks[n] { + annots.printf("<</Type /Annot /Subtype /Link /Rect [%.2f %.2f %.2f %.2f] /Border [0 0 0] ", + pl.x, pl.y, pl.x+pl.wd, pl.y-pl.ht) + if pl.link == 0 { + annots.printf("/A <</S /URI /URI %s>>>>", f.textstring(pl.linkStr)) + } else { + l := f.links[pl.link] + var sz SizeType + var h float64 + sz, ok = f.pageSizes[l.page] + if ok { + h = sz.Ht + } else { + h = hPt + } + // dbg("h [%.2f], l.y [%.2f] f.k [%.2f]\n", h, l.y, f.k) + annots.printf("/Dest [%d 0 R /XYZ 0 %.2f null]>>", 1+2*l.page, h-l.y*f.k) + } + } + annots.printf("]") + f.out(annots.String()) + } + if f.pdfVersion > "1.3" { + f.out("/Group <</Type /Group /S /Transparency /CS /DeviceRGB>>") + } + f.outf("/Contents %d 0 R>>", f.n+1) + f.out("endobj") + // Page content + f.newobj() + if f.compress { + data := sliceCompress(f.pages[n].Bytes()) + f.outf("<</Filter /FlateDecode /Length %d>>", len(data)) + f.putstream(data) + } else { + f.outf("<</Length %d>>", f.pages[n].Len()) + f.putstream(f.pages[n].Bytes()) + } + f.out("endobj") + } + // Pages root + f.offsets[1] = f.buffer.Len() + f.out("1 0 obj") + f.out("<</Type /Pages") + var kids fmtBuffer + kids.printf("/Kids [") + for i := 0; i < nb; i++ { + kids.printf("%d 0 R ", 3+2*i) + } + kids.printf("]") + f.out(kids.String()) + f.outf("/Count %d", nb) + f.outf("/MediaBox [0 0 %.2f %.2f]", wPt, hPt) + f.out(">>") + f.out("endobj") +} + +func (f *Fpdf) putfonts() { + if f.err != nil { + return + } + nf := f.n + for _, diff := range f.diffs { + // Encodings + f.newobj() + f.outf("<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [%s]>>", diff) + f.out("endobj") + } + { + var fileList []string + var info fontFileType + var file string + for file = range f.fontFiles { + fileList = append(fileList, file) + } + if f.catalogSort { + sort.Strings(fileList) + } + for _, file = range fileList { + info = f.fontFiles[file] + // Font file embedding + f.newobj() + info.n = f.n + f.fontFiles[file] = info + + var font []byte + + if info.embedded { + font = info.content + } else { + var err error + font, err = f.loadFontFile(file) + if err != nil { + f.err = err + return + } + } + + // dbg("font file [%s], ext [%s]", file, file[len(file)-2:]) + compressed := file[len(file)-2:] == ".z" + if !compressed && info.length2 > 0 { + buf := font[6:info.length1] + buf = append(buf, font[6+info.length1+6:info.length2]...) + font = buf + } + f.outf("<</Length %d", len(font)) + if compressed { + f.out("/Filter /FlateDecode") + } + f.outf("/Length1 %d", info.length1) + if info.length2 > 0 { + f.outf("/Length2 %d /Length3 0", info.length2) + } + f.out(">>") + f.putstream(font) + f.out("endobj") + } + } + { + var keyList []string + var font fontDefType + var key string + for key = range f.fonts { + keyList = append(keyList, key) + } + if f.catalogSort { + sort.Strings(keyList) + } + for _, key = range keyList { + font = f.fonts[key] + // Font objects + font.N = f.n + 1 + f.fonts[key] = font + tp := font.Tp + name := font.Name + if tp == "Core" { + // Core font + f.newobj() + f.out("<</Type /Font") + f.outf("/BaseFont /%s", name) + f.out("/Subtype /Type1") + if name != "Symbol" && name != "ZapfDingbats" { + f.out("/Encoding /WinAnsiEncoding") + } + f.out(">>") + f.out("endobj") + } else if tp == "Type1" || tp == "TrueType" { + // Additional Type1 or TrueType/OpenType font + f.newobj() + f.out("<</Type /Font") + f.outf("/BaseFont /%s", name) + f.outf("/Subtype /%s", tp) + f.out("/FirstChar 32 /LastChar 255") + f.outf("/Widths %d 0 R", f.n+1) + f.outf("/FontDescriptor %d 0 R", f.n+2) + if font.DiffN > 0 { + f.outf("/Encoding %d 0 R", nf+font.DiffN) + } else { + f.out("/Encoding /WinAnsiEncoding") + } + f.out(">>") + f.out("endobj") + // Widths + f.newobj() + var s fmtBuffer + s.WriteString("[") + for j := 32; j < 256; j++ { + s.printf("%d ", font.Cw[j]) + } + s.WriteString("]") + f.out(s.String()) + f.out("endobj") + // Descriptor + f.newobj() + s.Truncate(0) + s.printf("<</Type /FontDescriptor /FontName /%s ", name) + s.printf("/Ascent %d ", font.Desc.Ascent) + s.printf("/Descent %d ", font.Desc.Descent) + s.printf("/CapHeight %d ", font.Desc.CapHeight) + s.printf("/Flags %d ", font.Desc.Flags) + s.printf("/FontBBox [%d %d %d %d] ", font.Desc.FontBBox.Xmin, font.Desc.FontBBox.Ymin, + font.Desc.FontBBox.Xmax, font.Desc.FontBBox.Ymax) + s.printf("/ItalicAngle %d ", font.Desc.ItalicAngle) + s.printf("/StemV %d ", font.Desc.StemV) + s.printf("/MissingWidth %d ", font.Desc.MissingWidth) + var suffix string + if tp != "Type1" { + suffix = "2" + } + s.printf("/FontFile%s %d 0 R>>", suffix, f.fontFiles[font.File].n) + f.out(s.String()) + f.out("endobj") + } else { + f.err = fmt.Errorf("unsupported font type: %s", tp) + return + // Allow for additional types + // $mtd = 'put'.strtolower($type); + // if(!method_exists($this,$mtd)) + // $this->Error('Unsupported font type: '.$type); + // $this->$mtd($font); + } + } + } + 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() { + var keyList []string + var key string + for key = range f.images { + keyList = append(keyList, key) + } + if f.catalogSort { + sort.Strings(keyList) + } + for _, key = range keyList { + f.putimage(f.images[key]) + } +} + +func (f *Fpdf) putimage(info *ImageInfoType) { + f.newobj() + info.n = f.n + f.out("<</Type /XObject") + f.out("/Subtype /Image") + f.outf("/Width %d", int(info.w)) + f.outf("/Height %d", int(info.h)) + if info.cs == "Indexed" { + f.outf("/ColorSpace [/Indexed /DeviceRGB %d %d 0 R]", len(info.pal)/3-1, f.n+1) + } else { + f.outf("/ColorSpace /%s", info.cs) + if info.cs == "DeviceCMYK" { + f.out("/Decode [1 0 1 0 1 0 1 0]") + } + } + f.outf("/BitsPerComponent %d", info.bpc) + if len(info.f) > 0 { + f.outf("/Filter /%s", info.f) + } + if len(info.dp) > 0 { + f.outf("/DecodeParms <<%s>>", info.dp) + } + if len(info.trns) > 0 { + var trns fmtBuffer + for _, v := range info.trns { + trns.printf("%d %d ", v, v) + } + f.outf("/Mask [%s]", trns.String()) + } + if info.smask != nil { + f.outf("/SMask %d 0 R", f.n+1) + } + f.outf("/Length %d>>", len(info.data)) + f.putstream(info.data) + f.out("endobj") + // Soft mask + if len(info.smask) > 0 { + smask := &ImageInfoType{ + w: info.w, + h: info.h, + cs: "DeviceGray", + bpc: 8, + f: info.f, + dp: sprintf("/Predictor 15 /Colors 1 /BitsPerComponent 8 /Columns %d", int(info.w)), + data: info.smask, + scale: f.k, + } + f.putimage(smask) + } + // Palette + if info.cs == "Indexed" { + f.newobj() + if f.compress { + pal := sliceCompress(info.pal) + f.outf("<</Filter /FlateDecode /Length %d>>", len(pal)) + f.putstream(pal) + } else { + f.outf("<</Length %d>>", len(info.pal)) + f.putstream(info.pal) + } + f.out("endobj") + } +} + +func (f *Fpdf) putxobjectdict() { + { + var image *ImageInfoType + var key string + var keyList []string + for key = range f.images { + keyList = append(keyList, key) + } + if f.catalogSort { + sort.Strings(keyList) + } + for _, key = range keyList { + image = f.images[key] + f.outf("/I%d %d 0 R", image.i, image.n) + } + } + { + var keyList []int64 + var key int64 + var tpl Template + keyList = templateKeyList(f.templates, f.catalogSort) + for _, key = range keyList { + tpl = f.templates[key] + // for _, tpl := range f.templates { + id := tpl.ID() + if objID, ok := f.templateObjects[id]; ok { + f.outf("/TPL%d %d 0 R", id, objID) + } + } + } +} + +func (f *Fpdf) putresourcedict() { + f.out("/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]") + f.out("/Font <<") + { + var keyList []string + var font fontDefType + var key string + for key = range f.fonts { + keyList = append(keyList, key) + } + if f.catalogSort { + sort.Strings(keyList) + } + for _, key = range keyList { + font = f.fonts[key] + f.outf("/F%d %d 0 R", font.I, font.N) + } + } + f.out(">>") + f.out("/XObject <<") + f.putxobjectdict() + f.out(">>") + count := len(f.blendList) + if count > 1 { + f.out("/ExtGState <<") + for j := 1; j < count; j++ { + f.outf("/GS%d %d 0 R", j, f.blendList[j].objNum) + } + f.out(">>") + } + count = len(f.gradientList) + if count > 1 { + f.out("/Shading <<") + for j := 1; j < count; j++ { + f.outf("/Sh%d %d 0 R", j, f.gradientList[j].objNum) + } + f.out(">>") + } + // Layers + f.layerPutResourceDict() +} + +func (f *Fpdf) putBlendModes() { + count := len(f.blendList) + for j := 1; j < count; j++ { + bl := f.blendList[j] + f.newobj() + f.blendList[j].objNum = f.n + f.outf("<</Type /ExtGState /ca %s /CA %s /BM /%s>>", + bl.fillStr, bl.strokeStr, bl.modeStr) + f.out("endobj") + } +} + +func (f *Fpdf) putGradients() { + count := len(f.gradientList) + for j := 1; j < count; j++ { + var f1 int + gr := f.gradientList[j] + if gr.tp == 2 || gr.tp == 3 { + f.newobj() + f.outf("<</FunctionType 2 /Domain [0.0 1.0] /C0 [%s] /C1 [%s] /N 1>>", gr.clr1Str, gr.clr2Str) + f.out("endobj") + f1 = f.n + } + f.newobj() + f.outf("<</ShadingType %d /ColorSpace /DeviceRGB", gr.tp) + if gr.tp == 2 { + f.outf("/Coords [%.5f %.5f %.5f %.5f] /Function %d 0 R /Extend [true true]>>", + gr.x1, gr.y1, gr.x2, gr.y2, f1) + } else if gr.tp == 3 { + f.outf("/Coords [%.5f %.5f 0 %.5f %.5f %.5f] /Function %d 0 R /Extend [true true]>>", + gr.x1, gr.y1, gr.x2, gr.y2, gr.r, f1) + } + f.out("endobj") + f.gradientList[j].objNum = f.n + } +} + +func (f *Fpdf) putresources() { + if f.err != nil { + return + } + f.layerPutLayers() + f.putBlendModes() + f.putGradients() + f.putfonts() + if f.err != nil { + return + } + f.putimages() + f.putTemplates() + // Resource dictionary + f.offsets[2] = f.buffer.Len() + f.out("2 0 obj") + f.out("<<") + f.putresourcedict() + f.out(">>") + f.out("endobj") + if f.protect.encrypted { + f.newobj() + f.protect.objNum = f.n + f.out("<<") + f.out("/Filter /Standard") + f.out("/V 1") + f.out("/R 2") + f.outf("/O (%s)", f.escape(string(f.protect.oValue))) + f.outf("/U (%s)", f.escape(string(f.protect.uValue))) + f.outf("/P %d", f.protect.pValue) + f.out(">>") + f.out("endobj") + } + return +} + +func (f *Fpdf) putinfo() { + var tm time.Time + f.outf("/Producer %s", f.textstring("FPDF "+cnFpdfVersion)) + if len(f.title) > 0 { + f.outf("/Title %s", f.textstring(f.title)) + } + if len(f.subject) > 0 { + f.outf("/Subject %s", f.textstring(f.subject)) + } + if len(f.author) > 0 { + f.outf("/Author %s", f.textstring(f.author)) + } + if len(f.keywords) > 0 { + f.outf("/Keywords %s", f.textstring(f.keywords)) + } + if len(f.creator) > 0 { + f.outf("/Creator %s", f.textstring(f.creator)) + } + if f.creationDate.IsZero() { + tm = time.Now() + } else { + tm = f.creationDate + } + f.outf("/CreationDate %s", f.textstring("D:"+tm.Format("20060102150405"))) +} + +func (f *Fpdf) putcatalog() { + f.out("/Type /Catalog") + f.out("/Pages 1 0 R") + switch f.zoomMode { + case "fullpage": + f.out("/OpenAction [3 0 R /Fit]") + case "fullwidth": + f.out("/OpenAction [3 0 R /FitH null]") + case "real": + f.out("/OpenAction [3 0 R /XYZ null null 1]") + } + // } else if !is_string($this->zoomMode)) + // $this->out('/OpenAction [3 0 R /XYZ null null '.sprintf('%.2f',$this->zoomMode/100).']'); + switch f.layoutMode { + case "single", "SinglePage": + f.out("/PageLayout /SinglePage") + case "continuous", "OneColumn": + f.out("/PageLayout /OneColumn") + case "two", "TwoColumnLeft": + f.out("/PageLayout /TwoColumnLeft") + case "TwoColumnRight": + f.out("/PageLayout /TwoColumnRight") + case "TwoPageLeft", "TwoPageRight": + if f.pdfVersion < "1.5" { + f.pdfVersion = "1.5" + } + f.out("/PageLayout /" + f.layoutMode) + } + // Bookmarks + if len(f.outlines) > 0 { + f.outf("/Outlines %d 0 R", f.outlineRoot) + f.out("/PageMode /UseOutlines") + } + // Layers + f.layerPutCatalog() +} + +func (f *Fpdf) putheader() { + if len(f.blendMap) > 0 && f.pdfVersion < "1.4" { + f.pdfVersion = "1.4" + } + f.outf("%%PDF-%s", f.pdfVersion) +} + +func (f *Fpdf) puttrailer() { + f.outf("/Size %d", f.n+1) + f.outf("/Root %d 0 R", f.n) + f.outf("/Info %d 0 R", f.n-1) + if f.protect.encrypted { + f.outf("/Encrypt %d 0 R", f.protect.objNum) + f.out("/ID [()()]") + } +} + +func (f *Fpdf) putbookmarks() { + nb := len(f.outlines) + if nb > 0 { + lru := make(map[int]int) + level := 0 + for i, o := range f.outlines { + if o.level > 0 { + parent := lru[o.level-1] + f.outlines[i].parent = parent + f.outlines[parent].last = i + if o.level > level { + f.outlines[parent].first = i + } + } else { + f.outlines[i].parent = nb + } + if o.level <= level && i > 0 { + prev := lru[o.level] + f.outlines[prev].next = i + f.outlines[i].prev = prev + } + lru[o.level] = i + level = o.level + } + n := f.n + 1 + for _, o := range f.outlines { + f.newobj() + f.outf("<</Title %s", f.textstring(o.text)) + f.outf("/Parent %d 0 R", n+o.parent) + if o.prev != -1 { + f.outf("/Prev %d 0 R", n+o.prev) + } + if o.next != -1 { + f.outf("/Next %d 0 R", n+o.next) + } + if o.first != -1 { + f.outf("/First %d 0 R", n+o.first) + } + if o.last != -1 { + f.outf("/Last %d 0 R", n+o.last) + } + f.outf("/Dest [%d 0 R /XYZ 0 %.2f null]", 1+2*o.p, (f.h-o.y)*f.k) + f.out("/Count 0>>") + f.out("endobj") + } + f.newobj() + f.outlineRoot = f.n + f.outf("<</Type /Outlines /First %d 0 R", n) + f.outf("/Last %d 0 R>>", n+lru[0]) + f.out("endobj") + } +} + +func (f *Fpdf) enddoc() { + if f.err != nil { + return + } + f.layerEndDoc() + f.putheader() + f.putpages() + f.putresources() + if f.err != nil { + return + } + // Bookmarks + f.putbookmarks() + // Info + f.newobj() + f.out("<<") + f.putinfo() + f.out(">>") + f.out("endobj") + // Catalog + f.newobj() + f.out("<<") + f.putcatalog() + f.out(">>") + f.out("endobj") + // Cross-ref + o := f.buffer.Len() + f.out("xref") + f.outf("0 %d", f.n+1) + f.out("0000000000 65535 f ") + for j := 1; j <= f.n; j++ { + f.outf("%010d 00000 n ", f.offsets[j]) + } + // Trailer + f.out("trailer") + f.out("<<") + f.puttrailer() + f.out(">>") + f.out("startxref") + f.outf("%d", o) + f.out("%%EOF") + f.state = 3 + return +} + +// Path Drawing + +// 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. +// +// Create a "path" by moving a virtual stylus around the page (with +// MoveTo, LineTo, CurveTo, CurveBezierCubicTo, ArcTo & ClosePath) +// then draw it or fill it in (with DrawPath). 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. +func (f *Fpdf) MoveTo(x, y float64) { + f.point(x, y) + f.x, f.y = x, y +} + +// LineTo creates a line from the current stylus location to (x, y), which +// 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. +// +// The MoveTo() example demonstrates this method. +func (f *Fpdf) LineTo(x, y float64) { + f.outf("%.2f %.2f l", x*f.k, (f.h-y)*f.k) + f.x, f.y = x, y +} + +// CurveTo creates a single-segment quadratic Bézier curve. The curve starts at +// the current stylus location and ends at the point (x, y). The control point +// (cx, cy) specifies the curvature. At the start point, the curve is tangent +// to the straight line between the current stylus location and the control +// point. At the end point, the curve is tangent to the straight line between +// the end point and the control point. +// +// The MoveTo() example demonstrates this method. +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) + f.x, f.y = x, y +} + +// CurveBezierCubicTo creates a single-segment cubic Bézier curve. The curve +// starts at the current stylus location and ends at the point (x, y). The +// control points (cx0, cy0) and (cx1, cy1) specify the curvature. At the +// current stylus, the curve is tangent to the straight line between the +// current stylus location and the control point (cx0, cy0). At the end point, +// the curve is tangent to the straight line between the end point and the +// control point (cx1, cy1). +// +// The MoveTo() example demonstrates this method. +func (f *Fpdf) CurveBezierCubicTo(cx0, cy0, cx1, cy1, x, y float64) { + f.curve(cx0, cy0, cx1, cy1, x, y) + f.x, f.y = x, y +} + +// ClosePath creates a line from the current location to the last MoveTo point +// (if not the same) and mark the path as closed so the first and last lines +// join nicely. +// +// The MoveTo() example demonstrates this method. +func (f *Fpdf) ClosePath() { + f.outf("h") +} + +// DrawPath actually draws the path on the page. +// +// styleStr can be "F" for filled, "D" for outlined only, or "DF" or "FD" for +// outlined and filled. An empty string will be replaced with "D". +// Path-painting operators as defined in the PDF specification are also +// allowed: "S" (Stroke the path), "s" (Close and stroke the path), +// "f" (fill the path, using the nonzero winding number), "f*" +// (Fill the path, using the even-odd rule), "B" (Fill and then stroke +// the path, using the nonzero winding number rule), "B*" (Fill and +// then stroke the path, using the even-odd rule), "b" (Close, fill, +// and then stroke the path, using the nonzero winding number rule) and +// "b*" (Close, fill, and then stroke the path, using the even-odd +// rule). +// Drawing uses the current draw color, line width, and cap style +// centered on the +// path. Filling uses the current fill color. +// +// The MoveTo() example demonstrates this method. +func (f *Fpdf) DrawPath(styleStr string) { + f.outf(fillDrawOp(styleStr)) +} + +// ArcTo draws an elliptical arc centered at point (x, y). rx and ry specify its +// horizontal and vertical radii. If the start of the arc is not at +// the current position, a connecting line will be drawn. +// +// degRotate specifies the angle that the arc will be rotated. degStart and +// degEnd specify the starting and ending angle of the arc. All angles are +// specified in degrees and measured counter-clockwise from the 3 o'clock +// position. +// +// styleStr can be "F" for filled, "D" for outlined only, or "DF" or "FD" for +// outlined and filled. An empty string will be replaced with "D". Drawing uses +// the current draw color, line width, and cap style centered on the arc's +// path. Filling uses the current fill color. +// +// The MoveTo() example demonstrates this method. +func (f *Fpdf) ArcTo(x, y, rx, ry, degRotate, degStart, degEnd float64) { + f.arc(x, y, rx, ry, degRotate, degStart, degEnd, "", true) +} + +func (f *Fpdf) arc(x, y, rx, ry, degRotate, degStart, degEnd float64, + styleStr string, path bool) { + x *= f.k + y = (f.h - y) * f.k + rx *= f.k + ry *= f.k + segments := int(degEnd-degStart) / 60 + if segments < 2 { + segments = 2 + } + angleStart := degStart * math.Pi / 180 + angleEnd := degEnd * math.Pi / 180 + angleTotal := angleEnd - angleStart + dt := angleTotal / float64(segments) + dtm := dt / 3 + if degRotate != 0 { + a := -degRotate * math.Pi / 180 + f.outf("q %.5f %.5f %.5f %.5f %.5f %.5f cm", + math.Cos(a), -1*math.Sin(a), + math.Sin(a), math.Cos(a), x, y) + x = 0 + y = 0 + } + t := angleStart + a0 := x + rx*math.Cos(t) + b0 := y + ry*math.Sin(t) + c0 := -rx * math.Sin(t) + d0 := ry * math.Cos(t) + sx := a0 / f.k // start point of arc + sy := f.h - (b0 / f.k) + if path { + if f.x != sx || f.y != sy { + // Draw connecting line to start point + f.LineTo(sx, sy) + } + } else { + f.point(sx, sy) + } + for j := 1; j <= segments; j++ { + // Draw this bit of the total curve + t = (float64(j) * dt) + angleStart + a1 := x + rx*math.Cos(t) + b1 := y + ry*math.Sin(t) + c1 := -rx * math.Sin(t) + d1 := ry * math.Cos(t) + f.curve((a0+(c0*dtm))/f.k, + f.h-((b0+(d0*dtm))/f.k), + (a1-(c1*dtm))/f.k, + f.h-((b1-(d1*dtm))/f.k), + a1/f.k, + f.h-(b1/f.k)) + a0 = a1 + b0 = b1 + c0 = c1 + d0 = d1 + if path { + f.x = a1 / f.k + f.y = f.h - (b1 / f.k) + } + } + if !path { + f.out(fillDrawOp(styleStr)) + } + if degRotate != 0 { + f.out("Q") + } +} diff --git a/vendor/github.com/jung-kurt/gofpdf/fpdftrans.go b/vendor/github.com/jung-kurt/gofpdf/fpdftrans.go new file mode 100644 index 0000000..9cda397 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/fpdftrans.go @@ -0,0 +1,213 @@ +package gofpdf + +import ( + "fmt" + "math" +) + +// Routines in this file are translated from the work of Moritz Wagner and +// Andreas Würmser. + +// TransformMatrix is used for generalized transformations of text, drawings +// and images. +type TransformMatrix struct { + A, B, C, D, E, F float64 +} + +// TransformBegin sets up a transformation context for subsequent text, +// drawings and images. The typical usage is to immediately follow a call to +// this method with a call to one or more of the transformation methods such as +// TransformScale(), TransformSkew(), etc. This is followed by text, drawing or +// image output and finally a call to TransformEnd(). All transformation +// contexts must be properly ended prior to outputting the document. +func (f *Fpdf) TransformBegin() { + f.transformNest++ + f.out("q") +} + +// TransformScaleX scales the width of the following text, drawings and images. +// scaleWd is the percentage scaling factor. (x, y) is center of scaling. +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformScaleX(scaleWd, x, y float64) { + f.TransformScale(scaleWd, 100, x, y) +} + +// TransformScaleY scales the height of the following text, drawings and +// images. scaleHt is the percentage scaling factor. (x, y) is center of +// scaling. +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformScaleY(scaleHt, x, y float64) { + f.TransformScale(100, scaleHt, x, y) +} + +// TransformScaleXY uniformly scales the width and height of the following +// text, drawings and images. s is the percentage scaling factor for both width +// and height. (x, y) is center of scaling. +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformScaleXY(s, x, y float64) { + f.TransformScale(s, s, x, y) +} + +// TransformScale generally scales the following text, drawings and images. +// scaleWd and scaleHt are the percentage scaling factors for width and height. +// (x, y) is center of scaling. +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformScale(scaleWd, scaleHt, x, y float64) { + if scaleWd == 0 || scaleHt == 0 { + f.err = fmt.Errorf("scale factor cannot be zero") + return + } + y = (f.h - y) * f.k + x *= f.k + scaleWd /= 100 + scaleHt /= 100 + f.Transform(TransformMatrix{scaleWd, 0, 0, + scaleHt, x * (1 - scaleWd), y * (1 - scaleHt)}) +} + +// TransformMirrorHorizontal horizontally mirrors the following text, drawings +// and images. x is the axis of reflection. +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformMirrorHorizontal(x float64) { + f.TransformScale(-100, 100, x, f.y) +} + +// TransformMirrorVertical vertically mirrors the following text, drawings and +// images. y is the axis of reflection. +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformMirrorVertical(y float64) { + f.TransformScale(100, -100, f.x, y) +} + +// TransformMirrorPoint symmetrically mirrors the following text, drawings and +// images on the point specified by (x, y). +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformMirrorPoint(x, y float64) { + f.TransformScale(-100, -100, x, y) +} + +// TransformMirrorLine symmetrically mirrors the following text, drawings and +// images on the line defined by angle and the point (x, y). angles is +// specified in degrees and measured counter-clockwise from the 3 o'clock +// position. +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformMirrorLine(angle, x, y float64) { + f.TransformScale(-100, 100, x, y) + f.TransformRotate(-2*(angle-90), x, y) +} + +// TransformTranslateX moves the following text, drawings and images +// horizontally by the amount specified by tx. +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformTranslateX(tx float64) { + f.TransformTranslate(tx, 0) +} + +// TransformTranslateY moves the following text, drawings and images vertically +// by the amount specified by ty. +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformTranslateY(ty float64) { + f.TransformTranslate(0, ty) +} + +// TransformTranslate moves the following text, drawings and images +// horizontally and vertically by the amounts specified by tx and ty. +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformTranslate(tx, ty float64) { + f.Transform(TransformMatrix{1, 0, 0, 1, tx * f.k, -ty * f.k}) +} + +// TransformRotate rotates the following text, drawings and images around the +// center point (x, y). angle is specified in degrees and measured +// counter-clockwise from the 3 o'clock position. +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformRotate(angle, x, y float64) { + y = (f.h - y) * f.k + x *= f.k + angle = angle * math.Pi / 180 + var tm TransformMatrix + tm.A = math.Cos(angle) + tm.B = math.Sin(angle) + tm.C = -tm.B + tm.D = tm.A + tm.E = x + tm.B*y - tm.A*x + tm.F = y - tm.A*y - tm.B*x + f.Transform(tm) +} + +// TransformSkewX horizontally skews the following text, drawings and images +// keeping the point (x, y) stationary. angleX ranges from -90 degrees (skew to +// the left) to 90 degrees (skew to the right). +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformSkewX(angleX, x, y float64) { + f.TransformSkew(angleX, 0, x, y) +} + +// TransformSkewY vertically skews the following text, drawings and images +// keeping the point (x, y) stationary. angleY ranges from -90 degrees (skew to +// the bottom) to 90 degrees (skew to the top). +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformSkewY(angleY, x, y float64) { + f.TransformSkew(0, angleY, x, y) +} + +// TransformSkew generally skews the following text, drawings and images +// keeping the point (x, y) stationary. angleX ranges from -90 degrees (skew to +// the left) to 90 degrees (skew to the right). angleY ranges from -90 degrees +// (skew to the bottom) to 90 degrees (skew to the top). +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformSkew(angleX, angleY, x, y float64) { + if angleX <= -90 || angleX >= 90 || angleY <= -90 || angleY >= 90 { + f.err = fmt.Errorf("skew values must be between -90° and 90°") + return + } + x *= f.k + y = (f.h - y) * f.k + var tm TransformMatrix + tm.A = 1 + tm.B = math.Tan(angleY * math.Pi / 180) + tm.C = math.Tan(angleX * math.Pi / 180) + tm.D = 1 + tm.E = -tm.C * y + tm.F = -tm.B * x + f.Transform(tm) +} + +// Transform generally transforms the following text, drawings and images +// according to the specified matrix. It is typically easier to use the various +// methods such as TransformRotate() and TransformMirrorVertical() instead. +func (f *Fpdf) Transform(tm TransformMatrix) { + if f.transformNest > 0 { + f.outf("%.5f %.5f %.5f %.5f %.5f %.5f cm", + tm.A, tm.B, tm.C, tm.D, tm.E, tm.F) + } else if f.err == nil { + f.err = fmt.Errorf("transformation context is not active") + } +} + +// TransformEnd applies a transformation that was begun with a call to TransformBegin(). +// +// The TransformBegin() example demonstrates this method. +func (f *Fpdf) TransformEnd() { + if f.transformNest > 0 { + f.transformNest-- + f.out("Q") + } else { + f.err = fmt.Errorf("error attempting to end transformation operation out of sequence") + } +} diff --git a/vendor/github.com/jung-kurt/gofpdf/htmlbasic.go b/vendor/github.com/jung-kurt/gofpdf/htmlbasic.go new file mode 100644 index 0000000..ee3be7d --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/htmlbasic.go @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2014 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gofpdf + +import ( + "regexp" + "strings" +) + +// HTMLBasicSegmentType defines a segment of literal text in which the current +// attributes do not vary, or an open tag or a close tag. +type HTMLBasicSegmentType struct { + Cat byte // 'O' open tag, 'C' close tag, 'T' text + Str string // Literal text unchanged, tags are lower case + Attr map[string]string // Attribute keys are lower case +} + +// HTMLBasicTokenize returns a list of HTML tags and literal elements. This is +// done with regular expressions, so the result is only marginally better than +// useless. +func HTMLBasicTokenize(htmlStr string) (list []HTMLBasicSegmentType) { + // This routine is adapted from http://www.fpdf.org/ + list = make([]HTMLBasicSegmentType, 0, 16) + htmlStr = strings.Replace(htmlStr, "\n", " ", -1) + htmlStr = strings.Replace(htmlStr, "\r", "", -1) + tagRe, _ := regexp.Compile(`(?U)<.*>`) + attrRe, _ := regexp.Compile(`([^=]+)=["']?([^"']+)`) + capList := tagRe.FindAllStringIndex(htmlStr, -1) + if capList != nil { + var seg HTMLBasicSegmentType + var parts []string + pos := 0 + for _, cap := range capList { + if pos < cap[0] { + seg.Cat = 'T' + seg.Str = htmlStr[pos:cap[0]] + seg.Attr = nil + list = append(list, seg) + } + if htmlStr[cap[0]+1] == '/' { + seg.Cat = 'C' + seg.Str = strings.ToLower(htmlStr[cap[0]+2 : cap[1]-1]) + seg.Attr = nil + list = append(list, seg) + } else { + // Extract attributes + parts = strings.Split(htmlStr[cap[0]+1:cap[1]-1], " ") + if len(parts) > 0 { + for j, part := range parts { + if j == 0 { + seg.Cat = 'O' + seg.Str = strings.ToLower(parts[0]) + seg.Attr = make(map[string]string) + } else { + attrList := attrRe.FindAllStringSubmatch(part, -1) + if attrList != nil { + for _, attr := range attrList { + seg.Attr[strings.ToLower(attr[1])] = attr[2] + } + } + } + } + list = append(list, seg) + } + } + pos = cap[1] + } + if len(htmlStr) > pos { + seg.Cat = 'T' + seg.Str = htmlStr[pos:] + seg.Attr = nil + list = append(list, seg) + } + } else { + list = append(list, HTMLBasicSegmentType{Cat: 'T', Str: htmlStr, Attr: nil}) + } + return +} + +// HTMLBasicType is used for rendering a very basic subset of HTML. It supports +// only hyperlinks and bold, italic and underscore attributes. In the Link +// structure, the ClrR, ClrG and ClrB fields (0 through 255) define the color +// of hyperlinks. The Bold, Italic and Underscore values define the hyperlink +// style. +type HTMLBasicType struct { + pdf *Fpdf + Link struct { + ClrR, ClrG, ClrB int + Bold, Italic, Underscore bool + } +} + +// HTMLBasicNew returns an instance that facilitates writing basic HTML in the +// specified PDF file. +func (f *Fpdf) HTMLBasicNew() (html HTMLBasicType) { + html.pdf = f + html.Link.ClrR, html.Link.ClrG, html.Link.ClrB = 0, 0, 128 + html.Link.Bold, html.Link.Italic, html.Link.Underscore = false, false, true + return +} + +// Write prints text from the current position using the currently selected +// font. See HTMLBasicNew() to create a receiver that is associated with the +// PDF document instance. The text can be encoded with a basic subset of HTML +// that includes hyperlinks and tags for italic (I), bold (B), underscore +// (U) and center (CENTER) attributes. When the right margin is reached a line +// break occurs and text continues from the left margin. Upon method exit, the +// current position is left at the end of the text. +// +// lineHt indicates the line height in the unit of measure specified in New(). +func (html *HTMLBasicType) Write(lineHt float64, htmlStr string) { + var boldLvl, italicLvl, underscoreLvl, linkBold, linkItalic, linkUnderscore int + var textR, textG, textB = html.pdf.GetTextColor() + var hrefStr string + if html.Link.Bold { + linkBold = 1 + } + if html.Link.Italic { + linkItalic = 1 + } + if html.Link.Underscore { + linkUnderscore = 1 + } + setStyle := func(boldAdj, italicAdj, underscoreAdj int) { + styleStr := "" + boldLvl += boldAdj + if boldLvl > 0 { + styleStr += "B" + } + italicLvl += italicAdj + if italicLvl > 0 { + styleStr += "I" + } + underscoreLvl += underscoreAdj + if underscoreLvl > 0 { + styleStr += "U" + } + html.pdf.SetFont("", styleStr, 0) + } + putLink := func(urlStr, txtStr string) { + // Put a hyperlink + html.pdf.SetTextColor(html.Link.ClrR, html.Link.ClrG, html.Link.ClrB) + setStyle(linkBold, linkItalic, linkUnderscore) + html.pdf.WriteLinkString(lineHt, txtStr, urlStr) + setStyle(-linkBold, -linkItalic, -linkUnderscore) + html.pdf.SetTextColor(textR, textG, textB) + } + list := HTMLBasicTokenize(htmlStr) + var ok bool + alignStr := "L" + for _, el := range list { + switch el.Cat { + case 'T': + if len(hrefStr) > 0 { + putLink(hrefStr, el.Str) + hrefStr = "" + } else { + if alignStr == "C" { + html.pdf.WriteAligned(0, lineHt, el.Str, alignStr) + } else { + html.pdf.Write(lineHt, el.Str) + } + } + case 'O': + switch el.Str { + case "b": + setStyle(1, 0, 0) + case "i": + setStyle(0, 1, 0) + case "u": + setStyle(0, 0, 1) + case "br": + html.pdf.Ln(lineHt) + case "center": + html.pdf.Ln(lineHt) + alignStr = "C" + case "a": + hrefStr, ok = el.Attr["href"] + if !ok { + hrefStr = "" + } + } + case 'C': + switch el.Str { + case "b": + setStyle(-1, 0, 0) + case "i": + setStyle(0, -1, 0) + case "u": + setStyle(0, 0, -1) + case "center": + html.pdf.Ln(lineHt) + alignStr = "L" + } + } + } +} diff --git a/vendor/github.com/jung-kurt/gofpdf/internal/example/example.go b/vendor/github.com/jung-kurt/gofpdf/internal/example/example.go new file mode 100644 index 0000000..edf2388 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/internal/example/example.go @@ -0,0 +1,126 @@ +// Copyright (c) 2015 Kurt Jung (Gmail: kurt.w.jung) +// +// Permission to use, copy, modify, and distribute this software for any purpose +// with or without fee is hereby granted, provided that the above copyright notice +// and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +// Package example provides some helper routines for the test packages of +// gofpdf and its various contributed packages located beneath the contrib +// directory. +package example + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "time" + + "github.com/jung-kurt/gofpdf" +) + +var gofpdfDir string + +func init() { + setRoot() + gofpdf.SetDefaultCompression(false) + gofpdf.SetDefaultCatalogSort(true) + gofpdf.SetDefaultCreationDate(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)) +} + +// Assign the relative path to the gofpdfDir directory based on current working +// directory +func setRoot() { + wdStr, err := os.Getwd() + if err == nil { + gofpdfDir = "" + list := strings.Split(filepath.ToSlash(wdStr), "/") + for j := len(list) - 1; j >= 0 && list[j] != "gofpdf"; j-- { + gofpdfDir = filepath.Join(gofpdfDir, "..") + } + } else { + panic(err) + } +} + +// ImageFile returns a qualified filename in which the path to the image +// directory is prepended to the specified filename. +func ImageFile(fileStr string) string { + return filepath.Join(gofpdfDir, "image", fileStr) +} + +// FontDir returns the path to the font directory. +func FontDir() string { + return filepath.Join(gofpdfDir, "font") +} + +// FontFile returns a qualified filename in which the path to the font +// directory is prepended to the specified filename. +func FontFile(fileStr string) string { + return filepath.Join(FontDir(), fileStr) +} + +// TextFile returns a qualified filename in which the path to the text +// directory is prepended to the specified filename. +func TextFile(fileStr string) string { + return filepath.Join(gofpdfDir, "text", fileStr) +} + +// PdfDir returns the path to the PDF output directory. +func PdfDir() string { + return filepath.Join(gofpdfDir, "pdf") +} + +// PdfFile returns a qualified filename in which the path to the PDF output +// directory is prepended to the specified filename. +func PdfFile(fileStr string) string { + return filepath.Join(PdfDir(), fileStr) +} + +// Filename returns a qualified filename in which the example PDF directory +// path is prepended and the suffix ".pdf" is appended to the specified +// filename. +func Filename(baseStr string) string { + return PdfFile(baseStr + ".pdf") +} + +// referenceCompare compares the specified file with the file's reference copy +// located in the 'reference' subdirectory. All bytes of the two files are +// compared except for the value of the /CreationDate field in the PDF. This +// function succeeds if both files are equivalent except for their +// /CreationDate values or if the reference file does not exist. +func referenceCompare(fileStr string) (err error) { + var refFileStr, refDirStr, dirStr, baseFileStr string + dirStr, baseFileStr = filepath.Split(fileStr) + refDirStr = filepath.Join(dirStr, "reference") + err = os.MkdirAll(refDirStr, 0755) + if err == nil { + refFileStr = filepath.Join(refDirStr, baseFileStr) + err = gofpdf.ComparePDFFiles(fileStr, refFileStr) + } + return +} + +// Summary generates a predictable report for use by test examples. If the +// specified error is nil, the filename delimiters are normalized and the +// filename printed to standard output with a success message. If the specified +// error is not nil, its String() value is printed to standard output. +func Summary(err error, fileStr string) { + if err == nil { + err = referenceCompare(fileStr) + } + if err == nil { + fileStr = filepath.ToSlash(fileStr) + fmt.Printf("Successfully generated %s\n", fileStr) + } else { + fmt.Println(err) + } +} diff --git a/vendor/github.com/jung-kurt/gofpdf/internal/files/bin/bin.go b/vendor/github.com/jung-kurt/gofpdf/internal/files/bin/bin.go new file mode 100644 index 0000000..5b56313 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/internal/files/bin/bin.go @@ -0,0 +1,28 @@ +package main + +import ( + "fmt" + "io/ioutil" + "os" +) + +func main() { + var buf []byte + var pos int + var b byte + var err error + buf, err = ioutil.ReadAll(os.Stdin) + if err == nil { + for _, b = range buf { + fmt.Printf("0x%02X, ", b) + pos++ + if pos >= 16 { + fmt.Println("") + pos = 0 + } + } + } + if err != nil { + fmt.Fprintf(os.Stderr, "%s\n", err) + } +} diff --git a/vendor/github.com/jung-kurt/gofpdf/internal/files/files.go b/vendor/github.com/jung-kurt/gofpdf/internal/files/files.go new file mode 100644 index 0000000..7f73413 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/internal/files/files.go @@ -0,0 +1,1691 @@ +package files + +// CalligraJson is embedded byte slice for calligra.json +var CalligraJson = []byte{ + 0x7B, 0x22, 0x54, 0x70, 0x22, 0x3A, 0x22, 0x54, 0x72, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, + 0x2C, 0x22, 0x4E, 0x61, 0x6D, 0x65, 0x22, 0x3A, 0x22, 0x43, 0x61, 0x6C, 0x6C, 0x69, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x65, 0x72, 0x52, 0x65, 0x67, 0x75, 0x6C, 0x61, 0x72, 0x22, 0x2C, 0x22, 0x44, + 0x65, 0x73, 0x63, 0x22, 0x3A, 0x7B, 0x22, 0x41, 0x73, 0x63, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x38, + 0x39, 0x39, 0x2C, 0x22, 0x44, 0x65, 0x73, 0x63, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x2D, 0x32, 0x33, + 0x34, 0x2C, 0x22, 0x43, 0x61, 0x70, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3A, 0x38, 0x39, + 0x39, 0x2C, 0x22, 0x46, 0x6C, 0x61, 0x67, 0x73, 0x22, 0x3A, 0x33, 0x32, 0x2C, 0x22, 0x46, 0x6F, + 0x6E, 0x74, 0x42, 0x42, 0x6F, 0x78, 0x22, 0x3A, 0x7B, 0x22, 0x58, 0x6D, 0x69, 0x6E, 0x22, 0x3A, + 0x2D, 0x31, 0x37, 0x33, 0x2C, 0x22, 0x59, 0x6D, 0x69, 0x6E, 0x22, 0x3A, 0x2D, 0x32, 0x33, 0x34, + 0x2C, 0x22, 0x58, 0x6D, 0x61, 0x78, 0x22, 0x3A, 0x31, 0x33, 0x32, 0x38, 0x2C, 0x22, 0x59, 0x6D, + 0x61, 0x78, 0x22, 0x3A, 0x38, 0x39, 0x39, 0x7D, 0x2C, 0x22, 0x49, 0x74, 0x61, 0x6C, 0x69, 0x63, + 0x41, 0x6E, 0x67, 0x6C, 0x65, 0x22, 0x3A, 0x30, 0x2C, 0x22, 0x53, 0x74, 0x65, 0x6D, 0x56, 0x22, + 0x3A, 0x37, 0x30, 0x2C, 0x22, 0x4D, 0x69, 0x73, 0x73, 0x69, 0x6E, 0x67, 0x57, 0x69, 0x64, 0x74, + 0x68, 0x22, 0x3A, 0x38, 0x30, 0x30, 0x7D, 0x2C, 0x22, 0x55, 0x70, 0x22, 0x3A, 0x2D, 0x32, 0x30, + 0x30, 0x2C, 0x22, 0x55, 0x74, 0x22, 0x3A, 0x32, 0x30, 0x2C, 0x22, 0x43, 0x77, 0x22, 0x3A, 0x5B, + 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, + 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, + 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, + 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, + 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, + 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, + 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, + 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, + 0x32, 0x38, 0x32, 0x2C, 0x33, 0x32, 0x34, 0x2C, 0x34, 0x30, 0x35, 0x2C, 0x35, 0x38, 0x34, 0x2C, + 0x36, 0x33, 0x32, 0x2C, 0x39, 0x38, 0x30, 0x2C, 0x37, 0x37, 0x36, 0x2C, 0x32, 0x35, 0x39, 0x2C, + 0x32, 0x39, 0x39, 0x2C, 0x32, 0x39, 0x39, 0x2C, 0x33, 0x37, 0x37, 0x2C, 0x36, 0x30, 0x30, 0x2C, + 0x32, 0x35, 0x39, 0x2C, 0x34, 0x33, 0x32, 0x2C, 0x32, 0x35, 0x34, 0x2C, 0x35, 0x39, 0x37, 0x2C, + 0x35, 0x32, 0x39, 0x2C, 0x32, 0x39, 0x38, 0x2C, 0x34, 0x35, 0x31, 0x2C, 0x33, 0x35, 0x39, 0x2C, + 0x35, 0x32, 0x35, 0x2C, 0x34, 0x32, 0x33, 0x2C, 0x34, 0x36, 0x34, 0x2C, 0x34, 0x31, 0x37, 0x2C, + 0x34, 0x35, 0x37, 0x2C, 0x34, 0x37, 0x39, 0x2C, 0x32, 0x37, 0x35, 0x2C, 0x32, 0x38, 0x32, 0x2C, + 0x36, 0x30, 0x30, 0x2C, 0x36, 0x30, 0x30, 0x2C, 0x36, 0x30, 0x30, 0x2C, 0x35, 0x30, 0x31, 0x2C, + 0x38, 0x30, 0x30, 0x2C, 0x37, 0x34, 0x33, 0x2C, 0x36, 0x33, 0x36, 0x2C, 0x35, 0x39, 0x38, 0x2C, + 0x37, 0x31, 0x32, 0x2C, 0x36, 0x30, 0x38, 0x2C, 0x35, 0x36, 0x32, 0x2C, 0x36, 0x38, 0x30, 0x2C, + 0x37, 0x35, 0x36, 0x2C, 0x33, 0x30, 0x38, 0x2C, 0x33, 0x31, 0x34, 0x2C, 0x36, 0x37, 0x36, 0x2C, + 0x35, 0x35, 0x32, 0x2C, 0x31, 0x30, 0x34, 0x31, 0x2C, 0x38, 0x31, 0x37, 0x2C, 0x37, 0x32, 0x39, + 0x2C, 0x35, 0x36, 0x39, 0x2C, 0x36, 0x39, 0x38, 0x2C, 0x36, 0x37, 0x34, 0x2C, 0x36, 0x31, 0x38, + 0x2C, 0x36, 0x37, 0x33, 0x2C, 0x38, 0x30, 0x35, 0x2C, 0x37, 0x35, 0x33, 0x2C, 0x31, 0x32, 0x33, + 0x38, 0x2C, 0x37, 0x31, 0x36, 0x2C, 0x37, 0x35, 0x34, 0x2C, 0x35, 0x39, 0x39, 0x2C, 0x33, 0x31, + 0x35, 0x2C, 0x34, 0x36, 0x33, 0x2C, 0x33, 0x31, 0x35, 0x2C, 0x36, 0x30, 0x30, 0x2C, 0x35, 0x34, + 0x37, 0x2C, 0x32, 0x37, 0x38, 0x2C, 0x35, 0x38, 0x31, 0x2C, 0x35, 0x36, 0x34, 0x2C, 0x34, 0x34, + 0x30, 0x2C, 0x35, 0x37, 0x31, 0x2C, 0x34, 0x35, 0x30, 0x2C, 0x33, 0x34, 0x37, 0x2C, 0x36, 0x32, + 0x38, 0x2C, 0x36, 0x31, 0x31, 0x2C, 0x32, 0x38, 0x33, 0x2C, 0x32, 0x38, 0x33, 0x2C, 0x35, 0x36, + 0x30, 0x2C, 0x32, 0x35, 0x32, 0x2C, 0x39, 0x37, 0x36, 0x2C, 0x35, 0x39, 0x35, 0x2C, 0x35, 0x30, + 0x38, 0x2C, 0x35, 0x34, 0x39, 0x2C, 0x35, 0x34, 0x30, 0x2C, 0x33, 0x39, 0x35, 0x2C, 0x34, 0x34, + 0x31, 0x2C, 0x33, 0x30, 0x37, 0x2C, 0x36, 0x31, 0x34, 0x2C, 0x35, 0x35, 0x36, 0x2C, 0x39, 0x31, + 0x35, 0x2C, 0x35, 0x35, 0x39, 0x2C, 0x35, 0x39, 0x37, 0x2C, 0x34, 0x35, 0x32, 0x2C, 0x33, 0x31, + 0x35, 0x2C, 0x32, 0x32, 0x32, 0x2C, 0x33, 0x31, 0x35, 0x2C, 0x36, 0x30, 0x30, 0x2C, 0x38, 0x30, + 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, + 0x37, 0x38, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x32, 0x37, 0x38, 0x2C, 0x30, 0x2C, 0x30, 0x2C, + 0x30, 0x2C, 0x31, 0x30, 0x36, 0x34, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x30, 0x2C, 0x38, 0x30, 0x30, + 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x32, 0x35, 0x39, 0x2C, 0x32, 0x35, 0x39, 0x2C, 0x34, 0x37, 0x30, + 0x2C, 0x34, 0x37, 0x30, 0x2C, 0x35, 0x30, 0x30, 0x2C, 0x33, 0x30, 0x30, 0x2C, 0x36, 0x30, 0x30, + 0x2C, 0x32, 0x37, 0x38, 0x2C, 0x39, 0x39, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x37, 0x39, 0x30, + 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x2C, 0x37, 0x35, 0x34, 0x2C, 0x32, 0x38, 0x32, + 0x2C, 0x33, 0x32, 0x34, 0x2C, 0x34, 0x35, 0x30, 0x2C, 0x36, 0x34, 0x30, 0x2C, 0x35, 0x31, 0x38, + 0x2C, 0x36, 0x30, 0x33, 0x2C, 0x30, 0x2C, 0x35, 0x31, 0x39, 0x2C, 0x32, 0x35, 0x34, 0x2C, 0x38, + 0x30, 0x30, 0x2C, 0x33, 0x34, 0x39, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x34, 0x33, 0x32, 0x2C, 0x38, + 0x30, 0x30, 0x2C, 0x32, 0x37, 0x38, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x32, + 0x37, 0x38, 0x2C, 0x36, 0x31, 0x34, 0x2C, 0x30, 0x2C, 0x32, 0x35, 0x34, 0x2C, 0x32, 0x37, 0x38, + 0x2C, 0x30, 0x2C, 0x33, 0x30, 0x35, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x35, + 0x30, 0x31, 0x2C, 0x37, 0x34, 0x33, 0x2C, 0x37, 0x34, 0x33, 0x2C, 0x37, 0x34, 0x33, 0x2C, 0x37, + 0x34, 0x33, 0x2C, 0x37, 0x34, 0x33, 0x2C, 0x37, 0x34, 0x33, 0x2C, 0x31, 0x30, 0x36, 0x30, 0x2C, + 0x35, 0x39, 0x38, 0x2C, 0x36, 0x30, 0x38, 0x2C, 0x36, 0x30, 0x38, 0x2C, 0x36, 0x30, 0x38, 0x2C, + 0x36, 0x30, 0x38, 0x2C, 0x33, 0x30, 0x38, 0x2C, 0x33, 0x30, 0x38, 0x2C, 0x33, 0x30, 0x38, 0x2C, + 0x33, 0x30, 0x38, 0x2C, 0x30, 0x2C, 0x38, 0x31, 0x37, 0x2C, 0x37, 0x32, 0x39, 0x2C, 0x37, 0x32, + 0x39, 0x2C, 0x37, 0x32, 0x39, 0x2C, 0x37, 0x32, 0x39, 0x2C, 0x37, 0x32, 0x39, 0x2C, 0x30, 0x2C, + 0x37, 0x32, 0x39, 0x2C, 0x38, 0x30, 0x35, 0x2C, 0x38, 0x30, 0x35, 0x2C, 0x38, 0x30, 0x35, 0x2C, + 0x38, 0x30, 0x35, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x36, 0x38, 0x38, 0x2C, 0x35, 0x38, 0x31, 0x2C, + 0x35, 0x38, 0x31, 0x2C, 0x35, 0x38, 0x31, 0x2C, 0x35, 0x38, 0x31, 0x2C, 0x35, 0x38, 0x31, 0x2C, + 0x35, 0x38, 0x31, 0x2C, 0x37, 0x39, 0x32, 0x2C, 0x34, 0x34, 0x30, 0x2C, 0x34, 0x35, 0x30, 0x2C, + 0x34, 0x35, 0x30, 0x2C, 0x34, 0x35, 0x30, 0x2C, 0x34, 0x35, 0x30, 0x2C, 0x32, 0x38, 0x33, 0x2C, + 0x32, 0x38, 0x33, 0x2C, 0x32, 0x38, 0x33, 0x2C, 0x32, 0x38, 0x33, 0x2C, 0x30, 0x2C, 0x35, 0x39, + 0x35, 0x2C, 0x35, 0x30, 0x38, 0x2C, 0x35, 0x30, 0x38, 0x2C, 0x35, 0x30, 0x38, 0x2C, 0x35, 0x30, + 0x38, 0x2C, 0x35, 0x30, 0x38, 0x2C, 0x30, 0x2C, 0x35, 0x30, 0x38, 0x2C, 0x36, 0x31, 0x34, 0x2C, + 0x36, 0x31, 0x34, 0x2C, 0x36, 0x31, 0x34, 0x2C, 0x36, 0x31, 0x34, 0x2C, 0x30, 0x2C, 0x30, 0x2C, + 0x35, 0x39, 0x37, 0x5D, 0x2C, 0x22, 0x45, 0x6E, 0x63, 0x22, 0x3A, 0x22, 0x63, 0x70, 0x31, 0x32, + 0x35, 0x32, 0x22, 0x2C, 0x22, 0x44, 0x69, 0x66, 0x66, 0x22, 0x3A, 0x22, 0x22, 0x2C, 0x22, 0x46, + 0x69, 0x6C, 0x65, 0x22, 0x3A, 0x22, 0x63, 0x61, 0x6C, 0x6C, 0x69, 0x67, 0x72, 0x61, 0x2E, 0x7A, + 0x22, 0x2C, 0x22, 0x53, 0x69, 0x7A, 0x65, 0x31, 0x22, 0x3A, 0x30, 0x2C, 0x22, 0x53, 0x69, 0x7A, + 0x65, 0x32, 0x22, 0x3A, 0x30, 0x2C, 0x22, 0x4F, 0x72, 0x69, 0x67, 0x69, 0x6E, 0x61, 0x6C, 0x53, + 0x69, 0x7A, 0x65, 0x22, 0x3A, 0x34, 0x30, 0x31, 0x32, 0x30, 0x2C, 0x22, 0x49, 0x22, 0x3A, 0x30, + 0x2C, 0x22, 0x4E, 0x22, 0x3A, 0x30, 0x2C, 0x22, 0x44, 0x69, 0x66, 0x66, 0x4E, 0x22, 0x3A, 0x30, + 0x7D} + +// CalligraZ is embedded byte slice for calligra.z +var CalligraZ = []byte{ + 0x78, 0x9C, 0xA4, 0xFC, 0x07, 0x80, 0x5C, 0x57, 0x7D, 0x2F, 0x8E, 0x9F, 0x73, 0x6E, 0xEF, 0xFD, + 0xDE, 0xE9, 0xBD, 0xF7, 0x9D, 0xD9, 0x99, 0xD9, 0xDD, 0x99, 0xDD, 0x99, 0xED, 0xAB, 0xDE, 0x65, + 0xAD, 0xEC, 0xB5, 0x25, 0x4B, 0xB2, 0xE4, 0x22, 0x5B, 0x96, 0x6D, 0x59, 0xC6, 0x35, 0xB8, 0x51, + 0x0D, 0xBC, 0x47, 0x4B, 0x80, 0x40, 0x02, 0x06, 0x02, 0x04, 0x4C, 0x7B, 0x0F, 0xF1, 0x02, 0xA4, + 0x40, 0x02, 0x04, 0x0C, 0x8F, 0xBC, 0x88, 0x16, 0x02, 0xFF, 0x07, 0x8F, 0x7F, 0x78, 0x18, 0x1B, + 0x1B, 0x48, 0x20, 0x41, 0xDA, 0xDF, 0xB9, 0x77, 0x66, 0x57, 0x2B, 0xD9, 0x3C, 0x7E, 0x65, 0x77, + 0xEE, 0xCC, 0x9D, 0x33, 0x33, 0xF7, 0x9E, 0xF2, 0x2D, 0x9F, 0x6F, 0x3B, 0x00, 0x02, 0x00, 0x64, + 0x50, 0x03, 0x04, 0x78, 0x6A, 0xC7, 0x9E, 0x6A, 0xFD, 0x1E, 0xA6, 0x29, 0x02, 0xF0, 0x9A, 0x77, + 0xE1, 0xD6, 0xED, 0x47, 0x4E, 0x1E, 0x3E, 0xE5, 0xFF, 0xD5, 0xB1, 0xDF, 0x00, 0xF0, 0x07, 0xAF, + 0x07, 0x80, 0xBC, 0xE6, 0xC8, 0x99, 0x3B, 0x63, 0xAF, 0xFF, 0xCD, 0xC7, 0x9E, 0x01, 0xE0, 0x95, + 0x5F, 0x04, 0x00, 0x9D, 0xBF, 0xE1, 0xD4, 0xF1, 0x93, 0xEF, 0xFB, 0xF6, 0xB5, 0xFF, 0xD9, 0xFD, + 0x0C, 0x7F, 0xFF, 0xE8, 0xF1, 0x5B, 0xEE, 0xB9, 0x21, 0xF2, 0x96, 0x57, 0x75, 0xF1, 0x7B, 0xFC, + 0xF9, 0x99, 0xF3, 0x27, 0x8E, 0x9E, 0x3C, 0x7B, 0xEC, 0x0B, 0xC2, 0xF5, 0xF8, 0x7A, 0x3F, 0x07, + 0x40, 0xF9, 0xE2, 0x89, 0x63, 0x87, 0x8F, 0x1E, 0x2F, 0xDE, 0xF5, 0x49, 0xFC, 0x5D, 0x7C, 0x0D, + 0xD0, 0x3A, 0x81, 0x1B, 0x58, 0x0E, 0xDD, 0x0A, 0x00, 0x4C, 0xE1, 0xF7, 0xA9, 0x13, 0x27, 0xEF, + 0x3C, 0xFB, 0x5F, 0xF6, 0x33, 0x0D, 0x00, 0x1E, 0xC5, 0x9F, 0x13, 0xFF, 0x74, 0xCB, 0x6D, 0x47, + 0x0E, 0x83, 0x4D, 0xF4, 0x5F, 0x00, 0x70, 0x2F, 0xEE, 0x0F, 0xF1, 0x83, 0x93, 0x87, 0xCF, 0x9E, + 0x82, 0xF7, 0xC0, 0x1F, 0xE0, 0xEF, 0x2F, 0xE1, 0xEF, 0xC7, 0x6E, 0x3D, 0x7C, 0xF2, 0x58, 0x3D, + 0x7D, 0xF4, 0x53, 0xF8, 0xFD, 0x09, 0xDC, 0x9F, 0xE7, 0x4F, 0xDD, 0x76, 0xC7, 0x9D, 0x9D, 0xCD, + 0x9D, 0x3F, 0x03, 0xE0, 0xC1, 0x87, 0xF0, 0x7B, 0xF5, 0xD4, 0xE9, 0x63, 0xA7, 0x7E, 0x4D, 0x40, + 0x1D, 0xF7, 0xE7, 0x2F, 0xF1, 0xF7, 0x59, 0x6F, 0xAC, 0xF8, 0x58, 0xFA, 0x8F, 0x7F, 0x50, 0xAE, + 0x53, 0xBA, 0xBF, 0xC2, 0xD7, 0xFC, 0x17, 0xDC, 0x02, 0xDE, 0xBB, 0x84, 0x9E, 0x5C, 0x7B, 0x5D, + 0xDD, 0xB3, 0x6A, 0x53, 0x35, 0xE2, 0x61, 0xFC, 0x96, 0x00, 0xC8, 0xFB, 0x85, 0xF7, 0x1B, 0xE2, + 0xE1, 0x55, 0x1B, 0x5F, 0xE7, 0xFC, 0xEA, 0x9E, 0x0B, 0xAF, 0xA2, 0x6A, 0xC3, 0xF6, 0x4B, 0x7F, + 0xFF, 0xE6, 0xB5, 0xFC, 0x1B, 0xB8, 0x19, 0x90, 0xE0, 0x30, 0x3E, 0x10, 0xBE, 0x5B, 0x1F, 0xF0, + 0xB8, 0xED, 0x18, 0xF8, 0x1A, 0x7E, 0x47, 0xE0, 0x33, 0x0B, 0xA2, 0xF5, 0xEF, 0x4F, 0x80, 0xF0, + 0xF0, 0x0C, 0x02, 0x1F, 0x38, 0x32, 0x3C, 0x47, 0x78, 0x25, 0x5E, 0x3E, 0x3C, 0x27, 0xC0, 0x41, + 0xF0, 0x99, 0xE1, 0x39, 0x09, 0x72, 0xB0, 0x38, 0x3C, 0xA7, 0x40, 0x1F, 0xDE, 0x31, 0x3C, 0xA7, + 0x71, 0xFB, 0xDF, 0xAD, 0xF7, 0x25, 0x3C, 0xE8, 0xA9, 0xF7, 0x2C, 0x82, 0xAB, 0x86, 0xE7, 0x08, + 0x30, 0xE0, 0xDE, 0xE1, 0x39, 0x01, 0xCA, 0xE0, 0xF5, 0xC3, 0x73, 0x12, 0x98, 0xD0, 0x19, 0x9E, + 0x53, 0x20, 0x06, 0xF7, 0x0C, 0xCF, 0x69, 0xDC, 0xFE, 0x71, 0xFC, 0x4D, 0x48, 0x72, 0xC3, 0x7E, + 0x0E, 0xCE, 0x07, 0xFD, 0x1C, 0x9C, 0x0F, 0xFA, 0x39, 0x38, 0x1F, 0xF4, 0x73, 0x70, 0x3E, 0xE8, + 0xE7, 0xE0, 0x7C, 0xD0, 0xCF, 0xC1, 0xB9, 0xD7, 0xCF, 0xC5, 0x63, 0xB7, 0x1E, 0x3B, 0x7D, 0xF8, + 0xCE, 0x63, 0x47, 0x63, 0xD7, 0xDF, 0x13, 0x5B, 0xB8, 0xED, 0xD6, 0x3B, 0x6F, 0x3B, 0x7E, 0xFA, + 0xF0, 0xA9, 0x13, 0xC7, 0x4E, 0xC7, 0x1A, 0x95, 0x26, 0x58, 0xC4, 0x13, 0x75, 0x2B, 0x3E, 0x4E, + 0xE3, 0xE9, 0xBB, 0x13, 0xBF, 0x1E, 0x05, 0x31, 0x70, 0x3D, 0xB8, 0x07, 0x3F, 0x2F, 0x80, 0xDB, + 0xF0, 0x27, 0x77, 0xE2, 0xE7, 0xE3, 0xDE, 0xA7, 0xA7, 0xC0, 0x09, 0xEF, 0x7B, 0x31, 0xD0, 0x00, + 0x15, 0xD0, 0x9C, 0x3D, 0x7C, 0xCB, 0x2D, 0x37, 0x0E, 0xAF, 0x04, 0x66, 0xF1, 0xE7, 0xB7, 0xE0, + 0xFF, 0x1B, 0x2F, 0xFF, 0xEE, 0xEE, 0x63, 0xC7, 0xEF, 0xBA, 0xE5, 0xF0, 0x69, 0xB0, 0x1B, 0xBF, + 0x39, 0x0E, 0xEE, 0xC2, 0x5F, 0x38, 0x0C, 0x4E, 0x4F, 0xDF, 0x72, 0xE7, 0x1D, 0xF7, 0xDC, 0xF1, + 0xA2, 0x9E, 0xC4, 0x62, 0x1B, 0xAF, 0x18, 0x5B, 0xFB, 0xE9, 0x34, 0xFE, 0xD1, 0x9D, 0xE0, 0x0E, + 0xDC, 0xA3, 0x3B, 0x7E, 0x7F, 0x9F, 0xF0, 0x6B, 0xEC, 0x77, 0xF5, 0x05, 0x7F, 0x72, 0x59, 0x37, + 0x5E, 0xF2, 0x6E, 0xFF, 0x37, 0x7F, 0xFB, 0x3B, 0x87, 0xD0, 0xAC, 0xD6, 0x5B, 0xD5, 0xF1, 0xFA, + 0xFF, 0x8B, 0x5E, 0x37, 0x41, 0x15, 0xD4, 0x41, 0x0B, 0x3F, 0x8F, 0x83, 0xFA, 0xFF, 0x97, 0xBE, + 0x61, 0xE2, 0xE9, 0x53, 0x14, 0x49, 0x20, 0x50, 0x3A, 0x33, 0x1F, 0x7B, 0x8A, 0x48, 0xCF, 0x27, + 0x0F, 0x9F, 0xF0, 0x25, 0x4F, 0x1C, 0x9A, 0x2B, 0x97, 0xD6, 0xDF, 0x0F, 0xDE, 0xC6, 0x62, 0x9F, + 0x5A, 0xFD, 0xCB, 0x31, 0xFD, 0xA3, 0x7D, 0xD8, 0x1A, 0x73, 0xDF, 0x3D, 0xD5, 0x1F, 0xD3, 0x9F, + 0x82, 0x2D, 0xB7, 0xB1, 0x5C, 0x82, 0x4F, 0x2D, 0x9C, 0x89, 0x2D, 0xE2, 0x5F, 0x2E, 0x1C, 0x3E, + 0x11, 0x3B, 0xE0, 0xFE, 0x30, 0x39, 0xF6, 0x14, 0x4A, 0xBB, 0x5F, 0x38, 0x36, 0xB6, 0x5C, 0xEE, + 0x43, 0xF8, 0xDA, 0x4F, 0xC1, 0xD5, 0x47, 0x31, 0x4D, 0xD6, 0x31, 0xB1, 0x3F, 0x4B, 0xC4, 0x30, + 0xCD, 0x31, 0x60, 0xB2, 0x1F, 0x64, 0xC8, 0xBF, 0x03, 0x34, 0xF5, 0x77, 0x90, 0x22, 0x11, 0x81, + 0x18, 0x1A, 0x41, 0x80, 0xE0, 0x3F, 0x62, 0x7A, 0x84, 0x60, 0xE1, 0x4C, 0xB5, 0xED, 0x03, 0xBD, + 0x6E, 0xAF, 0x0B, 0xAB, 0xDD, 0x0B, 0x5D, 0xF7, 0x00, 0xEA, 0x85, 0x2E, 0x7E, 0x8C, 0xD4, 0x3E, + 0xC6, 0x02, 0xAA, 0xD8, 0xD0, 0xE2, 0x5A, 0x16, 0x1F, 0x75, 0xF4, 0x17, 0xF5, 0x0B, 0xEF, 0x27, + 0x62, 0xBF, 0xFD, 0x01, 0x3E, 0xBB, 0x30, 0x87, 0xEF, 0x31, 0xBB, 0xFA, 0x73, 0xF0, 0x1F, 0xE8, + 0x69, 0xCC, 0xD9, 0x3E, 0x30, 0xDB, 0x0F, 0x09, 0xC0, 0x86, 0x0C, 0x81, 0x1F, 0xB4, 0xDF, 0xA6, + 0xFC, 0x1A, 0x03, 0x11, 0x03, 0x98, 0x15, 0x51, 0x66, 0xA1, 0xB6, 0x76, 0x93, 0x33, 0x3D, 0x1F, + 0xAC, 0x5E, 0x50, 0xCF, 0xE3, 0x3B, 0xA8, 0x17, 0xA0, 0xA6, 0x8F, 0xE3, 0x07, 0xAC, 0x54, 0xF0, + 0x9D, 0xFC, 0x1A, 0x55, 0x34, 0x14, 0x54, 0x25, 0x7A, 0xC8, 0x60, 0xE8, 0x64, 0x22, 0xD3, 0x1C, + 0xED, 0x11, 0x8E, 0xFD, 0x0C, 0x45, 0x9F, 0x16, 0x05, 0x8E, 0xCB, 0x17, 0x0A, 0x63, 0x47, 0x78, + 0x3A, 0x9A, 0x89, 0xC5, 0x89, 0x14, 0xED, 0xA0, 0xA7, 0xFF, 0xE9, 0x17, 0x5B, 0xCE, 0xDC, 0x75, + 0xCD, 0x35, 0xE1, 0x70, 0xE4, 0xC2, 0x63, 0xB3, 0xA8, 0x6D, 0x05, 0x7C, 0x3E, 0x14, 0x30, 0xA6, + 0x70, 0xAF, 0xBA, 0xF0, 0x2B, 0xF0, 0x30, 0xEE, 0x95, 0x3B, 0xF2, 0x64, 0x5F, 0xA4, 0x49, 0x84, + 0x59, 0x91, 0x59, 0xA1, 0x11, 0x77, 0x16, 0x9C, 0x71, 0xBB, 0xD0, 0xF5, 0x01, 0x7C, 0x4F, 0xEF, + 0xAE, 0x2C, 0x4D, 0x15, 0xA1, 0x02, 0xDB, 0x59, 0x7C, 0xC0, 0xC3, 0xF5, 0xBD, 0x62, 0x1A, 0x1F, + 0xE8, 0xE9, 0x5F, 0xF3, 0x2F, 0xA8, 0xF8, 0x70, 0xE5, 0x45, 0x12, 0x3F, 0xA5, 0xD1, 0x67, 0x40, + 0x10, 0x44, 0xC1, 0xD7, 0xFA, 0x47, 0x74, 0x99, 0x04, 0x8E, 0x8D, 0x7C, 0x7E, 0xBF, 0x2F, 0xCA, + 0xB1, 0x21, 0x14, 0xE1, 0x85, 0x70, 0x58, 0xC0, 0x2D, 0x96, 0x7B, 0x86, 0x4C, 0x4D, 0x95, 0x44, + 0xCB, 0x12, 0x7D, 0x7E, 0x14, 0xF0, 0x3E, 0x0F, 0xD2, 0x78, 0xBA, 0x03, 0x01, 0x26, 0x1C, 0xD2, + 0x35, 0x44, 0x41, 0x3E, 0xE8, 0x73, 0x4C, 0x83, 0x02, 0xE3, 0xD1, 0x88, 0xAA, 0x90, 0x14, 0xC1, + 0xCB, 0x12, 0xCF, 0xD1, 0x14, 0x15, 0xF0, 0xDB, 0x84, 0x25, 0x89, 0x02, 0x4B, 0x30, 0x10, 0xF4, + 0x9C, 0x2E, 0x7E, 0x80, 0xAA, 0xD3, 0xBD, 0xE0, 0x9D, 0xE1, 0xE7, 0xC7, 0x2B, 0xF2, 0xE7, 0xD7, + 0xFF, 0x7F, 0x3B, 0x78, 0xAD, 0xB8, 0x27, 0xBF, 0xFF, 0x83, 0x61, 0xA3, 0xF7, 0x1E, 0x9F, 0xAF, + 0x8D, 0x3C, 0x26, 0xE3, 0x91, 0x33, 0x49, 0xA6, 0x81, 0x8F, 0x64, 0xDB, 0x3B, 0xDA, 0x0D, 0xEF, + 0x68, 0x30, 0xF8, 0x50, 0x20, 0xFE, 0x08, 0xA5, 0x95, 0x53, 0xA9, 0x53, 0xF2, 0xA9, 0xC2, 0x42, + 0x61, 0x1F, 0x3E, 0x4E, 0x79, 0xEF, 0x6E, 0xCF, 0x2F, 0xE4, 0xF7, 0xBA, 0x2D, 0x7B, 0x93, 0x7B, + 0xE0, 0xAF, 0x17, 0xDE, 0xB7, 0xF0, 0x05, 0xFC, 0xB7, 0xFE, 0x82, 0x67, 0x3D, 0xB6, 0xFA, 0x72, + 0xB4, 0x87, 0xA8, 0x80, 0xAD, 0x60, 0x2F, 0x38, 0x04, 0x5E, 0xD1, 0x9F, 0x3D, 0xB0, 0x6D, 0x22, + 0x29, 0x6F, 0xDF, 0xA6, 0x14, 0xEA, 0x33, 0x33, 0xD5, 0x2A, 0xA7, 0x1C, 0xB8, 0xE6, 0x68, 0xDF, + 0xD7, 0x7C, 0xD3, 0x4A, 0xC4, 0xD1, 0x67, 0x66, 0xCC, 0xFA, 0x03, 0xD7, 0x1D, 0xDC, 0x5D, 0x10, + 0x78, 0x96, 0xE0, 0xB6, 0x17, 0x0B, 0x68, 0x2E, 0x1A, 0x51, 0xD0, 0xD5, 0x07, 0x17, 0xEB, 0xE4, + 0xB2, 0x4F, 0xD9, 0x72, 0xA0, 0x1A, 0x92, 0xC3, 0xD0, 0x37, 0x24, 0x9F, 0x1E, 0x54, 0xBF, 0xA7, + 0x7E, 0x6F, 0xC4, 0x9D, 0x98, 0x6E, 0xB7, 0xEA, 0x1E, 0x4E, 0x57, 0x3D, 0x8F, 0xA9, 0xA9, 0x77, + 0xA1, 0x77, 0xA1, 0x8B, 0x9F, 0xCE, 0xBB, 0x24, 0xA5, 0x76, 0x01, 0x7E, 0x06, 0x78, 0x98, 0xDE, + 0x58, 0xDD, 0xC1, 0x1E, 0xF6, 0x51, 0xC5, 0xB4, 0x0C, 0x15, 0x84, 0x0F, 0x68, 0x39, 0x32, 0x64, + 0xDA, 0x32, 0x4C, 0x26, 0xAA, 0xB0, 0x02, 0x31, 0x99, 0x41, 0xC7, 0x76, 0x9A, 0x55, 0x88, 0x29, + 0xAE, 0xD5, 0x9E, 0x82, 0x3D, 0x98, 0xED, 0x11, 0x32, 0xB4, 0xA6, 0x60, 0xA3, 0x1E, 0x41, 0x96, + 0xE9, 0xFE, 0x2C, 0x93, 0xA5, 0x2D, 0xD3, 0x8E, 0x22, 0xDB, 0x32, 0xD3, 0xD9, 0x04, 0xFE, 0xD0, + 0x74, 0x8C, 0x0A, 0xCC, 0x46, 0xF1, 0xB5, 0xDA, 0xAD, 0xE6, 0x28, 0x1A, 0xE5, 0xA2, 0x8E, 0x42, + 0x45, 0xDA, 0x09, 0x88, 0x7C, 0x39, 0x93, 0xD2, 0x55, 0x2D, 0x5B, 0x0B, 0x96, 0x0B, 0xCE, 0xCB, + 0xF8, 0xE8, 0xCC, 0x13, 0xEA, 0x96, 0x50, 0xCE, 0x8A, 0x4A, 0xD7, 0x42, 0x4D, 0xF3, 0xF9, 0x48, + 0x12, 0x7F, 0x18, 0x1E, 0x8B, 0x15, 0x03, 0x69, 0xDD, 0x09, 0x07, 0xCB, 0x1C, 0x24, 0x5F, 0x6F, + 0x6F, 0xBD, 0xF8, 0x45, 0x4A, 0xF6, 0xA5, 0x3B, 0x4F, 0x11, 0x63, 0x61, 0x84, 0xA0, 0xD5, 0xFB, + 0xB8, 0x9C, 0x30, 0x24, 0xCA, 0x9F, 0x50, 0x75, 0xA3, 0x2D, 0xF8, 0xB5, 0xBB, 0x08, 0x24, 0xF3, + 0x6A, 0xC1, 0x17, 0x14, 0x17, 0xEC, 0xBE, 0xF6, 0x74, 0x91, 0xC9, 0xCC, 0x06, 0x36, 0xA7, 0x2C, + 0x87, 0xAE, 0x2D, 0x0A, 0xBC, 0x22, 0xDB, 0xED, 0x00, 0x81, 0x44, 0x21, 0x6A, 0x6A, 0xBA, 0xC9, + 0x09, 0x62, 0xCE, 0xDF, 0x6C, 0x29, 0x81, 0x4C, 0x95, 0x4B, 0x2F, 0x16, 0xFE, 0xF7, 0xFB, 0x84, + 0x74, 0xBC, 0x19, 0xB8, 0xF8, 0x4C, 0xA4, 0x4E, 0xD6, 0xEA, 0xC5, 0x02, 0x1D, 0x6C, 0xB2, 0xAE, + 0xE6, 0x4B, 0xAE, 0xFE, 0x9C, 0xF8, 0x28, 0xFA, 0x1C, 0x28, 0x61, 0x01, 0x76, 0x13, 0x78, 0xA0, + 0xDF, 0xD8, 0xB7, 0x7B, 0x5B, 0xD9, 0xD4, 0xF9, 0xCD, 0xE5, 0x80, 0xC6, 0x64, 0xF2, 0xF1, 0xA3, + 0xC7, 0x0F, 0x8D, 0xB5, 0xC7, 0x5B, 0xA8, 0x3B, 0x39, 0xD9, 0xDD, 0x75, 0x30, 0x76, 0x73, 0x2A, + 0x1E, 0xCD, 0x1F, 0x8A, 0xAC, 0x20, 0xCC, 0xF5, 0xE1, 0x7C, 0xA2, 0xD3, 0x65, 0x21, 0xBF, 0x2E, + 0x37, 0x30, 0x43, 0x57, 0x2F, 0x80, 0x73, 0xE0, 0x38, 0x5C, 0xE9, 0x5D, 0xF0, 0x24, 0xC7, 0x39, + 0x70, 0x04, 0xCE, 0xF4, 0xCE, 0xAF, 0x91, 0x9C, 0xFB, 0x0F, 0x06, 0xBC, 0x0E, 0xBC, 0x15, 0x19, + 0xAC, 0x8B, 0xB7, 0x32, 0x37, 0xF3, 0x98, 0x0C, 0x4D, 0x19, 0x0D, 0x59, 0xBE, 0x39, 0x85, 0xF0, + 0x72, 0x28, 0xD0, 0x8C, 0x10, 0x8D, 0x7A, 0x0F, 0x8E, 0x56, 0xF0, 0x2A, 0xD1, 0x49, 0x26, 0xDB, + 0x6E, 0xE1, 0xC5, 0x80, 0x69, 0x85, 0xC4, 0xAB, 0x41, 0xD2, 0x98, 0x59, 0x5B, 0x3A, 0x5E, 0xAA, + 0xB6, 0x61, 0xCA, 0x84, 0xF7, 0xBB, 0x29, 0x18, 0x85, 0x0C, 0x5E, 0xA3, 0x08, 0x6A, 0xD4, 0xF1, + 0x82, 0x64, 0x92, 0x09, 0x05, 0x0E, 0x7F, 0x04, 0xBF, 0x14, 0x1B, 0xE3, 0xED, 0xA5, 0xFE, 0x35, + 0x9B, 0x11, 0xED, 0x73, 0x0A, 0x32, 0xC5, 0xF9, 0x23, 0x7A, 0x39, 0xD4, 0xD3, 0x48, 0x7A, 0xEE, + 0x5A, 0x46, 0xA5, 0x7C, 0xAC, 0x7F, 0x53, 0x73, 0x74, 0x77, 0x06, 0xF6, 0x17, 0x3A, 0xD7, 0xFB, + 0xAB, 0x62, 0x49, 0x8B, 0x97, 0x7C, 0x4A, 0x24, 0x66, 0x9D, 0xB9, 0xED, 0x2F, 0x36, 0xD1, 0x11, + 0xF6, 0xAB, 0x47, 0x9D, 0x62, 0x37, 0x72, 0xD5, 0x96, 0x7A, 0x5E, 0x94, 0x19, 0xBD, 0x56, 0x49, + 0x2B, 0x8D, 0xF8, 0xF4, 0x71, 0x45, 0xB7, 0x18, 0x7B, 0x6F, 0x21, 0xBA, 0x6B, 0x1A, 0xB1, 0xE3, + 0x3B, 0xA6, 0x59, 0xBD, 0xFE, 0xEA, 0x3C, 0x4D, 0xB3, 0xB9, 0x74, 0xB0, 0x41, 0xE7, 0x97, 0x7C, + 0xDD, 0x9C, 0x1E, 0xD9, 0x16, 0x8D, 0x4F, 0x3E, 0x8A, 0x48, 0x5E, 0xCD, 0xF7, 0xB6, 0x3C, 0x72, + 0xFD, 0x9E, 0x57, 0x26, 0x66, 0xD5, 0xBE, 0xBF, 0x36, 0x9B, 0x76, 0x38, 0x02, 0xFD, 0xC9, 0x5B, + 0xA0, 0x72, 0x3B, 0xC1, 0xA2, 0x8B, 0xF3, 0xFB, 0x0F, 0x19, 0x61, 0xF3, 0xE1, 0x46, 0xFE, 0xAA, + 0x34, 0x49, 0x2A, 0x85, 0x74, 0x79, 0x6F, 0x56, 0x3E, 0x90, 0x2C, 0xBF, 0x97, 0x20, 0x65, 0xA1, + 0x90, 0xBC, 0xDA, 0x95, 0x40, 0xF9, 0xD5, 0xE7, 0x88, 0x22, 0xFA, 0x63, 0x8C, 0xA0, 0x76, 0x82, + 0x53, 0xFD, 0x56, 0xBF, 0x97, 0xA7, 0x41, 0xC3, 0xE9, 0xCE, 0xF4, 0xFA, 0xA5, 0x5C, 0x9A, 0x22, + 0xB3, 0x60, 0xEB, 0x96, 0x8C, 0x30, 0x6D, 0xA7, 0xFB, 0xB3, 0x33, 0xC9, 0xC9, 0xEE, 0x11, 0x23, + 0xBC, 0xD0, 0xDE, 0xB9, 0x63, 0x86, 0x98, 0x46, 0x54, 0x1B, 0x85, 0xD3, 0xC9, 0xA2, 0x50, 0x82, + 0xC6, 0x1A, 0x03, 0x75, 0xBD, 0xC5, 0x5A, 0xE3, 0x1A, 0x57, 0xDC, 0x7B, 0x92, 0xDE, 0x7B, 0xC6, + 0x2D, 0xDE, 0x0A, 0xAD, 0x73, 0xCD, 0x2E, 0xC3, 0x15, 0x8E, 0x44, 0xD2, 0xC1, 0xEB, 0x93, 0x4C, + 0x54, 0x28, 0xCC, 0x1F, 0x98, 0x39, 0x2A, 0x84, 0xF7, 0x8A, 0xE7, 0xD6, 0xC1, 0xB3, 0x6B, 0x99, + 0x0A, 0xAC, 0x50, 0x49, 0x8F, 0x27, 0xF0, 0xE4, 0xF7, 0x10, 0x9E, 0x77, 0xBC, 0x64, 0xDE, 0x1B, + 0x8F, 0x99, 0x88, 0xA2, 0x3F, 0x10, 0x8F, 0x1D, 0x80, 0x63, 0xAF, 0xDA, 0x52, 0x34, 0x5B, 0x39, + 0x7F, 0x2B, 0x67, 0x8F, 0x76, 0x45, 0x35, 0x91, 0x30, 0xC5, 0xCD, 0xDB, 0xA6, 0x3A, 0x55, 0x95, + 0x29, 0xB6, 0x8C, 0xDC, 0x66, 0x9E, 0xB3, 0x43, 0xC1, 0x08, 0x14, 0x4B, 0x89, 0xC8, 0xFC, 0xE8, + 0xA6, 0xAD, 0xE8, 0x15, 0xD4, 0xAB, 0xD0, 0x1D, 0x27, 0x16, 0x26, 0x37, 0xDB, 0x5A, 0xA2, 0x90, + 0xA0, 0x20, 0xFC, 0x40, 0x20, 0x10, 0x4F, 0xDA, 0x13, 0xFB, 0xEE, 0x4D, 0xF2, 0x02, 0x1F, 0xCA, + 0xD4, 0x7D, 0xE9, 0xA5, 0x22, 0xC7, 0x1A, 0xC1, 0x68, 0x42, 0xCB, 0xEF, 0x2F, 0x85, 0x4C, 0xE8, + 0x0B, 0xB3, 0xAA, 0xAF, 0xAA, 0x8A, 0x86, 0xCE, 0x22, 0x21, 0x1F, 0x72, 0x26, 0x4C, 0x04, 0x23, + 0xBB, 0x6E, 0xBA, 0x9D, 0xC8, 0xD5, 0x13, 0x1D, 0x9B, 0x44, 0x54, 0x20, 0xA2, 0x60, 0xDC, 0xB6, + 0x04, 0xBF, 0x02, 0x9E, 0xF6, 0xB4, 0x43, 0xB0, 0xCF, 0x62, 0x08, 0xCA, 0xAC, 0x0C, 0xF4, 0x02, + 0xD6, 0x4C, 0x60, 0xA0, 0x89, 0xF0, 0x57, 0xB1, 0x26, 0x82, 0xED, 0xA7, 0xD7, 0x54, 0x01, 0xFE, + 0xD5, 0xF8, 0xEA, 0x2B, 0x61, 0x91, 0xD0, 0x30, 0xFE, 0x8B, 0xF7, 0x05, 0x13, 0xF8, 0x91, 0x68, + 0x56, 0x56, 0xC8, 0xEA, 0xF0, 0x87, 0x78, 0x52, 0x87, 0xBF, 0x8D, 0x88, 0x54, 0x91, 0x62, 0xB0, + 0x7C, 0xA9, 0x40, 0x2C, 0x5C, 0x10, 0x26, 0x4C, 0x84, 0x85, 0x09, 0x81, 0xA7, 0x03, 0x3A, 0xB0, + 0xD8, 0xF5, 0x8B, 0x72, 0x30, 0x67, 0x88, 0x02, 0x2F, 0xDA, 0x41, 0x9F, 0xC8, 0x70, 0x8F, 0xA8, + 0xF1, 0x82, 0x9D, 0x4A, 0xA7, 0x7C, 0x55, 0x5B, 0x50, 0x12, 0xDB, 0xC7, 0x33, 0xD9, 0xFA, 0x9D, + 0xD5, 0xE6, 0x7D, 0x57, 0x4D, 0x07, 0x04, 0xB5, 0x17, 0x59, 0x38, 0x75, 0xDB, 0xD2, 0xF2, 0x1F, + 0x5F, 0x33, 0xEE, 0x62, 0xD1, 0xD5, 0x57, 0x82, 0x17, 0xD6, 0xEE, 0x6F, 0x09, 0x0A, 0x42, 0xBE, + 0xCA, 0x8A, 0xF0, 0x12, 0xF7, 0xB7, 0x70, 0xDF, 0xB1, 0x94, 0x92, 0x09, 0x85, 0x98, 0xC2, 0xB7, + 0xAF, 0xA0, 0x2A, 0xC4, 0x8B, 0x15, 0xC1, 0xEC, 0x61, 0xFF, 0x84, 0xD3, 0x39, 0x3B, 0x20, 0xD0, + 0xDC, 0xA3, 0xA9, 0x31, 0x9B, 0x0F, 0x64, 0x52, 0x62, 0x24, 0xDC, 0x08, 0xE6, 0x0D, 0x41, 0x87, + 0x5F, 0xDC, 0x59, 0x6B, 0x5F, 0x9F, 0xDA, 0x32, 0xEB, 0x13, 0xD5, 0x7E, 0xFF, 0x8D, 0xB7, 0x2D, + 0x15, 0xF7, 0xDD, 0xBD, 0x32, 0x66, 0x58, 0x81, 0x6A, 0x62, 0xDB, 0x58, 0x66, 0x12, 0xDF, 0x3F, + 0x09, 0xDF, 0x02, 0xF7, 0xA3, 0x2F, 0x83, 0x49, 0xF0, 0x70, 0xBF, 0x5B, 0x4F, 0xA7, 0xA2, 0x41, + 0x9E, 0x03, 0x9D, 0x6C, 0x54, 0x46, 0x80, 0x2E, 0x44, 0x4B, 0x4D, 0x55, 0x05, 0x25, 0x7B, 0xB4, + 0x24, 0x33, 0x0C, 0x28, 0x75, 0x40, 0x49, 0xB5, 0x9A, 0xCF, 0xC7, 0x47, 0x0A, 0x7B, 0xAB, 0x95, + 0x52, 0x53, 0x1B, 0x45, 0x25, 0x0C, 0xC0, 0x56, 0xEC, 0xF6, 0x59, 0x98, 0x1A, 0xD0, 0xA1, 0xDB, + 0xE9, 0xAE, 0xDB, 0xEB, 0x2E, 0x26, 0xC4, 0xAE, 0x27, 0xBD, 0x87, 0x58, 0x40, 0xED, 0x0E, 0xE5, + 0xC4, 0x46, 0x71, 0xB1, 0x2E, 0x2F, 0xDC, 0x11, 0x4E, 0xA5, 0x30, 0x51, 0x62, 0xFE, 0xC6, 0x42, + 0x00, 0x8B, 0x6D, 0xCB, 0x9D, 0xEB, 0x4C, 0xD6, 0x15, 0xEC, 0x4C, 0x85, 0xC8, 0xBA, 0x32, 0x81, + 0x76, 0xE5, 0x7A, 0xB3, 0xD5, 0x76, 0xEC, 0x46, 0xBD, 0x9D, 0x99, 0x84, 0xF5, 0x56, 0x83, 0x66, + 0xB0, 0x34, 0x77, 0x3F, 0x73, 0x6C, 0xB8, 0x5F, 0x65, 0xC5, 0x90, 0xE4, 0x04, 0x53, 0x3E, 0x89, + 0xD7, 0x0D, 0xA3, 0x46, 0x12, 0x18, 0x18, 0x48, 0x52, 0xC4, 0xB2, 0x59, 0xC3, 0xEF, 0xD0, 0x56, + 0xC0, 0x0E, 0x4A, 0x94, 0x22, 0xA5, 0x03, 0x2C, 0x17, 0xD1, 0xE6, 0x74, 0x8D, 0x62, 0x1C, 0x41, + 0xB6, 0x15, 0xD5, 0x46, 0x58, 0x7E, 0x50, 0x22, 0x67, 0xA6, 0x38, 0x53, 0x33, 0xF5, 0x89, 0xA2, + 0x4F, 0x88, 0xF1, 0xBA, 0x42, 0x8A, 0x92, 0xC6, 0x48, 0x7A, 0xD4, 0xE2, 0x39, 0x32, 0x98, 0x4B, + 0x8B, 0x71, 0x22, 0x9D, 0x0D, 0xA1, 0x78, 0xD1, 0x2F, 0x38, 0x1C, 0x27, 0x50, 0x56, 0xCC, 0xB5, + 0x3F, 0xAA, 0x98, 0x8D, 0xF3, 0xF0, 0xDF, 0x81, 0x00, 0x76, 0xF6, 0x53, 0x14, 0x09, 0x09, 0x60, + 0x09, 0x3C, 0x43, 0x08, 0x00, 0xD2, 0x18, 0x02, 0x70, 0x88, 0x80, 0x88, 0x65, 0x48, 0x82, 0xE0, + 0xD8, 0x71, 0x02, 0x41, 0x48, 0x6D, 0x84, 0x64, 0x9E, 0xFA, 0x57, 0xBF, 0xE7, 0x3E, 0x46, 0xB0, + 0x90, 0xA5, 0xE1, 0xE8, 0x00, 0x11, 0xE0, 0xA9, 0x10, 0x29, 0xAC, 0xD5, 0x92, 0x56, 0xB2, 0x99, + 0x6C, 0x36, 0x9A, 0x0D, 0xAB, 0x81, 0xF2, 0x5F, 0x3D, 0xF4, 0x55, 0xF7, 0xE1, 0x3D, 0xB9, 0xAB, + 0xB6, 0xFA, 0x19, 0xF0, 0x03, 0xF0, 0xA7, 0xC0, 0x04, 0xD1, 0x3E, 0x6F, 0x88, 0x1C, 0xAD, 0x76, + 0x56, 0xA8, 0xEE, 0x06, 0x6A, 0xF7, 0x66, 0xD4, 0xC2, 0x34, 0xDB, 0x56, 0xC8, 0xAC, 0xAB, 0xC9, + 0xAA, 0xDE, 0x34, 0xB9, 0x6C, 0xFD, 0x05, 0x95, 0x0E, 0x4B, 0x2D, 0x4D, 0x08, 0x56, 0x75, 0xD9, + 0xA8, 0xF8, 0xF5, 0x59, 0x41, 0x22, 0x35, 0x36, 0xA5, 0x09, 0x11, 0x2B, 0x94, 0x11, 0x05, 0x2D, + 0x2A, 0x09, 0xCD, 0xA4, 0xE3, 0x8E, 0x2E, 0x04, 0x7E, 0x03, 0xDF, 0x08, 0xEF, 0x01, 0x1A, 0xE8, + 0xF4, 0x7D, 0x02, 0xD0, 0x54, 0x00, 0x44, 0x4E, 0xE0, 0xB9, 0xC7, 0x44, 0x4D, 0x55, 0x26, 0x69, + 0xB1, 0xB7, 0x42, 0xF7, 0xD7, 0xEE, 0xA9, 0xBA, 0x4B, 0x8E, 0x0F, 0xE0, 0xAD, 0x75, 0xD7, 0x15, + 0x36, 0xB8, 0x07, 0xBA, 0xE0, 0x0A, 0x1A, 0x6F, 0x0D, 0x21, 0x06, 0x25, 0xF8, 0xFE, 0x8D, 0x1E, + 0x84, 0x6F, 0x34, 0xF9, 0x06, 0x62, 0xA9, 0x50, 0x27, 0xB7, 0xB0, 0xE7, 0xB8, 0x93, 0xDF, 0x39, + 0xD2, 0x84, 0xB7, 0xFA, 0xA4, 0x09, 0x24, 0x70, 0x34, 0x09, 0xEF, 0xE6, 0x49, 0x8C, 0x5D, 0xF1, + 0xDD, 0x8B, 0x18, 0x83, 0xFE, 0x10, 0x8F, 0x51, 0x02, 0x85, 0xBE, 0x22, 0x60, 0xE3, 0x0A, 0xD1, + 0x42, 0x67, 0x05, 0x12, 0x2C, 0xA4, 0x2F, 0x07, 0x9D, 0xC0, 0x25, 0x31, 0x7C, 0x33, 0x19, 0x43, + 0xBE, 0xF6, 0x06, 0x84, 0xF9, 0xC3, 0x0D, 0xB0, 0xB2, 0xB9, 0x11, 0x49, 0x42, 0xC0, 0xAC, 0xBE, + 0x80, 0x76, 0x60, 0xAA, 0xD7, 0x81, 0xDD, 0xA7, 0x45, 0x6C, 0xA3, 0x8B, 0x33, 0x58, 0x86, 0x0E, + 0x59, 0xCD, 0x10, 0x3D, 0xE8, 0x88, 0x39, 0x0D, 0x77, 0x3C, 0xD9, 0xF6, 0x08, 0x0C, 0xED, 0xF0, + 0x27, 0x13, 0x57, 0xBF, 0xFD, 0x70, 0x44, 0x31, 0x9C, 0xAC, 0x79, 0xEC, 0x83, 0x6F, 0xDB, 0x66, + 0x65, 0xD1, 0x97, 0xD3, 0xD5, 0xF2, 0x03, 0xFF, 0xF4, 0xDA, 0x8A, 0x13, 0x66, 0x98, 0x57, 0xFF, + 0xE4, 0xFB, 0x67, 0x69, 0xC6, 0xED, 0xB7, 0xB5, 0xFA, 0x2C, 0xFC, 0x2D, 0x5A, 0x04, 0x35, 0x90, + 0xEB, 0x2B, 0x69, 0x53, 0xE1, 0xD3, 0xC1, 0x32, 0x1D, 0x45, 0xA8, 0x34, 0x4B, 0xCF, 0xB9, 0x48, + 0x07, 0x77, 0x58, 0xBD, 0x30, 0x14, 0xC6, 0xF8, 0x6E, 0x23, 0xAE, 0x9E, 0x74, 0x19, 0x1B, 0x2B, + 0x44, 0x17, 0xB4, 0xB8, 0xA2, 0xD5, 0x93, 0x2B, 0x64, 0xA3, 0x3E, 0x85, 0xDF, 0x57, 0x88, 0x24, + 0x96, 0xC9, 0xED, 0x01, 0x68, 0x81, 0xDF, 0x0F, 0x8F, 0x7F, 0x70, 0xA9, 0x73, 0xDC, 0x3F, 0x5E, + 0xAB, 0xE8, 0x94, 0x22, 0xB2, 0x08, 0xA9, 0xB9, 0x76, 0x28, 0x97, 0xE1, 0x47, 0xA7, 0xF7, 0x06, + 0x14, 0x96, 0x56, 0x94, 0xE2, 0xB8, 0x8F, 0xE6, 0xC7, 0x17, 0xE1, 0x67, 0xFA, 0xA3, 0xCD, 0x9B, + 0xFF, 0xDB, 0x6D, 0xFB, 0x12, 0xAD, 0x03, 0x59, 0x8B, 0xD6, 0xFD, 0x66, 0x22, 0xC0, 0xE8, 0x91, + 0xE2, 0x64, 0xBA, 0xDE, 0xC8, 0xD6, 0x4E, 0x76, 0xC3, 0x14, 0x4B, 0x29, 0x6C, 0x38, 0x00, 0xC5, + 0x69, 0xDC, 0x67, 0x76, 0xF5, 0x79, 0xF0, 0x13, 0xB4, 0x00, 0xFC, 0xA0, 0xD4, 0xD7, 0x6C, 0x0C, + 0x56, 0x11, 0x44, 0x7E, 0x9F, 0x43, 0x00, 0x63, 0x01, 0x2E, 0xBA, 0x4B, 0xEC, 0xEB, 0xC1, 0x01, + 0x38, 0x03, 0x5E, 0xCF, 0x71, 0xBF, 0x03, 0x82, 0x3B, 0xDB, 0x93, 0x58, 0x93, 0x63, 0x15, 0xC2, + 0x64, 0x7B, 0x70, 0x0A, 0x77, 0xD8, 0xB6, 0x30, 0x72, 0xFA, 0xC9, 0x2B, 0x08, 0xDE, 0x51, 0x05, + 0x5E, 0x95, 0x74, 0xC1, 0x48, 0x8D, 0x84, 0x78, 0xD5, 0x42, 0x68, 0xE9, 0xAA, 0xDA, 0x77, 0x9A, + 0xDD, 0xB1, 0x18, 0xA3, 0x89, 0x32, 0xA7, 0xF8, 0x63, 0x92, 0xDF, 0xDA, 0xF3, 0xF6, 0xBF, 0x77, + 0xE7, 0x4B, 0x5B, 0xFD, 0x35, 0xFC, 0x30, 0xDA, 0x8A, 0x79, 0x69, 0xB2, 0x1F, 0x28, 0x65, 0xC3, + 0x1A, 0x08, 0x39, 0x2C, 0xE4, 0xB8, 0x12, 0x05, 0xB6, 0xD6, 0xAA, 0x95, 0xF2, 0x12, 0x05, 0xE3, + 0xDB, 0xD0, 0xC3, 0xEE, 0xFA, 0xF4, 0x3C, 0x22, 0x1B, 0x90, 0xD8, 0x65, 0x30, 0xB0, 0xC6, 0x61, + 0x86, 0xC1, 0xFA, 0xCA, 0x05, 0x15, 0x83, 0xBE, 0x60, 0xC4, 0xE1, 0x76, 0x8C, 0x56, 0x50, 0x76, + 0x0A, 0x43, 0x07, 0xDB, 0x71, 0x49, 0xDF, 0x05, 0x89, 0x3D, 0x04, 0x3F, 0xBC, 0x23, 0x92, 0xDF, + 0xBF, 0x57, 0xCB, 0x09, 0x7E, 0x95, 0xD1, 0x4A, 0xDD, 0x76, 0x8C, 0xF0, 0xDD, 0x8A, 0x25, 0x09, + 0xAD, 0x62, 0xF9, 0x6D, 0xDE, 0x52, 0x93, 0x23, 0xA6, 0xB5, 0x48, 0x15, 0x3A, 0x7B, 0xC6, 0x26, + 0x66, 0xFE, 0xE0, 0x48, 0x46, 0xA4, 0x68, 0x18, 0xD1, 0x28, 0xA3, 0x38, 0xBE, 0x34, 0x1F, 0xA3, + 0x68, 0xE9, 0x90, 0x4C, 0x40, 0x82, 0x30, 0x38, 0x75, 0x33, 0xCB, 0xF0, 0x13, 0x5B, 0x94, 0xF2, + 0xA6, 0xC5, 0x1B, 0x20, 0x26, 0x59, 0x08, 0x84, 0xD5, 0x2F, 0xC3, 0x5D, 0x78, 0x16, 0x47, 0x40, + 0xB1, 0xAF, 0xD6, 0xCA, 0xB9, 0xA8, 0xCF, 0x90, 0x98, 0x48, 0x50, 0x57, 0x93, 0x0B, 0xF4, 0x0E, + 0xB7, 0xFF, 0xE0, 0x4A, 0x99, 0x57, 0x8F, 0xBA, 0xF0, 0x95, 0x70, 0x21, 0x0D, 0x26, 0xB3, 0x01, + 0xBE, 0x71, 0x31, 0x51, 0xFB, 0x12, 0xD4, 0xD9, 0x80, 0x56, 0xB1, 0x5C, 0xB4, 0x4C, 0xB8, 0x85, + 0x8A, 0xD6, 0x3B, 0x0B, 0x51, 0x23, 0x91, 0x2B, 0x33, 0xE2, 0x49, 0x93, 0x95, 0x99, 0xF1, 0x80, + 0x69, 0xF5, 0x6D, 0x4B, 0xD7, 0xB4, 0x93, 0x42, 0xCC, 0xA4, 0x63, 0xE5, 0x74, 0xC6, 0x54, 0x55, + 0xFF, 0x91, 0x77, 0xF9, 0xAA, 0x95, 0x5C, 0x4E, 0xF3, 0x59, 0xE1, 0x9A, 0x19, 0x0C, 0xEE, 0xC8, + 0x21, 0x2B, 0xAA, 0x9A, 0x01, 0xAC, 0x1A, 0x18, 0x56, 0xDB, 0xC3, 0xF0, 0xA4, 0x5E, 0x8F, 0xA6, + 0xAA, 0xA6, 0x24, 0x71, 0xD5, 0xFD, 0xB6, 0xBB, 0x12, 0xFA, 0xEA, 0x33, 0x88, 0x41, 0x07, 0x31, + 0xE5, 0xDE, 0xD2, 0xAF, 0x57, 0x42, 0x96, 0x04, 0x6A, 0x15, 0x2D, 0x58, 0x2B, 0x53, 0x7B, 0x46, + 0x8A, 0x85, 0x8C, 0x5E, 0x2C, 0x4D, 0x1A, 0x7A, 0x27, 0x5B, 0xE6, 0x30, 0x32, 0x45, 0xBC, 0xAA, + 0x68, 0x88, 0x2F, 0xA3, 0x6A, 0x2D, 0xB8, 0x77, 0x45, 0xDA, 0x77, 0x16, 0x5A, 0x97, 0x34, 0x80, + 0xCF, 0xB5, 0x37, 0xAB, 0x03, 0x81, 0xB0, 0x8E, 0x47, 0x3C, 0xFC, 0x08, 0xAF, 0xC4, 0xEF, 0x23, + 0x58, 0xAD, 0x41, 0x17, 0x88, 0xE3, 0x95, 0x22, 0x68, 0xA6, 0x47, 0x30, 0xC9, 0x04, 0xE6, 0x01, + 0xA2, 0x8D, 0xA1, 0xA2, 0x87, 0x08, 0x31, 0x3A, 0x6F, 0x44, 0x31, 0x4B, 0x28, 0xD8, 0xE6, 0x14, + 0xFD, 0x92, 0xA6, 0x73, 0x16, 0xCD, 0x93, 0x81, 0x46, 0x0B, 0xC3, 0x69, 0xF8, 0xA0, 0xB5, 0xA2, + 0xE5, 0x8E, 0x6E, 0x2B, 0xFA, 0xCD, 0x92, 0xA4, 0xEA, 0xB4, 0x41, 0x69, 0xAC, 0x63, 0x06, 0xF2, + 0xE4, 0x83, 0xF8, 0xC3, 0xA4, 0x9E, 0x51, 0x1D, 0x1F, 0x5E, 0xAA, 0x9B, 0xB5, 0x78, 0xA8, 0x54, + 0x29, 0x14, 0x51, 0x47, 0xAF, 0xCC, 0xBE, 0x7A, 0x7F, 0xC2, 0xF1, 0x8D, 0xA9, 0x76, 0x98, 0x4F, + 0x70, 0x29, 0x5D, 0x32, 0x1C, 0x04, 0x5F, 0xB5, 0xEB, 0x6D, 0x13, 0xEE, 0xE8, 0xF9, 0xD5, 0x2F, + 0xC1, 0xF7, 0xE0, 0xD5, 0x2B, 0x81, 0x91, 0xBE, 0x1A, 0x0F, 0xF9, 0x14, 0x1E, 0x70, 0x80, 0xDA, + 0x5C, 0xC8, 0x2C, 0x38, 0x57, 0x0D, 0x58, 0x00, 0x4B, 0xE9, 0x3C, 0x3C, 0x8C, 0x07, 0x03, 0xD6, + 0x57, 0x11, 0x0F, 0xA1, 0x1C, 0x1F, 0x88, 0x0B, 0x8F, 0x7F, 0xB3, 0x8C, 0xE3, 0x2D, 0x16, 0xE1, + 0xD1, 0x1D, 0x16, 0xBB, 0x04, 0xE6, 0x67, 0x14, 0x81, 0x1D, 0xAC, 0xAD, 0xE0, 0x7B, 0x46, 0x05, + 0x3D, 0x1E, 0x96, 0x1B, 0xD9, 0x02, 0x93, 0x2A, 0x76, 0xBB, 0x6C, 0xA4, 0xD5, 0x4D, 0x27, 0x13, + 0xA6, 0x11, 0xBD, 0x7A, 0xBF, 0x14, 0x2B, 0x27, 0x4B, 0x0D, 0x45, 0xB1, 0x27, 0xCC, 0x40, 0xB3, + 0x84, 0xFA, 0xCB, 0x8A, 0xA5, 0xD3, 0x94, 0x9C, 0xD5, 0x9C, 0xD2, 0xA6, 0x86, 0x92, 0xAD, 0xB4, + 0x2B, 0x3E, 0xCB, 0x0C, 0x63, 0xB4, 0x3B, 0xB3, 0xD4, 0x64, 0x8D, 0xC0, 0xE8, 0xD2, 0xBE, 0x80, + 0x9F, 0xE2, 0x09, 0xB7, 0xDF, 0xCE, 0xEA, 0x0B, 0xF0, 0x73, 0x68, 0x1B, 0x18, 0x03, 0xF9, 0xBE, + 0x52, 0xF2, 0x89, 0x44, 0x2B, 0xB7, 0x3C, 0x6E, 0xD4, 0x63, 0xCE, 0x41, 0x66, 0xC6, 0x93, 0x37, + 0xE7, 0xBB, 0x97, 0x09, 0x9C, 0x71, 0x2C, 0xDE, 0xD2, 0xB6, 0xB9, 0x26, 0x71, 0x46, 0xDD, 0xE9, + 0xEE, 0x51, 0x8E, 0x8B, 0xC0, 0xAD, 0x10, 0x8C, 0x20, 0x57, 0xBD, 0xBA, 0x82, 0x07, 0xDB, 0x4D, + 0x55, 0xE8, 0xC1, 0x41, 0x1B, 0x7E, 0x06, 0xCD, 0x3F, 0x5A, 0x1E, 0x3B, 0x66, 0x2A, 0x9D, 0x05, + 0x4E, 0xE0, 0x66, 0x0C, 0xC2, 0x6F, 0xF0, 0x9A, 0xC1, 0x46, 0xEA, 0x23, 0xE6, 0x58, 0x44, 0xE2, + 0x65, 0xCD, 0x47, 0x08, 0x6C, 0x74, 0xC6, 0x9A, 0x92, 0x32, 0xA1, 0x91, 0xF6, 0x2F, 0x18, 0x89, + 0x19, 0xB9, 0x66, 0xF9, 0xE8, 0xB2, 0x46, 0xDB, 0xFB, 0xAE, 0x5B, 0xE2, 0x58, 0x6E, 0x5C, 0x45, + 0x6A, 0x88, 0x91, 0x15, 0x26, 0xDC, 0x3C, 0xD1, 0x10, 0xD4, 0x7D, 0x13, 0x3E, 0x92, 0x72, 0x6C, + 0xDE, 0x8C, 0xD9, 0x13, 0x3E, 0xA6, 0xCC, 0x38, 0x47, 0x3C, 0x19, 0xF4, 0x2C, 0x7C, 0x27, 0x1E, + 0x47, 0x0C, 0x6C, 0xEF, 0x87, 0xF8, 0x98, 0x13, 0x96, 0x41, 0x58, 0xA6, 0x48, 0x6C, 0x66, 0x4B, + 0xA2, 0x2C, 0x8B, 0xBA, 0x26, 0x5F, 0x1D, 0x38, 0xB8, 0x22, 0xCE, 0xAD, 0x69, 0x9C, 0x73, 0x20, + 0x8C, 0x11, 0x10, 0xA6, 0xB2, 0xA1, 0x41, 0x7C, 0xA5, 0x3D, 0xE2, 0x29, 0xA0, 0xB8, 0x33, 0xA0, + 0x2F, 0x42, 0x46, 0x96, 0x02, 0x8D, 0x36, 0xB6, 0x39, 0xAA, 0x30, 0xE1, 0x0E, 0x0C, 0x2F, 0x0A, + 0xB6, 0x28, 0xDA, 0xF0, 0x9D, 0xA2, 0xC8, 0x13, 0xF9, 0xC5, 0xA0, 0xC2, 0xED, 0xDC, 0xFC, 0xF1, + 0x54, 0xB0, 0x15, 0xD4, 0xA3, 0xA9, 0x92, 0xC5, 0x3B, 0xCE, 0x16, 0xBB, 0xBF, 0xC5, 0x19, 0x0D, + 0xA2, 0xB0, 0xAC, 0xAB, 0xF4, 0xAE, 0xD7, 0x4D, 0xD5, 0xC6, 0x63, 0xC5, 0x2C, 0x3C, 0xB5, 0x09, + 0x42, 0xC2, 0xB0, 0x04, 0xCB, 0x9E, 0xB7, 0xB0, 0xC2, 0xC1, 0x28, 0xDE, 0x58, 0xFD, 0x39, 0x7C, + 0x0A, 0xCB, 0xFB, 0x16, 0x58, 0x04, 0x9B, 0xFA, 0xC1, 0x54, 0x24, 0xE8, 0x88, 0x6C, 0x21, 0x59, + 0x40, 0xB5, 0xCE, 0x54, 0xBB, 0x9C, 0xAD, 0x21, 0x80, 0x46, 0x67, 0x0D, 0x16, 0x3A, 0xEB, 0xB6, + 0xAE, 0xCB, 0x1D, 0xE7, 0xAB, 0xE7, 0xF1, 0x08, 0x66, 0xE0, 0x35, 0x03, 0xD3, 0xF6, 0x32, 0x8A, + 0x5A, 0x72, 0x06, 0x2A, 0x81, 0x71, 0x79, 0x3E, 0xEA, 0x29, 0x07, 0x72, 0xA0, 0x1C, 0x5C, 0x98, + 0x9E, 0x19, 0xE8, 0x08, 0xC7, 0xB5, 0x8A, 0x6C, 0x67, 0x5D, 0xB7, 0xE3, 0x65, 0x22, 0x46, 0xF1, + 0xC0, 0x3C, 0x63, 0xC9, 0x1B, 0xDA, 0x14, 0x84, 0xEF, 0x84, 0x2C, 0xC6, 0x35, 0x85, 0x05, 0xA9, + 0x96, 0x5D, 0x58, 0x0A, 0x74, 0x42, 0x5C, 0xBB, 0xAD, 0x07, 0x97, 0xED, 0xEB, 0x82, 0x8A, 0x6F, + 0x93, 0xC2, 0x85, 0x96, 0xFD, 0x8A, 0xDC, 0xD4, 0x3B, 0x66, 0x44, 0x0A, 0xE5, 0x6E, 0x69, 0x34, + 0x78, 0x23, 0x22, 0x26, 0x23, 0x54, 0x55, 0xA7, 0x59, 0x8C, 0x88, 0x58, 0xDD, 0x32, 0x02, 0x18, + 0xA2, 0x33, 0x99, 0x42, 0xB0, 0x3B, 0x59, 0x51, 0x23, 0x4C, 0xBB, 0xA4, 0x4F, 0x05, 0x76, 0xF0, + 0xD5, 0x6E, 0xB8, 0xA0, 0x98, 0x93, 0x82, 0x58, 0x88, 0x8D, 0x54, 0x09, 0x23, 0x60, 0x95, 0x03, + 0x4C, 0x5D, 0xE5, 0x53, 0x17, 0x6F, 0x8D, 0x77, 0x55, 0x42, 0x8B, 0xE7, 0x98, 0x46, 0x92, 0xF5, + 0xF1, 0x2A, 0x5E, 0xD3, 0x00, 0x9E, 0x9B, 0xBF, 0xC6, 0xB2, 0xBD, 0x09, 0x32, 0x7D, 0xA9, 0x1A, + 0x8B, 0x48, 0x28, 0xC8, 0x66, 0xAD, 0xC6, 0x36, 0x91, 0x5D, 0xA3, 0xCC, 0x0D, 0x56, 0x49, 0xAB, + 0xBA, 0xA6, 0x09, 0x15, 0x3A, 0xDB, 0x23, 0x87, 0xCA, 0x0F, 0x9B, 0x1C, 0x9E, 0x89, 0x0E, 0xF1, + 0x43, 0x81, 0xF4, 0x9A, 0x92, 0x74, 0xA9, 0xF2, 0x2F, 0x68, 0x6D, 0x62, 0x22, 0xCA, 0xCD, 0x1A, + 0x84, 0xCF, 0xE4, 0x0D, 0x8D, 0xC3, 0xE4, 0xA8, 0x8F, 0xC5, 0x02, 0xBC, 0x11, 0xC0, 0xF0, 0x8B, + 0x0F, 0xCE, 0xD9, 0x3D, 0x31, 0x19, 0xAD, 0x4D, 0x50, 0x2E, 0xED, 0x1E, 0x85, 0xEF, 0x0F, 0xDA, + 0x81, 0x5D, 0xD7, 0x75, 0xC3, 0xEC, 0x84, 0x47, 0x8C, 0x8A, 0xCC, 0x44, 0x46, 0x4F, 0xD4, 0xAD, + 0x03, 0x53, 0x3E, 0xDE, 0x36, 0x78, 0x8A, 0x0B, 0x68, 0xF6, 0xB8, 0x9F, 0x2E, 0xB3, 0xF6, 0x91, + 0x2A, 0x5B, 0xBB, 0x76, 0xF9, 0x98, 0x6B, 0xA1, 0x75, 0x30, 0x06, 0x79, 0x01, 0xFE, 0x14, 0x63, + 0x90, 0x20, 0x98, 0xE8, 0x3B, 0x84, 0x5F, 0xC0, 0x40, 0xC4, 0x4F, 0x85, 0x4C, 0x1A, 0xC9, 0x40, + 0x38, 0xB4, 0xA2, 0x68, 0x57, 0xA2, 0x91, 0x81, 0x93, 0x6D, 0xE8, 0xAD, 0x70, 0x47, 0x15, 0xC2, + 0xA8, 0x64, 0xA3, 0xDF, 0x6B, 0xE3, 0xF9, 0x0B, 0x47, 0x28, 0x21, 0xE2, 0x21, 0x14, 0xCA, 0x69, + 0x1C, 0xE1, 0xA9, 0xE8, 0xF0, 0x1C, 0xDE, 0x3F, 0x83, 0xDA, 0x66, 0xD0, 0x83, 0x2B, 0x93, 0x17, + 0xFF, 0x68, 0x76, 0xFD, 0x8D, 0xEB, 0x05, 0x6B, 0x61, 0xEC, 0xF7, 0x2B, 0xAF, 0x4F, 0x09, 0xB0, + 0xD8, 0x0F, 0xC7, 0x1D, 0x13, 0xE3, 0x4D, 0x3A, 0x02, 0x68, 0x03, 0x3F, 0x53, 0x49, 0x80, 0x02, + 0x34, 0xEE, 0x99, 0xD1, 0x3D, 0xBB, 0xD6, 0xB3, 0x75, 0x91, 0x0C, 0xD6, 0x3D, 0x73, 0xEB, 0xE6, + 0x20, 0xEE, 0x60, 0xF2, 0xCA, 0x0E, 0x5E, 0x86, 0x18, 0x5D, 0x95, 0xF3, 0xB3, 0x0D, 0xDD, 0x8C, + 0xA9, 0x54, 0x44, 0x6C, 0xAB, 0xBC, 0x87, 0x1E, 0xCB, 0xC1, 0x68, 0xF3, 0xF2, 0xBE, 0x9E, 0xBA, + 0x1C, 0x4B, 0x46, 0x64, 0xBB, 0x98, 0xF0, 0x7B, 0x48, 0x79, 0xF5, 0xD7, 0x28, 0x8F, 0xB0, 0x51, + 0x01, 0x16, 0xFA, 0x3E, 0x8A, 0x44, 0x88, 0x20, 0x30, 0x8D, 0x21, 0xD7, 0x4F, 0x49, 0x61, 0x69, + 0x4D, 0x5C, 0xBF, 0x02, 0x1E, 0x3E, 0xBB, 0xA1, 0xAB, 0x2E, 0x53, 0x9F, 0xFB, 0xC2, 0xF6, 0x1F, + 0x3F, 0x28, 0xAC, 0xB9, 0xBC, 0x7E, 0x8B, 0xDF, 0xFA, 0xFF, 0x40, 0xF8, 0x3C, 0xEE, 0x32, 0x03, + 0xB1, 0x31, 0x96, 0x6E, 0xA6, 0x2D, 0x09, 0xA2, 0xFC, 0x45, 0x1A, 0xFE, 0xFB, 0xC5, 0x97, 0xC3, + 0x07, 0xD8, 0xEF, 0xED, 0xFC, 0xDE, 0x75, 0xEF, 0x7D, 0x2F, 0x9E, 0xA1, 0x2A, 0xB8, 0x1E, 0xA3, + 0xF2, 0xB7, 0x7A, 0x7E, 0xC2, 0xD1, 0xBE, 0xCD, 0xD0, 0xAE, 0x7F, 0x16, 0x83, 0x3E, 0xDA, 0x22, + 0x31, 0x3C, 0x43, 0x04, 0x3A, 0x42, 0x91, 0x47, 0x3D, 0x14, 0x3E, 0xF4, 0x87, 0x6E, 0x54, 0xC9, + 0x2C, 0xBE, 0x36, 0x8C, 0x37, 0xE3, 0x1A, 0x3E, 0x86, 0x17, 0xC7, 0x07, 0x1C, 0x3B, 0x74, 0xF1, + 0xCB, 0x87, 0xAE, 0x1C, 0x07, 0x41, 0xE2, 0x31, 0x50, 0x34, 0x72, 0xAF, 0x0E, 0x20, 0x1E, 0x10, + 0xA0, 0xAE, 0x5F, 0x81, 0x2F, 0x1E, 0xC7, 0xC4, 0xC7, 0x2E, 0x1B, 0xC7, 0xC4, 0xC7, 0x36, 0x8C, + 0x23, 0x4D, 0x35, 0xCB, 0xB0, 0x49, 0x79, 0xB7, 0x7A, 0x00, 0x8F, 0xE3, 0xDF, 0xFF, 0xD1, 0x1D, + 0xC5, 0x75, 0xDF, 0xC3, 0xE3, 0xB0, 0x30, 0xF7, 0x7C, 0x1B, 0xFD, 0x77, 0xBC, 0xCE, 0x75, 0x2C, + 0x59, 0xA2, 0x3E, 0xDE, 0x31, 0xAA, 0xC9, 0x02, 0x87, 0x1F, 0xC7, 0x1A, 0x55, 0xAA, 0x91, 0x44, + 0x05, 0x6C, 0x2E, 0x06, 0x6F, 0x48, 0x65, 0xD8, 0xB3, 0x6B, 0x9E, 0x34, 0xD7, 0xFC, 0x1A, 0xFA, + 0x6D, 0x36, 0x38, 0x62, 0x07, 0xD2, 0x05, 0xDF, 0xB0, 0xE1, 0x5B, 0x67, 0x31, 0x22, 0xEB, 0xDA, + 0xFA, 0x4D, 0xCF, 0x11, 0x83, 0xF1, 0xB9, 0xE7, 0x53, 0xB1, 0x1B, 0x11, 0x82, 0x60, 0x86, 0x3C, + 0x86, 0x69, 0x21, 0x02, 0xE1, 0x37, 0xD1, 0xE8, 0xA6, 0xF1, 0x71, 0x49, 0x76, 0xD2, 0x59, 0x27, + 0xDD, 0xDF, 0x11, 0xD3, 0xAD, 0xBA, 0x2D, 0xDD, 0x9A, 0xEF, 0x68, 0x36, 0x9D, 0xC8, 0xCD, 0xD6, + 0xDE, 0x73, 0x8C, 0xA7, 0xE4, 0x60, 0xC8, 0x03, 0xD9, 0x7C, 0x16, 0x85, 0x45, 0xAB, 0xBA, 0x77, + 0x53, 0xB9, 0xC0, 0xF2, 0xA1, 0x50, 0x39, 0xD2, 0x1C, 0x6B, 0xEE, 0xF5, 0x21, 0x9E, 0x35, 0x0F, + 0xC4, 0x49, 0x5A, 0xAE, 0xCC, 0x5F, 0x78, 0x6E, 0x16, 0xC9, 0xF9, 0x21, 0xAD, 0x84, 0x2B, 0x78, + 0x84, 0xE1, 0xD5, 0x5F, 0x62, 0x3A, 0xF8, 0x0E, 0x18, 0x05, 0x7D, 0x70, 0xAC, 0x5F, 0xC9, 0x3B, + 0xB4, 0x1E, 0xC5, 0xFA, 0x30, 0x77, 0x72, 0x7A, 0xEC, 0x16, 0xFF, 0xCD, 0x1C, 0x11, 0x5D, 0xAE, + 0xA7, 0x97, 0x4B, 0x53, 0x37, 0xD1, 0xCD, 0x8E, 0x19, 0xEA, 0x20, 0x31, 0x81, 0xAA, 0x21, 0x04, + 0xEA, 0xB7, 0x97, 0x4E, 0xC3, 0xEA, 0x25, 0x71, 0x7A, 0xC1, 0xFD, 0xF7, 0x80, 0x06, 0x7E, 0xC1, + 0xFF, 0x78, 0xDE, 0xCF, 0x01, 0x05, 0x1E, 0x72, 0x9D, 0x56, 0xD8, 0x0C, 0x55, 0xCF, 0x0F, 0x29, + 0x7D, 0xDA, 0x15, 0x30, 0xA6, 0x47, 0xE9, 0xAE, 0xEE, 0x73, 0xDD, 0x82, 0x2E, 0x32, 0x6C, 0x37, + 0x08, 0x2C, 0x61, 0xD6, 0xDC, 0x4B, 0x1E, 0xE2, 0xC0, 0xD2, 0xB3, 0xB1, 0xE1, 0x2B, 0xD4, 0x86, + 0x0F, 0x08, 0xE2, 0xCF, 0x0F, 0xF8, 0x62, 0xF6, 0x78, 0x68, 0x6A, 0xF9, 0xBE, 0xFD, 0x99, 0x31, + 0x53, 0xD9, 0x31, 0x49, 0xFB, 0xAB, 0x9B, 0xFF, 0xF0, 0x81, 0x57, 0xBC, 0xF3, 0x7D, 0xAF, 0x59, + 0xBA, 0x23, 0xBB, 0xAB, 0xFE, 0xCE, 0x13, 0xEF, 0xFF, 0xFE, 0xF7, 0x9E, 0x7C, 0xCB, 0x57, 0x2F, + 0xFE, 0x28, 0x17, 0x1F, 0x5D, 0x28, 0xA4, 0xEA, 0xB3, 0xF0, 0x93, 0x6F, 0x78, 0x6B, 0x28, 0xE4, + 0x8B, 0x1D, 0x99, 0x3F, 0xFE, 0xC6, 0x68, 0xAA, 0x75, 0x71, 0xD5, 0x56, 0x83, 0x37, 0x6E, 0xBB, + 0xF3, 0xE5, 0xEF, 0x7B, 0xE8, 0x91, 0x77, 0x16, 0x73, 0xDB, 0xF7, 0xFC, 0xC3, 0xBB, 0xFE, 0xF8, + 0x1F, 0xDF, 0xF6, 0x97, 0xE9, 0x91, 0x83, 0x13, 0xD9, 0xD1, 0xC3, 0x58, 0xEE, 0xAC, 0xFE, 0x04, + 0xDB, 0x27, 0x2F, 0xA0, 0x7F, 0x00, 0x65, 0x8C, 0x25, 0xFB, 0x7D, 0xBB, 0x56, 0x31, 0x40, 0x95, + 0x38, 0x5C, 0xAF, 0xDC, 0xC5, 0xD5, 0xEE, 0x1C, 0x31, 0x79, 0x36, 0xF6, 0x5F, 0x8D, 0x99, 0x75, + 0x4C, 0xC2, 0xC1, 0x48, 0xAF, 0xEB, 0x0E, 0xB9, 0x80, 0x4F, 0xBC, 0x09, 0xB8, 0xA4, 0xEC, 0xEB, + 0x86, 0xE7, 0x1F, 0xCD, 0x62, 0x95, 0x47, 0x78, 0x88, 0xCA, 0xB5, 0xC5, 0xA6, 0xC8, 0x1E, 0xC2, + 0x10, 0xAB, 0x85, 0x25, 0x6A, 0x84, 0x8E, 0xC2, 0x74, 0x96, 0x70, 0xD0, 0x0B, 0xE9, 0x7D, 0x96, + 0x3F, 0x16, 0x0B, 0xD9, 0x6F, 0x79, 0x0D, 0x4D, 0xD2, 0x88, 0x3A, 0x29, 0x15, 0x34, 0x2D, 0xD3, + 0x1D, 0xED, 0xC9, 0x51, 0x83, 0x89, 0x26, 0x62, 0x1A, 0xEB, 0xA3, 0x05, 0x42, 0x1A, 0x5F, 0x72, + 0x4A, 0x35, 0x2D, 0x74, 0xF1, 0xAF, 0x6F, 0x39, 0x71, 0x70, 0x5B, 0x78, 0x02, 0xE5, 0x9A, 0x95, + 0x3C, 0x82, 0x58, 0x82, 0x2A, 0x85, 0x1A, 0x2D, 0xD3, 0xFE, 0xA9, 0xC7, 0xEF, 0x7E, 0x75, 0xF5, + 0xC0, 0x38, 0x21, 0x9B, 0x2A, 0x4B, 0xF2, 0x5A, 0x46, 0xC8, 0x3E, 0xFE, 0xA1, 0xCA, 0xAE, 0x05, + 0x82, 0xFA, 0xD0, 0xEA, 0x2A, 0x5E, 0x6F, 0xB4, 0x7A, 0x7E, 0xF5, 0x37, 0xE8, 0x10, 0xFA, 0x6B, + 0x90, 0x03, 0x9B, 0xC1, 0x74, 0x3F, 0xB4, 0xA9, 0x9A, 0x74, 0x34, 0xE4, 0x58, 0xB3, 0xC9, 0x2D, + 0x9D, 0xA9, 0x60, 0x13, 0xC5, 0xA6, 0x3A, 0xC8, 0x08, 0xBE, 0x4C, 0x78, 0x78, 0xA3, 0xBA, 0x74, + 0xDD, 0x58, 0x60, 0x30, 0xAE, 0x0D, 0x5A, 0x72, 0xCB, 0x50, 0x4B, 0xD2, 0x0C, 0x06, 0xF9, 0x1E, + 0xCD, 0x56, 0x11, 0x5E, 0x42, 0xD7, 0xE1, 0xBF, 0x86, 0x99, 0xB1, 0xF6, 0xC4, 0x6A, 0x9E, 0xA9, + 0xA0, 0x2A, 0xC2, 0x36, 0x01, 0xF2, 0xF4, 0x89, 0xA9, 0x5B, 0xAE, 0x31, 0xD0, 0xA8, 0x37, 0xDC, + 0x06, 0xB4, 0x42, 0xA4, 0x47, 0x04, 0x25, 0x18, 0x3C, 0xD4, 0x13, 0xC2, 0x93, 0x9B, 0x74, 0x49, + 0xE3, 0x67, 0x26, 0xEF, 0x0F, 0x4F, 0x07, 0x6F, 0xB9, 0x7B, 0x5F, 0xA9, 0x29, 0x63, 0x50, 0x6D, + 0x05, 0x5E, 0x6D, 0x54, 0xC2, 0x01, 0xBF, 0x00, 0xD5, 0x7C, 0x4E, 0xAF, 0xC6, 0xD2, 0x85, 0x18, + 0x32, 0xA4, 0xF8, 0xAC, 0x46, 0xD3, 0x6C, 0x32, 0x0F, 0x73, 0x9A, 0x12, 0xEF, 0x96, 0x45, 0xC1, + 0x30, 0x17, 0x09, 0xC6, 0xA2, 0xA8, 0xC7, 0x6E, 0xFD, 0xE1, 0x76, 0x82, 0xBE, 0x93, 0xE6, 0x95, + 0xEA, 0x4C, 0xAA, 0x53, 0x11, 0x25, 0x59, 0x31, 0x2B, 0x53, 0xB1, 0xB8, 0xCC, 0xD0, 0x84, 0x41, + 0x8A, 0x99, 0x9C, 0x51, 0x0D, 0x2B, 0x12, 0xB5, 0xF5, 0xE2, 0xD7, 0xB7, 0x70, 0x48, 0xE0, 0x11, + 0x55, 0x4F, 0x46, 0x5D, 0xF9, 0x18, 0x5C, 0xFD, 0x25, 0xEA, 0xA2, 0x2F, 0x62, 0x4E, 0x2F, 0xF5, + 0xF5, 0x62, 0x58, 0x01, 0x99, 0x7A, 0xB9, 0x51, 0xBB, 0xBF, 0x91, 0xBC, 0xD7, 0xEF, 0x7F, 0x80, + 0x3E, 0xED, 0x5A, 0x0F, 0xEA, 0x15, 0x6B, 0xDB, 0x50, 0xF0, 0xDA, 0xBA, 0x6E, 0x12, 0x3C, 0xF8, + 0xA4, 0xEB, 0xC4, 0x73, 0x2D, 0x55, 0xB2, 0xE1, 0xF9, 0xEE, 0x3C, 0xE8, 0x30, 0x60, 0x6D, 0x73, + 0xE0, 0x3C, 0x6D, 0xA3, 0x6E, 0xAC, 0xDE, 0xCE, 0x58, 0x58, 0x1C, 0x72, 0x3B, 0x5F, 0xDE, 0x71, + 0x24, 0x3B, 0xC1, 0x09, 0x76, 0xF9, 0xE0, 0x1F, 0x8C, 0x96, 0xEB, 0x61, 0x51, 0xAA, 0xEA, 0x21, + 0x63, 0x6F, 0x7A, 0x6C, 0x2B, 0xC7, 0xF4, 0xFF, 0xAA, 0x99, 0xCD, 0xDF, 0xE8, 0xCF, 0x25, 0x14, + 0x02, 0x31, 0xFB, 0x8E, 0x4E, 0x4C, 0x65, 0x72, 0x5B, 0x27, 0x54, 0x31, 0x9C, 0xED, 0x16, 0x94, + 0x90, 0x80, 0xD1, 0x52, 0x56, 0x32, 0xC2, 0xC9, 0xED, 0xDB, 0x54, 0xD2, 0x1A, 0xFB, 0xF4, 0xA2, + 0xE0, 0xAD, 0xE9, 0xAF, 0xD0, 0x87, 0xD0, 0x5F, 0x61, 0x39, 0x35, 0x06, 0xB6, 0xF5, 0x13, 0x96, + 0xA5, 0xB5, 0x26, 0xC7, 0x8B, 0x95, 0x07, 0x43, 0xB6, 0xA8, 0xD4, 0x6B, 0x23, 0x95, 0x6A, 0x05, + 0x69, 0xAA, 0x92, 0x41, 0xC0, 0x1F, 0x7A, 0x39, 0xF7, 0xF0, 0x9A, 0xA5, 0x30, 0xF4, 0x59, 0x76, + 0x5D, 0xDB, 0xE0, 0xFC, 0xC0, 0x5F, 0xE4, 0x49, 0x63, 0x6F, 0x91, 0x5D, 0x9C, 0x6A, 0x79, 0xDC, + 0xCA, 0xB8, 0xD8, 0xA7, 0x0A, 0x47, 0xF5, 0x26, 0x06, 0x6E, 0xF4, 0x60, 0x71, 0x27, 0x60, 0xBB, + 0x1E, 0x21, 0x19, 0x0F, 0x21, 0xA0, 0x64, 0x26, 0x91, 0xB4, 0xF0, 0x3A, 0xBB, 0x0E, 0x62, 0xF4, + 0x21, 0x25, 0xAC, 0x4E, 0x14, 0xAE, 0xDB, 0x53, 0xAD, 0x1E, 0x6F, 0x0A, 0x10, 0xC6, 0x6A, 0x81, + 0xFC, 0xAB, 0x04, 0x43, 0x0D, 0x34, 0xFC, 0x8B, 0xAF, 0x3E, 0x39, 0x99, 0xB1, 0x1F, 0x86, 0xB0, + 0xFF, 0x67, 0x8E, 0xC1, 0x5A, 0x34, 0x01, 0x61, 0x65, 0x8F, 0x9F, 0x9E, 0x9F, 0x86, 0x77, 0x95, + 0xEB, 0x8D, 0x58, 0x2F, 0x35, 0x97, 0xF5, 0xCB, 0x93, 0x70, 0x7E, 0xAA, 0x57, 0x43, 0x24, 0xFB, + 0x00, 0x22, 0x60, 0x60, 0x7C, 0xBE, 0xB3, 0xED, 0x3D, 0xBC, 0x4A, 0x8D, 0x7C, 0x0E, 0xCB, 0xE7, + 0xC7, 0x9E, 0xE8, 0x1C, 0x09, 0xB2, 0xB0, 0x0F, 0xE0, 0xEA, 0x4F, 0x31, 0x8B, 0x1E, 0x42, 0x9F, + 0x07, 0xE3, 0xE0, 0xC9, 0xFE, 0x8E, 0xE6, 0x68, 0x23, 0x1F, 0xB3, 0x34, 0x1E, 0xB0, 0x46, 0xA6, + 0x2A, 0x8E, 0x51, 0xD5, 0xB4, 0xC1, 0xA6, 0x0D, 0x7F, 0xDA, 0x68, 0x6A, 0xE0, 0x15, 0x13, 0xE9, + 0x87, 0x42, 0x95, 0xB2, 0xF6, 0x60, 0x26, 0x55, 0x56, 0xCB, 0x99, 0x4A, 0xF5, 0xB1, 0xCC, 0xF8, + 0xD8, 0x63, 0x94, 0x65, 0x3E, 0x12, 0xF5, 0x27, 0x42, 0xC8, 0xA8, 0x65, 0xD2, 0xC8, 0x54, 0x15, + 0x91, 0x34, 0x62, 0x4F, 0xF0, 0x14, 0x09, 0x2F, 0x85, 0xD3, 0xBA, 0x6B, 0xF6, 0x36, 0x9E, 0x8F, + 0xA1, 0xF5, 0x54, 0x1D, 0x38, 0xE0, 0x43, 0x70, 0xA7, 0xE7, 0x8C, 0xEF, 0x7A, 0xE4, 0x70, 0x7E, + 0x83, 0x42, 0xDF, 0xA8, 0xD7, 0xD7, 0xB9, 0x64, 0x42, 0x1B, 0x04, 0x48, 0x5C, 0x11, 0x80, 0x59, + 0xA3, 0x07, 0x47, 0x5B, 0x93, 0x90, 0x69, 0xB5, 0xB3, 0xCC, 0xC0, 0x1F, 0x84, 0x27, 0xAD, 0xD1, + 0xC6, 0xD4, 0x92, 0x64, 0x1C, 0x2C, 0xF4, 0x64, 0x84, 0xE1, 0xB1, 0x83, 0x61, 0x25, 0x63, 0xB9, + 0xED, 0xE8, 0x90, 0x95, 0x8B, 0xF8, 0x26, 0x8E, 0xDC, 0x37, 0x6E, 0x85, 0x11, 0x24, 0x1F, 0xDD, + 0x34, 0x01, 0x1F, 0x2A, 0x66, 0xE2, 0x76, 0xE4, 0x20, 0x9D, 0xF9, 0x1B, 0x67, 0xAB, 0xBE, 0x67, + 0xE4, 0xE0, 0x0A, 0x9C, 0x79, 0x78, 0x46, 0x9F, 0x99, 0xDF, 0x12, 0xA5, 0x5D, 0x0F, 0xD7, 0xE8, + 0x93, 0xE2, 0xEC, 0x7D, 0x81, 0x72, 0xD4, 0x76, 0xCD, 0x33, 0x54, 0x4C, 0x86, 0xDE, 0xA0, 0xA7, + 0x51, 0x75, 0xE6, 0x23, 0x30, 0x82, 0x61, 0x31, 0x81, 0x48, 0x5A, 0xDF, 0xEF, 0x27, 0xDF, 0x88, + 0x60, 0x70, 0x31, 0x80, 0x60, 0x3E, 0x33, 0x17, 0xA3, 0x39, 0x0C, 0x02, 0xDC, 0x39, 0x5D, 0x7D, + 0x16, 0x2D, 0xA1, 0xAF, 0x80, 0x06, 0xB8, 0xBF, 0x3F, 0x56, 0xCC, 0x06, 0x35, 0x50, 0xCC, 0x67, + 0x93, 0xB1, 0x68, 0x32, 0x29, 0xD9, 0x29, 0xC9, 0x2E, 0x89, 0x29, 0xC7, 0x7E, 0x85, 0x2C, 0xD1, + 0xAF, 0x28, 0xD5, 0x5F, 0xC6, 0xB1, 0xCC, 0x43, 0x3E, 0x14, 0x76, 0x24, 0x11, 0x45, 0x23, 0xE1, + 0x10, 0x99, 0x02, 0x6F, 0x0A, 0xCE, 0x9D, 0x85, 0xC5, 0x35, 0x15, 0xE8, 0xDB, 0x30, 0x79, 0xE7, + 0x40, 0x15, 0xCE, 0xBA, 0x56, 0x02, 0x9E, 0x45, 0x17, 0x9C, 0xC1, 0x4B, 0x33, 0xE5, 0xB9, 0xA9, + 0x36, 0x1A, 0xA3, 0xA3, 0xC5, 0xA1, 0xB7, 0x2A, 0xE9, 0x3E, 0x85, 0x3D, 0x10, 0xED, 0x19, 0x76, + 0x0C, 0x06, 0xDB, 0x4C, 0x0F, 0x7A, 0x14, 0x98, 0x6C, 0x8F, 0x66, 0x9A, 0x5E, 0x68, 0x71, 0x38, + 0x79, 0x68, 0x69, 0x06, 0x43, 0xCE, 0x74, 0xE4, 0xA0, 0x93, 0x81, 0xE8, 0x40, 0xA5, 0xBF, 0xB5, + 0x25, 0xE7, 0x6A, 0xD7, 0x3A, 0x4C, 0xBA, 0xD1, 0x86, 0x10, 0x86, 0xD5, 0xBE, 0x7A, 0x3F, 0xE5, + 0xF7, 0xA7, 0xD3, 0x8F, 0x85, 0xAA, 0x89, 0xCC, 0x87, 0xD2, 0x5B, 0xD1, 0x57, 0x7A, 0x01, 0x41, + 0x57, 0xF0, 0x6A, 0x73, 0xC5, 0xD8, 0x34, 0xCD, 0x4E, 0x28, 0x15, 0x03, 0xFE, 0x4F, 0x27, 0x9A, + 0x3F, 0x10, 0xB8, 0x7F, 0x05, 0xA1, 0xE3, 0xB9, 0xFB, 0x78, 0x08, 0xEF, 0x26, 0x11, 0x45, 0xBB, + 0x72, 0x21, 0x8C, 0xF1, 0xC6, 0xDB, 0xD1, 0x97, 0x41, 0x0F, 0x94, 0xFB, 0xFA, 0x78, 0x23, 0x84, + 0xA6, 0x6A, 0x66, 0x3F, 0xF6, 0x66, 0x5F, 0x0E, 0xA9, 0xBE, 0x96, 0xF8, 0xF0, 0xBA, 0x43, 0x69, + 0xA3, 0x60, 0xE8, 0xAB, 0x43, 0x2D, 0x4F, 0x0C, 0x05, 0x63, 0x76, 0x74, 0x8A, 0x6A, 0x78, 0x02, + 0x11, 0xB9, 0x4E, 0x11, 0xCF, 0xA5, 0x4F, 0x79, 0x0A, 0xCF, 0x33, 0xF2, 0xDA, 0xAE, 0x87, 0x04, + 0xBD, 0x85, 0xAA, 0xC7, 0x5A, 0x96, 0x5F, 0xD7, 0xA6, 0xA7, 0x6E, 0xB9, 0x67, 0x82, 0x2D, 0xEE, + 0xDB, 0xB4, 0x75, 0x77, 0x53, 0x6B, 0xE4, 0xA3, 0xDA, 0x9E, 0x00, 0x1B, 0x6E, 0x95, 0xAA, 0x8B, + 0x41, 0x5A, 0x43, 0xCD, 0x87, 0xC7, 0x84, 0x6C, 0x95, 0x60, 0x7C, 0xDB, 0x84, 0x30, 0x63, 0x37, + 0x33, 0x9B, 0xE1, 0xBC, 0xAD, 0x56, 0x76, 0x64, 0xAB, 0x8A, 0x2C, 0x70, 0xC9, 0xC7, 0x8F, 0xEC, + 0xBE, 0xEA, 0xDE, 0x03, 0x95, 0xBC, 0x4A, 0x51, 0x9C, 0xA3, 0x69, 0x62, 0x53, 0xE1, 0xFD, 0xC9, + 0xCE, 0x72, 0xD9, 0x37, 0xD2, 0x67, 0xEE, 0xDE, 0xCE, 0x8E, 0x14, 0x25, 0xCD, 0x37, 0x1F, 0x20, + 0x1C, 0x46, 0x4D, 0xE1, 0xB1, 0x2D, 0xAC, 0x3E, 0x47, 0x70, 0xE8, 0x5B, 0x60, 0x19, 0xFC, 0x97, + 0xFE, 0x72, 0xAB, 0x91, 0x53, 0xC0, 0xF2, 0x44, 0x16, 0x4C, 0x44, 0x46, 0xE4, 0x07, 0x0F, 0x8A, + 0x6F, 0x3B, 0x98, 0x36, 0x0F, 0x5A, 0xD3, 0x07, 0x47, 0xB7, 0x6D, 0x4D, 0xEC, 0xD8, 0xB5, 0xF3, + 0xF9, 0xDE, 0xD4, 0xEC, 0xFD, 0xC1, 0xDE, 0x54, 0x3F, 0x15, 0x0E, 0xB1, 0x34, 0x45, 0x2C, 0xB3, + 0x8B, 0x0B, 0x73, 0xB3, 0xE4, 0x3C, 0xC2, 0x86, 0x30, 0xDA, 0xBF, 0x6F, 0xF7, 0xAE, 0x9D, 0x3B, + 0xB6, 0x6F, 0xDB, 0xBA, 0x85, 0xA5, 0x45, 0x66, 0xAA, 0x13, 0x25, 0x22, 0x68, 0x64, 0xCB, 0xDB, + 0x57, 0xCA, 0x25, 0xD8, 0x18, 0x72, 0xD4, 0xC0, 0x55, 0xE8, 0x74, 0x3D, 0xC2, 0x50, 0xBD, 0x40, + 0x89, 0xD3, 0xC5, 0xD4, 0x11, 0x84, 0xD7, 0xBA, 0xCA, 0x73, 0xE0, 0xBC, 0xEC, 0x9D, 0x3F, 0x07, + 0xB6, 0xC3, 0xEB, 0x7B, 0xE7, 0xDD, 0x93, 0x26, 0xB6, 0x2E, 0xCF, 0x0F, 0x64, 0xEE, 0x25, 0xC7, + 0xC5, 0x25, 0x62, 0x39, 0xD8, 0xC0, 0x93, 0x4C, 0xBB, 0x72, 0x16, 0x39, 0x9E, 0xC1, 0xE5, 0xB9, + 0x2C, 0xF0, 0xEC, 0x56, 0xC9, 0xA4, 0xE2, 0x5A, 0xD2, 0xB6, 0xE7, 0xA7, 0x76, 0xE8, 0x35, 0xA3, + 0xA5, 0x0A, 0x27, 0x91, 0x6B, 0xB8, 0x31, 0x98, 0xBD, 0x1A, 0x98, 0xD9, 0x7A, 0x68, 0x12, 0xF6, + 0x88, 0x30, 0x6D, 0xD2, 0x61, 0x68, 0xDA, 0x16, 0xC1, 0x25, 0x52, 0x02, 0xB6, 0x2B, 0x20, 0x54, + 0x82, 0xB4, 0xCC, 0x0B, 0xD3, 0x44, 0xAD, 0xA0, 0x33, 0x41, 0x8A, 0xA0, 0x60, 0xE1, 0x7C, 0x38, + 0xCA, 0x50, 0xAC, 0x2C, 0xB0, 0xE2, 0x26, 0x73, 0x9C, 0x67, 0x0C, 0x8E, 0xA4, 0x90, 0x95, 0x65, + 0x97, 0x30, 0x7D, 0xA5, 0x33, 0x9D, 0x33, 0x1D, 0x08, 0x33, 0x99, 0x78, 0x1C, 0x52, 0xF0, 0x91, + 0x7C, 0x44, 0x50, 0x28, 0x55, 0x29, 0xB6, 0xD3, 0x1C, 0xAF, 0x97, 0x88, 0x64, 0x88, 0x49, 0xC5, + 0x1E, 0xDD, 0x47, 0x20, 0x62, 0xDC, 0x29, 0x26, 0x79, 0x81, 0x55, 0xB3, 0x6A, 0x8E, 0x0A, 0xD4, + 0x02, 0xDF, 0x7F, 0x63, 0x61, 0x7C, 0x93, 0xE0, 0xA3, 0x46, 0x37, 0x4F, 0x3D, 0xBC, 0x00, 0x11, + 0xEC, 0x74, 0x7A, 0xFD, 0x60, 0xC0, 0xF1, 0xF9, 0x2D, 0x43, 0x53, 0x24, 0x41, 0x4B, 0x68, 0x7C, + 0xFC, 0xB8, 0x9B, 0x49, 0x24, 0xAF, 0x3E, 0x0F, 0x9E, 0x45, 0x4F, 0x83, 0x00, 0x68, 0xF5, 0x2D, + 0x6C, 0x46, 0x8B, 0x24, 0x02, 0x01, 0x1A, 0xF9, 0x1D, 0x9F, 0xC9, 0x10, 0x8B, 0x67, 0xA1, 0xB2, + 0x91, 0xE9, 0xBA, 0x1E, 0x8F, 0x81, 0x75, 0xB8, 0x19, 0x54, 0x5C, 0x07, 0x34, 0x6A, 0x67, 0x06, + 0x96, 0x1C, 0x93, 0xED, 0x21, 0x0C, 0xA7, 0xA2, 0xC8, 0x32, 0x9E, 0x8D, 0xC7, 0xB6, 0x41, 0x92, + 0xA2, 0x69, 0x49, 0x92, 0x38, 0x99, 0xBE, 0x3B, 0x22, 0x89, 0x41, 0x1A, 0x21, 0x6A, 0x97, 0x6D, + 0x35, 0xBF, 0xF4, 0xC9, 0x4C, 0x67, 0xB4, 0xE8, 0x98, 0x82, 0x4E, 0xED, 0xD0, 0x99, 0x98, 0xDE, + 0x63, 0x2F, 0x1E, 0xF3, 0x7C, 0xB6, 0x71, 0xF0, 0x4B, 0xF4, 0x4D, 0x90, 0x05, 0x53, 0xFD, 0xA0, + 0xCD, 0x00, 0x4B, 0xCB, 0x66, 0x12, 0x71, 0x32, 0x92, 0x96, 0x50, 0x5A, 0x44, 0x89, 0x78, 0x3A, + 0xF8, 0x0E, 0xFA, 0x8F, 0xA1, 0xBD, 0xC1, 0xCA, 0xEE, 0x7A, 0x12, 0xD2, 0xE9, 0x0E, 0x3B, 0xE4, + 0xF6, 0x28, 0x67, 0x53, 0x45, 0xC7, 0x03, 0x41, 0xD9, 0x29, 0xA2, 0x99, 0xF5, 0xD0, 0xAF, 0x82, + 0xB2, 0x83, 0xB0, 0x97, 0x0B, 0x26, 0xF0, 0x5A, 0xD0, 0x56, 0x14, 0xFE, 0x52, 0x67, 0x6F, 0xE0, + 0x42, 0x61, 0x59, 0xB5, 0x1C, 0x9E, 0x10, 0x75, 0x9D, 0xE3, 0x44, 0x42, 0x59, 0x8A, 0xCC, 0x29, + 0x92, 0x9F, 0x83, 0x18, 0xEF, 0xB7, 0x14, 0x66, 0x2F, 0x13, 0x88, 0xF8, 0xB5, 0xCC, 0xC2, 0xC9, + 0x9B, 0xDE, 0xFA, 0xE8, 0x5D, 0x93, 0x24, 0x05, 0xCD, 0x8C, 0x59, 0xE6, 0xCA, 0x71, 0x5F, 0xD1, + 0xD0, 0xAA, 0xCF, 0x4F, 0x2C, 0x6D, 0x76, 0xF3, 0x87, 0x56, 0x7F, 0x8E, 0x3E, 0x88, 0xFE, 0x11, + 0xE4, 0xC1, 0x1C, 0xB8, 0xB9, 0x5F, 0xE9, 0x34, 0x42, 0xB6, 0xC6, 0x32, 0x60, 0x62, 0xCC, 0xC7, + 0xC6, 0xA2, 0x48, 0x92, 0x65, 0x29, 0xFF, 0x27, 0xF3, 0xD9, 0x33, 0xF3, 0xCC, 0xBB, 0xE6, 0xC9, + 0x77, 0xCE, 0x57, 0x46, 0xE6, 0x0A, 0xB3, 0x68, 0xA4, 0xF7, 0xA7, 0x15, 0x0C, 0xE8, 0x3B, 0x1B, + 0x27, 0xD6, 0x8B, 0xA7, 0x80, 0x35, 0x62, 0x7C, 0xBC, 0x72, 0xEE, 0xBB, 0x7B, 0x47, 0xCF, 0x0A, + 0x9E, 0xCF, 0xE3, 0x45, 0x3E, 0xC5, 0xF9, 0xCE, 0x00, 0x16, 0x60, 0xF4, 0x9A, 0x75, 0xDC, 0x30, + 0x91, 0x07, 0xF3, 0xB3, 0x58, 0x0A, 0xF4, 0x06, 0xCE, 0x04, 0x05, 0x45, 0x49, 0x97, 0x34, 0xBD, + 0x70, 0xD6, 0x68, 0x0B, 0xAF, 0x4E, 0xD5, 0x83, 0x0A, 0xCC, 0xD0, 0xD9, 0x08, 0x2D, 0x07, 0x7D, + 0x30, 0x58, 0x19, 0x53, 0xA5, 0x30, 0x6F, 0x26, 0xFC, 0xBB, 0x2A, 0xD3, 0x6F, 0x49, 0x1B, 0x65, + 0xC1, 0xCF, 0x6F, 0x6A, 0xDA, 0xA9, 0x49, 0xDF, 0x89, 0x43, 0x12, 0x73, 0x92, 0xD9, 0xEE, 0x37, + 0x04, 0xF1, 0xE2, 0x96, 0x8C, 0x83, 0x97, 0x13, 0x32, 0x90, 0x26, 0x54, 0x55, 0x12, 0xF8, 0xAB, + 0x93, 0x15, 0xDE, 0x96, 0x09, 0xB8, 0xDB, 0x4A, 0xC7, 0x35, 0xC9, 0x28, 0xA7, 0xEE, 0x9E, 0x5F, + 0x79, 0x20, 0x65, 0x1A, 0x41, 0x93, 0x16, 0x50, 0xB5, 0x40, 0xCB, 0xE1, 0x98, 0x19, 0xBC, 0xFA, + 0x2A, 0x99, 0x7B, 0x2B, 0x77, 0x3C, 0x46, 0x87, 0x4C, 0x29, 0xEA, 0xDF, 0xFA, 0xDA, 0x85, 0xBF, + 0x2F, 0x30, 0x29, 0x15, 0x63, 0xC8, 0xF1, 0x60, 0x24, 0x73, 0xE2, 0x7F, 0xFD, 0x17, 0x8F, 0xEA, + 0x7E, 0x8D, 0xE6, 0xD0, 0x97, 0x40, 0x1A, 0xEC, 0xEC, 0x67, 0x1C, 0x89, 0x06, 0xB6, 0x01, 0x36, + 0x65, 0x38, 0xF6, 0x68, 0xFA, 0xDD, 0x64, 0xE2, 0x71, 0xAC, 0x29, 0x13, 0x88, 0x89, 0xC7, 0x10, + 0xCF, 0xB1, 0x04, 0x13, 0x7A, 0x92, 0xBE, 0x0C, 0x2D, 0x0E, 0x18, 0xDC, 0xD5, 0x9A, 0xEA, 0x05, + 0x97, 0x81, 0xD7, 0x40, 0x23, 0x9E, 0x9A, 0x8C, 0x33, 0x44, 0x4C, 0x71, 0xA6, 0x3D, 0x89, 0x46, + 0x33, 0x59, 0x3C, 0x2D, 0x68, 0xE8, 0x66, 0x45, 0xEE, 0xC8, 0xC3, 0x10, 0x33, 0x66, 0x03, 0x61, + 0x28, 0x90, 0x0F, 0x5E, 0xFC, 0xDB, 0x34, 0x24, 0x20, 0x41, 0x71, 0x18, 0xF2, 0x28, 0x14, 0xE7, + 0xAB, 0x75, 0x53, 0x4C, 0x4C, 0x40, 0x64, 0xE1, 0x13, 0x63, 0x8F, 0x66, 0x7C, 0xA5, 0x18, 0x31, + 0x36, 0x3A, 0x76, 0x55, 0x75, 0x5B, 0xAE, 0xEB, 0xF3, 0x55, 0xFD, 0x1C, 0x61, 0xD8, 0xA5, 0x9C, + 0xB4, 0xEB, 0x0D, 0xFF, 0x8D, 0xFF, 0x73, 0xDE, 0x95, 0xDB, 0x05, 0x2C, 0xDB, 0x7E, 0x83, 0x7E, + 0x08, 0x66, 0xC0, 0x4C, 0xDF, 0x37, 0x3D, 0x39, 0xDE, 0x6A, 0xA6, 0x62, 0xC1, 0xBC, 0x49, 0x3B, + 0x55, 0xA5, 0x7A, 0xD2, 0x37, 0xFE, 0xDE, 0x15, 0x14, 0x2C, 0x0D, 0xB3, 0x56, 0x5C, 0x57, 0x96, + 0x02, 0xAF, 0x71, 0xFD, 0x8A, 0x97, 0xB9, 0x47, 0x07, 0x7D, 0x9E, 0x0D, 0x7A, 0xAE, 0x6D, 0x77, + 0xFD, 0x30, 0xFB, 0x11, 0x1E, 0xCE, 0xC5, 0x3A, 0xC9, 0x8B, 0x8F, 0xF5, 0xC8, 0xEC, 0xC0, 0x52, + 0xF3, 0x82, 0x05, 0x04, 0x96, 0x27, 0x5E, 0x1E, 0x84, 0x2B, 0xE9, 0x89, 0x5F, 0x04, 0x6F, 0x32, + 0xC2, 0x39, 0xC1, 0xCF, 0x36, 0x1D, 0x3A, 0x9C, 0x6B, 0x07, 0x52, 0x0B, 0xBD, 0xEA, 0x2C, 0x27, + 0x14, 0x92, 0xE3, 0x49, 0x9B, 0xD5, 0x03, 0x6A, 0xC0, 0x67, 0x4B, 0xD2, 0x78, 0x9D, 0x8D, 0x9F, + 0xBA, 0x67, 0x77, 0xA2, 0x33, 0x17, 0xD0, 0xD8, 0xD3, 0xE5, 0x8A, 0xE9, 0x08, 0x9A, 0x38, 0xDE, + 0x5C, 0x50, 0x17, 0x5A, 0x07, 0xDE, 0x35, 0x9B, 0x15, 0xF7, 0xC5, 0x30, 0xC6, 0x4D, 0xD4, 0x7A, + 0xCD, 0x6D, 0xF5, 0xBB, 0xAB, 0x3E, 0x3B, 0x1D, 0x78, 0xB0, 0x7C, 0xCD, 0x83, 0x3B, 0xCB, 0xE5, + 0x96, 0xAC, 0xC9, 0x42, 0x22, 0x5A, 0xD9, 0xFA, 0xB9, 0xC7, 0xC6, 0xEE, 0xD9, 0xBC, 0x69, 0x2E, + 0x1F, 0xEA, 0x07, 0x83, 0x23, 0xDD, 0x68, 0xF1, 0xC4, 0x0F, 0x1E, 0xE1, 0xDD, 0x28, 0x08, 0xC6, + 0x84, 0xCF, 0xA1, 0x9F, 0xA2, 0x1F, 0x60, 0xBB, 0xEE, 0x54, 0xBF, 0x59, 0x8A, 0x31, 0x34, 0xE8, + 0x54, 0x8B, 0x79, 0x53, 0xEC, 0x74, 0x88, 0x5E, 0x97, 0xE8, 0x89, 0xD3, 0xD3, 0xF1, 0x44, 0x32, + 0x15, 0x0A, 0x5A, 0x44, 0xD8, 0xEA, 0x21, 0x44, 0x84, 0x82, 0x01, 0xBF, 0x45, 0xD9, 0x28, 0x05, + 0xDE, 0xB7, 0x12, 0x2B, 0x9D, 0x85, 0xA5, 0xCB, 0x7C, 0x17, 0xAE, 0xE0, 0xEE, 0x7A, 0xBC, 0xAC, + 0xBA, 0x8E, 0x33, 0xF5, 0x52, 0x54, 0x71, 0x63, 0xDE, 0x81, 0x6B, 0xE2, 0x95, 0x86, 0x2A, 0x3C, + 0x0C, 0x15, 0x3C, 0x39, 0xC8, 0xB5, 0x7A, 0x3C, 0x86, 0xB6, 0x3C, 0x15, 0x4E, 0xAC, 0x53, 0xBA, + 0x2B, 0x87, 0x06, 0xD1, 0xD3, 0x28, 0x81, 0x35, 0x7A, 0xB6, 0x8D, 0x7E, 0x8A, 0x01, 0x0B, 0x49, + 0x51, 0xA1, 0x70, 0x38, 0xCC, 0xF9, 0x1B, 0xA7, 0x1B, 0x73, 0xBA, 0x49, 0x60, 0xC9, 0x48, 0xC0, + 0xF4, 0xD8, 0x38, 0x4D, 0xD3, 0x14, 0x6B, 0x66, 0x6B, 0xA6, 0x28, 0x89, 0x0F, 0x49, 0x82, 0x1E, + 0x8A, 0x07, 0x66, 0x83, 0xCD, 0x1B, 0xC7, 0xAA, 0x4A, 0x08, 0x72, 0xF2, 0x16, 0xF4, 0x83, 0x6C, + 0x7C, 0x76, 0xF9, 0xAB, 0x2F, 0x97, 0xAF, 0x36, 0x4D, 0xD3, 0xF6, 0x75, 0x36, 0x3F, 0x50, 0xEF, + 0x29, 0x9A, 0x5F, 0x71, 0x4E, 0x07, 0xF4, 0x79, 0x2E, 0x61, 0x25, 0x8A, 0x0F, 0x3D, 0xF4, 0x9A, + 0x27, 0x18, 0x2D, 0x16, 0xA0, 0xD4, 0xEB, 0x58, 0xDD, 0x36, 0x3A, 0xFE, 0xDA, 0xA1, 0x6E, 0x43, + 0xF5, 0x77, 0xEE, 0xBB, 0x6D, 0xB4, 0x8D, 0xA9, 0x25, 0x86, 0xE5, 0xC4, 0xA7, 0xD1, 0x17, 0xC0, + 0x04, 0x28, 0xF4, 0xD5, 0x7A, 0xCA, 0xEF, 0x68, 0xC4, 0x48, 0xD9, 0x8E, 0xBD, 0xBF, 0xD3, 0xFE, + 0x33, 0x81, 0x1D, 0x60, 0xFF, 0x0D, 0x74, 0x81, 0xC7, 0xD9, 0xD1, 0x5C, 0x15, 0x6F, 0xBA, 0x26, + 0x8E, 0x47, 0x13, 0xC4, 0xD0, 0x29, 0x48, 0x6F, 0x08, 0x1C, 0xD1, 0x5E, 0x2C, 0x75, 0x8D, 0xB4, + 0xD1, 0x39, 0xB8, 0x1C, 0xB4, 0xFC, 0xFB, 0x0F, 0x8F, 0xDD, 0xBB, 0x9F, 0x0B, 0xEB, 0xD5, 0xA9, + 0x11, 0xD9, 0x2C, 0xA7, 0xCC, 0xE2, 0x64, 0xC3, 0xC9, 0x4D, 0x25, 0x10, 0xAB, 0x95, 0x16, 0xFA, + 0x11, 0xC3, 0xAC, 0xE8, 0xAA, 0x94, 0x93, 0x53, 0xCB, 0x55, 0x67, 0xEB, 0x87, 0xE1, 0x07, 0x58, + 0x9D, 0xBD, 0xFB, 0xB6, 0x98, 0xE5, 0xF4, 0x33, 0xA7, 0xA4, 0x91, 0x6B, 0x23, 0x95, 0x95, 0x99, + 0x04, 0x2B, 0x77, 0xB6, 0x4F, 0xEC, 0x8A, 0x4F, 0x94, 0xF4, 0xD2, 0xFE, 0xBE, 0x66, 0x4E, 0x35, + 0x77, 0xCC, 0xFA, 0x19, 0x86, 0x20, 0x4C, 0x87, 0xD3, 0x0B, 0xF2, 0x8D, 0xEE, 0xDA, 0x7F, 0x6F, + 0xF5, 0x79, 0x34, 0x81, 0xB1, 0x5C, 0x1E, 0x6C, 0xED, 0xC7, 0xA3, 0x61, 0x5F, 0x94, 0x0D, 0xEB, + 0xDA, 0x43, 0x19, 0xCE, 0x94, 0x10, 0x32, 0x2D, 0x14, 0x30, 0x75, 0x03, 0xF9, 0x03, 0x99, 0x37, + 0xF9, 0xB0, 0xFE, 0x88, 0x5E, 0xA6, 0x3F, 0x06, 0x7A, 0x78, 0x98, 0x47, 0xE6, 0xC1, 0xB3, 0xA1, + 0xDC, 0x2E, 0x44, 0x87, 0x90, 0x06, 0x0D, 0x62, 0x22, 0x9E, 0xDF, 0x82, 0x89, 0xBA, 0x82, 0x1C, + 0x43, 0xDA, 0x4C, 0x33, 0xC1, 0xB8, 0x7E, 0x76, 0x2F, 0x2D, 0x04, 0x8D, 0x70, 0x13, 0x7B, 0xC7, + 0xC3, 0x29, 0x26, 0x30, 0x52, 0x10, 0xF6, 0x4C, 0x05, 0x21, 0x42, 0xD1, 0x7D, 0x31, 0x0E, 0x52, + 0x8B, 0x1D, 0x5F, 0xC5, 0xEF, 0x9B, 0x19, 0xAB, 0x6E, 0xBB, 0xFD, 0x18, 0x6A, 0x05, 0x03, 0xC5, + 0xCD, 0x55, 0x93, 0x13, 0x2D, 0x29, 0xD0, 0x4E, 0xCB, 0x93, 0x13, 0xE8, 0xD9, 0xC7, 0x1E, 0x35, + 0x26, 0x7C, 0x9F, 0x19, 0x79, 0xEC, 0xFB, 0xA2, 0x60, 0x56, 0x82, 0x41, 0x8E, 0x0E, 0xCE, 0x0E, + 0x2C, 0xB3, 0x36, 0x55, 0x43, 0x7F, 0x8F, 0x25, 0xF8, 0x78, 0xDF, 0xD7, 0x2C, 0x64, 0x31, 0xE2, + 0x54, 0x46, 0xC0, 0x34, 0x99, 0xD9, 0x3A, 0x3F, 0xF7, 0xE7, 0xF3, 0xD3, 0xEF, 0x27, 0x7D, 0x1F, + 0x26, 0x3F, 0xB2, 0xC1, 0x3E, 0xBB, 0x0C, 0x83, 0xBB, 0xF2, 0x58, 0x19, 0x64, 0x0E, 0xE0, 0x55, + 0x62, 0xDD, 0xB4, 0x81, 0xE1, 0x7A, 0x38, 0x61, 0x37, 0x3B, 0x46, 0x21, 0x3C, 0x5F, 0x5B, 0xA6, + 0x3A, 0x34, 0xD6, 0xF0, 0xF2, 0x71, 0x2E, 0xEC, 0xA4, 0x6A, 0xA5, 0x7B, 0x5F, 0xFF, 0x64, 0xFF, + 0xF0, 0x6B, 0xC6, 0x4E, 0x6D, 0xBD, 0x71, 0x76, 0x36, 0xDF, 0xED, 0xE9, 0xBE, 0x4C, 0x6F, 0x31, + 0x7B, 0xCB, 0xC9, 0x34, 0x8D, 0xB8, 0xE2, 0x98, 0x8F, 0x0C, 0xC9, 0x5A, 0x24, 0xE6, 0x77, 0xD2, + 0xBB, 0x0B, 0xDB, 0xEB, 0x8C, 0x3F, 0x56, 0xEB, 0x1D, 0x3C, 0x7D, 0xDB, 0xD6, 0x7B, 0x9F, 0xD8, + 0x74, 0xFD, 0xAD, 0xFD, 0xFB, 0x94, 0x82, 0x29, 0x26, 0xD4, 0x42, 0x7A, 0xB1, 0xB3, 0xEF, 0x68, + 0x7D, 0xEA, 0xD5, 0x5B, 0x74, 0x27, 0x9E, 0xB5, 0xEE, 0xB9, 0x7A, 0x32, 0x29, 0x52, 0xE2, 0xC4, + 0xB6, 0xAE, 0x8F, 0x08, 0xF2, 0xD1, 0xDE, 0x58, 0xE3, 0xFA, 0x7C, 0xB4, 0x5A, 0xDE, 0x53, 0xCD, + 0x87, 0xAE, 0xEA, 0x4E, 0x4E, 0xCC, 0x4D, 0x15, 0x03, 0x51, 0x9B, 0xE2, 0xBD, 0xF5, 0x7B, 0x06, + 0x7D, 0x0A, 0xDB, 0xA2, 0xD3, 0xE0, 0xFA, 0x7E, 0xB9, 0x95, 0x0E, 0x83, 0x74, 0x72, 0xFA, 0xA3, + 0x33, 0x3D, 0x6B, 0x86, 0xBA, 0x67, 0xC6, 0xD6, 0x9D, 0x12, 0x6F, 0xFB, 0xED, 0x64, 0x22, 0x12, + 0x97, 0xD1, 0x88, 0xCF, 0xB1, 0xB1, 0x00, 0x8D, 0x97, 0x1E, 0x08, 0xEF, 0x3B, 0x0B, 0xD3, 0x57, + 0x60, 0x81, 0xAE, 0xB7, 0x92, 0xDD, 0x41, 0x0C, 0xC8, 0xB3, 0xED, 0x36, 0x1A, 0xF1, 0x78, 0x6A, + 0x66, 0xD2, 0xAE, 0x6C, 0xF3, 0x30, 0x2A, 0xCA, 0xAE, 0x7B, 0xA3, 0x92, 0x74, 0x52, 0x8B, 0x42, + 0x05, 0xB3, 0x65, 0xAB, 0x5D, 0x75, 0x23, 0x76, 0xC4, 0x9A, 0x3D, 0x8F, 0x0D, 0x7D, 0x0C, 0xED, + 0x08, 0xD7, 0x98, 0xFD, 0x94, 0xEF, 0x08, 0x2D, 0x0A, 0xA1, 0x4D, 0xCB, 0x71, 0xA5, 0xAF, 0x8D, + 0x4D, 0xEF, 0x0E, 0xD2, 0x34, 0x47, 0x22, 0x22, 0x9F, 0x4B, 0xA6, 0x48, 0x8C, 0xA1, 0xE0, 0xEC, + 0x42, 0x04, 0xFF, 0xE5, 0x9B, 0x81, 0xBB, 0x97, 0xAF, 0x3A, 0x10, 0x4F, 0x55, 0x74, 0x8D, 0x4D, + 0x62, 0x83, 0xB7, 0x9E, 0x12, 0x49, 0x76, 0xB7, 0xD2, 0x27, 0xE9, 0xFD, 0x6F, 0x5C, 0xCA, 0x27, + 0xF8, 0xE2, 0x68, 0x61, 0x5A, 0x46, 0x17, 0xEF, 0xE8, 0x74, 0x83, 0x41, 0x9F, 0x6F, 0xDB, 0xC7, + 0x9F, 0x3E, 0xE4, 0xF3, 0x41, 0x32, 0x1C, 0x0E, 0x85, 0x59, 0x96, 0x09, 0x6E, 0xE9, 0xC4, 0xA6, + 0xE2, 0x49, 0x3E, 0x20, 0xB4, 0x9A, 0xB2, 0x36, 0x9D, 0x72, 0xF3, 0xA4, 0xA3, 0x98, 0x53, 0xB7, + 0x61, 0x4E, 0xED, 0x81, 0xF9, 0x7E, 0x64, 0xAA, 0xE4, 0x97, 0x1A, 0x5A, 0x3B, 0xA9, 0x7D, 0xB2, + 0x6F, 0x7E, 0xA2, 0x6F, 0x7F, 0xBC, 0x5F, 0xFB, 0x58, 0xBE, 0x8D, 0x92, 0xF9, 0x3F, 0x63, 0x59, + 0x28, 0x6D, 0xF0, 0x5F, 0x80, 0xCB, 0x61, 0xE4, 0x3A, 0x4E, 0x97, 0x5C, 0xDB, 0xCC, 0x1B, 0xBD, + 0xE7, 0xDA, 0xC7, 0x28, 0xD2, 0xF6, 0x50, 0xB9, 0xEB, 0xCA, 0xF0, 0x72, 0x4C, 0x08, 0x0F, 0x94, + 0x60, 0x80, 0x92, 0x19, 0x10, 0xC7, 0x20, 0x53, 0x0D, 0x4D, 0x0A, 0xE5, 0x96, 0x53, 0x9B, 0xDB, + 0x56, 0x28, 0x2D, 0x15, 0xD4, 0x7A, 0x37, 0x26, 0xEC, 0xCF, 0xD1, 0x42, 0xA3, 0x27, 0x15, 0x1B, + 0xF6, 0xC7, 0x45, 0x67, 0x7C, 0x76, 0xD9, 0x7F, 0x7A, 0xAE, 0xBF, 0x95, 0x4F, 0xEC, 0x12, 0xEB, + 0x3D, 0x66, 0xB3, 0x7F, 0x74, 0x9C, 0xFD, 0xA3, 0x97, 0x7F, 0xC5, 0x6E, 0x8D, 0x68, 0xD1, 0xB0, + 0xEE, 0x4B, 0xDB, 0x82, 0x5E, 0x48, 0x1B, 0xB9, 0x25, 0xD8, 0xCA, 0x31, 0xB5, 0x8C, 0xC1, 0x8C, + 0x90, 0x52, 0x65, 0xB4, 0x7C, 0x6D, 0x5B, 0x2A, 0x8D, 0x38, 0x12, 0x63, 0x95, 0xB4, 0xAE, 0x34, + 0xA5, 0x86, 0x6B, 0x36, 0x2A, 0x24, 0xAF, 0x8E, 0x0D, 0x6C, 0xB3, 0x67, 0xD0, 0x67, 0xB1, 0x0D, + 0xE2, 0x07, 0x4B, 0xFD, 0x98, 0x2E, 0x01, 0x9D, 0x66, 0x5E, 0x8F, 0x71, 0xED, 0xEB, 0x9C, 0x97, + 0x09, 0x48, 0x61, 0x90, 0xC2, 0x22, 0x59, 0xB1, 0x41, 0xCB, 0x8D, 0x02, 0xEA, 0x97, 0x48, 0xC0, + 0xCB, 0x3A, 0xF5, 0x16, 0xBC, 0xE7, 0xD9, 0xAF, 0xEB, 0x0E, 0xE7, 0x80, 0xEE, 0x26, 0x28, 0xBA, + 0xD0, 0x19, 0x03, 0x65, 0x0C, 0x86, 0x69, 0xA6, 0x6D, 0x24, 0x32, 0x49, 0x0C, 0x88, 0x9D, 0x7A, + 0x0A, 0x7D, 0xF6, 0x84, 0x9C, 0x55, 0x4A, 0xC1, 0x49, 0x82, 0x66, 0xAF, 0xDA, 0x43, 0xC1, 0xF2, + 0xC7, 0x8A, 0xAD, 0x29, 0x55, 0x39, 0x39, 0x0F, 0xA7, 0xD1, 0x97, 0x6F, 0x90, 0x05, 0x82, 0x84, + 0x67, 0x8F, 0x7F, 0xE0, 0x60, 0x7D, 0xA6, 0x8B, 0x22, 0x6A, 0xBD, 0xCC, 0x0B, 0x0C, 0xE3, 0x65, + 0xD1, 0xFC, 0x8C, 0x48, 0xA1, 0x6F, 0x80, 0x11, 0x37, 0x06, 0x56, 0x2E, 0x15, 0x0B, 0x36, 0xF0, + 0xA7, 0x5E, 0x57, 0x07, 0xFF, 0x75, 0x45, 0xFE, 0x14, 0x18, 0xE6, 0x27, 0x80, 0x0D, 0xE2, 0xB3, + 0x6E, 0x0F, 0x62, 0x76, 0xFC, 0x20, 0xFB, 0xC9, 0x05, 0x46, 0x11, 0x14, 0xF5, 0x42, 0x42, 0xAE, + 0x1A, 0xCD, 0x36, 0x7B, 0x04, 0x91, 0x22, 0x29, 0x46, 0x0C, 0x1B, 0x05, 0xB9, 0x3F, 0x3F, 0x51, + 0x2C, 0x1A, 0xA9, 0x2D, 0xDB, 0x67, 0xCB, 0xA1, 0x6A, 0xEA, 0x5E, 0x44, 0x72, 0xC1, 0x80, 0x0A, + 0xB5, 0xF2, 0x81, 0x7A, 0x71, 0x2E, 0xA9, 0x62, 0x3B, 0xAE, 0x5C, 0x1A, 0x45, 0xDF, 0x08, 0xD8, + 0xD9, 0xCA, 0xA1, 0xF6, 0xE1, 0xC8, 0xD9, 0x1B, 0xA7, 0xA2, 0x62, 0xFB, 0xF0, 0xE9, 0x83, 0xBD, + 0xFB, 0xAA, 0x65, 0x73, 0x4B, 0x30, 0xBE, 0x74, 0xC3, 0x62, 0x92, 0x8C, 0x5D, 0x73, 0xE6, 0x86, + 0xE5, 0x5D, 0x53, 0xD9, 0x78, 0x89, 0xF1, 0x07, 0x02, 0xAE, 0xC7, 0x67, 0xF5, 0x47, 0xAB, 0xCF, + 0x10, 0x26, 0xFA, 0x36, 0xA8, 0xBA, 0xB1, 0x91, 0x72, 0x48, 0xE4, 0x41, 0x2C, 0x18, 0x00, 0xE7, + 0x56, 0xB4, 0x7D, 0x83, 0x1E, 0x5F, 0x1E, 0xE0, 0x0E, 0x0D, 0xF5, 0x9A, 0x6B, 0x8F, 0x5A, 0xA6, + 0x17, 0x1D, 0x65, 0xAA, 0x44, 0x85, 0x58, 0x0B, 0x11, 0xDB, 0x51, 0xD7, 0xA9, 0x07, 0x9B, 0x3D, + 0x48, 0x98, 0xA6, 0x1A, 0xD9, 0x77, 0x75, 0xD4, 0x12, 0x59, 0x1E, 0x43, 0xFA, 0x54, 0x42, 0x12, + 0xFA, 0xBB, 0x2B, 0xE3, 0x31, 0x83, 0xF5, 0xF1, 0x0F, 0x92, 0x16, 0x6B, 0xE4, 0x73, 0x07, 0x1B, + 0x21, 0x4B, 0xE2, 0x0A, 0xF9, 0x50, 0x24, 0x82, 0xBE, 0x9D, 0x0C, 0xB6, 0xFE, 0xE8, 0x13, 0xF3, + 0xB5, 0x70, 0x40, 0x52, 0x1C, 0x51, 0x12, 0x2C, 0x23, 0x19, 0xFA, 0xCF, 0x1F, 0x3A, 0x7C, 0x24, + 0xCE, 0x43, 0xD1, 0xDE, 0x4F, 0xF0, 0xA3, 0x8B, 0x4F, 0x9D, 0x98, 0x28, 0x87, 0xF4, 0x23, 0xD7, + 0x9F, 0x6A, 0xAA, 0x8A, 0xD7, 0xEF, 0xE7, 0xC8, 0xDF, 0x60, 0xCD, 0x7E, 0x35, 0x18, 0xE9, 0x1B, + 0x9D, 0x4C, 0x4A, 0x91, 0xC0, 0xF6, 0xA9, 0x89, 0xB1, 0x90, 0x39, 0x7D, 0x0D, 0x78, 0x5F, 0xBE, + 0x34, 0x74, 0x4B, 0x0E, 0x14, 0xD6, 0x46, 0x95, 0x75, 0x4D, 0xC7, 0x0D, 0xC5, 0x51, 0x5E, 0x4C, + 0x77, 0xD8, 0x7F, 0x54, 0x21, 0xB2, 0x5E, 0xDC, 0x11, 0x37, 0xA0, 0x2A, 0x8D, 0xC9, 0x9E, 0xC8, + 0xAC, 0x69, 0x67, 0x97, 0xD4, 0x1D, 0x37, 0xD1, 0x8C, 0x72, 0xF0, 0xD8, 0xDC, 0x13, 0x44, 0xFE, + 0x86, 0x09, 0x4C, 0x6C, 0xEB, 0xE5, 0x05, 0x24, 0x49, 0x58, 0x2F, 0xAB, 0x9A, 0x3D, 0xA6, 0x92, + 0x28, 0x2B, 0x76, 0x26, 0x8D, 0x80, 0xAE, 0x09, 0xB9, 0x58, 0x34, 0x80, 0x2C, 0x6B, 0xBF, 0xE4, + 0x08, 0x04, 0x52, 0xE4, 0x70, 0xAB, 0x99, 0x21, 0x2C, 0xD3, 0x47, 0xB2, 0xE8, 0x6E, 0x96, 0x51, + 0x32, 0x23, 0x85, 0x6E, 0xBA, 0x1A, 0x2B, 0x36, 0x28, 0xD7, 0x5D, 0xFF, 0x9A, 0xCC, 0xF1, 0x9C, + 0x98, 0x40, 0x42, 0xBA, 0x99, 0xA3, 0xB1, 0xDE, 0xFF, 0x81, 0x54, 0xBA, 0xE9, 0x3F, 0xDD, 0x7F, + 0x55, 0x88, 0x8C, 0x27, 0x49, 0x51, 0xE6, 0x29, 0x91, 0x57, 0x53, 0x3C, 0x8D, 0x6E, 0x8C, 0x3F, + 0x78, 0x57, 0xB2, 0x1C, 0x8D, 0x5B, 0x5B, 0xA7, 0xA7, 0x17, 0x4C, 0x5A, 0x16, 0xC5, 0x5A, 0xAA, + 0x1B, 0x66, 0xA8, 0x68, 0x6A, 0xF6, 0xD6, 0xEB, 0xE7, 0x99, 0x64, 0x12, 0xF9, 0x77, 0xD3, 0xA3, + 0x07, 0xB6, 0xDF, 0xBD, 0xE9, 0xF8, 0xCC, 0x75, 0xAF, 0x49, 0x48, 0x8E, 0x23, 0xEE, 0x99, 0xFB, + 0xCC, 0x35, 0x81, 0xDD, 0xA4, 0x6F, 0xCB, 0x99, 0xFB, 0x7B, 0x6E, 0xC2, 0x8C, 0x6B, 0xB7, 0x7C, + 0x07, 0x7D, 0x01, 0x7D, 0x17, 0x4B, 0xD3, 0xCD, 0xFD, 0x48, 0x3D, 0x13, 0x8F, 0xCA, 0xA0, 0x39, + 0x52, 0x2D, 0x4C, 0xF8, 0xE9, 0x09, 0xBF, 0x94, 0x99, 0x11, 0xDE, 0x32, 0x63, 0xFC, 0xB7, 0x19, + 0xFF, 0xA7, 0xA7, 0x3F, 0x93, 0xFE, 0xAC, 0xAB, 0x45, 0xCE, 0x81, 0x89, 0x41, 0xBA, 0xE5, 0x9A, + 0x32, 0xB9, 0x1C, 0x13, 0xBA, 0x52, 0x33, 0xE3, 0xF2, 0x8F, 0x67, 0x78, 0x7A, 0x8E, 0x3D, 0x47, + 0x26, 0x3C, 0xFF, 0xAE, 0xEC, 0x36, 0x86, 0x3D, 0x1A, 0xF1, 0xD2, 0x09, 0x36, 0x62, 0x9D, 0x08, + 0x72, 0xDC, 0x84, 0x35, 0xF4, 0x85, 0xF1, 0xF2, 0xF5, 0x7E, 0x5F, 0x30, 0xBC, 0x7F, 0x53, 0x52, + 0x17, 0x24, 0x2E, 0x99, 0xEE, 0xE9, 0xBC, 0x20, 0x2B, 0x77, 0x71, 0x79, 0x46, 0xA2, 0x72, 0x56, + 0x71, 0x25, 0xDB, 0x96, 0xDF, 0xEE, 0xF4, 0xF3, 0xEC, 0x43, 0xE1, 0xA2, 0x2A, 0xC8, 0xDC, 0xEB, + 0x59, 0x5A, 0xAE, 0x4C, 0xC6, 0x32, 0x62, 0xC6, 0x4F, 0x13, 0xF5, 0x8F, 0xA2, 0xAF, 0xF5, 0x47, + 0xCF, 0xC4, 0xC2, 0x89, 0xC2, 0xD9, 0x6B, 0x43, 0x82, 0x6D, 0xFB, 0x1A, 0x22, 0x26, 0x92, 0xF7, + 0x8B, 0xF3, 0x9C, 0xC6, 0x4F, 0x37, 0x22, 0x1A, 0xAB, 0x64, 0xAC, 0xA0, 0xF1, 0x89, 0xC0, 0xDE, + 0x2E, 0xFF, 0x54, 0x36, 0xCD, 0xA9, 0xB7, 0xD0, 0x53, 0x47, 0xEB, 0x6D, 0x71, 0xBC, 0x9D, 0x30, + 0x7C, 0x7B, 0x06, 0xC8, 0xE0, 0x39, 0xC2, 0x42, 0x3F, 0x05, 0x6D, 0xD0, 0xEF, 0xFB, 0x1B, 0xB5, + 0x18, 0x28, 0x24, 0xA3, 0xE1, 0x82, 0x60, 0x6A, 0x26, 0x92, 0x44, 0xA1, 0xFD, 0x39, 0x0D, 0x23, + 0xBF, 0xD8, 0x95, 0x5A, 0x04, 0x5C, 0x6E, 0x7C, 0xE3, 0x19, 0x18, 0x8B, 0x0D, 0xA2, 0xBA, 0x14, + 0x26, 0x9D, 0xA8, 0x3B, 0x6A, 0xA6, 0x0B, 0xDB, 0x1E, 0xE0, 0xD9, 0x88, 0xEC, 0xDC, 0x24, 0x90, + 0x4C, 0x16, 0x73, 0xB2, 0x65, 0x97, 0x53, 0x9A, 0xD1, 0x31, 0x2A, 0x39, 0x13, 0xC2, 0x44, 0x70, + 0x2C, 0x01, 0x39, 0xAB, 0xB2, 0x35, 0x37, 0x55, 0xD3, 0x38, 0x59, 0xB0, 0xEF, 0xF0, 0x07, 0x37, + 0x05, 0xFA, 0x99, 0x31, 0x53, 0xF5, 0x8D, 0xD8, 0x0A, 0x41, 0x8E, 0x8F, 0xB7, 0xC6, 0xD0, 0xF7, + 0x9D, 0xB9, 0xB1, 0x40, 0xF4, 0xDA, 0xF0, 0xC2, 0x54, 0x77, 0xA2, 0x62, 0xFB, 0xF4, 0x9C, 0x5F, + 0x89, 0x28, 0x3B, 0xF6, 0x4C, 0x6C, 0xBD, 0x61, 0x64, 0x21, 0x4F, 0x6B, 0xDA, 0xBE, 0x03, 0x89, + 0x3D, 0xED, 0x83, 0x09, 0x2B, 0x75, 0xB0, 0x5C, 0xB3, 0x39, 0x5D, 0xC4, 0xA0, 0x31, 0x8C, 0xD7, + 0x3A, 0xB2, 0xFA, 0x1F, 0x68, 0x09, 0x3D, 0x03, 0x3A, 0x58, 0x52, 0x26, 0x1A, 0x79, 0x8C, 0x7D, + 0x14, 0x16, 0x64, 0xD2, 0x71, 0x05, 0xFC, 0x4D, 0xD7, 0x34, 0x34, 0x42, 0xFF, 0x58, 0x42, 0x53, + 0xFF, 0x32, 0xF1, 0xF5, 0x76, 0x8E, 0x0C, 0x7D, 0x9E, 0x84, 0x03, 0xD4, 0xD0, 0x1B, 0x3A, 0x24, + 0x2E, 0xBC, 0xC8, 0x94, 0xEB, 0xB2, 0x58, 0x41, 0xD0, 0xCC, 0x7A, 0xD0, 0xB3, 0x47, 0x28, 0xA8, + 0x08, 0x07, 0xD1, 0x19, 0xE4, 0x62, 0x3D, 0xD7, 0x8F, 0xD0, 0xC6, 0xBC, 0xE2, 0xB9, 0x7B, 0x65, + 0x72, 0x10, 0xF9, 0x9D, 0x42, 0x68, 0x69, 0x71, 0x72, 0xBC, 0x78, 0xF7, 0x43, 0x5B, 0xEC, 0xAD, + 0xCB, 0x57, 0x25, 0x32, 0x95, 0xDA, 0x44, 0x4F, 0x8D, 0x28, 0x5D, 0x4B, 0x3E, 0x60, 0xA3, 0xE2, + 0xF6, 0xFD, 0x5B, 0x96, 0x4C, 0x9A, 0x45, 0x50, 0x49, 0xF4, 0x27, 0x36, 0xD7, 0x83, 0xBE, 0xE8, + 0x64, 0xA9, 0x92, 0xDF, 0xE2, 0x7B, 0xFF, 0xB5, 0x9B, 0x68, 0x29, 0x99, 0xD1, 0xC7, 0x8E, 0x1D, + 0x3D, 0x9A, 0xAB, 0x22, 0x04, 0x91, 0x12, 0x31, 0xC3, 0xFA, 0x21, 0x8E, 0xE4, 0x42, 0x04, 0x45, + 0x8B, 0x2C, 0xA3, 0x27, 0xB7, 0x6F, 0x3E, 0xBC, 0x29, 0xDB, 0xD2, 0x0C, 0x4B, 0x20, 0x58, 0x0A, + 0x8F, 0x77, 0x65, 0xF5, 0x11, 0x38, 0x83, 0x9E, 0x06, 0x11, 0xB0, 0xAD, 0x9F, 0xB4, 0x54, 0xF0, + 0x45, 0x8C, 0x49, 0xDF, 0x6A, 0x30, 0xA1, 0xED, 0xE4, 0x45, 0x03, 0xD8, 0x21, 0xDB, 0x2F, 0x31, + 0xBC, 0x1F, 0xF1, 0x12, 0xB3, 0xC2, 0xC0, 0x2F, 0x41, 0xE6, 0xCA, 0x62, 0x81, 0xEE, 0xE0, 0x31, + 0xC8, 0xF2, 0xF6, 0xC6, 0x8F, 0x07, 0x1D, 0x65, 0x5C, 0xBC, 0x34, 0x48, 0xE5, 0x19, 0xD5, 0xDD, + 0x25, 0x1C, 0x84, 0xB3, 0x99, 0x2C, 0x63, 0x62, 0x0C, 0xA0, 0x5B, 0xF5, 0x16, 0xC4, 0x30, 0xA4, + 0x1D, 0x71, 0x3A, 0x36, 0xE6, 0x64, 0x7B, 0xD2, 0x1F, 0x9E, 0xB7, 0xC4, 0x5A, 0x03, 0x43, 0xF7, + 0xB9, 0xE6, 0x22, 0x22, 0x49, 0x74, 0x0B, 0x9C, 0x65, 0x1E, 0xF8, 0xEC, 0x01, 0xF7, 0x74, 0x9C, + 0x20, 0xF6, 0x5E, 0xFC, 0xAD, 0xBE, 0xFB, 0xE2, 0x45, 0x87, 0x1E, 0x78, 0x19, 0xE1, 0x8F, 0xB0, + 0xEC, 0xD2, 0x41, 0xAC, 0xCF, 0xF3, 0x80, 0x07, 0xD2, 0xFB, 0x56, 0x88, 0xF5, 0x8C, 0x82, 0x75, + 0xBF, 0x85, 0xC1, 0x53, 0xC5, 0x38, 0xBE, 0x7D, 0x85, 0xCA, 0xE2, 0x1B, 0x47, 0x48, 0xF8, 0xA3, + 0xD8, 0x48, 0x36, 0xD8, 0x98, 0xBC, 0x7E, 0x6B, 0x5B, 0x0B, 0xCD, 0xFA, 0xF5, 0xEA, 0xF6, 0x6B, + 0x6F, 0x66, 0xF9, 0xB9, 0xE3, 0xB7, 0x7E, 0xE8, 0x55, 0x37, 0xE6, 0x04, 0x66, 0xFC, 0xA6, 0xD7, + 0xBF, 0xF7, 0x33, 0xF8, 0xEA, 0xBF, 0x59, 0x7D, 0x04, 0xFC, 0x33, 0x9E, 0x8D, 0x30, 0xD8, 0xDD, + 0xCF, 0x12, 0x8F, 0x45, 0xD8, 0x58, 0x44, 0xFF, 0xB2, 0xC1, 0x31, 0x31, 0xFA, 0x4B, 0xCA, 0xDF, + 0x5A, 0x0F, 0xD0, 0x3A, 0xA7, 0x70, 0xA2, 0x0F, 0x04, 0x45, 0x14, 0xF4, 0x19, 0x0C, 0xF8, 0xD2, + 0x95, 0xEA, 0xF2, 0xC5, 0x33, 0xE2, 0xFE, 0xBB, 0xC9, 0x9F, 0x58, 0x63, 0x3A, 0x83, 0x19, 0x69, + 0x3B, 0x6D, 0x77, 0x52, 0x50, 0xD3, 0x3D, 0xF7, 0x02, 0x55, 0xEE, 0xA4, 0xD8, 0xFF, 0xAC, 0x56, + 0xC3, 0x91, 0xDD, 0xCE, 0x70, 0x1A, 0x34, 0x3B, 0x35, 0x1E, 0x9C, 0x33, 0x08, 0x74, 0x9F, 0x3B, + 0x07, 0x98, 0x03, 0xF6, 0x42, 0x52, 0xDF, 0x0D, 0x31, 0xC9, 0x50, 0xD3, 0x34, 0x89, 0x6E, 0xBC, + 0xF8, 0x57, 0xEC, 0xFD, 0x7F, 0xED, 0xCA, 0xA6, 0x1E, 0xE4, 0x91, 0x1F, 0xFD, 0x27, 0x2F, 0x9A, + 0x19, 0x20, 0x90, 0x6B, 0xFF, 0x90, 0xD0, 0x8D, 0x6E, 0xD2, 0x00, 0x59, 0x14, 0x4D, 0xFD, 0x3D, + 0x89, 0x2D, 0x60, 0xF0, 0x15, 0xAF, 0x70, 0xC1, 0x75, 0xCF, 0x7B, 0xD1, 0xCC, 0xE0, 0xE3, 0xE3, + 0x5F, 0x5E, 0x8B, 0x66, 0x9E, 0xFB, 0xD1, 0x3D, 0x83, 0x37, 0x6E, 0x34, 0x93, 0xC4, 0x5C, 0x99, + 0x14, 0x60, 0xD2, 0x68, 0x20, 0xFF, 0xA1, 0xD7, 0xBE, 0xF6, 0xD0, 0x5F, 0x1D, 0x80, 0x3C, 0xCC, + 0x5D, 0xFC, 0x16, 0x7C, 0x05, 0xF0, 0x66, 0x67, 0x02, 0x15, 0x56, 0x57, 0x00, 0x01, 0x22, 0x7D, + 0xDE, 0x8D, 0x98, 0x12, 0xE8, 0x69, 0x08, 0xBE, 0x36, 0x88, 0xC3, 0xAE, 0x71, 0x36, 0xE9, 0x46, + 0x76, 0xDD, 0xC8, 0x6B, 0xE1, 0xC2, 0xD7, 0xD0, 0xC8, 0xDF, 0x26, 0xF1, 0xEF, 0x56, 0x51, 0x18, + 0x9C, 0x47, 0x9F, 0x5C, 0xCB, 0xEB, 0x25, 0xBE, 0xBE, 0x02, 0xFF, 0xFB, 0x4B, 0xE4, 0xF5, 0x62, + 0xCE, 0x3F, 0x5F, 0x7F, 0x72, 0x1F, 0x1A, 0x75, 0x0E, 0xB7, 0xBD, 0x2C, 0xBC, 0x9F, 0xA3, 0x79, + 0xF8, 0x2C, 0xB6, 0xA8, 0x1A, 0x7D, 0xBB, 0x96, 0x8F, 0xDB, 0x12, 0xA8, 0x96, 0x2D, 0xBB, 0x63, + 0xDC, 0xD1, 0x19, 0xFD, 0x46, 0x24, 0x04, 0x89, 0x20, 0xEB, 0x8D, 0xEA, 0xC5, 0x71, 0xA5, 0x4E, + 0xDC, 0x75, 0x12, 0xB8, 0xC2, 0x64, 0x90, 0xFA, 0x5C, 0x1F, 0xBA, 0xF6, 0xA0, 0x9B, 0x9D, 0xEA, + 0x25, 0x61, 0xB4, 0x5B, 0x3D, 0x22, 0xBB, 0xD1, 0x63, 0x42, 0x38, 0x68, 0xFE, 0x1E, 0x86, 0x4F, + 0x8D, 0x4F, 0xA5, 0xF2, 0x9C, 0x9C, 0x34, 0xF9, 0x56, 0x49, 0x64, 0x0A, 0x11, 0x11, 0x55, 0xD3, + 0xCD, 0x88, 0x4C, 0x13, 0xBD, 0xB9, 0xE2, 0x52, 0xB6, 0x2A, 0x99, 0x49, 0x31, 0xD8, 0xF2, 0x19, + 0x2A, 0x3B, 0x17, 0xCE, 0x2B, 0xD1, 0x83, 0xF9, 0x72, 0x21, 0x35, 0xBF, 0xD7, 0xF2, 0x6D, 0xE9, + 0x87, 0x38, 0x8A, 0xB6, 0x65, 0x32, 0x92, 0xA6, 0x15, 0x19, 0x95, 0x92, 0x21, 0xC8, 0x8C, 0x65, + 0xEC, 0x9D, 0x65, 0x5B, 0x42, 0xD8, 0xEA, 0x2C, 0x14, 0x78, 0x61, 0xDC, 0xE7, 0x3F, 0xD3, 0xDD, + 0xB4, 0x63, 0xD1, 0x9D, 0xC7, 0x7F, 0xC1, 0x96, 0x75, 0x94, 0xF0, 0x83, 0x71, 0x2C, 0x43, 0x83, + 0xED, 0xBC, 0x55, 0xAF, 0x94, 0x4D, 0x2D, 0x63, 0x4E, 0x54, 0xE3, 0x71, 0x24, 0x45, 0x63, 0x48, + 0x0A, 0xFD, 0x23, 0x53, 0xBA, 0x14, 0x64, 0x81, 0x6B, 0x29, 0xE0, 0x1B, 0x35, 0xB2, 0x1B, 0x18, + 0xB0, 0xBC, 0xC0, 0x00, 0xE3, 0x65, 0x80, 0x13, 0x6E, 0x95, 0x84, 0xE7, 0x08, 0xF1, 0xCC, 0xA8, + 0x76, 0xCB, 0xB6, 0x1C, 0x63, 0x2D, 0xE7, 0xDE, 0xB5, 0xB4, 0x86, 0x62, 0xD5, 0xF5, 0x90, 0x21, + 0x99, 0x2F, 0x56, 0xE4, 0xE0, 0xB5, 0xE3, 0xED, 0x1D, 0x26, 0x47, 0x10, 0x18, 0x64, 0x70, 0x8A, + 0xC0, 0x07, 0xE7, 0x04, 0x31, 0x26, 0xA8, 0xAA, 0x0F, 0xD1, 0x74, 0x62, 0x97, 0xB4, 0xA0, 0xA7, + 0x16, 0x47, 0x34, 0x7A, 0x7F, 0x38, 0x36, 0xDB, 0x50, 0x0C, 0xF6, 0x7C, 0x64, 0x2C, 0x2F, 0x3B, + 0xB3, 0x3B, 0x46, 0xF7, 0x3C, 0x79, 0x7A, 0x6C, 0x5B, 0x9B, 0x22, 0x15, 0xBD, 0xCE, 0xF2, 0x3E, + 0x0E, 0x21, 0x5D, 0xCD, 0x5C, 0x3C, 0xDC, 0xAD, 0x1F, 0x54, 0x0E, 0x6A, 0xF1, 0xE3, 0x93, 0x50, + 0x19, 0xD3, 0x17, 0x82, 0xE9, 0x8A, 0x59, 0x19, 0x64, 0x52, 0x3E, 0x07, 0xDF, 0x0B, 0xFF, 0x37, + 0x28, 0xB9, 0x31, 0xB1, 0xA4, 0xC9, 0x81, 0x48, 0xE9, 0xCF, 0xCB, 0x05, 0xB3, 0x1C, 0x3C, 0xAF, + 0x28, 0xDF, 0x24, 0x4A, 0x2F, 0x15, 0x13, 0x2B, 0xBB, 0x89, 0x80, 0x9E, 0xC0, 0x24, 0x86, 0xF0, + 0xD9, 0x4D, 0x60, 0x50, 0x28, 0xCF, 0xCF, 0x07, 0x87, 0xD6, 0x71, 0x1B, 0xBE, 0x79, 0x64, 0x77, + 0x6F, 0xFB, 0x6E, 0x85, 0xA7, 0x0B, 0x2B, 0xA3, 0xD3, 0x11, 0x5F, 0xC9, 0x8A, 0xC4, 0x7D, 0x9C, + 0xC4, 0x05, 0x89, 0x4E, 0xDA, 0x6F, 0x8B, 0x9A, 0x3D, 0x5D, 0xCA, 0xC5, 0x60, 0x28, 0xB0, 0x33, + 0x35, 0x79, 0x67, 0x34, 0x95, 0x54, 0xB2, 0xC7, 0x77, 0x46, 0x2D, 0x55, 0x76, 0x02, 0xC1, 0x80, + 0x4E, 0x73, 0x8C, 0x1C, 0x9B, 0x37, 0x05, 0x27, 0xEE, 0xEC, 0xDD, 0x1C, 0x13, 0x11, 0xE7, 0x55, + 0x23, 0x62, 0x8B, 0x37, 0x83, 0xFE, 0x33, 0xE8, 0x82, 0x6C, 0x5F, 0xE9, 0x94, 0x8B, 0x99, 0x90, + 0x2A, 0xF3, 0xBE, 0xF7, 0x4F, 0x16, 0xBE, 0xC5, 0x2C, 0x0E, 0xBA, 0xB9, 0x51, 0xAC, 0x4F, 0x66, + 0xDC, 0xA9, 0xA7, 0x06, 0x19, 0x17, 0x03, 0x9B, 0x1D, 0x7A, 0xAA, 0xDC, 0xB3, 0x6B, 0x99, 0x35, + 0xE1, 0x8E, 0x4D, 0x1D, 0x37, 0x7E, 0x89, 0xD9, 0x1B, 0x89, 0x7C, 0xA3, 0x6D, 0xCE, 0x8D, 0x87, + 0x77, 0xDD, 0x70, 0x4B, 0x5C, 0x08, 0x70, 0x0C, 0x9F, 0x68, 0x86, 0xB9, 0xE4, 0x08, 0x87, 0x98, + 0xA9, 0xE5, 0xE0, 0x99, 0xFD, 0x11, 0x95, 0x7D, 0x50, 0x55, 0x33, 0x5A, 0x90, 0x8B, 0x64, 0xF3, + 0x9A, 0x9D, 0x28, 0xEC, 0xF9, 0x92, 0x3D, 0x51, 0xD7, 0xAA, 0xF6, 0xA3, 0xDD, 0x23, 0xB3, 0x1A, + 0x9B, 0x6F, 0xE8, 0x59, 0xCD, 0x1C, 0x75, 0xE8, 0x7C, 0x5D, 0x65, 0xB4, 0xA9, 0x85, 0x9C, 0x50, + 0x48, 0xFA, 0x74, 0xCD, 0x60, 0x0F, 0x89, 0x92, 0x19, 0x0E, 0xF0, 0x32, 0x2D, 0xAB, 0x0A, 0xC3, + 0x4A, 0x76, 0x6F, 0x73, 0xD5, 0xCB, 0xFB, 0x5D, 0xFD, 0x09, 0xFC, 0x10, 0xFC, 0x19, 0x28, 0x63, + 0xDE, 0xB1, 0x82, 0x3A, 0x28, 0x3F, 0x56, 0x29, 0x7C, 0xA7, 0x12, 0xCB, 0x64, 0x10, 0xAF, 0x7C, + 0x97, 0xFA, 0xA7, 0xF5, 0x0A, 0x91, 0xDE, 0x86, 0x8A, 0xAF, 0xC1, 0xC8, 0x2A, 0xBC, 0xE7, 0x60, + 0x43, 0x03, 0x93, 0xC6, 0x4B, 0xBC, 0xF4, 0x92, 0x0D, 0xC8, 0x4B, 0x39, 0x8D, 0xC3, 0xF4, 0xA4, + 0x1E, 0x84, 0x1F, 0xD2, 0x3B, 0xB9, 0x66, 0xB8, 0xD2, 0x17, 0x76, 0x4E, 0xDD, 0xB8, 0x2D, 0xD3, + 0x9E, 0x92, 0xE2, 0xB1, 0x02, 0x99, 0x2B, 0x49, 0x52, 0x51, 0x14, 0xB7, 0xB1, 0xA1, 0x54, 0xFC, + 0xE0, 0x62, 0x32, 0x23, 0x1D, 0x55, 0x9B, 0x51, 0xA7, 0xCA, 0xEF, 0xD9, 0x3F, 0x7E, 0xDB, 0x72, + 0xBC, 0x9E, 0x56, 0xE3, 0x09, 0x27, 0x42, 0xF8, 0xC3, 0x1A, 0x97, 0xB6, 0x34, 0xB5, 0x6C, 0x55, + 0x72, 0xA5, 0x6D, 0xD7, 0x28, 0xB4, 0x87, 0x2D, 0x5E, 0x80, 0xDF, 0x21, 0x34, 0x8C, 0xB3, 0x8E, + 0xF4, 0x6B, 0x05, 0x03, 0x54, 0xB2, 0x06, 0x4B, 0x7E, 0xAF, 0x53, 0x48, 0xDF, 0x35, 0x22, 0xD7, + 0x7F, 0x19, 0x41, 0xC9, 0xA8, 0x2C, 0x11, 0x22, 0x6A, 0xA4, 0x53, 0x44, 0x3D, 0x18, 0x40, 0x49, + 0x3F, 0x4A, 0xC4, 0x93, 0x9D, 0x4A, 0x7C, 0xE6, 0x2C, 0x2C, 0x5C, 0x01, 0x39, 0x5C, 0x1F, 0xC4, + 0x20, 0x3D, 0xDB, 0xF5, 0x23, 0x76, 0x2F, 0x6C, 0xD4, 0xCD, 0x2E, 0x00, 0x2B, 0x78, 0xE5, 0x13, + 0xD9, 0xA1, 0xC9, 0xEE, 0x58, 0xAE, 0x33, 0x5F, 0xA1, 0xA2, 0xAE, 0x31, 0xA3, 0xA0, 0x66, 0x96, + 0xC8, 0xD2, 0xC9, 0x82, 0x5B, 0x6C, 0x14, 0x25, 0x9A, 0x53, 0xB4, 0xC7, 0x37, 0x8E, 0x0D, 0xBF, + 0x13, 0x8D, 0x88, 0x51, 0xC9, 0xA8, 0x49, 0x21, 0x6C, 0x33, 0x38, 0xED, 0xA8, 0xAA, 0xF1, 0x5C, + 0x42, 0xB0, 0x9B, 0x24, 0xE2, 0xC9, 0x40, 0xF0, 0x20, 0xE4, 0x50, 0x24, 0xAA, 0xA7, 0x74, 0x6C, + 0x77, 0x32, 0xC1, 0xB0, 0xE3, 0xA3, 0xE2, 0xB3, 0xE1, 0x6A, 0x32, 0xC9, 0x59, 0x4A, 0xC1, 0x8F, + 0xF9, 0xE4, 0x1F, 0x7C, 0x21, 0x3E, 0xA4, 0x98, 0xD1, 0xE9, 0xA9, 0x6A, 0x4C, 0xC6, 0x52, 0x19, + 0x89, 0x42, 0x5E, 0x0C, 0x32, 0xBB, 0xF2, 0x23, 0xD7, 0x24, 0x74, 0x6D, 0x32, 0x6E, 0x42, 0x6D, + 0x91, 0x80, 0x41, 0xBF, 0x3F, 0x88, 0xF0, 0x5F, 0xB1, 0x39, 0x31, 0xEF, 0x4F, 0x19, 0x14, 0xED, + 0xC8, 0x9C, 0xAB, 0xA7, 0x8D, 0xD5, 0x34, 0x3A, 0x0A, 0x7F, 0x0E, 0xAE, 0x02, 0x33, 0xFD, 0xD0, + 0xD6, 0xD9, 0xF1, 0x56, 0x2D, 0x21, 0x92, 0x04, 0xD8, 0xBB, 0x67, 0x97, 0x31, 0xF9, 0xBA, 0x03, + 0xCD, 0xFB, 0x0E, 0x2C, 0x28, 0x6D, 0x07, 0x7C, 0x3F, 0xFF, 0x83, 0x81, 0xE3, 0xDC, 0x0B, 0xC5, + 0x5E, 0x89, 0x47, 0xBC, 0xA1, 0x1F, 0xA8, 0x79, 0x76, 0x88, 0x6B, 0x8A, 0x0F, 0xB2, 0x84, 0xD6, + 0xDC, 0x16, 0x78, 0x51, 0x3C, 0xDB, 0xD4, 0x8D, 0xD6, 0x26, 0xD7, 0xDD, 0x51, 0x5E, 0x8E, 0x5A, + 0xDD, 0x5D, 0x6D, 0x97, 0xB4, 0x33, 0x43, 0xAB, 0x16, 0x35, 0xA2, 0x9E, 0x46, 0x47, 0x47, 0x8B, + 0xE5, 0x39, 0xDD, 0xF1, 0x91, 0xAA, 0x28, 0x33, 0xC4, 0x44, 0x8A, 0x97, 0x32, 0x71, 0x96, 0xE6, + 0x03, 0xD1, 0xDC, 0xA7, 0x95, 0xEB, 0xA6, 0x77, 0x1D, 0x58, 0xDE, 0x15, 0x67, 0x59, 0x3E, 0xE3, + 0xE4, 0x6D, 0x7F, 0x72, 0x42, 0x63, 0xE9, 0xDD, 0x12, 0x5B, 0xCA, 0x86, 0xF0, 0xAA, 0x35, 0x2A, + 0x8F, 0x67, 0xED, 0x4D, 0x53, 0x8F, 0x6D, 0x69, 0x09, 0x51, 0xD9, 0x29, 0xCF, 0xC1, 0x9F, 0xD7, + 0x9B, 0x94, 0x1E, 0x4D, 0x99, 0x0E, 0xA1, 0xF0, 0x92, 0x26, 0x8B, 0xA5, 0x1A, 0xC9, 0x17, 0x03, + 0xAA, 0xCA, 0xC9, 0xB6, 0xC8, 0x44, 0xC8, 0xD8, 0x5C, 0x7E, 0xDF, 0xCC, 0x48, 0xC2, 0xC0, 0xB2, + 0xC9, 0x17, 0xC0, 0x8B, 0x14, 0xA9, 0x89, 0xA2, 0x2C, 0x36, 0x44, 0x5D, 0xB1, 0x4B, 0x66, 0x3A, + 0x21, 0x30, 0x26, 0x4D, 0xE7, 0x46, 0xB3, 0x2B, 0x77, 0xC5, 0xBC, 0x24, 0x1E, 0xB8, 0xFA, 0xC3, + 0xD5, 0x67, 0x31, 0x74, 0xD0, 0x30, 0x3F, 0x2F, 0xF6, 0xC3, 0x85, 0x98, 0x4F, 0x23, 0x41, 0xB3, + 0x1A, 0x0D, 0xF1, 0x6A, 0xD9, 0xAE, 0x56, 0xCA, 0xC8, 0x31, 0xEC, 0x5C, 0x45, 0x25, 0xE7, 0xD6, + 0xB0, 0xAA, 0x57, 0x2B, 0xE5, 0x39, 0x3C, 0x2E, 0x61, 0xD5, 0x0D, 0x1A, 0x65, 0x32, 0xE6, 0xBA, + 0x39, 0x08, 0x2F, 0x06, 0x22, 0x13, 0x6E, 0x7E, 0x72, 0xD7, 0x45, 0xE7, 0x83, 0xE0, 0x03, 0xCC, + 0x66, 0xB0, 0x3A, 0xC1, 0xD2, 0xD5, 0xCD, 0xE6, 0x0B, 0xC3, 0xB6, 0x2B, 0xB4, 0x30, 0xDF, 0x13, + 0x68, 0x3C, 0x1A, 0x49, 0xC4, 0x29, 0x51, 0xF4, 0x85, 0xAC, 0x82, 0xAF, 0x74, 0x43, 0xDA, 0x71, + 0xE3, 0xAB, 0x34, 0xA3, 0x59, 0xB2, 0xC5, 0x51, 0x70, 0x53, 0x51, 0xD3, 0xFD, 0x34, 0x53, 0x40, + 0x28, 0xD1, 0x49, 0xCF, 0x35, 0x34, 0x5F, 0xD0, 0xE0, 0x69, 0x02, 0xCD, 0x1A, 0x96, 0xED, 0x64, + 0xA6, 0x8E, 0x77, 0x66, 0x13, 0x76, 0xE5, 0x91, 0x15, 0x6E, 0x74, 0xFC, 0xAA, 0x77, 0x2C, 0x06, + 0xAE, 0xCD, 0xE4, 0x46, 0x79, 0xDA, 0x20, 0xAA, 0x21, 0x41, 0x10, 0x89, 0xB9, 0xC2, 0x7C, 0xFA, + 0x87, 0x37, 0xE4, 0x16, 0xF2, 0xBD, 0x44, 0xEF, 0xEA, 0x9D, 0xFD, 0x62, 0xC6, 0xCD, 0x38, 0x79, + 0x61, 0xF5, 0x79, 0xF0, 0x3C, 0x7A, 0x1F, 0x90, 0x41, 0xDA, 0x1D, 0x73, 0x50, 0x89, 0x05, 0x1C, + 0x42, 0x48, 0x9B, 0x21, 0xD6, 0x02, 0x29, 0x0B, 0xA5, 0x30, 0x42, 0x4F, 0x0B, 0xFF, 0x3F, 0x6D, + 0xF1, 0x2C, 0x0C, 0x5E, 0x1E, 0x98, 0x18, 0x64, 0xDE, 0x5C, 0x0E, 0xD2, 0x5D, 0x57, 0x7B, 0x70, + 0x98, 0x55, 0xE6, 0xBA, 0xAB, 0x5B, 0x98, 0x14, 0x22, 0xD0, 0xC0, 0x78, 0x2E, 0xD3, 0xCC, 0x8E, + 0x6E, 0x74, 0xB8, 0x5B, 0xCE, 0xF3, 0xFB, 0x25, 0x1F, 0x1F, 0xB0, 0x25, 0x3A, 0x57, 0x8E, 0xC9, + 0x56, 0x90, 0x59, 0x9C, 0x45, 0x5C, 0x5E, 0xC0, 0xC8, 0xBC, 0x1D, 0xED, 0xFB, 0x38, 0x22, 0xA4, + 0x32, 0xE8, 0xE8, 0xAC, 0x40, 0xEB, 0x96, 0x94, 0x8C, 0x99, 0x4A, 0xC0, 0xBC, 0xF0, 0xE3, 0x7C, + 0x2B, 0x71, 0x9B, 0xFD, 0x86, 0x1D, 0x34, 0x69, 0x46, 0xAD, 0xB2, 0x4A, 0x27, 0x8A, 0xEF, 0xF0, + 0xFA, 0x6F, 0x0F, 0xFB, 0x9F, 0x01, 0xBD, 0xBE, 0x3F, 0x11, 0x54, 0x22, 0x6E, 0xFF, 0x75, 0x56, + 0x07, 0x69, 0x43, 0x47, 0x19, 0xDC, 0x79, 0xFD, 0x7F, 0xAE, 0xF5, 0x7D, 0x90, 0x83, 0x39, 0xF0, + 0x4B, 0x6D, 0x4C, 0x49, 0xC6, 0xFD, 0xCE, 0xBE, 0xB8, 0xDF, 0xAE, 0x61, 0xA5, 0xAD, 0x2D, 0xD6, + 0xA0, 0xF4, 0xCC, 0x4B, 0x48, 0xBC, 0xA2, 0xE7, 0x64, 0x71, 0x3E, 0x4E, 0xEB, 0xBA, 0xC8, 0x72, + 0xF2, 0xBB, 0x59, 0x4E, 0xB5, 0x68, 0x8C, 0xA0, 0x2F, 0xEF, 0xFA, 0x6F, 0x7F, 0x2A, 0x45, 0x0D, + 0x78, 0xDF, 0x03, 0x5B, 0x22, 0x0C, 0x6B, 0xDC, 0x42, 0xD9, 0xB5, 0xA9, 0x5D, 0x5F, 0x3A, 0xBC, + 0xDB, 0x9D, 0xFD, 0x7F, 0xC1, 0xFA, 0x63, 0x81, 0xB0, 0x40, 0x02, 0xCC, 0x83, 0x95, 0x7E, 0xA1, + 0xD7, 0x1D, 0x1D, 0xC1, 0x30, 0x20, 0x18, 0x50, 0x89, 0x76, 0x56, 0x11, 0xE7, 0xEF, 0x5F, 0x98, + 0x7D, 0xCB, 0x42, 0x1C, 0x24, 0x10, 0x1D, 0x8F, 0x21, 0x3A, 0x82, 0x34, 0xDA, 0xFE, 0xA1, 0x1B, + 0x7C, 0x53, 0x2F, 0x77, 0x9E, 0x0E, 0x92, 0xD9, 0x5E, 0x9A, 0x77, 0xDD, 0xB1, 0x2D, 0xA8, 0x54, + 0xB1, 0x3D, 0x88, 0xF9, 0xB8, 0x1E, 0xC7, 0x81, 0xC2, 0xF7, 0x68, 0x0F, 0xEB, 0x1F, 0xCB, 0xD1, + 0xAD, 0x28, 0x31, 0x74, 0x54, 0x42, 0x2F, 0x28, 0x8C, 0x39, 0x96, 0xC1, 0xAA, 0x68, 0xA0, 0x42, + 0xA1, 0x97, 0x34, 0xD3, 0x3E, 0x9F, 0x9E, 0xCE, 0x22, 0x48, 0x88, 0x14, 0x1D, 0x94, 0x74, 0x8E, + 0x39, 0x42, 0x07, 0x0C, 0x5D, 0x0C, 0x70, 0x98, 0x34, 0x31, 0x16, 0xC0, 0xCF, 0xB7, 0xEF, 0xE5, + 0x6D, 0x21, 0x74, 0x28, 0xA4, 0x76, 0x77, 0x90, 0x92, 0xD1, 0xE7, 0xA6, 0x03, 0x01, 0x27, 0x9C, + 0x08, 0x95, 0x0E, 0x5D, 0x5B, 0x2A, 0x68, 0x14, 0xBB, 0xD5, 0x28, 0x44, 0xA6, 0xEE, 0x9B, 0xBA, + 0xF3, 0xD6, 0x87, 0x0B, 0x69, 0x9A, 0x54, 0x17, 0x49, 0x43, 0x64, 0xA3, 0x2A, 0x37, 0x32, 0x72, + 0xF1, 0x47, 0xFD, 0x42, 0x33, 0x9F, 0x0C, 0xCE, 0xB1, 0xCA, 0x99, 0x84, 0xB5, 0xAD, 0x4F, 0x4A, + 0x7E, 0x25, 0x6C, 0xC0, 0xBA, 0x65, 0x13, 0x8C, 0xAE, 0xD9, 0xC1, 0xF4, 0xAE, 0x9B, 0x1A, 0x09, + 0x34, 0xF0, 0x9B, 0x3C, 0x0F, 0xBE, 0x81, 0xE7, 0x2A, 0x86, 0xB5, 0x93, 0xA1, 0x20, 0x20, 0x0B, + 0x2A, 0x85, 0x02, 0xFE, 0xA0, 0xF5, 0x43, 0xF4, 0x12, 0xF1, 0xC8, 0x8D, 0xC1, 0xBF, 0xB8, 0x1B, + 0x8E, 0xA4, 0x7F, 0xD7, 0xF0, 0x8D, 0x28, 0xF1, 0x8D, 0xF9, 0x25, 0x77, 0x6C, 0x24, 0x1D, 0x92, + 0xB0, 0x1C, 0xC6, 0x63, 0x33, 0x75, 0xE1, 0xD2, 0xD8, 0xB6, 0xA6, 0x5B, 0x2F, 0xDD, 0xF5, 0xF7, + 0xB8, 0x3D, 0xF7, 0xAC, 0x8B, 0x9F, 0x13, 0xEF, 0xC4, 0x98, 0x73, 0x27, 0x68, 0xF5, 0xED, 0x62, + 0x2A, 0x99, 0x50, 0xC1, 0x4C, 0xAB, 0x56, 0xC8, 0x05, 0x94, 0x1F, 0xED, 0x5A, 0x9C, 0xFC, 0x46, + 0x22, 0x4E, 0xB2, 0x5E, 0x6A, 0x47, 0x77, 0x1D, 0x8B, 0x6D, 0x10, 0x12, 0xBB, 0x8A, 0xAE, 0xAD, + 0xA7, 0x20, 0x2F, 0x22, 0xE5, 0xB9, 0xB9, 0x71, 0x27, 0xC9, 0x01, 0xD5, 0xC9, 0x88, 0x49, 0xB6, + 0x07, 0xB2, 0xD6, 0x8B, 0xA1, 0xBA, 0xA9, 0x5B, 0xC4, 0xBA, 0xC3, 0x1B, 0x5B, 0xBA, 0x03, 0x99, + 0x41, 0x11, 0xEF, 0x6C, 0xB4, 0x78, 0x8E, 0x16, 0xF5, 0x60, 0x44, 0x2F, 0x54, 0xB7, 0xD4, 0x74, + 0xC3, 0xCD, 0xE4, 0x45, 0x2C, 0x1D, 0xD0, 0x34, 0xD9, 0x4E, 0x97, 0xAF, 0x89, 0x87, 0xA1, 0x1C, + 0x93, 0x04, 0x56, 0xEB, 0xCD, 0xB3, 0xAC, 0xE2, 0x04, 0x19, 0x8C, 0xFF, 0xAB, 0x7B, 0x37, 0x13, + 0x92, 0xA6, 0x07, 0x22, 0x36, 0x83, 0xDA, 0xD7, 0xE7, 0xEA, 0x76, 0x42, 0x63, 0x79, 0xCD, 0xCD, + 0x3F, 0x58, 0x88, 0xE4, 0x58, 0xB6, 0x7B, 0xFC, 0x86, 0x4D, 0xE1, 0xFA, 0xD1, 0xFD, 0x71, 0x32, + 0xD1, 0xA8, 0xAA, 0x71, 0x21, 0xEB, 0x0F, 0xF2, 0x6A, 0x7C, 0xF4, 0xD5, 0xDB, 0xEA, 0x6F, 0x5D, + 0xEE, 0x66, 0x24, 0xBB, 0x50, 0xA7, 0x19, 0x44, 0x95, 0xBA, 0xE2, 0x2D, 0x81, 0xC9, 0xE5, 0x59, + 0x7C, 0xA5, 0xD6, 0xA1, 0x6D, 0xE1, 0xC5, 0x9B, 0x32, 0xD9, 0x4A, 0xBC, 0x79, 0x34, 0xA0, 0x54, + 0xA6, 0x86, 0x6B, 0x86, 0xA6, 0x30, 0xA2, 0x68, 0xBB, 0x95, 0x11, 0x99, 0x88, 0xA5, 0x83, 0x42, + 0x38, 0xC0, 0xD5, 0xE2, 0xDF, 0xD5, 0x35, 0x62, 0x71, 0x38, 0x27, 0x97, 0x87, 0xD7, 0xC7, 0x22, + 0x1E, 0x90, 0x63, 0xDC, 0x62, 0x3B, 0x57, 0x6A, 0xE2, 0x89, 0xC1, 0xC2, 0xA3, 0x8A, 0x36, 0x14, + 0x80, 0x22, 0x4C, 0xAF, 0x83, 0x7C, 0x27, 0x2C, 0x2D, 0xA7, 0x22, 0xAD, 0x1C, 0x32, 0x38, 0x3E, + 0x14, 0x30, 0x5B, 0x57, 0x35, 0x74, 0x6C, 0x8B, 0x04, 0x39, 0x01, 0x11, 0x74, 0x4A, 0x12, 0x38, + 0xE1, 0x6D, 0x0C, 0xCB, 0x19, 0x06, 0x0F, 0x49, 0x48, 0x9A, 0x46, 0xBB, 0x37, 0x1F, 0x88, 0x04, + 0x0D, 0x41, 0xA5, 0xD1, 0x82, 0x9A, 0x48, 0xCA, 0xAF, 0xEC, 0x8D, 0x4C, 0x16, 0x4E, 0xAE, 0xA4, + 0x6C, 0x5E, 0x44, 0xA5, 0x37, 0xA3, 0x13, 0xBA, 0x55, 0x60, 0x68, 0xE3, 0x34, 0x25, 0x85, 0xEB, + 0x01, 0x7A, 0x4E, 0xCD, 0x07, 0xFD, 0xD3, 0xB3, 0xD3, 0xF3, 0xFB, 0x16, 0x4E, 0x55, 0x0D, 0x2F, + 0x1A, 0xF0, 0x1C, 0xFC, 0x5F, 0x18, 0x93, 0x16, 0xDD, 0x7C, 0x8C, 0x74, 0x40, 0x57, 0x78, 0x94, + 0x52, 0x92, 0xD1, 0xB6, 0xEF, 0xFD, 0xA5, 0xDC, 0x37, 0xE9, 0x21, 0x26, 0xED, 0x75, 0xCF, 0x6F, + 0xF4, 0x36, 0x96, 0xAE, 0x2C, 0xF1, 0x41, 0x6D, 0x66, 0x98, 0xD3, 0x8C, 0x39, 0xCA, 0x2B, 0xA0, + 0x49, 0x5E, 0xAA, 0x85, 0x85, 0x5F, 0xB7, 0x6A, 0xEF, 0xD8, 0x35, 0xBF, 0xCB, 0xCE, 0x6C, 0x09, + 0x71, 0xA2, 0x14, 0x9E, 0x31, 0x34, 0xB5, 0xC3, 0x0A, 0xD5, 0xBD, 0x75, 0x86, 0xE6, 0x48, 0x8B, + 0xC8, 0xED, 0x6B, 0x8F, 0x2C, 0x86, 0xE0, 0xED, 0xF5, 0xF2, 0xC8, 0x35, 0x6F, 0xBE, 0x71, 0x3A, + 0x5A, 0x9A, 0xEC, 0xEA, 0x54, 0x3A, 0x17, 0x76, 0x4E, 0xA4, 0x78, 0x66, 0x6B, 0xB2, 0xBD, 0x3C, + 0x8E, 0x28, 0x3D, 0x3C, 0xDA, 0xCA, 0x78, 0xF3, 0x9E, 0x43, 0x32, 0xD6, 0xFB, 0xA3, 0xD8, 0x3E, + 0x8F, 0xE3, 0xF9, 0x2C, 0xA7, 0xE2, 0x6A, 0xA9, 0x5C, 0x76, 0x82, 0xF4, 0x5F, 0x34, 0x7D, 0x8E, + 0x80, 0x90, 0xE9, 0xA0, 0x70, 0xA8, 0x96, 0xFB, 0x7E, 0xF0, 0xC7, 0x6B, 0xDE, 0xFB, 0xDE, 0xDA, + 0x76, 0x01, 0x03, 0x68, 0x07, 0x2F, 0x45, 0xD9, 0x86, 0x5C, 0xD4, 0x4C, 0xAF, 0x8D, 0x86, 0x19, + 0x46, 0x62, 0x86, 0x29, 0x25, 0xB6, 0x57, 0x7F, 0x7D, 0x49, 0xAF, 0x79, 0x5E, 0x3C, 0x2B, 0x0A, + 0x87, 0xA6, 0x03, 0xE6, 0xD4, 0xD9, 0xBB, 0xBA, 0xB2, 0xD1, 0xAA, 0x71, 0xC9, 0x86, 0xE6, 0x64, + 0x78, 0x84, 0xF5, 0x72, 0x82, 0x80, 0xB4, 0xED, 0xC8, 0x16, 0xCD, 0x7F, 0x90, 0x16, 0x7C, 0x0A, + 0x82, 0x99, 0xD3, 0xF9, 0x28, 0x36, 0x93, 0xE0, 0x2D, 0xF5, 0x74, 0x67, 0x79, 0xC1, 0x32, 0x84, + 0x78, 0x37, 0xA7, 0x15, 0xAF, 0x8B, 0x26, 0x46, 0x4B, 0x91, 0x77, 0x57, 0x3E, 0x47, 0x5B, 0xEA, + 0x0F, 0xEA, 0x7F, 0xBA, 0x69, 0x87, 0x44, 0x39, 0xA7, 0xA9, 0x8C, 0x1C, 0x89, 0x84, 0xF6, 0xE6, + 0xE5, 0x8C, 0x87, 0x59, 0xD3, 0xF0, 0xA7, 0x98, 0xC2, 0xBC, 0x98, 0x53, 0xC0, 0x64, 0xD4, 0x3F, + 0x2A, 0xC8, 0xDF, 0x29, 0x70, 0x84, 0x86, 0x62, 0x58, 0x0C, 0xE7, 0x73, 0x04, 0x89, 0xF2, 0x20, + 0x15, 0xFB, 0x2E, 0xFC, 0xC1, 0x59, 0x18, 0xB8, 0x52, 0x46, 0x78, 0x09, 0xF9, 0xC3, 0x28, 0xC5, + 0xA5, 0x04, 0xB4, 0x42, 0xC0, 0x75, 0x44, 0x18, 0x3D, 0xCF, 0x8D, 0x36, 0x4C, 0xA2, 0x73, 0x18, + 0x7A, 0xAD, 0xBA, 0xDC, 0xB3, 0x2E, 0x30, 0xE6, 0x73, 0x11, 0x20, 0xFC, 0xE9, 0x1B, 0xB0, 0xF2, + 0x2D, 0xED, 0xA0, 0x17, 0x55, 0x63, 0xB2, 0x46, 0xCB, 0xAC, 0xB4, 0x3B, 0x1F, 0xCA, 0x9A, 0xF5, + 0x50, 0xBF, 0xB7, 0xD2, 0x0A, 0xFA, 0xE7, 0x72, 0x6E, 0x14, 0xEA, 0xA3, 0x05, 0x78, 0xF7, 0x75, + 0xD7, 0x06, 0xF8, 0x2D, 0xE6, 0x4C, 0x71, 0x27, 0xD2, 0x84, 0xF9, 0xA0, 0x5C, 0xDA, 0x1F, 0x69, + 0x1E, 0xEC, 0xF6, 0x7C, 0xB2, 0xC8, 0xEF, 0x7C, 0xF7, 0x37, 0xDB, 0xD3, 0x03, 0x6F, 0xFB, 0xCF, + 0xE0, 0x87, 0xE1, 0x33, 0x60, 0xC4, 0xF5, 0x17, 0xC6, 0x08, 0x50, 0x88, 0x86, 0x58, 0xA2, 0x90, + 0xCB, 0xE7, 0x15, 0x47, 0x15, 0x15, 0xE4, 0x33, 0x9D, 0x4A, 0xF2, 0xA7, 0xE6, 0xA7, 0x2E, 0x73, + 0x94, 0x75, 0x37, 0xC2, 0x8F, 0xB5, 0xBC, 0xA6, 0xB5, 0x05, 0xAB, 0xC7, 0x3C, 0xCC, 0x36, 0xEA, + 0x89, 0x3C, 0xAF, 0xC8, 0xC3, 0xB1, 0x14, 0x02, 0x43, 0x90, 0xE6, 0xE5, 0x4A, 0x2D, 0x8A, 0xAC, + 0x41, 0xF5, 0xAF, 0x0D, 0x3F, 0x6C, 0x3B, 0x4B, 0xA6, 0xC3, 0x70, 0x7E, 0x8B, 0x82, 0xC1, 0x40, + 0x26, 0x0B, 0x65, 0xC3, 0x60, 0x54, 0x5E, 0xF8, 0x53, 0x96, 0x15, 0x74, 0x1A, 0x11, 0xF0, 0x66, + 0x36, 0xAE, 0x3A, 0x11, 0x01, 0xDE, 0x67, 0x18, 0x6D, 0x35, 0x6A, 0x93, 0x13, 0x99, 0x74, 0xBC, + 0x17, 0x4E, 0x68, 0x86, 0x3F, 0x10, 0x9A, 0x08, 0xEB, 0xD3, 0x8F, 0xB7, 0x19, 0xC6, 0x39, 0x49, + 0xC9, 0x8A, 0x2F, 0x42, 0xE6, 0x0F, 0x31, 0xFE, 0x69, 0x13, 0xAF, 0x51, 0x62, 0xF5, 0x79, 0xF8, + 0x0E, 0xBC, 0x46, 0xB3, 0x6E, 0x56, 0xF6, 0xE4, 0x68, 0x25, 0x1F, 0x31, 0x08, 0x55, 0xAA, 0x7F, + 0x62, 0xAE, 0xF2, 0xB3, 0x14, 0xFF, 0xCC, 0xCC, 0xCC, 0x77, 0x53, 0x8B, 0x1B, 0x6D, 0xBA, 0x8D, + 0x41, 0xB4, 0xB9, 0x3C, 0x1E, 0x83, 0xAB, 0x77, 0x31, 0xEE, 0xC4, 0x9D, 0xCE, 0x24, 0x3C, 0x43, + 0xC2, 0x05, 0x9D, 0x5E, 0xAB, 0x17, 0x03, 0xF5, 0x82, 0x28, 0xC8, 0xB3, 0x2E, 0xBC, 0x10, 0x0A, + 0x91, 0x19, 0x98, 0x20, 0xF0, 0x76, 0x4D, 0x31, 0x7C, 0xBA, 0xC4, 0x5B, 0x7C, 0x39, 0xC9, 0x0A, + 0x04, 0xEB, 0x63, 0x28, 0x39, 0xEA, 0x37, 0x96, 0xC5, 0xCE, 0xE8, 0xB5, 0xA5, 0x7A, 0x40, 0x48, + 0x64, 0xC3, 0x99, 0x3A, 0xE1, 0x98, 0x8D, 0x52, 0x49, 0x6D, 0xB6, 0x6B, 0x9C, 0x3A, 0x5B, 0x8E, + 0x3C, 0xD8, 0x4B, 0xC2, 0x6F, 0xC9, 0xA6, 0x20, 0xDA, 0xBA, 0xC4, 0xD2, 0x52, 0x38, 0x0E, 0x69, + 0x9D, 0x63, 0x59, 0xC9, 0xE4, 0x31, 0x0B, 0xA6, 0x32, 0x91, 0x85, 0xED, 0x41, 0x99, 0x32, 0x4B, + 0xAA, 0x99, 0x8A, 0x22, 0xC5, 0x29, 0x06, 0x82, 0x5C, 0x3A, 0xC1, 0x73, 0x88, 0x8A, 0x94, 0x63, + 0x0D, 0xFF, 0x75, 0x83, 0x75, 0xFC, 0x39, 0x7C, 0x19, 0x3A, 0x09, 0xAA, 0xE0, 0x9A, 0x7E, 0xA9, + 0x54, 0x4C, 0xE8, 0x20, 0x93, 0x00, 0x19, 0x3A, 0xA2, 0x3D, 0x57, 0x53, 0x9E, 0xAD, 0x45, 0x23, + 0x24, 0x41, 0xDC, 0x5F, 0x4E, 0x97, 0x7E, 0x19, 0x8E, 0xF0, 0x1C, 0x45, 0x92, 0x34, 0x8A, 0x14, + 0x9F, 0xF7, 0xB3, 0x30, 0xB1, 0xC1, 0xB8, 0x72, 0xC3, 0xDD, 0x9E, 0x01, 0xE2, 0x74, 0x37, 0x26, + 0x21, 0x5D, 0x8A, 0x0A, 0x24, 0x06, 0x7E, 0x50, 0x68, 0x31, 0x21, 0x38, 0x48, 0x81, 0x6C, 0x3B, + 0xAE, 0x63, 0x78, 0xE0, 0x31, 0x6C, 0xBB, 0x25, 0xF6, 0x58, 0x81, 0xF7, 0x48, 0x06, 0xC3, 0x6D, + 0xF8, 0xB2, 0x78, 0x2B, 0x90, 0x77, 0x31, 0x24, 0xA9, 0xF9, 0x49, 0x86, 0xC7, 0xD0, 0xC5, 0xA4, + 0xC3, 0x49, 0x23, 0x1E, 0x26, 0xC9, 0xA8, 0x38, 0x2A, 0xB7, 0x15, 0x39, 0x4A, 0xE4, 0x72, 0xE1, + 0x30, 0xD3, 0xD3, 0x4A, 0xF0, 0xC7, 0xE1, 0x56, 0x0C, 0xCA, 0xF3, 0xB5, 0x1C, 0x47, 0x67, 0x22, + 0x7E, 0x8C, 0xB5, 0x0C, 0x55, 0x20, 0x55, 0xE3, 0xBA, 0xAB, 0xEF, 0xDE, 0x89, 0x16, 0x4D, 0x93, + 0x68, 0x07, 0x03, 0x86, 0xF1, 0x04, 0x89, 0xC7, 0xF9, 0x02, 0xC6, 0xCA, 0x15, 0xF8, 0x2B, 0x8C, + 0x95, 0x37, 0xF7, 0x63, 0xA9, 0x48, 0x3C, 0x1C, 0xA0, 0x4A, 0x7F, 0x33, 0x09, 0xBA, 0x13, 0x14, + 0x9A, 0x20, 0x51, 0xBB, 0x8E, 0x3A, 0x13, 0xED, 0x17, 0x56, 0x74, 0x72, 0xEE, 0x2C, 0x8C, 0xAC, + 0x27, 0xA9, 0xAF, 0x17, 0x89, 0x79, 0x19, 0xDA, 0xE0, 0x12, 0x5E, 0x71, 0xE1, 0x72, 0x64, 0x98, + 0xA5, 0xE1, 0x15, 0x60, 0x2A, 0xD4, 0x10, 0x8C, 0xAD, 0xD3, 0xAA, 0xE3, 0x4A, 0x15, 0x84, 0x75, + 0xB6, 0x2B, 0x3D, 0x31, 0x4A, 0x99, 0x22, 0xDA, 0x6E, 0xBC, 0xDF, 0x41, 0x95, 0x4C, 0x21, 0x1E, + 0xA5, 0x4D, 0x24, 0x68, 0xE9, 0x6C, 0x84, 0x20, 0x52, 0x11, 0x41, 0x09, 0x6B, 0x34, 0x1D, 0xA6, + 0x35, 0xBF, 0xC4, 0x32, 0xD4, 0x9B, 0x31, 0xF8, 0xD5, 0x04, 0x56, 0x84, 0x04, 0x45, 0xDB, 0xA2, + 0xE4, 0x4F, 0xCF, 0x53, 0xDA, 0xB4, 0x3F, 0x49, 0x10, 0xE4, 0x0E, 0x27, 0x68, 0xFB, 0xA1, 0xE2, + 0x47, 0x96, 0xBF, 0x5A, 0x4A, 0x92, 0x28, 0xEA, 0x67, 0x93, 0x7A, 0xF4, 0xC7, 0x8D, 0x30, 0x84, + 0xE6, 0x01, 0x0A, 0x2A, 0xFC, 0xED, 0xA3, 0xFB, 0x28, 0x85, 0xD5, 0x18, 0x35, 0x75, 0x64, 0x33, + 0x25, 0xD5, 0x54, 0x23, 0xBA, 0x58, 0x39, 0x7B, 0xE3, 0x30, 0x8A, 0x83, 0xC6, 0xE1, 0x0F, 0x41, + 0x01, 0x64, 0xFA, 0x72, 0x3A, 0xAE, 0x10, 0x72, 0xF8, 0x17, 0xC5, 0xBC, 0xFE, 0x4B, 0x9A, 0xD9, + 0xB7, 0x56, 0x61, 0x70, 0xC9, 0x3B, 0x51, 0x54, 0x86, 0x54, 0xAC, 0xA0, 0x0A, 0x95, 0x1C, 0x86, + 0x39, 0x5C, 0x5F, 0x35, 0xE9, 0x05, 0x3F, 0xAB, 0xC8, 0x4B, 0xC4, 0x0B, 0x68, 0xF2, 0x43, 0x1F, + 0x8A, 0x18, 0xF1, 0xC9, 0x6A, 0x26, 0x65, 0x0B, 0xAF, 0x64, 0x59, 0xA3, 0x9C, 0xB1, 0x9C, 0x30, + 0x03, 0x25, 0x48, 0x37, 0xC2, 0x7A, 0x2B, 0x69, 0x26, 0x0B, 0x95, 0x40, 0x08, 0x7E, 0x1E, 0x8F, + 0x26, 0xFA, 0x27, 0xCF, 0xA2, 0xFA, 0xF6, 0x07, 0xF7, 0xD7, 0x6C, 0x6B, 0x96, 0x6C, 0xCC, 0x66, + 0x4B, 0x93, 0x26, 0x91, 0xA1, 0x94, 0xA5, 0x91, 0x0C, 0x36, 0xEC, 0x05, 0xD2, 0x1F, 0x4F, 0x0D, + 0x22, 0x36, 0xC4, 0xBB, 0xE0, 0x73, 0x60, 0x0B, 0xA8, 0xF4, 0x8D, 0x4D, 0x33, 0xBD, 0xD4, 0xDC, + 0x68, 0x32, 0x3E, 0x91, 0xDB, 0x9A, 0xFD, 0x55, 0x30, 0x40, 0x11, 0xAE, 0xD2, 0x1A, 0x38, 0xC2, + 0x2E, 0xF3, 0xB1, 0x6F, 0x4D, 0x0D, 0xCB, 0xDA, 0x14, 0x88, 0x61, 0x88, 0x5B, 0xE3, 0x49, 0x7B, + 0xCB, 0x81, 0x01, 0x0A, 0xB9, 0x21, 0x46, 0xE3, 0x5A, 0x76, 0x9E, 0xD4, 0x70, 0xC7, 0xE1, 0x78, + 0xA0, 0x11, 0xE3, 0xE6, 0xB6, 0x67, 0x0B, 0xD2, 0xC4, 0x1B, 0xF2, 0xCB, 0xC9, 0x43, 0x82, 0x5F, + 0x26, 0x0B, 0x82, 0x22, 0x84, 0x32, 0x7E, 0x7F, 0x5E, 0x4E, 0x71, 0xBA, 0xA2, 0x89, 0x58, 0x3D, + 0x0B, 0xB1, 0x46, 0xB5, 0x64, 0xF2, 0x1C, 0xF7, 0x88, 0xC4, 0xF9, 0x67, 0xC6, 0x09, 0xD5, 0x66, + 0x03, 0xD5, 0x34, 0x1D, 0x75, 0x92, 0xD3, 0x5A, 0x22, 0xA9, 0x45, 0xCC, 0x30, 0xB7, 0x57, 0xAE, + 0x75, 0x8C, 0x48, 0xA1, 0xC4, 0xC1, 0x07, 0xBA, 0x0F, 0x34, 0xDE, 0xA0, 0xC2, 0x08, 0x7B, 0xD8, + 0x1F, 0xB1, 0xCB, 0x8D, 0x86, 0xD2, 0xD3, 0x13, 0xB1, 0x74, 0x58, 0xD4, 0x50, 0xFE, 0xBA, 0xFB, + 0x0F, 0x56, 0x48, 0xDF, 0x3E, 0xF6, 0xD4, 0x6B, 0xE9, 0x28, 0x86, 0x27, 0x4B, 0x13, 0x6C, 0xEE, + 0x64, 0xA4, 0xBB, 0xA9, 0x52, 0x8A, 0x94, 0xE3, 0x72, 0x2D, 0x48, 0xB6, 0x4A, 0xB4, 0xA0, 0xEB, + 0x16, 0x6D, 0x78, 0x79, 0x45, 0xCF, 0xA1, 0x04, 0xFC, 0x25, 0x98, 0x03, 0x3B, 0xFB, 0x49, 0x3C, + 0xBF, 0x31, 0xBF, 0xA9, 0x81, 0x52, 0x3E, 0x9D, 0xA2, 0x1B, 0x63, 0x75, 0xF1, 0x67, 0xF3, 0x73, + 0x7F, 0x34, 0x3F, 0x73, 0xD7, 0x7C, 0x1D, 0x8D, 0x35, 0xFE, 0xD5, 0x2A, 0xC1, 0xCC, 0x8B, 0x43, + 0xB8, 0x2F, 0x32, 0xEF, 0x06, 0x21, 0xFE, 0xCC, 0x30, 0xC9, 0x96, 0x66, 0x68, 0x37, 0x10, 0x43, + 0x58, 0x66, 0x14, 0x6B, 0x47, 0x57, 0x4B, 0x78, 0x81, 0xAB, 0xAC, 0x5B, 0xFD, 0x3C, 0x74, 0xA1, + 0x79, 0x6E, 0x90, 0x6C, 0xDB, 0x2B, 0x13, 0x54, 0x88, 0x41, 0x04, 0x07, 0x25, 0xFC, 0xA1, 0xB4, + 0x8F, 0xD6, 0x35, 0xDD, 0x6C, 0x18, 0x05, 0xDE, 0xF6, 0xCB, 0x2D, 0xF3, 0x78, 0x3A, 0x53, 0xD4, + 0x7D, 0x99, 0xB8, 0xBC, 0xA9, 0x56, 0x8F, 0x65, 0x82, 0xF2, 0xEB, 0x04, 0x4E, 0x0F, 0x1E, 0x93, + 0x5A, 0x4D, 0xF1, 0x06, 0x8D, 0xD3, 0x5B, 0x6A, 0x72, 0xD3, 0xD8, 0xD6, 0x48, 0x30, 0xC4, 0x08, + 0xCA, 0x0E, 0x49, 0x0F, 0x1A, 0x14, 0x42, 0x62, 0x68, 0xD1, 0xDF, 0xA5, 0x55, 0xCB, 0x62, 0xB1, + 0x5C, 0xDD, 0xCD, 0xB1, 0x61, 0x55, 0xD1, 0x8C, 0x88, 0x8F, 0x1F, 0x9F, 0x5F, 0x0C, 0xD8, 0x3B, + 0xE8, 0xEC, 0x9B, 0x98, 0x82, 0x6D, 0x87, 0xC9, 0x25, 0x86, 0x64, 0xC2, 0xB6, 0x24, 0x85, 0x27, + 0x2A, 0x27, 0x2A, 0x3E, 0x92, 0x1A, 0xC8, 0xAA, 0x30, 0x0A, 0xE3, 0x79, 0x19, 0x71, 0xFD, 0x03, + 0xB5, 0x00, 0xAC, 0xF9, 0x9D, 0xDC, 0xAF, 0xEB, 0xE2, 0xBF, 0xD5, 0xC1, 0x08, 0x85, 0x46, 0x10, + 0x1A, 0x89, 0xFF, 0x2B, 0xFC, 0xCD, 0x15, 0x8A, 0xF3, 0x82, 0x7A, 0xE1, 0x92, 0xC2, 0x5C, 0xD7, + 0x35, 0x9E, 0xCE, 0x74, 0x53, 0x64, 0x31, 0xB1, 0x20, 0x8F, 0x71, 0x89, 0x61, 0x81, 0x30, 0x31, + 0x08, 0x53, 0x22, 0xB7, 0xBC, 0xD0, 0xDD, 0x0B, 0x08, 0x85, 0x5F, 0x83, 0xB8, 0xC4, 0x5E, 0x5E, + 0x74, 0x02, 0x46, 0xCC, 0x92, 0x39, 0x41, 0xA6, 0x14, 0x41, 0x35, 0xB1, 0xB8, 0x35, 0x4D, 0xB3, + 0xE1, 0x04, 0x78, 0xD9, 0x20, 0x4A, 0xBC, 0x68, 0x8B, 0x69, 0x27, 0x37, 0x16, 0x0D, 0x24, 0xD1, + 0xC7, 0x6B, 0xF7, 0xCC, 0xFE, 0x42, 0xAA, 0xDE, 0x24, 0xCA, 0x8E, 0x55, 0xE9, 0xE6, 0x6A, 0x8B, + 0xDA, 0x78, 0x22, 0xA0, 0x5A, 0xAA, 0x24, 0x27, 0x64, 0x41, 0xE6, 0xBF, 0x9F, 0xCE, 0x44, 0x7C, + 0x8D, 0xEB, 0xBA, 0x2D, 0x78, 0x71, 0xD7, 0xC0, 0x8B, 0xF5, 0x1F, 0xF0, 0xD3, 0x88, 0x00, 0x0D, + 0x3C, 0xA6, 0x70, 0xD1, 0x52, 0x44, 0x10, 0x57, 0x12, 0x11, 0x05, 0xFC, 0x62, 0xB4, 0xE2, 0x1F, + 0xAD, 0x3D, 0x3E, 0xAA, 0xA9, 0xFF, 0xEE, 0x8F, 0x04, 0x2E, 0x90, 0xEE, 0xBE, 0x3C, 0x98, 0xFC, + 0x3D, 0x83, 0x70, 0x43, 0x06, 0xC7, 0x86, 0xB4, 0x60, 0x6B, 0xB8, 0xBA, 0x05, 0xC8, 0x78, 0x5A, + 0xA6, 0xE7, 0xAE, 0x2D, 0x1A, 0x56, 0xC8, 0x34, 0xB0, 0x80, 0x55, 0x48, 0x19, 0x0D, 0x0A, 0x55, + 0xDD, 0x8A, 0xC2, 0x4F, 0x87, 0xA7, 0xB3, 0xA9, 0xE0, 0x88, 0x1D, 0x8B, 0x8B, 0xE3, 0xC5, 0x0F, + 0xFE, 0xA1, 0xA1, 0xDA, 0x9A, 0x14, 0x8C, 0xF4, 0x90, 0x60, 0x25, 0xF6, 0xCB, 0xBB, 0x29, 0x81, + 0x21, 0x0F, 0x85, 0x63, 0xFE, 0x60, 0x4C, 0xCD, 0x53, 0x66, 0xB1, 0xF6, 0x9A, 0xC4, 0x7C, 0x86, + 0x80, 0x14, 0x61, 0xC5, 0xA3, 0xCD, 0x6F, 0x30, 0x90, 0x10, 0x34, 0x49, 0x95, 0x82, 0xBE, 0x0A, + 0xE7, 0x13, 0x48, 0xC8, 0x98, 0x0A, 0x47, 0x9D, 0x4A, 0xE6, 0xE2, 0x45, 0xC5, 0x10, 0x08, 0x2C, + 0xBA, 0xF1, 0xB8, 0xE8, 0xD5, 0x57, 0xC1, 0x26, 0x7A, 0x1A, 0xDB, 0x8A, 0xCB, 0x7D, 0xAC, 0x55, + 0x34, 0x10, 0xC0, 0x7A, 0x69, 0x99, 0x5B, 0x35, 0xF4, 0x11, 0x35, 0x11, 0x1F, 0x01, 0x91, 0xB0, + 0x43, 0xD8, 0x48, 0x12, 0x29, 0x82, 0x0C, 0x20, 0x8E, 0xD5, 0x54, 0x3C, 0xC0, 0x8B, 0x90, 0xBD, + 0x7C, 0x37, 0xA8, 0x81, 0x7B, 0x6B, 0x58, 0xFE, 0xD4, 0xF3, 0x86, 0xBC, 0xC6, 0xF8, 0x49, 0x16, + 0x2F, 0x61, 0x32, 0x91, 0x99, 0x84, 0xA3, 0x99, 0x64, 0xB3, 0xDE, 0xC2, 0xAF, 0xAD, 0x0E, 0xB4, + 0xB0, 0x2E, 0x71, 0x73, 0x23, 0x19, 0x37, 0x49, 0xCE, 0xB4, 0x3B, 0x10, 0x36, 0xAF, 0xCB, 0x6F, + 0x9B, 0x88, 0xC5, 0x26, 0xB6, 0x16, 0xAE, 0x6B, 0x46, 0xEC, 0x6E, 0xAA, 0x51, 0x0E, 0xF9, 0x9A, + 0x67, 0x96, 0xA6, 0xDE, 0x5C, 0x1C, 0xDD, 0xDE, 0x28, 0xBD, 0x79, 0x6A, 0x69, 0xA9, 0x9C, 0x78, + 0xFD, 0x44, 0x8B, 0xD7, 0x27, 0xCB, 0xAF, 0x2F, 0x25, 0xBD, 0x68, 0xC3, 0xEA, 0xB3, 0xE0, 0x9D, + 0xE8, 0x3B, 0x80, 0x00, 0xD1, 0xBE, 0x80, 0xAD, 0x63, 0x02, 0x10, 0xE8, 0x76, 0x88, 0x99, 0x71, + 0x7D, 0x8F, 0x2A, 0x30, 0x0C, 0x01, 0x38, 0x49, 0xAD, 0xF1, 0xCE, 0x43, 0x87, 0x74, 0xF4, 0x0C, + 0xB8, 0x72, 0xC4, 0x01, 0x3F, 0x1E, 0x53, 0x02, 0x80, 0xE5, 0xC4, 0xAA, 0xDF, 0x37, 0x12, 0xE0, + 0xB9, 0x11, 0xC6, 0xD5, 0xFF, 0x12, 0xF2, 0x34, 0xAA, 0x86, 0x12, 0x20, 0x18, 0x60, 0x58, 0xE6, + 0xFF, 0xE9, 0x88, 0xE1, 0x60, 0x78, 0x45, 0xD8, 0x6C, 0x0C, 0x86, 0xDC, 0xAE, 0x40, 0x77, 0x06, + 0xBC, 0x06, 0xDB, 0x1D, 0x72, 0x03, 0x36, 0xAF, 0x18, 0xAC, 0x37, 0x01, 0x90, 0x7A, 0xF1, 0x60, + 0x97, 0xBC, 0x59, 0xC0, 0x3D, 0x9F, 0x07, 0xEF, 0x45, 0x06, 0xDC, 0x0B, 0x1C, 0xD0, 0xEC, 0xAB, + 0xA2, 0x49, 0x00, 0x93, 0x60, 0x2D, 0x65, 0xD5, 0xB4, 0x9C, 0xD5, 0x95, 0xB3, 0xE0, 0xCC, 0x39, + 0x20, 0x40, 0x30, 0x2C, 0x66, 0x25, 0xA0, 0x17, 0xF4, 0x19, 0x46, 0x7C, 0x71, 0xAF, 0x7C, 0xA2, + 0xA7, 0xDC, 0x5D, 0x60, 0xE3, 0x55, 0xB5, 0x0F, 0x92, 0x60, 0x3C, 0xBF, 0x99, 0x61, 0x4E, 0x54, + 0xC3, 0xD5, 0xAB, 0xC3, 0x5A, 0x20, 0x67, 0xA7, 0x36, 0x9C, 0x43, 0x98, 0xAD, 0x2A, 0x45, 0x3E, + 0x93, 0xDC, 0x33, 0x7C, 0x05, 0xAB, 0xAB, 0x83, 0x5A, 0x22, 0xE2, 0x34, 0xC8, 0x00, 0x77, 0xF7, + 0x41, 0x06, 0x3C, 0x01, 0xBE, 0x09, 0xBE, 0xB8, 0xDE, 0xFE, 0xF0, 0x7A, 0xFB, 0xF7, 0xC0, 0x3F, + 0x81, 0x27, 0x3D, 0x0B, 0x67, 0x93, 0x57, 0x89, 0x32, 0x0D, 0xEE, 0xEF, 0x8F, 0x4C, 0x8C, 0x97, + 0xA3, 0x7E, 0xD0, 0x92, 0x69, 0x91, 0xE6, 0x7C, 0x0A, 0x27, 0xFB, 0x74, 0x8A, 0xA4, 0x95, 0x57, + 0xCC, 0x4C, 0x97, 0x67, 0x7A, 0xF7, 0xCF, 0x34, 0xEE, 0xCD, 0x8B, 0xA2, 0x8C, 0x38, 0x1F, 0xE2, + 0x2C, 0xC4, 0xE5, 0x1F, 0x58, 0xCB, 0xE6, 0x3A, 0x07, 0x44, 0xC8, 0xF4, 0x86, 0x32, 0x02, 0x8B, + 0xCE, 0x73, 0x40, 0x87, 0xC4, 0x05, 0xD5, 0xDD, 0xE4, 0x82, 0xBC, 0xB0, 0x96, 0x0B, 0x33, 0xA8, + 0xCC, 0xBA, 0x54, 0xBB, 0xB0, 0xD1, 0x62, 0x9A, 0x89, 0x0E, 0x21, 0x40, 0x92, 0xF1, 0xB2, 0x72, + 0x93, 0x89, 0xEC, 0x20, 0xDD, 0xDE, 0x75, 0x21, 0xB7, 0x2B, 0xE4, 0x4B, 0xD7, 0xBA, 0xD0, 0x8C, + 0xB3, 0xB1, 0xD4, 0x25, 0xA8, 0x86, 0x73, 0xF5, 0x6C, 0xB3, 0xE4, 0x57, 0x63, 0xA6, 0xA4, 0x67, + 0xEC, 0xC8, 0xB6, 0x47, 0x7E, 0x67, 0xD9, 0x0B, 0x8B, 0xA4, 0xF6, 0x7A, 0xDD, 0x4B, 0x09, 0x9B, + 0x15, 0x85, 0xAC, 0x29, 0x49, 0x3A, 0x66, 0xC6, 0x5D, 0xCC, 0xFE, 0x23, 0xBF, 0xAB, 0x06, 0x66, + 0x71, 0x93, 0x9A, 0x7B, 0xD7, 0xA2, 0xE0, 0xCE, 0xB2, 0x57, 0x13, 0x42, 0xDC, 0x8F, 0x67, 0x33, + 0xE7, 0xCD, 0xE6, 0x6B, 0xC1, 0xDB, 0xBC, 0x59, 0xF6, 0xF2, 0x20, 0x89, 0x7B, 0x70, 0xFB, 0x88, + 0xD7, 0xFE, 0x6D, 0x70, 0xC1, 0x6D, 0x1F, 0x64, 0xFC, 0x79, 0xAB, 0x52, 0xDF, 0xB8, 0x2A, 0x83, + 0x4C, 0x16, 0xAF, 0x7D, 0x6C, 0xD8, 0xFE, 0x2B, 0xAF, 0xDD, 0x8B, 0x67, 0xA1, 0x4F, 0xE2, 0xF6, + 0x39, 0x6F, 0xF7, 0xC2, 0xD7, 0xDE, 0x01, 0x5E, 0xD4, 0xCA, 0x60, 0x64, 0xFD, 0x66, 0x70, 0xA9, + 0xFD, 0xC9, 0xF5, 0xF6, 0x6F, 0x81, 0xD7, 0x6C, 0x68, 0xFF, 0xC0, 0x7A, 0xFB, 0x13, 0x97, 0x7D, + 0xFF, 0xA3, 0xEB, 0xED, 0xDF, 0x06, 0xAF, 0xDA, 0xD0, 0xFE, 0xCF, 0xEB, 0xED, 0xDF, 0x73, 0xDB, + 0xBD, 0xC8, 0xCC, 0x26, 0x2F, 0x32, 0x33, 0x03, 0xCE, 0xF4, 0xCB, 0xF9, 0x08, 0x18, 0x15, 0x49, + 0x9E, 0x64, 0x6C, 0x87, 0xB1, 0x25, 0x46, 0x74, 0xA4, 0x2F, 0xD9, 0xEA, 0xCC, 0x9F, 0xCF, 0xF6, + 0xCD, 0xD9, 0xDA, 0xF9, 0x14, 0xCF, 0xD7, 0xC6, 0x6D, 0xC4, 0x18, 0x88, 0x49, 0x7D, 0x73, 0x0D, + 0x00, 0x9E, 0x03, 0xFC, 0x3A, 0x7D, 0xB8, 0xE9, 0x9C, 0xE7, 0x80, 0x3A, 0xA0, 0x0F, 0xF2, 0x12, + 0x7D, 0x9C, 0xEF, 0x5D, 0x51, 0xDB, 0xB2, 0x9E, 0x3F, 0x34, 0x3B, 0x70, 0x0D, 0x28, 0xF0, 0x25, + 0x48, 0x23, 0xE1, 0xD1, 0xC6, 0xA5, 0xB8, 0xCF, 0xE8, 0x8B, 0x02, 0x3F, 0xBD, 0x86, 0x7C, 0x39, + 0x59, 0x04, 0xD3, 0xB3, 0xD5, 0x17, 0x47, 0x82, 0x94, 0xEA, 0x15, 0x91, 0xA0, 0x1A, 0x9F, 0xDD, + 0x48, 0x16, 0x9B, 0x47, 0x66, 0x5F, 0x2A, 0x32, 0x24, 0x47, 0xC7, 0x36, 0x84, 0x86, 0xF0, 0x0C, + 0x7A, 0xB1, 0x14, 0x6F, 0x85, 0x96, 0x06, 0xEB, 0x76, 0x2B, 0x78, 0x51, 0xEB, 0xA5, 0x75, 0x73, + 0xDB, 0x9F, 0xF2, 0xD6, 0x6D, 0xE9, 0xB2, 0x75, 0x1B, 0x7C, 0xFF, 0x03, 0xEB, 0x57, 0x79, 0xC2, + 0x5D, 0x7D, 0xD7, 0x67, 0x0B, 0x25, 0xEF, 0x2A, 0xDF, 0x1C, 0x5C, 0xFB, 0x5F, 0x87, 0xAD, 0xE0, + 0x97, 0x1B, 0x5A, 0x67, 0x23, 0x6B, 0xDF, 0xCD, 0x7B, 0x57, 0x1E, 0xB4, 0x7E, 0x8B, 0x72, 0x5B, + 0xFF, 0xFF, 0xB8, 0xB5, 0xEA, 0x5D, 0x77, 0xD0, 0xFA, 0xC4, 0x7F, 0xB8, 0xAD, 0x9E, 0xB7, 0xC6, + 0xA3, 0x86, 0x5D, 0x43, 0x6A, 0x78, 0x9B, 0xD7, 0x0B, 0xCF, 0xF7, 0xE1, 0x5D, 0x79, 0xF7, 0xE0, + 0x7E, 0xFB, 0x5E, 0xDC, 0x7A, 0x69, 0x2C, 0x83, 0xF6, 0x27, 0xD7, 0xDB, 0xBF, 0xE5, 0xEE, 0xF9, + 0xB9, 0xDE, 0xFE, 0x81, 0xF5, 0xAB, 0x3C, 0x71, 0xF6, 0x52, 0xEB, 0x47, 0xD7, 0x5B, 0xBF, 0x7D, + 0xEB, 0xA0, 0xD7, 0xD8, 0xB6, 0xF0, 0xAE, 0x7D, 0x60, 0xC8, 0x55, 0x6F, 0x00, 0x2F, 0xD5, 0x3E, + 0x8B, 0x49, 0xEA, 0x52, 0xFB, 0x93, 0xEB, 0xED, 0xDF, 0xC2, 0x12, 0xED, 0x52, 0xFB, 0x07, 0xD6, + 0xDB, 0x9F, 0x00, 0xEF, 0xF2, 0xF6, 0x0C, 0x0D, 0xAE, 0x3E, 0x06, 0x3F, 0x89, 0x76, 0x82, 0x1A, + 0xE8, 0x80, 0x07, 0xFB, 0xA5, 0xB0, 0xA5, 0x50, 0xA0, 0x5E, 0xCE, 0x18, 0x76, 0xC6, 0xB6, 0xBA, + 0xDD, 0x92, 0xD5, 0x0D, 0x7C, 0xA3, 0x55, 0x37, 0x0D, 0x8E, 0x25, 0x19, 0x54, 0xB0, 0x8D, 0x3A, + 0x22, 0x47, 0x50, 0x21, 0x4B, 0xAE, 0xAC, 0xB9, 0x19, 0xCF, 0x01, 0x06, 0xDA, 0x3D, 0x2C, 0xC7, + 0x2D, 0x68, 0x79, 0x16, 0xCD, 0x20, 0x76, 0xD4, 0x1D, 0x5A, 0x6E, 0xE7, 0x40, 0x12, 0x6A, 0x2E, + 0x31, 0x9F, 0x03, 0x35, 0xA8, 0xBB, 0x2F, 0x1D, 0x68, 0xAC, 0x6F, 0xC7, 0xB5, 0x01, 0x62, 0x74, + 0xD7, 0x4A, 0xF9, 0x1C, 0x05, 0x6B, 0x9D, 0x4C, 0x76, 0x98, 0x10, 0x98, 0x6D, 0x33, 0xC3, 0x18, + 0x1A, 0x36, 0xE9, 0x18, 0x77, 0x77, 0x09, 0x6C, 0xBB, 0x63, 0xDD, 0x5B, 0xC7, 0xAC, 0x03, 0x33, + 0x83, 0xF0, 0xB4, 0x03, 0xDF, 0x1D, 0xAF, 0x96, 0x03, 0x74, 0x4E, 0x99, 0x6A, 0xB2, 0xDA, 0xE8, + 0x8E, 0x9D, 0x49, 0xD4, 0x84, 0xA4, 0xA2, 0xCA, 0xA5, 0x4D, 0xC9, 0x04, 0xA9, 0x5B, 0xBC, 0xDF, + 0x44, 0x30, 0x55, 0x12, 0x59, 0xD9, 0xFE, 0x18, 0x69, 0x25, 0x02, 0xB4, 0x94, 0x0D, 0x5C, 0x15, + 0x48, 0x84, 0xF8, 0xF9, 0x38, 0x97, 0xDE, 0x24, 0xD6, 0x69, 0x73, 0xF3, 0xEC, 0xD4, 0xCB, 0x5A, + 0xCE, 0xCE, 0xC4, 0x09, 0x48, 0xA0, 0x91, 0x70, 0x30, 0xE0, 0x43, 0x92, 0xE0, 0x4F, 0xA9, 0xFD, + 0xE6, 0x8D, 0x0D, 0x0B, 0x91, 0x1F, 0x79, 0x8C, 0xD0, 0x8B, 0xB6, 0x14, 0xAF, 0x2D, 0x4A, 0x83, + 0x48, 0xE7, 0xBF, 0xA1, 0x9B, 0xD1, 0x57, 0xF0, 0x8C, 0x9F, 0xEE, 0x8F, 0x4D, 0x34, 0xE2, 0xAA, + 0x22, 0x0B, 0x40, 0xE0, 0x19, 0xBE, 0xEA, 0xEB, 0x4D, 0x4E, 0x29, 0x19, 0x0D, 0xBC, 0x6E, 0x6E, + 0x72, 0x66, 0x2B, 0x31, 0x3E, 0xA6, 0x12, 0xCA, 0xA3, 0x0D, 0xCB, 0x34, 0x74, 0x8D, 0xAE, 0x1D, + 0x99, 0xAC, 0x55, 0x91, 0x63, 0xFB, 0x42, 0x6F, 0x22, 0x1E, 0x5E, 0xF3, 0x5A, 0xF7, 0xD6, 0x63, + 0x26, 0xBD, 0x61, 0xAC, 0xCD, 0x8B, 0x53, 0xBB, 0x09, 0xA3, 0xF0, 0x25, 0xF2, 0xE0, 0xE7, 0x54, + 0xCF, 0x3F, 0x8A, 0xF1, 0xA4, 0xBB, 0x6F, 0xDC, 0x14, 0x9E, 0xA6, 0x64, 0xDB, 0xE9, 0xA0, 0x76, + 0xB3, 0x3D, 0xBA, 0x71, 0x8B, 0x94, 0x81, 0xFB, 0x14, 0x63, 0x94, 0x7A, 0xAB, 0xC1, 0x78, 0xB8, + 0x9B, 0x71, 0x1D, 0x6D, 0x58, 0x3E, 0xF4, 0x20, 0xBA, 0xB9, 0x58, 0xCD, 0xB5, 0xB7, 0x24, 0x59, + 0x73, 0x61, 0x24, 0x25, 0x71, 0xEF, 0x3E, 0x25, 0x49, 0x9A, 0x82, 0xE0, 0xD5, 0x6F, 0x6A, 0xAB, + 0xD3, 0x75, 0xC9, 0x97, 0x09, 0xA5, 0x68, 0x4E, 0x8D, 0xC4, 0x4A, 0x31, 0x39, 0xFF, 0xFE, 0xE2, + 0xCB, 0x2C, 0x3B, 0xE3, 0x0B, 0x61, 0xF3, 0x28, 0xA0, 0x8E, 0x5E, 0x5D, 0xD8, 0x7C, 0xFF, 0x78, + 0x31, 0x41, 0xBA, 0x99, 0xA5, 0x68, 0xF4, 0xD8, 0xCD, 0x95, 0x53, 0x30, 0x20, 0x56, 0x42, 0x27, + 0xF6, 0x32, 0x71, 0x47, 0xD4, 0x8C, 0x80, 0xA6, 0x69, 0x56, 0x38, 0x39, 0x39, 0xD9, 0xE8, 0xA0, + 0x97, 0xE1, 0x2F, 0xD5, 0xAA, 0x9D, 0x18, 0x42, 0x90, 0x74, 0x3D, 0xFB, 0x4F, 0xAF, 0xE6, 0x90, + 0x88, 0xFE, 0x1D, 0x4B, 0xF3, 0x05, 0x3C, 0x63, 0xB9, 0x5A, 0x50, 0x07, 0x91, 0x39, 0x2B, 0x03, + 0xAD, 0xCC, 0x14, 0xDB, 0x88, 0xB0, 0x8D, 0xC5, 0x56, 0xFC, 0x4E, 0x5F, 0x6B, 0x1A, 0x95, 0x59, + 0xD4, 0xC8, 0x20, 0x6B, 0x1C, 0x29, 0xBE, 0x1F, 0xAF, 0x87, 0x29, 0xCE, 0x81, 0x16, 0x0C, 0xAE, + 0x15, 0x38, 0x57, 0x3D, 0x45, 0x4A, 0x42, 0xDF, 0x80, 0xA0, 0x20, 0xF4, 0xBB, 0x2F, 0x73, 0x30, + 0xB0, 0xA1, 0xA8, 0xFF, 0xB2, 0xF4, 0xD2, 0xC5, 0xA0, 0x9B, 0x27, 0x86, 0x05, 0x20, 0x3D, 0xF4, + 0x36, 0x7A, 0xFE, 0x13, 0xC6, 0x7B, 0x76, 0x8B, 0x43, 0xD6, 0xEA, 0xFF, 0xD6, 0x13, 0x90, 0x9B, + 0x1E, 0xEA, 0x19, 0x94, 0x3C, 0x13, 0x5E, 0xC5, 0x88, 0x4B, 0x62, 0xA4, 0x33, 0x05, 0x91, 0xF8, + 0x40, 0x6B, 0x2C, 0x19, 0x8D, 0x58, 0xD3, 0x73, 0x37, 0x34, 0xC7, 0x5B, 0x71, 0x8A, 0x3E, 0x77, + 0xCB, 0xF6, 0x9B, 0x24, 0xED, 0x0C, 0x52, 0xAE, 0x4B, 0xD6, 0xE2, 0xBA, 0x91, 0x6B, 0x3F, 0x3A, + 0xDF, 0x9E, 0x29, 0xC9, 0xD2, 0x67, 0x6F, 0x9D, 0xEA, 0x6E, 0x4B, 0xD5, 0x1F, 0x9A, 0xC5, 0x98, + 0x89, 0x4F, 0x48, 0x06, 0xFA, 0xC8, 0xCE, 0x66, 0x50, 0x55, 0x8C, 0x78, 0xB9, 0x9E, 0x6E, 0x87, + 0x16, 0x9B, 0x8D, 0x43, 0x21, 0x35, 0x1B, 0x38, 0xF8, 0x78, 0x79, 0xCC, 0x3C, 0x88, 0xCA, 0x5B, + 0xFC, 0x92, 0x9E, 0x8E, 0xB7, 0xF4, 0x8A, 0x6F, 0x4F, 0xAD, 0x73, 0x34, 0xAA, 0x55, 0xFD, 0x57, + 0xDF, 0x99, 0xBE, 0x48, 0x86, 0xED, 0xC0, 0xFC, 0x84, 0x92, 0xF3, 0x37, 0xEE, 0x0F, 0xE9, 0x59, + 0x97, 0xEA, 0x16, 0xC0, 0xC7, 0xE1, 0x87, 0x51, 0x10, 0x08, 0x20, 0xD4, 0x47, 0x34, 0xF0, 0xE0, + 0x52, 0xA4, 0xE7, 0x96, 0x3E, 0x87, 0xD7, 0x76, 0x6D, 0x12, 0xE9, 0xF5, 0xE2, 0x6E, 0x6F, 0x00, + 0xF0, 0xC3, 0x37, 0x6D, 0xD9, 0x7C, 0xE3, 0x8D, 0x9B, 0xB7, 0xDC, 0x04, 0x8F, 0x6F, 0xBE, 0xE9, + 0xC6, 0x2D, 0x5B, 0x6E, 0x3C, 0xB1, 0x96, 0x9B, 0xFE, 0x76, 0x42, 0x03, 0xC7, 0xC0, 0x6D, 0xFD, + 0xD6, 0x35, 0x07, 0xA6, 0x7D, 0xBA, 0x84, 0xE6, 0xA7, 0xF2, 0xF6, 0x27, 0x6E, 0xD0, 0x7F, 0xC6, + 0x4E, 0x77, 0xEF, 0x5A, 0xDA, 0xF4, 0xCB, 0x4C, 0x2D, 0x5E, 0x6F, 0xA2, 0x89, 0x4A, 0x15, 0x6D, + 0xDE, 0xD4, 0x25, 0x3A, 0xF5, 0x11, 0x34, 0x51, 0x43, 0xE3, 0x63, 0x13, 0xBB, 0x2B, 0x63, 0xEC, + 0x22, 0x9C, 0xBE, 0x3C, 0xE4, 0x37, 0x0C, 0x15, 0x0F, 0x49, 0x77, 0x58, 0xAB, 0x79, 0x59, 0xB6, + 0xBE, 0xDB, 0xB9, 0x1B, 0xA6, 0xD7, 0x2A, 0xF2, 0x7E, 0x87, 0x9F, 0x6A, 0x2D, 0x3A, 0x2E, 0xBB, + 0x4E, 0xED, 0xDF, 0x19, 0x46, 0x1E, 0xEC, 0x61, 0x34, 0xF4, 0x7B, 0xD9, 0xE8, 0x96, 0xDA, 0xEF, + 0xF0, 0x5F, 0xCD, 0x6D, 0xC9, 0x2A, 0xD7, 0x84, 0xB2, 0x96, 0x44, 0x42, 0xE2, 0xF7, 0x87, 0x97, + 0x53, 0x9B, 0x4F, 0x05, 0xD7, 0x3C, 0x62, 0x50, 0x09, 0xFF, 0x9F, 0x7C, 0x5B, 0xF1, 0x5D, 0xC5, + 0xC8, 0xE8, 0xE2, 0x49, 0x63, 0x6C, 0xAA, 0x1A, 0x3B, 0xFD, 0x7B, 0x63, 0xCF, 0xE6, 0xE9, 0x69, + 0xF9, 0xF5, 0xCC, 0x25, 0xB7, 0x99, 0xBB, 0x1B, 0xF3, 0x5A, 0xC5, 0xBF, 0x80, 0x31, 0x71, 0x1A, + 0x54, 0x30, 0x7E, 0x68, 0xFA, 0x03, 0xC8, 0x97, 0x4E, 0xFB, 0xC2, 0x21, 0x3F, 0xE1, 0xB3, 0xD2, + 0x79, 0x6B, 0x99, 0x50, 0x96, 0xB9, 0x60, 0x20, 0x52, 0x2A, 0xE4, 0x23, 0x51, 0x11, 0x01, 0x1D, + 0xD1, 0xC5, 0x42, 0x88, 0x08, 0xA2, 0x48, 0x38, 0x83, 0x12, 0xDC, 0xED, 0xC4, 0xE9, 0xF5, 0x3D, + 0x37, 0x3C, 0xDE, 0x70, 0x85, 0xC7, 0x70, 0xA7, 0xCA, 0x88, 0xB7, 0x3D, 0x4F, 0xF7, 0x1C, 0x28, + 0xC2, 0x99, 0xB5, 0xA5, 0x70, 0xD7, 0x65, 0xB8, 0xCF, 0xEA, 0x20, 0x4F, 0xA9, 0x7A, 0x05, 0xA5, + 0x30, 0x1B, 0xAA, 0xFB, 0x99, 0x64, 0x36, 0x69, 0x61, 0xE3, 0x63, 0x00, 0x2D, 0xDA, 0x2E, 0xFE, + 0xB7, 0xBC, 0xA2, 0xFF, 0xEF, 0xFC, 0xE1, 0x5B, 0xBF, 0xFB, 0xDD, 0xB7, 0xFE, 0xE1, 0x77, 0xF6, + 0xBE, 0xF7, 0x9E, 0x7B, 0xDE, 0xEB, 0x1E, 0xF7, 0xED, 0x3D, 0x52, 0xDF, 0xFE, 0x91, 0xB1, 0xAD, + 0x63, 0xB5, 0x40, 0x29, 0x3B, 0xB7, 0x54, 0x48, 0xC3, 0xE3, 0xEF, 0xF9, 0xDA, 0xD7, 0xDE, 0xF3, + 0x9E, 0xAF, 0x3D, 0xFD, 0xE4, 0xBD, 0x1F, 0xF8, 0xC0, 0xBD, 0xF8, 0xD8, 0xFB, 0x89, 0x4F, 0xC0, + 0x77, 0x34, 0xA6, 0xC6, 0x27, 0x4E, 0x47, 0x7C, 0xB7, 0xFB, 0xB0, 0xD5, 0xB3, 0x71, 0xEC, 0x23, + 0x60, 0x5B, 0x3F, 0x3D, 0xE2, 0x4B, 0xA7, 0x06, 0xC3, 0xAD, 0x2C, 0x07, 0x73, 0xCB, 0xF1, 0x85, + 0x94, 0xE8, 0x13, 0x8B, 0x28, 0x82, 0x47, 0x8C, 0xC7, 0xFD, 0xE2, 0x91, 0xAE, 0x6D, 0x73, 0xD0, + 0xBB, 0xB0, 0xB6, 0xD1, 0xC1, 0x79, 0x77, 0xBB, 0xB8, 0xFA, 0xFF, 0x61, 0x40, 0xD9, 0x8D, 0x3B, + 0x1D, 0x24, 0x3D, 0x94, 0x3C, 0xDC, 0xE0, 0xE0, 0xD2, 0x98, 0xB6, 0x7F, 0xF0, 0x65, 0x2F, 0xFB, + 0xA0, 0x7B, 0x9C, 0x14, 0x8F, 0xCC, 0x1E, 0x3C, 0x7D, 0xEB, 0xB5, 0xF3, 0x87, 0xF8, 0xAD, 0x74, + 0x3B, 0xD3, 0xEA, 0x76, 0x5B, 0x85, 0x26, 0x79, 0x69, 0x60, 0x83, 0x6F, 0x7D, 0xB0, 0xB3, 0x69, + 0xDF, 0x03, 0xD7, 0x5D, 0x7F, 0xDF, 0xCE, 0xCD, 0xC9, 0xFC, 0xF6, 0xFE, 0xD4, 0x9E, 0x42, 0x06, + 0x6B, 0xD2, 0x29, 0x58, 0x27, 0xDE, 0x85, 0x6D, 0x34, 0x11, 0x98, 0xE0, 0xAD, 0xFD, 0x19, 0x5E, + 0x40, 0x04, 0x42, 0xEE, 0x16, 0x78, 0x6E, 0x4A, 0x19, 0x40, 0xF7, 0xB3, 0xBA, 0x86, 0x8D, 0xB4, + 0x65, 0xD6, 0x94, 0x64, 0x45, 0x46, 0x9A, 0xCA, 0x32, 0xC8, 0x0D, 0x90, 0x02, 0x43, 0x67, 0x44, + 0x40, 0x99, 0x86, 0x28, 0x70, 0x14, 0xCB, 0xA8, 0x0A, 0x43, 0x93, 0x04, 0x64, 0xD6, 0x12, 0xE3, + 0xB0, 0x56, 0xF7, 0xB6, 0xC5, 0xC3, 0x0F, 0x38, 0xDC, 0x2A, 0x6F, 0x50, 0x09, 0x3D, 0x08, 0xDF, + 0xBA, 0xE6, 0x9C, 0xE7, 0x1A, 0x75, 0x01, 0x65, 0xE3, 0xC2, 0x70, 0x7B, 0x8D, 0x9F, 0xDC, 0xFB, + 0x79, 0x47, 0x58, 0xDB, 0x6B, 0xC3, 0x7E, 0xD4, 0x7D, 0xE3, 0x6E, 0x86, 0xE7, 0x66, 0x9D, 0x27, + 0x35, 0xC2, 0x4D, 0x50, 0xD3, 0x1A, 0x41, 0xD8, 0xA0, 0x92, 0x1A, 0xFE, 0x6F, 0xC6, 0x89, 0x77, + 0x1D, 0xBC, 0x7D, 0xFE, 0x36, 0x74, 0xF0, 0xF1, 0xE3, 0xC7, 0x1F, 0xBB, 0xF0, 0xEC, 0xD9, 0x43, + 0x67, 0xE1, 0x4E, 0x58, 0x87, 0xB5, 0x8B, 0x5F, 0xF7, 0x8E, 0xB7, 0x5F, 0x7C, 0x16, 0xEA, 0xDB, + 0x2F, 0x7E, 0x0C, 0x6E, 0xDF, 0x8E, 0xE5, 0xD0, 0x08, 0xF2, 0x41, 0xC7, 0xCB, 0x45, 0x8B, 0xF4, + 0x69, 0x2F, 0x17, 0xCD, 0xB3, 0xE2, 0xB0, 0x31, 0x7C, 0x45, 0x3A, 0x9A, 0x1B, 0x1B, 0x81, 0xCE, + 0x47, 0xDA, 0x6F, 0x40, 0x0F, 0xDC, 0xE0, 0x3C, 0x86, 0xF5, 0xC0, 0x33, 0xA8, 0x00, 0x47, 0x31, + 0x02, 0x11, 0x81, 0x1F, 0x4C, 0xF7, 0x2D, 0x1E, 0xD0, 0x8E, 0x64, 0x48, 0xC8, 0xC0, 0x57, 0x71, + 0x56, 0x54, 0x19, 0x12, 0x6B, 0x5B, 0x79, 0xBA, 0xA2, 0xAD, 0x85, 0xC7, 0x7B, 0xC6, 0x1D, 0x93, + 0x30, 0xD8, 0x4D, 0x71, 0xB8, 0xC7, 0xDD, 0xC0, 0x2E, 0x0C, 0x18, 0x5E, 0xFA, 0xFC, 0x20, 0x7B, + 0x08, 0x2B, 0x55, 0xAF, 0xBE, 0x74, 0x78, 0x0E, 0x47, 0x17, 0x59, 0xCA, 0x0A, 0x62, 0x45, 0x4B, + 0x69, 0xEF, 0xBA, 0x74, 0x8A, 0xAE, 0xA9, 0xA1, 0x9C, 0x62, 0xAA, 0xBA, 0x21, 0x95, 0xAC, 0x4B, + 0xA7, 0x03, 0xDC, 0xF5, 0x4B, 0xD4, 0x25, 0x4E, 0x62, 0x64, 0x94, 0x19, 0x22, 0xA6, 0x73, 0xE0, + 0x8B, 0xB8, 0xBF, 0x3F, 0x5C, 0x7D, 0x81, 0x0C, 0xA3, 0xCF, 0x83, 0xBD, 0x18, 0x31, 0xBD, 0xAF, + 0xBF, 0x7D, 0x76, 0x2C, 0x19, 0x92, 0xC0, 0x62, 0xB3, 0x3E, 0x52, 0x2A, 0x64, 0x93, 0xD9, 0xFE, + 0xBE, 0x42, 0x7F, 0xDF, 0xE2, 0xE4, 0xBE, 0x78, 0x02, 0xED, 0xDF, 0xB7, 0x6F, 0x7F, 0x7F, 0x12, + 0xBC, 0x62, 0x99, 0xFD, 0x83, 0xE5, 0xBD, 0x7B, 0x1E, 0x23, 0x29, 0x38, 0xB9, 0x54, 0xED, 0xA6, + 0xAB, 0x5F, 0x3F, 0x70, 0x97, 0x7E, 0x95, 0x69, 0x68, 0xDB, 0x26, 0xFB, 0xDA, 0x01, 0xD4, 0x57, + 0xF7, 0xA1, 0xCD, 0xFD, 0xB1, 0x27, 0x42, 0x33, 0x67, 0x61, 0xE8, 0x8A, 0x92, 0x1F, 0x75, 0xB0, + 0x94, 0xAE, 0x91, 0xE8, 0x6D, 0x64, 0xE1, 0x66, 0xC4, 0xBA, 0x31, 0xB4, 0x35, 0xF6, 0x5D, 0xDF, + 0xE0, 0x78, 0x83, 0x8E, 0xAB, 0x5C, 0x19, 0x3E, 0x5D, 0x0E, 0xAD, 0xD7, 0xB9, 0xBB, 0x26, 0x01, + 0x9D, 0xF1, 0xC2, 0x85, 0xF0, 0xD2, 0x9E, 0x17, 0x44, 0x0F, 0x7A, 0x25, 0xEF, 0x75, 0xBB, 0xE1, + 0xED, 0x74, 0x52, 0x6F, 0xBB, 0xD5, 0xDB, 0x2E, 0x4A, 0x70, 0x0B, 0xBC, 0x4D, 0xDA, 0x2D, 0x78, + 0x97, 0x51, 0x92, 0x36, 0xDD, 0x40, 0x56, 0xC4, 0xAB, 0x03, 0x6C, 0x43, 0xC2, 0x69, 0x93, 0x61, + 0xAF, 0x06, 0x3E, 0xF7, 0x69, 0xCE, 0x2F, 0xF8, 0x15, 0x9E, 0x25, 0xDE, 0xFC, 0x5A, 0x95, 0xF4, + 0x51, 0xBE, 0x97, 0x2B, 0x23, 0x46, 0x70, 0xE1, 0xCE, 0x8F, 0xED, 0x9F, 0xBE, 0xCA, 0x2D, 0x89, + 0x57, 0xFB, 0x22, 0xC9, 0xD2, 0x31, 0x5E, 0x12, 0x9C, 0xC2, 0xA3, 0xAC, 0x54, 0x97, 0xDC, 0xE2, + 0xF8, 0x1D, 0x64, 0xE3, 0xB3, 0x92, 0xDE, 0x3F, 0xB8, 0x13, 0x22, 0x4A, 0x60, 0x8A, 0x6F, 0xA2, + 0x66, 0x2F, 0x6E, 0xFB, 0xCE, 0xF2, 0xBD, 0x83, 0x02, 0x79, 0x2C, 0x9C, 0xF3, 0xA3, 0x5C, 0x88, + 0x73, 0xF7, 0xCF, 0xA0, 0x63, 0xDC, 0x60, 0xFF, 0x8C, 0xE9, 0x47, 0xBE, 0x7A, 0x74, 0x97, 0x57, + 0x2C, 0x8F, 0xF9, 0x83, 0xA4, 0xDD, 0x72, 0x79, 0x22, 0x72, 0x16, 0x52, 0xC1, 0xF9, 0x10, 0x2D, + 0x91, 0x6C, 0x4E, 0xAA, 0x56, 0x64, 0x0A, 0xC1, 0x37, 0xAC, 0x02, 0x44, 0x78, 0xF5, 0xA5, 0xFF, + 0x82, 0xFE, 0x07, 0xFA, 0x02, 0xB6, 0xCE, 0xF6, 0x62, 0x79, 0x12, 0xDA, 0xBD, 0x79, 0xAC, 0x92, + 0x49, 0x85, 0x1D, 0x9B, 0x21, 0xC0, 0x52, 0x23, 0x09, 0xE2, 0xED, 0xBD, 0xDB, 0xDF, 0xBF, 0x6F, + 0x9F, 0x42, 0xEE, 0x9B, 0xFC, 0x33, 0x3C, 0xBF, 0x36, 0xEC, 0x0C, 0xC2, 0x2B, 0xE7, 0x80, 0x06, + 0xC7, 0xBD, 0xF2, 0xC8, 0x17, 0xA5, 0x09, 0xB8, 0x73, 0xB9, 0xCF, 0xAB, 0x8E, 0x40, 0x11, 0xB8, + 0x5E, 0x5F, 0x96, 0xF5, 0xCA, 0xE0, 0xD7, 0x0C, 0xEF, 0x56, 0x63, 0x98, 0xB3, 0x36, 0x85, 0xDA, + 0xDE, 0x0E, 0x4D, 0x97, 0xF2, 0x39, 0xDC, 0x8C, 0x7D, 0xC2, 0x2D, 0x55, 0x84, 0x6B, 0xF9, 0x6C, + 0x19, 0xF4, 0x3F, 0xA2, 0x45, 0x63, 0x4C, 0x18, 0x16, 0x9F, 0x5D, 0x3D, 0xAB, 0x3B, 0xFE, 0xAC, + 0x79, 0x90, 0xE1, 0x06, 0x45, 0x68, 0x1C, 0x65, 0x96, 0x13, 0x12, 0xB9, 0xF5, 0x50, 0xBA, 0xE8, + 0xEB, 0xB4, 0x2F, 0x2F, 0x40, 0x5B, 0x30, 0x2A, 0x76, 0xFE, 0x4F, 0x28, 0x4D, 0x7D, 0xE4, 0x4C, + 0xAC, 0x31, 0x28, 0x53, 0x43, 0x7F, 0x99, 0xAE, 0x9A, 0x73, 0xA7, 0xD7, 0xCB, 0xD2, 0xC6, 0xED, + 0x30, 0xC3, 0x1C, 0xE5, 0x84, 0xCB, 0xAA, 0xD3, 0xB6, 0x3A, 0xF4, 0xDE, 0x9B, 0x0B, 0x8D, 0xC4, + 0x88, 0x75, 0xA9, 0x30, 0xAD, 0xA0, 0xB5, 0x69, 0xE6, 0xE2, 0x9B, 0xD3, 0xCD, 0xC8, 0x9B, 0x1E, + 0x4F, 0xA7, 0x07, 0xB5, 0x6B, 0x03, 0x0B, 0xF7, 0x39, 0xF8, 0x5E, 0xCF, 0x62, 0x58, 0x18, 0xD8, + 0x45, 0x9E, 0x5D, 0xED, 0x55, 0xDD, 0x7B, 0x5C, 0x51, 0x18, 0x72, 0xC5, 0x37, 0x3C, 0x2B, 0xDC, + 0xCB, 0xA3, 0xF2, 0xBE, 0xBD, 0x79, 0xD8, 0xFE, 0x06, 0x30, 0x88, 0x02, 0x7C, 0x0E, 0xDD, 0x8D, + 0x7E, 0x8A, 0x51, 0xF1, 0xAB, 0xFB, 0xD3, 0xBD, 0x6E, 0x39, 0x9D, 0x4A, 0x86, 0x43, 0x41, 0x5D, + 0x53, 0x64, 0x89, 0x63, 0x19, 0xD0, 0xAE, 0x95, 0x0A, 0x46, 0xBB, 0xAD, 0x06, 0x1C, 0xDB, 0x56, + 0x03, 0xC9, 0x04, 0x4F, 0x70, 0x13, 0xE9, 0x14, 0x4B, 0x30, 0x47, 0xC2, 0x21, 0x2C, 0x15, 0x27, + 0xDC, 0x44, 0x0F, 0x25, 0x1A, 0x08, 0x20, 0x75, 0xF6, 0x73, 0xB0, 0xBC, 0x26, 0x07, 0x6C, 0xD8, + 0x5D, 0x4B, 0xB1, 0xDB, 0xB8, 0x63, 0x38, 0x5C, 0xDB, 0x4D, 0x55, 0xED, 0xBE, 0x78, 0xF5, 0x2E, + 0xC1, 0xE5, 0xF2, 0x20, 0x34, 0x44, 0x36, 0xAC, 0x24, 0x43, 0x33, 0xF8, 0x79, 0xB0, 0xA5, 0x2A, + 0x5E, 0x10, 0x77, 0x57, 0xD1, 0x4C, 0x13, 0x2F, 0x12, 0x7E, 0x1D, 0x94, 0x65, 0x6F, 0xC8, 0x99, + 0x27, 0x06, 0x39, 0xF3, 0xE8, 0x6E, 0x55, 0x1B, 0x91, 0x95, 0xAA, 0x70, 0xC7, 0x5B, 0xA8, 0x3C, + 0xF5, 0xE5, 0xAF, 0xC0, 0xA0, 0x59, 0xF3, 0x53, 0x1F, 0xFB, 0x10, 0x49, 0xFB, 0xEC, 0x3B, 0xB7, + 0x59, 0xF6, 0x58, 0x52, 0x66, 0x05, 0x4E, 0x5F, 0xD1, 0xAD, 0xAE, 0x59, 0x2A, 0xE6, 0x54, 0x67, + 0x44, 0xC3, 0x12, 0xBF, 0x52, 0x2E, 0x96, 0xD1, 0xF7, 0xAD, 0xC8, 0xA1, 0x40, 0xF4, 0x5A, 0x7B, + 0x96, 0xDF, 0x5E, 0x9B, 0xDD, 0x65, 0xFB, 0xD4, 0x92, 0xD3, 0x4D, 0x9D, 0xA4, 0x66, 0x35, 0xCA, + 0x6A, 0x65, 0x67, 0x93, 0x89, 0xED, 0xD9, 0x41, 0xFE, 0xFC, 0xE2, 0xF6, 0x1D, 0x89, 0xEC, 0xAD, + 0xA5, 0x8A, 0x4F, 0x90, 0x25, 0x2F, 0x7D, 0xDE, 0x8B, 0x25, 0xF9, 0xBD, 0x58, 0xD2, 0x34, 0xB8, + 0xB6, 0x9F, 0xCD, 0x25, 0xFC, 0xB6, 0xA9, 0xA6, 0x93, 0xF1, 0x08, 0x35, 0xF2, 0x37, 0x33, 0xE4, + 0xB5, 0x33, 0x65, 0x0A, 0x4C, 0xF7, 0x28, 0xD4, 0x23, 0x51, 0xB7, 0x8D, 0xFA, 0xBD, 0xEE, 0x0B, + 0x2B, 0x67, 0xD7, 0xC2, 0x65, 0x67, 0xDC, 0xE9, 0x9A, 0xEC, 0x5D, 0x1E, 0x56, 0xDA, 0xE0, 0x9E, + 0xBE, 0xAC, 0x7E, 0x22, 0x71, 0x79, 0x7C, 0x29, 0x4A, 0xB8, 0x39, 0x21, 0xCD, 0x0D, 0x11, 0xA6, + 0x41, 0xDC, 0xDA, 0x45, 0x5B, 0xBF, 0x37, 0xC6, 0x44, 0xBB, 0x1B, 0x5D, 0xCC, 0x2F, 0x69, 0x84, + 0xBA, 0x16, 0x65, 0x92, 0x59, 0x37, 0xCA, 0x44, 0xD3, 0xDC, 0xEF, 0x0B, 0x32, 0xD1, 0xC9, 0x7C, + 0x32, 0x97, 0x6E, 0xE5, 0x9F, 0x8A, 0xBE, 0xF9, 0xE1, 0x41, 0xA8, 0xE9, 0xFF, 0xA2, 0xEE, 0xCB, + 0xE3, 0xE4, 0x2A, 0xCA, 0x76, 0xDF, 0xAA, 0xD3, 0x67, 0xDF, 0x7B, 0x9D, 0xE9, 0xD9, 0xF7, 0xC9, + 0x64, 0x9B, 0x25, 0x99, 0xC9, 0x3E, 0x93, 0x7D, 0x21, 0x84, 0x09, 0x21, 0x3B, 0x43, 0x86, 0x24, + 0x06, 0x0C, 0x04, 0x48, 0x08, 0x18, 0x64, 0x5F, 0x8C, 0x88, 0x80, 0x88, 0x8A, 0x44, 0x81, 0x0F, + 0x90, 0x25, 0x0A, 0x22, 0x28, 0x2E, 0xEC, 0x88, 0xC8, 0x26, 0xAB, 0x22, 0x84, 0x45, 0xE4, 0x13, + 0xAE, 0xEC, 0x08, 0x08, 0x5C, 0xF4, 0x23, 0xF4, 0x7D, 0xAA, 0x4E, 0x77, 0x4F, 0x27, 0x99, 0x28, + 0xF7, 0xFE, 0xBE, 0xFB, 0xC7, 0x77, 0xA6, 0x6B, 0xBA, 0xBB, 0xBA, 0x4E, 0x55, 0x3D, 0x55, 0x6F, + 0x3D, 0xEF, 0x5B, 0xCB, 0xA9, 0x8A, 0x89, 0x99, 0xA6, 0xFA, 0x46, 0xDF, 0x09, 0xF6, 0x9E, 0x6A, + 0x82, 0xEC, 0xC9, 0xDD, 0x12, 0xA4, 0x4C, 0x8E, 0xCC, 0xCB, 0xDE, 0x5B, 0x72, 0x84, 0xA9, 0xB0, + 0x56, 0xAD, 0x99, 0x0E, 0x88, 0xFC, 0x99, 0x29, 0xFB, 0xD9, 0x7A, 0xAE, 0x8E, 0x4D, 0x95, 0xE1, + 0x47, 0xE7, 0xC3, 0x97, 0x4B, 0x66, 0xFF, 0x20, 0x97, 0x96, 0x23, 0x01, 0x19, 0xAA, 0xA6, 0x65, + 0x7D, 0x35, 0x95, 0x09, 0xF2, 0x8D, 0x6C, 0x5A, 0xA9, 0xAC, 0x80, 0xF9, 0xD5, 0x52, 0x55, 0xE5, + 0x28, 0x65, 0xE9, 0x4C, 0x9A, 0xC7, 0x94, 0x6A, 0xE5, 0x2F, 0xCC, 0x29, 0x76, 0x44, 0x60, 0xCD, + 0xE7, 0xC7, 0x68, 0xE5, 0x4E, 0xED, 0xA2, 0x2B, 0x92, 0x65, 0x7D, 0xBB, 0x83, 0xBC, 0x40, 0x0E, + 0x2D, 0xB2, 0xA9, 0x71, 0xD4, 0x91, 0x99, 0xFD, 0xAC, 0x98, 0x4A, 0x34, 0xB4, 0xE8, 0x0D, 0x3D, + 0x5D, 0xBB, 0x86, 0x59, 0x29, 0xB5, 0xE4, 0x84, 0xF6, 0xA9, 0xFD, 0x47, 0x6C, 0xB8, 0x61, 0xB8, + 0x15, 0x52, 0xFC, 0xA2, 0x95, 0x2B, 0xB7, 0x01, 0x91, 0x7C, 0xF6, 0x4E, 0x22, 0xEA, 0xCE, 0x23, + 0xFA, 0x11, 0x10, 0x31, 0x72, 0xD9, 0x99, 0x6C, 0x80, 0x3F, 0x86, 0x5E, 0xFC, 0xDC, 0xBE, 0x74, + 0x6B, 0x3D, 0x35, 0x85, 0xBE, 0x11, 0xC6, 0xB3, 0x4E, 0x4B, 0x4B, 0x3C, 0x1B, 0xE7, 0x59, 0x56, + 0x98, 0xB7, 0x10, 0x32, 0x02, 0xB3, 0x50, 0x58, 0x87, 0xD3, 0x7B, 0x0B, 0x1B, 0xC7, 0xCA, 0xA6, + 0x54, 0xBA, 0xBE, 0xA1, 0x23, 0x2B, 0xD5, 0xB7, 0x98, 0xE5, 0xF2, 0xF2, 0x8B, 0x9E, 0x32, 0xFA, + 0xD0, 0xD2, 0x8D, 0x5E, 0xA5, 0xA5, 0xB9, 0xE4, 0xA9, 0x1A, 0x36, 0x30, 0xDF, 0x4D, 0xD4, 0x8D, + 0x48, 0xC6, 0x0D, 0xBD, 0x3C, 0x50, 0xED, 0x6E, 0xAB, 0x3C, 0xAE, 0x57, 0xA5, 0x6B, 0x12, 0xE6, + 0xC8, 0xD6, 0xF2, 0xEE, 0xF2, 0xC0, 0x70, 0x52, 0x7A, 0x5D, 0xB5, 0xE9, 0xA8, 0x23, 0x1A, 0x82, + 0x44, 0x6F, 0x5B, 0x59, 0x86, 0xDD, 0xD6, 0xD3, 0x30, 0x72, 0x44, 0x52, 0x55, 0x62, 0x81, 0x5F, + 0x6F, 0xDA, 0x56, 0x55, 0x59, 0x5C, 0x6B, 0x2C, 0x0F, 0x3A, 0x1B, 0x6D, 0x95, 0xC5, 0x54, 0xB7, + 0x47, 0xD7, 0x9B, 0x6A, 0x57, 0x2C, 0xEC, 0x68, 0x17, 0xBD, 0x9E, 0x80, 0x9D, 0xC0, 0x1A, 0xF8, + 0xDD, 0xC0, 0xDB, 0xD2, 0xA7, 0xD7, 0x96, 0x05, 0xAE, 0xA9, 0xB8, 0x72, 0xA7, 0xE0, 0x59, 0x72, + 0x64, 0x61, 0x66, 0x2F, 0x95, 0x8E, 0x99, 0xB6, 0x98, 0x85, 0x29, 0xF2, 0xC8, 0xE0, 0xEB, 0x65, + 0x7B, 0x2C, 0x32, 0x29, 0xAD, 0x0C, 0xF4, 0x1D, 0xEC, 0x93, 0xDB, 0xDB, 0xA6, 0xA5, 0x1B, 0x6B, + 0x75, 0x23, 0xDE, 0xE2, 0x98, 0x56, 0xA3, 0xAA, 0xB7, 0x4F, 0xB5, 0x54, 0x97, 0x97, 0x75, 0x34, + 0x54, 0xB7, 0x85, 0xFC, 0x38, 0xAD, 0x35, 0x9C, 0x76, 0xDA, 0x8A, 0x91, 0x55, 0xCD, 0x35, 0x65, + 0x65, 0x65, 0x29, 0x7F, 0x56, 0x46, 0x8F, 0x75, 0x64, 0x1A, 0xD6, 0x30, 0xC5, 0x49, 0xD4, 0x35, + 0x94, 0x0B, 0xF9, 0x92, 0xB3, 0xF9, 0x92, 0x0B, 0x97, 0x45, 0xCC, 0xB9, 0x26, 0x1A, 0x19, 0x7C, + 0x43, 0x51, 0xD9, 0xBB, 0xB4, 0x56, 0x3C, 0xF7, 0xBD, 0x70, 0xE6, 0xF8, 0x66, 0x74, 0x78, 0xA7, + 0x8C, 0xEB, 0xAC, 0x9B, 0xB2, 0x7C, 0x4C, 0x76, 0xF9, 0x98, 0x85, 0x87, 0xAC, 0xDD, 0xBE, 0x6E, + 0x4D, 0x66, 0x5D, 0x36, 0xBD, 0x6E, 0xE0, 0xF9, 0x75, 0x65, 0xC7, 0xAF, 0xAB, 0x8D, 0xAD, 0x6B, + 0x98, 0xBD, 0x6E, 0xF1, 0xF2, 0xE5, 0x7C, 0x4C, 0xDF, 0xC4, 0xDF, 0xAB, 0x2F, 0x0E, 0xCD, 0xB9, + 0x4D, 0x19, 0x5A, 0x5C, 0x3C, 0xF4, 0x37, 0xF6, 0x19, 0x56, 0x62, 0x01, 0x94, 0x74, 0xB0, 0xD6, + 0x35, 0x0F, 0x2D, 0x3C, 0x6E, 0xC1, 0x4B, 0xFF, 0xBC, 0x6B, 0xF7, 0x41, 0x79, 0x25, 0xAB, 0x94, + 0x3B, 0x4B, 0x56, 0x29, 0xCB, 0x99, 0xAA, 0x1E, 0x61, 0x28, 0xAB, 0x85, 0x85, 0xCA, 0x9D, 0xF1, + 0x8A, 0x39, 0x8D, 0xE5, 0x13, 0xE2, 0x9F, 0x6F, 0x81, 0xFF, 0x82, 0xC6, 0x9A, 0xA5, 0xA5, 0xEB, + 0x9A, 0x63, 0xE3, 0xA2, 0x75, 0xCD, 0x41, 0x22, 0x3B, 0x6D, 0x6E, 0x43, 0xB3, 0xA2, 0xC5, 0xF2, + 0x6B, 0x9B, 0xC7, 0x8F, 0xAD, 0xA9, 0x35, 0x15, 0xA6, 0xFC, 0xBB, 0x47, 0x00, 0x0E, 0xEF, 0x6A, + 0x9B, 0x57, 0xBA, 0x04, 0x7A, 0x4C, 0x7E, 0x05, 0xF4, 0xC8, 0xD6, 0x86, 0xDA, 0x5E, 0x3F, 0xC6, + 0xC5, 0x78, 0xC3, 0x27, 0xB9, 0x47, 0x18, 0x5A, 0x09, 0xF5, 0x40, 0x9F, 0x9D, 0xDB, 0x37, 0xAD, + 0xB1, 0x26, 0x11, 0x37, 0x68, 0xDC, 0x98, 0x96, 0xCE, 0xA9, 0x63, 0x3B, 0xA7, 0x2A, 0x9D, 0x53, + 0x2B, 0x7B, 0x33, 0x63, 0xEA, 0x32, 0x5E, 0x5D, 0xA6, 0x72, 0xE4, 0x88, 0x9E, 0xC6, 0x77, 0xE6, + 0xCE, 0xDC, 0x3A, 0x77, 0xF6, 0xCE, 0xB9, 0x73, 0x9D, 0x1D, 0x73, 0xA7, 0xFE, 0x57, 0xE7, 0xB3, + 0x13, 0x7A, 0x61, 0x45, 0xD6, 0xF1, 0x0C, 0xAD, 0x8A, 0x1F, 0x54, 0xB0, 0xC1, 0x7B, 0x8B, 0x73, + 0x7D, 0xBD, 0xD1, 0xC8, 0x83, 0xC7, 0xE6, 0xE6, 0xAB, 0xA3, 0x77, 0xCA, 0xBE, 0xFB, 0x0F, 0xED, + 0xBD, 0x99, 0xE5, 0xDC, 0xB8, 0x34, 0x26, 0xA2, 0x6D, 0x51, 0x51, 0xEE, 0xA2, 0x6A, 0x1A, 0x7A, + 0x5A, 0x4A, 0xD6, 0x41, 0x65, 0x60, 0x70, 0xC1, 0xAA, 0x68, 0x6E, 0x10, 0x0F, 0xAC, 0x47, 0xB3, + 0xE2, 0xD2, 0x8C, 0x18, 0x87, 0x7A, 0x94, 0x76, 0x04, 0xEA, 0x81, 0xBD, 0x57, 0xDE, 0xD0, 0xA8, + 0xA4, 0x2A, 0xEB, 0xDA, 0x2F, 0x5F, 0xDC, 0x39, 0xAA, 0x26, 0xD3, 0x92, 0x5C, 0xAC, 0xA4, 0xF2, + 0x2B, 0xA4, 0x4C, 0xBD, 0x65, 0x7C, 0x66, 0x6C, 0x6F, 0x68, 0xC4, 0x7C, 0xAE, 0xB4, 0x2E, 0xED, + 0xAE, 0xA8, 0x98, 0x9C, 0x6A, 0x39, 0xC6, 0xAE, 0x54, 0x6D, 0xFE, 0xA5, 0x54, 0x9B, 0x19, 0x0B, + 0x83, 0xC9, 0xFC, 0xC0, 0xA6, 0xB1, 0x5D, 0x3C, 0x68, 0x3E, 0x48, 0xAC, 0x99, 0x6A, 0x99, 0xA6, + 0xEB, 0xC7, 0x29, 0x15, 0x25, 0x2B, 0xA7, 0x6A, 0x95, 0x90, 0x77, 0x1F, 0xD8, 0x30, 0x52, 0x2E, + 0x9C, 0x72, 0xD6, 0xC2, 0x50, 0x58, 0x0A, 0x9A, 0x32, 0x3D, 0xE5, 0xC6, 0xCA, 0x32, 0x4D, 0x87, + 0x9D, 0xE5, 0xE7, 0xA6, 0xB0, 0x3F, 0xF0, 0x2A, 0x0A, 0xA8, 0x93, 0xFA, 0xFB, 0xCA, 0x9A, 0x42, + 0x5D, 0xE7, 0x76, 0x23, 0xB7, 0xBB, 0x3A, 0x97, 0x75, 0xD9, 0x9C, 0xB7, 0xF1, 0x2A, 0x67, 0x80, + 0x55, 0x15, 0x58, 0x26, 0xC9, 0x16, 0x88, 0x31, 0x41, 0x8F, 0xCD, 0x2F, 0x9A, 0xEF, 0xB2, 0xE0, + 0xC6, 0xB0, 0xB2, 0xA1, 0x1D, 0xF9, 0xF2, 0x1B, 0xF2, 0x55, 0x45, 0x03, 0x03, 0x72, 0x35, 0x79, + 0xA4, 0x79, 0x12, 0x25, 0xFB, 0x79, 0xF5, 0x2A, 0x72, 0xFF, 0x98, 0xFC, 0x73, 0x5D, 0xAC, 0x87, + 0xAD, 0x8D, 0xE7, 0xB7, 0xDA, 0xCB, 0xCA, 0x8D, 0xF7, 0x4E, 0x3E, 0x66, 0xC4, 0x64, 0xD7, 0x75, + 0x5B, 0x5B, 0x67, 0xB6, 0x1B, 0xFB, 0xEE, 0xD3, 0xC7, 0x29, 0x5B, 0xDC, 0x6C, 0xCF, 0x9F, 0xC9, + 0xBD, 0xDD, 0xD7, 0xAD, 0xA8, 0x53, 0x74, 0x6F, 0xCC, 0xEC, 0xF1, 0xC3, 0xED, 0xD2, 0x27, 0xC6, + 0x43, 0x67, 0xE7, 0xC6, 0xD3, 0x6E, 0x9E, 0x20, 0x0F, 0xBA, 0x62, 0x56, 0x5F, 0x32, 0x61, 0xA5, + 0x75, 0x1D, 0x9D, 0x05, 0x3F, 0xC9, 0xC5, 0xCB, 0xDE, 0x56, 0x58, 0xFA, 0x0F, 0x74, 0x09, 0xB6, + 0xB0, 0xB7, 0xEC, 0x36, 0x70, 0xEF, 0x01, 0x85, 0xA6, 0xBA, 0xF7, 0x66, 0x83, 0x59, 0x2B, 0xDA, + 0xB2, 0x1E, 0xD8, 0x9A, 0x25, 0xB4, 0x84, 0xAF, 0xF4, 0xF2, 0x1A, 0xFE, 0x66, 0x22, 0xDA, 0x93, + 0xBB, 0x4B, 0xEC, 0xCF, 0xDD, 0x30, 0xA2, 0xAD, 0x6D, 0x44, 0x74, 0x14, 0x0C, 0xFB, 0x38, 0x5B, + 0xD8, 0xA2, 0xBB, 0x72, 0x26, 0xDF, 0xBD, 0xA3, 0xAA, 0xAA, 0xBA, 0x26, 0x3A, 0x0C, 0x06, 0x39, + 0xAB, 0x46, 0xF6, 0x9E, 0xE7, 0x77, 0xCA, 0x3D, 0x1D, 0xE7, 0xF4, 0x41, 0x65, 0xE8, 0x24, 0x4E, + 0xBC, 0x21, 0x5D, 0x28, 0x60, 0x85, 0xA1, 0x0B, 0xC6, 0x0A, 0x03, 0x33, 0xB7, 0x11, 0x67, 0x8B, + 0xF6, 0x38, 0xF4, 0x46, 0x0C, 0x9B, 0x1D, 0x08, 0xCD, 0x75, 0x1B, 0xA9, 0xE2, 0x3D, 0xBF, 0xCB, + 0xE3, 0x08, 0x16, 0xD6, 0x29, 0x61, 0x5D, 0xC8, 0x9F, 0xDF, 0x3D, 0x8B, 0xDF, 0x59, 0xBE, 0xFB, + 0x44, 0x7E, 0xE7, 0xEE, 0x01, 0x7E, 0xDE, 0xEE, 0x13, 0xA9, 0x38, 0x0F, 0xB3, 0xAC, 0x38, 0x0F, + 0xF3, 0x02, 0x33, 0xE8, 0xB2, 0xE2, 0x48, 0xF2, 0xED, 0xC5, 0x91, 0xE4, 0x17, 0xE8, 0x6A, 0x79, + 0xE2, 0xD4, 0x48, 0xE8, 0xA6, 0xB7, 0xE4, 0x6E, 0xE5, 0x15, 0x34, 0x82, 0x96, 0xF4, 0x35, 0x8B, + 0x8D, 0x42, 0xBD, 0x64, 0x4B, 0x65, 0x7D, 0x25, 0xAF, 0x47, 0x27, 0x8F, 0xBC, 0xFA, 0xA4, 0xC7, + 0x93, 0x2D, 0xE5, 0xF6, 0xE4, 0x81, 0x9A, 0xAA, 0xD0, 0x67, 0xAA, 0x32, 0xB4, 0xD6, 0x27, 0x23, + 0xCE, 0xAE, 0x91, 0xA2, 0x22, 0x95, 0xAB, 0x34, 0x5A, 0x86, 0x1A, 0x96, 0x58, 0x8A, 0x56, 0x9F, + 0x7F, 0xAC, 0x25, 0xBF, 0x47, 0x67, 0xB1, 0xCF, 0xB7, 0xD7, 0x67, 0xFE, 0x56, 0xC9, 0x9E, 0xE7, + 0x4F, 0xED, 0xE7, 0x73, 0xE9, 0x5E, 0xE8, 0x95, 0xFB, 0xF9, 0x5C, 0x9C, 0x1F, 0x3C, 0xB5, 0x38, + 0x3F, 0x38, 0x33, 0x9A, 0x89, 0xCA, 0xFB, 0x9F, 0x54, 0xF4, 0x7F, 0x8E, 0x9E, 0x2C, 0x99, 0xD1, + 0x3A, 0xA9, 0x38, 0xA3, 0xF5, 0x1C, 0x3D, 0x20, 0xB5, 0x33, 0xFC, 0x63, 0x35, 0xE8, 0xA3, 0xAC, + 0xA3, 0x1F, 0xF4, 0xF5, 0x0F, 0xAC, 0x5E, 0xBA, 0x70, 0x52, 0x5D, 0x4D, 0x99, 0x45, 0xF3, 0x67, + 0xCE, 0x18, 0x5F, 0x6D, 0xCC, 0x5C, 0x3D, 0xDA, 0x58, 0x3D, 0x7A, 0xCE, 0xA1, 0xA3, 0xD7, 0xAC, + 0x74, 0xD5, 0xCA, 0x89, 0x87, 0xD0, 0xB9, 0xEB, 0x5B, 0x77, 0xAE, 0x5F, 0x7C, 0xC6, 0x9C, 0x55, + 0x2B, 0x4F, 0x3F, 0xB8, 0x7F, 0xF4, 0xAA, 0xD5, 0xDB, 0x0F, 0x5E, 0xB7, 0x76, 0xBB, 0x65, 0xC6, + 0xA0, 0x54, 0x5C, 0xC7, 0x56, 0x46, 0xF3, 0x35, 0x87, 0x1D, 0xBC, 0x38, 0x76, 0xE8, 0xC2, 0xDE, + 0x1F, 0xC6, 0x8D, 0xA1, 0xE3, 0x63, 0x0A, 0xDB, 0xE9, 0xCB, 0xA1, 0x64, 0x31, 0x3E, 0x70, 0x1B, + 0xCD, 0xC9, 0xEF, 0x93, 0x96, 0x67, 0x2A, 0xB9, 0xBC, 0x6F, 0x9F, 0x1E, 0xE4, 0x9E, 0x0F, 0x37, + 0xAC, 0x2F, 0xDB, 0x6B, 0xAF, 0xB4, 0xF1, 0x43, 0x7B, 0x6B, 0x14, 0x3A, 0x3D, 0x62, 0x73, 0x0D, + 0xB1, 0x91, 0xA0, 0x5A, 0xD2, 0xED, 0x49, 0x67, 0xF2, 0x7B, 0x81, 0x15, 0x7A, 0x93, 0xC5, 0xAD, + 0xD4, 0x6A, 0x58, 0xB4, 0x91, 0x5A, 0xAC, 0xA6, 0x74, 0x23, 0x35, 0xC5, 0x5F, 0x3E, 0xB4, 0x0B, + 0x87, 0xE8, 0x00, 0x15, 0xB6, 0xE1, 0xC8, 0xFA, 0x46, 0xD0, 0xBD, 0xD7, 0x36, 0x1C, 0x73, 0xEA, + 0xAB, 0xA2, 0xED, 0xD6, 0xF2, 0x7D, 0xCA, 0xD2, 0x0D, 0xD7, 0x94, 0x7D, 0xF6, 0x5B, 0x2B, 0x53, + 0xDC, 0x19, 0xC3, 0xEE, 0xD5, 0x31, 0x7B, 0x46, 0x5D, 0x6A, 0x52, 0xD3, 0xE1, 0xA5, 0x7B, 0x75, + 0x24, 0x2A, 0xF6, 0xD9, 0x90, 0xED, 0x3C, 0xB9, 0x1D, 0x9B, 0x98, 0x03, 0x7E, 0x83, 0x7F, 0xCA, + 0xDE, 0xA1, 0x35, 0x74, 0x78, 0xDF, 0xD8, 0xA5, 0x07, 0xCE, 0xEB, 0x6D, 0x47, 0x8F, 0x26, 0x9B, + 0x89, 0xD3, 0x84, 0xAE, 0xB1, 0xF3, 0x46, 0x65, 0xFA, 0x47, 0xB5, 0xF5, 0xAC, 0xD9, 0x3E, 0x78, + 0x68, 0x66, 0x70, 0xD5, 0xF3, 0x83, 0xD6, 0x09, 0x83, 0x35, 0x5B, 0x07, 0xEB, 0x76, 0x0E, 0x7A, + 0x3B, 0x06, 0xA7, 0xBC, 0xA0, 0xBE, 0x38, 0xB4, 0x84, 0x2F, 0x28, 0xAA, 0x89, 0x29, 0x62, 0xD4, + 0x6A, 0x98, 0x9E, 0xE6, 0x60, 0xBC, 0x44, 0x6D, 0xD7, 0xEF, 0xB5, 0x3E, 0x36, 0x62, 0xFE, 0x1E, + 0xB1, 0x4B, 0x13, 0x2F, 0xD5, 0x0D, 0x51, 0x2F, 0x73, 0x18, 0xA5, 0x2D, 0xF7, 0x3A, 0x8C, 0x2C, + 0x36, 0x31, 0x4B, 0xFE, 0x69, 0x41, 0x6D, 0xD7, 0xF9, 0x5C, 0x3F, 0xAA, 0x64, 0x45, 0xED, 0x3C, + 0xA9, 0x13, 0x0C, 0xE6, 0x8E, 0x3A, 0xA4, 0x33, 0x34, 0x23, 0xAD, 0xD1, 0xD3, 0xD1, 0x19, 0x4F, + 0x5B, 0x0D, 0x23, 0xF7, 0x55, 0xD8, 0x99, 0x3A, 0x4D, 0x0F, 0x0F, 0xDF, 0x43, 0x61, 0xD7, 0x67, + 0x8D, 0x23, 0xF6, 0x58, 0x79, 0xDB, 0xAA, 0xE9, 0x0B, 0xE3, 0xF1, 0x54, 0xEB, 0xC1, 0xD1, 0xDA, + 0xDB, 0x66, 0xBF, 0x3C, 0x55, 0xD7, 0xB8, 0xAF, 0xAA, 0xAE, 0x69, 0x8A, 0xC7, 0x6A, 0xAB, 0x3A, + 0xD6, 0x49, 0x5D, 0x2D, 0xCE, 0xA1, 0xFB, 0x88, 0x8D, 0x62, 0x87, 0x81, 0x3D, 0x1A, 0xFB, 0x34, + 0xF9, 0x44, 0x24, 0x93, 0x23, 0x5E, 0x87, 0x44, 0x1C, 0xB6, 0x64, 0xAF, 0xE7, 0x22, 0x9B, 0xEA, + 0xC6, 0xD7, 0xB1, 0x51, 0x9F, 0x3D, 0xCD, 0x46, 0x7D, 0xF4, 0xC5, 0xE8, 0x6E, 0xBE, 0xE2, 0xFF, + 0xEE, 0x6E, 0xBE, 0x62, 0xF7, 0x4E, 0xBE, 0x02, 0x77, 0x73, 0x98, 0x8F, 0x6F, 0xB0, 0x3B, 0x60, + 0x33, 0x27, 0xD1, 0x9B, 0xE8, 0xEC, 0x73, 0x46, 0x34, 0x57, 0xC7, 0x7D, 0xD2, 0x53, 0x4D, 0x03, + 0xE5, 0x72, 0x44, 0x4B, 0x61, 0xCB, 0x7A, 0xA7, 0x48, 0x1D, 0x36, 0x5D, 0xEA, 0xB0, 0x67, 0xA8, + 0x64, 0x39, 0x73, 0x75, 0xB4, 0x7F, 0x83, 0x5C, 0x02, 0xA3, 0xCA, 0x67, 0x7C, 0xA2, 0xE7, 0xF9, + 0xC7, 0xC8, 0xCD, 0xA9, 0xF3, 0x5E, 0x69, 0x76, 0x87, 0x37, 0x6A, 0x8C, 0xE9, 0xF4, 0x55, 0x14, + 0xCF, 0x9B, 0x78, 0xD8, 0x4B, 0x8C, 0xC9, 0x9A, 0x96, 0xDD, 0x2D, 0xBC, 0x9C, 0x1E, 0x78, 0x75, + 0xF1, 0x0E, 0xB7, 0x29, 0xAD, 0xEA, 0xE3, 0xEA, 0x33, 0x55, 0x4E, 0x2C, 0x61, 0x34, 0xC4, 0xED, + 0xAA, 0x74, 0x45, 0xB3, 0x2D, 0x76, 0x0E, 0x56, 0x75, 0xAB, 0xAD, 0xA1, 0x3C, 0xEB, 0xC5, 0x42, + 0xA3, 0x21, 0xB4, 0xAA, 0x53, 0x95, 0x6D, 0xF2, 0xD4, 0x2E, 0xF6, 0x5A, 0x69, 0xBE, 0xDB, 0xAA, + 0x2B, 0x1C, 0x53, 0x4B, 0xD4, 0x35, 0x0D, 0xA8, 0x32, 0xDF, 0x59, 0xB6, 0x5C, 0xE6, 0xDB, 0x1F, + 0x2E, 0xDF, 0x8E, 0x38, 0xFE, 0xA5, 0xB8, 0xB9, 0x71, 0x77, 0x8F, 0x30, 0x49, 0x32, 0x79, 0x8F, + 0xE6, 0x96, 0x68, 0x3F, 0x44, 0x31, 0x6D, 0x5C, 0x7A, 0x42, 0x86, 0x84, 0x70, 0x6F, 0x31, 0xBF, + 0x5E, 0x01, 0x02, 0xEF, 0x29, 0xCD, 0x6F, 0x01, 0x44, 0x4D, 0x49, 0x6E, 0x8D, 0x21, 0x10, 0xF2, + 0x9C, 0x95, 0x37, 0xE8, 0x65, 0xE4, 0x3B, 0x4D, 0x4D, 0x7D, 0x5A, 0x32, 0x34, 0x29, 0x1A, 0x39, + 0x8C, 0xA1, 0x9C, 0x4F, 0x14, 0xD3, 0xDF, 0xD3, 0x4B, 0xCE, 0xED, 0xC8, 0x98, 0xE2, 0x19, 0x94, + 0x7D, 0x0A, 0xF4, 0xE5, 0xE1, 0x8A, 0x6F, 0x7F, 0x25, 0x35, 0x94, 0x62, 0x52, 0xA4, 0x28, 0xCE, + 0x08, 0x89, 0x52, 0x54, 0xA3, 0x14, 0xFD, 0x3D, 0x52, 0x4C, 0x0D, 0x57, 0x34, 0xFB, 0x14, 0xC3, + 0xF0, 0x98, 0x65, 0x5A, 0xA8, 0x9A, 0x4F, 0xF8, 0xB3, 0xA5, 0xCF, 0xF6, 0x5E, 0x2E, 0x4E, 0x44, + 0xD8, 0xE7, 0xD9, 0x5E, 0xA1, 0x73, 0xF9, 0x27, 0xBB, 0x47, 0xF2, 0x3F, 0xF2, 0x67, 0xC5, 0xAA, + 0x09, 0xB1, 0xEE, 0x4C, 0xCE, 0xCB, 0x1E, 0x9A, 0x9F, 0x97, 0x95, 0x33, 0xCD, 0xD1, 0x3E, 0x01, + 0x72, 0x15, 0xC4, 0x94, 0xA1, 0x55, 0x10, 0xC4, 0x72, 0x4B, 0x72, 0xAF, 0xB2, 0x6E, 0x7E, 0x13, + 0xD2, 0x69, 0xEB, 0x33, 0x8B, 0xDB, 0x2E, 0x93, 0x18, 0x81, 0x5D, 0x25, 0xC4, 0x9E, 0xD8, 0x4A, + 0x24, 0x58, 0x32, 0xD6, 0x2F, 0xC6, 0x62, 0x4D, 0xD6, 0xC0, 0x58, 0xF7, 0x67, 0xC7, 0x1E, 0xCC, + 0xBE, 0xC9, 0x6F, 0xDA, 0xDD, 0xCD, 0x1F, 0x21, 0x79, 0x52, 0xE5, 0x3C, 0xDC, 0xBF, 0x00, 0x39, + 0x1F, 0x4B, 0xDB, 0xFA, 0x46, 0x57, 0x86, 0xB6, 0x95, 0x4D, 0xC6, 0x33, 0x2D, 0x34, 0x5A, 0x6D, + 0x40, 0x5F, 0xBC, 0xB6, 0xD1, 0x6C, 0xF3, 0xF8, 0xC2, 0xF6, 0x96, 0x54, 0x66, 0xCE, 0xE8, 0x14, + 0x6F, 0xE4, 0xB5, 0xC9, 0x36, 0xEE, 0x55, 0x0C, 0x98, 0xA5, 0x26, 0x10, 0x13, 0x9B, 0x76, 0x49, + 0x53, 0x68, 0x75, 0xFE, 0xD4, 0x1B, 0xBC, 0x48, 0x14, 0xF1, 0xA1, 0xBD, 0x72, 0x0C, 0x93, 0x0D, + 0x6D, 0x34, 0xB9, 0xA7, 0x65, 0x2C, 0xD6, 0xEE, 0xCA, 0x47, 0x25, 0xA3, 0xE1, 0xF9, 0x16, 0x74, + 0x46, 0xA2, 0xDE, 0x49, 0x4B, 0x4F, 0x46, 0x52, 0x5B, 0x06, 0x7D, 0xCE, 0x68, 0xBA, 0xAE, 0xA5, + 0x64, 0x30, 0x9F, 0x2B, 0x3D, 0x13, 0xB2, 0x8B, 0x46, 0xB4, 0x1D, 0x50, 0x39, 0xA1, 0x07, 0xFD, + 0x81, 0xB2, 0xF2, 0x89, 0x7B, 0x7D, 0x1F, 0xBF, 0x74, 0xEA, 0x94, 0x65, 0xC2, 0x9D, 0xDE, 0x33, + 0x31, 0x0D, 0x55, 0x3E, 0xB1, 0x67, 0x52, 0xD9, 0xA2, 0xB6, 0xD1, 0x0B, 0xCA, 0x27, 0xED, 0xF5, + 0xFD, 0xA2, 0xA9, 0xAB, 0x57, 0x4D, 0x83, 0x13, 0xE7, 0xAC, 0xB0, 0x34, 0xBD, 0xC2, 0x1E, 0x82, + 0xE5, 0xD2, 0xDE, 0x67, 0x47, 0xE7, 0xAC, 0x0C, 0xB0, 0xC2, 0xBC, 0x83, 0x60, 0x82, 0xC3, 0x24, + 0x48, 0x9B, 0x0D, 0xEC, 0x73, 0xDA, 0x4A, 0x62, 0x3F, 0xA7, 0xAD, 0xB0, 0xD5, 0xA5, 0xC7, 0xAD, + 0x14, 0x6D, 0x86, 0x4D, 0x45, 0x9B, 0x61, 0x17, 0xBD, 0x28, 0x6D, 0x89, 0x68, 0xD5, 0xCC, 0xA6, + 0xE2, 0xAA, 0x19, 0x39, 0xFA, 0x3C, 0x8C, 0xED, 0x71, 0x01, 0x6A, 0x7F, 0x28, 0xFC, 0x96, 0x62, + 0xF8, 0x0B, 0xE9, 0x27, 0x25, 0xFE, 0x43, 0xAB, 0x6F, 0x66, 0x46, 0xE1, 0xC5, 0xEE, 0x85, 0x2C, + 0x2E, 0xFD, 0x47, 0x45, 0xF1, 0xE4, 0xFE, 0x4B, 0xFA, 0x33, 0xF8, 0x77, 0xC9, 0x74, 0x47, 0xE5, + 0xD3, 0xF5, 0x65, 0x3C, 0xEF, 0xC3, 0x7F, 0xA2, 0x8C, 0x7F, 0x54, 0x3E, 0x7E, 0xB5, 0x18, 0x8F, + 0x51, 0x12, 0xCF, 0x4C, 0xD8, 0x38, 0x43, 0x36, 0xCF, 0xA9, 0x45, 0x9B, 0xE7, 0x02, 0xBA, 0xB5, + 0xC4, 0x7F, 0x53, 0xD1, 0x7F, 0x97, 0xC8, 0xCF, 0xFF, 0x7B, 0x3B, 0xD9, 0x27, 0x9D, 0x99, 0xD1, + 0xD8, 0x4F, 0xDE, 0x4A, 0x3D, 0xB5, 0x68, 0xA5, 0x5E, 0x40, 0xEF, 0x95, 0xF8, 0x6F, 0x2A, 0xFA, + 0x8B, 0x31, 0xA1, 0xE1, 0xC2, 0xCF, 0x64, 0x2D, 0xB2, 0x5D, 0x89, 0x35, 0x23, 0xAF, 0xB0, 0xBF, + 0x83, 0x9D, 0x7A, 0xFA, 0xE2, 0x0E, 0xD9, 0x86, 0xC6, 0x53, 0x5C, 0xE5, 0xE9, 0x01, 0xF1, 0x48, + 0x95, 0x53, 0xDC, 0x8A, 0x4D, 0x8C, 0x1B, 0xAF, 0xE9, 0xCD, 0x4B, 0xFA, 0xD0, 0x76, 0x09, 0x19, + 0x27, 0x7A, 0xAE, 0x6A, 0xDF, 0x87, 0xFB, 0x5E, 0xD9, 0xF7, 0x69, 0xBE, 0xFE, 0x61, 0x1E, 0xDF, + 0x13, 0x39, 0xE0, 0xA3, 0x59, 0x23, 0xBF, 0x16, 0xE2, 0x37, 0xAA, 0xCF, 0x88, 0x91, 0xAA, 0xC9, + 0x9D, 0x07, 0x44, 0x8B, 0x1E, 0x84, 0x4D, 0x27, 0xDA, 0x94, 0xD5, 0x2B, 0x2D, 0x79, 0xCE, 0xFA, + 0x76, 0x47, 0xC9, 0x46, 0xFB, 0x0D, 0xC8, 0x11, 0x25, 0xD6, 0x18, 0x0D, 0x1F, 0xF1, 0xD1, 0x2B, + 0x57, 0x6E, 0x43, 0x6C, 0x4F, 0xF3, 0x2E, 0x36, 0x87, 0xDF, 0x02, 0xEE, 0xEB, 0xE9, 0x0B, 0xC8, + 0xD3, 0xED, 0x30, 0xA6, 0x1F, 0xE5, 0x85, 0x47, 0xC5, 0xBC, 0x81, 0x98, 0x64, 0x41, 0x4B, 0x4C, + 0x14, 0x9E, 0x28, 0xBA, 0x6A, 0x8E, 0x38, 0x35, 0xB2, 0x64, 0xAF, 0x15, 0xC1, 0x86, 0xB6, 0xDC, + 0xDA, 0x53, 0xC8, 0x76, 0x71, 0xE5, 0x9D, 0x9C, 0x32, 0x63, 0x73, 0x32, 0x99, 0xEA, 0xD6, 0xD4, + 0x39, 0x61, 0xA2, 0xDC, 0xAD, 0xA8, 0x68, 0x6F, 0x4C, 0x9D, 0x56, 0x11, 0xAF, 0x74, 0xF9, 0x95, + 0x0D, 0x0D, 0xCD, 0xAD, 0xA9, 0x64, 0xB2, 0xB3, 0xA7, 0x15, 0x26, 0x12, 0xCB, 0x3D, 0xC5, 0xE7, + 0xB1, 0xD9, 0x7C, 0x07, 0x7A, 0x51, 0x6D, 0x7D, 0xE8, 0x57, 0x39, 0x1D, 0xAA, 0x61, 0x99, 0xBB, + 0x06, 0x24, 0x33, 0xAC, 0x13, 0xA5, 0x48, 0x6C, 0x2D, 0xC8, 0xB7, 0x37, 0x7A, 0x6E, 0x1A, 0x09, + 0xFA, 0x62, 0x01, 0xA2, 0x3C, 0xF0, 0xAE, 0x21, 0xB2, 0x24, 0xD9, 0x6C, 0x2F, 0x3B, 0x62, 0x4D, + 0x75, 0xDD, 0x96, 0x44, 0x7D, 0x7C, 0x70, 0xC2, 0xE8, 0x95, 0x7C, 0xC7, 0xD8, 0xCA, 0x18, 0xD7, + 0xE6, 0x70, 0xF9, 0x74, 0xEA, 0xCB, 0xBC, 0x0E, 0x2C, 0x78, 0x3B, 0xD9, 0xD4, 0xDC, 0xA7, 0xAB, + 0x64, 0xAC, 0x54, 0xEC, 0x01, 0xD9, 0x52, 0xD7, 0x8B, 0xC8, 0x35, 0x18, 0xBE, 0x12, 0x52, 0x7E, + 0x5E, 0x5C, 0xCD, 0x2F, 0x23, 0x6C, 0x89, 0xB6, 0x8B, 0x60, 0xDD, 0xC9, 0x55, 0x53, 0xCF, 0x1A, + 0x51, 0xDF, 0xB6, 0x7E, 0xD4, 0xFC, 0x80, 0x5F, 0x39, 0x75, 0xC6, 0xE9, 0xD9, 0x03, 0x9A, 0x9B, + 0x20, 0x83, 0x2B, 0x78, 0x1B, 0xBD, 0x28, 0x67, 0xA8, 0xC0, 0x03, 0xD6, 0x30, 0x3C, 0xD0, 0xDD, + 0x5B, 0x98, 0x94, 0x2A, 0xE5, 0x01, 0xB7, 0x94, 0x07, 0x78, 0x26, 0xFD, 0xE2, 0xF0, 0xD3, 0x4E, + 0x82, 0x73, 0x6D, 0x9E, 0x64, 0x36, 0x7F, 0x49, 0xCE, 0x7F, 0x76, 0xF5, 0xF9, 0xFE, 0x46, 0x33, + 0xB5, 0x51, 0x89, 0xE6, 0x3A, 0x4B, 0xD3, 0xD9, 0x20, 0x27, 0xF6, 0xDD, 0x92, 0x6D, 0xEC, 0xC5, + 0x6A, 0xC8, 0x7F, 0x31, 0xC7, 0xC9, 0xEC, 0xF9, 0x3D, 0xDD, 0x0B, 0xE6, 0xF7, 0x4C, 0x98, 0x37, + 0xAF, 0xAC, 0xB6, 0x3A, 0x2B, 0x1C, 0x3F, 0xA9, 0x63, 0xDC, 0xF8, 0xF6, 0xAE, 0xCE, 0xCE, 0xAE, + 0xDA, 0x86, 0xC6, 0x1A, 0x38, 0x21, 0x63, 0x9F, 0xE4, 0x5A, 0xE9, 0x35, 0x00, 0x4B, 0xD0, 0xDC, + 0xBE, 0xCA, 0x40, 0x0D, 0xC9, 0xF3, 0x8C, 0x64, 0x88, 0x8E, 0xD8, 0x03, 0x8A, 0x27, 0x72, 0x47, + 0x81, 0x4F, 0xCA, 0x5F, 0x8B, 0xA7, 0x74, 0x45, 0xFD, 0xDA, 0xFC, 0xCA, 0x6F, 0x51, 0xAE, 0x47, + 0xE4, 0xF7, 0x5B, 0x8E, 0x0A, 0x36, 0x89, 0x82, 0xCD, 0x44, 0xEB, 0xCF, 0xD2, 0x85, 0xE5, 0x67, + 0x5D, 0x7A, 0x67, 0xFA, 0xB5, 0xD9, 0x1D, 0x33, 0xBB, 0x6B, 0xEA, 0xBB, 0xC2, 0x74, 0x4B, 0x63, + 0x7B, 0x47, 0x45, 0xE3, 0xF8, 0x33, 0x1B, 0xC6, 0xB5, 0x57, 0x54, 0x04, 0x6E, 0x90, 0x3A, 0x7A, + 0x4A, 0x8B, 0x18, 0xA3, 0x79, 0x8C, 0x27, 0xD8, 0xC9, 0x72, 0x16, 0x51, 0xA7, 0x8E, 0x3E, 0x5F, + 0xE3, 0xE8, 0xC9, 0x0A, 0x4D, 0xA6, 0x2B, 0x4F, 0xE6, 0xCD, 0x18, 0xC6, 0xBE, 0x98, 0x3F, 0xCF, + 0xB4, 0xE4, 0x74, 0xCF, 0x8E, 0xFC, 0xA9, 0xA6, 0x50, 0x16, 0xA2, 0x8D, 0xB1, 0x93, 0xEF, 0x6E, + 0xFD, 0xE6, 0xF1, 0x70, 0xFC, 0xB4, 0xA3, 0x2A, 0xB7, 0xF7, 0xC0, 0x91, 0xEC, 0x6D, 0xB5, 0xD2, + 0x5F, 0x80, 0x31, 0x14, 0xCF, 0xA7, 0x99, 0xE4, 0xF3, 0xF0, 0x92, 0xB8, 0xFF, 0x00, 0x77, 0xB8, + 0x6A, 0x1A, 0xC4, 0xFF, 0x9A, 0x47, 0x55, 0x14, 0xF8, 0xE8, 0x94, 0x2E, 0x81, 0x24, 0x5F, 0xB4, + 0x62, 0xDF, 0x7B, 0x59, 0xAA, 0x3D, 0x7F, 0x19, 0xD9, 0xD9, 0x3A, 0x75, 0x46, 0xC7, 0xD8, 0xB6, + 0xC6, 0xB2, 0x54, 0x55, 0xD9, 0xDD, 0xD9, 0x8E, 0xD6, 0xC6, 0xB9, 0xD9, 0xD6, 0xB1, 0xD5, 0xC9, + 0xA6, 0x70, 0xEF, 0xF6, 0xAA, 0xA0, 0xFE, 0x62, 0x4A, 0x5E, 0x11, 0x0F, 0x46, 0x8A, 0xD8, 0x12, + 0x27, 0x9D, 0xCA, 0x1E, 0xF7, 0xC6, 0x42, 0x7B, 0x55, 0xE4, 0xC1, 0xA4, 0x2D, 0x5D, 0x99, 0x1E, + 0xD6, 0xB8, 0xE6, 0xE8, 0x23, 0x4E, 0x68, 0xEF, 0xE0, 0xD7, 0x6E, 0xDB, 0xB6, 0x64, 0x09, 0x15, + 0xAF, 0xF5, 0x7B, 0xB9, 0x7F, 0x46, 0x67, 0x60, 0xF3, 0x2F, 0x13, 0xC5, 0xAA, 0x89, 0x54, 0xA8, + 0x6E, 0xBD, 0x0C, 0x6E, 0x11, 0xDC, 0xE3, 0x44, 0x06, 0xDE, 0xCD, 0xF3, 0x89, 0xAC, 0x18, 0xDC, + 0x46, 0xB8, 0xD7, 0x89, 0xEC, 0x59, 0x70, 0x57, 0x12, 0x39, 0x87, 0xC0, 0x3D, 0x49, 0xE4, 0x7E, + 0x0F, 0x7D, 0xEF, 0x55, 0x44, 0x3E, 0xFA, 0xEB, 0x41, 0x00, 0xB7, 0x8B, 0x28, 0xBC, 0x88, 0x28, + 0x7E, 0x23, 0x51, 0xE2, 0x68, 0x02, 0x45, 0xC0, 0xFD, 0x82, 0x28, 0x55, 0x0F, 0x77, 0x1A, 0xDC, + 0x9B, 0x44, 0xE9, 0x47, 0x89, 0x32, 0xAF, 0x12, 0x95, 0xDD, 0x4D, 0x54, 0xFE, 0x0C, 0x51, 0xF6, + 0x62, 0xA2, 0x8A, 0xB3, 0x88, 0x2A, 0xF1, 0xB9, 0xEA, 0x5D, 0xA2, 0xEA, 0x47, 0xC4, 0xB1, 0xDC, + 0x70, 0x9F, 0x10, 0xD5, 0x21, 0x9E, 0x7A, 0x84, 0x6D, 0xB8, 0x8E, 0xA8, 0x11, 0xAE, 0xE9, 0x69, + 0xA2, 0xE6, 0xAB, 0x89, 0x5A, 0x8E, 0x23, 0x6A, 0x5D, 0x4B, 0x34, 0x02, 0x71, 0xB6, 0x6D, 0x21, + 0x1A, 0x89, 0x84, 0x46, 0x3E, 0x44, 0x34, 0xEA, 0x0C, 0xA2, 0xD1, 0x37, 0x83, 0x3C, 0xEF, 0x24, + 0x1A, 0x7B, 0x19, 0x51, 0x3B, 0xF2, 0xDF, 0x01, 0x2B, 0xA7, 0x03, 0xF9, 0xEC, 0x5C, 0x08, 0xF7, + 0x2B, 0xB8, 0xF7, 0x88, 0xBA, 0x9A, 0x89, 0xC6, 0x21, 0x6F, 0xE3, 0x90, 0x9F, 0xF1, 0xDF, 0x26, + 0xEA, 0x46, 0x5C, 0x90, 0x4A, 0x9A, 0x00, 0xCF, 0x89, 0x28, 0x9B, 0x49, 0xCB, 0x88, 0x26, 0xA7, + 0xE1, 0x90, 0xDE, 0x54, 0x84, 0x9B, 0x8A, 0xFB, 0xA7, 0xDD, 0x4A, 0xD4, 0x8B, 0xF4, 0xFA, 0xD0, + 0xDC, 0xA6, 0xE3, 0xB7, 0xE9, 0x2F, 0x13, 0xCD, 0xB8, 0x9D, 0x68, 0xE6, 0x4E, 0xA2, 0x59, 0xC0, + 0x3C, 0xFB, 0x42, 0xA2, 0x39, 0xD0, 0x20, 0x73, 0x91, 0xDE, 0x3C, 0x94, 0xCF, 0x7C, 0x68, 0x4B, + 0x31, 0x91, 0xB5, 0x00, 0x61, 0x16, 0x7C, 0x40, 0x74, 0x00, 0xB0, 0x2C, 0x6C, 0x87, 0x43, 0x99, + 0x2F, 0x1C, 0x24, 0x3A, 0xF0, 0x12, 0xB8, 0x9B, 0xE0, 0x1E, 0x80, 0x7B, 0x09, 0xEE, 0x63, 0xA2, + 0x45, 0x0E, 0x1C, 0x9A, 0xD3, 0x22, 0xC4, 0xB1, 0x08, 0x71, 0x2C, 0x42, 0x19, 0x2E, 0x3A, 0x87, + 0xE8, 0x20, 0x84, 0x3B, 0xE8, 0x7E, 0xB8, 0x17, 0xE1, 0x3E, 0x24, 0xEA, 0xB7, 0xE0, 0x6A, 0xE1, + 0xBA, 0xE1, 0x80, 0xAB, 0x1F, 0xF9, 0xEF, 0x47, 0x3D, 0xF6, 0x23, 0x1F, 0xFD, 0xC8, 0x4F, 0xFF, + 0xBD, 0x70, 0x28, 0xCF, 0xFE, 0xB7, 0x89, 0x16, 0xA3, 0xFE, 0x16, 0x57, 0xC2, 0x01, 0xDB, 0xE2, + 0x85, 0x43, 0xEE, 0x60, 0x60, 0x59, 0x82, 0x78, 0x0F, 0x41, 0x7C, 0x4B, 0xA7, 0x45, 0x6E, 0x19, + 0xEA, 0x64, 0x39, 0xF2, 0xBB, 0x02, 0x79, 0x5B, 0x79, 0x0A, 0x1C, 0xEA, 0x6E, 0x15, 0xE4, 0x60, + 0xD5, 0x06, 0xA2, 0x43, 0x91, 0xB7, 0x01, 0x7C, 0x1E, 0x58, 0x9F, 0x77, 0xF8, 0x7D, 0x00, 0x65, + 0x77, 0x18, 0xF2, 0xB4, 0x06, 0x75, 0x35, 0x88, 0xFA, 0x1F, 0x04, 0xE6, 0xC1, 0x3E, 0x38, 0xC8, + 0xD6, 0xE1, 0x71, 0x38, 0x94, 0xEF, 0xDA, 0x73, 0xE1, 0xAE, 0x80, 0xC8, 0x41, 0xC6, 0xBE, 0xB0, + 0x95, 0x68, 0x03, 0xAC, 0xD1, 0x0D, 0x1F, 0x47, 0xEE, 0x88, 0x0D, 0x79, 0x87, 0xBC, 0x1C, 0x71, + 0xC9, 0x90, 0x3B, 0xF2, 0xC8, 0xBC, 0x43, 0x7D, 0x1E, 0x79, 0x29, 0x1C, 0xEA, 0x74, 0x23, 0xD2, + 0x3C, 0x0A, 0xB2, 0x71, 0xB4, 0x01, 0x37, 0x07, 0xEE, 0x33, 0xA2, 0x4D, 0xC8, 0xDF, 0x31, 0x48, + 0xF3, 0x98, 0x6F, 0xE7, 0x1D, 0x64, 0xEB, 0x18, 0xC8, 0xCB, 0x31, 0x9F, 0x12, 0x1D, 0x8B, 0x30, + 0xC7, 0xF5, 0xEF, 0xC7, 0xDD, 0xBA, 0x97, 0xC3, 0x7D, 0xC7, 0xE1, 0xBE, 0xE3, 0x70, 0xDF, 0x66, + 0xC8, 0xD2, 0x66, 0xD4, 0xF1, 0x66, 0xC8, 0xFA, 0x66, 0xE4, 0x75, 0x33, 0xF2, 0xBC, 0x19, 0x72, + 0xB4, 0xF9, 0x1A, 0x38, 0xC8, 0xD5, 0x66, 0x94, 0xD7, 0x16, 0x94, 0xC5, 0x16, 0xD4, 0xD3, 0x16, + 0xD4, 0xD3, 0x16, 0xD4, 0xD3, 0x16, 0x94, 0xF5, 0xF1, 0xF8, 0x7E, 0x3C, 0x64, 0x73, 0x2B, 0xBA, + 0x9F, 0x5B, 0xD1, 0x1E, 0xB6, 0xA2, 0x1C, 0x4F, 0x98, 0x04, 0x77, 0x1F, 0xD1, 0x89, 0xC0, 0x7E, + 0xE2, 0x76, 0x71, 0x9E, 0xFD, 0xFF, 0x17, 0x97, 0x3F, 0x13, 0x3E, 0x37, 0x41, 0x36, 0xB8, 0x7D, + 0xAF, 0xFF, 0x2D, 0xD7, 0x15, 0x0B, 0xBB, 0x1C, 0xCA, 0x1F, 0xAC, 0xA2, 0x93, 0x41, 0x26, 0x59, + 0xD0, 0x15, 0x0E, 0x2C, 0x53, 0x0F, 0xF6, 0x59, 0x00, 0x4E, 0x8B, 0x83, 0xBB, 0x93, 0x94, 0x82, + 0x9D, 0x92, 0xA1, 0x32, 0x2A, 0xA7, 0x2C, 0x55, 0x50, 0x25, 0x55, 0x51, 0x35, 0xD5, 0x50, 0x2D, + 0xD5, 0x51, 0x3D, 0x2C, 0xAC, 0x46, 0x6A, 0x12, 0x33, 0x26, 0xB0, 0x04, 0x47, 0x50, 0x1B, 0x7A, + 0x89, 0xA3, 0x68, 0x34, 0x8D, 0x81, 0x95, 0xDF, 0x4E, 0x1D, 0xB0, 0x9E, 0xBA, 0xD0, 0xA8, 0xC6, + 0x53, 0x37, 0xF5, 0xC0, 0x02, 0x9A, 0x48, 0x93, 0x68, 0x32, 0x7A, 0x18, 0x53, 0x69, 0x1A, 0xF5, + 0x52, 0x1F, 0x4D, 0xA7, 0x19, 0xB0, 0xAC, 0x66, 0xD1, 0x6C, 0x9A, 0x43, 0x73, 0x69, 0x1E, 0xCD, + 0x47, 0xE3, 0x38, 0x80, 0x16, 0xD2, 0x81, 0xB4, 0x88, 0x0E, 0xA2, 0x7E, 0x5A, 0x4C, 0x07, 0xD3, + 0x12, 0x3A, 0x84, 0x96, 0xD2, 0x32, 0x5A, 0x4E, 0x2B, 0x68, 0x25, 0xAD, 0xA2, 0xD5, 0xE8, 0xB9, + 0x0C, 0xD0, 0x61, 0xB4, 0x86, 0x06, 0xE9, 0x70, 0x5A, 0x4B, 0xEB, 0xC0, 0x5B, 0x5F, 0xA0, 0x0D, + 0x74, 0x04, 0x1D, 0x49, 0x5F, 0xA4, 0x8D, 0x74, 0x14, 0x1D, 0x4D, 0x9B, 0xE8, 0x18, 0x3A, 0x96, + 0x8E, 0xA3, 0xCD, 0xB4, 0x85, 0x8E, 0xA7, 0xAD, 0x74, 0x02, 0x9D, 0x48, 0x5F, 0xA2, 0x6D, 0x74, + 0x12, 0x7D, 0x99, 0x4E, 0xA6, 0x53, 0xE8, 0x54, 0x3A, 0x8D, 0x4E, 0xA7, 0x33, 0xE8, 0x4C, 0x3A, + 0x8B, 0xCE, 0xA6, 0x73, 0xE8, 0x2B, 0xB4, 0x9D, 0xBE, 0x4A, 0xE7, 0xD2, 0xD7, 0xE8, 0x3C, 0xFA, + 0x3A, 0x9D, 0x0F, 0xAB, 0xEE, 0x42, 0xFA, 0x06, 0x5D, 0x44, 0xDF, 0xA4, 0x8B, 0xE9, 0x5B, 0xF4, + 0x6D, 0xFA, 0x0E, 0x5D, 0x42, 0xDF, 0xA5, 0x4B, 0x69, 0x07, 0x7D, 0x0F, 0xFD, 0xA5, 0xCB, 0xE8, + 0x72, 0xBA, 0x82, 0xFE, 0x83, 0xAE, 0xA4, 0xAB, 0xE8, 0x6A, 0xFA, 0x01, 0x5D, 0x43, 0xD7, 0xD2, + 0x75, 0x74, 0x3D, 0xED, 0xA4, 0x1F, 0xD2, 0x8F, 0xE8, 0x06, 0xBA, 0x91, 0x7E, 0x4C, 0x37, 0xC1, + 0x4E, 0xBE, 0x99, 0x6E, 0xA1, 0x9F, 0xD2, 0xCF, 0x60, 0xA1, 0xFE, 0x9C, 0x7E, 0x41, 0xBF, 0xA4, + 0x5F, 0x81, 0xAD, 0x6F, 0xA7, 0x3B, 0xE8, 0x4E, 0xBA, 0x8B, 0xEE, 0xA6, 0x7B, 0xE8, 0x5E, 0xFA, + 0x35, 0xDD, 0x47, 0xBF, 0xA1, 0xFB, 0xE9, 0xB7, 0xF4, 0x00, 0x3D, 0x08, 0xBB, 0xF0, 0x61, 0x7A, + 0x84, 0x7E, 0x47, 0x8F, 0xD2, 0x63, 0xF4, 0x38, 0x3D, 0x41, 0x4F, 0xD2, 0x53, 0xF4, 0x7B, 0xFA, + 0x03, 0x3D, 0x4D, 0x7F, 0xA4, 0x67, 0xE8, 0x59, 0xD8, 0xB4, 0xCF, 0xD1, 0xF3, 0xF4, 0x02, 0x2C, + 0xF9, 0x3F, 0xD1, 0x4B, 0xF4, 0x67, 0x7A, 0x99, 0xFE, 0x13, 0x9A, 0xE7, 0x15, 0x7A, 0x95, 0xFE, + 0x17, 0xFD, 0x15, 0x7A, 0xF6, 0x75, 0x7A, 0x03, 0x56, 0xEA, 0x5B, 0xF4, 0x36, 0xBD, 0x43, 0xEF, + 0xD2, 0xDF, 0x60, 0x99, 0xBE, 0x4F, 0x1F, 0xD0, 0xDF, 0xE9, 0x43, 0xF4, 0xE5, 0x3E, 0x96, 0x63, + 0xA6, 0xF2, 0x62, 0x8D, 0xF9, 0x13, 0xF9, 0x2B, 0xC5, 0x29, 0xFA, 0xF2, 0x3B, 0xB4, 0x09, 0x15, + 0x8F, 0xFB, 0x67, 0x8A, 0x5C, 0xA9, 0xBB, 0xE7, 0x85, 0x1F, 0x95, 0x98, 0xAA, 0xE9, 0x06, 0xBA, + 0xC3, 0xE2, 0x88, 0x8D, 0x20, 0x8C, 0x27, 0x92, 0xA9, 0x74, 0xA6, 0xAC, 0x3C, 0x5B, 0x51, 0x59, + 0x55, 0x5D, 0x53, 0x2B, 0x36, 0x17, 0x6E, 0x6A, 0x6E, 0x69, 0x1D, 0xD1, 0x36, 0x72, 0xD4, 0xE8, + 0x31, 0x63, 0xDB, 0x3B, 0x3A, 0xBB, 0xC6, 0x8D, 0xEF, 0xEE, 0x99, 0x30, 0x71, 0xD2, 0xE4, 0x29, + 0x53, 0xA7, 0xF5, 0xF6, 0x4D, 0x9F, 0x31, 0x73, 0xD6, 0xEC, 0x39, 0x73, 0xE7, 0xCD, 0x5F, 0x70, + 0xC0, 0xC2, 0x03, 0x17, 0x1D, 0xD4, 0xBF, 0xF8, 0xE0, 0x25, 0x87, 0x2C, 0x5D, 0xB6, 0x7C, 0xC5, + 0xCA, 0x55, 0xAB, 0x0F, 0x1D, 0x38, 0x6C, 0xCD, 0x20, 0xAA, 0x72, 0xDD, 0xFA, 0x2F, 0x6C, 0x38, + 0xE2, 0xC8, 0x2F, 0x6E, 0x3C, 0xEA, 0xE8, 0x4D, 0xC7, 0x1C, 0x7B, 0xDC, 0xE6, 0x2D, 0xC7, 0x6F, + 0x3D, 0xE1, 0xC4, 0x2F, 0x6D, 0x3B, 0xE9, 0xCB, 0x27, 0x9F, 0x72, 0xEA, 0x69, 0xA7, 0x9F, 0x71, + 0xE6, 0x59, 0x67, 0x9F, 0xF3, 0x95, 0xED, 0x5F, 0x3D, 0xF7, 0x6B, 0xE7, 0x7D, 0xFD, 0xFC, 0x0B, + 0x2E, 0xFC, 0xC6, 0x45, 0xDF, 0xBC, 0xF8, 0x5B, 0xDF, 0xFE, 0xCE, 0x25, 0xDF, 0xBD, 0x74, 0xC7, + 0xF7, 0xBE, 0x7F, 0xD9, 0xE5, 0x57, 0xFC, 0xC7, 0x95, 0x57, 0x5D, 0xFD, 0x83, 0x6B, 0xAE, 0xBD, + 0xEE, 0xFA, 0x9D, 0x3F, 0xFC, 0xD1, 0x0D, 0x37, 0xFE, 0xF8, 0xA6, 0x9F, 0xDC, 0x7C, 0xCB, 0x4F, + 0x7F, 0x76, 0xEB, 0xCF, 0x7F, 0xF1, 0xCB, 0x5F, 0xDD, 0x76, 0xFB, 0x1D, 0x77, 0xDE, 0x75, 0xF7, + 0x3D, 0xF7, 0xFE, 0xFA, 0xBE, 0xDF, 0xDC, 0xFF, 0xDB, 0x07, 0x1E, 0x7C, 0xE8, 0xE1, 0x47, 0x7E, + 0xF7, 0xE8, 0x63, 0x8F, 0x3F, 0xF1, 0xE4, 0x53, 0xBF, 0xFF, 0xC3, 0xD3, 0x7F, 0x7C, 0xE6, 0xD9, + 0x5D, 0xCF, 0x3D, 0xFF, 0xC2, 0x8B, 0x7F, 0x7A, 0xE9, 0xCF, 0x2F, 0xFF, 0x27, 0x50, 0xC6, 0x14, + 0x61, 0xA5, 0x2F, 0x82, 0x64, 0xAA, 0x68, 0x01, 0xA7, 0x51, 0x8E, 0x75, 0xB0, 0x19, 0x6C, 0x09, + 0x3B, 0x9C, 0x6D, 0x63, 0xA7, 0xB2, 0xD3, 0xD9, 0xC5, 0xFC, 0x76, 0xFE, 0x20, 0x7F, 0x98, 0xBF, + 0xA8, 0xFC, 0x40, 0xF9, 0xA1, 0x72, 0x6F, 0x6D, 0xB2, 0x36, 0x5B, 0x5B, 0x5D, 0x5B, 0x5F, 0xDB, + 0x5C, 0xDB, 0x5E, 0x3B, 0xA9, 0xAE, 0xBE, 0x9E, 0xD7, 0x6B, 0xF5, 0x7E, 0x7D, 0xBC, 0x3E, 0x55, + 0x9F, 0xAD, 0xAF, 0xAE, 0x1F, 0x59, 0x3F, 0xAF, 0x7E, 0xB0, 0xFE, 0x0B, 0x4D, 0x8F, 0xBC, 0xC7, + 0x45, 0x4F, 0x00, 0xED, 0xE5, 0x4A, 0xC4, 0x37, 0x9D, 0x1D, 0xCC, 0x06, 0x4B, 0xE2, 0x7B, 0x00, + 0xF1, 0xED, 0xCA, 0xC7, 0x97, 0xA8, 0x2D, 0xAB, 0xAD, 0xAC, 0xAD, 0x95, 0xF1, 0x4D, 0xDC, 0x23, + 0xBE, 0xF2, 0x62, 0x7C, 0xEB, 0x11, 0x9F, 0x1C, 0x2F, 0xFF, 0x6F, 0xBC, 0x18, 0x2D, 0x62, 0x16, + 0x7B, 0x08, 0x7F, 0x8F, 0xB0, 0x47, 0xD9, 0xE3, 0x25, 0x7F, 0x4F, 0xE2, 0x6F, 0x57, 0xFE, 0xEF, + 0x79, 0xF6, 0x12, 0xFB, 0x0B, 0xFB, 0xAB, 0xFC, 0x7B, 0x7D, 0x8F, 0xBF, 0x37, 0x8B, 0x7F, 0x6F, + 0xB3, 0xB7, 0xA5, 0xA4, 0xFD, 0x4F, 0xE6, 0x94, 0x1B, 0xD1, 0xA6, 0x05, 0x27, 0xDC, 0x85, 0x56, + 0xFF, 0x3A, 0x98, 0xE1, 0x42, 0x70, 0xC2, 0xE5, 0x68, 0xDB, 0xD7, 0x20, 0xF7, 0xE7, 0xA1, 0x05, + 0x9E, 0x0D, 0x4E, 0x10, 0xED, 0xEA, 0x02, 0x70, 0xC2, 0xB9, 0x68, 0xBF, 0x2F, 0xA1, 0x9D, 0x5D, + 0x81, 0x96, 0xFF, 0x11, 0x5A, 0xDA, 0xC7, 0x60, 0x84, 0x1F, 0xA3, 0x1D, 0x3F, 0x08, 0x06, 0x10, + 0xDC, 0x74, 0x11, 0xD8, 0xE9, 0x77, 0xE0, 0xA7, 0x87, 0xD0, 0xB2, 0x9F, 0xC8, 0xB7, 0xEC, 0x37, + 0xC0, 0x56, 0x7F, 0x90, 0xAD, 0xFB, 0x27, 0x60, 0xAD, 0xF7, 0xC0, 0x32, 0xCF, 0xC8, 0x36, 0x7E, + 0x24, 0xDA, 0xEE, 0x3B, 0xE0, 0xA0, 0x8D, 0xE0, 0xB1, 0xA3, 0xC0, 0x61, 0x47, 0x83, 0xC5, 0xAE, + 0x04, 0x8F, 0x6D, 0x06, 0x93, 0x09, 0x1E, 0x3B, 0x01, 0x4C, 0x26, 0x78, 0xEC, 0x4D, 0x30, 0xD9, + 0x97, 0xC1, 0x65, 0x27, 0x83, 0xC7, 0x4E, 0x01, 0xAB, 0x5C, 0x05, 0x2E, 0x3B, 0x4D, 0xB2, 0xD9, + 0xDB, 0x68, 0xF7, 0xB7, 0x83, 0x29, 0x04, 0x2B, 0x08, 0xF6, 0x11, 0xCC, 0x70, 0x87, 0xE4, 0x86, + 0xEB, 0xC0, 0x17, 0xBB, 0xC0, 0x17, 0x05, 0xFE, 0x78, 0x19, 0x5C, 0xB2, 0x03, 0x1C, 0xF6, 0x7D, + 0xC9, 0x50, 0x82, 0x9D, 0xEE, 0x97, 0x3C, 0xF5, 0x5B, 0x30, 0xE2, 0x7D, 0xE0, 0xC2, 0x1B, 0xC0, + 0x48, 0x82, 0xA3, 0xCE, 0x07, 0xEB, 0xED, 0x04, 0xEB, 0xFD, 0x0D, 0xAC, 0xF5, 0x1B, 0xF0, 0xDC, + 0xC5, 0x60, 0xBF, 0xEB, 0xC1, 0x8D, 0x82, 0x13, 0x6F, 0x03, 0x3B, 0x81, 0xC3, 0xCE, 0xFE, 0x54, + 0xA9, 0x95, 0xBD, 0x64, 0x62, 0xD9, 0xBC, 0x9B, 0x85, 0x7E, 0xEE, 0x77, 0x68, 0x0A, 0x9F, 0x47, + 0x0D, 0x7C, 0x1B, 0xD5, 0x2A, 0x4F, 0x53, 0x83, 0x62, 0xD0, 0x08, 0x30, 0xCB, 0x3C, 0x36, 0x92, + 0x26, 0xC2, 0x11, 0x3B, 0x09, 0xBF, 0xAD, 0xA0, 0xB1, 0xF0, 0x6B, 0x60, 0x37, 0xA3, 0xFE, 0x3F, + 0xA3, 0x91, 0x7C, 0x29, 0xE9, 0x3C, 0xA4, 0x14, 0x6B, 0x23, 0x83, 0xFD, 0x06, 0x5D, 0xDF, 0x23, + 0xD0, 0x47, 0x70, 0x29, 0xCE, 0xAE, 0x47, 0x27, 0xE8, 0x49, 0xCA, 0xB0, 0xAB, 0xE0, 0xFF, 0x30, + 0x25, 0xD8, 0x9F, 0x29, 0xCB, 0x12, 0x34, 0x19, 0x69, 0x75, 0x8B, 0x38, 0x0A, 0x8E, 0x7D, 0x44, + 0x29, 0xE4, 0xA5, 0x8A, 0xBF, 0x96, 0x7B, 0x83, 0x9F, 0x92, 0x7B, 0x86, 0x2F, 0xA3, 0x0A, 0xFE, + 0x10, 0xDE, 0x07, 0x73, 0x6F, 0xF1, 0x4E, 0xB8, 0x9D, 0xF8, 0xED, 0x43, 0x9A, 0xC3, 0xC6, 0x91, + 0xC7, 0x26, 0x21, 0xAD, 0x6B, 0xC8, 0xE3, 0xAD, 0xE4, 0xC5, 0x42, 0x6A, 0x53, 0x3A, 0x10, 0xEE, + 0x39, 0xAA, 0xE5, 0x13, 0x73, 0x7F, 0x42, 0x4F, 0xAF, 0x82, 0x5F, 0x8D, 0xF7, 0x8D, 0x54, 0xC3, + 0xAF, 0xCA, 0xBD, 0xA5, 0x34, 0x81, 0x10, 0xDF, 0xCF, 0xBD, 0x1A, 0x7B, 0x26, 0xF7, 0x2A, 0x7F, + 0x14, 0xF7, 0x7D, 0x80, 0xDF, 0x96, 0x53, 0x35, 0x9B, 0x4C, 0x03, 0xEC, 0x89, 0xDC, 0x5B, 0x6C, + 0x72, 0xEE, 0x1F, 0x48, 0xBF, 0x97, 0x37, 0xE4, 0xFE, 0xC1, 0xD2, 0xB9, 0x1C, 0x9F, 0x4D, 0x29, + 0x3E, 0x2E, 0xF7, 0x3A, 0xFB, 0x15, 0xDE, 0x27, 0x03, 0xEB, 0x7D, 0x54, 0xC9, 0x56, 0xE3, 0x9E, + 0xAD, 0x94, 0xE0, 0xEB, 0x72, 0xAF, 0xB0, 0x8A, 0xDC, 0x07, 0xC2, 0xF1, 0xF6, 0xDC, 0xEB, 0xF4, + 0x69, 0xEE, 0x55, 0xE5, 0x49, 0xE4, 0x4D, 0x8C, 0xB4, 0x7D, 0x8A, 0x74, 0x9B, 0x90, 0x46, 0x25, + 0xC2, 0x7F, 0x1D, 0xF1, 0xDE, 0x46, 0xF5, 0xAC, 0x0B, 0xBF, 0x6D, 0x40, 0xD8, 0x51, 0x08, 0xF7, + 0x2D, 0xFC, 0x36, 0x16, 0x79, 0x5E, 0x8A, 0xDF, 0xEE, 0x47, 0x98, 0xC9, 0x68, 0x63, 0x2F, 0x51, + 0xAF, 0x78, 0x47, 0xFA, 0xB3, 0x25, 0x6E, 0xE1, 0x04, 0x6E, 0x60, 0x2E, 0x60, 0x92, 0xF9, 0x17, + 0x79, 0x1A, 0xC6, 0x89, 0x3C, 0xCA, 0xFC, 0x95, 0xBA, 0x7C, 0xFE, 0xF2, 0xEE, 0xB5, 0x42, 0xDE, + 0xF6, 0x76, 0x32, 0x5F, 0x25, 0xAE, 0x48, 0x27, 0xF7, 0xE1, 0xB7, 0x33, 0x90, 0xA6, 0x9E, 0x7B, + 0x9C, 0x7D, 0x28, 0xD7, 0x79, 0x11, 0xBF, 0x39, 0xF7, 0x27, 0x51, 0x37, 0xD2, 0xBD, 0x44, 0xD3, + 0x58, 0x1A, 0x2D, 0xF9, 0xB3, 0xDC, 0xDB, 0x22, 0xAF, 0xB1, 0xC6, 0xDC, 0x2B, 0xC8, 0xA7, 0x27, + 0xF2, 0x22, 0xC3, 0x8A, 0x7A, 0x12, 0x65, 0xB5, 0x1A, 0x78, 0x45, 0xDC, 0x88, 0x43, 0x96, 0x1B, + 0xEA, 0x4C, 0x96, 0x1B, 0xEA, 0x85, 0x0D, 0x90, 0xCB, 0x3A, 0x28, 0x60, 0xDF, 0xA7, 0x7A, 0xA5, + 0x0C, 0x18, 0x3E, 0xCD, 0x7D, 0x82, 0xFA, 0xF7, 0x99, 0x68, 0xF9, 0x22, 0x8E, 0x4F, 0xC4, 0x0C, + 0x26, 0xA8, 0x48, 0x60, 0x2F, 0xC9, 0x9B, 0xE2, 0xD0, 0x48, 0x21, 0xA3, 0xC5, 0xB2, 0x42, 0xF9, + 0xC4, 0x5A, 0x51, 0x46, 0x69, 0x60, 0x12, 0x9D, 0x66, 0x58, 0x69, 0xEC, 0x19, 0xC8, 0xA4, 0x70, + 0x4A, 0xE4, 0xE4, 0x7D, 0x15, 0x90, 0x57, 0x94, 0xBB, 0xA8, 0x7B, 0xBA, 0x3E, 0xB7, 0x84, 0x6B, + 0x05, 0x7D, 0xBA, 0xD7, 0xF5, 0x99, 0x5C, 0x2D, 0x54, 0xBC, 0x64, 0x1A, 0x42, 0xFE, 0x0A, 0xEF, + 0x70, 0x52, 0xFE, 0xC6, 0xA1, 0xE7, 0x36, 0x2E, 0xF7, 0xBE, 0xF8, 0x2C, 0xE5, 0x4E, 0xD4, 0x93, + 0x48, 0x23, 0x5F, 0x5F, 0x05, 0x27, 0xEB, 0x20, 0x2D, 0xDD, 0xD3, 0x70, 0x4F, 0xC1, 0xBD, 0x8C, + 0x34, 0x56, 0xA0, 0xFC, 0x6C, 0x7C, 0xFE, 0x04, 0xEE, 0x31, 0x7C, 0xAE, 0x15, 0x61, 0xFE, 0x1B, + 0x35, 0x42, 0xC9, 0x05, 0x5D, 0x73, 0x15, 0xB0, 0x06, 0x60, 0xB6, 0x5B, 0xF9, 0xE3, 0xB9, 0xF7, + 0xD8, 0xA3, 0xA8, 0xD1, 0xEB, 0x69, 0x16, 0xBF, 0x0B, 0x8C, 0xF7, 0x29, 0xB8, 0xB5, 0x1F, 0x5C, + 0xBA, 0x1C, 0x1C, 0x3A, 0x08, 0xD6, 0x3A, 0x0E, 0x61, 0x4F, 0x03, 0xAB, 0xFD, 0x52, 0x19, 0x93, + 0x3B, 0x4B, 0xB2, 0x72, 0x2F, 0xDA, 0xE6, 0x3D, 0xD2, 0x36, 0xDB, 0x0C, 0x06, 0xDB, 0x06, 0xE6, + 0x58, 0x47, 0x1B, 0xF9, 0x15, 0xB9, 0xBF, 0xD1, 0x97, 0x94, 0x30, 0xF7, 0x35, 0xB0, 0xF6, 0x3C, + 0x70, 0xAB, 0x98, 0xAD, 0x3C, 0x86, 0x3F, 0xC2, 0xBE, 0x4B, 0x8F, 0xB1, 0x7F, 0x82, 0xBF, 0xAF, + 0xCE, 0xDD, 0x25, 0x38, 0x0F, 0x2C, 0xF1, 0x0F, 0xF2, 0x50, 0xE3, 0x73, 0x73, 0xEF, 0xA2, 0x6B, + 0x3D, 0x27, 0xF7, 0x3E, 0x38, 0x30, 0xB2, 0xD6, 0xCE, 0xE4, 0x0B, 0xA9, 0x3B, 0xF7, 0x08, 0x38, + 0x72, 0x0B, 0xB4, 0xC9, 0x8D, 0x7C, 0x55, 0xEE, 0x6D, 0xEA, 0xC9, 0x3D, 0x0C, 0x26, 0x5A, 0xC4, + 0x0F, 0x04, 0x47, 0x0B, 0x8B, 0x2C, 0x4E, 0xDF, 0x60, 0x6F, 0x91, 0xC1, 0x39, 0xBB, 0x14, 0x6C, + 0xFC, 0x20, 0x7F, 0x0A, 0x5A, 0xE0, 0x20, 0xF0, 0x58, 0x3D, 0xF8, 0x7F, 0x15, 0x18, 0x6C, 0x01, + 0x58, 0xFF, 0x2C, 0xFE, 0x7C, 0xEE, 0xC3, 0x02, 0xFF, 0xF3, 0x27, 0xC0, 0x7A, 0x3A, 0xBF, 0x0F, + 0xCC, 0xE8, 0xD0, 0xD1, 0xFC, 0x21, 0xC9, 0xB2, 0x36, 0xFF, 0x75, 0xEE, 0x23, 0x69, 0x53, 0x9E, + 0x08, 0xDE, 0x3D, 0x05, 0x08, 0x2E, 0x05, 0x33, 0xC2, 0x76, 0xE3, 0xF7, 0x83, 0x81, 0xCF, 0xC8, + 0x5B, 0x87, 0xDF, 0x07, 0x33, 0x7C, 0x17, 0xDC, 0x3D, 0x11, 0x1A, 0x6E, 0x1D, 0x1D, 0xCB, 0x77, + 0xF1, 0x67, 0x73, 0x75, 0xD0, 0x7E, 0x29, 0xFA, 0x02, 0xFF, 0x23, 0xF4, 0xC9, 0x04, 0xE8, 0xF9, + 0x57, 0xF8, 0xCB, 0xB4, 0x4C, 0xEE, 0x65, 0x3E, 0x1D, 0x9C, 0xBB, 0x9E, 0xFF, 0x2E, 0xD7, 0x03, + 0x4D, 0xB1, 0x16, 0xDA, 0x45, 0x68, 0xA5, 0xFB, 0x20, 0xF1, 0xBF, 0xCF, 0xBD, 0x03, 0x09, 0xB8, + 0x05, 0xDA, 0xB2, 0x99, 0xBF, 0x90, 0x7B, 0x9E, 0xBF, 0x05, 0xEE, 0xBD, 0x0C, 0x5A, 0x60, 0x27, + 0x7F, 0x1B, 0xE5, 0xD7, 0x0E, 0xCD, 0x37, 0x37, 0x77, 0x0E, 0x4D, 0xE7, 0x17, 0x33, 0x8B, 0x1A, + 0x72, 0x03, 0xB9, 0x49, 0xFC, 0xE7, 0xBC, 0x8A, 0xBD, 0x0B, 0x99, 0xEB, 0x50, 0x32, 0x74, 0x3B, + 0x7B, 0x93, 0x7F, 0x0B, 0x5A, 0xF5, 0x70, 0xF6, 0x4E, 0xEE, 0x0D, 0xE4, 0xF2, 0x4E, 0xF6, 0x5E, + 0xAE, 0x89, 0x5F, 0x9F, 0x4B, 0x2B, 0x29, 0x68, 0xDA, 0x6C, 0xAE, 0x15, 0x79, 0xCB, 0x88, 0x59, + 0x62, 0x68, 0xE9, 0x2B, 0xA0, 0xDF, 0x96, 0x42, 0xFB, 0x5D, 0xC8, 0x37, 0xA1, 0xDD, 0x9C, 0xCF, + 0x5E, 0x61, 0x7F, 0x43, 0x5B, 0xD5, 0xE8, 0xA7, 0xB9, 0x2A, 0xE8, 0x93, 0x6B, 0xE8, 0x06, 0xAE, + 0xE4, 0xCE, 0x63, 0x87, 0xD0, 0x75, 0xCA, 0x16, 0xE5, 0x6C, 0x68, 0xE5, 0xB3, 0xA0, 0x83, 0x27, + 0xE7, 0xE6, 0x2B, 0xA7, 0x2A, 0x27, 0xF1, 0x6B, 0xF9, 0x8F, 0xF8, 0x2D, 0xFC, 0x25, 0xD4, 0xF7, + 0x57, 0x90, 0xF3, 0x9F, 0x43, 0x9F, 0xED, 0xA0, 0x23, 0x79, 0x7F, 0x6E, 0x3B, 0x4A, 0xE3, 0x00, + 0xE8, 0x94, 0xAF, 0xF1, 0x7F, 0xD2, 0xCF, 0x78, 0x05, 0x34, 0xCB, 0x24, 0xC8, 0x40, 0x9F, 0xB4, + 0x70, 0xBF, 0x0E, 0xED, 0xB1, 0x13, 0xBA, 0x71, 0x19, 0xB4, 0xEC, 0x26, 0xC8, 0x89, 0xD0, 0xCD, + 0x67, 0xC3, 0x06, 0xFA, 0x2A, 0x64, 0xA2, 0x87, 0xCE, 0x63, 0x9D, 0xBC, 0x8C, 0xB7, 0x29, 0x9B, + 0x80, 0x77, 0x04, 0x2D, 0xCC, 0xBD, 0x9E, 0xBB, 0x27, 0x57, 0x8E, 0xFC, 0xF5, 0x83, 0x81, 0x1F, + 0x63, 0x67, 0xF2, 0xBB, 0xD9, 0x09, 0xB0, 0x26, 0x02, 0xD8, 0x0C, 0xF7, 0xF3, 0xAA, 0xDC, 0x14, + 0x9E, 0xC8, 0x8D, 0xA7, 0x72, 0x7E, 0xA7, 0xB2, 0x8C, 0xDF, 0xCE, 0x62, 0xB4, 0x81, 0x1D, 0x06, + 0x59, 0xAC, 0x66, 0x6F, 0xB0, 0xD7, 0xA8, 0x92, 0xDF, 0x04, 0xD6, 0x58, 0x00, 0x4D, 0xF3, 0x10, + 0x4B, 0xB3, 0xBF, 0xF3, 0xD1, 0xBC, 0x8B, 0xEF, 0xE0, 0xF3, 0x78, 0x1D, 0x6D, 0xE7, 0x49, 0xE8, + 0xEC, 0x19, 0x3C, 0x01, 0xDB, 0x42, 0x5C, 0xF7, 0xC0, 0x46, 0x51, 0x87, 0x11, 0x78, 0xF6, 0xAF, + 0xDB, 0xC3, 0xF4, 0xA3, 0xB7, 0x1E, 0x0F, 0x4C, 0xB5, 0xEF, 0x71, 0xE5, 0xEC, 0x1C, 0xFA, 0xFC, + 0x28, 0x9D, 0x37, 0xE5, 0x0F, 0xE8, 0xEB, 0xD2, 0xA7, 0xA6, 0xAD, 0x93, 0xA2, 0x08, 0x5B, 0xD9, + 0xD4, 0x39, 0x3E, 0xA8, 0x3C, 0xC6, 0x55, 0x55, 0x89, 0x29, 0x6A, 0x4C, 0x5C, 0x5C, 0x51, 0x71, + 0xE9, 0xBA, 0xA6, 0x8A, 0x73, 0x2C, 0x75, 0x45, 0xD1, 0x54, 0x53, 0xD7, 0x55, 0x0D, 0x97, 0xAE, + 0xDB, 0x9A, 0x2E, 0x43, 0xAA, 0x78, 0xC5, 0xD4, 0x18, 0x7E, 0x13, 0xF7, 0x9B, 0xE2, 0x8E, 0x98, + 0xF8, 0x66, 0xA8, 0xE2, 0x5C, 0x4D, 0x05, 0xB7, 0x8B, 0x28, 0x74, 0x55, 0x8D, 0x7E, 0xC1, 0xA5, + 0x88, 0x94, 0xE4, 0x25, 0x62, 0x82, 0x21, 0x8B, 0xD8, 0x09, 0x31, 0x9A, 0x0A, 0x57, 0x2D, 0x3D, + 0x46, 0x1A, 0xD2, 0x43, 0xDC, 0x8A, 0x86, 0x9C, 0xE1, 0x3E, 0x31, 0x0E, 0xA6, 0x23, 0x98, 0xAE, + 0x20, 0x1A, 0x4B, 0x17, 0x79, 0xE3, 0x9C, 0x74, 0x55, 0xE7, 0x51, 0x79, 0x08, 0xEB, 0x1F, 0xDF, + 0x10, 0x10, 0x97, 0x1E, 0x5D, 0xE2, 0xA3, 0xC2, 0xE5, 0xFF, 0xFD, 0x95, 0x8C, 0xE5, 0x18, 0x12, + 0xBB, 0xA6, 0x59, 0x86, 0x7C, 0x57, 0x24, 0x06, 0x81, 0x05, 0x7F, 0x22, 0x79, 0x71, 0xAA, 0x87, + 0x0E, 0xA8, 0x78, 0x19, 0xE2, 0xE0, 0x4B, 0x0B, 0xDF, 0x50, 0x18, 0xBA, 0x61, 0x38, 0xBA, 0xA1, + 0x29, 0xAA, 0x08, 0xAE, 0x69, 0x31, 0xF9, 0x5F, 0xE4, 0xD6, 0xD2, 0xF2, 0xD8, 0x35, 0x13, 0xB7, + 0x22, 0x79, 0x11, 0x5A, 0x33, 0x10, 0x56, 0x5E, 0x31, 0x81, 0x58, 0xE4, 0x48, 0x2B, 0xC1, 0x2E, + 0x4A, 0x96, 0x10, 0xA3, 0x05, 0x6F, 0x1B, 0xD8, 0x71, 0x83, 0x66, 0x68, 0x11, 0x76, 0x43, 0x60, + 0x37, 0xC8, 0x40, 0x30, 0x43, 0x00, 0xB3, 0x0D, 0x71, 0x2B, 0x10, 0x19, 0x9A, 0x91, 0xC7, 0x2E, + 0xD0, 0xE9, 0x22, 0x87, 0x11, 0x76, 0xA4, 0x65, 0x18, 0xCA, 0xD0, 0xB5, 0x3F, 0xEC, 0xB6, 0x67, + 0x02, 0x7B, 0x2C, 0xA6, 0xE9, 0xB6, 0x29, 0xB0, 0xA3, 0x50, 0x81, 0x0F, 0xD8, 0xA3, 0xAC, 0xC9, + 0x62, 0xD4, 0x4C, 0x43, 0x44, 0x98, 0xC7, 0x6E, 0x9B, 0x48, 0x14, 0xBE, 0xA6, 0xE1, 0x19, 0x46, + 0x3E, 0xB8, 0xA8, 0x27, 0x35, 0x26, 0x0A, 0x5B, 0x53, 0x6C, 0x5D, 0x22, 0x14, 0xA5, 0x24, 0xEA, + 0x8E, 0x2B, 0xBA, 0x78, 0x94, 0xC8, 0x34, 0xCC, 0x08, 0xBB, 0x5A, 0xC0, 0xAE, 0x6B, 0x91, 0xF4, + 0xE8, 0x3A, 0xB0, 0xE3, 0x0B, 0x19, 0xA6, 0x69, 0xC3, 0xDB, 0x31, 0x50, 0x0C, 0xBA, 0x48, 0x10, + 0x5F, 0x20, 0x55, 0xB8, 0x2F, 0x26, 0xEC, 0x71, 0x04, 0x33, 0x15, 0x80, 0x72, 0x4C, 0x45, 0xD6, + 0x30, 0x7C, 0x0C, 0xF1, 0x88, 0x57, 0x1E, 0x3B, 0x00, 0x47, 0x95, 0x6D, 0x18, 0x48, 0xCB, 0x34, + 0x3F, 0x07, 0x76, 0xC7, 0xB7, 0x04, 0x76, 0x55, 0x17, 0x71, 0xC6, 0xF0, 0x2E, 0xC1, 0xC4, 0x04, + 0x76, 0x21, 0xE5, 0x11, 0x76, 0x0B, 0xE0, 0x21, 0xEA, 0x86, 0x19, 0x8B, 0x19, 0xBA, 0x63, 0x99, + 0x02, 0x8D, 0x61, 0x99, 0xBE, 0x69, 0xEA, 0x31, 0x4D, 0x40, 0xD6, 0x85, 0xC4, 0xC5, 0x64, 0x6E, + 0x15, 0x47, 0xD4, 0x80, 0x2A, 0x4A, 0xC2, 0x86, 0x77, 0x0C, 0xC5, 0x89, 0x60, 0xBA, 0x65, 0x5A, + 0x91, 0x2C, 0x0E, 0x8F, 0xDD, 0x10, 0xD8, 0x2D, 0xCB, 0x81, 0xB7, 0x6B, 0xAA, 0x24, 0x4B, 0x0B, + 0xC0, 0x75, 0xE4, 0xC8, 0x12, 0xD8, 0xD1, 0x13, 0x91, 0xD8, 0x01, 0xCA, 0x35, 0x63, 0xB2, 0x86, + 0xE1, 0x63, 0x96, 0x60, 0x37, 0x45, 0x0E, 0x45, 0x7B, 0x32, 0x4D, 0xA4, 0x65, 0x59, 0x9F, 0x03, + 0xBB, 0x1B, 0x58, 0x84, 0x1B, 0x54, 0xC3, 0x70, 0x2D, 0x81, 0x1D, 0x02, 0xA5, 0x18, 0x40, 0x04, + 0x2C, 0x40, 0xAF, 0x01, 0x2C, 0xF2, 0x61, 0x59, 0xA2, 0x30, 0x75, 0xD3, 0x42, 0xCC, 0xBA, 0x67, + 0x23, 0x19, 0x14, 0xAD, 0x65, 0x05, 0xA6, 0x65, 0x00, 0x3B, 0x82, 0x1B, 0x12, 0xAF, 0x61, 0xC4, + 0x20, 0x37, 0xAE, 0x10, 0x0A, 0x55, 0x78, 0x8B, 0x36, 0x01, 0xEC, 0x86, 0xB8, 0xDD, 0x46, 0x58, + 0x79, 0x45, 0x82, 0x1F, 0x13, 0xA5, 0x28, 0x6B, 0x17, 0x17, 0x91, 0x10, 0x24, 0x42, 0x8C, 0x6E, + 0x4C, 0x31, 0x3C, 0x53, 0x23, 0x13, 0xBE, 0x88, 0x1B, 0xF2, 0x0E, 0xEC, 0x80, 0x84, 0x3E, 0x98, + 0x58, 0x6F, 0x66, 0xC5, 0x2C, 0xCB, 0xF4, 0xAC, 0x98, 0x11, 0x61, 0x37, 0x2C, 0xAE, 0x17, 0xB1, + 0xE3, 0x9B, 0x48, 0xBF, 0x88, 0x3D, 0xE2, 0x15, 0xF9, 0x7F, 0x7F, 0xD8, 0xBD, 0xD0, 0x06, 0x76, + 0x55, 0x33, 0x4C, 0xCF, 0x96, 0x65, 0x10, 0x81, 0xD1, 0x54, 0x59, 0x2D, 0x7A, 0x84, 0xDD, 0x46, + 0xC5, 0x8B, 0x17, 0x42, 0x98, 0x86, 0x6F, 0x23, 0x19, 0x94, 0xBF, 0x6D, 0x87, 0x96, 0x2D, 0x83, + 0x1B, 0x78, 0xA1, 0x79, 0xAA, 0xA6, 0x90, 0x8B, 0x98, 0x27, 0x9A, 0x1B, 0xE0, 0x99, 0x86, 0x6B, + 0x14, 0xB1, 0x9B, 0x36, 0xC2, 0x0E, 0x87, 0x1D, 0x11, 0x99, 0xC0, 0x8E, 0x3A, 0x23, 0xCB, 0xB6, + 0x3D, 0x78, 0xFB, 0x96, 0x46, 0x48, 0xCC, 0xB4, 0x11, 0x9B, 0x09, 0xF9, 0x13, 0xD2, 0x83, 0xDE, + 0xA7, 0x8D, 0x60, 0x36, 0xB0, 0x5B, 0xBE, 0x2D, 0x6E, 0x05, 0x22, 0xDB, 0xB0, 0xF3, 0xD8, 0x05, + 0x3A, 0x00, 0x16, 0xE9, 0xC7, 0x10, 0x04, 0x69, 0xD9, 0x76, 0x6C, 0xE8, 0xDA, 0x1F, 0x76, 0x3F, + 0xE1, 0x48, 0xEC, 0xA6, 0xE9, 0x3B, 0x08, 0xA6, 0x99, 0x31, 0x91, 0x6B, 0x90, 0xAB, 0xA1, 0x09, + 0x4A, 0x13, 0xC5, 0x68, 0x1A, 0x0E, 0xC0, 0xDB, 0x02, 0xBB, 0xAA, 0x5A, 0x46, 0xE0, 0xA0, 0x0E, + 0x91, 0x92, 0x63, 0x27, 0x6C, 0xDB, 0x84, 0x7C, 0x20, 0xB8, 0x6C, 0x13, 0x79, 0xEC, 0xBE, 0xA8, + 0x34, 0x4D, 0x78, 0x7B, 0x06, 0x3C, 0xD1, 0x60, 0x11, 0xCC, 0x74, 0x6C, 0xC7, 0x94, 0x97, 0x44, + 0x2C, 0xEB, 0x47, 0x16, 0x45, 0x84, 0x5D, 0x47, 0x9D, 0x81, 0x76, 0x1D, 0x1F, 0xDE, 0x01, 0x34, + 0x8F, 0x2C, 0x5B, 0x00, 0x87, 0xCE, 0xD0, 0x1C, 0xC3, 0x10, 0xD8, 0x1D, 0x04, 0x73, 0x62, 0x00, + 0x15, 0x38, 0xAA, 0x94, 0x6E, 0xF8, 0xD8, 0xE8, 0x8D, 0x15, 0xB0, 0xDB, 0xB8, 0x41, 0xAA, 0x18, + 0xDB, 0x46, 0x5A, 0x8E, 0xF3, 0x39, 0xB0, 0x07, 0x49, 0x97, 0x04, 0xDD, 0x9A, 0x56, 0xE0, 0x80, + 0x82, 0x35, 0x2B, 0xA6, 0xC7, 0x2C, 0x03, 0xB5, 0x2E, 0xAB, 0xC5, 0x80, 0xC8, 0xA1, 0xD6, 0x5C, + 0x47, 0x14, 0xA6, 0x69, 0x3B, 0x88, 0xD9, 0x0C, 0x5D, 0x24, 0x8A, 0xA2, 0x75, 0x9D, 0xA4, 0xED, + 0x58, 0xC0, 0x6E, 0x99, 0x28, 0x20, 0x60, 0xD7, 0x2C, 0x4B, 0x55, 0xCD, 0x58, 0x80, 0x5A, 0x36, + 0x35, 0xE1, 0xED, 0xA3, 0x8D, 0x0B, 0xA1, 0x75, 0x70, 0xBB, 0xEB, 0xB8, 0x25, 0xD8, 0x45, 0x1E, + 0xA3, 0x36, 0x80, 0xE8, 0xAD, 0x3C, 0x76, 0xDB, 0x75, 0x03, 0x54, 0x5B, 0xE8, 0xE8, 0x64, 0xC3, + 0x17, 0x71, 0xA3, 0xAD, 0xAB, 0xBA, 0x2B, 0xB0, 0x3B, 0xE4, 0x22, 0x98, 0xA3, 0x02, 0x54, 0xE8, + 0xAA, 0x52, 0xBA, 0xE1, 0xE3, 0x94, 0x60, 0x77, 0x70, 0x83, 0x25, 0xE2, 0x75, 0x1C, 0xA4, 0xE5, + 0xBA, 0xEA, 0xBF, 0xC7, 0x1E, 0xA6, 0x3C, 0x12, 0x9A, 0xDB, 0xB2, 0x43, 0xB7, 0x88, 0xDD, 0x44, + 0xAD, 0x9B, 0x52, 0x55, 0xA8, 0x02, 0xBB, 0xE9, 0xB9, 0xB6, 0x88, 0xD9, 0x71, 0x05, 0xF6, 0xB8, + 0x87, 0x64, 0x50, 0xFE, 0x9E, 0x9B, 0x72, 0x5C, 0x0B, 0x4A, 0x1C, 0xC1, 0x2D, 0x0B, 0xB9, 0xD7, + 0x6C, 0x91, 0xDB, 0x58, 0x68, 0x49, 0x84, 0xF0, 0x0E, 0x50, 0x6C, 0x02, 0xBB, 0xEB, 0x5A, 0x96, + 0xE7, 0x78, 0x96, 0xBC, 0x64, 0x0B, 0x97, 0xD8, 0x65, 0x51, 0x44, 0xD8, 0x41, 0x07, 0x26, 0x39, + 0x9E, 0x17, 0xAA, 0x31, 0x2B, 0x0E, 0xEC, 0x10, 0x34, 0x0B, 0x71, 0xAB, 0xB6, 0xC0, 0x8E, 0x92, + 0x14, 0xA3, 0x2D, 0x08, 0xE6, 0xAA, 0xAE, 0xEB, 0xC4, 0x0B, 0xD8, 0x3D, 0xCB, 0x55, 0xCC, 0x22, + 0x76, 0x17, 0x37, 0xE4, 0xB1, 0x23, 0x2D, 0xCF, 0x8B, 0x8C, 0x09, 0xF9, 0x7F, 0x7F, 0xD8, 0xE3, + 0xE9, 0x08, 0xBB, 0x6D, 0xC7, 0x45, 0x70, 0xDD, 0x06, 0x18, 0x60, 0x00, 0x76, 0x29, 0x91, 0x42, + 0x84, 0x6C, 0x81, 0xDD, 0x16, 0xF0, 0x3D, 0x4D, 0x73, 0xAC, 0x84, 0x8F, 0x64, 0x20, 0x56, 0x9E, + 0x97, 0x76, 0x3D, 0x5B, 0x93, 0x90, 0x2D, 0xC1, 0x34, 0x9A, 0x2D, 0xDA, 0x84, 0x1A, 0x17, 0x4D, + 0x42, 0x17, 0xDE, 0x01, 0xDA, 0x38, 0x14, 0x3F, 0xEA, 0xD3, 0xB6, 0x7D, 0x37, 0x8F, 0xDD, 0x28, + 0x60, 0xB7, 0x25, 0x76, 0x44, 0x6F, 0x03, 0xBB, 0x13, 0x61, 0x8F, 0xC3, 0x3B, 0xE1, 0x1A, 0x24, + 0xCB, 0x16, 0xC0, 0x05, 0x76, 0x4F, 0x60, 0xF7, 0xC8, 0x43, 0x30, 0x0F, 0xD8, 0xDD, 0x84, 0xA7, + 0xDA, 0x22, 0x06, 0xF8, 0x78, 0x79, 0xEC, 0x02, 0x9D, 0x8B, 0x1C, 0xDA, 0x82, 0x4B, 0x5C, 0xD7, + 0x73, 0x0B, 0xD8, 0xD5, 0x7F, 0x89, 0x3D, 0x51, 0xE6, 0x0B, 0xEC, 0x86, 0xED, 0x24, 0x7C, 0xF0, + 0x7A, 0x1E, 0x3B, 0x6A, 0xDD, 0x92, 0x6A, 0x52, 0x62, 0xB7, 0x7C, 0xCF, 0xB1, 0xF1, 0x72, 0x81, + 0xDD, 0xB5, 0x92, 0x81, 0x07, 0x34, 0x8E, 0xEB, 0x7B, 0x65, 0x1E, 0xF2, 0x67, 0x0A, 0xEC, 0x36, + 0x78, 0xC7, 0xD4, 0x1D, 0xD1, 0x26, 0xD4, 0x84, 0x2D, 0x11, 0x6A, 0x8E, 0x1D, 0xA2, 0xD8, 0x04, + 0x76, 0x04, 0x73, 0x02, 0xCF, 0xB7, 0xE5, 0x25, 0x5B, 0xB8, 0xC4, 0x2E, 0x8B, 0x02, 0x42, 0xEC, + 0x40, 0x41, 0x41, 0xAA, 0xC8, 0xF5, 0xFD, 0x04, 0xBC, 0x93, 0x9E, 0x41, 0xB2, 0x6C, 0x1D, 0x4D, + 0x85, 0xBE, 0x04, 0xF7, 0x59, 0x02, 0xBB, 0x8F, 0x60, 0xBE, 0x0A, 0x50, 0x49, 0x5F, 0x93, 0x2D, + 0x9B, 0x7C, 0x60, 0xB7, 0x8A, 0xD8, 0x51, 0xD9, 0x8E, 0x23, 0xB0, 0x7B, 0x9E, 0xEF, 0xF9, 0xBE, + 0xFF, 0x39, 0xB0, 0x27, 0xCB, 0x03, 0x12, 0x46, 0x94, 0xE3, 0x26, 0x03, 0x55, 0xBC, 0xAB, 0xA6, + 0xEA, 0x00, 0x11, 0xCC, 0x27, 0xA1, 0xC7, 0x50, 0xD1, 0x68, 0xAD, 0x81, 0xEF, 0x3A, 0x02, 0xBE, + 0x8F, 0x98, 0xED, 0x54, 0x80, 0x44, 0x81, 0x3D, 0xF0, 0xCB, 0x3D, 0xDF, 0x01, 0x76, 0x04, 0x77, + 0x04, 0xD3, 0xE8, 0x2E, 0xD2, 0xB6, 0xD5, 0xA4, 0x63, 0x09, 0x84, 0xF0, 0x8B, 0x83, 0xDF, 0x80, + 0xDD, 0xF1, 0x7D, 0xC7, 0x09, 0xFC, 0xC0, 0x91, 0x97, 0xAC, 0x6D, 0x91, 0x47, 0xA7, 0x14, 0x3B, + 0xE4, 0x95, 0xBC, 0x20, 0x48, 0x02, 0x6E, 0xCA, 0x37, 0x09, 0xF1, 0x3B, 0x88, 0x5B, 0x13, 0xD8, + 0x03, 0x81, 0xDD, 0xA7, 0x00, 0xC1, 0x02, 0x0D, 0xA0, 0x52, 0x81, 0xE6, 0x48, 0xEC, 0x81, 0xE3, + 0x97, 0x60, 0xF7, 0x71, 0x83, 0xC4, 0xEE, 0xFB, 0x48, 0x2B, 0x08, 0x22, 0x43, 0x4A, 0x8B, 0xEC, + 0xC6, 0xE1, 0xAF, 0x54, 0x36, 0x04, 0x76, 0xDD, 0x74, 0xDC, 0x94, 0xC4, 0xEE, 0x02, 0xBB, 0x0B, + 0xEC, 0x42, 0x21, 0x43, 0x76, 0xE5, 0x79, 0x9A, 0x76, 0x18, 0xB8, 0xAE, 0x80, 0x1F, 0x68, 0xBA, + 0xE7, 0xA4, 0x43, 0x24, 0x03, 0xB1, 0x0A, 0x83, 0xAC, 0x1F, 0xB8, 0x30, 0xAF, 0x11, 0x1C, 0x90, + 0x1C, 0x60, 0x77, 0x91, 0x5B, 0x60, 0x07, 0xD1, 0x02, 0xBB, 0xEB, 0x24, 0xC4, 0x52, 0x7A, 0x34, + 0xD8, 0x20, 0x10, 0xFB, 0x22, 0x84, 0x7B, 0x63, 0x97, 0x62, 0x80, 0xE8, 0x5D, 0x81, 0x1D, 0x92, + 0xEF, 0x85, 0x61, 0x4A, 0x53, 0xDD, 0xB4, 0xC4, 0x0E, 0xDE, 0x73, 0x75, 0x0D, 0x2F, 0x13, 0xD2, + 0x23, 0x7A, 0x46, 0xA1, 0x2B, 0xB0, 0x07, 0x81, 0x9F, 0x0E, 0x35, 0xD9, 0xB2, 0xE1, 0x13, 0xC4, + 0xEC, 0x22, 0xF6, 0x00, 0x37, 0xB8, 0x11, 0x76, 0xA4, 0x15, 0x86, 0x9F, 0x03, 0x7B, 0xBA, 0x22, + 0x2E, 0xB1, 0xBB, 0x1E, 0xE2, 0x04, 0xB1, 0xBB, 0xB0, 0x44, 0x5D, 0x07, 0x12, 0xEF, 0x08, 0xEC, + 0x76, 0x84, 0x3D, 0x1E, 0x78, 0x88, 0xD9, 0xF1, 0x43, 0x5D, 0xF7, 0x9D, 0x4C, 0x3C, 0x80, 0x74, + 0x7A, 0x7E, 0x3C, 0xAC, 0x08, 0x42, 0x89, 0xDD, 0xC1, 0x1D, 0x60, 0x1A, 0xC3, 0x13, 0xD8, 0xB5, + 0x94, 0x0B, 0x15, 0x03, 0x86, 0xF7, 0x9C, 0x24, 0xB8, 0xB0, 0x80, 0x3D, 0x1E, 0xC4, 0x5D, 0x79, + 0xC9, 0xDA, 0x96, 0xED, 0x52, 0x62, 0x87, 0x10, 0x7B, 0x50, 0xCE, 0x1E, 0xB0, 0xFB, 0xF1, 0x78, + 0x1A, 0xDE, 0x19, 0x58, 0x5B, 0xB2, 0x6C, 0x01, 0x1C, 0xB6, 0x42, 0x84, 0x3D, 0xA4, 0x38, 0x82, + 0x85, 0xC0, 0x1E, 0x64, 0x42, 0xDD, 0x15, 0x31, 0x00, 0x7B, 0x98, 0xC7, 0xAE, 0x15, 0xB0, 0x0B, + 0x1D, 0x12, 0x04, 0x61, 0x10, 0x8F, 0xC7, 0xB5, 0xA1, 0x6B, 0x7F, 0xD8, 0x33, 0x95, 0x79, 0xEC, + 0x7E, 0x26, 0x2E, 0x3A, 0x52, 0x1E, 0xB0, 0x7B, 0x12, 0xBB, 0x34, 0x11, 0x44, 0xF3, 0xF1, 0x1C, + 0xF1, 0xBC, 0xA1, 0x80, 0x0F, 0xEC, 0x81, 0x5B, 0x96, 0x40, 0x81, 0xA3, 0xF9, 0x26, 0xC2, 0xCA, + 0x20, 0xF4, 0x60, 0xB8, 0x02, 0xB2, 0xEB, 0x4A, 0xEC, 0x9E, 0xAE, 0xBB, 0x5A, 0xDA, 0x83, 0x92, + 0x11, 0xD8, 0xDD, 0x14, 0xF8, 0x0D, 0xD8, 0x51, 0x9F, 0x9E, 0x97, 0x08, 0x13, 0x25, 0xD8, 0x45, + 0x1E, 0x3D, 0x29, 0x06, 0x79, 0xEC, 0x90, 0x57, 0x42, 0x8E, 0x33, 0x48, 0xAF, 0x2C, 0xB4, 0x28, + 0x80, 0x2F, 0xE2, 0xD6, 0x05, 0xF6, 0xB8, 0xE3, 0x08, 0xEC, 0x09, 0x04, 0x8B, 0x6B, 0xA8, 0xD0, + 0xB2, 0x38, 0x4C, 0x4B, 0x64, 0x0C, 0xA5, 0x11, 0xC6, 0x9C, 0x22, 0xF6, 0x10, 0x37, 0x78, 0x22, + 0xDE, 0x30, 0x8C, 0x87, 0x89, 0x44, 0x42, 0xFF, 0xF7, 0xD8, 0xCB, 0xAA, 0x13, 0xE8, 0x39, 0x18, + 0x96, 0xE7, 0x97, 0x25, 0x8A, 0xD8, 0x5D, 0x74, 0x6C, 0x5C, 0x89, 0x1D, 0xC9, 0x03, 0x7B, 0x22, + 0xEE, 0x7B, 0xA1, 0xEF, 0x06, 0x71, 0xDD, 0x08, 0xDC, 0xF2, 0x24, 0x92, 0x41, 0x93, 0x4A, 0xC4, + 0xAB, 0xC3, 0xB8, 0x67, 0xD8, 0xA8, 0x6E, 0x04, 0x02, 0x2D, 0x1B, 0xBE, 0x2F, 0xB0, 0x67, 0x80, + 0xDD, 0x45, 0xD7, 0xD8, 0x77, 0x85, 0x1E, 0x30, 0x54, 0xC3, 0x8B, 0xC7, 0x3D, 0x3F, 0x19, 0x26, + 0x3C, 0x79, 0xC9, 0xDA, 0x1E, 0xC2, 0x8E, 0x06, 0xEC, 0xC3, 0x30, 0x11, 0xD8, 0x91, 0xE3, 0x32, + 0x54, 0x75, 0x39, 0x2C, 0xCD, 0x40, 0xC8, 0x95, 0x6F, 0xE8, 0x78, 0x59, 0x09, 0x07, 0x5D, 0xCD, + 0x38, 0x25, 0x10, 0x2C, 0xA1, 0xC7, 0xE3, 0x61, 0x36, 0x91, 0xC7, 0x9E, 0xF0, 0xE2, 0x25, 0xD8, + 0xE3, 0xB8, 0xC1, 0x8F, 0xB0, 0x27, 0x24, 0x76, 0x71, 0xC9, 0xEE, 0x82, 0xBE, 0x3F, 0xEC, 0xFF, + 0x27, 0x00, 0x00, 0xFF, 0xFF, 0xA4, 0xB4, 0xB8, 0xA4} diff --git a/vendor/github.com/jung-kurt/gofpdf/layer.go b/vendor/github.com/jung-kurt/gofpdf/layer.go new file mode 100644 index 0000000..bca364f --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/layer.go @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2014 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gofpdf + +// Routines in this file are translated from +// http://www.fpdf.org/en/script/script97.php + +type layerType struct { + name string + visible bool + objNum int // object number +} + +type layerRecType struct { + list []layerType + currentLayer int + openLayerPane bool +} + +func (f *Fpdf) layerInit() { + f.layer.list = make([]layerType, 0) + f.layer.currentLayer = -1 + f.layer.openLayerPane = false +} + +// AddLayer defines a layer that can be shown or hidden when the document is +// displayed. name specifies the layer name that the document reader will +// display in the layer list. visible specifies whether the layer will be +// initially visible. The return value is an integer ID that is used in a call +// to BeginLayer(). +func (f *Fpdf) AddLayer(name string, visible bool) (layerID int) { + layerID = len(f.layer.list) + f.layer.list = append(f.layer.list, layerType{name: name, visible: visible}) + return +} + +// BeginLayer is called to begin adding content to the specified layer. All +// content added to the page between a call to BeginLayer and a call to +// EndLayer is added to the layer specified by id. See AddLayer for more +// details. +func (f *Fpdf) BeginLayer(id int) { + f.EndLayer() + if id >= 0 && id < len(f.layer.list) { + f.outf("/OC /OC%d BDC", id) + f.layer.currentLayer = id + } +} + +// EndLayer is called to stop adding content to the currently active layer. See +// BeginLayer for more details. +func (f *Fpdf) EndLayer() { + if f.layer.currentLayer >= 0 { + f.out("EMC") + f.layer.currentLayer = -1 + } +} + +// OpenLayerPane advises the document reader to open the layer pane when the +// document is initially displayed. +func (f *Fpdf) OpenLayerPane() { + f.layer.openLayerPane = true +} + +func (f *Fpdf) layerEndDoc() { + if len(f.layer.list) > 0 { + if f.pdfVersion < "1.5" { + f.pdfVersion = "1.5" + } + } +} + +func (f *Fpdf) layerPutLayers() { + for j, l := range f.layer.list { + f.newobj() + f.layer.list[j].objNum = f.n + f.outf("<</Type /OCG /Name %s>>", f.textstring(utf8toutf16(l.name))) + f.out("endobj") + } +} + +func (f *Fpdf) layerPutResourceDict() { + if len(f.layer.list) > 0 { + f.out("/Properties <<") + for j, layer := range f.layer.list { + f.outf("/OC%d %d 0 R", j, layer.objNum) + } + f.out(">>") + } + +} + +func (f *Fpdf) layerPutCatalog() { + if len(f.layer.list) > 0 { + onStr := "" + offStr := "" + for _, layer := range f.layer.list { + onStr += sprintf("%d 0 R ", layer.objNum) + if !layer.visible { + offStr += sprintf("%d 0 R ", layer.objNum) + } + } + f.outf("/OCProperties <</OCGs [%s] /D <</OFF [%s] /Order [%s]>>>>", onStr, offStr, onStr) + if f.layer.openLayerPane { + f.out("/PageMode /UseOC") + } + } +} diff --git a/vendor/github.com/jung-kurt/gofpdf/license.txt b/vendor/github.com/jung-kurt/gofpdf/license.txt new file mode 100644 index 0000000..eb1abac --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/license.txt @@ -0,0 +1,23 @@ +MIT License + +Copyright (c) 2013-2016 Kurt Jung (Gmail: kurt.w.jung) + +Portions copyright by the contributors acknowledged in the documentation. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/jung-kurt/gofpdf/list/list.go b/vendor/github.com/jung-kurt/gofpdf/list/list.go new file mode 100644 index 0000000..8099404 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/list/list.go @@ -0,0 +1,59 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + "strings" +) + +func matchTail(str, tailStr string) (match bool, headStr string) { + sln := len(str) + ln := len(tailStr) + if sln > ln { + match = str[sln-ln:] == tailStr + if match { + headStr = str[:sln-ln] + } + } + return +} + +func matchHead(str, headStr string) (match bool, tailStr string) { + ln := len(headStr) + if len(str) > ln { + match = str[:ln] == headStr + if match { + tailStr = str[ln:] + } + } + return +} + +func main() { + var err error + var ok bool + var showStr, name string + err = filepath.Walk("pdf/reference", func(path string, info os.FileInfo, err error) error { + if info.Mode().IsRegular() { + name = filepath.Base(path) + ok, name = matchTail(name, ".pdf") + if ok { + name = strings.Replace(name, "_", " ", -1) + ok, showStr = matchHead(name, "Fpdf ") + if ok { + fmt.Printf("[%s](%s)\n", showStr, path) + } else { + ok, showStr = matchHead(name, "contrib ") + if ok { + fmt.Printf("[%s](%s)\n", showStr, path) + } + } + } + } + return nil + }) + if err != nil { + fmt.Println(err) + } +} diff --git a/vendor/github.com/jung-kurt/gofpdf/makefont/doc.go b/vendor/github.com/jung-kurt/gofpdf/makefont/doc.go new file mode 100644 index 0000000..306ead2 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/makefont/doc.go @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2013 Kurt Jung + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* +Command makefont generates a font definition file. + +This utility is used to generate a font definition file that allows TrueType +and Type1 fonts to be used in PDFs produced with the fpdf package. +*/ +package main diff --git a/vendor/github.com/jung-kurt/gofpdf/makefont/makefont b/vendor/github.com/jung-kurt/gofpdf/makefont/makefont Binary files differnew file mode 100755 index 0000000..2e49bc1 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/makefont/makefont diff --git a/vendor/github.com/jung-kurt/gofpdf/makefont/makefont.go b/vendor/github.com/jung-kurt/gofpdf/makefont/makefont.go new file mode 100644 index 0000000..eb2993e --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/makefont/makefont.go @@ -0,0 +1,71 @@ +package main + +import ( + "flag" + "fmt" + "github.com/jung-kurt/gofpdf" + "os" +) + +func errPrintf(fmtStr string, args ...interface{}) { + fmt.Fprintf(os.Stderr, fmtStr, args...) +} + +func showHelp() { + errPrintf("Usage: %s [options] font_file [font_file...]\n", os.Args[0]) + flag.PrintDefaults() + fmt.Fprintln(os.Stderr, "\n"+ + "font_file is the name of the TrueType file (extension .ttf), OpenType file\n"+ + "(extension .otf) or binary Type1 file (extension .pfb) from which to\n"+ + "generate a definition file. If an OpenType file is specified, it must be one\n"+ + "that is based on TrueType outlines, not PostScript outlines; this cannot be\n"+ + "determined from the file extension alone. If a Type1 file is specified, a\n"+ + "metric file with the same pathname except with the extension .afm must be\n"+ + "present.") + errPrintf("\nExample: %s --embed --enc=../font/cp1252.map --dst=../font calligra.ttf /opt/font/symbol.pfb\n", os.Args[0]) +} + +func tutorialSummary(f *gofpdf.Fpdf, fileStr string) { + if f.Ok() { + fl, err := os.Create(fileStr) + defer fl.Close() + if err == nil { + f.Output(fl) + } else { + f.SetError(err) + } + } + if f.Ok() { + fmt.Printf("Successfully generated %s\n", fileStr) + } else { + errPrintf("%s\n", f.Error()) + } +} + +func main() { + var dstDirStr, encodingFileStr string + var err error + var help, embed bool + flag.StringVar(&dstDirStr, "dst", ".", "directory for output files (*.z, *.json)") + flag.StringVar(&encodingFileStr, "enc", "cp1252.map", "code page file") + flag.BoolVar(&embed, "embed", false, "embed font into PDF") + flag.BoolVar(&help, "help", false, "command line usage") + flag.Parse() + if help { + showHelp() + } else { + args := flag.Args() + if len(args) > 0 { + for _, fileStr := range args { + err = gofpdf.MakeFont(fileStr, encodingFileStr, dstDirStr, os.Stderr, embed) + if err != nil { + errPrintf("%s\n", err) + } + // errPrintf("Font file [%s], Encoding file [%s], Embed [%v]\n", fileStr, encodingFileStr, embed) + } + } else { + errPrintf("At least one Type1 or TrueType font must be specified\n") + showHelp() + } + } +} diff --git a/vendor/github.com/jung-kurt/gofpdf/png.go b/vendor/github.com/jung-kurt/gofpdf/png.go new file mode 100644 index 0000000..854b003 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/png.go @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2013-2016 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gofpdf + +import ( + "bytes" + "fmt" + "strings" +) + +func (f *Fpdf) pngColorSpace(ct byte) (colspace string, colorVal int) { + colorVal = 1 + switch ct { + case 0, 4: + colspace = "DeviceGray" + case 2, 6: + colspace = "DeviceRGB" + colorVal = 3 + case 3: + colspace = "Indexed" + default: + f.err = fmt.Errorf("unknown color type in PNG buffer: %d", ct) + } + return +} + +func (f *Fpdf) parsepngstream(buf *bytes.Buffer, readdpi bool) (info *ImageInfoType) { + info = f.newImageInfo() + // Check signature + if string(buf.Next(8)) != "\x89PNG\x0d\x0a\x1a\x0a" { + f.err = fmt.Errorf("not a PNG buffer") + return + } + // Read header chunk + _ = buf.Next(4) + if string(buf.Next(4)) != "IHDR" { + f.err = fmt.Errorf("incorrect PNG buffer") + return + } + w := f.readBeInt32(buf) + h := f.readBeInt32(buf) + bpc := f.readByte(buf) + if bpc > 8 { + f.err = fmt.Errorf("16-bit depth not supported in PNG file") + } + ct := f.readByte(buf) + var colspace string + var colorVal int + colspace, colorVal = f.pngColorSpace(ct) + if f.err != nil { + return + } + if f.readByte(buf) != 0 { + f.err = fmt.Errorf("'unknown compression method in PNG buffer") + return + } + if f.readByte(buf) != 0 { + f.err = fmt.Errorf("'unknown filter method in PNG buffer") + return + } + if f.readByte(buf) != 0 { + f.err = fmt.Errorf("interlacing not supported in PNG buffer") + return + } + _ = buf.Next(4) + dp := sprintf("/Predictor 15 /Colors %d /BitsPerComponent %d /Columns %d", colorVal, bpc, w) + // Scan chunks looking for palette, transparency and image data + pal := make([]byte, 0, 32) + var trns []int + data := make([]byte, 0, 32) + loop := true + for loop { + n := int(f.readBeInt32(buf)) + // dbg("Loop [%d]", n) + switch string(buf.Next(4)) { + case "PLTE": + // dbg("PLTE") + // Read palette + pal = buf.Next(n) + _ = buf.Next(4) + case "tRNS": + // dbg("tRNS") + // Read transparency info + t := buf.Next(n) + if ct == 0 { + trns = []int{int(t[1])} // ord(substr($t,1,1))); + } else if ct == 2 { + trns = []int{int(t[1]), int(t[3]), int(t[5])} // array(ord(substr($t,1,1)), ord(substr($t,3,1)), ord(substr($t,5,1))); + } else { + pos := strings.Index(string(t), "\x00") + if pos >= 0 { + trns = []int{pos} // array($pos); + } + } + _ = buf.Next(4) + case "IDAT": + // dbg("IDAT") + // Read image data block + data = append(data, buf.Next(n)...) + _ = buf.Next(4) + case "IEND": + // dbg("IEND") + loop = false + case "pHYs": + // dbg("pHYs") + // png files theoretically support different x/y dpi + // but we ignore files like this + // but if they're the same then we can stamp our info + // object with it + x := int(f.readBeInt32(buf)) + y := int(f.readBeInt32(buf)) + units := buf.Next(1)[0] + // fmt.Printf("got a pHYs block, x=%d, y=%d, u=%d, readdpi=%t\n", + // x, y, int(units), readdpi) + // only modify the info block if the user wants us to + if x == y && readdpi { + switch units { + // if units is 1 then measurement is px/meter + case 1: + info.dpi = float64(x) / 39.3701 // inches per meter + default: + info.dpi = float64(x) + } + } + _ = buf.Next(4) + default: + // dbg("default") + _ = buf.Next(n + 4) + } + if loop { + loop = n > 0 + } + } + if colspace == "Indexed" && len(pal) == 0 { + f.err = fmt.Errorf("missing palette in PNG buffer") + } + info.w = float64(w) + info.h = float64(h) + info.cs = colspace + info.bpc = int(bpc) + info.f = "FlateDecode" + info.dp = dp + info.pal = pal + info.trns = trns + // dbg("ct [%d]", ct) + if ct >= 4 { + // Separate alpha and color channels + var err error + data, err = sliceUncompress(data) + if err != nil { + f.err = err + return + } + var color, alpha bytes.Buffer + if ct == 4 { + // Gray image + width := int(w) + height := int(h) + length := 2 * width + var pos, elPos int + for i := 0; i < height; i++ { + pos = (1 + length) * i + color.WriteByte(data[pos]) + alpha.WriteByte(data[pos]) + elPos = pos + 1 + for k := 0; k < width; k++ { + color.WriteByte(data[elPos]) + alpha.WriteByte(data[elPos+1]) + elPos += 2 + } + } + } else { + // RGB image + width := int(w) + height := int(h) + length := 4 * width + var pos, elPos int + for i := 0; i < height; i++ { + pos = (1 + length) * i + color.WriteByte(data[pos]) + alpha.WriteByte(data[pos]) + elPos = pos + 1 + for k := 0; k < width; k++ { + color.Write(data[elPos : elPos+3]) + alpha.WriteByte(data[elPos+3]) + elPos += 4 + } + } + } + data = sliceCompress(color.Bytes()) + info.smask = sliceCompress(alpha.Bytes()) + if f.pdfVersion < "1.4" { + f.pdfVersion = "1.4" + } + } + info.data = data + return +} diff --git a/vendor/github.com/jung-kurt/gofpdf/protect.go b/vendor/github.com/jung-kurt/gofpdf/protect.go new file mode 100644 index 0000000..e934c2b --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/protect.go @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2013-2014 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +// PDF protection is adapted from the work of Klemen VODOPIVEC for the fpdf +// product. + +package gofpdf + +import ( + "crypto/md5" + "crypto/rc4" + "encoding/binary" + "math/rand" +) + +// Advisory bitflag constants that control document activities +const ( + CnProtectPrint = 4 + CnProtectModify = 8 + CnProtectCopy = 16 + CnProtectAnnotForms = 32 +) + +type protectType struct { + encrypted bool + uValue []byte + oValue []byte + pValue int + padding []byte + encryptionKey []byte + objNum int + rc4cipher *rc4.Cipher + rc4n uint32 // Object number associated with rc4 cipher +} + +func (p *protectType) rc4(n uint32, buf *[]byte) { + if p.rc4cipher == nil || p.rc4n != n { + p.rc4cipher, _ = rc4.NewCipher(p.objectKey(n)) + p.rc4n = n + } + p.rc4cipher.XORKeyStream(*buf, *buf) +} + +func (p *protectType) objectKey(n uint32) []byte { + var nbuf, b []byte + nbuf = make([]byte, 8, 8) + binary.LittleEndian.PutUint32(nbuf, n) + b = append(b, p.encryptionKey...) + b = append(b, nbuf[0], nbuf[1], nbuf[2], 0, 0) + s := md5.Sum(b) + return s[0:10] +} + +func oValueGen(userPass, ownerPass []byte) (v []byte) { + var c *rc4.Cipher + tmp := md5.Sum(ownerPass) + c, _ = rc4.NewCipher(tmp[0:5]) + cap := len(userPass) + v = make([]byte, cap, cap) + c.XORKeyStream(v, userPass) + return +} + +func (p *protectType) uValueGen() (v []byte) { + var c *rc4.Cipher + c, _ = rc4.NewCipher(p.encryptionKey) + cap := len(p.padding) + v = make([]byte, cap, cap) + c.XORKeyStream(v, p.padding) + return +} + +func (p *protectType) setProtection(privFlag byte, userPassStr, ownerPassStr string) { + privFlag = 192 | (privFlag & (CnProtectCopy | CnProtectModify | CnProtectPrint | CnProtectAnnotForms)) + p.padding = []byte{ + 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, + 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, + 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, + 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A, + } + userPass := []byte(userPassStr) + var ownerPass []byte + if ownerPassStr == "" { + ownerPass = make([]byte, 8, 8) + binary.LittleEndian.PutUint64(ownerPass, uint64(rand.Int63())) + } else { + ownerPass = []byte(ownerPassStr) + } + userPass = append(userPass, p.padding...)[0:32] + ownerPass = append(ownerPass, p.padding...)[0:32] + p.encrypted = true + p.oValue = oValueGen(userPass, ownerPass) + var buf []byte + buf = append(buf, userPass...) + buf = append(buf, p.oValue...) + buf = append(buf, privFlag, 0xff, 0xff, 0xff) + sum := md5.Sum(buf) + p.encryptionKey = sum[0:5] + p.uValue = p.uValueGen() + p.pValue = -(int(privFlag^255) + 1) +} diff --git a/vendor/github.com/jung-kurt/gofpdf/svgbasic.go b/vendor/github.com/jung-kurt/gofpdf/svgbasic.go new file mode 100644 index 0000000..cb8e91e --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/svgbasic.go @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2014 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gofpdf + +import ( + "encoding/xml" + "fmt" + "io/ioutil" + "strconv" + "strings" +) + +var pathCmdSub *strings.Replacer + +func init() { + // Handle permitted constructions like "100L200,230" + pathCmdSub = strings.NewReplacer(",", " ", + "L", " L ", "l", " l ", + "C", " C ", "c", " c ", + "M", " M ", "m", " m ") +} + +// SVGBasicSegmentType describes a single curve or position segment +type SVGBasicSegmentType struct { + Cmd byte // See http://www.w3.org/TR/SVG/paths.html for path command structure + Arg [6]float64 +} + +func absolutizePath(segs []SVGBasicSegmentType) { + var x, y float64 + var segPtr *SVGBasicSegmentType + adjust := func(pos int, adjX, adjY float64) { + segPtr.Arg[pos] += adjX + segPtr.Arg[pos+1] += adjY + } + for j, seg := range segs { + segPtr = &segs[j] + if j == 0 && seg.Cmd == 'm' { + segPtr.Cmd = 'M' + } + switch segPtr.Cmd { + case 'M': + x = seg.Arg[0] + y = seg.Arg[1] + case 'm': + adjust(0, x, y) + segPtr.Cmd = 'M' + x = segPtr.Arg[0] + y = segPtr.Arg[1] + case 'L': + x = seg.Arg[0] + y = seg.Arg[1] + case 'l': + adjust(0, x, y) + segPtr.Cmd = 'L' + x = segPtr.Arg[0] + y = segPtr.Arg[1] + case 'C': + x = seg.Arg[4] + y = seg.Arg[5] + case 'c': + adjust(0, x, y) + adjust(2, x, y) + adjust(4, x, y) + segPtr.Cmd = 'C' + x = segPtr.Arg[4] + y = segPtr.Arg[5] + } + } +} + +func pathParse(pathStr string) (segs []SVGBasicSegmentType, err error) { + var seg SVGBasicSegmentType + var j, argJ, argCount, prevArgCount int + setup := func(n int) { + // It is not strictly necessary to clear arguments, but result may be clearer + // to caller + for j := 0; j < len(seg.Arg); j++ { + seg.Arg[j] = 0.0 + } + argJ = 0 + argCount = n + prevArgCount = n + } + var str string + var c byte + pathStr = pathCmdSub.Replace(pathStr) + strList := strings.Fields(pathStr) + count := len(strList) + for j = 0; j < count && err == nil; j++ { + str = strList[j] + if argCount == 0 { // Look for path command or argument continuation + c = str[0] + if c == '-' || (c >= '0' && c <= '9') { // More arguments + if j > 0 { + setup(prevArgCount) + // Repeat previous action + if seg.Cmd == 'M' { + seg.Cmd = 'L' + } else if seg.Cmd == 'm' { + seg.Cmd = 'l' + } + } else { + err = fmt.Errorf("expecting SVG path command at first position, got %s", str) + } + } + } + if err == nil { + if argCount == 0 { + seg.Cmd = str[0] + switch seg.Cmd { + case 'M', 'm': // Absolute/relative moveto: x, y + setup(2) + case 'C', 'c': // Absolute/relative Bézier curve: cx0, cy0, cx1, cy1, x1, y1 + setup(6) + case 'L', 'l': // Absolute/relative lineto: x, y + setup(2) + default: + err = fmt.Errorf("expecting SVG path command at position %d, got %s", j, str) + } + } else { + seg.Arg[argJ], err = strconv.ParseFloat(str, 64) + if err == nil { + argJ++ + argCount-- + if argCount == 0 { + segs = append(segs, seg) + } + } + } + } + } + if err == nil { + if argCount == 0 { + absolutizePath(segs) + } else { + err = fmt.Errorf("expecting additional (%d) numeric arguments", argCount) + } + } + return +} + +// SVGBasicType aggregates the information needed to describe a multi-segment +// basic vector image +type SVGBasicType struct { + Wd, Ht float64 + Segments [][]SVGBasicSegmentType +} + +// SVGBasicParse parses a simple scalable vector graphics (SVG) buffer into a +// descriptor. Only a small subset of the SVG standard, in particular the path +// information generated by jSignature, is supported. The returned path data +// includes only the commands 'M' (absolute moveto: x, y), 'L' (absolute +// lineto: x, y), and 'C' (absolute cubic Bézier curve: cx0, cy0, cx1, cy1, +// x1,y1). +func SVGBasicParse(buf []byte) (sig SVGBasicType, err error) { + type pathType struct { + D string `xml:"d,attr"` + } + type srcType struct { + Wd float64 `xml:"width,attr"` + Ht float64 `xml:"height,attr"` + Paths []pathType `xml:"path"` + } + var src srcType + err = xml.Unmarshal(buf, &src) + if err == nil { + if src.Wd > 0 && src.Ht > 0 { + sig.Wd, sig.Ht = src.Wd, src.Ht + var segs []SVGBasicSegmentType + for _, path := range src.Paths { + if err == nil { + segs, err = pathParse(path.D) + if err == nil { + sig.Segments = append(sig.Segments, segs) + } + } + } + } else { + err = fmt.Errorf("unacceptable values for basic SVG extent: %.2f x %.2f", + sig.Wd, sig.Ht) + } + } + return +} + +// SVGBasicFileParse parses a simple scalable vector graphics (SVG) file into a +// basic descriptor. The SVGBasicWrite() example demonstrates this method. +func SVGBasicFileParse(svgFileStr string) (sig SVGBasicType, err error) { + var buf []byte + buf, err = ioutil.ReadFile(svgFileStr) + if err == nil { + sig, err = SVGBasicParse(buf) + } + return +} diff --git a/vendor/github.com/jung-kurt/gofpdf/svgwrite.go b/vendor/github.com/jung-kurt/gofpdf/svgwrite.go new file mode 100644 index 0000000..04f6cb3 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/svgwrite.go @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gofpdf + +// SVGBasicWrite renders the paths encoded in the basic SVG image specified by +// sb. The scale value is used to convert the coordinates in the path to the +// unit of measure specified in New(). The current position (as set with a call +// to SetXY()) is used as the origin of the image. The current line cap style +// (as set with SetLineCapStyle()), line width (as set with SetLineWidth()), +// and draw color (as set with SetDrawColor()) are used in drawing the image +// paths. +func (f *Fpdf) SVGBasicWrite(sb *SVGBasicType, scale float64) { + originX, originY := f.GetXY() + var x, y, newX, newY float64 + var cx0, cy0, cx1, cy1 float64 + var path []SVGBasicSegmentType + var seg SVGBasicSegmentType + val := func(arg int) (float64, float64) { + return originX + scale*seg.Arg[arg], originY + scale*seg.Arg[arg+1] + } + for j := 0; j < len(sb.Segments) && f.Ok(); j++ { + path = sb.Segments[j] + for k := 0; k < len(path) && f.Ok(); k++ { + seg = path[k] + switch seg.Cmd { + case 'M': + x, y = val(0) + f.SetXY(x, y) + case 'L': + newX, newY = val(0) + f.Line(x, y, newX, newY) + x, y = newX, newY + case 'C': + cx0, cy0 = val(0) + cx1, cy1 = val(2) + newX, newY = val(4) + f.CurveCubic(x, y, cx0, cy0, newX, newY, cx1, cy1, "D") + x, y = newX, newY + default: + f.SetErrorf("Unexpected path command '%c'", seg.Cmd) + } + } + } +} diff --git a/vendor/github.com/jung-kurt/gofpdf/template.go b/vendor/github.com/jung-kurt/gofpdf/template.go new file mode 100644 index 0000000..1826fd7 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/template.go @@ -0,0 +1,269 @@ +package gofpdf + +/* + * Copyright (c) 2015 Kurt Jung (Gmail: kurt.w.jung), + * Marcus Downing, Jan Slabon (Setasign) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import ( + "sort" +) + +// CreateTemplate defines a new template using the current page size. +func (f *Fpdf) CreateTemplate(fn func(*Tpl)) Template { + return newTpl(PointType{0, 0}, f.curPageSize, f.unitStr, f.fontDirStr, fn, f) +} + +// CreateTemplateCustom starts a template, using the given bounds. +func (f *Fpdf) CreateTemplateCustom(corner PointType, size SizeType, fn func(*Tpl)) Template { + return newTpl(corner, size, f.unitStr, f.fontDirStr, fn, f) +} + +// CreateTemplate creates a template not attached to any document +func CreateTemplate(corner PointType, size SizeType, unitStr, fontDirStr string, fn func(*Tpl)) Template { + return newTpl(corner, size, unitStr, fontDirStr, fn, nil) +} + +// UseTemplate adds a template to the current page or another template, +// using the size and position at which it was originally written. +func (f *Fpdf) UseTemplate(t Template) { + if t == nil { + f.SetErrorf("template is nil") + return + } + corner, size := t.Size() + f.UseTemplateScaled(t, corner, size) +} + +// UseTemplateScaled adds a template to the current page or another template, +// using the given page coordinates. +func (f *Fpdf) UseTemplateScaled(t Template, corner PointType, size SizeType) { + if t == nil { + f.SetErrorf("template is nil") + return + } + + // You have to add at least a page first + if f.page <= 0 { + f.SetErrorf("cannot use a template without first adding a page") + return + } + + // make a note of the fact that we actually use this template, as well as any other templates, + // images or fonts it uses + f.templates[t.ID()] = t + for _, tt := range t.Templates() { + f.templates[tt.ID()] = tt + } + for name, ti := range t.Images() { + name = sprintf("t%d-%s", t.ID(), name) + f.images[name] = ti + } + + // template data + _, templateSize := t.Size() + scaleX := size.Wd / templateSize.Wd + scaleY := size.Ht / templateSize.Ht + tx := corner.X * f.k + ty := (f.curPageSize.Ht - corner.Y - size.Ht) * f.k + + f.outf("q %.4f 0 0 %.4f %.4f %.4f cm", scaleX, scaleY, tx, ty) // Translate + f.outf("/TPL%d Do Q", t.ID()) +} + +var nextTemplateIDChannel = func() chan int64 { + ch := make(chan int64) + go func() { + var nextID int64 = 1 + for { + ch <- nextID + nextID++ + } + }() + return ch +}() + +// GenerateTemplateID gives the next template ID. These numbers are global so that they can never clash. +func GenerateTemplateID() int64 { + return <-nextTemplateIDChannel +} + +// Template is an object that can be written to, then used and re-used any number of times within a document. +type Template interface { + ID() int64 + Size() (PointType, SizeType) + Bytes() []byte + Images() map[string]*ImageInfoType + Templates() []Template +} + +func (f *Fpdf) templateFontCatalog() { + var keyList []string + var font fontDefType + var key string + f.out("/Font <<") + for key = range f.fonts { + keyList = append(keyList, key) + } + if f.catalogSort { + sort.Strings(keyList) + } + for _, key = range keyList { + font = f.fonts[key] + f.outf("/F%d %d 0 R", font.I, font.N) + } + f.out(">>") +} + +// putTemplates writes the templates to the PDF +func (f *Fpdf) putTemplates() { + filter := "" + if f.compress { + filter = "/Filter /FlateDecode " + } + + templates := sortTemplates(f.templates, f.catalogSort) + var t Template + for _, t = range templates { + corner, size := t.Size() + + f.newobj() + f.templateObjects[t.ID()] = f.n + f.outf("<<%s/Type /XObject", filter) + f.out("/Subtype /Form") + f.out("/Formtype 1") + f.outf("/BBox [%.2f %.2f %.2f %.2f]", corner.X*f.k, corner.Y*f.k, (corner.X+size.Wd)*f.k, (corner.Y+size.Ht)*f.k) + if corner.X != 0 || corner.Y != 0 { + f.outf("/Matrix [1 0 0 1 %.5f %.5f]", -corner.X*f.k*2, corner.Y*f.k*2) + } + + // Template's resource dictionary + f.out("/Resources ") + f.out("<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]") + + f.templateFontCatalog() + + tImages := t.Images() + tTemplates := t.Templates() + if len(tImages) > 0 || len(tTemplates) > 0 { + f.out("/XObject <<") + { + var key string + var keyList []string + var ti *ImageInfoType + for key = range tImages { + keyList = append(keyList, key) + } + if gl.catalogSort { + sort.Strings(keyList) + } + for _, key = range keyList { + // for _, ti := range tImages { + ti = tImages[key] + f.outf("/I%d %d 0 R", ti.i, ti.n) + } + } + for _, tt := range tTemplates { + id := tt.ID() + if objID, ok := f.templateObjects[id]; ok { + f.outf("/TPL%d %d 0 R", id, objID) + } + } + f.out(">>") + } + + f.out(">>") + + // Write the template's byte stream + buffer := t.Bytes() + // fmt.Println("Put template bytes", string(buffer[:])) + if f.compress { + buffer = sliceCompress(buffer) + } + f.outf("/Length %d >>", len(buffer)) + f.putstream(buffer) + f.out("endobj") + } +} + +func templateKeyList(mp map[int64]Template, sort bool) (keyList []int64) { + var key int64 + for key = range mp { + keyList = append(keyList, key) + } + if sort { + gensort(len(keyList), + func(a, b int) bool { + return keyList[a] < keyList[b] + }, + func(a, b int) { + keyList[a], keyList[b] = keyList[b], keyList[a] + }) + } + return +} + +// sortTemplates puts templates in a suitable order based on dependices +func sortTemplates(templates map[int64]Template, catalogSort bool) []Template { + chain := make([]Template, 0, len(templates)*2) + + // build a full set of dependency chains + var keyList []int64 + var key int64 + var t Template + keyList = templateKeyList(templates, catalogSort) + for _, key = range keyList { + t = templates[key] + tlist := templateChainDependencies(t) + for _, tt := range tlist { + if tt != nil { + chain = append(chain, tt) + } + } + } + + // reduce that to make a simple list + sorted := make([]Template, 0, len(templates)) +chain: + for _, t := range chain { + for _, already := range sorted { + if t == already { + continue chain + } + } + sorted = append(sorted, t) + } + + return sorted +} + +// templateChainDependencies is a recursive function for determining the full chain of template dependencies +func templateChainDependencies(template Template) []Template { + requires := template.Templates() + chain := make([]Template, len(requires)*2) + for _, req := range requires { + for _, sub := range templateChainDependencies(req) { + chain = append(chain, sub) + } + } + chain = append(chain, template) + return chain +} + +// < 0002640 31 20 31 32 20 30 20 52 0a 2f 54 50 4c 32 20 31 |1 12 0 R./TPL2 1| +// < 0002650 35 20 30 20 52 0a 2f 54 50 4c 31 20 31 34 20 30 |5 0 R./TPL1 14 0| + +// > 0002640 31 20 31 32 20 30 20 52 0a 2f 54 50 4c 31 20 31 |1 12 0 R./TPL1 1| +// > 0002650 34 20 30 20 52 0a 2f 54 50 4c 32 20 31 35 20 30 |4 0 R./TPL2 15 0| diff --git a/vendor/github.com/jung-kurt/gofpdf/template_impl.go b/vendor/github.com/jung-kurt/gofpdf/template_impl.go new file mode 100644 index 0000000..01bb040 --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/template_impl.go @@ -0,0 +1,123 @@ +package gofpdf + +/* + * Copyright (c) 2015 Kurt Jung (Gmail: kurt.w.jung), + * Marcus Downing, Jan Slabon (Setasign) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +// newTpl creates a template, copying graphics settings from a template if one is given +func newTpl(corner PointType, size SizeType, unitStr, fontDirStr string, fn func(*Tpl), copyFrom *Fpdf) Template { + orientationStr := "p" + if size.Wd > size.Ht { + orientationStr = "l" + } + sizeStr := "" + + fpdf := fpdfNew(orientationStr, unitStr, sizeStr, fontDirStr, size) + tpl := Tpl{*fpdf} + if copyFrom != nil { + tpl.loadParamsFromFpdf(copyFrom) + } + tpl.Fpdf.SetAutoPageBreak(false, 0) + tpl.Fpdf.AddPage() + fn(&tpl) + bytes := tpl.Fpdf.pages[tpl.Fpdf.page].Bytes() + templates := make([]Template, 0, len(tpl.Fpdf.templates)) + for _, key := range templateKeyList(tpl.Fpdf.templates, true) { + templates = append(templates, tpl.Fpdf.templates[key]) + } + images := tpl.Fpdf.images + + id := GenerateTemplateID() + template := FpdfTpl{id, corner, size, bytes, images, templates} + return &template +} + +// FpdfTpl is a concrete implementation of the Template interface. +type FpdfTpl struct { + id int64 + corner PointType + size SizeType + bytes []byte + images map[string]*ImageInfoType + templates []Template +} + +// ID returns the global template identifier +func (t *FpdfTpl) ID() int64 { + return t.id +} + +// Size gives the bounding dimensions of this template +func (t *FpdfTpl) Size() (corner PointType, size SizeType) { + return t.corner, t.size +} + +// Bytes returns the actual template data, not including resources +func (t *FpdfTpl) Bytes() []byte { + return t.bytes +} + +// Images returns a list of the images used in this template +func (t *FpdfTpl) Images() map[string]*ImageInfoType { + return t.images +} + +// Templates returns a list of templates used in this template +func (t *FpdfTpl) Templates() []Template { + return t.templates +} + +// Tpl is an Fpdf used for writing a template. It has most of the facilities of +// an Fpdf, but cannot add more pages. Tpl is used directly only during the +// limited time a template is writable. +type Tpl struct { + Fpdf +} + +func (t *Tpl) loadParamsFromFpdf(f *Fpdf) { + t.Fpdf.compress = false + + t.Fpdf.k = f.k + t.Fpdf.x = f.x + t.Fpdf.y = f.y + t.Fpdf.lineWidth = f.lineWidth + t.Fpdf.capStyle = f.capStyle + t.Fpdf.joinStyle = f.joinStyle + + t.Fpdf.color.draw = f.color.draw + t.Fpdf.color.fill = f.color.fill + t.Fpdf.color.text = f.color.text + + t.Fpdf.fonts = f.fonts + t.Fpdf.currentFont = f.currentFont + t.Fpdf.fontFamily = f.fontFamily + t.Fpdf.fontSize = f.fontSize + t.Fpdf.fontSizePt = f.fontSizePt + t.Fpdf.fontStyle = f.fontStyle + t.Fpdf.ws = f.ws +} + +// AddPage does nothing because you cannot add pages to a template +func (t *Tpl) AddPage() { +} + +// AddPageFormat does nothign because you cannot add pages to a template +func (t *Tpl) AddPageFormat(orientationStr string, size SizeType) { +} + +// SetAutoPageBreak does nothing because you cannot add pages to a template +func (t *Tpl) SetAutoPageBreak(auto bool, margin float64) { +} diff --git a/vendor/github.com/jung-kurt/gofpdf/ttfparser.go b/vendor/github.com/jung-kurt/gofpdf/ttfparser.go new file mode 100644 index 0000000..669ab4d --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/ttfparser.go @@ -0,0 +1,374 @@ +/* + * Copyright (c) 2013 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gofpdf + +// Utility to parse TTF font files +// Version: 1.0 +// Date: 2011-06-18 +// Author: Olivier PLATHEY +// Port to Go: Kurt Jung, 2013-07-15 + +import ( + "encoding/binary" + "fmt" + "os" + "regexp" + "strings" +) + +// TtfType contains metrics of a TrueType font. +type TtfType struct { + Embeddable bool + UnitsPerEm uint16 + PostScriptName string + Bold bool + ItalicAngle int16 + IsFixedPitch bool + TypoAscender int16 + TypoDescender int16 + UnderlinePosition int16 + UnderlineThickness int16 + Xmin, Ymin, Xmax, Ymax int16 + CapHeight int16 + Widths []uint16 + Chars map[uint16]uint16 +} + +type ttfParser struct { + rec TtfType + f *os.File + tables map[string]uint32 + numberOfHMetrics uint16 + numGlyphs uint16 +} + +// TtfParse extracts various metrics from a TrueType font file. +func TtfParse(fileStr string) (TtfRec TtfType, err error) { + var t ttfParser + t.f, err = os.Open(fileStr) + if err != nil { + return + } + version, err := t.ReadStr(4) + if err != nil { + return + } + if version == "OTTO" { + err = fmt.Errorf("fonts based on PostScript outlines are not supported") + return + } + if version != "\x00\x01\x00\x00" { + err = fmt.Errorf("unrecognized file format") + return + } + numTables := int(t.ReadUShort()) + t.Skip(3 * 2) // searchRange, entrySelector, rangeShift + t.tables = make(map[string]uint32) + var tag string + for j := 0; j < numTables; j++ { + tag, err = t.ReadStr(4) + if err != nil { + return + } + t.Skip(4) // checkSum + offset := t.ReadULong() + t.Skip(4) // length + t.tables[tag] = offset + } + err = t.ParseComponents() + if err != nil { + return + } + t.f.Close() + TtfRec = t.rec + return +} + +func (t *ttfParser) ParseComponents() (err error) { + err = t.ParseHead() + if err == nil { + err = t.ParseHhea() + if err == nil { + err = t.ParseMaxp() + if err == nil { + err = t.ParseHmtx() + if err == nil { + err = t.ParseCmap() + if err == nil { + err = t.ParseName() + if err == nil { + err = t.ParseOS2() + if err == nil { + err = t.ParsePost() + } + } + } + } + } + } + } + return +} + +func (t *ttfParser) ParseHead() (err error) { + err = t.Seek("head") + t.Skip(3 * 4) // version, fontRevision, checkSumAdjustment + magicNumber := t.ReadULong() + if magicNumber != 0x5F0F3CF5 { + err = fmt.Errorf("incorrect magic number") + return + } + t.Skip(2) // flags + t.rec.UnitsPerEm = t.ReadUShort() + t.Skip(2 * 8) // created, modified + t.rec.Xmin = t.ReadShort() + t.rec.Ymin = t.ReadShort() + t.rec.Xmax = t.ReadShort() + t.rec.Ymax = t.ReadShort() + return +} + +func (t *ttfParser) ParseHhea() (err error) { + err = t.Seek("hhea") + if err == nil { + t.Skip(4 + 15*2) + t.numberOfHMetrics = t.ReadUShort() + } + return +} + +func (t *ttfParser) ParseMaxp() (err error) { + err = t.Seek("maxp") + if err == nil { + t.Skip(4) + t.numGlyphs = t.ReadUShort() + } + return +} + +func (t *ttfParser) ParseHmtx() (err error) { + err = t.Seek("hmtx") + if err == nil { + t.rec.Widths = make([]uint16, 0, 8) + for j := uint16(0); j < t.numberOfHMetrics; j++ { + t.rec.Widths = append(t.rec.Widths, t.ReadUShort()) + t.Skip(2) // lsb + } + if t.numberOfHMetrics < t.numGlyphs { + lastWidth := t.rec.Widths[t.numberOfHMetrics-1] + for j := t.numberOfHMetrics; j < t.numGlyphs; j++ { + t.rec.Widths = append(t.rec.Widths, lastWidth) + } + } + } + return +} + +func (t *ttfParser) ParseCmap() (err error) { + var offset int64 + if err = t.Seek("cmap"); err != nil { + return + } + t.Skip(2) // version + numTables := int(t.ReadUShort()) + offset31 := int64(0) + for j := 0; j < numTables; j++ { + platformID := t.ReadUShort() + encodingID := t.ReadUShort() + offset = int64(t.ReadULong()) + if platformID == 3 && encodingID == 1 { + offset31 = offset + } + } + if offset31 == 0 { + err = fmt.Errorf("no Unicode encoding found") + return + } + startCount := make([]uint16, 0, 8) + endCount := make([]uint16, 0, 8) + idDelta := make([]int16, 0, 8) + idRangeOffset := make([]uint16, 0, 8) + t.rec.Chars = make(map[uint16]uint16) + t.f.Seek(int64(t.tables["cmap"])+offset31, os.SEEK_SET) + format := t.ReadUShort() + if format != 4 { + err = fmt.Errorf("unexpected subtable format: %d", format) + return + } + t.Skip(2 * 2) // length, language + segCount := int(t.ReadUShort() / 2) + t.Skip(3 * 2) // searchRange, entrySelector, rangeShift + for j := 0; j < segCount; j++ { + endCount = append(endCount, t.ReadUShort()) + } + t.Skip(2) // reservedPad + for j := 0; j < segCount; j++ { + startCount = append(startCount, t.ReadUShort()) + } + for j := 0; j < segCount; j++ { + idDelta = append(idDelta, t.ReadShort()) + } + offset, _ = t.f.Seek(int64(0), os.SEEK_CUR) + for j := 0; j < segCount; j++ { + idRangeOffset = append(idRangeOffset, t.ReadUShort()) + } + for j := 0; j < segCount; j++ { + c1 := startCount[j] + c2 := endCount[j] + d := idDelta[j] + ro := idRangeOffset[j] + if ro > 0 { + t.f.Seek(offset+2*int64(j)+int64(ro), os.SEEK_SET) + } + for c := c1; c <= c2; c++ { + if c == 0xFFFF { + break + } + var gid int32 + if ro > 0 { + gid = int32(t.ReadUShort()) + if gid > 0 { + gid += int32(d) + } + } else { + gid = int32(c) + int32(d) + } + if gid >= 65536 { + gid -= 65536 + } + if gid > 0 { + t.rec.Chars[c] = uint16(gid) + } + } + } + return +} + +func (t *ttfParser) ParseName() (err error) { + err = t.Seek("name") + if err == nil { + tableOffset, _ := t.f.Seek(0, os.SEEK_CUR) + t.rec.PostScriptName = "" + t.Skip(2) // format + count := t.ReadUShort() + stringOffset := t.ReadUShort() + for j := uint16(0); j < count && t.rec.PostScriptName == ""; j++ { + t.Skip(3 * 2) // platformID, encodingID, languageID + nameID := t.ReadUShort() + length := t.ReadUShort() + offset := t.ReadUShort() + if nameID == 6 { + // PostScript name + t.f.Seek(int64(tableOffset)+int64(stringOffset)+int64(offset), os.SEEK_SET) + var s string + s, err = t.ReadStr(int(length)) + if err != nil { + return + } + s = strings.Replace(s, "\x00", "", -1) + var re *regexp.Regexp + if re, err = regexp.Compile("[(){}<> /%[\\]]"); err != nil { + return + } + t.rec.PostScriptName = re.ReplaceAllString(s, "") + } + } + if t.rec.PostScriptName == "" { + err = fmt.Errorf("the name PostScript was not found") + } + } + return +} + +func (t *ttfParser) ParseOS2() (err error) { + err = t.Seek("OS/2") + if err == nil { + version := t.ReadUShort() + t.Skip(3 * 2) // xAvgCharWidth, usWeightClass, usWidthClass + fsType := t.ReadUShort() + t.rec.Embeddable = (fsType != 2) && (fsType&0x200) == 0 + t.Skip(11*2 + 10 + 4*4 + 4) + fsSelection := t.ReadUShort() + t.rec.Bold = (fsSelection & 32) != 0 + t.Skip(2 * 2) // usFirstCharIndex, usLastCharIndex + t.rec.TypoAscender = t.ReadShort() + t.rec.TypoDescender = t.ReadShort() + if version >= 2 { + t.Skip(3*2 + 2*4 + 2) + t.rec.CapHeight = t.ReadShort() + } else { + t.rec.CapHeight = 0 + } + } + return +} + +func (t *ttfParser) ParsePost() (err error) { + err = t.Seek("post") + if err == nil { + t.Skip(4) // version + t.rec.ItalicAngle = t.ReadShort() + t.Skip(2) // Skip decimal part + t.rec.UnderlinePosition = t.ReadShort() + t.rec.UnderlineThickness = t.ReadShort() + t.rec.IsFixedPitch = t.ReadULong() != 0 + } + return +} + +func (t *ttfParser) Seek(tag string) (err error) { + ofs, ok := t.tables[tag] + if ok { + t.f.Seek(int64(ofs), os.SEEK_SET) + } else { + err = fmt.Errorf("table not found: %s", tag) + } + return +} + +func (t *ttfParser) Skip(n int) { + t.f.Seek(int64(n), os.SEEK_CUR) +} + +func (t *ttfParser) ReadStr(length int) (str string, err error) { + var n int + buf := make([]byte, length) + n, err = t.f.Read(buf) + if err == nil { + if n == length { + str = string(buf) + } else { + err = fmt.Errorf("unable to read %d bytes", length) + } + } + return +} + +func (t *ttfParser) ReadUShort() (val uint16) { + binary.Read(t.f, binary.BigEndian, &val) + return +} + +func (t *ttfParser) ReadShort() (val int16) { + binary.Read(t.f, binary.BigEndian, &val) + return +} + +func (t *ttfParser) ReadULong() (val uint32) { + binary.Read(t.f, binary.BigEndian, &val) + return +} diff --git a/vendor/github.com/jung-kurt/gofpdf/util.go b/vendor/github.com/jung-kurt/gofpdf/util.go new file mode 100644 index 0000000..149271c --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/util.go @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2013 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gofpdf + +import ( + "bytes" + "compress/zlib" + "fmt" + // "github.com/davecgh/go-spew/spew" + "bufio" + "io" + "math" + "os" + "path/filepath" + "strings" +) + +func round(f float64) int { + if f < 0 { + return -int(math.Floor(-f + 0.5)) + } + return int(math.Floor(f + 0.5)) +} + +func sprintf(fmtStr string, args ...interface{}) string { + return fmt.Sprintf(fmtStr, args...) +} + +// Returns true if the specified normal file exists +func fileExist(filename string) (ok bool) { + info, err := os.Stat(filename) + if err == nil { + if ^os.ModePerm&info.Mode() == 0 { + ok = true + } + } + return ok +} + +// Returns the size of the specified file; ok will be false +// if the file does not exist or is not an ordinary file +func fileSize(filename string) (size int64, ok bool) { + info, err := os.Stat(filename) + ok = err == nil + if ok { + size = info.Size() + } + return +} + +// Returns a new buffer populated with the contents of the specified Reader +func bufferFromReader(r io.Reader) (b *bytes.Buffer, err error) { + b = new(bytes.Buffer) + _, err = b.ReadFrom(r) + return +} + +// Returns true if the two specified float slices are equal +func slicesEqual(a, b []float64) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if a[i] != b[i] { + return false + } + } + return true +} + +// Returns a zlib-compressed copy of the specified byte array +func sliceCompress(data []byte) []byte { + var buf bytes.Buffer + cmp, _ := zlib.NewWriterLevel(&buf, zlib.BestSpeed) + cmp.Write(data) + cmp.Close() + return buf.Bytes() +} + +// Returns an uncompressed copy of the specified zlib-compressed byte array +func sliceUncompress(data []byte) (outData []byte, err error) { + inBuf := bytes.NewBuffer(data) + r, err := zlib.NewReader(inBuf) + defer r.Close() + if err == nil { + var outBuf bytes.Buffer + _, err = outBuf.ReadFrom(r) + if err == nil { + outData = outBuf.Bytes() + } + } + return +} + +// Convert UTF-8 to UTF-16BE with BOM; from http://www.fpdf.org/ +func utf8toutf16(s string) string { + res := make([]byte, 0, 8) + res = append(res, 0xFE, 0xFF) + nb := len(s) + i := 0 + for i < nb { + c1 := byte(s[i]) + i++ + if c1 >= 224 { + // 3-byte character + c2 := byte(s[i]) + i++ + c3 := byte(s[i]) + i++ + res = append(res, ((c1&0x0F)<<4)+((c2&0x3C)>>2), + ((c2&0x03)<<6)+(c3&0x3F)) + } else if c1 >= 192 { + // 2-byte character + c2 := byte(s[i]) + i++ + res = append(res, ((c1 & 0x1C) >> 2), + ((c1&0x03)<<6)+(c2&0x3F)) + } else { + // Single-byte character + res = append(res, 0, c1) + } + } + return string(res) +} + +// Return a if cnd is true, otherwise b +func intIf(cnd bool, a, b int) int { + if cnd { + return a + } + return b +} + +// Return aStr if cnd is true, otherwise bStr +func strIf(cnd bool, aStr, bStr string) string { + if cnd { + return aStr + } + return bStr +} + +// Dump the internals of the specified values +// func dump(fileStr string, a ...interface{}) { +// fl, err := os.OpenFile(fileStr, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600) +// if err == nil { +// fmt.Fprintf(fl, "----------------\n") +// spew.Fdump(fl, a...) +// fl.Close() +// } +// } + +func repClosure(m map[rune]byte) func(string) string { + var buf bytes.Buffer + return func(str string) string { + var ch byte + var ok bool + buf.Truncate(0) + for _, r := range str { + if r < 0x80 { + ch = byte(r) + } else { + ch, ok = m[r] + if !ok { + ch = byte('.') + } + } + buf.WriteByte(ch) + } + return buf.String() + } +} + +// UnicodeTranslator returns a function that can be used to translate, where +// possible, utf-8 strings to a form that is compatible with the specified code +// page. The returned function accepts a string and returns a string. +// +// r is a reader that should read a buffer made up of content lines that +// pertain to the code page of interest. Each line is made up of three +// whitespace separated fields. The first begins with "!" and is followed by +// two hexadecimal digits that identify the glyph position in the code page of +// interest. The second field begins with "U+" and is followed by the unicode +// code point value. The third is the glyph name. A number of these code page +// map files are packaged with the gfpdf library in the font directory. +// +// An error occurs only if a line is read that does not conform to the expected +// format. In this case, the returned function is valid but does not perform +// any rune translation. +func UnicodeTranslator(r io.Reader) (f func(string) string, err error) { + m := make(map[rune]byte) + var uPos, cPos uint32 + var lineStr, nameStr string + sc := bufio.NewScanner(r) + for sc.Scan() { + lineStr = sc.Text() + lineStr = strings.TrimSpace(lineStr) + if len(lineStr) > 0 { + _, err = fmt.Sscanf(lineStr, "!%2X U+%4X %s", &cPos, &uPos, &nameStr) + if err == nil { + if cPos >= 0x80 { + m[rune(uPos)] = byte(cPos) + } + } + } + } + if err == nil { + f = repClosure(m) + } else { + f = func(s string) string { + return s + } + } + return +} + +// UnicodeTranslatorFromFile returns a function that can be used to translate, +// where possible, utf-8 strings to a form that is compatible with the +// specified code page. See UnicodeTranslator for more details. +// +// fileStr identifies a font descriptor file that maps glyph positions to names. +// +// If an error occurs reading the file, the returned function is valid but does +// not perform any rune translation. +func UnicodeTranslatorFromFile(fileStr string) (f func(string) string, err error) { + var fl *os.File + fl, err = os.Open(fileStr) + if err == nil { + f, err = UnicodeTranslator(fl) + fl.Close() + } else { + f = func(s string) string { + return s + } + } + return +} + +// UnicodeTranslatorFromDescriptor returns a function that can be used to +// translate, where possible, utf-8 strings to a form that is compatible with +// the specified code page. See UnicodeTranslator for more details. +// +// cpStr identifies a code page. A descriptor file in the font directory, set +// with the fontDirStr argument in the call to New(), should have this name +// plus the extension ".map". If cpStr is empty, it will be replaced with +// "cp1252", the gofpdf code page default. +// +// If an error occurs reading the descriptor, the returned function is valid +// but does not perform any rune translation. +// +// The CellFormat (4) example demonstrates this method. +func (f *Fpdf) UnicodeTranslatorFromDescriptor(cpStr string) (rep func(string) string) { + var str string + var ok bool + if f.err != nil { + return + } + if len(cpStr) == 0 { + cpStr = "cp1252" + } + str, ok = embeddedMapList[cpStr] + if ok { + rep, f.err = UnicodeTranslator(strings.NewReader(str)) + } else { + rep, f.err = UnicodeTranslatorFromFile(filepath.Join(f.fontpath, cpStr) + ".map") + } + return +} + +// Transform moves a point by given X, Y offset +func (p *PointType) Transform(x, y float64) PointType { + return PointType{p.X + x, p.Y + y} +} + +// Orientation returns the orientation of a given size: +// "P" for portrait, "L" for landscape +func (s *SizeType) Orientation() string { + if s == nil || s.Ht == s.Wd { + return "" + } + if s.Wd > s.Ht { + return "L" + } + return "P" +} + +// ScaleBy expands a size by a certain factor +func (s *SizeType) ScaleBy(factor float64) SizeType { + return SizeType{s.Wd * factor, s.Ht * factor} +} + +// ScaleToWidth adjusts the height of a size to match the given width +func (s *SizeType) ScaleToWidth(width float64) SizeType { + height := s.Ht * width / s.Wd + return SizeType{width, height} +} + +// ScaleToHeight adjusts the width of a size to match the given height +func (s *SizeType) ScaleToHeight(height float64) SizeType { + width := s.Wd * height / s.Ht + return SizeType{width, height} +} |
