mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 16:44:23 +08:00
1 parent
8979550127
commit
05579265b8
5 files changed
+178
-17
No files matched your search
@@ -53,11 +53,10 @@ func (r *Reader) compressionFontUsage(ctx context.Context, documents map[string]
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
fonts := root.child("Fonts")
|
for font := range editorResourceNodes(root, "Fonts", "Font") {
|
||||||
if fonts == nil {
|
if err := ctx.Err(); err != nil {
|
||||||
continue
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, font := range fonts.children {
|
|
||||||
file := font.child("FontFile")
|
file := font.child("FontFile")
|
||||||
if file == nil {
|
if file == nil {
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -360,11 +360,9 @@ func fontBindingNode(data []byte, id string) (*editorXML, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if fonts := root.child("Fonts"); fonts != nil {
|
for node := range editorResourceNodes(root, "Fonts", "Font") {
|
||||||
for _, node := range fonts.children {
|
if editorResourceID(node.attr("ID")) == editorResourceID(id) {
|
||||||
if node.matchesOFD("Font") && editorResourceID(node.attr("ID")) == editorResourceID(id) {
|
return node, nil
|
||||||
return node, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("font declaration is missing")
|
return nil, fmt.Errorf("font declaration is missing")
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"iter"
|
||||||
"maps"
|
"maps"
|
||||||
"path"
|
"path"
|
||||||
"slices"
|
"slices"
|
||||||
@@ -411,17 +412,31 @@ func normalizeResourceReferences(references map[string]bool) {
|
|||||||
// 返回: *editorXML 资源节点,未找到时为nil
|
// 返回: *editorXML 资源节点,未找到时为nil
|
||||||
func editorResourceNode(root *editorXML, group, kind, id string) *editorXML {
|
func editorResourceNode(root *editorXML, group, kind, id string) *editorXML {
|
||||||
nodes := make(map[string]*editorXML)
|
nodes := make(map[string]*editorXML)
|
||||||
if collection := root.child(group); collection != nil {
|
for node := range editorResourceNodes(root, group, kind) {
|
||||||
for _, node := range collection.children {
|
nodes[node.attr("ID")] = node
|
||||||
if node.matchesOFD(kind) {
|
|
||||||
nodes[node.attr("ID")] = node
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
node, _ := resourceValue(nodes, id)
|
node, _ := resourceValue(nodes, id)
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// editorResourceNodes 按原顺序遍历同类资源,包含交错出现的重复集合
|
||||||
|
// 入参: root 资源文件根节点, group 集合名称, kind 资源类型
|
||||||
|
// 返回: iter.Seq[*editorXML] 资源节点序列
|
||||||
|
func editorResourceNodes(root *editorXML, group, kind string) iter.Seq[*editorXML] {
|
||||||
|
return func(yield func(*editorXML) bool) {
|
||||||
|
for _, collection := range root.children {
|
||||||
|
if !collection.matchesOFD(group) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, node := range collection.children {
|
||||||
|
if node.matchesOFD(kind) && !yield(node) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// editorResourceLocation 按ST_Loc与Res.BaseLoc解析路径,保留路径大小写
|
// editorResourceLocation 按ST_Loc与Res.BaseLoc解析路径,保留路径大小写
|
||||||
// 入参: name 所在XML, base 资源目录, value 路径值
|
// 入参: name 所在XML, base 资源目录, value 路径值
|
||||||
// 返回: string 包内路径
|
// 返回: string 包内路径
|
||||||
|
|||||||
+138
-1
@@ -14,7 +14,12 @@
|
|||||||
|
|
||||||
package ofdgo
|
package ofdgo
|
||||||
|
|
||||||
import "encoding/xml"
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
// Res 资源文件结构
|
// Res 资源文件结构
|
||||||
type Res struct {
|
type Res struct {
|
||||||
@@ -134,6 +139,138 @@ type CompositeGraphicUnit struct {
|
|||||||
extentSet bool
|
extentSet bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML 解析资源文件,隔离外部命名空间的同名集合。
|
||||||
|
// 入参: d XML解码器, start 起始节点
|
||||||
|
// 返回: error 解码错误
|
||||||
|
func (res *Res) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
if start.Name.Local != "Res" {
|
||||||
|
return fmt.Errorf("expected Res element, got %s", start.Name.Local)
|
||||||
|
}
|
||||||
|
*res = Res{XMLName: start.Name, BaseLoc: attrValue(start, "BaseLoc")}
|
||||||
|
return decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
|
||||||
|
var target any
|
||||||
|
switch node.Name.Local {
|
||||||
|
case "ColorSpaces":
|
||||||
|
target = &res.ColorSpaces
|
||||||
|
case "Fonts":
|
||||||
|
target = &res.Fonts
|
||||||
|
case "MultiMedias":
|
||||||
|
target = &res.MultiMedias
|
||||||
|
case "DrawParams":
|
||||||
|
target = &res.DrawParams
|
||||||
|
case "CompositeGraphicUnits":
|
||||||
|
target = &res.CompositeGraphicUnits
|
||||||
|
default:
|
||||||
|
return d.Skip()
|
||||||
|
}
|
||||||
|
return d.DecodeElement(target, &node)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML 解析颜色空间集合。
|
||||||
|
// 入参: d XML解码器, start 起始节点
|
||||||
|
// 返回: error 解码错误
|
||||||
|
func (spaces *ColorSpaces) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
return decodeOFDCollection(d, start, "ColorSpace", &spaces.ColorSpace)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML 解析颜色空间属性及调色板。
|
||||||
|
// 入参: d XML解码器, start 起始节点
|
||||||
|
// 返回: error 解码错误
|
||||||
|
func (space *ColorSpace) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
*space = ColorSpace{ID: attrValue(start, "ID"), Type: attrValue(start, "Type"), Profile: attrValue(start, "Profile")}
|
||||||
|
if value := strings.TrimSpace(attrValue(start, "BitsPerComponent")); value != "" {
|
||||||
|
bits, err := strconv.Atoi(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
space.BitsPerComponent = bits
|
||||||
|
}
|
||||||
|
return decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
|
||||||
|
if node.Name.Local == "Palette" {
|
||||||
|
return decodeOFDCollection(d, node, "CV", &space.Palette)
|
||||||
|
}
|
||||||
|
return d.Skip()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML 解析字体集合。
|
||||||
|
// 入参: d XML解码器, start 起始节点
|
||||||
|
// 返回: error 解码错误
|
||||||
|
func (fonts *Fonts) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
return decodeOFDCollection(d, start, "Font", &fonts.Font)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML 解析字体声明及内嵌字体路径。
|
||||||
|
// 入参: d XML解码器, start 起始节点
|
||||||
|
// 返回: error 解码错误
|
||||||
|
func (font *Font) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
*font = Font{ID: attrValue(start, "ID"), FontName: attrValue(start, "FontName"), FamilyName: attrValue(start, "FamilyName"), Charset: attrValue(start, "Charset")}
|
||||||
|
for _, attr := range start.Attr {
|
||||||
|
if attr.Name.Space != "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var target *bool
|
||||||
|
switch attr.Name.Local {
|
||||||
|
case "Italic":
|
||||||
|
target = &font.Italic
|
||||||
|
case "Bold":
|
||||||
|
target = &font.Bold
|
||||||
|
case "Serif":
|
||||||
|
target = &font.Serif
|
||||||
|
case "FixedWidth":
|
||||||
|
target = &font.FixedWidth
|
||||||
|
}
|
||||||
|
if value := strings.TrimSpace(attr.Value); target != nil && value != "" {
|
||||||
|
flag, err := strconv.ParseBool(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*target = flag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
|
||||||
|
if node.Name.Local == "FontFile" {
|
||||||
|
return d.DecodeElement(&font.FontFile, &node)
|
||||||
|
}
|
||||||
|
return d.Skip()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML 解析多媒体集合。
|
||||||
|
// 入参: d XML解码器, start 起始节点
|
||||||
|
// 返回: error 解码错误
|
||||||
|
func (media *MultiMedias) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
return decodeOFDCollection(d, start, "MultiMedia", &media.MultiMedia)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML 解析多媒体声明及包内文件路径。
|
||||||
|
// 入参: d XML解码器, start 起始节点
|
||||||
|
// 返回: error 解码错误
|
||||||
|
func (media *MultiMedia) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
*media = MultiMedia{ID: attrValue(start, "ID"), Type: attrValue(start, "Type"), Format: attrValue(start, "Format")}
|
||||||
|
return decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
|
||||||
|
if node.Name.Local == "MediaFile" {
|
||||||
|
return d.DecodeElement(&media.MediaFile, &node)
|
||||||
|
}
|
||||||
|
return d.Skip()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML 解析绘制参数集合。
|
||||||
|
// 入参: d XML解码器, start 起始节点
|
||||||
|
// 返回: error 解码错误
|
||||||
|
func (params *DrawParams) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
return decodeOFDCollection(d, start, "DrawParam", ¶ms.DrawParam)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML 解析复合图元资源集合。
|
||||||
|
// 入参: d XML解码器, start 起始节点
|
||||||
|
// 返回: error 解码错误
|
||||||
|
func (units *CompositeGraphicUnits) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
return decodeOFDCollection(d, start, "CompositeGraphicUnit", &units.CompositeGraphicUnit)
|
||||||
|
}
|
||||||
|
|
||||||
// sameResourceID 判断资源标识是否相同,数字标识按数值比较
|
// sameResourceID 判断资源标识是否相同,数字标识按数值比较
|
||||||
// 入参: first 第一个标识, second 第二个标识
|
// 入参: first 第一个标识, second 第二个标识
|
||||||
// 返回: bool 是否相同
|
// 返回: bool 是否相同
|
||||||
|
|||||||
@@ -92,6 +92,18 @@ func decodeOFDChildren(d *xml.Decoder, start xml.StartElement, decode func(*xml.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// decodeOFDCollection 按命名空间追加同类子节点,保留重复资源集合的记录
|
||||||
|
// 入参: d XML解码器, start 集合起始节点, name 子节点名称, values 接收结果的切片
|
||||||
|
// 返回: error 解析错误
|
||||||
|
func decodeOFDCollection[T any](d *xml.Decoder, start xml.StartElement, name string, values *[]T) error {
|
||||||
|
return decodeOFDChildren(d, start, func(d *xml.Decoder, node xml.StartElement) error {
|
||||||
|
if node.Name.Local == name {
|
||||||
|
return d.DecodeElement(values, &node)
|
||||||
|
}
|
||||||
|
return d.Skip()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// classifyOFDNamespace 识别OFD命名空间,未声明与未知版本分别处理
|
// classifyOFDNamespace 识别OFD命名空间,未声明与未知版本分别处理
|
||||||
// 入参: namespace XML命名空间
|
// 入参: namespace XML命名空间
|
||||||
// 返回: ofdXMLNamespace 命名空间类别
|
// 返回: ofdXMLNamespace 命名空间类别
|
||||||
|
|||||||
Reference in new issue
Block a user