Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h2>Backgrounds</h2> <p>By trying to consider the current transformation matrix you did one necessary thing but there is another datum to consider, the <em>current point</em> of the <em>current path</em>. Cf. the <a href="http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf" rel="nofollow">specification</a>:</p> <blockquote> <p>The path currently under construction is called the <em>current path</em>. In PDF (unlike PostScript), the current path is not part of the graphics state and is not saved and restored along with the other graphics state parameters. PDF paths shall be strictly internal objects with no explicit representation. After the current path has been painted, it shall become no longer defined; there is then no current path until a new one is begun with the <strong>m</strong> or <strong>re</strong> operator. </p> <p>The trailing endpoint of the segment most recently added to the current path is referred to as the <em>current point</em>. If the current path is empty, the current point shall be undefined. Most operators that add a segment to the current path start at the current point; if the current point is undefined, an error shall be generated.</p> <p>[...]</p> <p><em>x1 y1 x2 y2 x3 y3</em> <strong>c</strong> Append a cubic Bézier curve to the current path. The curve shall extend from the current point to the point (x3, y3), using (x1, y1) and (x2, y2) as the Bézier control points (see 8.5.2.2, "Cubic Bézier Curves"). The new current point shall be (x3, y3). </p> <p><em>(section 8.5.2</em> Path Construction Operators, <em>page 132)</em></p> </blockquote> <p>E.g. look at this</p> <pre><code>3 0 0 3 300 300 cm 10 0 m 10 5.52 5.52 10 0 10 c -5.52 10 -10 5.52 -10 0 c -10 -5.52 -5.52 -10 0 -10 c 5.52 -10 10 -5.52 10 0 c S </code></pre> <p>The <strong>m</strong>, <strong>c</strong>, and <strong>S</strong> operations draw a circle with diameter 10 around the origin:</p> <ul> <li><strong>10 0 m</strong> moves the <em>current point</em> to (10, 0);</li> <li><strong>10 5.52 5.52 10 0 10 c</strong> adds a quarter circle path element from the <em>current point</em> to (0, 10); now the current point is (0, 10);</li> <li><strong>-5.52 10 -10 5.52 -10 0 c</strong> adds a quarter circle path element from the <em>current point</em> to (-10, 0); now the current point is (-10, 0);</li> <li><strong>-10 -5.52 -5.52 -10 0 -10 c</strong> adds a quarter circle path element from the <em>current point</em> to (0, -10); now the current point is (0, -10);</li> <li><strong>5.52 -10 10 -5.52 10 0 c</strong> adds a quarter circle path element from the <em>current point</em> to (10, 0) finishing the circle; now the current point is (10, 0);</li> <li><strong>S</strong> draws along the path defined by the given path elements, i.e. the circle line.</li> </ul> <p>But due to the transformation matrix set before by <strong>3 0 0 3 300 300 cm</strong> which scales by a factor 3 and moves the scaled content to (300, 300), the circle actually is drawn around (300, 300) with a radius of 30.</p> <p>You get the final coordinates by multiplication, e.g. for the starting point of the first circle segment (10, 0):</p> <pre><code> ┌ 3 0 0 ┐ [ 10 0 1 ] x │ 0 3 0 │ = [ 330 300 1] └ 300 300 1 ┘ </code></pre> <p>so it's actually (330, 300).</p> <h2>Your task</h2> <p>Thus, to find the coordinates of a curve, you have to keep an eye on more than just the <strong>c</strong> operations. Instead you have to find where a path building process <em>is begun with the <strong>m</strong> or <strong>re</strong> operator</em> and keep track of the <em>current point</em>. When you get to the curve you are interested in, it starts at the then current point transformed and ends at the explicitly given curve end point transformed.</p> <p>Depending on your code the transformation matrix may either be provided by the framework or else you may also have to keep track of it.</p> <p>If you <em>intercept the "c" operation</em> by using some class derived from <code>PDFStreamEngine</code>, you can have that engine keep track of the current transformation matrix by registering the appropriate <code>OperatorProcessor</code>s.</p> <p>If, on the other hand, you work on the list returned by <code>PDFStreamParser.getTokens()</code>, you'll have to keep track of it manually.</p> <p>In either case the important operations are:</p> <blockquote> <p><em>—</em> <strong>q</strong> Save the current graphics state on the graphics state stack (see 8.4.2, "Graphics State Stack").</p> <p><em>—</em> <strong>Q</strong> Restore the graphics state by removing the most recently saved state from the stack and making it the current state (see 8.4.2, "Graphics State Stack"). </p> <p><em>a b c d e f</em> <strong>cm</strong> Modify the current transformation matrix (CTM) by concatenating the specified matrix (see 8.3.2, "Coordinate Spaces"). Although the operands specify a matrix, they shall be written as six separate numbers, not as an array. </p> <p><em>(section 8.4.4</em> Graphics State Operators, <em>page 127)</em></p> </blockquote>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload