Is it possible to draw strokes for a path after restoring the graphics state in PDF? - pdf

I'm drawing lines in PDF that I want to scale in a ratio other than 1:1.
The problem is that i get strokes that looks like they been drawn with a caligraphic pen.
Is it possible somehow in PDF to resize the path, restore the graphics state and then draw the stroke of the previous path.
This is how I get caligraphical line strokes in PDF:
5 w // width of stroke
q // saves the current graphics state
0 1 0 0.2 0 0 cm // transformation matrix scaling with height reduced to 20%
0 10 m // Start of line
10 10 l // line to
20 100 l
30 100 l
40 10 l
S // draws stroke
Q // Restores graphics state
In HTML5 canvas it's possible to draw stroke after restoring the graphics state so that the path is drawn by a equally width line.
http://www.html5canvastutorials.com/advanced/html5-canvas-ovals/
In PDF putting S after Q doesn't work.
Is there some way to get the same result in PDF where only the line path gets scaled, not the stroke itself?

Have a look at Figure 9 - Graphics Objects - on page 113 of the PDF specification ISO 32000-1:2008. It illustrates that as soon as you have started constructing a path, the only allowed operators are those for path construction, path clipping, and path painting. Q being a special graphics state operator is only allowed after a path painting operator, e.g. your S.
This also is stated in the example right below the graphic:
The path construction operators m and re signal the beginning
of a path object. Inside the path object, additional path construction
operators are permitted, as are the clipping path operators W and
W*, but not general graphics state operators such as w or J.
A path-painting operator, such as S or f, ends the path object
and returns to the page description level.
Thus in response to "Is there some way to get the same result in PDF where only the line path get's scaled, not the stroke itself?": No, you have to explicitly select a smaller stroke width to compensate the different scale introduced by the transmation matrix.

Related

How to get a uniform line width in PDF regardless of the device space aspect ratio?

The width of a line in PDF is defined in terms of distances in the user space. In my use case, the aspect ratio of the device space (e.g. 4:3) is different from the aspect ratio of the user space (e.g. 1:1), which causes the line widths in the device space to be different in vertical and horizontal directions.
For example, in this picture the horizontal and vertical lines should be of the same width, but they're not:
I would like to perform scaling that only results in line width uniformity and does not affect anything else.
I asked a similar question regarding PostScript here: How to ensure line widths are the same vertically and horizontally in PostScript?. A solution based in part on the answer to this question works for PostScript, but does not work in PDF after what seems to be an almost one-to-one translation.
I tried changing the stroke command S to q 1 0 0 1.5 0 0 cm S Q h, where q saves the graphics state, 1 0 0 1.5 0 0 cm scales the current transformation matrix, Q restores the graphics state, and h closes the current subpath. However, in addition to correctly scaling the line widths, this also scales the y-coordinates of the line endpoints by 1.5.
This is what I need to get:
But with q 1 0 0 1.5 0 0 cm S Q h, I get this instead:
How to make the line width uniform in the device space in PDF without affecting anything else?

Calculating the exact positions of(Td, TD, Tm, cm, T*) content stream in pdf?

Getting or calculating the exact positions of(Td, TD, Tm, cm, T*) content stream in pdf?
As a human I am able to calculate(whether it is replacing last Td or adding to last Td or multiplication with fontsize) the positions of tags in pdf content stream by comparing , where the glyphs are located in pdf and content stream position values. But I am unable to calculate perfect positions of glyph's programatically . Please see the screen short.
In above image left side box is pdf ui glyphs and right side box contains the related content stream. In content stream I highlighted two Td positions.
In first circle
3.321 -6.475999832 Td
The Td positions should add to the last Td positions. Assume x1, y1.
Current_x_pos = x1+3.321
Curent_y_pos = y1-6.475999832
then we can get the exact position of glyph "t".
In second highlighted circle the new Td positions (231.544 366.377990 Td) are completely replaced like
Current_x_pos = 231.544
Curent_y_pos = 366.377990
Along with that some times the parent tag is Tm at that case the formula might be like this
Current_x_pos = x1+(tdx1*font_size)
Curent_y_pos = y1+(tdy1*font_size)
When we need to multiply like above, and some times addition. Programatically how can I know this. To parse exact positions?(new screen short added for multiplication)
Any help ?
Thanks.
When we need to multiply like above, and some times addition. Programatically how can I know this. To parse exact positions?
It's quite simple, for a Td operation you always multiply, see the specification ISO 32000-1 (similarly in ISO 32000-2):
For a freshly initialized (i.e. identity) text line matrix Tlm this matrix multiplication looks like replacing its bottom row with tx ty 1.
For a text line matrix Tlm with only changes in the bottom row against an identity this matrix multiplication looks like an addition to the bottom row, e.g. x y 1 becomes x+tx y+ty 1.
For a text line matrix Tlm like in your second example
a 0 0
0 a 0
x y 1
this matrix multiplication looks like a multiplication with a followed by an addition to the bottom row, i.e. x y 1 becomes x+a·tx y+a·ty 1. If the font size parameter of the preceding Tf operation was 1, then a would effectively be the resultant font size giving rise to your assumption the font size is part of the formula.
In general, for an arbitrary, non-degenerate text line matrix Tlm
a b 0
c d 0
x y 1
this matrix multiplication looks even more complex, x y 1 becomes x+a·tx+c·ty y+b·tx+d·ty 1.
Thus, concerning your question
Programatically how can I know this. To parse exact positions?
your program should simply always use matrix multiplication and ignore what it looks like on the level of the separate coordinates.
What makes the second circled instruction look like a mere replacement, is that the prior text line matrix is the identity matrix. This is not due to the restore-state operation as assumed by François, though, but more simply to the start of text object operation BT:
As the text matrix and the text line matrix are reset at the start of a text object and the graphics state cannot be saved or restored in a text object, the save and restore graphics state operations are not to blame in this case.
(Screen shots are from the ISO 32000-1 copy shared by Adobe.)
When you say:
In second highlighted circle the new Td positions (231.544 366.377990
Td) are completely replaced
Actually, the positions Current_x_pos and Current_x_pos are not replaced. This Td command does exactly like always:
Current_x_pos = x1 + 231.544
Curent_y_pos = y1 - 366.377990
It is the Q from 3 line above that reloads previous graphic state, right after the current graphic state has been saved with q.

