diff --git a/assets/webui/ofdgo.js b/assets/webui/ofdgo.js index d5a229f..0a58b40 100644 --- a/assets/webui/ofdgo.js +++ b/assets/webui/ofdgo.js @@ -1665,6 +1665,7 @@ async function processPageRenderQueue() { const page = await callWASM("ofdgoRenderPage", task.index); await loadSVGFonts(page.fonts, task.openSeq); if (task.openSeq === state.openSeq) { + page.text = JSON.parse(page.text); state.pageCache.set(task.index, page); } task.resolve(page); diff --git a/internal/webui/wasm.go b/internal/webui/wasm.go index b72c1e0..af5f4b7 100644 --- a/internal/webui/wasm.go +++ b/internal/webui/wasm.go @@ -210,7 +210,7 @@ func renderPage(args []js.Value) (any, error) { "svg": page.SVG, "links": links, "fonts": fonts, - "text": js.Global().Get("JSON").Call("parse", string(textData)), + "text": string(textData), }), nil } diff --git a/internal/webui/webui.go b/internal/webui/webui.go index 80374f0..acabd39 100644 --- a/internal/webui/webui.go +++ b/internal/webui/webui.go @@ -418,7 +418,13 @@ func (s *Session) RenderPageSVG(index int) (PageSVG, error) { return PageSVG{}, err } var buf bytes.Buffer - fonts, err := s.Renderer.RenderToSVGWithFonts(page, &buf) + renderer := *s.Renderer + if s.textCache[index] == nil { + renderer.OnPageText = func(_ *ofdgo.PageContent, text *ofdgo.PageText) { + s.textCache[index] = text + } + } + fonts, err := renderer.RenderToSVGWithFonts(page, &buf) if err != nil { return PageSVG{}, err } diff --git a/ofdgo_renderer.go b/ofdgo_renderer.go index bdee388..c5c6c05 100644 --- a/ofdgo_renderer.go +++ b/ofdgo_renderer.go @@ -23,10 +23,12 @@ import ( ) // Renderer 渲染器实现 +// OnPageText可选,接收页面绘制时同步提取的文字,不包含图案和签名外观 type Renderer struct { Reader *Reader DPI float64 RenderAnnotations bool + OnPageText func(*PageContent, *PageText) fontFamily *canvas.FontFamily defaultFontLoaded bool DrawParams map[string]*DrawParam @@ -47,6 +49,7 @@ type Renderer struct { fontFS []fs.FS decodeImages bool pageText *PageText + textOnly bool } // RendererOption 渲染器配置选项 @@ -137,6 +140,11 @@ func (r *Renderer) renderPageToContext(ctx *canvas.Context, page *PageContent, d if err != nil { return err } + if r.OnPageText != nil { + renderer := *r + renderer.pageText = &PageText{} + r = &renderer + } pageH := box.H if drawBackground { ctx.SetFillColor(canvas.White) @@ -164,6 +172,9 @@ func (r *Renderer) renderPageToContext(ctx *canvas.Context, page *PageContent, d r.renderStamp(ctx, stamp, pageH) } } + if r.OnPageText != nil { + r.OnPageText(page, r.pageText) + } return nil } diff --git a/ofdgo_renderer_image.go b/ofdgo_renderer_image.go index ec64d30..c4a72de 100644 --- a/ofdgo_renderer_image.go +++ b/ofdgo_renderer_image.go @@ -30,7 +30,7 @@ import ( // renderImage 渲染图片 // 入参: ctx 画布上下文, obj 图片对象, pageH 页面高度, parentCTM 父级CTM, boundaryInCTM 边界是否参与父级CTM, parentClip 父级裁剪路径 func (r *Renderer) renderImage(ctx *canvas.Context, obj ImageObject, pageH float64, parentCTM *Matrix, boundaryInCTM bool, parentClip *canvas.Path) { - if r.pageText != nil { + if r.textOnly { return } if obj.Visible != nil && !*obj.Visible { diff --git a/ofdgo_renderer_path.go b/ofdgo_renderer_path.go index 13bc465..067ee11 100644 --- a/ofdgo_renderer_path.go +++ b/ofdgo_renderer_path.go @@ -173,7 +173,7 @@ func (s *pathStyle) scale(ctm Matrix) { // renderPath 渲染路径 // 入参: ctx 画布上下文, obj 路径对象, pageH 页面高度, defaults 默认绘制参数, parentCTM 父级CTM, boundaryInCTM 边界是否参与CTM变换, parentClip 父级裁剪路径 func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64, defaults *DrawParam, parentCTM *Matrix, boundaryInCTM bool, parentClip *canvas.Path) { - if r.pageText != nil { + if r.textOnly { return } if obj.Visible != nil && !*obj.Visible { @@ -304,6 +304,11 @@ func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64 // renderPattern 渲染图案填充 // 入参: ctx 画布上下文, pattern 底纹画刷, pageH 页面高度, clip 绘制区域, objectCTM 对象变换矩阵 func (r *Renderer) renderPattern(ctx *canvas.Context, pattern *patternPaint, pageH float64, clip *canvas.Path, objectCTM Matrix) { + if r.pageText != nil { + renderer := *r + renderer.pageText = nil + r = &renderer + } if clip == nil || clip.Empty() || len(pattern.CellContent.Objects) == 0 { return } @@ -504,6 +509,7 @@ func (r *Renderer) buildClipPath(clips *Clips, pageH float64, bx, by float64, ob textObj.StrokeColor = &StrokeColor{Value: "0 0 0"} textRenderer := *r textRenderer.pageText = nil + textRenderer.textOnly = false textRenderer.renderText(ctx, textObj, 0, r.drawParamDefaults(area.DrawParam, nil), nil, false, nil) } } diff --git a/ofdgo_renderer_stamp.go b/ofdgo_renderer_stamp.go index 7d9f8d6..7f13dd6 100644 --- a/ofdgo_renderer_stamp.go +++ b/ofdgo_renderer_stamp.go @@ -28,7 +28,7 @@ import ( // renderStamp 渲染印章 // 入参: ctx 画布上下文, s 印章对象, pageH 页面高度 func (r *Renderer) renderStamp(ctx *canvas.Context, s Stamp, pageH float64) { - if r.pageText != nil { + if r.textOnly { return } if s.Type == "ofd" && len(s.Data) > 0 { diff --git a/ofdgo_renderer_text.go b/ofdgo_renderer_text.go index cdca500..ce29d71 100644 --- a/ofdgo_renderer_text.go +++ b/ofdgo_renderer_text.go @@ -301,7 +301,9 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64 } textRun.addSpan(textPos+spans[i][0], textPos+spans[i][1], bounds, m.Scale(scaleX, 1), clipPath, pageH) } - continue + if r.textOnly { + continue + } } if shouldStroke { scaleX := hScale diff --git a/ofdgo_search.go b/ofdgo_search.go index 37bc849..2060209 100644 --- a/ofdgo_search.go +++ b/ofdgo_search.go @@ -65,7 +65,9 @@ func (r *Renderer) PageText(page *PageContent) (*PageText, error) { return nil, err } renderer := *r + renderer.OnPageText = nil renderer.pageText = &PageText{} + renderer.textOnly = true if err := renderer.renderPageToContext(canvas.NewContext(canvas.New(box.W, box.H)), page, false); err != nil { return nil, err }