From 5091de63b86791898cdb3ba45d6d5350265387d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 3 Mar 2023 21:22:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=20wpg?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apidrawing.go | 4 +- structdrawing.go | 145 +++++++++++++++++++++++++++++++++++++++++------ structgroup.go | 115 +++++++++++++++++++++++++++++++++++++ structshape.go | 21 ++++++- 4 files changed, 265 insertions(+), 20 deletions(-) diff --git a/apidrawing.go b/apidrawing.go index 90015ee..b21c487 100644 --- a/apidrawing.go +++ b/apidrawing.go @@ -90,7 +90,7 @@ func (p *Paragraph) AddInlineDrawing(pic []byte) (*Run, error) { CY: h, }, }, - PrstGeom: APrstGeom{ + PrstGeom: &APrstGeom{ Prst: "rect", }, }, @@ -200,7 +200,7 @@ func (p *Paragraph) AddAnchorDrawing(pic []byte) (*Run, error) { CY: h, }, }, - PrstGeom: APrstGeom{ + PrstGeom: &APrstGeom{ Prst: "rect", }, }, diff --git a/structdrawing.go b/structdrawing.go index 30ec665..ef91586 100644 --- a/structdrawing.go +++ b/structdrawing.go @@ -730,7 +730,44 @@ type AAlphaModFix struct { // AStretch ... type AStretch struct { XMLName xml.Name `xml:"a:stretch,omitempty"` - FillRect AFillRect + FillRect *AFillRect +} + +// UnmarshalXML ... +func (s *AStretch) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + for { + t, err := d.Token() + if err == io.EOF { + break + } + if err != nil { + return err + } + + if tt, ok := t.(xml.StartElement); ok { + switch tt.Name.Local { + case "fillRect": + var value AFillRect + /*err = d.DecodeElement(&value, &tt) + if err != nil && !strings.HasPrefix(err.Error(), "expected") { + return err + }*/ + s.FillRect = &value + err = d.Skip() // skip unparsed innerxml + if err != nil { + return err + } + default: + err = d.Skip() // skip unsupported tags + if err != nil { + return err + } + continue + } + } + + } + return nil } // AFillRect ... @@ -743,7 +780,7 @@ type AFillRect struct { type PICSpPr struct { XMLName xml.Name `xml:"pic:spPr,omitempty"` Xfrm AXfrm - PrstGeom APrstGeom + PrstGeom *APrstGeom } // UnmarshalXML ... @@ -765,7 +802,12 @@ func (p *PICSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { return err } case "prstGeom": - p.PrstGeom.Prst = getAtt(tt.Attr, "prst") + var value APrstGeom + err = d.DecodeElement(&value, &tt) + if err != nil && !strings.HasPrefix(err.Error(), "expected") { + return err + } + p.PrstGeom = &value default: err = d.Skip() // skip unsupported tags if err != nil { @@ -785,8 +827,10 @@ type AXfrm struct { Rot int64 `xml:"rot,attr,omitempty"` FlipH int `xml:"flipH,attr,omitempty"` FlipV int `xml:"flipV,attr,omitempty"` - Off AOff - Ext AExt + Off AOff `xml:"a:off,omitempty"` + Ext AExt `xml:"a:ext,omitempty"` + ChOff *AOff `xml:"a:chOff,omitempty"` + ChExt *AExt `xml:"a:chExt,omitempty"` } // UnmarshalXML ... @@ -847,6 +891,34 @@ func (a *AXfrm) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) return err } } + case "chOff": + var value AOff + for _, v := range tt.Attr { + switch v.Name.Local { + case "x": + value.X, err = strconv.ParseInt(v.Value, 10, 64) + case "y": + value.Y, err = strconv.ParseInt(v.Value, 10, 64) + } + if err != nil { + return err + } + } + a.ChOff = &value + case "chExt": + var value AExt + for _, v := range tt.Attr { + switch v.Name.Local { + case "cx": + value.CX, err = strconv.ParseInt(v.Value, 10, 64) + case "cy": + value.CY, err = strconv.ParseInt(v.Value, 10, 64) + } + if err != nil { + return err + } + } + a.ChExt = &value default: err = d.Skip() // skip unsupported tags if err != nil { @@ -859,30 +931,69 @@ func (a *AXfrm) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) return nil } -// AOff is a struct representing the element in OpenXML, +// AOff is a struct representing the / element in OpenXML, // which describes the offset of a shape from its original position. type AOff struct { - XMLName xml.Name `xml:"a:off,omitempty"` - X int64 `xml:"x,attr"` - Y int64 `xml:"y,attr"` + X int64 `xml:"x,attr"` + Y int64 `xml:"y,attr"` } -// AExt is a struct representing the element in OpenXML, +// AExt is a struct representing the / element in OpenXML, // which describes the size of a shape. type AExt struct { - XMLName xml.Name `xml:"a:ext,omitempty"` - CX int64 `xml:"cx,attr"` - CY int64 `xml:"cy,attr"` + CX int64 `xml:"cx,attr"` + CY int64 `xml:"cy,attr"` } // APrstGeom is a struct representing the element in OpenXML, // which describes the preset shape geometry for a shape. type APrstGeom struct { - XMLName xml.Name `xml:"a:prstGeom,omitempty"` - Prst string `xml:"prst,attr"` - AvLst AAvLst + XMLName xml.Name `xml:"a:prstGeom,omitempty"` + Prst string `xml:"prst,attr"` + AvLst *struct{} `xml:"a:avLst,omitempty"` } +// UnmarshalXML ... +func (a *APrstGeom) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + for _, attr := range start.Attr { + switch attr.Name.Local { + case "prst": + a.Prst = attr.Value + default: + // ignore other attributes + } + } + + for { + t, err := d.Token() + if err == io.EOF { + break + } + if err != nil { + return err + } + + if tt, ok := t.(xml.StartElement); ok { + switch tt.Name.Local { + case "avLst": + a.AvLst = &struct{}{} + err = d.Skip() // skip innerxml + if err != nil { + return err + } + default: + err = d.Skip() // skip unsupported tags + if err != nil { + return err + } + continue + } + } + } + return nil +} + +/* // AAvLst is a struct representing the element in OpenXML, // which describes the adjustments to the shape's preset geometry. type AAvLst struct { @@ -922,7 +1033,7 @@ func (a *AAvLst) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error a.RawXML = BytesToString(content) return nil -} +}*/ // WPAnchor is an element that represents an anchored object in a Word document. // diff --git a/structgroup.go b/structgroup.go index 7d29af9..dcd17ed 100644 --- a/structgroup.go +++ b/structgroup.go @@ -19,3 +19,118 @@ */ package docx + +import ( + "encoding/xml" + "io" + "strings" +) + +// WordprocessingGroup represents a group of drawing objects or pictures +type WordprocessingGroup struct { + XMLName xml.Name `xml:"wpg:wgp,omitempty"` + CNvGrpSpPr *WPGcNvGrpSpPr + GroupShapeProperties *WPGGroupShapeProperties + Elems []interface{} +} + +// UnmarshalXML ... +func (w *WordprocessingGroup) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + for { + t, err := d.Token() + if err == io.EOF { + break + } + if err != nil { + return err + } + + if tt, ok := t.(xml.StartElement); ok { + switch tt.Name.Local { + case "cNvGrpSpPr": + var value WPGcNvGrpSpPr + err = d.DecodeElement(&value, &tt) + if err != nil && !strings.HasPrefix(err.Error(), "expected") { + return err + } + w.CNvGrpSpPr = &value + case "grpSpPr": + var value WPGGroupShapeProperties + err = d.DecodeElement(&value, &tt) + if err != nil && !strings.HasPrefix(err.Error(), "expected") { + return err + } + w.GroupShapeProperties = &value + case "pic": + var value Picture + err = d.DecodeElement(&value, &tt) + if err != nil && !strings.HasPrefix(err.Error(), "expected") { + return err + } + w.Elems = append(w.Elems, &value) + case "wsp": + var value WordprocessingShape + err = d.DecodeElement(&value, &tt) + if err != nil && !strings.HasPrefix(err.Error(), "expected") { + return err + } + w.Elems = append(w.Elems, &value) + default: + err = d.Skip() // skip unsupported tags + if err != nil { + return err + } + continue + } + } + } + return nil +} + +// WPGcNvGrpSpPr represents the non-visual properties of a group shape. +type WPGcNvGrpSpPr struct { + XMLName xml.Name `xml:"wpg:cNvGrpSpPr,omitempty"` + Locks *AGroupShapeLocks +} + +// UnmarshalXML ... +func (w *WPGcNvGrpSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + for { + t, err := d.Token() + if err == io.EOF { + break + } + if err != nil { + return err + } + + if tt, ok := t.(xml.StartElement); ok { + switch tt.Name.Local { + case "grpSpLocks": + w.Locks = new(AGroupShapeLocks) + err = d.Skip() // skip innerxml + if err != nil { + return err + } + default: + err = d.Skip() // skip unsupported tags + if err != nil { + return err + } + continue + } + } + } + return nil +} + +// AGroupShapeLocks represents the locks applied to a group shape. +type AGroupShapeLocks struct { + XMLName xml.Name `xml:"a:grpSpLocks,omitempty"` +} + +// WPGGroupShapeProperties represents the properties applied to a group shape. +type WPGGroupShapeProperties struct { + XMLName xml.Name `xml:"wpg:grpSpPr,omitempty"` + Xfrm *AXfrm +} diff --git a/structshape.go b/structshape.go index 8e4c7a5..1016e39 100644 --- a/structshape.go +++ b/structshape.go @@ -215,7 +215,26 @@ func (w *WPSCNvSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err e // ASPLocks represents the locks applied to a shape. type ASPLocks struct { - XMLName xml.Name `xml:"a:spLocks,omitempty"` + XMLName xml.Name `xml:"a:spLocks,omitempty"` + NoChangeArrowheads int `xml:"noChangeArrowheads,attr,omitempty"` +} + +// UnmarshalXML ... +func (l *ASPLocks) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) { + for _, attr := range start.Attr { + switch attr.Name.Local { + case "noChangeArrowheads": + l.NoChangeArrowheads, err = strconv.Atoi(attr.Value) + if err != nil { + return err + } + default: + // ignore other attributes + } + } + // Consume the end element + _, err = d.Token() + return err } // WPSSpPr is a container element that represents the visual properties of a shape.