Create, read, edit, convert, repair, inspect, or export OpenDocument Graphics/Drawing files (.odg).
An .odg file is an OpenDocument ZIP package for vector drawings, diagrams, and LibreOffice Draw documents. Important package files:
mimetype - should be the first ZIP entry and stored uncompressed as application/vnd.oasis.opendocument.graphicscontent.xml - pages, shapes, connectors, text boxes, images, and drawing contentstyles.xml - drawing, text, page, and graphic stylesmeta.xml - document metadatasettings.xml - application settingsMETA-INF/manifest.xml - package manifestPictures/... - embedded raster or vector media| Task | Preferred approach |
|---|---|
| Create simple drawing/diagram | Generate ODG package XML directly |
| Create branded/repeated diagram | Start from an .odg template and edit XML |
| Use SVG-first | Only when portable vector output matters more than Draw editability |
| Extract visible text | Use scripts/extract_text.py or parse content.xml |
| Inspect shapes/geometry | Use scripts/extract_shapes.py |
| Convert ODG to PDF/SVG/PNG | LibreOffice headless export |
| Visual QA | Export to PDF/PNG/SVG and inspect the rendered output |
Before starting a real ODG task, check available tools:
which pandoc
Resolve the LibreOffice command as described in docs/soffice-resolver.md.
For raw package inspection:
unzip -l input.odg
python -m zipfile -e input.odg unpacked_odg
Drawing content is usually in content.xml. Inspect:
draw:page for pages/canvasesdraw:custom-shape, draw:rect, draw:ellipse, draw:path, draw:line, and draw:connector for vector objectsdraw:frame and draw:image for embedded mediatext:p and text:span for visible text labelsstyle:style references for fill, stroke, text, and positioning behaviorUse an XML parser with namespace support. Do not use regex for XML edits.
Bundled scripts for common inspection tasks:
python scripts/extract_text.py input.odg
python scripts/extract_shapes.py input.odg
python scripts/inspect_package.py input.odg
For the full script reference, see docs/script-reference.md.
An ODG drawing normally stores pages in content.xml under:
office:document-content
office:body
office:drawing
draw:page
Important drawing elements and attributes:
draw:page - one canvas/page; usually has draw:name and draw:master-page-namedraw:frame - positioned container for images, text boxes, objects, or pluginsdraw:text-box - text container, normally inside a frametext:p, text:span - visible labelsdraw:image - embedded or linked image via xlink:hrefdraw:rect, draw:ellipse, draw:line, draw:path, draw:connector, draw:custom-shape - vector objectssvg:x, svg:y, svg:width, svg:height - geometry for many positioned objectssvg:x1, svg:y1, svg:x2, svg:y2 - line/connector endpointsdraw:style-name, draw:text-style-name - style referencesStyles and page layouts are usually defined in styles.xml and automatic styles in content.xml. Connector routing and glue points can be fragile; if you move connected shapes, visually verify connector positions after export.
ODG is an XML package and can be generated directly. Do not default to SVG conversion when the deliverable should remain editable in LibreOffice Draw.
Choose the creation path by the user's goal:
| Scenario | Use |
|---|---|
| Editable Draw diagram with simple shapes/connectors/text | Direct ODG XML generation |
| Branded diagram, repeated canvas, institutional styling | Template-first ODG |
| Portable vector graphic where Draw editability is secondary | SVG-first fallback |
| Existing SVG/PDF/PNG source or explicit export request | LibreOffice conversion/export fallback |
Use this for simple diagrams and Draw-editable vector drawings:
python scripts/create_minimal_odg.py drawing.json output.odg
Keep direct generation deliberately small: pages, text boxes, rectangles, ellipses, lines, connectors, and images. Add custom paths, groups, glue points, and advanced styles only when a real task needs them.
Use this when visual identity, repeated layout, logos, or exact page size matter.
content.xml pages and styles.xml graphic/text/page styles.Pictures/ and update META-INF/manifest.xml.If an ODG deliverable is not strictly required, offer SVG or PDF as a more portable vector output. Use SVG-first only when portability matters more than Draw editability.
# Resolve SOFFICE as shown in Tool Checks.
"$SOFFICE" --headless --convert-to odg diagram.svg --outdir out
Treat conversion as lossy until QA proves otherwise. Check text, fonts, shapes, connectors, image embedding, and page size.
create_minimal_odg.py emits a designed default theme, not raw shapes:
standard graphic style — named standard because LibreOffice
treats it as the graphic-family default, so even a styleless shape inherits
a sensible look instead of LibreOffice's generic #729fcf blue.gr-shape, gr-text, gr-line, gr-image) parented to
standard; every generated shape carries an explicit draw:style-name.drawing-page style (dp-default) for the page background.Per-shape styling — spec items accept optional styling keys:
| Key | Applies to | Example |
|---|---|---|
fill |
rect/ellipse/text | "#F4C542" or "none" |
stroke |
any shape | "#7A5C00" or "none" |
stroke-width |
any shape | "0.05cm" |
text-color |
any shape with text | "#FFFFFF" |
font-size |
any shape with text | "20pt" |
corner-radius |
rect | "0.3cm" |
fill/stroke/stroke-width produce a per-shape automatic graphic style;
text-color/font-size produce paragraph + text automatic styles — a graphic
style's text-properties are ignored by LibreOffice Draw from an automatic
style in content.xml.
Whole-theme swap — write a curated styles.xml that redefines the same
named styles (standard, gr-shape, gr-text, gr-line, gr-image,
dp-default, master Default, layout Screen) and inject it:
from odg_common import embed_pictures, inject_styles_from_file
inject_styles_from_file("base.odg", "branded-styles.xml", "themed.odg")
Per-shape overrides live in content.xml, so a theme swap re-themes every
default-styled shape while the overrides survive. See
examples/diagram/ for a complete branded build.
create_minimal_odg.py accepts --theme NAME — a curated colour palette and
font pairing applied to the drawing's default shape/page styling. Five themes:
| Theme | Feel |
|---|---|
corporate-blue |
clean corporate blue |
warm-editorial |
cream background, terracotta serif |
high-contrast |
black on white, bold — accessibility, print |
slate-mono |
slate palette, monospaced shape text |
forest |
deep green, sans heading + serif body |
python scripts/create_minimal_odg.py diagram.json out.odg --theme forest
Without --theme the output is unchanged. A theme sets the page background,
shape fill, stroke/accent, shape text colour, and font. Per-shape styling keys
still override the theme. Themes name fonts as stacks with a Liberation
fallback so a themed drawing renders even where the first-choice font is absent.
For creation and editing scripts, see docs/script-reference.md. All scripts use the Python standard library and are invoked as:
python scripts/<script_name>.py [args]
cm for coordinates and dimensions.For layout-preserving edits:
content.xml and styles.xml with an XML library.Pictures/ and update META-INF/manifest.xml.mimetype first and uncompressed.Repack pattern:
cd unpacked_odg
zip -0 -X ../output.odg mimetype
zip -r -X ../output.odg . -x mimetype
Assume generated or edited ODG files have problems until proven otherwise. Draw rendering can change text fit, connector routing, image scaling, stroke widths, and page/canvas boundaries.
python scripts/extract_text.py output.odg > qa/text.txt
python scripts/extract_shapes.py output.odg > qa/shapes.json
Check labels, object counts, page names, expected shape types, and missing/duplicated text.
python scripts/inspect_package.py output.odg > qa/package.json
python scripts/validate_refs.py output.odg
Check that mimetype is first, required XML files exist, media targets exist, manifest entries are present, style references are not broken, and geometry has no zero-size or suspicious negative-size objects.
Rendering is a design step, not only a final check. Render an early draft, look at it, fix what is wrong, then continue — do not place every shape blind and render once at the end.
python scripts/render.py output.odg --outdir qa --contact-sheet # all pages in one image
python scripts/render.py output.odg --outdir qa --formats pdf,svg,png
The contact sheet composes every page into a single labelled grid image. Open the rendered output and actually look at it: check for missing images, shifted connectors, wrong fonts, clipped text, changed line widths, and page-size/canvas problems.
The final pass of a loop you should already be running while drawing:
cm, mm, in, or pt; preserve units unless intentionally changing layout.Part of the open-document-skills suite: