Created attachment 14047 [details] source Adobe Illustrator file Hello, we have an integration with Ghostscript in our application that extracts thumbnails from source documents. In the case of the attached source document (AI or PDF), the resulting png has layers mispositioned. Here is the command I am running: /usr/local/bin/gs -dQUIET -dNOPROMPT -dNOPAUSE -dBATCH -dSAFER -r300 -sDEVICE=png16m -sOutputFile=target.png source.ai or /usr/local/bin/gs -dQUIET -dNOPROMPT -dNOPAUSE -dBATCH -dSAFER -r300 -sDEVICE=png16m -sOutputFile=target.png source.pdf Please see attached source and target files for reference. Thanks, Carl
Created attachment 14048 [details] source pdf file
Created attachment 14049 [details] target png
This is nothing to do with layers (which are q
Created attachment 14050 [details] simplified file Oops, pressed submit by accident. This is nothing to do with layers, which are a specific feature of PDF files. The problem is something to do with patterns. The important part of this is reproduced in the reduced file (attached) which is an irregular path filled with a pattern. The pattern simply draws an image. At different resolutions the image appears to be scaled differently, or possibly the pattern offset is slightly different, resulting in different portions of the image underlying the fill. As a quick test tried using -dNOINTERPOLATE and -dNOTRANSPARENCY, no difference.
Looks like a pattern or image issue. I'll have a look.
This is the result of mismatch between adjusted and unadjusted sizes used in the calculation of the pattern phase, when translation values in the pattern matrix are large.
The problem here seems to be that the Pattern has a TilingType of 3 (constant spacing and faster tiling), which permits us to distort the pattern cell and it's placement, for better performance. The exact nature of the distortion is not documented for type 3. If I alter the TilingType to 2 (no distortion) then the pattern is painted as expected. To me this looks like a combination of using a small image to create a pattern, scaling that image up by a large amount, and then permitting the interpreter to be lax about the position and size of the cell. Basically; "don't do that" However I'd like another (ideally better informed) opinion so I'm assigning this to Robin on the basis that he seems to have been the last one to work on gs_pattern1_make_pattern() which is where the adjustment to the pattern cell/position takes place.
Created attachment 22660 [details] reduced4.pdf Even more reduced file. A 'simple' path filled with a pattern.
The problem is indeed down to TilingType 3. We are operating within the spec. It's a badly formed file. I toyed with the following patch: diff --git a/base/gsptype1.c b/base/gsptype1.c index 4dc86e8fc..06abe6705 100644 --- a/base/gsptype1.c +++ b/base/gsptype1.c @@ -278,15 +278,23 @@ gs_pattern1_make_pattern(gs_client_color * pcc, gs_scale(saved, fabs(inst.size.x / inst.step_matrix.xx), 1); inst.step_matrix.xx = (float)inst.size.x; } else { - float cx, ox, dx; - float n; - + float cx, ox, dx, n; + + /* We are about to adjust our matrices/bbox such that it + * will become integer sized, and will tile based upon + * those integer sizes. For cases where the transformation + * is large, this small adjustment can have large effects + * by the time we come to have one on screen. Before we + * do anything else, we therefore adjust the transformation + * using the accurate widths/heights so that our 0th tile + * repeat has the smallest transformation possible. + */ if (inst.step_matrix.tx >= 0) n = floor(inst.step_matrix.tx/inst.step_matrix.xx); else n = -ceil(-inst.step_matrix.tx/inst.step_matrix.xx); inst.step_matrix.tx -= n * inst.step_matrix.xx; - inst.saved->ctm.tx -= n * inst.step_matrix.xx; + saved->ctm.tx -= n * inst.step_matrix.xx; bbox.p.x -= n*inst.step_matrix.xx; bbox.q.x -= n*inst.step_matrix.xx; if (inst.step_matrix.ty >= 0) @@ -294,7 +302,7 @@ gs_pattern1_make_pattern(gs_client_color * pcc, else n = -ceil(-inst.step_matrix.ty/inst.step_matrix.yy); inst.step_matrix.ty -= n * inst.step_matrix.yy; - inst.saved->ctm.ty -= n * inst.step_matrix.yy; + saved->ctm.ty -= n * inst.step_matrix.yy; bbox.p.y -= n*inst.step_matrix.yy; bbox.q.y -= n*inst.step_matrix.yy; That "fixes" this bug, but it changes many other files, and possibly not all for the good. An alternative idea would be to create a new command line option that forces all patterns to be interpreted as TilingType 2. We'd need more evidence to justify that I think.