mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 17:27:08 +08:00
1 parent
2c96b4e490
commit
32ab7fe732
18 files changed
+83
-56
No files matched your search
+1
-1
@@ -1035,7 +1035,7 @@ func transformEditorObject(object GraphicObject, dx, dy, scale float64) (Graphic
|
|||||||
default:
|
default:
|
||||||
return GraphicObject{}, fmt.Errorf("unsupported object type %q", object.Type)
|
return GraphicObject{}, fmt.Errorf("unsupported object type %q", object.Type)
|
||||||
}
|
}
|
||||||
if clips := editorObjectClips(&object); scale != 1 && *clips != nil && (object.Type == "TextObject" || (*clips).TransFlag != nil && !*(*clips).TransFlag) {
|
if clips := editorObjectClips(&object); scale != 1 && *clips != nil && (object.Type == "TextObject" || !(*clips).usesObjectMatrix()) {
|
||||||
*clips = transformObjectClips(*clips, Matrix{a: scale, d: scale})
|
*clips = transformObjectClips(*clips, Matrix{a: scale, d: scale})
|
||||||
}
|
}
|
||||||
box, err := ParseBox(*boundary)
|
box, err := ParseBox(*boundary)
|
||||||
|
|||||||
@@ -470,10 +470,8 @@ func (e *Editor) compositeMembers(n *editorCompositeNode, reader *Reader, render
|
|||||||
boundary := n.parent.Multiply(TranslationMatrix(box.X, box.Y))
|
boundary := n.parent.Multiply(TranslationMatrix(box.X, box.Y))
|
||||||
matrix := boundary.Multiply(NewMatrix(c.CTM))
|
matrix := boundary.Multiply(NewMatrix(c.CTM))
|
||||||
clips, clipMatrix := c.Clips, matrix
|
clips, clipMatrix := c.Clips, matrix
|
||||||
if clips != nil && clips.TransFlag != nil && !*clips.TransFlag {
|
if !clips.usesObjectMatrix() {
|
||||||
copy := *clips
|
clipMatrix = boundary
|
||||||
copy.TransFlag = nil
|
|
||||||
clips, clipMatrix = ©, boundary
|
|
||||||
}
|
}
|
||||||
clip := n.clip
|
clip := n.clip
|
||||||
var err error
|
var err error
|
||||||
@@ -658,7 +656,7 @@ func (e *Editor) measureCompositeMembers(renderer *Renderer, nodes []*editorComp
|
|||||||
}
|
}
|
||||||
if transform && node.object.Type == "ImageObject" && bounds.Bounds.W > 0 && bounds.Bounds.H > 0 {
|
if transform && node.object.Type == "ImageObject" && bounds.Bounds.W > 0 && bounds.Bounds.H > 0 {
|
||||||
clips := node.object.ImageObject.Clips
|
clips := node.object.ImageObject.Clips
|
||||||
_, capability.CropImage = node.matrix(clips == nil || clips.TransFlag == nil || *clips.TransFlag).Invert()
|
_, capability.CropImage = node.matrix(clips.usesObjectMatrix()).Invert()
|
||||||
capability.FitImage = capability.CropImage && axisAlignedMatrix(NewMatrix(node.object.ImageObject.CTM))
|
capability.FitImage = capability.CropImage && axisAlignedMatrix(NewMatrix(node.object.ImageObject.CTM))
|
||||||
capability.ResetCrop = node.states[editorObjectID(node.object)].crop != nil
|
capability.ResetCrop = node.states[editorObjectID(node.object)].crop != nil
|
||||||
}
|
}
|
||||||
@@ -903,7 +901,7 @@ func transformCompositeOffsets(data []byte, matrix Matrix) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
object := cloneEditorData(n.object)
|
object := cloneEditorData(n.object)
|
||||||
object = compositeBoundary(object, Matrix{a: matrix.a, b: matrix.b, c: matrix.c, d: matrix.d}, false)
|
object = compositeBoundary(object, Matrix{a: matrix.a, b: matrix.b, c: matrix.c, d: matrix.d}, false)
|
||||||
if clips := editorObjectClips(&object); *clips != nil && (*clips).TransFlag != nil && !*(*clips).TransFlag {
|
if clips := editorObjectClips(&object); *clips != nil && !(*clips).usesObjectMatrix() {
|
||||||
*clips = transformObjectClips(*clips, TranslationMatrix(matrix.e, matrix.f))
|
*clips = transformObjectClips(*clips, TranslationMatrix(matrix.e, matrix.f))
|
||||||
}
|
}
|
||||||
fragment, err = editorXMLObject(n.data, n.node, n.object, object)
|
fragment, err = editorXMLObject(n.data, n.node, n.object, object)
|
||||||
@@ -943,7 +941,7 @@ func compositeBoundary(object GraphicObject, parent Matrix, inward bool) Graphic
|
|||||||
case "ImageObject":
|
case "ImageObject":
|
||||||
object.ImageObject.Boundary = editorBoxString(box)
|
object.ImageObject.Boundary = editorBoxString(box)
|
||||||
}
|
}
|
||||||
if clips := editorObjectClips(&object); *clips != nil && (*clips).TransFlag != nil && !*(*clips).TransFlag {
|
if clips := editorObjectClips(&object); *clips != nil && !(*clips).usesObjectMatrix() {
|
||||||
*clips = transformObjectClips(*clips, clipMatrix)
|
*clips = transformObjectClips(*clips, clipMatrix)
|
||||||
}
|
}
|
||||||
return object
|
return object
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ func (e *Editor) pasteCompositeSelection(selection *CompositeSelection, paste fu
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
clips := *editorObjectClips(©.object)
|
clips := *editorObjectClips(©.object)
|
||||||
matrix, ok := copy.matrix(clips == nil || clips.TransFlag == nil || *clips.TransFlag).Invert()
|
matrix, ok := copy.matrix(clips.usesObjectMatrix()).Invert()
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("composite clip transform is not invertible")
|
return fmt.Errorf("composite clip transform is not invertible")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ func (e *Editor) CropCompositeImage(page int, path ObjectPath, index int, box Bo
|
|||||||
return fmt.Errorf("crop does not intersect the image")
|
return fmt.Errorf("crop does not intersect the image")
|
||||||
}
|
}
|
||||||
clips := node.object.ImageObject.Clips
|
clips := node.object.ImageObject.Clips
|
||||||
inverse, _ := node.matrix(clips == nil || clips.TransFlag == nil || *clips.TransFlag).Invert()
|
inverse, _ := node.matrix(clips.usesObjectMatrix()).Invert()
|
||||||
shape, err := NewShape(ShapeRectangle, box)
|
shape, err := NewShape(ShapeRectangle, box)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -143,7 +143,7 @@ func (e *Editor) FitCompositeImage(page int, path ObjectPath, index int, mode st
|
|||||||
frame = TranslationMatrix(box.X, box.Y).Multiply(node.parent)
|
frame = TranslationMatrix(box.X, box.Y).Multiply(node.parent)
|
||||||
}
|
}
|
||||||
clips := object.ImageObject.Clips
|
clips := object.ImageObject.Clips
|
||||||
inverse, _ := node.matrix(clips == nil || clips.TransFlag == nil || *clips.TransFlag).Invert()
|
inverse, _ := node.matrix(clips.usesObjectMatrix()).Invert()
|
||||||
return appendCompositeClip(node, shape, inverse.Multiply(frame), true)
|
return appendCompositeClip(node, shape, inverse.Multiply(frame), true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -192,7 +192,7 @@ func appendCompositeClip(node *editorCompositeNode, shape PathObject, matrix Mat
|
|||||||
state.crop = &crop
|
state.crop = &crop
|
||||||
}
|
}
|
||||||
data, err := encodeOFDXML(func(x *ofdXML) {
|
data, err := encodeOFDXML(func(x *ofdXML) {
|
||||||
x.clips(&Clips{Clip: []Clip{clip}})
|
x.clips(&Clips{Clip: []Clip{clip}}, "")
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -209,8 +209,12 @@ func appendCompositeClip(node *editorCompositeNode, shape PathObject, matrix Mat
|
|||||||
patch = editorXMLContent(node.data, original, content)
|
patch = editorXMLContent(node.data, original, content)
|
||||||
} else {
|
} else {
|
||||||
data = editorXMLEncodedFragment(data, root)
|
data = editorXMLEncodedFragment(data, root)
|
||||||
content := append(data, node.data[node.node.open:node.node.close]...)
|
if actions := node.node.child("Actions"); actions != nil {
|
||||||
patch = editorXMLContent(node.data, node.node, content)
|
patch = editorXMLPatch{actions.end, actions.end, data}
|
||||||
|
} else {
|
||||||
|
content := append(data, node.data[node.node.open:node.node.close]...)
|
||||||
|
patch = editorXMLContent(node.data, node.node, content)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
updated, err := newEditorCompositeNode(editorPatchXML(node.data, []editorXMLPatch{patch}))
|
updated, err := newEditorCompositeNode(editorPatchXML(node.data, []editorXMLPatch{patch}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ func (e *Editor) eraseCompositeObjects(page int, path ObjectPath, indexes []int,
|
|||||||
return fmt.Errorf("composite member cannot be erased")
|
return fmt.Errorf("composite member cannot be erased")
|
||||||
}
|
}
|
||||||
clips := *editorObjectClips(&node.object)
|
clips := *editorObjectClips(&node.object)
|
||||||
inverse, ok := node.matrix(clips == nil || clips.TransFlag == nil || *clips.TransFlag).Invert()
|
inverse, ok := node.matrix(clips.usesObjectMatrix()).Invert()
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("composite clip transform is not invertible")
|
return fmt.Errorf("composite clip transform is not invertible")
|
||||||
}
|
}
|
||||||
@@ -212,7 +212,7 @@ func (e *Editor) eraseObjects(page int, ids []string, box Box, points []Point, r
|
|||||||
*clips = &Clips{}
|
*clips = &Clips{}
|
||||||
}
|
}
|
||||||
matrix := IdentityMatrix
|
matrix := IdentityMatrix
|
||||||
if (*clips).TransFlag == nil || *(*clips).TransFlag {
|
if (*clips).usesObjectMatrix() {
|
||||||
if object.Type == "ImageObject" && ctm == "" {
|
if object.Type == "ImageObject" && ctm == "" {
|
||||||
ctm = Matrix{a: frame.W, d: frame.H}.String()
|
ctm = Matrix{a: frame.W, d: frame.H}.String()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -261,6 +261,11 @@ func (x *ofdXML) referenceElement(name string, value any) {
|
|||||||
}
|
}
|
||||||
var attrs ofdAttrs
|
var attrs ofdAttrs
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
|
case *Dest:
|
||||||
|
if value == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
attrs.add("PageID", value.PageID)
|
||||||
case ShdColor:
|
case ShdColor:
|
||||||
attrs.add("ColorSpace", value.ColorSpace)
|
attrs.add("ColorSpace", value.ColorSpace)
|
||||||
case *ShdColor:
|
case *ShdColor:
|
||||||
|
|||||||
@@ -456,7 +456,7 @@ func transformEditorMatrix(object GraphicObject, matrix Matrix) GraphicObject {
|
|||||||
local := TranslationMatrix(-after.X, -after.Y).Multiply(matrix).Multiply(TranslationMatrix(before.X, before.Y))
|
local := TranslationMatrix(-after.X, -after.Y).Multiply(matrix).Multiply(TranslationMatrix(before.X, before.Y))
|
||||||
*ctm = local.Multiply(NewMatrix(*ctm)).String()
|
*ctm = local.Multiply(NewMatrix(*ctm)).String()
|
||||||
*boundary = editorBoxString(after)
|
*boundary = editorBoxString(after)
|
||||||
if clips := editorObjectClips(&object); *clips != nil && (*clips).TransFlag != nil && !*(*clips).TransFlag {
|
if clips := editorObjectClips(&object); *clips != nil && !(*clips).usesObjectMatrix() {
|
||||||
*clips = transformObjectClips(*clips, local)
|
*clips = transformObjectClips(*clips, local)
|
||||||
}
|
}
|
||||||
if !axisAlignedMatrix(matrix) && before.W > 0 && before.H > 0 {
|
if !axisAlignedMatrix(matrix) && before.W > 0 && before.H > 0 {
|
||||||
@@ -469,13 +469,12 @@ func transformEditorMatrix(object GraphicObject, matrix Matrix) GraphicObject {
|
|||||||
*clips = ©
|
*clips = ©
|
||||||
}
|
}
|
||||||
clipMatrix := local
|
clipMatrix := local
|
||||||
if (*clips).TransFlag == nil || *(*clips).TransFlag {
|
if (*clips).usesObjectMatrix() {
|
||||||
if inverse, ok := NewMatrix(*ctm).Invert(); ok {
|
if inverse, ok := NewMatrix(*ctm).Invert(); ok {
|
||||||
clipMatrix = inverse.Multiply(local)
|
clipMatrix = inverse.Multiply(local)
|
||||||
} else {
|
} else {
|
||||||
*clips = transformObjectClips(*clips, NewMatrix(*ctm))
|
*clips = transformObjectClips(*clips, NewMatrix(*ctm))
|
||||||
flag := false
|
(*clips).TransFlag = nil
|
||||||
(*clips).TransFlag = &flag
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fill, stroke := true, false
|
fill, stroke := true, false
|
||||||
@@ -526,17 +525,13 @@ func cropImageObject(image *ImageObject, box Box) error {
|
|||||||
image.Boundary = editorBoxString(box)
|
image.Boundary = editorBoxString(box)
|
||||||
image.Clips = nil
|
image.Clips = nil
|
||||||
if box != full {
|
if box != full {
|
||||||
inverse, ok := NewMatrix(image.CTM).Invert()
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("image transform is not invertible")
|
|
||||||
}
|
|
||||||
path, err := NewShape(ShapeRectangle, Box{W: box.W, H: box.H})
|
path, err := NewShape(ShapeRectangle, Box{W: box.W, H: box.H})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fill, stroke := true, false
|
fill, stroke := true, false
|
||||||
path.Fill, path.Stroke = &fill, &stroke
|
path.Fill, path.Stroke = &fill, &stroke
|
||||||
image.Clips = &Clips{Clip: []Clip{{Area: []ClipArea{{CTM: inverse.String(), Path: []PathObject{path}}}}}}
|
image.Clips = &Clips{Clip: []Clip{{Area: []ClipArea{{Path: []PathObject{path}}}}}}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -373,6 +373,19 @@ func editorXMLObject(data []byte, node *editorXML, before, after GraphicObject)
|
|||||||
// 入参: data 原文, node 原节点, oldXML 修改前编码, newXML 修改后编码
|
// 入参: data 原文, node 原节点, oldXML 修改前编码, newXML 修改后编码
|
||||||
// 返回: []byte 更新节点, error 错误信息
|
// 返回: []byte 更新节点, error 错误信息
|
||||||
func editorXMLMerge(data []byte, node *editorXML, oldXML, newXML []byte) ([]byte, error) {
|
func editorXMLMerge(data []byte, node *editorXML, oldXML, newXML []byte) ([]byte, error) {
|
||||||
|
legacyClip := node.name.Local == "Clips" && node.hasAttr("TransFlag")
|
||||||
|
if legacyClip {
|
||||||
|
var clips Clips
|
||||||
|
if err := xml.Unmarshal(data[node.start:node.end], &clips); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
clips.TransFlag = nil
|
||||||
|
var err error
|
||||||
|
oldXML, err = encodeOFDXML(func(x *ofdXML) { x.clips(&clips, "") })
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
oldNode, err := parseEditorXML(oldXML)
|
oldNode, err := parseEditorXML(oldXML)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -382,6 +395,9 @@ func editorXMLMerge(data []byte, node *editorXML, oldXML, newXML []byte) ([]byte
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
changes := make(map[string]string)
|
changes := make(map[string]string)
|
||||||
|
if legacyClip {
|
||||||
|
changes["TransFlag"] = ""
|
||||||
|
}
|
||||||
for _, attr := range append(oldNode.attrs, newNode.attrs...) {
|
for _, attr := range append(oldNode.attrs, newNode.attrs...) {
|
||||||
if attr.Name.Space == "" && (oldNode.attr(attr.Name.Local) != newNode.attr(attr.Name.Local) || oldNode.hasAttr(attr.Name.Local) != newNode.hasAttr(attr.Name.Local)) {
|
if attr.Name.Space == "" && (oldNode.attr(attr.Name.Local) != newNode.attr(attr.Name.Local) || oldNode.hasAttr(attr.Name.Local) != newNode.hasAttr(attr.Name.Local)) {
|
||||||
changes[attr.Name.Local] = newNode.attr(attr.Name.Local)
|
changes[attr.Name.Local] = newNode.attr(attr.Name.Local)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ type StrokeOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GeometryBackend 操作库自有路径,坐标以页面左上角为原点,不修改任何输入
|
// GeometryBackend 操作库自有路径,坐标以页面左上角为原点,不修改任何输入
|
||||||
// Clip返回nil表示不裁剪,空路径指针表示完全裁去,矩阵映射到页面坐标
|
// Clip返回nil表示不裁剪,空路径指针表示完全裁去,矩阵将裁剪坐标映射到页面坐标
|
||||||
type GeometryBackend interface {
|
type GeometryBackend interface {
|
||||||
Backend
|
Backend
|
||||||
Path(object PathObject) (GeometryPath, error)
|
Path(object PathObject) (GeometryPath, error)
|
||||||
|
|||||||
@@ -47,6 +47,12 @@ func (o GraphicObject) Actions() []Action {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// usesObjectMatrix 判断旧式扩展是否要求裁剪跟随对象变换,标准裁剪以外接矩形为基准
|
||||||
|
// 返回: bool 是否叠加对象CTM
|
||||||
|
func (clips *Clips) usesObjectMatrix() bool {
|
||||||
|
return clips != nil && clips.TransFlag != nil && *clips.TransFlag
|
||||||
|
}
|
||||||
|
|
||||||
// UnmarshalXML 解析路径并区分省略样式、显式实线与零线宽
|
// UnmarshalXML 解析路径并区分省略样式、显式实线与零线宽
|
||||||
// 入参: d XML解码器, start 起始节点
|
// 入参: d XML解码器, start 起始节点
|
||||||
// 返回: error 错误信息
|
// 返回: error 错误信息
|
||||||
|
|||||||
+2
-1
@@ -62,7 +62,8 @@ type GraphicObject struct {
|
|||||||
state editorCompositeState
|
state editorCompositeState
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clips 裁剪区域集合
|
// Clips 相对于对象外接矩形的裁剪集合
|
||||||
|
// TransFlag仅兼容旧式扩展,写入时折算为Area的CTM
|
||||||
type Clips struct {
|
type Clips struct {
|
||||||
TransFlag *bool `xml:"TransFlag,attr"`
|
TransFlag *bool `xml:"TransFlag,attr"`
|
||||||
Clip []Clip `xml:"Clip"`
|
Clip []Clip `xml:"Clip"`
|
||||||
|
|||||||
+1
-1
@@ -502,7 +502,7 @@ func (p *pdfImporter) clips(paths []pdfgo.Path, origin Box) (*Clips, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if clips == nil {
|
if clips == nil {
|
||||||
clips = &Clips{TransFlag: new(false), Clip: make([]Clip, 0, len(paths))}
|
clips = &Clips{Clip: make([]Clip, 0, len(paths))}
|
||||||
areas = make([]ClipArea, len(paths))
|
areas = make([]ClipArea, len(paths))
|
||||||
if origin.X != 0 || origin.Y != 0 {
|
if origin.X != 0 || origin.Y != 0 {
|
||||||
translation = pdfNumbers(1, 0, 0, 1, -origin.X, -origin.Y)
|
translation = pdfNumbers(1, 0, 0, 1, -origin.X, -origin.Y)
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ func pdfPageClip(object GraphicObject) *Clips {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
clips := *editorObjectClips(&object)
|
clips := *editorObjectClips(&object)
|
||||||
if clips == nil || clips.TransFlag == nil || *clips.TransFlag || len(clips.Clip) == 0 {
|
if clips == nil || clips.usesObjectMatrix() || len(clips.Clip) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
boundary, _ := editorGeometry(object)
|
boundary, _ := editorGeometry(object)
|
||||||
@@ -87,7 +87,7 @@ func pdfPageClip(object GraphicObject) *Clips {
|
|||||||
translation = pdfNumbers(1, 0, 0, 1, -box.X, -box.Y)
|
translation = pdfNumbers(1, 0, 0, 1, -box.X, -box.Y)
|
||||||
}
|
}
|
||||||
bytes := 0
|
bytes := 0
|
||||||
result := &Clips{TransFlag: clips.TransFlag, Clip: make([]Clip, len(clips.Clip))}
|
result := &Clips{Clip: make([]Clip, len(clips.Clip))}
|
||||||
for index, clip := range clips.Clip {
|
for index, clip := range clips.Clip {
|
||||||
if len(clip.Area) != 1 || clip.Area[0].CTM != translation {
|
if len(clip.Area) != 1 || clip.Area[0].CTM != translation {
|
||||||
return nil
|
return nil
|
||||||
@@ -113,7 +113,7 @@ func pdfMatchesPageClip(object GraphicObject, pageClip *Clips) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
clips := *editorObjectClips(&object)
|
clips := *editorObjectClips(&object)
|
||||||
if clips == nil || clips.TransFlag == nil || *clips.TransFlag || len(clips.Clip) != len(pageClip.Clip) {
|
if clips == nil || clips.usesObjectMatrix() || len(clips.Clip) != len(pageClip.Clip) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
boundary, _ := editorGeometry(object)
|
boundary, _ := editorGeometry(object)
|
||||||
|
|||||||
@@ -373,10 +373,7 @@ func (r *Renderer) objectGeometryClip(clips *Clips, boundary string, local Matri
|
|||||||
return clip, nil
|
return clip, nil
|
||||||
}
|
}
|
||||||
matrix, _ := renderObjectMatrix(boundary, local, state)
|
matrix, _ := renderObjectMatrix(boundary, local, state)
|
||||||
if clips.TransFlag != nil && !*clips.TransFlag {
|
if !clips.usesObjectMatrix() {
|
||||||
copy := *clips
|
|
||||||
copy.TransFlag = nil
|
|
||||||
clips = ©
|
|
||||||
box, _ := ParseBox(boundary)
|
box, _ := ParseBox(boundary)
|
||||||
matrix = TranslationMatrix(box.X, box.Y)
|
matrix = TranslationMatrix(box.X, box.Y)
|
||||||
if state.BoundaryInCTM && state.Parent != nil {
|
if state.BoundaryInCTM && state.Parent != nil {
|
||||||
|
|||||||
@@ -225,10 +225,8 @@ func (r *Renderer) walkComposite(object CompositeGraphicUnit, state RenderState,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
clips, clipMatrix := object.Clips, matrix
|
clips, clipMatrix := object.Clips, matrix
|
||||||
if clips != nil && clips.TransFlag != nil && !*clips.TransFlag {
|
if !clips.usesObjectMatrix() {
|
||||||
copy := *clips
|
clipMatrix = boundary
|
||||||
copy.TransFlag = nil
|
|
||||||
clips, clipMatrix = ©, boundary
|
|
||||||
}
|
}
|
||||||
if clips != nil {
|
if clips != nil {
|
||||||
geometry, err := r.Geometry()
|
geometry, err := r.Geometry()
|
||||||
|
|||||||
@@ -86,9 +86,9 @@ func (r *Renderer) buildObjectClipPath(clips *Clips, pageH float64, boundary str
|
|||||||
}
|
}
|
||||||
|
|
||||||
// buildClipPath 构建裁剪路径
|
// buildClipPath 构建裁剪路径
|
||||||
// 入参: clips 裁剪对象, pageH 页面高度, bx 边界X坐标, by 边界Y坐标, objectCTM 对象CTM
|
// 入参: clips 裁剪对象, pageH 页面高度, bx 边界X坐标, by 边界Y坐标, matrix 裁剪坐标到页面的变换
|
||||||
// 返回: *canvas.Path 路径对象
|
// 返回: *canvas.Path 路径对象
|
||||||
func (r *Renderer) buildClipPath(clips *Clips, pageH float64, bx, by float64, objectCTM Matrix) *canvas.Path {
|
func (r *Renderer) buildClipPath(clips *Clips, pageH float64, bx, by float64, matrix Matrix) *canvas.Path {
|
||||||
if clips == nil {
|
if clips == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -96,10 +96,7 @@ func (r *Renderer) buildClipPath(clips *Clips, pageH float64, bx, by float64, ob
|
|||||||
for _, clip := range clips.Clip {
|
for _, clip := range clips.Clip {
|
||||||
renderer := &clipRenderer{}
|
renderer := &clipRenderer{}
|
||||||
for _, area := range clip.Area {
|
for _, area := range clip.Area {
|
||||||
areaCTM := NewMatrix(area.CTM)
|
areaCTM := matrix.Multiply(NewMatrix(area.CTM))
|
||||||
if clips.TransFlag == nil || *clips.TransFlag {
|
|
||||||
areaCTM = objectCTM.Multiply(areaCTM)
|
|
||||||
}
|
|
||||||
for _, pathObj := range area.Path {
|
for _, pathObj := range area.Path {
|
||||||
renderer.add(r.buildClipAreaPath(pathObj, area.DrawParam, areaCTM, pageH, bx, by))
|
renderer.add(r.buildClipAreaPath(pathObj, area.DrawParam, areaCTM, pageH, bx, by))
|
||||||
if r.renderError != nil {
|
if r.renderError != nil {
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ func (CanvasBackend) Stroke(path GeometryPath, options StrokeOptions) (result Ge
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clip 解析对象裁剪并与父裁剪相交,保留未裁剪与完全裁去的区别
|
// Clip 解析对象裁剪并与父裁剪相交,保留未裁剪与完全裁去的区别
|
||||||
// 入参: r 渲染器, clips OFD裁剪, matrix 页面变换, parent 父裁剪
|
// 入参: r 渲染器, clips OFD裁剪, matrix 裁剪坐标到页面的变换, parent 父裁剪
|
||||||
// 返回: *GeometryPath 页面裁剪, error 无效父路径错误
|
// 返回: *GeometryPath 页面裁剪, error 无效父路径错误
|
||||||
func (CanvasBackend) Clip(r *Renderer, clips *Clips, matrix Matrix, parent *GeometryPath) (*GeometryPath, error) {
|
func (CanvasBackend) Clip(r *Renderer, clips *Clips, matrix Matrix, parent *GeometryPath) (*GeometryPath, error) {
|
||||||
p, err := geometryToCanvasPath(parent)
|
p, err := geometryToCanvasPath(parent)
|
||||||
|
|||||||
+20
-10
@@ -870,17 +870,22 @@ func (x *ofdXML) object(object GraphicObject, root bool) {
|
|||||||
x.start(object.Type, attrs)
|
x.start(object.Type, attrs)
|
||||||
x.actions(actions)
|
x.actions(actions)
|
||||||
if object.Type == "ImageObject" {
|
if object.Type == "ImageObject" {
|
||||||
x.clips(object.ImageObject.Clips)
|
ctm := object.ImageObject.CTM
|
||||||
|
if ctm == "" && object.ImageObject.Clips.usesObjectMatrix() {
|
||||||
|
box, _ := ParseBox(object.ImageObject.Boundary)
|
||||||
|
ctm = (Matrix{a: box.W, d: box.H}).String()
|
||||||
|
}
|
||||||
|
x.clips(object.ImageObject.Clips, ctm)
|
||||||
x.border(object.ImageObject.Border)
|
x.border(object.ImageObject.Border)
|
||||||
} else if object.Type == "CompositeObject" || object.Type == "CompositeGraphicUnit" {
|
} else if object.Type == "CompositeObject" || object.Type == "CompositeGraphicUnit" {
|
||||||
x.clips(object.CompositeGraphicUnit.Clips)
|
x.clips(object.CompositeGraphicUnit.Clips, object.CompositeGraphicUnit.CTM)
|
||||||
} else if object.Type == "PathObject" || object.Type == "Path" {
|
} else if object.Type == "PathObject" || object.Type == "Path" {
|
||||||
x.clips(object.PathObject.Clips)
|
x.clips(object.PathObject.Clips, object.PathObject.CTM)
|
||||||
x.color("StrokeColor", stroke)
|
x.color("StrokeColor", stroke)
|
||||||
x.color("FillColor", fill)
|
x.color("FillColor", fill)
|
||||||
x.text("AbbreviatedData", object.PathObject.AbbreviatedData)
|
x.text("AbbreviatedData", object.PathObject.AbbreviatedData)
|
||||||
} else if object.Type == "TextObject" || object.Type == "Text" {
|
} else if object.Type == "TextObject" || object.Type == "Text" {
|
||||||
x.clips(object.TextObject.Clips)
|
x.clips(object.TextObject.Clips, object.TextObject.CTM)
|
||||||
x.color("FillColor", fill)
|
x.color("FillColor", fill)
|
||||||
x.color("StrokeColor", stroke)
|
x.color("StrokeColor", stroke)
|
||||||
offset, index := 0, 0
|
offset, index := 0, 0
|
||||||
@@ -917,15 +922,17 @@ func (x *ofdXML) object(object GraphicObject, root bool) {
|
|||||||
x.end(object.Type)
|
x.end(object.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
// clips 写出对象裁剪,保留区域内的路径与文字
|
// clips 写出标准裁剪,将旧式随动裁剪折算为区域变换
|
||||||
// 入参: clips 裁剪集合,nil不输出节点
|
// 入参: clips 裁剪集合,nil不输出节点, ctm 对象变换矩阵
|
||||||
func (x *ofdXML) clips(clips *Clips) {
|
func (x *ofdXML) clips(clips *Clips, ctm string) {
|
||||||
if clips == nil || !x.checkContext() {
|
if clips == nil || !x.checkContext() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var attrs ofdAttrs
|
matrix := IdentityMatrix
|
||||||
attrs.flag("TransFlag", clips.TransFlag)
|
if clips.usesObjectMatrix() {
|
||||||
x.start("Clips", attrs)
|
matrix = NewMatrix(ctm)
|
||||||
|
}
|
||||||
|
x.start("Clips", nil)
|
||||||
for _, clip := range clips.Clip {
|
for _, clip := range clips.Clip {
|
||||||
if x.err != nil {
|
if x.err != nil {
|
||||||
return
|
return
|
||||||
@@ -936,6 +943,9 @@ func (x *ofdXML) clips(clips *Clips) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
var attrs ofdAttrs
|
var attrs ofdAttrs
|
||||||
|
if clips.usesObjectMatrix() {
|
||||||
|
area.CTM = matrix.Multiply(NewMatrix(area.CTM)).String()
|
||||||
|
}
|
||||||
attrs.add("CTM", area.CTM)
|
attrs.add("CTM", area.CTM)
|
||||||
attrs.add("DrawParam", area.DrawParam)
|
attrs.add("DrawParam", area.DrawParam)
|
||||||
for _, path := range area.Path {
|
for _, path := range area.Path {
|
||||||
|
|||||||
Reference in new issue
Block a user