diff --git a/internal/webview/webview.go b/internal/webview/webview.go index 4c5dc13..de5bebc 100644 --- a/internal/webview/webview.go +++ b/internal/webview/webview.go @@ -717,7 +717,7 @@ func (h *Host) readFonts() { } // loadFont 按转换请求读取单个系统字体 -// 入参: ctx 调用上下文, name 字体文件路径及字体索引 +// 入参: ctx 调用上下文, name 字体别名对应的文件名 // 返回: []byte 字体数据, error 读取错误 func (h *Host) loadFont(ctx context.Context, name string) ([]byte, error) { if err := ctx.Err(); err != nil { diff --git a/ofdgo_convert_pool.go b/ofdgo_convert_pool.go index bc4432e..3ebcb41 100644 --- a/ofdgo_convert_pool.go +++ b/ofdgo_convert_pool.go @@ -82,6 +82,12 @@ func (p *ConversionPool) memoryLimit() int64 { // 入参: ctx 取消上下文, image 是否为图像任务, size 图像工作量 // 返回: error 取消错误 func (p *ConversionPool) acquire(ctx context.Context, image bool, size int64) error { + var timer *time.Timer + defer func() { + if timer != nil { + timer.Stop() + } + }() for { if err := ctx.Err(); err != nil { return err @@ -104,15 +110,23 @@ func (p *ConversionPool) acquire(ctx context.Context, image bool, size int64) er } changed := p.changed p.mu.Unlock() - timer := time.NewTimer(250 * time.Millisecond) + var tick <-chan time.Time + if p.options.AvailableMemory != nil { + if timer == nil { + timer = time.NewTimer(250 * time.Millisecond) + } else { + timer.Reset(250 * time.Millisecond) + } + tick = timer.C + } select { case <-ctx.Done(): - timer.Stop() - return ctx.Err() case <-changed: - case <-timer.C: + case <-tick: + } + if timer != nil { + timer.Stop() } - timer.Stop() } } diff --git a/ofdgo_editor_composite.go b/ofdgo_editor_composite.go index b522d8f..8edbfb1 100644 --- a/ofdgo_editor_composite.go +++ b/ofdgo_editor_composite.go @@ -119,6 +119,13 @@ func (e *Editor) CompositeObjectsAt(page int, path ObjectPath, indexes []int) ([ return nil, err } defer reader.Close() + return e.measureCompositeSelection(renderer, nodes, indexes) +} + +// measureCompositeSelection 复用已解析范围,按输入索引度量成员并保留容器位置 +// 入参: renderer 资源渲染器, nodes 范围内全部成员, indexes 不重复的成员序号 +// 返回: []CompositeMember 独立成员快照, error 索引或度量错误 +func (e *Editor) measureCompositeSelection(renderer *Renderer, nodes []*editorCompositeNode, indexes []int) ([]CompositeMember, error) { selected := make([]*editorCompositeNode, len(indexes)) seen := make(map[int]bool, len(indexes)) for i, index := range indexes { diff --git a/ofdgo_editor_text_selection.go b/ofdgo_editor_text_selection.go index 6bd3901..bc2fef3 100644 --- a/ofdgo_editor_text_selection.go +++ b/ofdgo_editor_text_selection.go @@ -118,15 +118,15 @@ func (e *Editor) analyzeTextSelection(page int, selection TextSelection) (TextSe if len(selection.IDs) != 0 || len(selection.Indexes) == 0 { return result, fmt.Errorf("composite selection requires indexes only") } - members, err := e.CompositeObjectsAt(page, root, selection.Indexes) - if err != nil { - return result, err - } - reader, _, _, nodes, err := e.compositeScope(page, root) + reader, renderer, _, nodes, err := e.compositeScope(page, root) if err != nil { return result, err } defer reader.Close() + members, err := e.measureCompositeSelection(renderer, nodes, selection.Indexes) + if err != nil { + return result, err + } for i, member := range members { if member.Object.Type != "TextObject" || !member.Capabilities.RewriteText { return result, fmt.Errorf("selection member is not editable text") @@ -648,19 +648,21 @@ func (e *Editor) prepareTextSelectionEdit(edit *TextSelectionEdit) error { // 返回: TextSelection 提交后可用于重新枚举的选择 func selectionAfterTextEdit(analysis TextSelectionAnalysis, parts []TextSelectionPart, reflow bool) TextSelection { result := TextSelection{Root: analysis.Selection.Root} - deleted := make(map[int]bool) + var deleted []int if reflow { for _, part := range analysis.Parts[1:] { - deleted[part.Index] = true + deleted = append(deleted, part.Index) } parts = analysis.Parts[:1] } else { for _, part := range parts { if part.Deleted { - deleted[part.Index] = true + deleted = append(deleted, part.Index) } } } + slices.Sort(deleted) + deleted = slices.Compact(deleted) for _, part := range parts { if part.Deleted { continue @@ -669,13 +671,8 @@ func selectionAfterTextEdit(analysis TextSelectionAnalysis, parts []TextSelectio result.IDs = append(result.IDs, part.ID) continue } - index := part.Index - for removed := range deleted { - if removed < part.Index { - index-- - } - } - result.Indexes = append(result.Indexes, index) + removed, _ := slices.BinarySearch(deleted, part.Index) + result.Indexes = append(result.Indexes, part.Index-removed) } return result } @@ -700,35 +697,39 @@ func (e *Editor) UpdateTextSelection(page int, selection TextSelection, edit Tex return e.reflowTextSelection(page, selection, edit, preview) } if selection.Root != nil { + parts := make(map[int]int, len(preview.Parts)) + for i, part := range preview.Parts { + parts[part.Index] = i + } return e.editCompositeObjects(page, *selection.Root, selection.Indexes, func(_ *Renderer, nodes []*editorCompositeNode, _ []CompositeMember) error { for i, node := range nodes { - for _, part := range preview.Parts { - if part.Index != selection.Indexes[i] { - continue - } - if part.Deleted { - node.owner.patches = append(node.owner.patches, editorXMLPatch{node.span.start, node.span.end, nil}) - continue - } - object := cloneEditorData(node.object) - object.TextObject.TextCode, object.TextObject.CGTransform = part.TextObject.TextCode, part.TextObject.CGTransform - if edit.Font != "" { - object.TextObject.Font = part.TextObject.Font - } - if edit.Size != 0 { - object.TextObject.Size = part.TextObject.Size - } - if edit.Color != "" { - object.TextObject.FillColor = part.TextObject.FillColor - } - if reflect.DeepEqual(object, node.object) { - continue - } - if err := node.update(object); err != nil { - return err - } - node.setState(editorCompositeState{}) + index, exists := parts[selection.Indexes[i]] + if !exists { + continue } + part := &preview.Parts[index] + if part.Deleted { + node.owner.patches = append(node.owner.patches, editorXMLPatch{node.span.start, node.span.end, nil}) + continue + } + object := cloneEditorData(node.object) + object.TextObject.TextCode, object.TextObject.CGTransform = part.TextObject.TextCode, part.TextObject.CGTransform + if edit.Font != "" { + object.TextObject.Font = part.TextObject.Font + } + if edit.Size != 0 { + object.TextObject.Size = part.TextObject.Size + } + if edit.Color != "" { + object.TextObject.FillColor = part.TextObject.FillColor + } + if reflect.DeepEqual(object, node.object) { + continue + } + if err := node.update(object); err != nil { + return err + } + node.setState(editorCompositeState{}) } return nil })