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