Converting Path to Points and Page Coordinates
📌 Overview
This knowledge base article describes how vector objects in Mako’s DOM are represented, and how to access them and retrieve information such as their dimensions or position on the page.
📗 Instructions
Vector paths in documents can be accessed by finding the path nodes on a page. Each path node will have the following structure:
Path Node (
IDOMPathNode)Geometry (
IDOMPathGeometry)Figures (
IDOMPathFigure)Segments (
IDOMPathSegment)
🪜 Steps
Find all path nodes on page: The following code finds all path nodes font anywhere within the content node.
CEDLVectIDOMNode pathNodes = content.findChildrenOfType(eDOMNodeType.eDOMPathNode);
If the input PDF contains XObject forms then you can use the IFormUnpackerTransform or use a custom transform implementing transformPath to reach the path nodes inside forms.
Work out the transform required to get the points in page coordinates: To convert the path points to points in page coordinates we need to use the
CTransformStatewhich tracks the graphics state up to the point the node transform is applied and post multiplying it with the geometry transform of the path node. Below is sample code which shows how this can be achieved.
CTransformState pathState = new CTransformState(path);
IDOMPathGeometry geometry = path.getPathData();
FMatrix toPage = geometry.getRenderTransform();
toPage.postMul(pathState.transform);
Establish the type of path segment: First get the path figures using
geometry.getFigures(). Once you have a path figure you can then get the smallest unit of the path geometry, the path segment (IDOMPathSegment) and then establish the type of path segment (IDOMArcSegment,IDOMPolyBezierSegment,IDOMPolyLineSegment,IPolyQuadraticBezierSegment).Transform points to page coordinates: Once the type of path segment has been established, the points can be retrieved and transformed to page coordinates. Below is sample code showing how to do this.
⌨️ Sample Code
CEDLVectIDOMNode pathNodes = content.findChildrenOfType(eDOMNodeType.eDOMPathNode);
for (uint pathcount = 1; pathcount < pathNodes.size(); pathcount++)
{
IDOMPathNode path = IDOMPathNode.fromRCObject(pathNodes[pathcount]);
// Work out the transform required to get the points in page coordinates
CTransformState pathstate = new CTransformState(path);
IDOMPathGeometry geometry = path.getPathData();
FMatrix toPage = geometry.getRenderTransform();
toPage.postMul(pathstate.transform);
CEDLVectIDOMPathFigure figures;
figures = geometry.getFigures();
IDOMPathFigure figure;
CEDLVectIDOMPathSegment segments;
IDOMPathSegment segment;
IDOMPolyLineSegment lineSegment;
IDOMPolyQuadraticBezierSegment quadSegment;
IDOMPolyBezierSegment bezSegment;
IDOMArcSegment arcSegment;
CEDLVectFPoint points = new CEDLVectFPoint();
for (uint i = 0; i < figures.size(); i++)
{
figure = figures[i];
FPoint start = figure.getStartPoint();
Console.WriteLine(String.Format("Before {0}|{1}", start.x, start.y));
// Apply the page transform to the start point
start = toPage.transform(start);
Console.WriteLine(String.Format("After {0}|{1}", start.x, start.y));
segments = figure.getSegments();
for (uint segmentcount = 0; segmentcount < segments.size(); segmentcount++)
{
segment = segments[segmentcount];
// Establish the type of segment we are dealing and then get the points of the segment.
lineSegment = IDOMPolyLineSegment.fromRCObject(segment.toRCObject());
quadSegment = IDOMPolyQuadraticBezierSegment.fromRCObject(segment.toRCObject());
bezSegment = IDOMPolyBezierSegment.fromRCObject(segment.toRCObject());
arcSegment = IDOMArcSegment.fromRCObject(segment.toRCObject());
if (lineSegment != null)
points = lineSegment.getPoints();
if (quadSegment != null)
points = quadSegment.getPoints();
if (bezSegment != null)
points = bezSegment.getPoints();
if (arcSegment != null)
points[0] = arcSegment.getPoint();
for (uint pointCount = 0; pointCount < points.size(); pointCount++)
{
FPoint point = points[pointCount];
Console.WriteLine(String.Format("Before {0}|{1}", point.x, point.y));
// Apply the page transform to the point
point = toPage.transform(point);
Console.WriteLine(String.Format("After {0}|{1}", point.x, point.y));
}
}
}
}
☑️ Conclusion
Converting paths to points and page coordinates in Mako involves accessing vector paths, determining their transformations, and applying these to convert path points accurately. By following the detailed steps and sample code provided, users can effectively manage and manipulate vector paths within PDFs. This capability is essential for precise graphic rendering and editing.
📚 Additional Resources
If you need additional help, see our API documentation for detailed information on class/method usage, or raise a support ticket via our customer portal.