diff options
author | Ken Sharp <ken.sharp@artifex.com> | 2022-05-14 13:32:48 +0100 |
---|---|---|
committer | Ken Sharp <ken.sharp@artifex.com> | 2022-05-14 14:36:38 +0100 |
commit | cf21335a57b279bdd4ee950e20c02ae3dee34996 (patch) | |
tree | 24534cd9e4f3b1568fbd0525aa8f4217a9eafa27 /pdf/pdf.mak | |
parent | 860d0ca2ed2264ef98503e6a63f800c93dd77fb6 (diff) | |
download | ghostpdl-cf21335a57b279bdd4ee950e20c02ae3dee34996.tar.gz |
GhostPDF - Defer path construction until painting
Bug #705252 "Transformation matrix sometimes not applied with the new PDF interpreter"
PDF does not maintain the current path as part of the graphics state; as
noted in section 4.4.1 of the 1.7 PDF Reference Manual. As can be seen
from this bug report, and previously with grestore, the path segments
are accumulated and not transformed from user space to device space
until a path-painting operation occurs.
This means that all path segments are mapped using the same CTM, not the
CTM in force at the time the path construction operator was encountered.
In the old PDF interpreter, and previously in GhostPDF, we dealt with
this rather painfully by constructing the path as we went and if we
came to an operator which might change the CTM (cm or Q) while there was
a partial path, we would traverse the path accumulating the path
operations and applying the inverse of the CTM to transform the co-ords
back to user space, perform the CTM-changing operation, and then run
the path again with the new CTM.
Obviously that's laborious and somewhat prone to error. So here we
completely change the way we deal with paths. We now behave in a manner
similar to that which the specification implies for Acrobat; we store
the path operations until a path-painting operator occurs, only then
do we execute the path construction, transforming the user space
co-ordinates to device space.
We store the path operations in a simple array; a char representing the
operation followed by 0 to 6 doubles depending on the nature of the
segment.
The array size is increased 4KB at a time when exhausted to try and
strike a balance between memory use and performance; we don't want to
continually reallocate and copy the accumulated path for each segment.
For PDF files which do not rely on this 'feature' of the PDF spec we do
end up using slightly more memory but for files which do use it, we
use less memory and are slightly faster. In addition the code for the
cm and Q operators is simplified, as are other path construction
operators.
At Chris's suggestion I did look at using a gs_path to store the
segments, and then scaling it when it was needed, but looking at the way
that we create paths in the graphics library this would have led to
considerably more floating point multiplications which would hurt
performance as they would be done for all path construction operations.
On a historical note; this behaviour of PDF is not documented in the
1.0, 1.1 or 1.2 specifications and in fact those versions of the spec
are written in a way which certainly strongly implies that the intention
is that paths should behave as they do in PostScript.
This 'feature' is introduced without fanfare in the PDF 1.3 spec. I am
suspicious that someone discovered that Acrobat had been written in this
way, and rather than change the application Adobe chose to quietly
change the specification.
In passing; noted that a 'M' operation (set miter limit) with an operand
of < 1 was causing an error. The old code silently clamped values less
than 1 to 1, so we do the same here.
Diffstat (limited to 'pdf/pdf.mak')
-rw-r--r-- | pdf/pdf.mak | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/pdf/pdf.mak b/pdf/pdf.mak index 7040a72e9..118a0b7d5 100644 --- a/pdf/pdf.mak +++ b/pdf/pdf.mak @@ -188,7 +188,7 @@ $(PDFOBJ)pdf_stack.$(OBJ): $(PDFSRC)pdf_stack.c $(PDFINCLUDES) $(PDF_MAK) $(MAKE $(PDFOBJ)pdf_gstate.$(OBJ): $(PDFSRC)pdf_gstate.c $(PDFINCLUDES) $(gsstate_h) \ $(gsmatrix_h) $(gslparam_h) $(gstparam_h) $(gxdht_h) $(gxht_h) $(gzht_h) $(gsht_h) \ - $(gscoord_h) $(gsutil_h) $(gscolor3_h) $(PDF_MAK) $(MAKEDIRS) + $(gscoord_h) $(gsutil_h) $(gscolor3_h) $(PDF_MAK) $(MAKEDIRS) $(gzpath_h) $(gspenum_h) $(PDFCCC) $(PDFSRC)pdf_gstate.c $(PDFO_)pdf_gstate.$(OBJ) $(PDFOBJ)pdf_colour.$(OBJ): $(PDFSRC)pdf_colour.c $(PDFINCLUDES) \ |