feat(渲染编辑): 优化渲染编辑完善资源保存
build.yaml / build (push) Successful in 45s

This commit is contained in:
xiaoqidun committed 2026-10-05 12:49:51 +08:00
1 parent 5dcd7a4e8d
commit 6c14eef1ee
39 files changed
+1926 -420

No files matched your search

+119
View File
@@ -0,0 +1,119 @@
// Copyright 2025-2026 肖其顿 (XIAO QI DUN)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ofdgo
import "context"
// pdfObjectChunkLimit 限制导入暂存片段的容量,不限制页面对象数量
const pdfObjectChunkLimit = 256
// pdfObjectBuffer 分块收集导入对象,提交前只整理一次连续数据
type pdfObjectBuffer struct {
parts [][]GraphicObject
size int
}
// appendObject 追加本次导入对象,按需建立独立暂存缓冲
// 入参: object 独立导入对象
func (p *pdfImporter) appendObject(object GraphicObject) {
if p.objects == nil {
p.objects = &pdfObjectBuffer{}
}
p.objects.append(object)
}
// append 追加对象,小批量连续存储,超过阈值后不复制前序片段
// 入参: object 独立对象
func (b *pdfObjectBuffer) append(object GraphicObject) {
index := len(b.parts) - 1
if index == 0 && len(b.parts[0]) == cap(b.parts[0]) && cap(b.parts[0]) < pdfObjectChunkLimit {
part := b.parts[0]
next := make([]GraphicObject, len(part), min(pdfObjectChunkLimit, max(1, cap(part)*2)))
copy(next, part)
b.parts[0] = next
}
if index < 0 || len(b.parts[index]) == cap(b.parts[index]) {
capacity := pdfObjectChunkLimit
if index < 0 {
capacity = 1
}
b.parts = append(b.parts, make([]GraphicObject, 0, capacity))
index++
}
b.parts[index] = append(b.parts[index], object)
b.size++
}
// len 获取暂存对象数量,空缓冲返回零
// 返回: int 对象数量
func (b *pdfObjectBuffer) len() int {
if b == nil {
return 0
}
return b.size
}
// truncate 回滚到已有对象位置,清理丢弃对象及片段引用
// 入参: size 保留对象数量
func (b *pdfObjectBuffer) truncate(size int) {
if size < 0 || size > b.len() {
panic("invalid PDF object buffer size")
}
if size == b.len() {
return
}
remaining := size
for index, part := range b.parts {
if remaining <= len(part) {
clear(part[remaining:])
b.parts[index] = part[:remaining]
clear(b.parts[index+1:])
b.parts = b.parts[:index+1]
b.size = size
return
}
remaining -= len(part)
}
}
// data 按绘制顺序整理独立对象数组,取消时保留原片段供重试
// 入参: ctx 取消上下文
// 返回: []GraphicObject 暂存数据, error 取消错误
func (b *pdfObjectBuffer) data(ctx context.Context) ([]GraphicObject, error) {
if err := ctx.Err(); err != nil {
return nil, err
}
if b.len() == 0 {
return nil, nil
}
if len(b.parts) == 1 {
return b.parts[0][:b.size:b.size], nil
}
objects := make([]GraphicObject, b.size)
offset := 0
for _, part := range b.parts {
if err := ctx.Err(); err != nil {
return nil, err
}
offset += copy(objects[offset:], part)
}
if err := ctx.Err(); err != nil {
return nil, err
}
b.parts[0] = objects
clear(b.parts[1:])
b.parts = b.parts[:1]
return objects, nil
}