After reading the Adobe PDF 1.7 (ISO 32000-1:2008) specification, I'm still having trouble understanding how to properly create my transformation matrix.
The specification in section 4.2/4.3 state the following:
• Translations are specified as [ 1 0 0 1 tx ty ], where tx and ty are the distances to translate the origin of the coordinate system in the horizontal and vertical dimensions, respectively.
• Scaling is obtained by [ sx 0 0 sy 0 0 ]. This scales the coordinates so that 1 unit in the horizontal and vertical dimensions of the new coordinate system is the same size as sx and sy units, respectively, in the previous coordinate system.
• Rotations are produced by [ cos θ sin θ −sin θ cos θ 0 0 ], which has the effect of rotating the coordinate system axes by an angle θ counterclockwise.
• Skew is specified by [ 1 tan α tan β 1 0 0 ], which skews the x axis by an angle α and the y axis by an angle β.
Given this, how exactly does one go about using transformations in sequence with each other?
I can successfully use the Translation
and Rotation
together, but when I attempt to also use Scaling
or Skewing
things go severely wrong. Perhaps I'm using the CTM incorrectly or maybe even my math is off. I am attempting to create text at coordinate position (50, 50) with a rotation of 45 degrees and a scaling of 2 (in that order). The reason why I state "In that order" is because the specification states that ordering of transformations makes a difference (the spec gives a graphical example of the differences based on the transformation ordering). So what would the stream object look like and/or how would the matrix mathematics apply here?
Working (Transformation of (50, 50) + 45 degree rotation)
[ 1 0 0 ] [ 0.707 0.707 0 ] [ 0.707 0.707 0 ]
[ 0 1 0 ] x [ -0.707 0.707 0 ] = [ -0.707 0.707 0 ]
[ 50 50 1 ] [ 0 0 1 ] [ 50.000 50.000 1 ]
BT
0.707 0.707 -0.707 0.707 50 50 Tm
/F1 36 Tf
(Hello, World!) Tj
ET
When I try to do matrix multiplication to add scaling, it doesn't seem to work:
[ 0.707 0.707 0 ] [ 2 0 0 ] [ 1.414 1.414 0 ]
[ -0.707 0.707 0 ] x [ 0 2 0 ] = [ -1.414 1.414 0 ]
[ 50.000 50.000 1 ] [ 0 0 1 ] [ 100.000 100.000 1 ]
The math seems correct, except now the text starts at coordinate (100, 100) instead of (50, 50). This just doesn't seem correct to me, since I'm trying to start at (50, 50), rotate by 45 degrees, then scale it by 2.
Transformation Matrix is a matrix that transforms one vector into another vector by the process of matrix multiplication. The transformation matrix alters the cartesian system and maps the coordinates of the vector to the new coordinates.
Transformation Matrix (CTM) 4x4 homogeneous coordinate matrix that is part of the state and applied to all vertices that pass down the pipeline.
When you want to transform a point using a transformation matrix, you right-multiply that matrix with a column vector representing your point. Say you want to translate (5, 2, 1) by some transformation matrix A. You first define v = [5, 2, 1, 1]T.
The math seems correct, except now the text starts at coordinate (100, 100) instead of (50, 50). This just doesn't seem correct to me, since I'm trying to start at (50, 50), rotate by 45 degrees, then scale it by 2.
But that does make sense. If you first translate by (50, 50) and then scale by two, you effectively translate by (50, 50) times two, i.e. (100, 100).
What you seem to need is to first scale by two (to have thing twice the size, but not yet moved or rotated) and only thereafter rotate and translate (without scaling affecting the translation), i.e.
[ 2 0 0 ] [ 0.707 0.707 0 ] [ 1.414 1.414 0 ]
[ 0 2 0 ] x [ -0.707 0.707 0 ] = [ -1.414 1.414 0 ]
[ 0 0 1 ] [ 50.000 50.000 1 ] [ 50.000 50.000 1 ]
Some hand-waving: What you had in mind when you said
I am attempting to create text at coordinate position (50, 50) with a rotation of 45 degrees and a scaling of 2 (in that order).
surely was that after translating to (50, 50), the following operations should leave the point (50, 50) fixed. But that's not what the other operations do, they keep the origin (0,0) fixed. Thus you should first scale and rotate your object at the origin and only thereafter translate it, at least to match what you had in mind...
The operator Tm is used for setting the text matrix, which is combined with the Current Transformation Matrix when the text is rendered.
Instead you could use the cm operator (concatenate matrix), which is going to do all the math operations for you. If you want to keep the original matrix that was used before you started outputting the text, you could use the operators q/Q to save/restore the current graphic state.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With