Class: PDF::Reader::TransformationMatrix
- Inherits:
-
Object
- Object
- PDF::Reader::TransformationMatrix
- Defined in:
- lib/pdf/reader/transformation_matrix.rb
Overview
co-ordinate systems in PDF files are specified using a 3x3 matrix that looks something like this:
[ a b 0 ]
[ c d 0 ]
[ e f 1 ]
Because the final column never changes, we can represent each matrix using only 6 numbers. This is important to save CPU time, memory and GC pressure caused by allocating too many unnecessary objects.
Instance Attribute Summary collapse
-
#a ⇒ Object
readonly
Returns the value of attribute a.
-
#b ⇒ Object
readonly
Returns the value of attribute b.
-
#c ⇒ Object
readonly
Returns the value of attribute c.
-
#d ⇒ Object
readonly
Returns the value of attribute d.
-
#e ⇒ Object
readonly
Returns the value of attribute e.
-
#f ⇒ Object
readonly
Returns the value of attribute f.
Instance Method Summary collapse
-
#displacement_left_multiply!(e2, f2) ⇒ Object
Optimised method for when the second matrix in the calculation is a simple displacement.
-
#horizontal_displacement_multiply!(e2) ⇒ Object
Optimised method for when the second matrix in the calculation is a simple horizontal displacement.
-
#initialize(a, b, c, d, e, f) ⇒ TransformationMatrix
constructor
A new instance of TransformationMatrix.
- #inspect ⇒ Object
-
#left_multiply!(a, b, c, d, e, f) ⇒ Object
Same as “multiply!”, but left-multiplying instead of right-multiplying.
-
#multiply!(a, b = nil, c = nil, d = nil, e = nil, f = nil) ⇒ Object
multiply this matrix with another.
- #to_a ⇒ Object
Constructor Details
#initialize(a, b, c, d, e, f) ⇒ TransformationMatrix
Returns a new instance of TransformationMatrix.
17 18 19 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 17 def initialize(a, b, c, d, e, f) @a, @b, @c, @d, @e, @f = a, b, c, d, e, f end |
Instance Attribute Details
#a ⇒ Object (readonly)
Returns the value of attribute a.
15 16 17 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 15 def a @a end |
#b ⇒ Object (readonly)
Returns the value of attribute b.
15 16 17 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 15 def b @b end |
#c ⇒ Object (readonly)
Returns the value of attribute c.
15 16 17 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 15 def c @c end |
#d ⇒ Object (readonly)
Returns the value of attribute d.
15 16 17 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 15 def d @d end |
#e ⇒ Object (readonly)
Returns the value of attribute e.
15 16 17 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 15 def e @e end |
#f ⇒ Object (readonly)
Returns the value of attribute f.
15 16 17 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 15 def f @f end |
Instance Method Details
#displacement_left_multiply!(e2, f2) ⇒ Object
Optimised method for when the second matrix in the calculation is a simple displacement.
The current matrix (self) is on the right hand side
Like this:
[ 1 0 0 ] [ a b 0 ]
[ 0 1 0 ] X [ c d 0 ]
[ e2 f2 1 ] [ e f 1 ]
121 122 123 124 125 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 121 def displacement_left_multiply!(e2, f2) newe = (e2 * @a) + (f2 * @c) + @e newf = (e2 * @b) + (f2 * @d) + @f @e, @f = newe, newf end |
#horizontal_displacement_multiply!(e2) ⇒ Object
Optimised method for when the second matrix in the calculation is a simple horizontal displacement.
The current matrix (self) is on the left hand side
Like this:
[ 1 2 0 ] [ 1 0 0 ]
[ 3 4 0 ] x [ 0 1 0 ]
[ 5 6 1 ] [ e2 0 1 ]
106 107 108 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 106 def horizontal_displacement_multiply!(e2) @e = @e + e2 end |
#inspect ⇒ Object
21 22 23 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 21 def inspect "#{a}, #{b}, 0,\n#{c}, #{d}, #{0},\n#{e}, #{f}, 1" end |
#left_multiply!(a, b, c, d, e, f) ⇒ Object
Same as “multiply!”, but left-multiplying instead of right-multiplying
Currently no optimizations because I don’t have a benchmarking suite set up
91 92 93 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 91 def left_multiply!(a,b,c,d,e,f) faster_left_multiply!(a,b,c,d,e,f) end |
#multiply!(a, b = nil, c = nil, d = nil, e = nil, f = nil) ⇒ Object
multiply this matrix with another.
the second matrix is represented by the 6 scalar values that are changeable in a PDF transformation matrix.
WARNING: This mutates the current matrix to avoid allocating memory when
we don't need too. Matrices are multiplied ALL THE FREAKING TIME
so this is a worthwhile optimisation
NOTE: When multiplying matrices, ordering matters. Double check
the PDF spec to ensure you're multiplying things correctly.
NOTE: This matrix (self) is the matrix on the left side of the
equation
NOTE: see Section 8.3.3, PDF 32000-1:2008, pp 119
NOTE: The if statements in this method are ordered to prefer optimisations
that allocate fewer objects
TODO: it might be worth adding an optimised path for vertical
displacement to speed up processing documents that use vertical
writing systems
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 55 def multiply!(a,b=nil,c=nil, d=nil,e=nil,f=nil) if a == 1 && b == 0 && c == 0 && d == 1 && e == 0 && f == 0 # the identity matrix, no effect self elsif @a == 1 && @b == 0 && @c == 0 && @d == 1 && @e == 0 && @f == 0 # I'm the identity matrix, so just copy values across @a = a @b = b @c = c @d = d @e = e @f = f elsif a == 1 && b == 0 && c == 0 && d == 1 && f == 0 # the other matrix is a horizontal displacement horizontal_displacement_multiply!(e) elsif @a == 1 && @b == 0 && @c == 0 && @d == 1 && @f == 0 # I'm a horizontal displacement horizontal_displacement_multiply_reversed!(a,b,c,d,e,f) elsif @a != 1 && @b == 0 && @c == 0 && @d != 1 && @e == 0 && @f == 0 # I'm a xy scale xy_scaling_multiply_reversed!(a,b,c,d,e,f) elsif a != 1 && b == 0 && c == 0 && d != 1 && e == 0 && f == 0 # the other matrix is an xy scale xy_scaling_multiply!(a,b,c,d,e,f) else faster_multiply!(a,b,c, d,e,f) end self end |
#to_a ⇒ Object
25 26 27 28 29 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 25 def to_a [@a,@b,0, @c,@d,0, @e,@f,1] end |