Class: PDF::Reader::TransformationMatrix

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

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

#aObject (readonly)

: Numeric



18
19
20
# File 'lib/pdf/reader/transformation_matrix.rb', line 18

def a
  @a
end

#bObject (readonly)

: Numeric



21
22
23
# File 'lib/pdf/reader/transformation_matrix.rb', line 21

def b
  @b
end

#cObject (readonly)

: Numeric



24
25
26
# File 'lib/pdf/reader/transformation_matrix.rb', line 24

def c
  @c
end

#dObject (readonly)

: Numeric



27
28
29
# File 'lib/pdf/reader/transformation_matrix.rb', line 27

def d
  @d
end

#eObject (readonly)

: Numeric



30
31
32
# File 'lib/pdf/reader/transformation_matrix.rb', line 30

def e
  @e
end

#fObject (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

#inspectObject

: () -> 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_aObject

: () -> [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