1
0
mirror of https://github.com/fumiama/go-docx.git synced 2026-06-09 01:30:25 +08:00

add: anchor drawing & some attrs

This commit is contained in:
源文雨
2023-02-22 17:09:04 +08:00
parent d2666ec617
commit 9f0dbc43d1
8 changed files with 617 additions and 112 deletions

View File

@@ -20,6 +20,7 @@ const (
type Drawing struct {
XMLName xml.Name `xml:"w:drawing,omitempty"`
Inline *WPInline
Anchor *WPAnchor
}
func (r *Drawing) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
@@ -37,25 +38,10 @@ func (r *Drawing) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
switch tt.Name.Local {
case "inline":
r.Inline = new(WPInline)
r.Inline.DistT, err = strconv.Atoi(getAtt(tt.Attr, "distT"))
if err != nil {
return err
}
r.Inline.DistB, err = strconv.Atoi(getAtt(tt.Attr, "distB"))
if err != nil {
return err
}
r.Inline.DistL, err = strconv.Atoi(getAtt(tt.Attr, "distL"))
if err != nil {
return err
}
r.Inline.DistR, err = strconv.Atoi(getAtt(tt.Attr, "distR"))
if err != nil {
return err
}
// r.Inline.AnchorID = getAtt(tt.Attr, "anchorId")
// r.Inline.EditID = getAtt(tt.Attr, "editId")
d.DecodeElement(r.Inline, &start)
d.DecodeElement(r.Inline, &tt)
case "anchor":
r.Anchor = new(WPAnchor)
d.DecodeElement(r.Anchor, &tt)
default:
continue
}
@@ -69,10 +55,10 @@ func (r *Drawing) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
// WPInline wp:inline
type WPInline struct {
XMLName xml.Name `xml:"wp:inline,omitempty"`
DistT int `xml:"distT,attr"`
DistB int `xml:"distB,attr"`
DistL int `xml:"distL,attr"`
DistR int `xml:"distR,attr"`
DistT int64 `xml:"distT,attr"`
DistB int64 `xml:"distB,attr"`
DistL int64 `xml:"distL,attr"`
DistR int64 `xml:"distR,attr"`
// AnchorID string `xml:"wp14:anchorId,attr,omitempty"`
// EditID string `xml:"wp14:editId,attr,omitempty"`
@@ -83,7 +69,33 @@ type WPInline struct {
Graphic *AGraphic
}
func (r *WPInline) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
func (r *WPInline) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
for _, attr := range start.Attr {
switch attr.Name.Local {
case "distT":
r.DistT, err = strconv.ParseInt(attr.Value, 10, 64)
if err != nil {
return
}
case "distB":
r.DistB, err = strconv.ParseInt(attr.Value, 10, 64)
if err != nil {
return
}
case "distL":
r.DistL, err = strconv.ParseInt(attr.Value, 10, 64)
if err != nil {
return
}
case "distR":
r.DistR, err = strconv.ParseInt(attr.Value, 10, 64)
if err != nil {
return
}
default:
// ignore other attributes
}
}
for {
t, err := d.Token()
if err == io.EOF {
@@ -98,46 +110,42 @@ func (r *WPInline) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
switch tt.Name.Local {
case "extent":
r.Extent = new(WPExtent)
r.Extent.CX, err = strconv.Atoi(getAtt(tt.Attr, "cx"))
r.Extent.CX, err = strconv.ParseInt(getAtt(tt.Attr, "cx"), 10, 64)
if err != nil {
return err
}
r.Extent.CY, err = strconv.Atoi(getAtt(tt.Attr, "cy"))
r.Extent.CY, err = strconv.ParseInt(getAtt(tt.Attr, "cy"), 10, 64)
if err != nil {
return err
}
case "effectExtent":
r.EffectExtent = new(WPEffectExtent)
r.EffectExtent.L, err = strconv.Atoi(getAtt(tt.Attr, "l"))
r.EffectExtent.L, err = strconv.ParseInt(getAtt(tt.Attr, "l"), 10, 64)
if err != nil {
return err
}
r.EffectExtent.T, err = strconv.Atoi(getAtt(tt.Attr, "t"))
r.EffectExtent.T, err = strconv.ParseInt(getAtt(tt.Attr, "t"), 10, 64)
if err != nil {
return err
}
r.EffectExtent.R, err = strconv.Atoi(getAtt(tt.Attr, "r"))
r.EffectExtent.R, err = strconv.ParseInt(getAtt(tt.Attr, "r"), 10, 64)
if err != nil {
return err
}
r.EffectExtent.B, err = strconv.Atoi(getAtt(tt.Attr, "b"))
r.EffectExtent.B, err = strconv.ParseInt(getAtt(tt.Attr, "b"), 10, 64)
if err != nil {
return err
}
case "docPr":
r.DocPr = new(WPDocPr)
r.DocPr.ID = getAtt(tt.Attr, "id")
r.DocPr.Name = getAtt(tt.Attr, "name")
r.DocPr.Macro = getAtt(tt.Attr, "macro")
r.DocPr.Hidden = getAtt(tt.Attr, "hidden")
d.DecodeElement(r.DocPr, &tt)
case "cNvGraphicFramePr":
var value WPCNvGraphicFramePr
d.DecodeElement(&value, &start)
d.DecodeElement(&value, &tt)
r.CNvGraphicFramePr = &value
case "graphic":
var value AGraphic
d.DecodeElement(&value, &start)
value.XMLA = getAtt(tt.Attr, "a")
d.DecodeElement(&value, &tt)
r.Graphic = &value
default:
continue
@@ -154,26 +162,106 @@ func (r *WPInline) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
// CX CY 's unit is English Metric Units, which is 1/914400 inch
type WPExtent struct {
XMLName xml.Name `xml:"wp:extent,omitempty"`
CX int `xml:"cx,attr"`
CY int `xml:"cy,attr"`
CX int64 `xml:"cx,attr"`
CY int64 `xml:"cy,attr"`
}
func (r *WPExtent) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var err error
for _, attr := range start.Attr {
switch attr.Name.Local {
case "cx":
r.CX, err = strconv.ParseInt(attr.Value, 10, 64)
if err != nil {
return err
}
case "cy":
r.CY, err = strconv.ParseInt(attr.Value, 10, 64)
if err != nil {
return err
}
}
}
// Consume the end element
_, err = d.Token()
if err != nil {
return err
}
return nil
}
// WPEffectExtent represents the effect extent of a drawing in a Word document.
type WPEffectExtent struct {
XMLName xml.Name `xml:"wp:effectExtent,omitempty"`
L int `xml:"l,attr"`
T int `xml:"t,attr"`
R int `xml:"r,attr"`
B int `xml:"b,attr"`
L int64 `xml:"l,attr"`
T int64 `xml:"t,attr"`
R int64 `xml:"r,attr"`
B int64 `xml:"b,attr"`
}
func (r *WPEffectExtent) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var err error
for _, attr := range start.Attr {
switch attr.Name.Local {
case "l":
r.L, err = strconv.ParseInt(attr.Value, 10, 64)
if err != nil {
return err
}
case "t":
r.T, err = strconv.ParseInt(attr.Value, 10, 64)
if err != nil {
return err
}
case "r":
r.R, err = strconv.ParseInt(attr.Value, 10, 64)
if err != nil {
return err
}
case "b":
r.B, err = strconv.ParseInt(attr.Value, 10, 64)
if err != nil {
return err
}
}
}
// Consume the end element
_, err = d.Token()
if err != nil {
return err
}
return nil
}
// WPDocPr represents the document properties of a drawing in a Word document.
type WPDocPr struct {
XMLName xml.Name `xml:"wp:docPr,omitempty"`
ID string `xml:"id,attr"`
ID int `xml:"id,attr"`
Name string `xml:"name,attr,omitempty"`
Macro string `xml:"macro,attr,omitempty"`
Hidden string `xml:"hidden,attr,omitempty"`
}
func (r *WPDocPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for _, attr := range start.Attr {
switch attr.Name.Local {
case "id":
id, err := strconv.Atoi(attr.Value)
if err != nil {
return err
}
r.ID = id
case "name":
r.Name = attr.Value
default:
// ignore other attributes
}
}
// Consume the end element
_, err := d.Token()
if err != nil {
return err
}
return nil
}
// WPCNvGraphicFramePr represents the non-visual properties of a graphic frame.
@@ -197,7 +285,7 @@ func (w *WPCNvGraphicFramePr) UnmarshalXML(d *xml.Decoder, start xml.StartElemen
switch tt.Name.Local {
case "graphicFrameLocks":
var value AGraphicFrameLocks
d.DecodeElement(&value, &start)
d.DecodeElement(&value, &tt)
value.NoChangeAspect, err = strconv.Atoi(getAtt(tt.Attr, "noChangeAspect"))
if err != nil {
return err
@@ -226,6 +314,14 @@ type AGraphic struct {
}
func (a *AGraphic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for _, attr := range start.Attr {
switch attr.Name.Local {
case "a":
a.XMLA = attr.Value
default:
// ignore other attributes
}
}
for {
t, err := d.Token()
if err == io.EOF {
@@ -240,7 +336,7 @@ func (a *AGraphic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
switch tt.Name.Local {
case "graphicData":
var value AGraphicData
d.DecodeElement(&value, &start)
d.DecodeElement(&value, &tt)
value.URI = getAtt(tt.Attr, "uri")
a.GraphicData = &value
default:
@@ -274,7 +370,7 @@ func (a *AGraphicData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
switch tt.Name.Local {
case "pic":
var value PICPic
d.DecodeElement(&value, &start)
d.DecodeElement(&value, &tt)
value.XMLPIC = getAtt(tt.Attr, "pic")
a.Pic = &value
default:
@@ -310,15 +406,15 @@ func (p *PICPic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
switch tt.Name.Local {
case "nvPicPr":
var value PICNonVisualPicProperties
d.DecodeElement(&value, &start)
d.DecodeElement(&value, &tt)
p.NonVisualPicProperties = &value
case "blipFill":
var value PICBlipFill
d.DecodeElement(&value, &start)
d.DecodeElement(&value, &tt)
p.BlipFill = &value
case "spPr":
var value PICSpPr
d.DecodeElement(&value, &start)
d.DecodeElement(&value, &tt)
p.SpPr = &value
default:
continue
@@ -389,10 +485,9 @@ func (p *PICBlipFill) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
case xml.StartElement:
switch tt.Name.Local {
case "blip":
p.Blip.Embed = getAtt(tt.Attr, "embed")
p.Blip.Cstate = getAtt(tt.Attr, "cstate")
d.DecodeElement(&p.Blip, &tt)
case "stretch":
d.DecodeElement(&p.Stretch, &start)
d.DecodeElement(&p.Stretch, &tt)
default:
continue
}
@@ -404,9 +499,54 @@ func (p *PICBlipFill) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
// ABlip represents the blip of a picture in a Word document.
type ABlip struct {
XMLName xml.Name `xml:"a:blip,omitempty"`
Embed string `xml:"r:embed,attr"`
Cstate string `xml:"cstate,attr"`
XMLName xml.Name `xml:"a:blip,omitempty"`
Embed string `xml:"r:embed,attr"`
Cstate string `xml:"cstate,attr"`
AlphaModFix *AAlphaModFix
}
func (a *ABlip) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for _, attr := range start.Attr {
switch attr.Name.Local {
case "embed":
a.Embed = attr.Value
case "cstate":
a.Cstate = attr.Value
default:
// ignore other attributes
}
}
for {
t, err := d.Token()
if err == io.EOF {
break
}
if err != nil {
return err
}
switch tt := t.(type) {
case xml.StartElement:
switch tt.Name.Local {
case "alphaModFix":
var value AAlphaModFix
value.Amount, err = strconv.Atoi(getAtt(tt.Attr, "amt"))
if err != nil {
return err
}
a.AlphaModFix = &value
default:
continue
}
}
}
return nil
}
type AAlphaModFix struct {
XMLName xml.Name `xml:"a:alphaModFix,omitempty"`
Amount int `xml:"amt,attr"`
}
// AStretch ...
@@ -442,9 +582,9 @@ func (p *PICSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
case xml.StartElement:
switch tt.Name.Local {
case "xfrm":
d.DecodeElement(&p.Xfrm, &start)
d.DecodeElement(&p.Xfrm, &tt)
case "prstGeom":
d.DecodeElement(&p.PrstGeom, &start)
d.DecodeElement(&p.PrstGeom, &tt)
p.PrstGeom.Prst = getAtt(tt.Attr, "prst")
default:
continue
@@ -459,11 +599,35 @@ func (p *PICSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
// which describes the position and size of a shape.
type AXfrm struct {
XMLName xml.Name `xml:"a:xfrm,omitempty"`
Rot int64 `xml:"rot,attr,omitempty"`
FlipH int `xml:"flipH,attr,omitempty"`
FlipV int `xml:"flipV,attr,omitempty"`
Off AOff
Ext AExt
}
func (a *AXfrm) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
func (a *AXfrm) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
for _, attr := range start.Attr {
switch attr.Name.Local {
case "rot":
a.Rot, err = strconv.ParseInt(attr.Value, 10, 64)
if err != nil {
return err
}
case "flipH":
a.FlipH, err = strconv.Atoi(attr.Value)
if err != nil {
return err
}
case "flipV":
a.FlipV, err = strconv.Atoi(attr.Value)
if err != nil {
return err
}
default:
// ignore other attributes
}
}
for {
t, err := d.Token()
if err == io.EOF {
@@ -477,20 +641,20 @@ func (a *AXfrm) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
case xml.StartElement:
switch tt.Name.Local {
case "off":
a.Off.X, err = strconv.Atoi(getAtt(tt.Attr, "x"))
a.Off.X, err = strconv.ParseInt(getAtt(tt.Attr, "x"), 10, 64)
if err != nil {
return err
}
a.Off.Y, err = strconv.Atoi(getAtt(tt.Attr, "y"))
a.Off.Y, err = strconv.ParseInt(getAtt(tt.Attr, "y"), 10, 64)
if err != nil {
return err
}
case "ext":
a.Ext.CX, err = strconv.Atoi(getAtt(tt.Attr, "cx"))
a.Ext.CX, err = strconv.ParseInt(getAtt(tt.Attr, "cx"), 10, 64)
if err != nil {
return err
}
a.Ext.CY, err = strconv.Atoi(getAtt(tt.Attr, "cy"))
a.Ext.CY, err = strconv.ParseInt(getAtt(tt.Attr, "cy"), 10, 64)
if err != nil {
return err
}
@@ -507,16 +671,16 @@ func (a *AXfrm) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
// which describes the offset of a shape from its original position.
type AOff struct {
XMLName xml.Name `xml:"a:off,omitempty"`
X int `xml:"x,attr"`
Y int `xml:"y,attr"`
X int64 `xml:"x,attr"`
Y int64 `xml:"y,attr"`
}
// AExt is a struct representing the <a:ext> element in OpenXML,
// which describes the size of a shape.
type AExt struct {
XMLName xml.Name `xml:"a:ext,omitempty"`
CX int `xml:"cx,attr"`
CY int `xml:"cy,attr"`
CX int64 `xml:"cx,attr"`
CY int64 `xml:"cy,attr"`
}
// APrstGeom is a struct representing the <a:prstGeom> element in OpenXML,
@@ -566,3 +730,233 @@ func (a *AAvLst) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error
return nil
}
// WPAnchor wp:anchor
type WPAnchor struct {
XMLName xml.Name `xml:"wp:anchor,omitempty"`
DistT int64 `xml:"distT,attr"`
DistB int64 `xml:"distB,attr"`
DistL int64 `xml:"distL,attr"`
DistR int64 `xml:"distR,attr"`
SimplePos int `xml:"simplePos,attr"`
RelativeHeight int `xml:"relativeHeight,attr"`
BehindDoc int `xml:"behindDoc,attr"`
Locked int `xml:"locked,attr"`
LayoutInCell int `xml:"layoutInCell,attr"`
AllowOverlap int `xml:"allowOverlap,attr"`
SimplePosXY *WPSimplePos
PositionH *WPPositionH
PositionV *WPPositionV
Extent *WPExtent
EffectExtent *WPEffectExtent
WrapNone *struct{} `xml:"wp:wrapNone,omitempty"`
WrapSquare *WPWrapSquare
DocPr *WPDocPr
CNvGraphicFramePr *WPCNvGraphicFramePr
Graphic *AGraphic
}
func (r *WPAnchor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
for _, tt := range start.Attr {
switch tt.Name.Local {
case "distT":
r.DistT, err = strconv.ParseInt(tt.Value, 10, 64)
if err != nil {
return err
}
case "distB":
r.DistB, err = strconv.ParseInt(tt.Value, 10, 64)
if err != nil {
return err
}
case "distL":
r.DistL, err = strconv.ParseInt(tt.Value, 10, 64)
if err != nil {
return err
}
case "distR":
r.DistR, err = strconv.ParseInt(tt.Value, 10, 64)
if err != nil {
return err
}
case "simplePos":
r.SimplePos, err = strconv.Atoi(tt.Value)
if err != nil {
return err
}
case "relativeHeight":
r.RelativeHeight, err = strconv.Atoi(tt.Value)
if err != nil {
return err
}
case "behindDoc":
r.BehindDoc, err = strconv.Atoi(tt.Value)
if err != nil {
return err
}
case "locked":
r.Locked, err = strconv.Atoi(tt.Value)
if err != nil {
return err
}
case "layoutInCell":
r.LayoutInCell, err = strconv.Atoi(tt.Value)
if err != nil {
return err
}
case "allowOverlap":
r.AllowOverlap, err = strconv.Atoi(tt.Value)
if err != nil {
return err
}
}
}
for {
t, err := d.Token()
if err == io.EOF {
break
}
if err != nil {
return err
}
switch tt := t.(type) {
case xml.StartElement:
switch tt.Name.Local {
case "simplePos":
r.SimplePosXY = new(WPSimplePos)
r.SimplePosXY.X, err = strconv.ParseInt(getAtt(tt.Attr, "x"), 10, 64)
if err != nil {
return err
}
r.SimplePosXY.Y, err = strconv.ParseInt(getAtt(tt.Attr, "y"), 10, 64)
if err != nil {
return err
}
case "positionH":
r.PositionH = new(WPPositionH)
// r.PositionH.RelativeFrom = getAtt(tt.Attr, "relativeFrom")
d.DecodeElement(&r.PositionH, &tt)
case "positionV":
r.PositionV = new(WPPositionV)
// r.PositionV.RelativeFrom = getAtt(tt.Attr, "relativeFrom")
d.DecodeElement(&r.PositionV, &tt)
case "extent":
r.Extent = new(WPExtent)
d.DecodeElement(&r.Extent, &tt)
case "effectExtent":
r.EffectExtent = new(WPEffectExtent)
d.DecodeElement(&r.EffectExtent, &tt)
case "wrapNone":
r.WrapNone = &struct{}{}
case "wrapSquare":
r.WrapSquare = new(WPWrapSquare)
r.WrapSquare.WrapText = getAtt(tt.Attr, "wrapText")
case "docPr":
r.DocPr = new(WPDocPr)
d.DecodeElement(r.DocPr, &tt)
case "cNvGraphicFramePr":
r.CNvGraphicFramePr = new(WPCNvGraphicFramePr)
d.DecodeElement(r.CNvGraphicFramePr, &tt)
case "graphic":
r.Graphic = new(AGraphic)
d.DecodeElement(&r.Graphic, &tt)
default:
continue
}
}
}
return nil
}
// WPSimplePos represents the position of an object in a Word document.
type WPSimplePos struct {
XMLName xml.Name `xml:"wp:simplePos,omitempty"`
X int64 `xml:"x,attr"`
Y int64 `xml:"y,attr"`
}
// WPPositionH represents the horizontal position of an object in a Word document.
type WPPositionH struct {
XMLName xml.Name `xml:"wp:positionH,omitempty"`
RelativeFrom string `xml:"relativeFrom,attr"`
PosOffset int64 `xml:"wp:posOffset"`
}
func (r *WPPositionH) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for _, attr := range start.Attr {
switch attr.Name.Local {
case "relativeFrom":
r.RelativeFrom = attr.Value
}
}
for {
t, err := d.Token()
if err == io.EOF {
break
}
if err != nil {
return err
}
switch tt := t.(type) {
case xml.StartElement:
switch tt.Name.Local {
case "posOffset":
err = d.DecodeElement(&r.PosOffset, &tt)
if err != nil {
return err
}
default:
continue
}
}
}
return nil
}
// WPPositionV represents the vertical position of an object in a Word document.
type WPPositionV struct {
XMLName xml.Name `xml:"wp:positionV,omitempty"`
RelativeFrom string `xml:"relativeFrom,attr"`
PosOffset int64 `xml:"wp:posOffset"`
}
func (r *WPPositionV) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for _, attr := range start.Attr {
switch attr.Name.Local {
case "relativeFrom":
r.RelativeFrom = attr.Value
}
}
for {
t, err := d.Token()
if err == io.EOF {
break
}
if err != nil {
return err
}
switch tt := t.(type) {
case xml.StartElement:
switch tt.Name.Local {
case "posOffset":
err = d.DecodeElement(&r.PosOffset, &tt)
if err != nil {
return err
}
default:
continue
}
}
}
return nil
}
// WPWrapSquare represents the square wrapping of an object in a Word document.
type WPWrapSquare struct {
XMLName xml.Name `xml:"wp:wrapSquare,omitempty"`
WrapText string `xml:"wrapText,attr"`
}