feat(归并文件): 归并文件下沉通用能力
build.yaml / build (push) Successful in 53s

This commit is contained in:
xiaoqidun committed 2026-10-14 10:40:08 +08:00
1 parent d07972346b
commit 70003486b8
37 files changed
+2386 -2509

No files matched your search

+91 -1
View File
@@ -17,9 +17,10 @@ package ofdgo
import (
"encoding/xml"
"fmt"
basegeom "github.com/xiaoqidun/ofdgo/internal/base/geom"
"net/url"
"strconv"
basegeom "github.com/xiaoqidun/ofdgo/internal/base/geom"
)
// Action 动作
@@ -548,3 +549,92 @@ func resolveActionURI(action URI) string {
}
return base.ResolveReference(target).String()
}
// MarshalXML 按标准属性写入目标,书签和动作采用相同格式
// 入参: encoder XML编码器, start 起始节点
// 返回: error 参数或编码错误
func (dest Dest) MarshalXML(encoder *xml.Encoder, start xml.StartElement) error {
attrs, err := dest.attributes()
if err != nil {
return err
}
start.Attr = attrs
if err := encoder.EncodeToken(start); err != nil {
return err
}
return encoder.EncodeToken(start.End())
}
// effective 应用省略属性的默认值,不改变原始声明
// 返回: Dest 生效的目标参数
func (dest Dest) effective() Dest {
if dest.OmitLeft {
dest.Left = 0
}
if dest.OmitTop {
dest.Top = 0
}
if dest.OmitZoom {
dest.Zoom = 0
}
return dest
}
// attributes 校验并生成目标属性,缩放为0表示沿用当前比例
// 返回: ofdAttrs 标准属性, error 模式或参数错误
func (dest Dest) attributes() (ofdAttrs, error) {
dest = dest.effective()
attrs := ofdAttrs{{Name: xml.Name{Local: "Type"}, Value: dest.Type}, {Name: xml.Name{Local: "PageID"}, Value: dest.PageID}}
if dest.PageID == "" {
return nil, fmt.Errorf("missing destination page")
}
add := func(name string, value float64, omit bool) error {
if !finite(value) {
return fmt.Errorf("invalid destination %s", name)
}
if !omit {
attrs.add(name, ofdNumber(value))
}
return nil
}
switch dest.Type {
case "XYZ":
if dest.Zoom != 0 && (dest.Zoom < 0.1 || dest.Zoom > 64) {
return nil, fmt.Errorf("destination zoom must be zero or between 0.1 and 64")
}
if err := add("Zoom", dest.Zoom, dest.OmitZoom); err != nil {
return nil, err
}
fallthrough
case "FitR":
if err := add("Left", dest.Left, dest.OmitLeft); err != nil {
return nil, err
}
if err := add("Top", dest.Top, dest.OmitTop); err != nil {
return nil, err
}
if dest.Type == "FitR" {
if dest.Right <= dest.Left || dest.Bottom <= dest.Top {
return nil, fmt.Errorf("empty destination rectangle")
}
if err := add("Right", dest.Right, false); err != nil {
return nil, err
}
if err := add("Bottom", dest.Bottom, false); err != nil {
return nil, err
}
}
case "FitH":
if err := add("Top", dest.Top, dest.OmitTop); err != nil {
return nil, err
}
case "FitV":
if err := add("Left", dest.Left, dest.OmitLeft); err != nil {
return nil, err
}
case "Fit":
default:
return nil, fmt.Errorf("invalid destination type %q", dest.Type)
}
return attrs, nil
}