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
: Numeric.
-
#b ⇒ Object
readonly
: Numeric.
-
#c ⇒ Object
readonly
: Numeric.
-
#d ⇒ Object
readonly
: Numeric.
-
#e ⇒ Object
readonly
: Numeric.
-
#f ⇒ Object
readonly
: Numeric.
Instance Method Summary collapse
-
#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
: (Numeric, Numeric, Numeric, Numeric, Numeric, Numeric) -> void.
-
#inspect ⇒ Object
: () -> String.
-
#multiply!(a, b, c, d, e, f) ⇒ Object
multiply this matrix with another.
-
#to_a ⇒ Object
: () -> [Numeric].
Constructor Details
#initialize(a, b, c, d, e, f) ⇒ TransformationMatrix
: (Numeric, Numeric, Numeric, Numeric, Numeric, Numeric) -> void
36 37 38 39 40 41 42 43 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 36 def initialize(a, b, c, d, e, f) @a = a @b = b @c = c @d = d @e = e @f = f end |
Instance Attribute Details
#a ⇒ Object (readonly)
: Numeric
18 19 20 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 18 def a @a end |
#b ⇒ Object (readonly)
: Numeric
21 22 23 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 21 def b @b end |
#c ⇒ Object (readonly)
: Numeric
24 25 26 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 24 def c @c end |
#d ⇒ Object (readonly)
: Numeric
27 28 29 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 27 def d @d end |
#e ⇒ Object (readonly)
: Numeric
30 31 32 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 30 def e @e end |
#f ⇒ Object (readonly)
: Numeric
33 34 35 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 33 def f @f end |
Instance Method Details
#horizontal_displacement_multiply!(e2) ⇒ Object
Optimised method for when the second matrix in the calculation is a simple horizontal displacement.
Like this:
[ 1 2 0 ] [ 1 0 0 ]
[ 3 4 0 ] x [ 0 1 0 ]
[ 5 6 1 ] [ e2 0 1 ]
: (Numeric) -> void
119 120 121 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 119 def horizontal_displacement_multiply!(e2) @e = @e + e2 end |
#inspect ⇒ Object
: () -> String
46 47 48 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 46 def inspect "#{a}, #{b}, 0,\n#{c}, #{d}, #{0},\n#{e}, #{f}, 1" end |
#multiply!(a, b, c, d, e, f) ⇒ 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: 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
: (Numeric, Numeric, Numeric, Numeric, Numeric, Numeric) -> PDF::Reader::TransformationMatrix
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 79 def multiply!(a,b,c, d,e,f) 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
: () -> [Numeric]
51 52 53 54 55 |
# File 'lib/pdf/reader/transformation_matrix.rb', line 51 def to_a [@a,@b,0, @c,@d,0, @e,@f,1] end |