Clipping path seems to be outside of text

recently I wanted to construct a PDF document which should have text clipping: With 4 Tr I tried to define the text as clipping area. But when I wanted to fill the lower part of the text with red color, the result was reversed.
Do anyone knows, why?
Thanks for any answer!
stream
BT
4 8 Td
0.8 0.2 0.7 rg % Writing lila.
4 Tr % Fill & Use text as clipping area.
/TR 32 Tf
(Hallo Welt) Tj
1 0 0 rg % Fill in red.
0 0 200 20 re F % <- Mistake?
ET
What I wanted to have:
What I got:
Have a look at the specification ISO 32000-1:
The behaviour of the clipping modes requires further explanation. Glyph outlines shall begin accumulating if a BT operator is executed while the text rendering mode is set to a clipping mode or if it is set to a clipping mode within a text object. Glyphs shall accumulate until the text object is ended by an ET operator; the text rendering mode shall not be changed back to a nonclipping mode before that point.
(section 9.3.6 Text Rendering Mode )
In your sample you don't wait until the ET for the clipping path to take effect. So, when you are painting the red rectangle, your special clipping path is not yet in effect.
Furthermore your operation sequence actually is invalid! Neither path construction nor path painting operators (i.e. neither your 0 0 200 20 re nor your F) are allowed inside a text object, cf. Figure 9 – Graphics Objects in the specification:
Thus, strictly speaking your PDF viewer had better refuse to draw your content stream at all.

PDF Low-Level: Drawing a line in the content object?

