Questions of Matrix2D: Working with matrix transforms.

Q: I have several questions relating to Matrix2D.
1) I do not see a way to apply a rotation via an api method. I am
currently applying a rotation in a manner such as:
Matrix2D mtx = ...;
Matrix2D rotation = Matrix2D.RotationMatrix(30 *PI/180);
mtx = rotation*mtx;

Is this the preferred way to perform this?

2) I do not see a way to apply a skew via an api method. I assume that
I would create a matrix as described in the PDF Spec like [1, tan a,
tan b, 1, 0, 0]. I would then multiply this by my matrix containing my
translation, rotation and scale data. Is this the preferred way to do
this?

3) It was my understanding from the PDF spec that all transformations
are multiplicative. However, the scale method in Matrix2D only
multiplies the a and d values, and does not actually do a matrix
multiplication. Is this by design? I thought that is was a bug at
first, but then i re-read the PDFNet documentation and it verified
this. For instance if I do a rotation of 30deg on an identity matrix,
i get :
0.866025403784439, b=-0.5, c=0.5, d=0.866025403784439, h=0, v=0.

If I then multiply a scale matrix (a=5, b=0, c=0, d=10, h=0, v=0) by
hand (ie row*column) then I get:
a=4.33012701892219, b=-5, c=2.5, d=8.66025403784439, h=0, v=0.

However, using the matrix.scale(5,10) method I get:
a=4.33012701892219, b=-0.5, c=0.5, d=8.66025403784439, h=0, v=0
------
A: Regarding #1, you are on the right track. To apply rotation
transformation, create a rotation matrix (using
Matrix2D.RotationMatrix(rad_angle)) and then pre multiply it to
another matrix.

Regarding #2: you are also on the right track. You could create skew
matrix as follows:

Matrix2D skew = new Matrix2D(1, scwx, scwy, 1, 0, 0);
Now if you also want to translate, scale, and rotate content you could
create additional matrices:

const double deg2rad = 3.1415926535 / 180.0;
Matrix2D rotate = Matrix2D.RotationMatrix(30 * deg2rad);
Matrix2D scale = Matrix2D (scx, 0, 0, scy, 0, 0);
Matrix2D translate = Matrix2D (1, 0, 0, 1, offset_x, offset_y);

The final matrix will depend on the desired order of transforms. For
example if you want first to skew the element, followed by rotation,
followed by scaling, followed by translation, you would multiply
matrices as follows:

Matrix2D mtx = translate * scale * rotate * skew;

Alternatively if you would like to first translate the element,
followed by other transforms you would multiply matrices as follows:

Matrix2D mtx = scale * rotate * skew * translate;

This is similar to the convention used in OpenGL, where the rightmost
matrix is the topmost matrix on the stack, whereas the leftmost matrix
is the first matrix on the stack.

The transforms are applied from right to left:

               <--4--<---3----<--2---<-----1----
Matrix2D mtx = scale * rotate * skew * translate;

Re #3, the Scale method in Matrix2D simple multiplies a and d entries
by a given value. To create a scale matrix use the steps described
above.