Files
ofdgo/ofdgo_render.go
T
2026-10-14 08:22:31 +08:00

193 lines
5.9 KiB
Go

// 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 "fmt"
// RenderPage 编译页面为与绘图库无关的只读绘制数据
// 入参: page 页面内容
// 返回: *RasterPage 绘制页面, error 错误信息
func (r *Renderer) RenderPage(page *PageContent) (*RasterPage, error) {
return r.CompilePage(page)
}
// GetPageBox 获取页面物理区域
// 入参: page 页面内容
// 返回: Box 区域, error 错误信息
func (r *Renderer) GetPageBox(page *PageContent) (Box, error) {
area, err := r.Reader.resolvePageAreaContext(r.outputContext(), page.Area, page.Template)
if err != nil {
return Box{}, err
}
boxStr := area.PhysicalBox
if boxStr == "" {
boxStr = area.ApplicationBox
}
if boxStr == "" {
boxStr = area.ContentBox
}
if boxStr == "" {
boxStr = "0 0 210 297"
}
return ParseBox(boxStr)
}
// PageLinks 获取页面、模板和可见注释中图元的点击动作,保留复杂区域和组合图元
// 入参: page 页面内容
// 返回: []PageLink 页面链接, error 错误信息
func (r *Renderer) PageLinks(page *PageContent) ([]PageLink, error) {
if r.RenderAnnotations && r.Reader.relatedPending {
if _, err := r.Reader.DocContext(r.outputContext()); err != nil {
return nil, err
}
}
sources := r.pageActionSources(page)
if r.RenderAnnotations {
sources = append(sources, r.annotationActionSources(r.Reader.Annots[page.ID])...)
}
return r.sourceLinks(sources, "CLICK")
}
// DocumentOpenLinks 获取文档打开动作的有序目标,不执行动作
// 返回: []PageLink 动作目标, error 文档解析错误
func (r *Renderer) DocumentOpenLinks() ([]PageLink, error) {
doc, err := r.Reader.Doc()
if err != nil {
return nil, err
}
return r.sourceLinks([]actionSource{{Actions: doc.Actions}}, "DO")
}
// PageOpenLinks 获取页面及模板打开动作的有序目标,不遍历图元或执行动作
// 入参: page 页面内容
// 返回: []PageLink 动作目标, error 目标解析错误
func (r *Renderer) PageOpenLinks(page *PageContent) ([]PageLink, error) {
return r.sourceLinks(r.pageOpenActionSources(page), "PO")
}
// OutlineLinks 获取目录节点的有序动作目标,不执行动作
// 入参: path 从根节点开始的各级索引
// 返回: []PageLink 动作目标,不包含页面点击区域, error 目录路径或解析错误
func (r *Renderer) OutlineLinks(path []int) ([]PageLink, error) {
doc, err := r.Reader.Doc()
if err != nil {
return nil, err
}
if len(path) == 0 {
return nil, fmt.Errorf("empty outline path")
}
nodes := doc.Outlines.OutlineElem
var node OutlineElem
for _, index := range path {
if index < 0 || index >= len(nodes) {
return nil, fmt.Errorf("invalid outline index: %d", index)
}
node = nodes[index]
nodes = node.OutlineElem
}
return r.sourceLinks([]actionSource{{Actions: node.Actions}}, "")
}
// sourceLinks 解析动作目标,保留动作顺序及独立目标数据
// 入参: sources 动作来源, event 事件类型,空值表示目录激活动作
// 返回: []PageLink 动作目标, error 区域或文档解析错误
func (r *Renderer) sourceLinks(sources []actionSource, event string) ([]PageLink, error) {
var links []PageLink
var bookmarks map[string]Dest
for sourceIndex, source := range sources {
start := len(links)
for _, action := range source.Actions {
if event != "" && action.Event != event {
continue
}
var link PageLink
if event == "CLICK" {
box, path, err := r.actionLinkRegion(source, action)
if err != nil {
return nil, err
}
if box.W <= 0 || box.H <= 0 {
continue
}
link.Box, link.Path = box, path
}
if action.Goto != nil {
if bookmarks == nil {
doc, err := r.Reader.Doc()
if err != nil {
return nil, err
}
bookmarks = make(map[string]Dest, len(doc.Bookmarks.Bookmark))
for _, bookmark := range doc.Bookmarks.Bookmark {
bookmarks[bookmark.Name] = bookmark.Dest
}
}
if dest := gotoDest(action.Goto, bookmarks); dest != nil {
value := *dest
link.Dest = &value
links = append(links, link)
}
} else if action.URI != nil && action.URI.URI != "" {
link.URI = resolveActionURI(*action.URI)
link.Target = action.URI.Target
links = append(links, link)
} else if action.GotoA != nil {
link.Attachment = action.GotoA.AttachID
if action.GotoA.NewWindow != nil {
window := *action.GotoA.NewWindow
link.NewWindow = &window
}
links = append(links, link)
} else if action.Sound != nil {
value := *action.Sound
if value.Volume != nil {
volume := *value.Volume
value.Volume = &volume
}
link.Sound = &value
links = append(links, link)
} else if action.Movie != nil {
value := *action.Movie
if value.Operator == "" {
value.Operator = "Play"
}
link.Movie = &value
if source.Graphic {
playback := source.Box
link.PlaybackBox = &playback
}
links = append(links, link)
}
}
if len(links)-start > 1 {
for i := start; i < len(links); i++ {
links[i].Group = sourceIndex + 1
}
}
}
return links, nil
}
// RenderPageByIndex 按索引渲染页面
// 入参: index 页面索引,从0开始
// 返回: *RasterPage 绘制页面, error 错误信息
func (r *Renderer) RenderPageByIndex(index int) (*RasterPage, error) {
page, err := r.Reader.PageContentByIndex(index)
if err != nil {
return nil, err
}
return r.RenderPage(page)
}