mirror of
https://github.com/fumiama/go-docx.git
synced 2026-06-12 11:40:28 +08:00
add AddInlineDrawingFrom
This commit is contained in:
327
structdrawing.go
327
structdrawing.go
@@ -3,6 +3,12 @@ package docxlib
|
||||
import (
|
||||
"encoding/xml"
|
||||
"io"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
// A4_EMU_MAX_WIDTH is the max display width of an A4 paper
|
||||
A4_EMU_MAX_WIDTH = 5274310
|
||||
)
|
||||
|
||||
// Drawing element contains photos
|
||||
@@ -17,16 +23,31 @@ func (r *Drawing) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch tt := t.(type) {
|
||||
case xml.StartElement:
|
||||
switch tt.Name.Local {
|
||||
case "inline":
|
||||
r.Inline = new(WPInline)
|
||||
r.Inline.DistT = getAtt(tt.Attr, "distT")
|
||||
r.Inline.DistB = getAtt(tt.Attr, "distB")
|
||||
r.Inline.DistL = getAtt(tt.Attr, "distL")
|
||||
r.Inline.DistR = getAtt(tt.Attr, "distR")
|
||||
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)
|
||||
@@ -43,17 +64,18 @@ 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 string `xml:"distT,attr"`
|
||||
DistB string `xml:"distB,attr"`
|
||||
DistL string `xml:"distL,attr"`
|
||||
DistR string `xml:"distR,attr"`
|
||||
AnchorID string `xml:"wp14:anchorId,attr"`
|
||||
EditID string `xml:"wp14:editId,attr"`
|
||||
DistT int `xml:"distT,attr"`
|
||||
DistB int `xml:"distB,attr"`
|
||||
DistL int `xml:"distL,attr"`
|
||||
DistR int `xml:"distR,attr"`
|
||||
AnchorID string `xml:"wp14:anchorId,attr,omitempty"`
|
||||
EditID string `xml:"wp14:editId,attr,omitempty"`
|
||||
|
||||
Extent *WPExtent
|
||||
EffectExtent *WPEffectExtent
|
||||
DocPr *WPDocPr
|
||||
Graphic *AGraphic
|
||||
Extent *WPExtent
|
||||
EffectExtent *WPEffectExtent
|
||||
DocPr *WPDocPr
|
||||
CNvGraphicFramePr *WPCNvGraphicFramePr
|
||||
Graphic *AGraphic
|
||||
}
|
||||
|
||||
func (r *WPInline) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
@@ -62,26 +84,51 @@ func (r *WPInline) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch tt := t.(type) {
|
||||
case xml.StartElement:
|
||||
switch tt.Name.Local {
|
||||
case "extent":
|
||||
r.Extent = new(WPExtent)
|
||||
r.Extent.CX = getAtt(tt.Attr, "cx")
|
||||
r.Extent.CY = getAtt(tt.Attr, "cy")
|
||||
r.Extent.CX, err = strconv.Atoi(getAtt(tt.Attr, "cx"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Extent.CY, err = strconv.Atoi(getAtt(tt.Attr, "cy"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case "effectExtent":
|
||||
r.EffectExtent = new(WPEffectExtent)
|
||||
r.EffectExtent.L = getAtt(tt.Attr, "l")
|
||||
r.EffectExtent.T = getAtt(tt.Attr, "t")
|
||||
r.EffectExtent.R = getAtt(tt.Attr, "r")
|
||||
r.EffectExtent.B = getAtt(tt.Attr, "b")
|
||||
r.EffectExtent.L, err = strconv.Atoi(getAtt(tt.Attr, "l"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.EffectExtent.T, err = strconv.Atoi(getAtt(tt.Attr, "t"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.EffectExtent.R, err = strconv.Atoi(getAtt(tt.Attr, "r"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.EffectExtent.B, err = strconv.Atoi(getAtt(tt.Attr, "b"))
|
||||
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")
|
||||
case "cNvGraphicFramePr":
|
||||
var value WPCNvGraphicFramePr
|
||||
d.DecodeElement(&value, &start)
|
||||
r.CNvGraphicFramePr = &value
|
||||
case "graphic":
|
||||
var value AGraphic
|
||||
d.DecodeElement(&value, &start)
|
||||
@@ -97,19 +144,21 @@ func (r *WPInline) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
}
|
||||
|
||||
// WPExtent represents the extent of a drawing in a Word document.
|
||||
//
|
||||
// CX CY 's unit is English Metric Units, which is 1/914400 inch
|
||||
type WPExtent struct {
|
||||
XMLName xml.Name `xml:"wp:extent,omitempty"`
|
||||
CX string `xml:"cx,attr"`
|
||||
CY string `xml:"cy,attr"`
|
||||
CX int `xml:"cx,attr"`
|
||||
CY int `xml:"cy,attr"`
|
||||
}
|
||||
|
||||
// WPEffectExtent represents the effect extent of a drawing in a Word document.
|
||||
type WPEffectExtent struct {
|
||||
XMLName xml.Name `xml:"wp:effectExtent,omitempty"`
|
||||
L string `xml:"l,attr"`
|
||||
T string `xml:"t,attr"`
|
||||
R string `xml:"r,attr"`
|
||||
B string `xml:"b,attr"`
|
||||
L int `xml:"l,attr"`
|
||||
T int `xml:"t,attr"`
|
||||
R int `xml:"r,attr"`
|
||||
B int `xml:"b,attr"`
|
||||
}
|
||||
|
||||
// WPDocPr represents the document properties of a drawing in a Word document.
|
||||
@@ -121,6 +170,48 @@ type WPDocPr struct {
|
||||
Hidden string `xml:"hidden,attr,omitempty"`
|
||||
}
|
||||
|
||||
// WPCNvGraphicFramePr represents the non-visual properties of a graphic frame.
|
||||
type WPCNvGraphicFramePr struct {
|
||||
XMLName xml.Name `xml:"wp:cNvGraphicFramePr,omitempty"`
|
||||
Locks *AGraphicFrameLocks
|
||||
}
|
||||
|
||||
func (w *WPCNvGraphicFramePr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
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 "graphicFrameLocks":
|
||||
var value AGraphicFrameLocks
|
||||
d.DecodeElement(&value, &start)
|
||||
value.NoChangeAspect, err = strconv.Atoi(getAtt(tt.Attr, "noChangeAspect"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.Locks = &value
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AGraphicFrameLocks represents the locks applied to a graphic frame.
|
||||
type AGraphicFrameLocks struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/main graphicFrameLocks,omitempty"`
|
||||
NoChangeAspect int `xml:"noChangeAspect,attr"`
|
||||
}
|
||||
|
||||
// AGraphic represents a graphic in a Word document.
|
||||
type AGraphic struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/main graphic,omitempty"`
|
||||
@@ -133,6 +224,9 @@ func (a *AGraphic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch tt := t.(type) {
|
||||
case xml.StartElement:
|
||||
@@ -164,6 +258,9 @@ func (a *AGraphicData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch tt := t.(type) {
|
||||
case xml.StartElement:
|
||||
@@ -186,7 +283,7 @@ type PICPic struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/picture pic,omitempty"`
|
||||
NonVisualPicProperties *PICNonVisualPicProperties
|
||||
BlipFill *PICBlipFill
|
||||
// <pic:spPr> is unecessary
|
||||
SpPr *PICSpPr
|
||||
}
|
||||
|
||||
func (p *PICPic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
@@ -195,6 +292,9 @@ func (p *PICPic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch tt := t.(type) {
|
||||
case xml.StartElement:
|
||||
@@ -207,6 +307,10 @@ func (p *PICPic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
var value PICBlipFill
|
||||
d.DecodeElement(&value, &start)
|
||||
p.BlipFill = &value
|
||||
case "spPr":
|
||||
var value PICSpPr
|
||||
d.DecodeElement(&value, &start)
|
||||
p.SpPr = &value
|
||||
default:
|
||||
continue
|
||||
}
|
||||
@@ -228,6 +332,9 @@ func (p *PICNonVisualPicProperties) UnmarshalXML(d *xml.Decoder, start xml.Start
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch tt := t.(type) {
|
||||
case xml.StartElement:
|
||||
@@ -253,6 +360,7 @@ type PICNonVisualDrawingProperties struct {
|
||||
type PICBlipFill struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/picture blipFill,omitempty"`
|
||||
Blip ABlip
|
||||
Stretch AStretch
|
||||
}
|
||||
|
||||
func (p *PICBlipFill) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
@@ -261,12 +369,18 @@ func (p *PICBlipFill) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch tt := t.(type) {
|
||||
case xml.StartElement:
|
||||
switch tt.Name.Local {
|
||||
case "blip":
|
||||
p.Blip.Embed = getAtt(tt.Attr, "embed")
|
||||
p.Blip.Cstate = getAtt(tt.Attr, "cstate")
|
||||
case "stretch":
|
||||
d.DecodeElement(&p.Stretch, &start)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
@@ -280,4 +394,163 @@ func (p *PICBlipFill) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
|
||||
type ABlip struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/main blip,omitempty"`
|
||||
Embed string `xml:"r:embed,attr"`
|
||||
Cstate string `xml:"cstate,attr"`
|
||||
}
|
||||
|
||||
// AStretch ...
|
||||
type AStretch struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/main stretch,omitempty"`
|
||||
FillRect AFillRect
|
||||
}
|
||||
|
||||
// AFillRect ...
|
||||
type AFillRect struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/main fillRect,omitempty"`
|
||||
}
|
||||
|
||||
// PICSpPr is a struct representing the <pic:spPr> element in OpenXML,
|
||||
// which describes the shape properties for a picture.
|
||||
type PICSpPr struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/picture spPr,omitempty"`
|
||||
Xfrm AXfrm
|
||||
PrstGeom APrstGeom
|
||||
}
|
||||
|
||||
func (p *PICSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
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 "xfrm":
|
||||
d.DecodeElement(&p.Xfrm, &start)
|
||||
case "prstGeom":
|
||||
d.DecodeElement(&p.PrstGeom, &start)
|
||||
p.PrstGeom.Prst = getAtt(tt.Attr, "prst")
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AXfrm is a struct representing the <a:xfrm> element in OpenXML,
|
||||
// which describes the position and size of a shape.
|
||||
type AXfrm struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/main xfrm,omitempty"`
|
||||
Off AOff
|
||||
Ext AExt
|
||||
}
|
||||
|
||||
func (a *AXfrm) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
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 "off":
|
||||
a.Off.X, err = strconv.Atoi(getAtt(tt.Attr, "x"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.Off.Y, err = strconv.Atoi(getAtt(tt.Attr, "y"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case "ext":
|
||||
a.Ext.CX, err = strconv.Atoi(getAtt(tt.Attr, "cx"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.Ext.CY, err = strconv.Atoi(getAtt(tt.Attr, "cy"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AOff is a struct representing the <a:off> element in OpenXML,
|
||||
// which describes the offset of a shape from its original position.
|
||||
type AOff struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/main off,omitempty"`
|
||||
X int `xml:"x,attr"`
|
||||
Y int `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:"http://schemas.openxmlformats.org/drawingml/2006/main ext,omitempty"`
|
||||
CX int `xml:"cx,attr"`
|
||||
CY int `xml:"cy,attr"`
|
||||
}
|
||||
|
||||
// APrstGeom is a struct representing the <a:prstGeom> element in OpenXML,
|
||||
// which describes the preset shape geometry for a shape.
|
||||
type APrstGeom struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/main prstGeom,omitempty"`
|
||||
Prst string `xml:"prst,attr"`
|
||||
AvLst AAvLst
|
||||
}
|
||||
|
||||
// AAvLst is a struct representing the <a:avLst> element in OpenXML,
|
||||
// which describes the adjustments to the shape's preset geometry.
|
||||
type AAvLst struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/main avLst,omitempty"`
|
||||
RawXML string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
func (a *AAvLst) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
|
||||
var content []byte
|
||||
|
||||
if content, err = xml.Marshal(start); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
t, err := d.Token()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if end, ok := t.(xml.EndElement); ok && end == start.End() {
|
||||
break
|
||||
}
|
||||
|
||||
b, err := xml.Marshal(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
content = append(content, b...)
|
||||
}
|
||||
|
||||
a.RawXML = BytesToString(content)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user