PathGeometry
PathGeometry is the anchor-point outline of an IDML page item — nested GeometryPathType, PathPointArray, and PathPointType elements with Bézier handles, plus the PathOpen flag.
PathGeometry is how IDML records a page item's actual outline — anchor by anchor, with Bézier handles.
In short: PathGeometry is how IDML records the actual outline of a page
item. While GeometricBounds
gives only the bounding box, PathGeometry carries the real shape — anchor by
anchor, with Bézier control points — and real InDesign exports serialise it for
every shape, including plain rectangles. It nests four elements deep:
PathGeometry holds one or more GeometryPathType contours, each contour holds
a PathPointArray, and each array holds PathPointType points with an on-curve
anchor and two Bézier handles. A per-contour PathOpen flag decides whether each
loop is sealed. It lives inside the item's <Properties> element.
The element nesting
The outline is four elements deep, each with a single job:
<PathGeometry>
<GeometryPathType PathOpen="false">
<PathPointArray>
<PathPointType Anchor="0 0" LeftDirection="0 0" RightDirection="0 0"/>
<PathPointType Anchor="0 120" LeftDirection="0 120" RightDirection="0 120"/>
...
</PathPointArray>
</GeometryPathType>
</PathGeometry>PathGeometry— the container; holds one or more contours.GeometryPathType— one contour (one closed or open loop). More than one of these makes a compound path.PathPointArray— the ordered list of points for that contour.PathPointType— one point on the outline, with its on-curve anchor and two Bézier handles.
PathPointType: anchor and handles
Each point carries three coordinate pairs, every one written x y (note: this is
plain x y order, unlike GeometricBounds):
| Attribute · PathPointType | Type / values | Support | Notes |
|---|---|---|---|
| Anchor | "x y" (pt) | Supported | The on-curve point the outline passes through. |
| LeftDirection | "x y" (pt) | Supported | Incoming Bézier control handle. Equal to Anchor for a corner (no curve in). |
| RightDirection | "x y" (pt) | Supported | Outgoing Bézier control handle. Equal to Anchor for a corner (no curve out). |
The parser reads Anchor first; if it is missing the point is dropped. When
LeftDirection or RightDirection is absent, that handle defaults to the anchor
itself — i.e. a straight corner. A rectangle's four points therefore set all
three pairs equal per point, which the renderer reads as four straight corners.
All three pairs are in the item's inner coordinate space, the same space its
bounds use, placed onto the page by the item's
ItemTransform.
GeometryPathType: one contour, open or closed
A single GeometryPathType is one contour. Its one attribute decides whether the
loop is sealed:
| Attribute · GeometryPathType | Type / values | Support | Notes |
|---|---|---|---|
| PathOpen | boolean ("true" | "false") | Supported | true → the contour is left open (no closing segment back to the first anchor). false (default) → closed. Unparseable / missing is treated as false. |
When PathOpen is false (or absent), the renderer closes the contour by
joining the last anchor back to the first. When it is true, that closing
segment is omitted — the path is a stroke that starts and ends where its anchors
do. The parser lifts this flag onto a per-contour subpath_open record so the
renderer knows, contour by contour, whether to auto-close.
An open path
The shape below is a three-anchor contour with PathOpen="true" — a chevron.
Because the path is open, the renderer draws only the two segments between the
three anchors and does not add a third segment closing the "V" into a triangle.
A three-anchor open contour: PathOpen="true" leaves the loop unclosed.
Spreads/Spread_uspread.xml<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<idPkg:Spread xmlns:idPkg="http://ns.adobe.com/AdobeInDesign/idml/1.0/packaging" DOMVersion="20.0">
<Spread Self="uspread" PageCount="1" BindingLocation="0" ShowMasterItems="true" AllowPageShuffle="true" ItemTransform="1 0 0 1 0 0">
<Page Self="upage" Name="1" AppliedMaster="umaster" ItemTransform="1 0 0 1 0 0" GeometricBounds="0 0 841.89 595.276" MasterPageTransform="1 0 0 1 0 0"/>
<Polygon Self="uline" ItemTransform="1 0 0 1 150 250" FillColor="Swatch/None" StrokeColor="Color/Black" StrokeWeight="4">
<Properties>
<PathGeometry>
<GeometryPathType PathOpen="true">
<PathPointArray>
<PathPointType Anchor="0 0" LeftDirection="0 0" RightDirection="0 0"/>
<PathPointType Anchor="150 200" LeftDirection="150 200" RightDirection="150 200"/>
<PathPointType Anchor="300 0" LeftDirection="300 0" RightDirection="300 0"/>
</PathPointArray>
</GeometryPathType>
</PathGeometry>
</Properties>
</Polygon>
<TextFrame Self="uframe" ParentStory="ustory" PreviousTextFrame="n" NextTextFrame="n" ContentType="TextType" AppliedObjectStyle="ObjectStyle/$ID/[None]" Visible="true" Name="$ID/" ItemTransform="1 0 0 1 57.638 145.8237" FillColor="Swatch/None" StrokeColor="Swatch/None" StrokeWeight="0">
<Properties>
<PathGeometry>
<GeometryPathType PathOpen="false">
<PathPointArray>
<PathPointType Anchor="0 0" LeftDirection="0 0" RightDirection="0 0"/>
<PathPointType Anchor="0 400" LeftDirection="0 400" RightDirection="0 400"/>
<PathPointType Anchor="480 400" LeftDirection="480 400" RightDirection="480 400"/>
<PathPointType Anchor="480 0" LeftDirection="480 0" RightDirection="480 0"/>
</PathPointArray>
</GeometryPathType>
</PathGeometry>
</Properties>
</TextFrame>
</Spread>
</idPkg:Spread>
Flip PathOpen to false and the contour seals — the chevron would close into a
triangle. That single boolean is the whole difference between a line and a region.
Corner options render as rounded
IDML can ask for decorative corner treatments on a rectangle via CornerOption
(and the per-corner TopLeftCornerOption and siblings). The parser recognises
the full set of names, but the renderer collapses every non-square variant to a
plain rounded corner for now:
| Attribute · CornerOption values | Type / values | Support | Notes |
|---|---|---|---|
| None | enum | Supported | Square corner. The default. |
| Rounded | enum | Supported | Rounded corner — rendered as drawn. |
| Inverse / Inset / Bevel / Fancy | enum | Parsed, not yet rendered | Recognised and treated as a rounded corner; the bespoke decorative shapes are not yet generated. |
A second, related gap: decorative path and stroke treatments beyond the plain
outline are not generated either — the path you get is the anchor outline as
written, closed or open per PathOpen.
Frequently asked questions
How are PathGeometry elements nested?
The outline is four elements deep: PathGeometry holds one or more
GeometryPathType contours, each GeometryPathType holds a PathPointArray,
and each PathPointArray holds PathPointType points. Every PathPointType
carries an Anchor and two Bézier handles, LeftDirection and RightDirection.
What coordinate order do PathPointType anchors use?
Each of Anchor, LeftDirection, and RightDirection is written x y — plain
horizontal-then-vertical order, unlike
GeometricBounds, which puts Y
first. The parser reads Anchor first and drops the point if it is missing; an
absent handle defaults to the anchor itself, which the renderer reads as a
straight corner.
What does the PathOpen attribute do?
PathOpen is a per-contour boolean on GeometryPathType. When it is false (or
absent, the default) the renderer closes the contour by joining the last anchor
back to the first; when it is true the closing segment is omitted and the
contour stays an open stroke. The parser lifts the flag onto a per-contour
subpath_open record so each contour can be closed on its own terms.
GeometricBounds
GeometricBounds is the axis-aligned bounding box of an IDML page item, given as four points in the surprising y-before-x order y1 x1 y2 x2 (top, left, bottom, right).
Compound paths
A compound path packs multiple GeometryPathType contours into one IDML shape — how a hole gets punched with opposite winding, and why the parser records contour boundaries.