Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schema for: CT_ImageData, CT_OleObject, CT_Shape and support inside (CT_Object). #334

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
79 changes: 79 additions & 0 deletions _examples/document/oleobject/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// oleObject using demo

// $ cd unioffice/_examples/document/oleobject
// $ go run main.go

// print:
//=============oleObject info===========
//Data path = C:\Users\ADMINI~1\AppData\Local\Temp\gooxml-docx131058703\zz524008729
//Wmf path = C:\Users\ADMINI~1\AppData\Local\Temp\gooxml-docx131058703\zz731151394
//===============end=============
//=============oleObject info===========
//Data path = C:\Users\ADMINI~1\AppData\Local\Temp\gooxml-docx131058703\zz304145587
//Wmf path = C:\Users\ADMINI~1\AppData\Local\Temp\gooxml-docx131058703\zz059105188
//===============end=============
//=============oleObject info===========
//Data path = C:\Users\ADMINI~1\AppData\Local\Temp\gooxml-docx131058703\zz462161757
//Wmf path = C:\Users\ADMINI~1\AppData\Local\Temp\gooxml-docx131058703\zz101524598
//===============end=============
//

// Comments:
// I developed a project can do convert the oleObject file to LaTeX data
// project path: https://github.com/zhexiao/mtef-go

// code Demo:
//import "github.com/zhexiao/mtef-go/eqn"
//latexData := eqn.Convert(path)

package main

import (
"fmt"
"github.com/unidoc/unioffice/document"
"log"
)

func main() {
filepath := "oleobject.docx"

doc, err := document.Open(filepath)
if err != nil {
log.Panicf("Open file failed, err=%s", err)
}

//save oleObject data rid/filepath relationship
oleObjectDataMap := make(map[string]string)
for _, oleData := range doc.OleObjectPaths {
path := oleData.Path()
rid := oleData.Rid()

oleObjectDataMap[rid] = path
}

//save oleObject wmf rid/filepath relationship
oleObjectWmfMap := make(map[string]string)
for _, oleData := range doc.OleObjectWmfPath {
path := oleData.Path()
rid := oleData.Rid()

oleObjectWmfMap[rid] = path
}

// read the oleObject file information from the word data
for _, paragraph := range doc.Paragraphs() {
for _, run := range paragraph.Runs() {
if run.OleObjects() != nil {
for _, ole := range run.OleObjects() {
dataRid := ole.OleRid()
wmfRid := ole.ImagedataRid()

fmt.Println("=============oleObject info===========")
fmt.Printf("Data path = %s \n", oleObjectDataMap[dataRid])
fmt.Printf("Wmf path = %s \n", oleObjectWmfMap[wmfRid])
fmt.Println("===============end=============")
}
}
}
}
}
Binary file added _examples/document/oleobject/oleobject.docx
Binary file not shown.
35 changes: 35 additions & 0 deletions document/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ type Document struct {
fontTable *wml.Fonts
endNotes *wml.Endnotes
footNotes *wml.Footnotes

OleObjectPaths []OleObjectPath
OleObjectWmfPath []OleObjectWmfPath
}

// New constructs an empty document that content can be added to.
Expand Down Expand Up @@ -858,16 +861,30 @@ func (d *Document) onNewRelationship(decMap *zippkg.DecodeMap, target, typ strin
if f == nil {
continue
}

if f.Name == target {
path, err := zippkg.ExtractToDiskTmp(f, d.TmpPath)
if err != nil {
return err
}

if strings.Contains(rel.TargetAttr, ".wmf") {
d.OleObjectWmfPath = append(d.OleObjectWmfPath, OleObjectWmfPath{
rid: rel.IdAttr,
path: path,
})

continue
}

img, err := common.ImageFromFile(path)
if err != nil {
return err
}

iref = common.MakeImageRef(img, &d.DocBase, d.docRels)
iref.SetRelID(rel.IdAttr)

d.Images = append(d.Images, iref)
files[i] = nil
}
Expand All @@ -880,6 +897,24 @@ func (d *Document) onNewRelationship(decMap *zippkg.DecodeMap, target, typ strin
rel.TargetAttr = rel.TargetAttr[0:len(rel.TargetAttr)-len(newExt)] + ext
}

case unioffice.OleObjectType:
for _, f := range files {
if f == nil {
continue
}

if f.Name == target {
path, err := zippkg.ExtractToDiskTmp(f, d.TmpPath)
if err != nil {
return err
}

d.OleObjectPaths = append(d.OleObjectPaths, OleObjectPath{
rid: rel.IdAttr,
path: path,
})
}
}
default:
unioffice.Log("unsupported relationship type: %s tgt: %s", typ, target)
}
Expand Down
56 changes: 56 additions & 0 deletions document/oleobject.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2017 FoxyUtils ehf. All rights reserved.
//
// Use of this source code is governed by the terms of the Affero GNU General
// Public License version 3.0 as published by the Free Software Foundation and
// appearing in the file LICENSE included in the packaging of this file. A
// commercial license can be purchased by contacting [email protected].
package document

import "github.com/unidoc/unioffice/schema/soo/wml"

