b38661f588
Python application / build (push) Has been cancelled
- Add\Rework UI - Add Split Table and Listing - Add Support Customazeble schems
56 lines
1.8 KiB
Python
56 lines
1.8 KiB
Python
"""Attach SVG as Word svgBlip alongside a PNG InlineShape (Office 2016+)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from docx.opc.constants import RELATIONSHIP_TYPE as RT
|
|
from docx.opc.part import Part
|
|
from docx.oxml import OxmlElement
|
|
from docx.oxml.ns import qn
|
|
from lxml import etree
|
|
|
|
SVG_CONTENT_TYPE = "image/svg+xml"
|
|
SVG_BLIP_URI = "{96DAC541-7B7A-43C6-8E14-B03AE682B59D}"
|
|
ASVG_NS = "http://schemas.microsoft.com/office/drawing/2016/SVG/main"
|
|
ASVG_SVG_BLIP = f"{{{ASVG_NS}}}svgBlip"
|
|
|
|
|
|
def attach_svg_blip(run, inline_shape, svg_path: str | Path) -> bool:
|
|
"""
|
|
After run.add_picture(png), add an SVG part and asvg:svgBlip on the PNG blip.
|
|
Word 2016+ uses the vector; older apps keep the PNG.
|
|
Returns True if the SVG was attached.
|
|
"""
|
|
path = Path(svg_path)
|
|
if not path.is_file() or path.stat().st_size <= 0:
|
|
return False
|
|
data = path.read_bytes()
|
|
head = data.lstrip()[:200].lower()
|
|
if not (head.startswith(b"<svg") or head.startswith(b"<?xml") or b"<svg" in head):
|
|
return False
|
|
|
|
part = run.part
|
|
package = part.package
|
|
partname = package.next_partname("/word/media/image%d.svg")
|
|
svg_part = Part(partname, SVG_CONTENT_TYPE, data, package)
|
|
r_id = part.relate_to(svg_part, RT.IMAGE)
|
|
|
|
blip = inline_shape._inline.graphic.graphicData.pic.blipFill.blip
|
|
ext_lst = blip.find(qn("a:extLst"))
|
|
if ext_lst is None:
|
|
ext_lst = OxmlElement("a:extLst")
|
|
blip.append(ext_lst)
|
|
|
|
# Drop any previous svgBlip extension with the same URI.
|
|
for ext in list(ext_lst.findall(qn("a:ext"))):
|
|
if ext.get("uri") == SVG_BLIP_URI:
|
|
ext_lst.remove(ext)
|
|
|
|
ext = OxmlElement("a:ext")
|
|
ext.set("uri", SVG_BLIP_URI)
|
|
svg_blip = etree.SubElement(ext, ASVG_SVG_BLIP)
|
|
svg_blip.set(qn("r:embed"), r_id)
|
|
ext_lst.append(ext)
|
|
return True
|