mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 17:27:08 +08:00
1 parent
aa1fcd4cd6
commit
54995fb60e
10 files changed
+62
-22
No files matched your search
@@ -10,7 +10,7 @@ require (
|
|||||||
github.com/tdewolff/canvas v0.0.0-20260923214215-09804640d00c
|
github.com/tdewolff/canvas v0.0.0-20260923214215-09804640d00c
|
||||||
github.com/tdewolff/font v0.0.0-20260913163313-54f98bb59ee6
|
github.com/tdewolff/font v0.0.0-20260913163313-54f98bb59ee6
|
||||||
github.com/xiaoqidun/jbig2 v1.1.1
|
github.com/xiaoqidun/jbig2 v1.1.1
|
||||||
github.com/xiaoqidun/pdfgo v0.0.0-20261003042717-ffb073d5634d
|
github.com/xiaoqidun/pdfgo v0.0.0-20261003103143-2420f94d9b97
|
||||||
golang.org/x/crypto v0.57.0
|
golang.org/x/crypto v0.57.0
|
||||||
golang.org/x/image v0.46.0
|
golang.org/x/image v0.46.0
|
||||||
golang.org/x/text v0.42.0
|
golang.org/x/text v0.42.0
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ github.com/tdewolff/test v1.0.12 h1:7F21DqIajswxuche0geHdrUZRCWE4oko4b7bcmkkrxk=
|
|||||||
github.com/tdewolff/test v1.0.12/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
|
github.com/tdewolff/test v1.0.12/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
|
||||||
github.com/xiaoqidun/jbig2 v1.1.1 h1:SjliS9ZO0e9HX5oYUfBuXrfFsXhWricrSz+XY4zORDI=
|
github.com/xiaoqidun/jbig2 v1.1.1 h1:SjliS9ZO0e9HX5oYUfBuXrfFsXhWricrSz+XY4zORDI=
|
||||||
github.com/xiaoqidun/jbig2 v1.1.1/go.mod h1:8QonVWtENmh2kc6l+leqeGl7psb79DWlHDkCpdChjfQ=
|
github.com/xiaoqidun/jbig2 v1.1.1/go.mod h1:8QonVWtENmh2kc6l+leqeGl7psb79DWlHDkCpdChjfQ=
|
||||||
github.com/xiaoqidun/pdfgo v0.0.0-20261003042717-ffb073d5634d h1:WiG6LgYU1hZBAELi72qP6UnCyA8cPe7Ap6nto0ofGnA=
|
github.com/xiaoqidun/pdfgo v0.0.0-20261003103143-2420f94d9b97 h1:1YHWQ3BBFJd4RlWAEGhHHQ6D+OI/nriU91YIUzxZo8o=
|
||||||
github.com/xiaoqidun/pdfgo v0.0.0-20261003042717-ffb073d5634d/go.mod h1:4Pf0JO0BEf1uzRY+uZjlMjN/OPn3PYa0YMi6cqPPTLQ=
|
github.com/xiaoqidun/pdfgo v0.0.0-20261003103143-2420f94d9b97/go.mod h1:4Pf0JO0BEf1uzRY+uZjlMjN/OPn3PYa0YMi6cqPPTLQ=
|
||||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||||
github.com/yuin/goldmark v1.8.5 h1:r6N5afV5qj/5S4UTch8agZHJ8UxNCMwX7WjkkJam2NA=
|
github.com/yuin/goldmark v1.8.5 h1:r6N5afV5qj/5S4UTch8agZHJ8UxNCMwX7WjkkJam2NA=
|
||||||
|
|||||||
@@ -330,7 +330,14 @@ func (e *Editor) documentRoot() string {
|
|||||||
// 返回: bool 是否为同一文档
|
// 返回: bool 是否为同一文档
|
||||||
func (e *Editor) sameDocument(other *Editor) bool {
|
func (e *Editor) sameDocument(other *Editor) bool {
|
||||||
if e.source == nil || other.source == nil {
|
if e.source == nil || other.source == nil {
|
||||||
return e.source == nil && other.source == nil
|
if e.source == nil && other.source == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
fresh, packaged := e, other
|
||||||
|
if fresh.source != nil {
|
||||||
|
fresh, packaged = other, e
|
||||||
|
}
|
||||||
|
return len(packaged.source.reader.OFD.DocBody) == 1 && (packaged.source.fromNew || fresh.Info.DocID != "" && fresh.Info.DocID == packaged.source.info.DocID)
|
||||||
}
|
}
|
||||||
return e.documentRoot() == other.documentRoot() && e.source.info.DocID == other.source.info.DocID
|
return e.documentRoot() == other.documentRoot() && e.source.info.DocID == other.source.info.DocID
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -684,6 +684,7 @@ func (e *Editor) importBase() (*editorSource, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
editor.source.idsReady = true
|
editor.source.idsReady = true
|
||||||
|
editor.source.fromNew = true
|
||||||
return editor.source, nil
|
return editor.source, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ type editorSource struct {
|
|||||||
info DocInfo
|
info DocInfo
|
||||||
fallbackDocID string
|
fallbackDocID string
|
||||||
directory string
|
directory string
|
||||||
|
fromNew bool
|
||||||
pages map[string]*editorSourcePage
|
pages map[string]*editorSourcePage
|
||||||
origins map[string]*editorObjectOrigin
|
origins map[string]*editorObjectOrigin
|
||||||
idsReady bool
|
idsReady bool
|
||||||
|
|||||||
+1
-1
@@ -78,7 +78,7 @@ type pdfImporter struct {
|
|||||||
pages map[pdfgo.Reference]*pdfgo.Page
|
pages map[pdfgo.Reference]*pdfgo.Page
|
||||||
pageIDs map[pdfgo.Reference]string
|
pageIDs map[pdfgo.Reference]string
|
||||||
pageIndexes map[pdfgo.Reference]int
|
pageIndexes map[pdfgo.Reference]int
|
||||||
imageIDs map[pdfImageKey]string
|
imageIDs map[pdfImageKey][]pdfImageResource
|
||||||
attachmentIDs map[pdfAttachmentKey]string
|
attachmentIDs map[pdfAttachmentKey]string
|
||||||
maskClips map[*pdfgo.SoftMask]pdfgo.Path
|
maskClips map[*pdfgo.SoftMask]pdfgo.Path
|
||||||
pageBox pdfgo.Rectangle
|
pageBox pdfgo.Rectangle
|
||||||
|
|||||||
+17
-5
@@ -20,6 +20,7 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"math"
|
"math"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
@@ -32,6 +33,12 @@ type pdfImageKey struct {
|
|||||||
intent pdfgo.Name
|
intent pdfgo.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pdfImageResource 保存图像的有效颜色空间及对应资源,避免跨资源重映射复用
|
||||||
|
type pdfImageResource struct {
|
||||||
|
space pdfgo.Object
|
||||||
|
id string
|
||||||
|
}
|
||||||
|
|
||||||
// pdfStencilImage 按当前填充色读取模板图像,不分配整幅彩色样本
|
// pdfStencilImage 按当前填充色读取模板图像,不分配整幅彩色样本
|
||||||
type pdfStencilImage struct {
|
type pdfStencilImage struct {
|
||||||
source image.Image
|
source image.Image
|
||||||
@@ -103,9 +110,14 @@ func (p *pdfImporter) image(mark pdfgo.ImageMark) error {
|
|||||||
}
|
}
|
||||||
source := mark.Image
|
source := mark.Image
|
||||||
key := pdfImageKey{stream: source.Stream, intent: source.Intent}
|
key := pdfImageKey{stream: source.Stream, intent: source.Intent}
|
||||||
id := p.imageIDs[key]
|
id := ""
|
||||||
if source.ImageMask {
|
if !source.ImageMask {
|
||||||
id = ""
|
for _, resource := range p.imageIDs[key] {
|
||||||
|
if reflect.DeepEqual(resource.space, source.ColorSpace) {
|
||||||
|
id = resource.id
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if id == "" {
|
if id == "" {
|
||||||
jbig2Original, err := source.JBIG2File()
|
jbig2Original, err := source.JBIG2File()
|
||||||
@@ -155,9 +167,9 @@ func (p *pdfImporter) image(mark pdfgo.ImageMark) error {
|
|||||||
}
|
}
|
||||||
if !source.ImageMask {
|
if !source.ImageMask {
|
||||||
if p.imageIDs == nil {
|
if p.imageIDs == nil {
|
||||||
p.imageIDs = map[pdfImageKey]string{}
|
p.imageIDs = map[pdfImageKey][]pdfImageResource{}
|
||||||
}
|
}
|
||||||
p.imageIDs[key] = id
|
p.imageIDs[key] = append(p.imageIDs[key], pdfImageResource{space: source.ColorSpace, id: id})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p.appendImage(mark, id)
|
return p.appendImage(mark, id)
|
||||||
|
|||||||
@@ -160,11 +160,23 @@ func intersectClipPath(parent, current *canvas.Path) *canvas.Path {
|
|||||||
if parent.Empty() || current.Empty() {
|
if parent.Empty() || current.Empty() {
|
||||||
return &canvas.Path{}
|
return &canvas.Path{}
|
||||||
}
|
}
|
||||||
if parentOK && parentRect.Contains(current.FastBounds()) {
|
if parentOK {
|
||||||
return current
|
bounds := current.Bounds()
|
||||||
|
if parentRect.Contains(bounds) {
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
if !parentRect.Overlaps(bounds) {
|
||||||
|
return &canvas.Path{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if currentOK && currentRect.Contains(parent.FastBounds()) {
|
if currentOK {
|
||||||
return parent
|
bounds := parent.Bounds()
|
||||||
|
if currentRect.Contains(bounds) {
|
||||||
|
return parent
|
||||||
|
}
|
||||||
|
if !currentRect.Overlaps(bounds) {
|
||||||
|
return &canvas.Path{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if result, ok := intersectConvexCanvasPaths(parent, current); ok {
|
if result, ok := intersectConvexCanvasPaths(parent, current); ok {
|
||||||
return result
|
return result
|
||||||
@@ -199,7 +211,7 @@ func applyClipPath(path, clip *canvas.Path) *canvas.Path {
|
|||||||
return &canvas.Path{}
|
return &canvas.Path{}
|
||||||
}
|
}
|
||||||
if rect, ok := rectangularPath(clip); ok {
|
if rect, ok := rectangularPath(clip); ok {
|
||||||
bounds := path.FastBounds()
|
bounds := path.Bounds()
|
||||||
if rect.Contains(bounds) {
|
if rect.Contains(bounds) {
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
@@ -224,18 +236,25 @@ func rectangularPath(path *canvas.Path) (canvas.Rect, bool) {
|
|||||||
return canvas.Rect{}, false
|
return canvas.Rect{}, false
|
||||||
}
|
}
|
||||||
data := path.Data()
|
data := path.Data()
|
||||||
|
if len(data) != 20 {
|
||||||
|
return canvas.Rect{}, false
|
||||||
|
}
|
||||||
for i := 0; i < len(data); i += 4 {
|
for i := 0; i < len(data); i += 4 {
|
||||||
if i+4 > len(data) || (data[i] != canvas.MoveToCmd && data[i] != canvas.LineToCmd && data[i] != canvas.CloseCmd) {
|
if data[i] != canvas.MoveToCmd && data[i] != canvas.LineToCmd && data[i] != canvas.CloseCmd {
|
||||||
return canvas.Rect{}, false
|
return canvas.Rect{}, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
points := path.Coords()
|
if !(canvas.Point{X: data[1], Y: data[2]}).Equals(canvas.Point{X: data[17], Y: data[18]}) {
|
||||||
if len(points) != 5 || !points[0].Equals(points[4]) {
|
|
||||||
return canvas.Rect{}, false
|
return canvas.Rect{}, false
|
||||||
}
|
}
|
||||||
rect := path.FastBounds()
|
rect := path.FastBounds()
|
||||||
corners := 0
|
corners := 0
|
||||||
for _, point := range points[:4] {
|
for i := 0; i < 16; i += 4 {
|
||||||
|
point := canvas.Point{X: data[i+1], Y: data[i+2]}
|
||||||
|
next := (i + 4) % 16
|
||||||
|
if !canvas.Equal(point.X, data[next+1]) && !canvas.Equal(point.Y, data[next+2]) {
|
||||||
|
return canvas.Rect{}, false
|
||||||
|
}
|
||||||
corner := 0
|
corner := 0
|
||||||
switch {
|
switch {
|
||||||
case canvas.Equal(point.X, rect.X0) && canvas.Equal(point.Y, rect.Y0):
|
case canvas.Equal(point.X, rect.X0) && canvas.Equal(point.Y, rect.Y0):
|
||||||
|
|||||||
@@ -368,7 +368,7 @@ func (r *Renderer) renderPattern(ctx *canvas.Context, pattern *PatternPaint, pag
|
|||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bounds := clip.FastBounds()
|
bounds := clip.Bounds()
|
||||||
points := [][2]float64{
|
points := [][2]float64{
|
||||||
{bounds.X0, pageH - bounds.Y0},
|
{bounds.X0, pageH - bounds.Y0},
|
||||||
{bounds.X1, pageH - bounds.Y0},
|
{bounds.X1, pageH - bounds.Y0},
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ func (r *Renderer) drawSampledShading(ctx *canvas.Context, path *canvas.Path, vi
|
|||||||
if path.Empty() {
|
if path.Empty() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bounds := path.FastBounds().And(shdCanvasBounds(ctx))
|
bounds := path.Bounds().And(shdCanvasBounds(ctx))
|
||||||
if bounds.W() <= 0 || bounds.H() <= 0 {
|
if bounds.W() <= 0 || bounds.H() <= 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -243,7 +243,7 @@ func drawRepeatAxialPath(ctx *canvas.Context, path *canvas.Path, gradient *repea
|
|||||||
p = p.Transform(view.Inv())
|
p = p.Transform(view.Inv())
|
||||||
d := gradient.End.Sub(gradient.Start).Mul(gradient.period)
|
d := gradient.End.Sub(gradient.Start).Mul(gradient.period)
|
||||||
axis := canvas.Matrix{{d.X, -d.Y, gradient.Start.X}, {d.Y, d.X, gradient.Start.Y}}
|
axis := canvas.Matrix{{d.X, -d.Y, gradient.Start.X}, {d.Y, d.X, gradient.Start.Y}}
|
||||||
bounds := p.FastBounds().And(shdCanvasBounds(ctx).Transform(view.Inv()))
|
bounds := p.Bounds().And(shdCanvasBounds(ctx).Transform(view.Inv()))
|
||||||
area := bounds.Transform(axis.Inv())
|
area := bounds.Transform(axis.Inv())
|
||||||
origin := ctx.CoordView().Dot(canvas.Point{})
|
origin := ctx.CoordView().Dot(canvas.Point{})
|
||||||
m := ctx.CoordSystemView().Mul(ctx.View()).Translate(origin.X, origin.Y).Mul(view)
|
m := ctx.CoordSystemView().Mul(ctx.View()).Translate(origin.X, origin.Y).Mul(view)
|
||||||
|
|||||||
Reference in new issue
Block a user