type OleObjectPath struct {
rid string
path string
}

type OleObjectWmfPath struct {
rid string
path string
}

type OleObject struct {
oleobject *wml.CT_OleObject
shape *wml.CT_Shape
}

func (o OleObject) Shape() *wml.CT_Shape {
return o.shape
}

func (o OleObject) OleObject() *wml.CT_OleObject {
return o.oleobject
}

func (o OleObject) OleRid() string {
return *o.oleobject.IdAttr
}

func (o OleObject) ImagedataRid() string {
return *o.shape.Imagedata.IdAttr
}

func (o OleObjectPath) Rid() string {
return o.rid
}

func (o OleObjectPath) Path() string {
return o.path
}

func (o OleObjectWmfPath) Rid() string {
return o.rid
}

func (o OleObjectWmfPath) Path() string {
return o.path
}
35 changes: 35 additions & 0 deletions document/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,38 @@ func (r Run) AddDrawingInline(img common.ImageRef) (InlineDrawing, error) {

return inline, nil
}

func (r Run) DrawingInline() []InlineDrawing {
var ret []InlineDrawing
for _, ic := range r.x.EG_RunInnerContent {
if ic.Drawing == nil {
continue
}

for _, inl := range ic.Drawing.Inline {
ret = append(ret, InlineDrawing{r.d, inl})
}
}
return ret
}

func (r Run) OleObjects() []OleObject {
var ret []OleObject
for _, ic := range r.x.EG_RunInnerContent {
if ic.Object == nil {
continue
}

//读取对象
oleObject := ic.Object.OleObject
shape := ic.Object.Shape

if oleObject == nil || shape == nil {
continue
}

ret = append(ret, OleObject{oleobject: oleObject, shape: shape})
}

return ret
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
module github.com/unidoc/unioffice

go 1.13
23 changes: 23 additions & 0 deletions schema/soo/dml/CT_PositiveSize2D.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,26 @@ func (m *CT_PositiveSize2D) ValidateWithPath(path string) error {
}
return nil
}

//calculate image width and height
//convention: https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.drawing.wordprocessing.extent?view=openxml-2.8.1
type EmuSize struct {
Width string
Height string
}

const (
mm = 36000
cm = 360000
in = 914400
pt = 12700
pc = 152400
pi = 152400
)

//return width and height by using pt
func (m *CT_PositiveSize2D) Size() EmuSize {
return EmuSize{
Width: fmt.Sprintf("%spt", strconv.FormatInt(m.CxAttr/pt, 10)),
Height: fmt.Sprintf("%spt", strconv.FormatInt(m.CyAttr/pt, 10))}
}
95 changes: 95 additions & 0 deletions schema/soo/wml/CT_Imagedata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright 2017 FoxyUtils ehf. All rights reserved.
//
// Use of this source code is governed by the terms of the Affero GNU General
// Public License version 3.0 as published by the Free Software Foundation and
// appearing in the file LICENSE included in the packaging of this file. A
// commercial license can be purchased by contacting [email protected].
package wml

import (
"encoding/xml"
"fmt"
"github.com/unidoc/unioffice"
)

type CT_Imagedata struct {
//r:id
IdAttr *string

TitleAttr *string
}

func NewCT_Imagedata() *CT_Imagedata {
ret := &CT_Imagedata{}
return ret
}

func (m *CT_Imagedata) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
if m.IdAttr != nil {
start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: "r:id"},
Value: fmt.Sprintf("%v", *m.IdAttr)})
}

if m.TitleAttr != nil {
start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: "title"},
Value: fmt.Sprintf("%v", *m.TitleAttr)})
}

_ = e.EncodeToken(start)
_ = e.EncodeToken(xml.EndElement{Name: start.Name})
return nil
}

func (m *CT_Imagedata) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
// initialize to default
for _, attr := range start.Attr {
if attr.Name.Space == "http://schemas.openxmlformats.org/officeDocument/2006/relationships" && attr.Name.Local == "id" {
parsed, err := attr.Value, error(nil)
if err != nil {
return err
}
m.IdAttr = &parsed
continue
}

if attr.Name.Space == "urn:schemas-microsoft-com:office:office" && attr.Name.Local == "title" {
parsed, err := attr.Value, error(nil)
if err != nil {
return err
}
m.TitleAttr = &parsed
continue
}
}
lCT_Imagedata:
for {
tok, err := d.Token()
if err != nil {
return err
}
switch el := tok.(type) {
case xml.StartElement:
switch el.Name {
default:
unioffice.Log("skipping unsupported element on CT_Imagedata %v", el.Name)
if err := d.Skip(); err != nil {
return err
}
}
case xml.EndElement:
break lCT_Imagedata
case xml.CharData:
}
}
return nil
}

// Validate validates the CT_OleObject and its children
func (m *CT_Imagedata) Validate() error {
return m.ValidateWithPath("CT_Imagedata")
}

// ValidateWithPath validates the CT_OleObject and its children, prefixing error messages with path
func (m *CT_Imagedata) ValidateWithPath(path string) error {
return nil
}
Loading