Class: PDFShaver::Page

Inherits:
Object
  • Object
show all
Defined in:
lib/pdfshaver/page.rb

Constant Summary collapse

GM_MATCHER =
/^\s*((?<width>\d+)x((?<height>\d+))?|x?(?<height>\d+))(?<modifier>[@%!<>^]+)?\s*$/

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(document, number, options = {}) ⇒ Page

Returns a new instance of Page.

Raises:

  • (ArgumentError)


6
7
8
9
10
11
12
13
14
15
16
# File 'lib/pdfshaver/page.rb', line 6

def initialize document, number, options={}
  raise ArgumentError unless document.kind_of? PDFShaver::Document
  raise ArgumentError unless number.kind_of? Integer
  raise ArgumentError unless number > 0 and number <= document.length
  
  @number   = number
  @index    = number - 1
  @document = document
  @extension_data_is_loaded = false
  initialize_page_internals document, @index
end

Instance Attribute Details

#documentObject (readonly)

Returns the value of attribute document.



4
5
6
# File 'lib/pdfshaver/page.rb', line 4

def document
  @document
end

#indexObject (readonly)

Returns the value of attribute index.



4
5
6
# File 'lib/pdfshaver/page.rb', line 4

def index
  @index
end

#numberObject (readonly)

Returns the value of attribute number.



4
5
6
# File 'lib/pdfshaver/page.rb', line 4

def number
  @number
end

Instance Method Details

#<=>(other) ⇒ Object

Raises:

  • (ArgumentError)


23
24
25
26
# File 'lib/pdfshaver/page.rb', line 23

def <=> other
  raise ArgumentError, "unable to compare #{self.class} with #{other.class}" unless other.kind_of? self.class
  self.index <=> other.index
end

#==(other) ⇒ Object

Raises:

  • (ArgumentError)


18
19
20
21
# File 'lib/pdfshaver/page.rb', line 18

def == other
  raise ArgumentError, "unable to compare #{self.class} with #{other.class}" unless other.kind_of? self.class
  (self.document == other.document) and (self.index == other.index)
end

#aspectObject



38
39
40
41
# File 'lib/pdfshaver/page.rb', line 38

def aspect
  load_dimensions unless @aspect
  @aspect
end

#extract_dimensions_from_gm_geometry_string(arg) ⇒ Object

This code was written with the GraphicsMagick geometry argument parser as a direct reference. Its intent is to provide a compatibility layer for specifying page geometry that functions identically to graphicsmagick’s.

Raises:

  • (ArgumentError)


67
68
69
70
71
72
73
74
75
76
77
78
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/pdfshaver/page.rb', line 67

def extract_dimensions_from_gm_geometry_string(arg)
  dimensions = {}
  return dimensions if arg.nil? or arg.empty?
  raise ArgumentError, "argument is not a String" unless arg.kind_of? String
  arg.match(GM_MATCHER) do |match|
    
    # grab parsed tokens
    requested_width  = match[:width].to_f unless match[:width].nil? 
    requested_height = match[:height].to_f unless match[:height].nil? 
    modifier         = match[:modifier] || ""
    
    ## Algorithm ported from GraphicsMagick's GetMagickGeometry function.
    #
    # the '@' option precludes all other options.
    if modifier.include? '@'
      # calculate the current page area
      # and the specified target area for comparison
      current_area = self.width * self.height
      target_area  = (requested_width || 1) * (requested_height || 1)
      
      # if upper or lower bounds are supplied
      # check whether the target_area size adheres to that constraint.
      resize = if modifier.include? '>'
        current_area > target_area
      elsif modifier.include? '<'
        current_area < target_area
      else
        true
      end
      
      # Calculate page dimensions based on area
      if resize
        scale = 1.0 / Math.sqrt(current_area/target_area)
        dimensions[:width]  = (self.width*scale+0.25).floor
        dimensions[:height] = (self.height*scale+0.25).floor
      end
    else # Handle all of the non area modes.
      width = requested_width
      height = requested_height
      
      # when supplied with only a width or a height
      # infer the other using the page's aspect ratio.
      if width and not height
        height = (width/self.aspect+0.5).floor
      elsif height and not width
        width  = (self.width.to_f/self.height*height+0.5).floor
      end
      
      # For proportional mode, scales are specified by percent.
      # Sizes are recalculated and stored as the target width in place for further processing
      if modifier.include? '%'
        x_scale = width
        y_scale = height
        x_scale = y_scale if requested_width.nil? or requested_height.nil?
        width   = ((self.width * x_scale / 100.0) +0.5).floor
        height  = ((self.height * y_scale / 100.0) +0.5).floor
        # this is to match how GraphicsMagick works.
        requested_width = width
        requested_height = height
      end
      
      if modifier.include? '!' and ((width != requested_width) || (height != requested_height))
        if (requested_width == 0) || (requested_height == 0)
          scale = 1.0
        else
          width_ratio  = width / self.width
          height_ratio = height / self.height
          scale = width_ratio
        end
        
        width  = (scale*self.width+0.5).floor
        height = (scale*self.height+0.5).floor
      end
      
      if modifier.include? '>'
        width  = self.width  if self.width  < width
        height = self.height if self.height < height
      end
      
      if modifier.include? '<'
        width  = self.width  if self.width  > width
        height = self.height if self.height > height
      end
      
      dimensions[:width]  = width.floor
      dimensions[:height] = height.floor
    end
    dimensions[:width]  ||= self.width.floor
    dimensions[:height] ||= self.height.floor
    return dimensions
  end
  
  raise ArgumentError, "unable to extract width & height from '#{arg}'"
end

#heightObject



28
29
30
31
# File 'lib/pdfshaver/page.rb', line 28

def height
  load_dimensions unless @height
  @height
end

#lengthObject



43
44
45
46
# File 'lib/pdfshaver/page.rb', line 43

def length
  load_dimensions unless @length
  @length
end

#widthObject



33
34
35
36
# File 'lib/pdfshaver/page.rb', line 33

def width
  load_dimensions unless @width
  @width
end

#with_data_loaded(&block) ⇒ Object



48
49
50
51
52
53
# File 'lib/pdfshaver/page.rb', line 48

def with_data_loaded &block
  load_data
  output = yield self
  unload_data
  output
end