Skip to content

Some hack to include SVG #798

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

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from

Conversation

pfernique
Copy link

shape.py and pkgwriter.py are particularly ugly but it works with Word for Office 365 (16.0)

@pfernique pfernique changed the base branch from master to develop March 18, 2020 16:33
@mrsanrise
Copy link

Have tried this(https://github.com/pfernique/python-docx/tree/feature/add_svg_picture) with word 2013.
"This image cannot currently be displayed". ((

@pfernique
Copy link
Author

Unfortunatly SVG works only on word >= 2016 (more details here)

@mrsanrise
Copy link

Unfortunatly SVG works only on word >= 2016 (more details here)

Thank you for the link. I think that is not very important which vector format to use.
I have converted all my images to the wmf (my images source format is odg).
After that i wrote my class Wmf(BaseImageHeader). It is similar to your example with svg (Thank you! :) ). I got acceptable result - word shows these images . Now i have a small issue with a scaling for some images (but in my case it is not critical).
Example function for the WMF support:

def _dimensions_from_stream(cls, stream):
        #https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wmf/828e1864-7fe7-42d8-ab0a-1de161b32f27
        stream.seek(0)
        META_PLACEABLE = stream.read()
        print("META_PLACEABLE")
        mkey = META_PLACEABLE[0:4]  # Key (4 bytes): Identification value that indicates the presence of a placeable metafile header. This value MUST be 0x9AC6CDD7.
        mhmw = META_PLACEABLE[4:6]  # HWmf (2 bytes): The resource handle to the metafile, when the metafile is in memory. When the metafile is on disk, this field MUST  contain 0x0000. This attribute of the metafile is specified in the Type field of the META_HEADER Record.
        mbbox = META_PLACEABLE[6:14] # BoundingBox (8 bytes): The rectangle in the playback context (or simply the destination rectangle), measured in logical units, for displaying the metafile. The size of a logical unit is specified by the Inch field.
        minch = META_PLACEABLE[14:16] # Inch (2 bytes): The number of logical units per inch used to represent the image. This value can be used to scale an image.
       

@ftomassetti ftomassetti mentioned this pull request Jul 30, 2020
@jayceslesar
Copy link

Merge at some point?

@tobytraylor
Copy link

Would like to see this merged.

@@ -81,7 +80,10 @@ def new_pic_inline(cls, shape_id, rId, filename, cx, cy):
specified by the argument values.
"""
pic_id = 0 # Word doesn't seem to use this, but does not omit it
pic = CT_Picture.new(pic_id, filename, rId, cx, cy)
if filename.endswith('.svg'):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I'm misreading this - this would only capture SVG is actually provided as a file (that has a filename go with it). There are many use cases where pictures are generated on the fly in in-memory buffers and therefore not provided as files. Any way to account for that?
(For example the PNG equivalent for matplotlib + docx would be something like:

import base64
import io

import docx
from docx.shared import Inches
import matplotlib.figure as figure

fig = figure.Figure()
ax = fig.subplots()
ax.plot([1, 2])
buf = io.BytesIO()
fig.savefig(buf, format='png')

document = docx.Document()
document.add_heading('Document Title', 0)
document.add_picture(buf, width=Inches(1.25))
document.save('demo.docx')

Copy link
Author

@pfernique pfernique Apr 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true that this seems strange but when dispatch is done, a filename image.svg is given for a stream (must be the same for png). So even if you provide in-memory buffers, it's good.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't realize that - thank you for calling it out. I looked a bit further (which I should have from the beginning):filename is generated here in image.py.

@rgoubet
Copy link

rgoubet commented Apr 22, 2021

Definitely looking forward to this. Word now supports SVG natively, i.e. images are imported as editable vector objects. It's converted to DrawingML in the docx file with a reference to the embedded SVG file:

<asvg:svgBlip xmlns:asvg="http://schemas.microsoft.com/office/drawing/2016/SVG/main" r:embed="rId5"/>

Then, in Word, it can be converted into an actual shape, and the SVG file is removed from the docx media to be replaced with the usual v:shape element.

@scanny scanny force-pushed the develop branch 5 times, most recently from 4762810 to 0a8e9c4 Compare May 1, 2024 19:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants