mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 08:46:55 +08:00
This commit is contained in:
1 parent
cfbaa8a177
commit
2c06e5ff69
43 files changed
+3211
-397
No files matched your search
+75
-24
@@ -17,11 +17,13 @@ package ofdgo
|
||||
import "fmt"
|
||||
|
||||
// RenderState 保存对象继承的样式、父变换和页面坐标裁剪,所有引用只读
|
||||
// Clip为nil表示未裁剪,空路径表示完全裁去,单位为毫米
|
||||
// Clip为nil表示未提供裁剪,空路径表示完全裁去,单位为毫米
|
||||
// Hidden表示当前对象或其上层容器不可见,不改变源对象的Visible属性
|
||||
type RenderState struct {
|
||||
Defaults *DrawParam
|
||||
Parent *Matrix
|
||||
BoundaryInCTM bool
|
||||
Hidden bool
|
||||
Clip *GeometryPath
|
||||
}
|
||||
|
||||
@@ -42,6 +44,19 @@ type PageGroups interface {
|
||||
SkipObjects(count int)
|
||||
}
|
||||
|
||||
// PageComposites 可选地接收展开前的复合图元及矢量资源,不替代成员遍历
|
||||
// 状态包含当前图元到页面的完整变换,源对象及状态只读
|
||||
type PageComposites interface {
|
||||
VisitComposite(object *CompositeGraphicUnit, state RenderState) error
|
||||
}
|
||||
|
||||
// PageAnalysis 控制WalkPage和WalkObject对隐藏内容及裁剪的处理,不影响已构建场景的重放
|
||||
// 跳过裁剪时RenderState.Clip为空,源对象的裁剪定义不变,叶对象仍由访问器解释
|
||||
type PageAnalysis interface {
|
||||
IncludeHidden() bool
|
||||
SkipClips() bool
|
||||
}
|
||||
|
||||
// WalkPage 按模板、图层、注解和印章顺序访问页面,不依赖任何绘图库
|
||||
// 页面背景由调用方处理,文字裁剪可通过几何后端加载字体,图片由访问器按需加载
|
||||
// 入参: page 页面内容, visitor 页面访问器
|
||||
@@ -79,7 +94,7 @@ func (r *Renderer) WalkPage(page *PageContent, visitor PageVisitor) error {
|
||||
}
|
||||
if r.RenderAnnotations {
|
||||
for _, annotation := range r.Reader.Annots[page.ID] {
|
||||
if annotation.Visible != nil && !*annotation.Visible {
|
||||
if annotation.Visible != nil && !*annotation.Visible && !pageIncludesHidden(visitor) {
|
||||
continue
|
||||
}
|
||||
if err := r.walkAnnotation(annotation, visitor); err != nil {
|
||||
@@ -116,7 +131,7 @@ func (r *Renderer) walkAnnotation(annotation Annotation, visitor PageVisitor) er
|
||||
}
|
||||
box, _ := ParseBox(annotation.Appearance.Boundary)
|
||||
matrix := TranslationMatrix(box.X, box.Y)
|
||||
state := RenderState{Parent: &matrix, BoundaryInCTM: true}
|
||||
state := RenderState{Parent: &matrix, BoundaryInCTM: true, Hidden: annotation.Visible != nil && !*annotation.Visible}
|
||||
for i := range annotation.Appearance.Objects {
|
||||
if err := r.WalkObject(&annotation.Appearance.Objects[i], state, visitor); err != nil {
|
||||
return err
|
||||
@@ -175,11 +190,21 @@ func (r *Renderer) walkObject(object *GraphicObject, state RenderState, visitor
|
||||
return err
|
||||
}
|
||||
}
|
||||
if pageSkipsClips(visitor) {
|
||||
state.Clip = nil
|
||||
}
|
||||
if groups, ok := visitor.(PageGroups); ok && groups.BeginObject(object) {
|
||||
defer groups.EndObject()
|
||||
}
|
||||
switch object.Type {
|
||||
case "TextObject", "PathObject", "ImageObject":
|
||||
case "TextObject":
|
||||
state.Hidden = state.Hidden || object.TextObject.Visible != nil && !*object.TextObject.Visible
|
||||
return visitor.DrawObject(object, state)
|
||||
case "PathObject":
|
||||
state.Hidden = state.Hidden || object.PathObject.Visible != nil && !*object.PathObject.Visible
|
||||
return visitor.DrawObject(object, state)
|
||||
case "ImageObject":
|
||||
state.Hidden = state.Hidden || object.ImageObject.Visible != nil && !*object.ImageObject.Visible
|
||||
return visitor.DrawObject(object, state)
|
||||
case "CompositeGraphicUnit", "CompositeObject":
|
||||
return r.walkComposite(object.CompositeGraphicUnit, state, visitor, references)
|
||||
@@ -192,7 +217,8 @@ func (r *Renderer) walkObject(object *GraphicObject, state RenderState, visitor
|
||||
// 入参: object 复合图元, state 继承状态, visitor 页面访问器, references 当前资源引用链
|
||||
// 返回: error 几何或访问器错误
|
||||
func (r *Renderer) walkComposite(object CompositeGraphicUnit, state RenderState, visitor PageVisitor, references map[*CompositeGraphicUnit]bool) error {
|
||||
if object.Visible != nil && !*object.Visible {
|
||||
state.Hidden = state.Hidden || object.Visible != nil && !*object.Visible
|
||||
if state.Hidden && !pageIncludesHidden(visitor) {
|
||||
if groups, ok := visitor.(PageGroups); ok {
|
||||
count, ref, seen := len(object.Objects), object.ResourceID, make(map[*CompositeGraphicUnit]bool)
|
||||
for ref != "" {
|
||||
@@ -213,33 +239,42 @@ func (r *Renderer) walkComposite(object CompositeGraphicUnit, state RenderState,
|
||||
boundary = state.Parent.Multiply(boundary)
|
||||
}
|
||||
matrix := boundary.Multiply(NewMatrix(object.CTM))
|
||||
var err error
|
||||
if object.Boundary != "" {
|
||||
state.Clip, err = r.geometryExtentClip(box.W, box.H, boundary, state.Clip)
|
||||
if pageSkipsClips(visitor) {
|
||||
state.Clip = nil
|
||||
} else {
|
||||
var err error
|
||||
if object.Boundary != "" {
|
||||
state.Clip, err = r.geometryExtentClip(box.W, box.H, boundary, state.Clip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
state.Clip, err = r.compositeExtentClip(object, matrix, state.Clip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
state.Clip, err = r.compositeExtentClip(object, matrix, state.Clip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
clips, clipMatrix := object.Clips, matrix
|
||||
if !clips.usesObjectMatrix() {
|
||||
clipMatrix = boundary
|
||||
}
|
||||
if clips != nil {
|
||||
geometry, err := r.Geometry()
|
||||
if err != nil {
|
||||
return err
|
||||
clips, clipMatrix := object.Clips, matrix
|
||||
if !clips.usesObjectMatrix() {
|
||||
clipMatrix = boundary
|
||||
}
|
||||
state.Clip, err = geometry.Clip(r, clips, clipMatrix, state.Clip)
|
||||
if err != nil {
|
||||
return err
|
||||
if clips != nil {
|
||||
geometry, err := r.Geometry()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
state.Clip, err = geometry.Clip(r, clips, clipMatrix, state.Clip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
state.Defaults = r.drawParamDefaults(object.DrawParam, state.Defaults)
|
||||
state.Parent = &matrix
|
||||
if composites, ok := visitor.(PageComposites); ok {
|
||||
if err := composites.VisitComposite(&object, state); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if object.ResourceID != "" {
|
||||
if ref, _ := resourceValue(r.CompositeGraphicUnits, object.ResourceID); ref != nil {
|
||||
if references[ref] {
|
||||
@@ -269,6 +304,22 @@ func (r *Renderer) walkComposite(object CompositeGraphicUnit, state RenderState,
|
||||
return nil
|
||||
}
|
||||
|
||||
// pageIncludesHidden 查询访问器是否需要分析隐藏内容,不改变渲染器配置
|
||||
// 入参: visitor 页面访问器
|
||||
// 返回: bool 是否访问隐藏内容
|
||||
func pageIncludesHidden(visitor PageVisitor) bool {
|
||||
analysis, ok := visitor.(PageAnalysis)
|
||||
return ok && analysis.IncludeHidden()
|
||||
}
|
||||
|
||||
// pageSkipsClips 查询访问器是否只需资源和变换,不计算几何裁剪
|
||||
// 入参: visitor 页面访问器
|
||||
// 返回: bool 是否跳过裁剪
|
||||
func pageSkipsClips(visitor PageVisitor) bool {
|
||||
analysis, ok := visitor.(PageAnalysis)
|
||||
return ok && analysis.SkipClips()
|
||||
}
|
||||
|
||||
// compositeExtentClip 按矢量资源尺寸裁剪内容,资源裁剪随实例变换
|
||||
// 入参: object 矢量资源, matrix 资源到页面矩阵, parent 父裁剪
|
||||
// 返回: *GeometryPath 页面裁剪, error 尺寸或几何错误
|
||||
|
||||
Reference in new issue
Block a user