mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 16:59:27 +08:00
1 parent
65a839f1e8
commit
9b38f6f039
4 files changed
+253
-86
No files matched your search
@@ -10,7 +10,7 @@ require (
|
|||||||
github.com/tdewolff/font v0.0.0-20260913163313-54f98bb59ee6
|
github.com/tdewolff/font v0.0.0-20260913163313-54f98bb59ee6
|
||||||
github.com/xiaoqidun/j2kgo v0.0.0-20261009063910-4865a21ef893
|
github.com/xiaoqidun/j2kgo v0.0.0-20261009063910-4865a21ef893
|
||||||
github.com/xiaoqidun/jbig2 v1.1.3
|
github.com/xiaoqidun/jbig2 v1.1.3
|
||||||
github.com/xiaoqidun/pdfgo v0.0.0-20261009121346-abd17a2aa440
|
github.com/xiaoqidun/pdfgo v0.0.0-20261009130638-37c73506b373
|
||||||
golang.org/x/crypto v0.57.0
|
golang.org/x/crypto v0.57.0
|
||||||
golang.org/x/image v0.46.0
|
golang.org/x/image v0.46.0
|
||||||
golang.org/x/text v0.42.0
|
golang.org/x/text v0.42.0
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ github.com/xiaoqidun/j2kgo v0.0.0-20261009063910-4865a21ef893 h1:jmQlBO7R+bcimOM
|
|||||||
github.com/xiaoqidun/j2kgo v0.0.0-20261009063910-4865a21ef893/go.mod h1:DCwAfuDzCDYqUiAlZ7BDwigTjaXw7o9L1FtEma/D1aA=
|
github.com/xiaoqidun/j2kgo v0.0.0-20261009063910-4865a21ef893/go.mod h1:DCwAfuDzCDYqUiAlZ7BDwigTjaXw7o9L1FtEma/D1aA=
|
||||||
github.com/xiaoqidun/jbig2 v1.1.3 h1:p0d8FMLiLfzQuX278T4VTfTz8tIJEw87u4v63lH4CBc=
|
github.com/xiaoqidun/jbig2 v1.1.3 h1:p0d8FMLiLfzQuX278T4VTfTz8tIJEw87u4v63lH4CBc=
|
||||||
github.com/xiaoqidun/jbig2 v1.1.3/go.mod h1:8QonVWtENmh2kc6l+leqeGl7psb79DWlHDkCpdChjfQ=
|
github.com/xiaoqidun/jbig2 v1.1.3/go.mod h1:8QonVWtENmh2kc6l+leqeGl7psb79DWlHDkCpdChjfQ=
|
||||||
github.com/xiaoqidun/pdfgo v0.0.0-20261009121346-abd17a2aa440 h1:auHwW058jOQGHVB6FXNfT6kdLh5DU6KByu4DGDSLJ7U=
|
github.com/xiaoqidun/pdfgo v0.0.0-20261009130638-37c73506b373 h1:jw9W5q/sUnMOSEbYQD5U6Ppd0cDHXTuzREOwXm6ABtk=
|
||||||
github.com/xiaoqidun/pdfgo v0.0.0-20261009121346-abd17a2aa440/go.mod h1:swzoqA5+wSHsRPesJS1VOMLhSyWkLCSQ+IgHNYXbcKo=
|
github.com/xiaoqidun/pdfgo v0.0.0-20261009130638-37c73506b373/go.mod h1:swzoqA5+wSHsRPesJS1VOMLhSyWkLCSQ+IgHNYXbcKo=
|
||||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||||
github.com/yuin/goldmark v1.8.5 h1:r6N5afV5qj/5S4UTch8agZHJ8UxNCMwX7WjkkJam2NA=
|
github.com/yuin/goldmark v1.8.5 h1:r6N5afV5qj/5S4UTch8agZHJ8UxNCMwX7WjkkJam2NA=
|
||||||
|
|||||||
@@ -0,0 +1,215 @@
|
|||||||
|
// 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"
|
||||||
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
|
||||||
|
"github.com/tdewolff/canvas"
|
||||||
|
"github.com/xiaoqidun/pdfgo"
|
||||||
|
)
|
||||||
|
|
||||||
|
// pdfActionArea 保存互不重叠的点击区域及其有序动作
|
||||||
|
type pdfActionArea struct {
|
||||||
|
Path GeometryPath
|
||||||
|
Actions []pdfNavigationAction
|
||||||
|
}
|
||||||
|
|
||||||
|
// addActions 按命中区域组合同一对象的点击动作,不合并其他对象的事件
|
||||||
|
// 入参: renderer 渲染器, page 页面索引, source 动作来源, bookmarks 书签, pageIndex 页面索引表, pages 页面数据
|
||||||
|
// 返回: error 区域、目标或取消错误
|
||||||
|
func (n *pdfNavigation) addActions(renderer *Renderer, page int, source actionSource, bookmarks map[string]Dest, pageIndex map[string]int, pages []RenderDocumentPage) error {
|
||||||
|
ctx := renderer.outputContext()
|
||||||
|
var areas []pdfActionArea
|
||||||
|
for _, action := range source.Actions {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if action.Event != "CLICK" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
value, err := pdfNavigationTarget(action, bookmarks, pageIndex, pages)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if value == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
box, outline, err := renderer.actionLinkRegion(source, action)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if box.W <= 0 || box.H <= 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
path := geometryRectangle(box)
|
||||||
|
if outline != "" {
|
||||||
|
parsed, err := canvas.ParseSVGPath(outline)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if parsed.Len() > pdfLinkEdgeLimit {
|
||||||
|
return fmt.Errorf("PDF link region exceeds edge limit")
|
||||||
|
}
|
||||||
|
parsed, err = flattenPDFLink(ctx, parsed)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
path = *geometryFromCanvasPath(parsed.Transform(canvas.Identity.Scale(1, -1)))
|
||||||
|
}
|
||||||
|
areas, err = partitionPDFActions(ctx, renderer, areas, path, *value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, area := range areas {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
box, err := area.Path.Bounds()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if box.W <= 0 || box.H <= 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
outline, err := area.Path.SVG()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
region, err := pdfActionRegion(ctx, outline, pages[page].Box.H)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if region != nil && len(region.Quads) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
n.Link[page] = append(n.Link[page], pdfLink{Rect: pdfSourceRect(box, pages[page].Box.H), Region: region, Actions: area.Actions})
|
||||||
|
n.exactLinks = true
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// partitionPDFActions 将新增动作区域与已有区域分离,使每个区域具有唯一动作序列
|
||||||
|
// 入参: ctx 取消上下文, renderer 渲染器, areas 已有分区, path 新动作区域, action 新动作
|
||||||
|
// 返回: []pdfActionArea 新分区, error 几何、复杂度或取消错误
|
||||||
|
func partitionPDFActions(ctx context.Context, renderer *Renderer, areas []pdfActionArea, path GeometryPath, action pdfNavigationAction) ([]pdfActionArea, error) {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(areas) == 1 && slices.Equal(areas[0].Path, path) {
|
||||||
|
areas[0].Actions = append(areas[0].Actions, action)
|
||||||
|
return areas, nil
|
||||||
|
}
|
||||||
|
remaining := path
|
||||||
|
result := make([]pdfActionArea, 0, len(areas)+1)
|
||||||
|
box, err := path.Bounds()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, area := range areas {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
other, err := area.Path.Bounds()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if box.X >= other.X+other.W || other.X >= box.X+box.W || box.Y >= other.Y+other.H || other.Y >= box.Y+box.H {
|
||||||
|
result = append(result, area)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
geometry, err := renderer.Geometry()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
common, err := combinePDFActionRegion(ctx, geometry, area.Path, path, GeometryIntersect)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(common) == 0 {
|
||||||
|
result = append(result, area)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
only, err := combinePDFActionRegion(ctx, geometry, area.Path, path, GeometrySubtract)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(only) != 0 {
|
||||||
|
result = append(result, pdfActionArea{Path: only, Actions: area.Actions})
|
||||||
|
}
|
||||||
|
result = append(result, pdfActionArea{Path: common, Actions: append(slices.Clone(area.Actions), action)})
|
||||||
|
remaining, err = combinePDFActionRegion(ctx, geometry, remaining, area.Path, GeometrySubtract)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(result) > pdfLinkEdgeLimit {
|
||||||
|
return nil, fmt.Errorf("PDF action partition exceeds region limit")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(remaining) != 0 {
|
||||||
|
result = append(result, pdfActionArea{Path: remaining, Actions: []pdfNavigationAction{action}})
|
||||||
|
}
|
||||||
|
if len(result) > pdfLinkEdgeLimit {
|
||||||
|
return nil, fmt.Errorf("PDF action partition exceeds region limit")
|
||||||
|
}
|
||||||
|
edges := 0
|
||||||
|
for _, area := range result {
|
||||||
|
edges += len(area.Path)
|
||||||
|
if edges > pdfLinkQuadLimit {
|
||||||
|
return nil, fmt.Errorf("PDF action partition exceeds total edge limit")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result, ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
// combinePDFActionRegion 对有界点击路径执行布尔运算,检查取消及中间结果规模
|
||||||
|
// 入参: ctx 取消上下文, geometry 几何后端, left 左路径, right 右路径, operation 运算类型
|
||||||
|
// 返回: GeometryPath 结果路径, error 几何、复杂度或取消错误
|
||||||
|
func combinePDFActionRegion(ctx context.Context, geometry GeometryBackend, left, right GeometryPath, operation GeometryOperation) (GeometryPath, error) {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(left) > pdfLinkEdgeLimit || len(right) > pdfLinkEdgeLimit {
|
||||||
|
return nil, fmt.Errorf("PDF action partition exceeds edge limit")
|
||||||
|
}
|
||||||
|
result, err := geometry.Combine(left, right, operation)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(result) > pdfLinkEdgeLimit {
|
||||||
|
return nil, fmt.Errorf("PDF action partition exceeds edge limit")
|
||||||
|
}
|
||||||
|
return result, ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
// pdfNavigationValues 将输出页索引替换为实际PDF页面引用
|
||||||
|
// 入参: actions 有序导航动作, pages 输出页面引用
|
||||||
|
// 返回: []pdfgo.NavigationAction 原生导航动作
|
||||||
|
func pdfNavigationValues(actions []pdfNavigationAction, pages []pdfgo.Reference) []pdfgo.NavigationAction {
|
||||||
|
values := make([]pdfgo.NavigationAction, 0, len(actions))
|
||||||
|
for _, action := range actions {
|
||||||
|
value := pdfgo.NavigationAction{URI: action.URI}
|
||||||
|
if action.Target != nil {
|
||||||
|
dest := action.Target.Destination
|
||||||
|
dest.Page = pages[action.Target.Page]
|
||||||
|
value.Destination = &dest
|
||||||
|
}
|
||||||
|
values = append(values, value)
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
@@ -46,10 +46,9 @@ type pdfNavigation struct {
|
|||||||
|
|
||||||
// pdfLink PDF链接
|
// pdfLink PDF链接
|
||||||
type pdfLink struct {
|
type pdfLink struct {
|
||||||
URI string
|
Rect canvas.Rect
|
||||||
Rect canvas.Rect
|
Region *pdfgo.LinkRegion
|
||||||
Region *pdfgo.LinkRegion
|
Actions []pdfNavigationAction
|
||||||
Target *pdfTarget
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pdfTarget 保存输出页索引及默认用户空间中的跳转参数
|
// pdfTarget 保存输出页索引及默认用户空间中的跳转参数
|
||||||
@@ -62,11 +61,11 @@ type pdfTarget struct {
|
|||||||
type pdfOutline struct {
|
type pdfOutline struct {
|
||||||
Name string
|
Name string
|
||||||
Level int
|
Level int
|
||||||
Actions []pdfOutlineAction
|
Actions []pdfNavigationAction
|
||||||
}
|
}
|
||||||
|
|
||||||
// pdfOutlineAction 保存目录的导航动作,输出时关联实际页面引用
|
// pdfNavigationAction 保存链接或目录的导航动作,输出时关联实际页面引用
|
||||||
type pdfOutlineAction struct {
|
type pdfNavigationAction struct {
|
||||||
URI string
|
URI string
|
||||||
Target *pdfTarget
|
Target *pdfTarget
|
||||||
}
|
}
|
||||||
@@ -154,37 +153,8 @@ func newPDFNavigation(renderer *Renderer, doc *Document, pages []RenderDocumentP
|
|||||||
sources = append(sources, renderer.annotationActionSources(renderer.Reader.Annots[page.Content.ID])...)
|
sources = append(sources, renderer.annotationActionSources(renderer.Reader.Annots[page.Content.ID])...)
|
||||||
}
|
}
|
||||||
for _, source := range sources {
|
for _, source := range sources {
|
||||||
for _, action := range source.Actions {
|
if err := navigation.addActions(renderer, i, source, bookmarks, pageIndex, pages); err != nil {
|
||||||
if action.Event != "CLICK" {
|
return nil, err
|
||||||
continue
|
|
||||||
}
|
|
||||||
box, outline, err := renderer.actionLinkRegion(source, action)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if box.W <= 0 || box.H <= 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
rect := pdfSourceRect(box, page.Box.H)
|
|
||||||
count := len(navigation.Link[i])
|
|
||||||
if err := navigation.addAction(i, rect, action, bookmarks, pageIndex, pages); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(navigation.Link[i]) == count || outline == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
region, err := pdfActionRegion(renderer.outputContext(), outline, page.Box.H)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if region != nil && len(region.Quads) == 0 {
|
|
||||||
navigation.Link[i] = navigation.Link[i][:count]
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if region != nil {
|
|
||||||
navigation.Link[i][count].Region = region
|
|
||||||
navigation.exactLinks = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,31 +166,29 @@ func newPDFNavigation(renderer *Renderer, doc *Document, pages []RenderDocumentP
|
|||||||
return navigation, nil
|
return navigation, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// addAction 添加PDF动作
|
// pdfNavigationTarget 转换导航动作,选页未包含的目标不写入
|
||||||
// 入参: page 页面索引, rect 动作区域, action 动作, bookmarks 书签, pageIndex 页面索引表, pages 页面数据
|
// 入参: action 动作, bookmarks 书签, pageIndex 页面索引表, pages 页面数据
|
||||||
// 返回: error 目标参数错误
|
// 返回: *pdfNavigationAction 导航动作,nil表示无输出动作, error 目标参数错误
|
||||||
func (n *pdfNavigation) addAction(page int, rect canvas.Rect, action Action, bookmarks map[string]Dest, pageIndex map[string]int, pages []RenderDocumentPage) error {
|
func pdfNavigationTarget(action Action, bookmarks map[string]Dest, pageIndex map[string]int, pages []RenderDocumentPage) (*pdfNavigationAction, error) {
|
||||||
if action.Goto != nil {
|
if action.Goto != nil {
|
||||||
dest := gotoDest(action.Goto, bookmarks)
|
dest := gotoDest(action.Goto, bookmarks)
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
target, ok := pageIndex[dest.PageID]
|
target, ok := pageIndex[dest.PageID]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
destination, err := pdfDestination(*dest, pages[target].Box.H)
|
destination, err := pdfDestination(*dest, pages[target].Box.H)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
n.Link[page] = append(n.Link[page], pdfLink{Rect: rect, Target: &pdfTarget{Page: target, Destination: destination}})
|
return &pdfNavigationAction{Target: &pdfTarget{Page: target, Destination: destination}}, nil
|
||||||
n.exactLinks = true
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
if action.URI != nil && action.URI.URI != "" {
|
if action.URI != nil && action.URI.URI != "" {
|
||||||
n.Link[page] = append(n.Link[page], pdfLink{URI: resolveActionURI(*action.URI), Rect: rect})
|
return &pdfNavigationAction{URI: resolveActionURI(*action.URI)}, nil
|
||||||
}
|
}
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// addOutlines 保留目录层级及节点自身的导航动作,选页时移除无保留子项的失效跳转节点
|
// addOutlines 保留目录层级及节点自身的导航动作,选页时移除无保留子项的失效跳转节点
|
||||||
@@ -231,25 +199,15 @@ func (n *pdfNavigation) addOutlines(outlines []OutlineElem, level int, bookmarks
|
|||||||
entry := pdfOutline{Name: outline.Title, Level: level}
|
entry := pdfOutline{Name: outline.Title, Level: level}
|
||||||
onlyMissingTargets := len(outline.Actions) != 0
|
onlyMissingTargets := len(outline.Actions) != 0
|
||||||
for _, action := range outline.Actions {
|
for _, action := range outline.Actions {
|
||||||
if action.Goto != nil {
|
if action.Goto == nil {
|
||||||
dest := gotoDest(action.Goto, bookmarks)
|
|
||||||
if dest == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
page, ok := pageIndex[dest.PageID]
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
destination, err := pdfDestination(*dest, pages[page].Box.H)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
entry.Actions = append(entry.Actions, pdfOutlineAction{Target: &pdfTarget{Page: page, Destination: destination}})
|
|
||||||
} else {
|
|
||||||
onlyMissingTargets = false
|
onlyMissingTargets = false
|
||||||
if action.URI != nil && action.URI.URI != "" {
|
}
|
||||||
entry.Actions = append(entry.Actions, pdfOutlineAction{URI: resolveActionURI(*action.URI)})
|
value, err := pdfNavigationTarget(action, bookmarks, pageIndex, pages)
|
||||||
}
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if value != nil {
|
||||||
|
entry.Actions = append(entry.Actions, *value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
index := len(n.Outline)
|
index := len(n.Outline)
|
||||||
@@ -269,7 +227,7 @@ func (n *pdfNavigation) addOutlines(outlines []OutlineElem, level int, bookmarks
|
|||||||
// 入参: renderer PDF渲染器, page 页面索引
|
// 入参: renderer PDF渲染器, page 页面索引
|
||||||
func (n *pdfNavigation) apply(renderer *pdf.PDF, page int) {
|
func (n *pdfNavigation) apply(renderer *pdf.PDF, page int) {
|
||||||
for _, link := range n.Link[page] {
|
for _, link := range n.Link[page] {
|
||||||
renderer.AddLink(link.URI, link.Rect)
|
renderer.AddLink("", link.Rect)
|
||||||
}
|
}
|
||||||
if page == 0 {
|
if page == 0 {
|
||||||
for index, outline := range n.Outline {
|
for index, outline := range n.Outline {
|
||||||
@@ -283,15 +241,19 @@ func (n *pdfNavigation) apply(renderer *pdf.PDF, page int) {
|
|||||||
// 返回: error 目录结构或取消错误
|
// 返回: error 目录结构或取消错误
|
||||||
func (n *pdfNavigation) destinations(ctx context.Context, reader *pdfgo.Reader, pages []pdfgo.Reference, options *pdfgo.RewriteOptions) error {
|
func (n *pdfNavigation) destinations(ctx context.Context, reader *pdfgo.Reader, pages []pdfgo.Reference, options *pdfgo.RewriteOptions) error {
|
||||||
options.LinkDestinations = make(map[pdfgo.AnnotationLocation]pdfgo.Destination)
|
options.LinkDestinations = make(map[pdfgo.AnnotationLocation]pdfgo.Destination)
|
||||||
|
options.LinkActions = make(map[pdfgo.AnnotationLocation][]pdfgo.NavigationAction)
|
||||||
for page, links := range n.Link {
|
for page, links := range n.Link {
|
||||||
for index, link := range links {
|
for index, link := range links {
|
||||||
if err := ctx.Err(); err != nil {
|
if err := ctx.Err(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if link.Target != nil {
|
if len(link.Actions) == 1 && link.Actions[0].Target != nil {
|
||||||
dest := link.Target.Destination
|
target := link.Actions[0].Target
|
||||||
dest.Page = pages[link.Target.Page]
|
dest := target.Destination
|
||||||
|
dest.Page = pages[target.Page]
|
||||||
options.LinkDestinations[pdfgo.AnnotationLocation{Page: pages[page], Index: index}] = dest
|
options.LinkDestinations[pdfgo.AnnotationLocation{Page: pages[page], Index: index}] = dest
|
||||||
|
} else {
|
||||||
|
options.LinkActions[pdfgo.AnnotationLocation{Page: pages[page], Index: index}] = pdfNavigationValues(link.Actions, pages)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -313,17 +275,7 @@ func (n *pdfNavigation) destinations(ctx context.Context, reader *pdfgo.Reader,
|
|||||||
dest.Page = pages[target.Page]
|
dest.Page = pages[target.Page]
|
||||||
options.OutlineDestinations[item.Reference] = dest
|
options.OutlineDestinations[item.Reference] = dest
|
||||||
} else {
|
} else {
|
||||||
converted := make([]pdfgo.NavigationAction, 0, len(actions))
|
options.OutlineActions[item.Reference] = pdfNavigationValues(actions, pages)
|
||||||
for _, action := range actions {
|
|
||||||
value := pdfgo.NavigationAction{URI: action.URI}
|
|
||||||
if action.Target != nil {
|
|
||||||
dest := action.Target.Destination
|
|
||||||
dest.Page = pages[action.Target.Page]
|
|
||||||
value.Destination = &dest
|
|
||||||
}
|
|
||||||
converted = append(converted, value)
|
|
||||||
}
|
|
||||||
options.OutlineActions[item.Reference] = converted
|
|
||||||
}
|
}
|
||||||
options.OutlineTitles[item.Reference] = n.Outline[count].Name
|
options.OutlineTitles[item.Reference] = n.Outline[count].Name
|
||||||
count++
|
count++
|
||||||
|
|||||||
Reference in new issue
Block a user