mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 08:46:55 +08:00
feat(归并文件): 归并根包文件
This commit is contained in:
1 parent
ec24b6a17d
commit
1a8de5a3f1
23 files changed
+1724
-1981
No files matched your search
@@ -18,9 +18,14 @@ import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// editorClonePlans 仅共享类型的可变字段索引,不持有文档对象或资源
|
||||
var editorClonePlans sync.Map
|
||||
|
||||
// copiedObjectStyle 保留复杂路径的原始颜色引用,普通对象沿用有效样式快照
|
||||
// 入参: object 原对象, layer 图层绘制参数
|
||||
// 返回: GraphicObject 复制快照, error 错误信息
|
||||
@@ -231,3 +236,103 @@ func (e *Editor) copiedLayerStyle(object GraphicObject) string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// cloneEditorData 深复制编辑快照,未导出的排版及原文来源保持不可变共享
|
||||
// 入参: value 原值
|
||||
// 返回: T 独立副本
|
||||
func cloneEditorData[T any](value T) T {
|
||||
source := reflect.ValueOf(value)
|
||||
if !source.IsValid() {
|
||||
return value
|
||||
}
|
||||
return cloneEditorValue(source).Interface().(T)
|
||||
}
|
||||
|
||||
// cloneEditorValue 复制公开指针、切片及数组,纯值数据不创建额外结构
|
||||
// 入参: value 原值
|
||||
// 返回: reflect.Value 独立副本
|
||||
func cloneEditorValue(value reflect.Value) reflect.Value {
|
||||
if !value.IsValid() || !editorCloneMutable(value.Type()) {
|
||||
return value
|
||||
}
|
||||
switch value.Kind() {
|
||||
case reflect.Pointer:
|
||||
if value.IsNil() {
|
||||
return value
|
||||
}
|
||||
result := reflect.New(value.Type().Elem())
|
||||
cloneEditorInto(result.Elem(), value.Elem())
|
||||
return result
|
||||
case reflect.Slice:
|
||||
if value.IsNil() {
|
||||
return value
|
||||
}
|
||||
result := reflect.MakeSlice(value.Type(), value.Len(), value.Len())
|
||||
if !editorCloneMutable(value.Type().Elem()) {
|
||||
reflect.Copy(result, value)
|
||||
} else {
|
||||
for i := range value.Len() {
|
||||
cloneEditorInto(result.Index(i), value.Index(i))
|
||||
}
|
||||
}
|
||||
return result
|
||||
default:
|
||||
result := reflect.New(value.Type()).Elem()
|
||||
cloneEditorInto(result, value)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// cloneEditorInto 直接填充目标结构,避免指针及切片成员的二次结构分配
|
||||
// 入参: target 可写目标, source 原值
|
||||
func cloneEditorInto(target, source reflect.Value) {
|
||||
switch source.Kind() {
|
||||
case reflect.Struct:
|
||||
target.Set(source)
|
||||
for _, i := range editorCloneFields(source.Type()) {
|
||||
cloneEditorInto(target.Field(i), source.Field(i))
|
||||
}
|
||||
case reflect.Array:
|
||||
target.Set(source)
|
||||
if editorCloneMutable(source.Type().Elem()) {
|
||||
for i := range source.Len() {
|
||||
cloneEditorInto(target.Index(i), source.Index(i))
|
||||
}
|
||||
}
|
||||
default:
|
||||
target.Set(cloneEditorValue(source))
|
||||
}
|
||||
}
|
||||
|
||||
// editorCloneMutable 判断类型是否含有需要隔离的公开可变成员
|
||||
// 入参: kind 数据类型
|
||||
// 返回: bool 是否需要独立复制
|
||||
func editorCloneMutable(kind reflect.Type) bool {
|
||||
switch kind.Kind() {
|
||||
case reflect.Pointer, reflect.Slice:
|
||||
return true
|
||||
case reflect.Array:
|
||||
return editorCloneMutable(kind.Elem())
|
||||
case reflect.Struct:
|
||||
return len(editorCloneFields(kind)) != 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// editorCloneFields 按类型复用公开可变字段,索引发布后保持只读
|
||||
// 入参: kind 结构类型
|
||||
// 返回: []int 可变字段索引
|
||||
func editorCloneFields(kind reflect.Type) []int {
|
||||
if cached, ok := editorClonePlans.Load(kind); ok {
|
||||
return cached.([]int)
|
||||
}
|
||||
var fields []int
|
||||
for i := range kind.NumField() {
|
||||
field := kind.Field(i)
|
||||
if field.IsExported() && editorCloneMutable(field.Type) {
|
||||
fields = append(fields, i)
|
||||
}
|
||||
}
|
||||
actual, _ := editorClonePlans.LoadOrStore(kind, fields)
|
||||
return actual.([]int)
|
||||
}
|
||||
Reference in new issue
Block a user