diff --git a/docs/PLAN.md b/docs/CHECK_PLAN.md similarity index 100% rename from docs/PLAN.md rename to docs/CHECK_PLAN.md diff --git a/docs/img/badges.svg b/docs/img/badges.svg index c338e7f..7e7b18d 100644 --- a/docs/img/badges.svg +++ b/docs/img/badges.svg @@ -51,7 +51,7 @@ text-anchor="middle" font-family="sans-serif" font-size="11" fill="white">Coverage 82.7% + text-anchor="middle" font-family="sans-serif" font-size="11" fill="white">82.5% diff --git a/fpdf/attachments.go b/fpdf/attachments.go index 180a358..838635f 100644 --- a/fpdf/attachments.go +++ b/fpdf/attachments.go @@ -1,3 +1,5 @@ +//go:build !wasm + // Copyright ©2023 The go-pdf Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. diff --git a/fpdf/attachments_wasm.go b/fpdf/attachments_wasm.go new file mode 100644 index 0000000..a4352a9 --- /dev/null +++ b/fpdf/attachments_wasm.go @@ -0,0 +1,43 @@ +//go:build wasm + +package fpdf + +import ( + . "github.com/tinywasm/fmt" +) + +type Attachment struct { + Content []byte + Filename string + Description string + objectNumber int +} + +type annotationAttach struct { + *Attachment + x, y, w, h float64 +} + +func (f *Fpdf) SetAttachments(as []Attachment) { + f.err = Err("attachments", "unsupported", "in WASM") +} + +func (f *Fpdf) AddAttachmentAnnotation(a *Attachment, x, y, w, h float64) { + f.err = Err("attachments", "unsupported", "in WASM") +} + +func (f *Fpdf) putAttachments() { + // no-op in WASM +} + +func (f *Fpdf) putAnnotationsAttachments() { + // no-op in WASM +} + +func (f *Fpdf) getEmbeddedFiles() string { + return "" +} + +func (f *Fpdf) putAttachmentAnnotationLinks(out *fmtBuffer, page int) { + // no-op in WASM +} diff --git a/fpdf/def.go b/fpdf/def.go index 9828fb2..d8f28f3 100644 --- a/fpdf/def.go +++ b/fpdf/def.go @@ -675,7 +675,7 @@ func (f *fontDefType) Schema() []fmt.Field { {Name: "Desc", Type: fmt.FieldStruct}, {Name: "Up", Type: fmt.FieldInt}, {Name: "Ut", Type: fmt.FieldInt}, - {Name: "Cw", Type: fmt.FieldInt}, + {Name: "Cw", Type: fmt.FieldIntSlice}, {Name: "Enc", Type: fmt.FieldText}, {Name: "Diff", Type: fmt.FieldText}, {Name: "File", Type: fmt.FieldText}, diff --git a/fpdf/exampleDir_test.go b/fpdf/exampleDir_test.go index 969f383..68968d0 100644 --- a/fpdf/exampleDir_test.go +++ b/fpdf/exampleDir_test.go @@ -52,8 +52,8 @@ func NewDocPdfTest(options ...any) *fpdf.Fpdf { pdf := fpdf.New(options...) pdf.SetCompression(false) pdf.SetCatalogSort(true) - pdf.SetCreationDate(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)) - pdf.SetModificationDate(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)) + pdf.SetCreationDate(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC).UnixNano()) + pdf.SetModificationDate(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC).UnixNano()) return pdf } diff --git a/fpdf/font.go b/fpdf/font.go index 676a122..54478e6 100644 --- a/fpdf/font.go +++ b/fpdf/font.go @@ -1,3 +1,5 @@ +//go:build !wasm + package fpdf import ( @@ -12,6 +14,28 @@ import ( . "github.com/tinywasm/fmt" ) +// fileExist 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 +} + +// fileSize 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 +} + func baseNoExt(fileStr string) string { str := filepath.Base(fileStr) extLen := len(filepath.Ext(str)) diff --git a/fpdf/fontid_wasm.go b/fpdf/fontid.go similarity index 53% rename from fpdf/fontid_wasm.go rename to fpdf/fontid.go index 6599fb5..ee35555 100644 --- a/fpdf/fontid_wasm.go +++ b/fpdf/fontid.go @@ -1,18 +1,19 @@ -//go:build wasm - package fpdf import ( - . "github.com/tinywasm/fmt" + "github.com/tinywasm/unixid" ) +var uid, _ = unixid.NewUnixID() + func generateImageID(info *ImageInfoType) (string, error) { - // Simple deterministic ID for WASM to avoid crypto/sha1 - return Sprintf("img_%d_%d_%d", int(info.w), int(info.h), len(info.data)), nil + var id string + uid.SetNewID(&id) + return id, nil } // generateFontID generates a font Id from the font definition func generateFontID(fdt fontDefType) (string, error) { - // Simple deterministic ID for WASM + // Simple deterministic ID return fdt.Tp + "_" + fdt.Name, nil } diff --git a/fpdf/fontid_back.go b/fpdf/fontid_back.go deleted file mode 100644 index ab940f1..0000000 --- a/fpdf/fontid_back.go +++ /dev/null @@ -1,40 +0,0 @@ -//go:build !wasm - -package fpdf - -import ( - "crypto/sha1" - "encoding/json" - . "github.com/tinywasm/fmt" -) - -func generateImageID(info *ImageInfoType) (string, error) { - sha := sha1.New() - enc := newIDEncoder(sha) - enc.bytes(info.data) - enc.bytes(info.smask) - enc.i64(int64(info.n)) - enc.f64(info.w) - enc.f64(info.h) - enc.str(info.cs) - enc.bytes(info.pal) - enc.i64(int64(info.bpc)) - enc.str(info.f) - enc.str(info.dp) - for _, v := range info.trns { - enc.i64(int64(v)) - } - enc.f64(info.scale) - enc.f64(info.dpi) - enc.str(info.i) - - return Sprintf("%x", sha.Sum(nil)), nil -} - -// generateFontID generates a font Id from the font definition -func generateFontID(fdt fontDefType) (string, error) { - // file can be different if generated in different instance - fdt.File = "" - b, err := json.Marshal(&fdt) - return Sprintf("%x", sha1.Sum(b)), err -} diff --git a/fpdf/fonts_json_wasm.go b/fpdf/fonts_json.go similarity index 89% rename from fpdf/fonts_json_wasm.go rename to fpdf/fonts_json.go index b041266..2ba4385 100644 --- a/fpdf/fonts_json_wasm.go +++ b/fpdf/fonts_json.go @@ -1,5 +1,3 @@ -//go:build wasm - package fpdf import ( diff --git a/fpdf/fonts_json_back.go b/fpdf/fonts_json_back.go deleted file mode 100644 index 731f824..0000000 --- a/fpdf/fonts_json_back.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build !wasm - -package fpdf - -import ( - "encoding/json" -) - -func unmarshalFontDef(data []byte, def *fontDefType) error { - return json.Unmarshal(data, def) -} diff --git a/fpdf/fpdf_test.go b/fpdf/fpdf_test.go index 852cd50..a370be1 100644 --- a/fpdf/fpdf_test.go +++ b/fpdf/fpdf_test.go @@ -1296,7 +1296,7 @@ func Test_SVGBasicWrite(t *testing.T) { `web control is supported and is used in this example.` html := pdf.HTMLBasicNew() html.Write(lineHt, htmlStr) - sig, err = fpdf.SVGBasicFileParse(ImageFile(sigFileStr)) + sig, err = pdf.SVGBasicFileParse(ImageFile(sigFileStr)) if err == nil { scale := 100 / sig.Wd scaleY := 30 / sig.Ht @@ -1345,7 +1345,7 @@ func Test_SVGBasicDraw(t *testing.T) { `size is used. scale 1.0 is pt` html := pdf.HTMLBasicNew() html.Write(lineHt, htmlStr) - sig, err = fpdf.SVGBasicFileParse(ImageFile(sigFileStr)) + sig, err = pdf.SVGBasicFileParse(ImageFile(sigFileStr)) if err == nil { pdf.SetLineCapStyle("round") pdf.SetLineWidth(0.15) @@ -2696,7 +2696,7 @@ func Test_SetModificationDate(t *testing.T) { // ModDate: Sun Jan 2 10:22:30 2000 pdf := NewDocPdfTest() pdf.AddPage() - pdf.SetModificationDate(time.Date(2000, 1, 2, 10, 22, 30, 0, time.UTC)) + pdf.SetModificationDate(time.Date(2000, 1, 2, 10, 22, 30, 0, time.UTC).UnixNano()) fileStr := Filename("Test_SetModificationDate") err := pdf.OutputFileAndClose(fileStr) SummaryCompare(err, fileStr) diff --git a/fpdf/getter_test.go b/fpdf/getter_test.go index a05edcd..1655a90 100644 --- a/fpdf/getter_test.go +++ b/fpdf/getter_test.go @@ -124,13 +124,14 @@ func TestGetConversionRatio(t *testing.T) { } func TestGetCreationDate(t *testing.T) { - setDate, _ := time.Parse(time.RFC3339, "2003-06-17T01:23:45Z") + tm, _ := time.Parse(time.RFC3339, "2003-06-17T01:23:45Z") + setDate := tm.UnixNano() pdf := NewDocPdfTest() pdf.SetCreationDate(setDate) creationDate := pdf.GetCreationDate() - if got, want := creationDate, setDate; !got.Equal(want) { + if got, want := creationDate, setDate; got != want { t.Errorf("invalid creationDate: got=%v, want=%v", got, want) } } @@ -446,13 +447,14 @@ func TestGetMargins(t *testing.T) { } func TestGetModificationDate(t *testing.T) { - setDate, _ := time.Parse(time.RFC3339, "9-08-02T09:54:32Z") + tm, _ := time.Parse(time.RFC3339, "2009-08-02T09:54:32Z") + setDate := tm.UnixNano() pdf := NewDocPdfTest() pdf.SetModificationDate(setDate) modificationDate := pdf.GetModificationDate() - if got, want := modificationDate, setDate; !got.Equal(want) { + if got, want := modificationDate, setDate; got != want { t.Errorf("invalid modificationDate: got=%v, want=%v", got, want) } } diff --git a/fpdf/list/list.go b/fpdf/list/list.go index 8c54f4b..4f5b27a 100644 --- a/fpdf/list/list.go +++ b/fpdf/list/list.go @@ -1,3 +1,5 @@ +//go:build !wasm + package main import ( diff --git a/fpdf/svgbasic.go b/fpdf/svgbasic.go index 7c002c1..84262ff 100644 --- a/fpdf/svgbasic.go +++ b/fpdf/svgbasic.go @@ -2,7 +2,6 @@ package fpdf import ( "encoding/xml" - "os" . "github.com/tinywasm/fmt" ) @@ -297,9 +296,9 @@ func SVGBasicParse(buf []byte) (sig SVGBasicType, err error) { // 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) { +func (f *Fpdf) SVGBasicFileParse(svgFileStr string) (sig SVGBasicType, err error) { var buf []byte - buf, err = os.ReadFile(svgFileStr) + buf, err = f.readFile(svgFileStr) if err == nil { sig, err = SVGBasicParse(buf) } diff --git a/fpdf/time_wasm.go b/fpdf/time.go similarity index 99% rename from fpdf/time_wasm.go rename to fpdf/time.go index 0ed887a..d8c107a 100644 --- a/fpdf/time_wasm.go +++ b/fpdf/time.go @@ -1,5 +1,3 @@ -//go:build wasm - package fpdf import ( diff --git a/fpdf/time_back.go b/fpdf/time_back.go deleted file mode 100644 index d40b22e..0000000 --- a/fpdf/time_back.go +++ /dev/null @@ -1,57 +0,0 @@ -//go:build !wasm - -package fpdf - -import "time" - -// 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 = pdfTime(tm) -} - -// SetDefaultModificationDate sets the default value of the document modification date -// that will be used when initializing a new Fpdf instance. See -// SetCreationDate() for more details. -func SetDefaultModificationDate(tm time.Time) { - gl.modDate = pdfTime(tm) -} - -// GetCreationDate returns the document's internal CreationDate value. -func (f *Fpdf) GetCreationDate() time.Time { - return time.Time(f.creationDate) -} - -// 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 -// comparison. Specify a zero-value time to revert to the default behavior. -func (f *Fpdf) SetCreationDate(tm time.Time) { - f.creationDate = pdfTime(tm) -} - -// GetModificationDate returns the document's internal ModDate value. -func (f *Fpdf) GetModificationDate() time.Time { - return time.Time(f.modDate) -} - -// SetModificationDate fixes the document's internal ModDate value. -// See `SetCreationDate` for more details. -func (f *Fpdf) SetModificationDate(tm time.Time) { - f.modDate = pdfTime(tm) -} - -// returns Now() if tm is zero -func timeOrNow(tm pdfTime) time.Time { - t := time.Time(tm) - if t.IsZero() { - return time.Now() - } - return t -} - -func formatPDFDate(tm pdfTime) string { - t := timeOrNow(tm) - return "D:" + t.Format("20060102150405") -} diff --git a/fpdf/types_wasm.go b/fpdf/types.go similarity index 66% rename from fpdf/types_wasm.go rename to fpdf/types.go index cb0784c..ae95b1e 100644 --- a/fpdf/types_wasm.go +++ b/fpdf/types.go @@ -1,5 +1,3 @@ -//go:build wasm - package fpdf type pdfTime int64 diff --git a/fpdf/types_back.go b/fpdf/types_back.go deleted file mode 100644 index 2cc61e0..0000000 --- a/fpdf/types_back.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build !wasm - -package fpdf - -import "time" - -type pdfTime time.Time diff --git a/fpdf/util.go b/fpdf/util.go index 8f13e04..46bbd61 100644 --- a/fpdf/util.go +++ b/fpdf/util.go @@ -5,7 +5,6 @@ import ( "bytes" "io" "math" - "os" . "github.com/tinywasm/fmt" ) @@ -33,27 +32,6 @@ func sprintf(fmtStr string, args ...any) string { return Sprintf(fmtStr, args...) } -// fileExist 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 -} - -// fileSize 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 -} // utf8toutf16 converts UTF-8 to UTF-16BE; from http://www.fpdf.org/ func utf8toutf16(s string, withBOM ...bool) string { diff --git a/go.mod b/go.mod index 3dad9ed..094b413 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,9 @@ go 1.25.2 require ( github.com/tinywasm/fetch v0.1.23 - github.com/tinywasm/fmt v0.22.2 - github.com/tinywasm/json v0.4.1 - github.com/tinywasm/time v0.4.0 + github.com/tinywasm/fmt v0.23.6 + github.com/tinywasm/json v0.5.2 + github.com/tinywasm/time v0.5.0 ) + +require github.com/tinywasm/unixid v0.2.23 diff --git a/go.sum b/go.sum index 38c0737..2d9f1b3 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,10 @@ github.com/tinywasm/fetch v0.1.23 h1:R8Nr1LwcFUVgQsk5f0CilNNP8r0wc3DPaZuC5O8hYTM= github.com/tinywasm/fetch v0.1.23/go.mod h1:XR4SHs1qYUFcPcFVw/r+TrwG+9+jENQPslWAKVC6nHQ= -github.com/tinywasm/fmt v0.22.2 h1:/KL2WP3kNlRrkjK//0rwZpF80sxV7p3o3KyvYaeMCQE= -github.com/tinywasm/fmt v0.22.2/go.mod h1:L2GCAi6asgytPV6TVvGrRq5Ml+DkUt1Ijo5i/2J1jOY= -github.com/tinywasm/json v0.4.1 h1:UjBmaoDhUdD43ekAJ82PzzCT8nudYKFoa9sKBU/DPQs= -github.com/tinywasm/json v0.4.1/go.mod h1:+HsLi3s5kjiZTnv8+1kyV+IS274oU3iRD1NS5T5PkHM= -github.com/tinywasm/time v0.4.0 h1:Wo5qFsIM3hg1gy9iADRsbKrKnOt+wG5tFZIrpbWV55E= -github.com/tinywasm/time v0.4.0/go.mod h1:/c7FOB2jSYEyaQh+/f0g9UflP+Th6U91F6ghO8zbvcs= +github.com/tinywasm/fmt v0.23.6 h1:DXugqAD98VEeBKeguQqAWHzUnxhuESHRTDinyNHlSpk= +github.com/tinywasm/fmt v0.23.6/go.mod h1:L2GCAi6asgytPV6TVvGrRq5Ml+DkUt1Ijo5i/2J1jOY= +github.com/tinywasm/json v0.5.2 h1:ykHdD2qz2k+6r+trffNIVHfvdS46Ib+/8tSUKXx+EdY= +github.com/tinywasm/json v0.5.2/go.mod h1:uA5JXnQcz3T5XdKfwFKloZFvfP7TWgas41zmCM57UJU= +github.com/tinywasm/time v0.5.0 h1:M17DNgKrMYfkCK42V6miL9AcwfN/FHghbKOSTXJrkMo= +github.com/tinywasm/time v0.5.0/go.mod h1:vxGAkKA40im4ObiTS6hcsJYiIsVVLSz/A63JC/+TwvA= +github.com/tinywasm/unixid v0.2.23 h1:Lp/TER0RwbaT7EcHbQNzXj9LOGA2VD8rC8XLYmxJBc0= +github.com/tinywasm/unixid v0.2.23/go.mod h1:5KPbI26CrW8S7rgMS46gqlLKTYPno3QH49GSB5NSLMU= diff --git a/tests/test_api.pdf b/tests/test_api.pdf index c3cad62..ac7b598 100644 Binary files a/tests/test_api.pdf and b/tests/test_api.pdf differ diff --git a/tests/test_charts.pdf b/tests/test_charts.pdf index 63f0216..e956d4d 100644 Binary files a/tests/test_charts.pdf and b/tests/test_charts.pdf differ diff --git a/tests/test_table.pdf b/tests/test_table.pdf index 4f8cb0f..81b5476 100644 Binary files a/tests/test_table.pdf and b/tests/test_table.pdf differ diff --git a/web/public/client.wasm b/web/public/client.wasm index a38c9b2..53b0fd9 100755 Binary files a/web/public/client.wasm and b/web/public/client.wasm differ