Files
Igor20264 b38661f588
Python application / build (push) Has been cancelled
Update 0.4.0
- Add\Rework UI
- Add Split Table and Listing
- Add Support Customazeble schems
2026-09-04 22:28:39 +03:00

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