mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-30 01:27:26 +08:00
1 parent
e7686b5430
commit
3b7b7a3299
4 files changed
+123
-47
No files matched your search
+15
-24
@@ -2334,7 +2334,7 @@ async function refreshEditorPage(doc, index, openSeq, clearSelection = false) {
|
|||||||
updateControls();
|
updateControls();
|
||||||
loadDocumentDetails(openSeq);
|
loadDocumentDetails(openSeq);
|
||||||
for (const page of doc.pages) {
|
for (const page of doc.pages) {
|
||||||
observeFlowPage(pageShell(page.index), page.index);
|
observeFlowPage(pageShell(page.index));
|
||||||
const button = el.pageList.querySelector(`[data-page-index="${page.index}"]`);
|
const button = el.pageList.querySelector(`[data-page-index="${page.index}"]`);
|
||||||
observeThumbnail(button, page.index, openSeq);
|
observeThumbnail(button, page.index, openSeq);
|
||||||
}
|
}
|
||||||
@@ -3343,15 +3343,17 @@ async function openDocument(options = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function loadDocumentDetails(openSeq) {
|
async function loadDocumentDetails(openSeq) {
|
||||||
await waitForPaint();
|
|
||||||
if (openSeq !== state.openSeq) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const info = await callWASM("ofdgoDocumentInfo");
|
while (openSeq === state.openSeq) {
|
||||||
if (openSeq === state.openSeq) {
|
await waitForPaint();
|
||||||
|
if (openSeq !== state.openSeq) return;
|
||||||
|
const info = await callWASM("ofdgoDocumentInfo", true);
|
||||||
|
if (openSeq !== state.openSeq) return;
|
||||||
|
if (!info.detailsPending) {
|
||||||
Object.assign(state.doc, info, { detailsPending: false, detailsError: "" });
|
Object.assign(state.doc, info, { detailsPending: false, detailsError: "" });
|
||||||
renderMeta();
|
renderMeta();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (openSeq === state.openSeq) {
|
if (openSeq === state.openSeq) {
|
||||||
@@ -3607,12 +3609,12 @@ function renderPageFlow() {
|
|||||||
|
|
||||||
shell.append(surface, placeholder);
|
shell.append(surface, placeholder);
|
||||||
fragment.append(shell);
|
fragment.append(shell);
|
||||||
targets.push([shell, page.index]);
|
targets.push(shell);
|
||||||
}
|
}
|
||||||
el.svgHost.append(fragment);
|
el.svgHost.append(fragment);
|
||||||
layoutPages();
|
layoutPages();
|
||||||
for (const [shell, index] of targets) {
|
for (const shell of targets) {
|
||||||
observeFlowPage(shell, index);
|
observeFlowPage(shell);
|
||||||
}
|
}
|
||||||
el.emptyState.hidden = true;
|
el.emptyState.hidden = true;
|
||||||
el.pageFrame.hidden = false;
|
el.pageFrame.hidden = false;
|
||||||
@@ -3642,11 +3644,7 @@ function resetPageLoading() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function observeFlowPage(shell, index) {
|
function observeFlowPage(shell) {
|
||||||
const openSeq = state.openSeq;
|
|
||||||
if (index < 4 && index !== state.pageIndex) {
|
|
||||||
renderFlowPage(index, { openSeq, priority: 3 });
|
|
||||||
}
|
|
||||||
const observer = flowPageObserver();
|
const observer = flowPageObserver();
|
||||||
if (observer) {
|
if (observer) {
|
||||||
observer.observe(shell);
|
observer.observe(shell);
|
||||||
@@ -5152,14 +5150,7 @@ function observeThumbnail(button, index, openSeq = state.openSeq) {
|
|||||||
if (observer) {
|
if (observer) {
|
||||||
observer.observe(button);
|
observer.observe(button);
|
||||||
}
|
}
|
||||||
if (index === state.pageIndex || index < 6) {
|
if (index === state.pageIndex || !observer && index < 8) {
|
||||||
renderThumbnail(index, openSeq);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (observer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (index < 8) {
|
|
||||||
renderThumbnail(index, openSeq);
|
renderThumbnail(index, openSeq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5271,7 +5262,7 @@ function renderMeta(keepDetails = false) {
|
|||||||
renderMetaContent(el.attachmentList, [doc.attachments, doc.attachmentError], renderAttachments);
|
renderMetaContent(el.attachmentList, [doc.attachments, doc.attachmentError], renderAttachments);
|
||||||
renderMetaContent(el.signatureList, [doc.signatures, doc.signatureError], renderSignatures);
|
renderMetaContent(el.signatureList, [doc.signatures, doc.signatureError], renderSignatures);
|
||||||
renderMetaContent(el.docFontList, doc.fonts || [], renderDocumentFonts);
|
renderMetaContent(el.docFontList, doc.fonts || [], renderDocumentFonts);
|
||||||
updateTextFonts(canvasEditor.selected, true);
|
refreshEditorFonts();
|
||||||
updateLocalFontButton();
|
updateLocalFontButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-2
@@ -293,13 +293,16 @@ func configureDocument(args []js.Value) (any, error) {
|
|||||||
return currentSession.Summary(), nil
|
return currentSession.Summary(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentInfo 获取首屏之后加载的字体统计和验签结果
|
// documentInfo 获取字体统计和验签结果,首个参数为true时逐页扫描
|
||||||
// 入参: args 浏览器参数
|
// 入参: args 浏览器参数
|
||||||
// 返回: any 文档信息, error 错误信息
|
// 返回: any 文档信息, error 错误信息
|
||||||
func documentInfo(args []js.Value) (any, error) {
|
func documentInfo(args []js.Value) (any, error) {
|
||||||
if currentSession == nil {
|
if currentSession == nil {
|
||||||
return nil, fmt.Errorf("ofd document is not opened")
|
return nil, fmt.Errorf("ofd document is not opened")
|
||||||
}
|
}
|
||||||
|
if len(args) > 0 && args[0].Bool() && !currentSession.scanFontInfo() {
|
||||||
|
return map[string]bool{"detailsPending": true}, nil
|
||||||
|
}
|
||||||
return currentSession.Info(), nil
|
return currentSession.Info(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2731,7 +2734,14 @@ func editDocument(args []js.Value) (any, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
editor.SetHistoryLimit(100)
|
editor.SetHistoryLimit(100)
|
||||||
return previewEditor(editor, currentSession.Renderer.RenderAnnotations)
|
if currentSession.fontFS != nil {
|
||||||
|
editor.SetFontFS(currentSession.fontFS)
|
||||||
|
}
|
||||||
|
currentEditor = editor
|
||||||
|
currentSession.editing = true
|
||||||
|
copiedObjects = nil
|
||||||
|
copiedStyle = nil
|
||||||
|
return editorSummary(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// previewEditor 通过内存快照更新预览,不生成中间压缩包
|
// previewEditor 通过内存快照更新预览,不生成中间压缩包
|
||||||
|
|||||||
+41
-2
@@ -106,6 +106,10 @@ type Session struct {
|
|||||||
boxCache map[int]ofdgo.Box
|
boxCache map[int]ofdgo.Box
|
||||||
textCache map[int]*ofdgo.PageText
|
textCache map[int]*ofdgo.PageText
|
||||||
svgFonts map[string][]byte
|
svgFonts map[string][]byte
|
||||||
|
fontScan *ofdgo.FontInfoScanner
|
||||||
|
fontInfos []FontInfo
|
||||||
|
fontsRead bool
|
||||||
|
fontAnnotations bool
|
||||||
signatures []SignatureInfo
|
signatures []SignatureInfo
|
||||||
signatureError error
|
signatureError error
|
||||||
signaturesRead bool
|
signaturesRead bool
|
||||||
@@ -282,9 +286,44 @@ func (s *Session) SetFonts(fonts []FontFile) error {
|
|||||||
}
|
}
|
||||||
clear(s.textCache)
|
clear(s.textCache)
|
||||||
clear(s.svgFonts)
|
clear(s.svgFonts)
|
||||||
|
s.resetFontInfo()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resetFontInfo 清除字体统计及扫描状态,供字体或注解配置变更后重算
|
||||||
|
func (s *Session) resetFontInfo() {
|
||||||
|
s.fontScan = nil
|
||||||
|
s.fontInfos = nil
|
||||||
|
s.fontsRead = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// scanFontInfo 分步统计字体,每次最多处理一页,完成后保留当前会话的诊断
|
||||||
|
// 返回: bool 是否完成
|
||||||
|
func (s *Session) scanFontInfo() bool {
|
||||||
|
if s.fontAnnotations != s.Renderer.RenderAnnotations {
|
||||||
|
s.resetFontInfo()
|
||||||
|
s.fontAnnotations = s.Renderer.RenderAnnotations
|
||||||
|
}
|
||||||
|
if s.fontsRead {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if s.fontScan == nil {
|
||||||
|
var err error
|
||||||
|
s.fontScan, err = s.Renderer.ScanFontInfos()
|
||||||
|
if err != nil {
|
||||||
|
s.fontsRead = true
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if s.fontScan.Next() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
s.fontInfos, _ = s.fontScan.Infos()
|
||||||
|
s.fontsRead = true
|
||||||
|
s.fontScan = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// PageText 获取指定页面文字,复用当前会话的文字索引
|
// PageText 获取指定页面文字,复用当前会话的文字索引
|
||||||
// 入参: index 页面索引
|
// 入参: index 页面索引
|
||||||
// 返回: *ofdgo.PageText 页面文字, error 错误信息
|
// 返回: *ofdgo.PageText 页面文字, error 错误信息
|
||||||
@@ -429,9 +468,9 @@ func (s *Session) Info() DocumentInfo {
|
|||||||
}
|
}
|
||||||
info.Pages = append(info.Pages, pageInfo)
|
info.Pages = append(info.Pages, pageInfo)
|
||||||
}
|
}
|
||||||
if fonts, err := s.Renderer.FontInfos(); err == nil {
|
for !s.scanFontInfo() {
|
||||||
info.Fonts = fonts
|
|
||||||
}
|
}
|
||||||
|
info.Fonts = s.fontInfos
|
||||||
info.FontCount = len(info.Fonts)
|
info.FontCount = len(info.Fonts)
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|||||||
+55
-19
@@ -149,11 +149,61 @@ func (r *Reader) embeddedFontFace(of Font) (*FontFace, error) {
|
|||||||
// FontInfos 获取OFD字体诊断信息
|
// FontInfos 获取OFD字体诊断信息
|
||||||
// 返回: []FontInfo 字体诊断列表, error 错误信息
|
// 返回: []FontInfo 字体诊断列表, error 错误信息
|
||||||
func (r *Renderer) FontInfos() ([]FontInfo, error) {
|
func (r *Renderer) FontInfos() ([]FontInfo, error) {
|
||||||
|
scanner, err := r.ScanFontInfos()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for scanner.Next() {
|
||||||
|
}
|
||||||
|
return scanner.Infos()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FontInfoScanner 逐页统计字体用量,不保留页面图元,扫描期间不得修改阅读器或渲染器配置
|
||||||
|
type FontInfoScanner struct {
|
||||||
|
renderer *Renderer
|
||||||
|
doc *Document
|
||||||
|
index int
|
||||||
|
usage map[string]int
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScanFontInfos 创建分步字体诊断,页面读取失败的处理与FontInfos一致
|
||||||
|
// 返回: *FontInfoScanner 字体诊断扫描器, error 错误信息
|
||||||
|
func (r *Renderer) ScanFontInfos() (*FontInfoScanner, error) {
|
||||||
doc, err := r.fontInfoDocument()
|
doc, err := r.fontInfoDocument()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return r.fontInfos(doc, nil)
|
return &FontInfoScanner{renderer: r, doc: doc, usage: make(map[string]int)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next 统计下一页或模板的字体用量
|
||||||
|
// 返回: bool 是否处理了页面,false表示扫描结束
|
||||||
|
func (s *FontInfoScanner) Next() bool {
|
||||||
|
pages := len(s.doc.Pages.Page)
|
||||||
|
if s.index < pages {
|
||||||
|
if counts, err := s.renderer.readPageFontUsage(s.doc.Pages.Page[s.index]); err == nil {
|
||||||
|
for id, count := range counts {
|
||||||
|
s.usage[id] += count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if index := s.index - pages; index < len(s.doc.CommonData.TemplatePage) {
|
||||||
|
if page := s.renderer.loadTemplate(s.doc.CommonData.TemplatePage[index].ID); page != nil {
|
||||||
|
s.renderer.countPageFonts(page, s.usage)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
s.index++
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infos 获取扫描结束后的字体诊断,不返回未完成的用量统计
|
||||||
|
// 返回: []FontInfo 字体诊断列表, error 错误信息
|
||||||
|
func (s *FontInfoScanner) Infos() ([]FontInfo, error) {
|
||||||
|
if s.index < len(s.doc.Pages.Page)+len(s.doc.CommonData.TemplatePage) {
|
||||||
|
return nil, fmt.Errorf("font info scan is not complete")
|
||||||
|
}
|
||||||
|
return s.renderer.fontInfos(s.usage)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FontInfosFromPages 从页面内容获取OFD字体诊断信息
|
// FontInfosFromPages 从页面内容获取OFD字体诊断信息
|
||||||
@@ -164,10 +214,7 @@ func (r *Renderer) FontInfosFromPages(pages []*PageContent) ([]FontInfo, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if pages == nil {
|
return r.fontInfos(r.fontUsage(doc, pages))
|
||||||
pages = []*PageContent{}
|
|
||||||
}
|
|
||||||
return r.fontInfos(doc, pages)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fontInfoDocument 获取字体诊断文档结构
|
// fontInfoDocument 获取字体诊断文档结构
|
||||||
@@ -187,10 +234,9 @@ func (r *Renderer) fontInfoDocument() (*Document, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fontInfos 获取OFD字体诊断信息
|
// fontInfos 获取OFD字体诊断信息
|
||||||
// 入参: doc 文档结构, pages 页面内容列表
|
// 入参: usage 字体使用次数
|
||||||
// 返回: []FontInfo 字体诊断列表, error 错误信息
|
// 返回: []FontInfo 字体诊断列表, error 错误信息
|
||||||
func (r *Renderer) fontInfos(doc *Document, pages []*PageContent) ([]FontInfo, error) {
|
func (r *Renderer) fontInfos(usage map[string]int) ([]FontInfo, error) {
|
||||||
usage := r.fontUsage(doc, pages)
|
|
||||||
fonts, err := r.Reader.Fonts()
|
fonts, err := r.Reader.Fonts()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -271,25 +317,15 @@ func (r *Renderer) fontInfo(font Font) FontInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fontUsage 统计文档字体使用次数
|
// fontUsage 统计文档字体使用次数
|
||||||
// 入参: doc 文档结构, pages 页面内容列表, nil表示读取文档页面
|
// 入参: doc 文档结构, pages 页面内容列表
|
||||||
// 返回: map[string]int 字体使用次数
|
// 返回: map[string]int 字体使用次数
|
||||||
func (r *Renderer) fontUsage(doc *Document, pages []*PageContent) map[string]int {
|
func (r *Renderer) fontUsage(doc *Document, pages []*PageContent) map[string]int {
|
||||||
usage := make(map[string]int)
|
usage := make(map[string]int)
|
||||||
if pages == nil {
|
|
||||||
for _, pageRef := range doc.Pages.Page {
|
|
||||||
if counts, err := r.readPageFontUsage(pageRef); err == nil {
|
|
||||||
for id, count := range counts {
|
|
||||||
usage[id] += count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, page := range pages {
|
for _, page := range pages {
|
||||||
if page != nil {
|
if page != nil {
|
||||||
r.countPageFonts(page, usage)
|
r.countPageFonts(page, usage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
for _, tpl := range doc.CommonData.TemplatePage {
|
for _, tpl := range doc.CommonData.TemplatePage {
|
||||||
if page := r.loadTemplate(tpl.ID); page != nil {
|
if page := r.loadTemplate(tpl.ID); page != nil {
|
||||||
r.countPageFonts(page, usage)
|
r.countPageFonts(page, usage)
|
||||||
|
|||||||
Reference in new issue
Block a user