Hi Maruan,
> On 28 Dec 2014, at 02:54, Maruan Sahyoun <[email protected]> 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 <[email protected]>:
>
>> 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 <[email protected]> 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 <[email protected]>:
>>>
>>>> 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
>>>>
>>>
>>
>