I have searched extensively online and I have the PDF specification in which I have looked, yet I still can't figure out how to draw a simple black line on a PDF page from the content object's instructions (stream).
Let's say I just want to draw a 1-pixel thickness (assuming 72 dpi) black line at x 400, y 100-300.
This should in theory be a very simple operation, but the PDF spec goes on and on about all kinds of fancy things and appears to forget to explain how I would go about performing this simple operation.
Please can someone point me in the right direction?
In the PDF specification, have a look at chapter 8 (Graphics) and in there section 8.5, Path Construction and Painting.
To draw a simple straight path, you need a "move to" operation followed by a "line to" operation:
400 100 m
400 300 l
You can then stroke the path using the S operator so your code becomes
400 100 m
400 300 l
S
By default the color is black so you've already gotten a black line :-) But if you want to make sure you have to set some parameters in the graphics state.
0 G
1 w
400 100 m
400 300 l
S
The first line now sets the color space to "gray" and puts the shade of grey to 0 (black). The following line sets the line width of your stroked line to 1 user unit (what this comes out as is dependent on your current transformation matrix.
You can apply a neat trick if you really want 1 pixel (please don't for production files though!) and that is to set the width to zero:
0 w
This gives you "the thinnest line that can be rendered at device resolution: 1 device pixel wide".

How to identify which clip paths apply to a path or fill in PDF vector graphics?

I am trying to extract vector graphics from a PDF file and create corresponding SVG files. I am using SVGOutputDev (https://github.com/immateriel/pdf2svg/blob/master/SVGOutputDev.cc‎) with xpdf library for this purpose. Now SVGOutputDev hasn't implemented clip path extraction and I am trying to implement the same. While I am able to extract the clip path definitions themselves, I am unable to determine which of these definitions apply to a normal stroke or fill region. For instance, please refer to http://pastebin.com/jTdzv3YZ for the SVG I extracted from a page of PDF, and the corresponding dump of the sequence of PDF graphics commands as seen during extraction. As seen from that SVG, there are multiple clip paths and one rectangular fill region. Even though there are multiple clip paths defined before the filled rectangle is defined, only the circular clip paths defined just before the rectangle definition are expected to be associated with the rectangle (going by how the PDF page was rendered on various PDF readers, which show only 2 black-filled circles in a white background). The question is how does one know which clip paths are associated with a regular fill/stroke region defined in a PDF? FYI, I went through the relevant section of the PDF specification document butit wasn't very clear to me ("A clipping path operation may appear after the last path construction operator and before the path-painting operator that terminates a path object. Although the clipping path operator appears before the painting operator, it does not alter the clipping path at the point where it appears. Rather, it modifies the effect of the succeeding painting operator"). Can someone explain how to identify the relevant clip paths to apply to any normal path?
The question is how does one know which clip paths are associated with a regular fill/stroke region defined in a PDF?
In a nutshell: The intersection of all those clip path areas which have been defined at the time the fill or stroke operation is executed, applies with the exception of those which were voided during a Q (restore state) operator.
Thus, your analysis for your sample file
Even though there are multiple clip paths defined before the filled rectangle is defined, only the circular clip paths defined just before the rectangle definition are expected to be associated with the rectangle (going by how the PDF page was rendered on various PDF readers, which show only 2 black-filled circles in a white background)
is wrong: Not the last clip area but the intersection of all clip areas before the rectangle definition defines the current one. As each of those clip areas is contained in the preceding one, the result of the intersection indeed consists of those two circles.
In the documentation:
The graphics state shall contain a current clipping path that limits the regions of the page affected by painting operators. The closed subpaths of this path shall define the area that can be painted.
The initial clipping path shall include the entire page.
[Clipping Path Operators] modify the current clipping path by intersecting it with the current path, using the [nonzero winding number rule / even-odd rule] to determine which regions lie inside the clipping path.
There is no way to enlarge the current clipping path or to set a new clipping path without reference to the current one. However, since the clipping path is part of the graphics state, its effect can be localized to specific graphics objects by enclosing the modification of the clipping path and the painting of those objects between a pair of q and Q operators (see 8.4.2, "Graphics State Stack"). Execution of the Q operator causes the clipping path to revert to the value that was saved by the q operator before the clipping path was modified.
(section 8.5.4 in the current PDF specification ISO 32000-1)
In action: Let's look at the content stream of the page of your document (which has a Mediabox [0, 0, 595, 842]):
q
q
Twice push the graphics state.
0 842 m
0 0 l
595 0 l
595 842 l
h
W
n
Defines a clip path equivalent with the whole media box.
1 w
2 J
0 j
10 M
[]0 d
Defines general graphics state properties (line width, line cap style, line join style, miter Limit, and dash pattern).
q
Pushes the graphics state again, this time with the explicitly set clip path and those other graphics properties.
0 718.5 m
595 718.5 l
595 123.5 l
0 123.5 l
0 718.5 l
h
W
n
Defines a clip path which contains a rectangle as wide as the whole media box but cutting off the top and bottom stripes of 124 user space units height. As this clip path is completely contained in the clip path set before, the intersection equals this clip path here. Thus, the currently effective clip area is this smaller rectangle.
0 718.5 m
595 718.5 l
595 123.5 l
0 123.5 l
0 718.5 l
h
W
n
Defines a clip path which is identical to the former one. Thus, intersecting them changes nothing.
148.75 668.92 m
93.98 668.92 49.58 624.52 49.58 569.75 c
49.58 514.98 93.98 470.58 148.75 470.58 c
203.52 470.58 247.92 514.98 247.92 569.75 c
247.92 624.52 203.52 668.92 148.75 668.92 c
h
347.08 470.58 m
292.32 470.58 247.92 426.18 247.92 371.42 c
247.92 316.65 292.32 272.25 347.08 272.25 c
401.85 272.25 446.25 316.65 446.25 371.42 c
446.25 426.18 401.85 470.58 347.08 470.58 c
h
W
n
Defines a clip path consisting of two circle subpaths. These two circles don't intersect; thus we don't have to deal with the differences between the "Nonzero Winding Number Rule" and the "Even-Odd Rule". Furthermore, the circles are contained inside the present clip area. Thus, the new clip area consists of these two circles.
0 0 0 rg
49.58 668.92 m
545.42 668.92 l
545.42 173.08 l
49.58 173.08 l
49.58 668.92 l
h
f
This draws a filled black rectangle which contains the current clipping area. Thus, the whole clipping area (i.e. the two circles) is painted black.
Q
q
This restores the graphics state to the last pushed one. I.e. the clipping path for any following operations is the first one which encompassed the whole media box. This graphics state is pushed again.
0 718.5 m
0 123.5 l
595 123.5 l
595 718.5 l
h
W
n
Once again the clipping path clipping off bars at the top and the bottom is defined...
Q
q
... and immediately dropped by a restore state Operation; the state is again pushed.
0 718.5 m
0 123.5 l
595 123.5 l
595 718.5 l
h
W
n
Q
q
The same again...
0 718.5 m
0 123.5 l
595 123.5 l
595 718.5 l
h
W
n
Q
q
... and again.
0 842 m
0 0 l
595 0 l
595 842 l
h
W
n
This once again defines a clipping path circumpassing the whole media box. As this is the current clipping path anyhow, nothing changes by intersecting.
Q
Q
Q
All graphics states formerly pushed onto the stack are removed again.