Created Date: 01 Apr, 2022 11:10
Last Modifed Date: 01 Apr, 2022 11:10


Overview

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)

Finding paths

The following code finds all path nodes font anywhere within the content node.

C#

CEDLVectIDOMNode pathNodes = content.findChildrenOfType(eDOMNodeType.eDOMPathNode);
C#

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.

To convert the path points to points in page coordinates we need to use the CTransformState which tracks the graphics state up to the point the node transform is applied and post mutilpying it with the geometry transform of the path node. Below is sample code which shows how this can be achieved.

C#

CEDLVectIDOMNode pathNodes = null;
pathNodes = content.findChildrenOfType(eDOMNodeType.eDOMPathNode);
IDOMPathNode path = null;
path = IDOMPathNode.fromRCObject(pathNode[0]);
FMatrix pathTransform = null;
CTransformState pathstate = new CTransformState(path);
IDOMPathGeometry geometry = null;
geometry = path.getPathData();
FMatrix toPage = null;
toPage = geometry.getRenderTransform();
toPage.postMul(pathstate.transform);
C#

To get the points of a path node you first need to get the path geometry (IDOMPathGeometry)  and then the figures (IDOMPathFigure). Once you have the 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).

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.

C#

CEDLVectIDOMNode pathNodes = null;
pathNodes = content.findChildrenOfType(eDOMNodeType.eDOMPathNode);
for (uint pathcount = 1; pathcount < pathNodes.size(); pathcount++)
{
	IDOMPathNode path = null;
	path = IDOMPathNode.fromRCObject(pathNode[pathcount]);
	FMatrix pathTransform = null;

	// Work out the transform required to get the points in page coordinates
	CTransformState pathstate = new CTransformState(path);
	IDOMPathGeometry geometry = null;
	geometry = path.getPathData();
	FMatrix toPage = null;
	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));
             }
         }
     }
}
C#