Hi Maruan, > On 28 Dec 2014, at 02:54, Maruan Sahyoun <sahy...@fileaffairs.de> wrote: > > OK - I think the Matrix code is wrong in getting the shear values compared to > the description in the PDF spec. > > eg. using a text matrix to produce an 'italic' text > > AffineTransform transform = AffineTransform.getShearInstance(0, 0.5); > contentStream.setTextMatrix(transform); > > produces the same result as > > contentStream.setTextMatrix(1, 0, 0.5, 1, 0, 0); > > > Which is inline with the spec as c is the sy value. >
Yes. > Now getShearX, getShearY and create AffineTransform in Matrix are wrong IMHO > as they have the extraction flipped between sx and sy. That’s what was puzzling me. I think what we’re doing is fine based on AffineTransform’s definition of shear x/y, but that the terminology is simply different from PDF, i.e. an x-skew is described in terms of a y-factor, so it’s easy to see how the naming could be ambiguous. > e.g. printing the values of > > AffineTransform transform = AffineTransform.getShearInstance(0, 0.5); Ok, so that’s hx = 0, hy = 0.5 > produces > > AffineTransform[[1.0, 0.0, 0.0], [0.5, 1.0, 0.0]] > > where > > printing the values of > > Matrix matrix = new Matrix(); > matrix.setValue(1, 0, 0.5f); Element (1,0) is hx, so you’re doing hx = 0.5, hy = 0, which is the opposite of your example above. > produces > > AffineTransform[[1.0, 0.5, 0.0], [0.0, 1.0, 0.0]] > > which is wrong as it should produce AffineTransform[[1.0, 0.0, 0.0], [0.5, > 1.0, 0.0]] Which would make sense for hx = 0.5 but what you wanted was: matrix.setValue(0, 1, 0.5f) which produces the expected result: AffineTransform[[1.0, 0.0, 0.0], [0.5, 1.0, 0.0]] So I think we’re ok. — John > > BR > > Maruan > > Am 27.12.2014 um 23:47 schrieb John Hewson <j...@jahewson.com>: > >> Yes, the pure matrix code seems to work fine. As do the examples which >> Tilman mentioned. I can’t find any issue with the code itself. However, we >> make use the following Matrix method: >> >> public AffineTransform createAffineTransform() >> { >> AffineTransform retval = new AffineTransform( >> single[0], single[1], // m00 m10 = scaleX shearY >> single[3], single[4], // m01 m11 = shearX scaleY >> single[6], single[7] ); // m02 m12 = tx ty >> return retval; >> } >> >> Recall that single[] is the array: >> >> | sx hy 0 | >> | hx sy 0 | >> | tx ty 1 | >> >> Which is fine, except that shear-x and shear-y are flipped vs. the wording >> in the PDF spec, namely: >> >> "Skew shall be specified by [1 tan a tan b 1 0 0], which skews the x axis by >> an angle a and the y axis by >> an angle b.” >> >> But the AffineTransform constructor uses the following parameters: >> >> "m00 - the X coordinate scaling element of the 3x3 matrix >> m10 - the Y coordinate shearing element of the 3x3 matrix >> m01 - the X coordinate shearing element of the 3x3 matrix >> m11 - the Y coordinate scaling element of the 3x3 matrix >> m02 - the X coordinate translation element of the 3x3 matrix >> m12 - the Y coordinate translation element of the 3x3 matrix" >> >> At this point I’m left thinking that Java and PDF have chosen different >> meanings of “x” and “y” when talking about skew, indeed this appears to be >> the case, as the PDF spec defines the x-coordinate transform on p120 as: >> >> x’ = a*x + c*y + e >> >> while the AffineTransform documentation defines the same transform as: >> >> x' = [ m00*x + m01*y + m02 ] >> >> which might seem different until one realises that m00 = a, m01 = c, m02 = >> e. The only difference appears to be the description that c "skews the y >> axis” in PDF and m01 is "the X coordinate shearing" in AffineTransform. It >> seems like PDF is weird in this regard? >> >> -- John >> >>> On 27 Dec 2014, at 16:51, Maruan Sahyoun <sahy...@fileaffairs.de> wrote: >>> >>> Hi, >>> >>> I tried the following with skew being [1 tan a tan b 1 0 0] according to >>> the spec. >>> >>> Matrix matrix = new Matrix(); >>> >>> which gives me [1.0,0.0,0.0,1.0,0.0,0.0] >>> >>> then >>> >>> matrix.setValue(0, 1, 0.5f); >>> matrix.setValue(1, 0, 0.7f); >>> >>> which shall set the tan a and tan b values >>> >>> which gave me >>> >>> [1.0,0.5,0.7,1.0,0.0,0.0] >>> >>> then >>> >>> Matrix matrix2 = new Matrix() >>> >>> again being [1.0,0.0,0.0,1.0,0.0,0.0] >>> >>> then >>> >>> matrix.concatenate(matrix2) >>> >>> resulting in [1.0,0.5,0.7,1.0,0.0,0.0] >>> >>> To me that indicates that the pure matrix class is fine for that case. What >>> are the arguments to the Concatenate operator in your case? Could it be >>> that reading the values is not OK? >>> >>> BR >>> >>> Maruan >>> >>> Am 27.12.2014 um 14:16 schrieb John Hewson <j...@jahewson.com>: >>> >>>> Hi All, >>>> >>>> I’ve been looking at the Matrix class and trying to understand if it has >>>> some problems. The Matrix class >>>> in PDFBox uses the following matrix: >>>> >>>> | sx hy 0 | >>>> | hx sy 0 | >>>> | tx ty 1 | >>>> >>>> In a PDF file this matrix is represented as the 6-element array [a, b, c, >>>> d, e, f] where the meaning of >>>> the values comes from p118 and is [sx, hx, hy, sy, tx, ty]. Note that h is >>>> used to mean shear/skew. >>>> >>>> The Concatenate operator class populates the Matrix as follows: >>>> PDFBox PDF Spec >>>> newMatrix.setValue(0, 0, a.floatValue()); sx a = sx >>>> newMatrix.setValue(0, 1, b.floatValue()); hy c = hx <- Flipped? >>>> newMatrix.setValue(1, 0, c.floatValue()); hx b = hy <- Flipped? >>>> newMatrix.setValue(1, 1, d.floatValue()); sy d = sy >>>> newMatrix.setValue(2, 0, e.floatValue()); tx e = tx >>>> newMatrix.setValue(2, 1, f.floatValue()); ty f = ty >>>> >>>> I’ve annotated what PDFBox does on the left, compared to the PDF spec, the >>>> x and y skew elements >>>> (hx and hy) are flipped in PDFBox. This flip matches the order in which >>>> AWT’s AffineTransform’s >>>> constructor expects its elements but does not match the arrays used in the >>>> PDF spec. >>>> >>>> Are we accidentally flipping skew-x and skew-y in the Concatenate operator? >>>> >>>> -- John >>>> >>> >> >