feat(编辑渲染): 修复资源引用,完善注解读取

This commit is contained in:
xiaoqidun committed 2026-10-10 16:22:40 +08:00
1 parent a5f51294eb
commit 52fc88f2b8
14 files changed
+181 -97

No files matched your search

+3 -22
View File
@@ -1501,29 +1501,10 @@ func readAnnotation(args []js.Value) (any, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
texts := make([]string, 0) texts, err := currentEditor.AnnotationTexts(args[0].Int(), annotation.ID)
visiting := make(map[string]bool) if err != nil {
var collect func([]ofdgo.GraphicObject) return nil, err
collect = func(objects []ofdgo.GraphicObject) {
for _, object := range objects {
switch object.Type {
case "TextObject":
value := object.TextObject.Text()
if !slices.Contains(texts, value) {
texts = append(texts, value)
} }
case "CompositeObject", "CompositeGraphicUnit":
collect(object.CompositeGraphicUnit.Objects)
id := object.CompositeGraphicUnit.ResourceID
if unit := currentSession.Renderer.CompositeGraphicUnits[id]; unit != nil && !visiting[id] {
visiting[id] = true
collect(unit.Objects)
delete(visiting, id)
}
}
}
}
collect(annotation.Appearance.Objects)
info := map[string]any{"texts": texts, "remark": annotation.Remark, "creator": annotation.Creator} info := map[string]any{"texts": texts, "remark": annotation.Remark, "creator": annotation.Creator}
if annotation.Type == "Link" { if annotation.Type == "Link" {
info["linkKind"] = "keep" info["linkKind"] = "keep"
+6 -6
View File
@@ -366,7 +366,7 @@ func (r *Renderer) annotationActionSources(annotations []Annotation) []actionSou
// appendGraphicActionSources 添加图形对象动作来源 // appendGraphicActionSources 添加图形对象动作来源
// 入参: sources 动作来源, object 图形对象, parent 父级变换, boundaryInCTM 边界是否参与父级变换, seen 当前资源引用链 // 入参: sources 动作来源, object 图形对象, parent 父级变换, boundaryInCTM 边界是否参与父级变换, seen 当前资源引用链
// 返回: []actionSource 动作来源 // 返回: []actionSource 动作来源
func (r *Renderer) appendGraphicActionSources(sources []actionSource, object GraphicObject, parent Matrix, boundaryInCTM bool, seen map[string]bool) []actionSource { func (r *Renderer) appendGraphicActionSources(sources []actionSource, object GraphicObject, parent Matrix, boundaryInCTM bool, seen map[*CompositeGraphicUnit]bool) []actionSource {
var boundary, ctm, resource string var boundary, ctm, resource string
var actions []Action var actions []Action
var children []GraphicObject var children []GraphicObject
@@ -412,14 +412,14 @@ func (r *Renderer) appendGraphicActionSources(sources []actionSource, object Gra
} }
sources = append(sources, source) sources = append(sources, source)
} }
if resource != "" && !seen[resource] { if resource != "" {
if unit := r.CompositeGraphicUnits[resource]; unit != nil { if unit, _ := resourceValue(r.CompositeGraphicUnits, resource); unit != nil && !seen[unit] {
if seen == nil { if seen == nil {
seen = make(map[string]bool) seen = make(map[*CompositeGraphicUnit]bool)
} }
seen[resource] = true seen[unit] = true
sources = r.appendGraphicActionSources(sources, GraphicObject{Type: "CompositeGraphicUnit", CompositeGraphicUnit: *unit}, matrix, true, seen) sources = r.appendGraphicActionSources(sources, GraphicObject{Type: "CompositeGraphicUnit", CompositeGraphicUnit: *unit}, matrix, true, seen)
delete(seen, resource) delete(seen, unit)
} }
} }
for _, child := range children { for _, child := range children {
+11 -14
View File
@@ -102,26 +102,23 @@ func mergeDrawParam(base DrawParam, dp *DrawParam) *DrawParam {
return &base return &base
} }
// getDrawParam 获取绘制参数逻辑 // getDrawParam 解析绘制参数继承链,按实际资源识别循环引用
// 入参: id 参数ID, visited 访问记录 // 入参: id 参数标识, visited 已访问资源
// 返回: *DrawParam 绘制参数 // 返回: *DrawParam 绘制参数
func (r *Renderer) getDrawParam(id string, visited map[string]bool) *DrawParam { func (r *Renderer) getDrawParam(id string, visited map[*DrawParam]bool) *DrawParam {
if visited == nil { dp, _ := resourceValue(r.DrawParams, id)
visited = make(map[string]bool) if dp == nil || visited[dp] {
}
if visited[id] {
return nil return nil
} }
visited[id] = true if visited == nil {
if dp, ok := r.DrawParams[id]; ok { visited = make(map[*DrawParam]bool)
}
visited[dp] = true
if dp.Relative != "" { if dp.Relative != "" {
base := r.getDrawParam(dp.Relative, visited) base := r.getDrawParam(dp.Relative, visited)
if base == nil { if base != nil {
return dp
}
return mergeDrawParam(*base, dp) return mergeDrawParam(*base, dp)
} }
return dp
} }
return nil return dp
} }
+58
View File
@@ -154,6 +154,64 @@ func (e *Editor) Annotation(index int, id string) (Annotation, error) {
return annotation, err return annotation, err
} }
// AnnotationTexts 按绘制顺序读取注解外观中的文字,展开复合资源并去重,不依赖字体或渲染后端
// 入参: index 页面索引, id 注解标识
// 返回: []string 文字列表, error 注解读取或资源引用错误
func (e *Editor) AnnotationTexts(index int, id string) ([]string, error) {
annotation, err := e.Annotation(index, id)
if err != nil {
return nil, err
}
reader, err := e.Reader()
if err != nil {
return nil, err
}
defer reader.Close()
if _, err := reader.PageContentByIndex(index); err != nil {
return nil, err
}
texts := make([]string, 0)
seen := make(map[string]bool)
visiting := make(map[*CompositeGraphicUnit]bool)
collected := make(map[*CompositeGraphicUnit]bool)
var collect func(CompositeGraphicUnit) error
collect = func(unit CompositeGraphicUnit) error {
if unit.ResourceID != "" {
ref, _ := resourceValue(reader.compositeGraphicUnitCache, unit.ResourceID)
if ref == nil || visiting[ref] {
return fmt.Errorf("invalid composite resource %q", unit.ResourceID)
}
if !collected[ref] {
visiting[ref] = true
if err := collect(*ref); err != nil {
return err
}
delete(visiting, ref)
collected[ref] = true
}
}
for object := range unit.objects() {
switch object.Type {
case "TextObject":
value := object.TextObject.Text()
if !seen[value] {
seen[value] = true
texts = append(texts, value)
}
case "CompositeObject", "CompositeGraphicUnit":
if err := collect(object.CompositeGraphicUnit); err != nil {
return err
}
}
}
return nil
}
if err := collect(CompositeGraphicUnit{Objects: annotation.Appearance.Objects}); err != nil {
return nil, err
}
return texts, nil
}
// annotationXML 读取唯一注解的独立原文,不以类型、大小或可见性筛选 // annotationXML 读取唯一注解的独立原文,不以类型、大小或可见性筛选
// 入参: index 页面索引, id 注解标识 // 入参: index 页面索引, id 注解标识
// 返回: []byte 注解XML, error 错误信息 // 返回: []byte 注解XML, error 错误信息
+3
View File
@@ -269,6 +269,9 @@ func (e *Editor) ReplaceAnnotationText(page int, id, old, value string, style Te
count++ count++
} else if member.Object.Type == "CompositeObject" || member.Object.Type == "CompositeGraphicUnit" { } else if member.Object.Type == "CompositeObject" || member.Object.Type == "CompositeGraphicUnit" {
resource := member.Object.CompositeGraphicUnit.ResourceID resource := member.Object.CompositeGraphicUnit.ResourceID
if id := editorResourceID(resource); id != "" {
resource = id
}
if resource != "" && visiting[resource] { if resource != "" && visiting[resource] {
return fmt.Errorf("cyclic composite resource %q", resource) return fmt.Errorf("cyclic composite resource %q", resource)
} }
+11 -11
View File
@@ -500,7 +500,8 @@ func (e *Editor) compositeMembers(n *editorCompositeNode, reader *Reader, render
visible := n.visible && (c.Visible == nil || *c.Visible) visible := n.visible && (c.Visible == nil || *c.Visible)
alpha := mergeAlpha(n.alpha, c.Alpha) alpha := mergeAlpha(n.alpha, c.Alpha)
if c.ResourceID != "" { if c.ResourceID != "" {
data, err := reader.readFile(reader.resourceFiles[c.ResourceID]) name, _ := resourceValue(reader.resourceFiles, c.ResourceID)
data, err := reader.readFile(name)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -508,15 +509,7 @@ func (e *Editor) compositeMembers(n *editorCompositeNode, reader *Reader, render
if err != nil { if err != nil {
return nil, err return nil, err
} }
var resource *editorXML resource := editorResourceNode(root, "CompositeGraphicUnits", "CompositeGraphicUnit", c.ResourceID)
if units := root.child("CompositeGraphicUnits"); units != nil {
for _, child := range units.children {
if child.name.Local == "CompositeGraphicUnit" && child.attr("ID") == c.ResourceID {
resource = child
break
}
}
}
if resource == nil { if resource == nil {
return nil, fmt.Errorf("composite resource %q not found", c.ResourceID) return nil, fmt.Errorf("composite resource %q not found", c.ResourceID)
} }
@@ -530,7 +523,7 @@ func (e *Editor) compositeMembers(n *editorCompositeNode, reader *Reader, render
} }
var states map[string]editorCompositeState var states map[string]editorCompositeState
for _, resource := range e.resources { for _, resource := range e.resources {
if resource.composite == c.ResourceID { if sameResourceID(resource.composite, c.ResourceID) {
states = resource.states states = resource.states
break break
} }
@@ -578,6 +571,9 @@ func (e *Editor) compositeMembers(n *editorCompositeNode, reader *Reader, render
var result []*editorCompositeNode var result []*editorCompositeNode
if n.ref != nil { if n.ref != nil {
id := n.object.CompositeGraphicUnit.ResourceID id := n.object.CompositeGraphicUnit.ResourceID
if key := editorResourceID(id); key != "" {
id = key
}
if visiting[id] { if visiting[id] {
return nil, fmt.Errorf("cyclic composite resource %q", id) return nil, fmt.Errorf("cyclic composite resource %q", id)
} }
@@ -1072,6 +1068,7 @@ func editorResourceReferences(data []byte) ([]string, error) {
} }
} }
collect(root) collect(root)
normalizeResourceReferences(refs)
return slices.Sorted(maps.Keys(refs)), nil return slices.Sorted(maps.Keys(refs)), nil
} }
@@ -1091,6 +1088,9 @@ func collectCompositeReferences(composite CompositeGraphicUnit, used map[string]
// 入参: id 矢量资源标识 // 入参: id 矢量资源标识
// 返回: error 尺寸、内容或引用错误 // 返回: error 尺寸、内容或引用错误
func (v *editorValidation) validateVector(id string) error { func (v *editorValidation) validateVector(id string) error {
if key := editorResourceID(id); key != "" {
id = key
}
if v.composites[id] { if v.composites[id] {
return fmt.Errorf("cyclic composite resource %q", id) return fmt.Errorf("cyclic composite resource %q", id)
} }
+10 -9
View File
@@ -264,10 +264,14 @@ func (e *Editor) compositeUngroupable(node *editorXML) bool {
if id == "" { if id == "" {
return true return true
} }
if seen[id] { key := id
if value := editorResourceID(id); value != "" {
key = value
}
if seen[key] {
return false return false
} }
seen[id] = true seen[key] = true
resource, err := e.compositeDefinition(id) resource, err := e.compositeDefinition(id)
if err != nil { if err != nil {
return false return false
@@ -282,14 +286,15 @@ func (e *Editor) compositeUngroupable(node *editorXML) bool {
func (e *Editor) compositeDefinition(id string) (*editorCompositeNode, error) { func (e *Editor) compositeDefinition(id string) (*editorCompositeNode, error) {
var data []byte var data []byte
for _, resource := range e.resources { for _, resource := range e.resources {
if resource.composite == id { if sameResourceID(resource.composite, id) {
data = resource.data data = resource.data
break break
} }
} }
if data == nil && e.source != nil { if data == nil && e.source != nil {
var err error var err error
data, err = e.source.reader.readFile(e.source.reader.resourceFiles[id]) name, _ := resourceValue(e.source.reader.resourceFiles, id)
data, err = e.source.reader.readFile(name)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -298,16 +303,12 @@ func (e *Editor) compositeDefinition(id string) (*editorCompositeNode, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if units := root.child("CompositeGraphicUnits"); units != nil { if unit := editorResourceNode(root, "CompositeGraphicUnits", "CompositeGraphicUnit", id); unit != nil {
for _, unit := range units.children {
if unit.name.Local == "CompositeGraphicUnit" && unit.attr("ID") == id {
fragment, err := editorXMLStandalone(data[unit.start:unit.end], unit) fragment, err := editorXMLStandalone(data[unit.start:unit.end], unit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return newEditorCompositeNode(fragment) return newEditorCompositeNode(fragment)
} }
}
}
return nil, fmt.Errorf("composite resource %q not found", id) return nil, fmt.Errorf("composite resource %q not found", id)
} }
+13 -12
View File
@@ -25,14 +25,15 @@ import (
func (e *Editor) drawParamXML(id string) ([]byte, error) { func (e *Editor) drawParamXML(id string) ([]byte, error) {
var data []byte var data []byte
for _, resource := range e.resources { for _, resource := range e.resources {
if resource.draw != nil && resource.draw.ID == id { if resource.draw != nil && sameResourceID(resource.draw.ID, id) {
data = resource.data data = resource.data
break break
} }
} }
if data == nil && e.source != nil { if data == nil && e.source != nil {
var err error var err error
data, err = e.source.reader.readFile(e.source.reader.resourceFiles[id]) name, _ := resourceValue(e.source.reader.resourceFiles, id)
data, err = e.source.reader.readFile(name)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -41,13 +42,9 @@ func (e *Editor) drawParamXML(id string) ([]byte, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if params := root.child("DrawParams"); params != nil { if node := editorResourceNode(root, "DrawParams", "DrawParam", id); node != nil {
for _, node := range params.children {
if node.name.Local == "DrawParam" && node.attr("ID") == id && classifyOFDNamespace(node.name.Space) != ofdXMLUnknown {
return editorXMLStandalone(data[node.start:node.end], node) return editorXMLStandalone(data[node.start:node.end], node)
} }
}
}
return nil, fmt.Errorf("draw parameter %q not found", id) return nil, fmt.Errorf("draw parameter %q not found", id)
} }
@@ -55,13 +52,17 @@ func (e *Editor) drawParamXML(id string) ([]byte, error) {
// 入参: id 源参数标识, base 独立基准标识, visited 当前继承链 // 入参: id 源参数标识, base 独立基准标识, visited 当前继承链
// 返回: string 新继承链末端标识, error 错误信息 // 返回: string 新继承链末端标识, error 错误信息
func (e *Editor) copyDrawParam(id, base string, visited map[string]bool) (string, error) { func (e *Editor) copyDrawParam(id, base string, visited map[string]bool) (string, error) {
if id == "" || id == base { if id == "" || sameResourceID(id, base) {
return base, nil return base, nil
} }
if visited[id] { key := id
if value := editorResourceID(id); value != "" {
key = value
}
if visited[key] {
return "", fmt.Errorf("cyclic draw parameter %q", id) return "", fmt.Errorf("cyclic draw parameter %q", id)
} }
visited[id] = true visited[key] = true
data, err := e.drawParamXML(id) data, err := e.drawParamXML(id)
if err != nil { if err != nil {
return "", err return "", err
@@ -70,7 +71,7 @@ func (e *Editor) copyDrawParam(id, base string, visited map[string]bool) (string
if err != nil { if err != nil {
return "", err return "", err
} }
if root.attr("Relative") == base { if sameResourceID(root.attr("Relative"), base) {
return id, nil return id, nil
} }
base, err = e.copyDrawParam(root.attr("Relative"), base, visited) base, err = e.copyDrawParam(root.attr("Relative"), base, visited)
@@ -78,7 +79,7 @@ func (e *Editor) copyDrawParam(id, base string, visited map[string]bool) (string
return "", err return "", err
} }
for _, resource := range e.resources { for _, resource := range e.resources {
if resource.drawSource == id && resource.draw.Relative == base { if sameResourceID(resource.drawSource, id) && sameResourceID(resource.draw.Relative, base) {
return resource.draw.ID, nil return resource.draw.ID, nil
} }
} }
+27
View File
@@ -313,6 +313,33 @@ func editorResourceID(value string) string {
return strconv.FormatUint(id, 10) return strconv.FormatUint(id, 10)
} }
// normalizeResourceReferences 合并数值等价的资源引用,保留内部非数字标识
// 入参: references 待规范化的引用集合
func normalizeResourceReferences(references map[string]bool) {
for id, used := range references {
if key := editorResourceID(id); key != "" && key != id {
references[key] = references[key] || used
delete(references, id)
}
}
}
// editorResourceNode 按资源标识查找标准资源节点,等价别名冲突时不猜测
// 入参: root 资源文件根节点, group 资源集合名称, kind 资源类型, id 资源标识
// 返回: *editorXML 资源节点,未找到时为nil
func editorResourceNode(root *editorXML, group, kind, id string) *editorXML {
nodes := make(map[string]*editorXML)
if collection := root.child(group); collection != nil {
for _, node := range collection.children {
if node.matchesOFD(kind) {
nodes[node.attr("ID")] = node
}
}
}
node, _ := resourceValue(nodes, id)
return node
}
// editorResourceLocation 按ST_Loc与Res.BaseLoc解析路径,大小写折叠用于保守保留共享文件 // editorResourceLocation 按ST_Loc与Res.BaseLoc解析路径,大小写折叠用于保守保留共享文件
// 入参: name 所在XML, base 资源目录, value 路径值 // 入参: name 所在XML, base 资源目录, value 路径值
// 返回: string 包内路径 // 返回: string 包内路径
+7 -4
View File
@@ -98,12 +98,12 @@ func (e *Editor) DrawParam(id string, resolved bool) (*DrawParam, error) {
return cloneEditorData(draw), nil return cloneEditorData(draw), nil
} }
for _, resource := range e.resources { for _, resource := range e.resources {
if resource.draw != nil && resource.draw.ID == id { if resource.draw != nil && sameResourceID(resource.draw.ID, id) {
return cloneEditorData(resource.draw), nil return cloneEditorData(resource.draw), nil
} }
} }
if e.source != nil { if e.source != nil {
if value := e.source.reader.drawParamCache[id]; value != nil { if value, _ := resourceValue(e.source.reader.drawParamCache, id); value != nil {
return cloneEditorData(value), nil return cloneEditorData(value), nil
} }
} }
@@ -425,13 +425,16 @@ func (e *Editor) editorDrawParam(id string, visited map[string]bool) (*DrawParam
} }
var dp *DrawParam var dp *DrawParam
for _, resource := range e.resources { for _, resource := range e.resources {
if resource.draw != nil && resource.draw.ID == id { if resource.draw != nil && sameResourceID(resource.draw.ID, id) {
dp = resource.draw dp = resource.draw
break break
} }
} }
if dp == nil && e.source != nil { if dp == nil && e.source != nil {
dp = e.source.reader.drawParamCache[id] dp, _ = resourceValue(e.source.reader.drawParamCache, id)
}
if key := editorResourceID(id); key != "" {
id = key
} }
if dp == nil || visited[id] { if dp == nil || visited[id] {
return nil, &EditError{Code: EditUnsupportedStyle, Err: fmt.Errorf("invalid draw parameter reference %q", id)} return nil, &EditError{Code: EditUnsupportedStyle, Err: fmt.Errorf("invalid draw parameter reference %q", id)}
+6 -6
View File
@@ -68,7 +68,7 @@ type fontUsagePage struct {
// fontUsageReferences 保存字体统计中的当前引用路径,不合并共享内容的用量 // fontUsageReferences 保存字体统计中的当前引用路径,不合并共享内容的用量
type fontUsageReferences struct { type fontUsageReferences struct {
composites map[string]bool composites map[*CompositeGraphicUnit]bool
patterns map[*Pattern]bool patterns map[*Pattern]bool
} }
@@ -577,20 +577,20 @@ func (r *Renderer) countCompositeFonts(cgu CompositeGraphicUnit, usage map[strin
r.countClipFonts(cgu.Clips, usage) r.countClipFonts(cgu.Clips, usage)
defaults = r.drawParamDefaults(cgu.DrawParam, defaults) defaults = r.drawParamDefaults(cgu.DrawParam, defaults)
if cgu.ResourceID != "" { if cgu.ResourceID != "" {
if ref, _ := resourceValue(r.CompositeGraphicUnits, cgu.ResourceID); ref != nil {
if visited == nil { if visited == nil {
visited = &fontUsageReferences{} visited = &fontUsageReferences{}
} }
if visited.composites[cgu.ResourceID] { if visited.composites[ref] {
return return
} }
if visited.composites == nil { if visited.composites == nil {
visited.composites = make(map[string]bool) visited.composites = make(map[*CompositeGraphicUnit]bool)
} }
visited.composites[cgu.ResourceID] = true visited.composites[ref] = true
if ref := r.CompositeGraphicUnits[cgu.ResourceID]; ref != nil {
r.countCompositeFonts(*ref, usage, defaults, visited) r.countCompositeFonts(*ref, usage, defaults, visited)
defer delete(visited.composites, ref)
} }
defer delete(visited.composites, cgu.ResourceID)
} }
for object := range cgu.objects() { for object := range cgu.objects() {
r.countObjectFonts(object, usage, defaults, visited) r.countObjectFonts(object, usage, defaults, visited)
+12 -12
View File
@@ -169,7 +169,7 @@ func (r *Renderer) walkLayers(layers []Layer, order int, visitor PageVisitor) er
// walkObject 访问对象并传递当前资源引用链 // walkObject 访问对象并传递当前资源引用链
// 入参: object 源对象, state 继承状态, visitor 页面访问器, references 当前资源引用链 // 入参: object 源对象, state 继承状态, visitor 页面访问器, references 当前资源引用链
// 返回: error 遍历或访问器错误 // 返回: error 遍历或访问器错误
func (r *Renderer) walkObject(object *GraphicObject, state RenderState, visitor PageVisitor, references map[string]bool) error { func (r *Renderer) walkObject(object *GraphicObject, state RenderState, visitor PageVisitor, references map[*CompositeGraphicUnit]bool) error {
if r.pageContext != nil { if r.pageContext != nil {
if err := r.pageContext.Err(); err != nil { if err := r.pageContext.Err(); err != nil {
return err return err
@@ -191,16 +191,16 @@ func (r *Renderer) walkObject(object *GraphicObject, state RenderState, visitor
// walkComposite 展开复合图元的资源、成员与透明度,不修改共享资源 // walkComposite 展开复合图元的资源、成员与透明度,不修改共享资源
// 入参: object 复合图元, state 继承状态, visitor 页面访问器, references 当前资源引用链 // 入参: object 复合图元, state 继承状态, visitor 页面访问器, references 当前资源引用链
// 返回: error 几何或访问器错误 // 返回: error 几何或访问器错误
func (r *Renderer) walkComposite(object CompositeGraphicUnit, state RenderState, visitor PageVisitor, references map[string]bool) error { func (r *Renderer) walkComposite(object CompositeGraphicUnit, state RenderState, visitor PageVisitor, references map[*CompositeGraphicUnit]bool) error {
if object.Visible != nil && !*object.Visible { if object.Visible != nil && !*object.Visible {
if groups, ok := visitor.(PageGroups); ok { if groups, ok := visitor.(PageGroups); ok {
count, ref, seen := len(object.Objects), object.ResourceID, make(map[string]bool) count, ref, seen := len(object.Objects), object.ResourceID, make(map[*CompositeGraphicUnit]bool)
for ref != "" && !seen[ref] { for ref != "" {
seen[ref] = true unit, _ := resourceValue(r.CompositeGraphicUnits, ref)
unit := r.CompositeGraphicUnits[ref] if unit == nil || seen[unit] {
if unit == nil {
break break
} }
seen[unit] = true
count, ref = count+len(unit.Objects), unit.ResourceID count, ref = count+len(unit.Objects), unit.ResourceID
} }
groups.SkipObjects(count) groups.SkipObjects(count)
@@ -241,20 +241,20 @@ func (r *Renderer) walkComposite(object CompositeGraphicUnit, state RenderState,
state.Defaults = r.drawParamDefaults(object.DrawParam, state.Defaults) state.Defaults = r.drawParamDefaults(object.DrawParam, state.Defaults)
state.Parent = &matrix state.Parent = &matrix
if object.ResourceID != "" { if object.ResourceID != "" {
if references[object.ResourceID] { if ref, _ := resourceValue(r.CompositeGraphicUnits, object.ResourceID); ref != nil {
if references[ref] {
return fmt.Errorf("cyclic composite resource %q", object.ResourceID) return fmt.Errorf("cyclic composite resource %q", object.ResourceID)
} }
if ref, ok := r.CompositeGraphicUnits[object.ResourceID]; ok {
if references == nil { if references == nil {
references = make(map[string]bool) references = make(map[*CompositeGraphicUnit]bool)
} }
references[object.ResourceID] = true references[ref] = true
copy := *ref copy := *ref
copy.Alpha = mergeAlpha(copy.Alpha, object.Alpha) copy.Alpha = mergeAlpha(copy.Alpha, object.Alpha)
referenceState := state referenceState := state
referenceState.BoundaryInCTM = true referenceState.BoundaryInCTM = true
err := r.walkComposite(copy, referenceState, visitor, references) err := r.walkComposite(copy, referenceState, visitor, references)
delete(references, object.ResourceID) delete(references, ref)
if err != nil { if err != nil {
return err return err
} }
+11
View File
@@ -132,6 +132,17 @@ type CompositeGraphicUnit struct {
extentSet bool extentSet bool
} }
// sameResourceID 判断资源标识是否相同,数字标识按数值比较
// 入参: first 第一个标识, second 第二个标识
// 返回: bool 是否相同
func sameResourceID(first, second string) bool {
if first == second {
return true
}
id := editorResourceID(first)
return id != "" && id == editorResourceID(second)
}
// resourceValue 优先查找原标识与标准十进制标识,回退别名有冲突时不猜测 // resourceValue 优先查找原标识与标准十进制标识,回退别名有冲突时不猜测
// 入参: values 已加载资源, id 标识文本 // 入参: values 已加载资源, id 标识文本
// 返回: T 资源值, bool 是否存在唯一结果 // 返回: T 资源值, bool 是否存在唯一结果
+3 -1
View File
@@ -512,6 +512,8 @@ func (e *Editor) usedResources() (fonts, images []editorResource, spaces []Color
} }
} }
} }
normalizeResourceReferences(used)
normalizeResourceReferences(promoted)
for i := len(e.resources) - 1; i >= 0; i-- { for i := len(e.resources) - 1; i >= 0; i-- {
resource := e.resources[i] resource := e.resources[i]
if resource.definition() != "" && used[resource.definition()] { if resource.definition() != "" && used[resource.definition()] {
@@ -541,7 +543,7 @@ func (e *Editor) usedResources() (fonts, images []editorResource, spaces []Color
} }
} }
for id := range promoted { for id := range promoted {
if name := e.source.reader.resourceFiles[id]; name != "" { if name, _ := resourceValue(e.source.reader.resourceFiles, id); name != "" {
files[name] = true files[name] = true
} }
} }