Class: HexaPDF::Layout::BoxFitter

Inherits:
Object
  • Object
show all
Defined in:
lib/hexapdf/layout/box_fitter.rb

Overview

A BoxFitter instance contains an array of Frame objects and allows placing boxes one after the other in them. Such functionality is useful, for example, for boxes that provide multiple frames for content.

Usage

  • First one needs to add the frame objects via #<< or provide them on initialization.

  • Then use the #fit method to fit boxes one after the other. No drawing is done.

  • Once all boxes have been fitted, the #fit_results, #remaining_boxes and #success? methods can be used to get the result:

    • If there are no remaining boxes, all boxes were successfully fitted into the frames.

    • If there are remaining boxes but no fit results, the first box could not be fitted.

    • If there are remaining boxes and fit results, some boxes were able to fit.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(frames = []) ⇒ BoxFitter

Creates a new BoxFitter object for the given frames.



71
72
73
74
75
76
77
78
79
80
# File 'lib/hexapdf/layout/box_fitter.rb', line 71

def initialize(frames = [])
  @frames = []
  @content_heights = []
  @initial_frame_y = []
  @frame_index = 0
  @fit_results = []
  @remaining_boxes = []

  frames.each {|frame| self << frame }
end

Instance Attribute Details

#fit_resultsObject (readonly)

The Frame::FitResult objects for the successfully fitted objects in the order the boxes were fitted.



65
66
67
# File 'lib/hexapdf/layout/box_fitter.rb', line 65

def fit_results
  @fit_results
end

#framesObject (readonly)

The array of frames inside of which the boxes should be laid out.

Use #<< to add additional frames.



61
62
63
# File 'lib/hexapdf/layout/box_fitter.rb', line 61

def frames
  @frames
end

#remaining_boxesObject (readonly)

The boxes that could not be fitted into the frames.



68
69
70
# File 'lib/hexapdf/layout/box_fitter.rb', line 68

def remaining_boxes
  @remaining_boxes
end

Instance Method Details

#<<(frame) ⇒ Object

Add the given frame to the list of frames.



83
84
85
86
87
# File 'lib/hexapdf/layout/box_fitter.rb', line 83

def <<(frame)
  @frames << frame
  @initial_frame_y << frame.y
  @content_heights << 0
end

#content_heightsObject

Returns an array with the heights of the content of each frame.



125
126
127
# File 'lib/hexapdf/layout/box_fitter.rb', line 125

def content_heights
  @content_heights
end

#fit(box) ⇒ Object

Fits the given box at the current location.



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
# File 'lib/hexapdf/layout/box_fitter.rb', line 90

def fit(box)
  unless @remaining_boxes.empty?
    @remaining_boxes << box
    return
  end

  while (current_frame = @frames[@frame_index])
    result = current_frame.fit(box)
    if result.success?
      current_frame.remove_area(result.mask)
      @content_heights[@frame_index] = [@content_heights[@frame_index],
                                        @initial_frame_y[@frame_index] - result.mask.y].max
      @fit_results << result
      box = nil
      break
    elsif current_frame.full?
      @frame_index += 1
    else
      draw_box, box = current_frame.split(result)
      if draw_box
        current_frame.remove_area(result.mask)
        @content_heights[@frame_index] = [@content_heights[@frame_index],
                                          @initial_frame_y[@frame_index] - result.mask.y].max
        @fit_results << result
        break unless box
      elsif !current_frame.find_next_region
        @frame_index += 1
      end
    end
  end

  @remaining_boxes << box if box
end

#success?Boolean

Returns true if all boxes were successfully fitted.

Returns:

  • (Boolean)


130
131
132
# File 'lib/hexapdf/layout/box_fitter.rb', line 130

def success?
  @remaining_boxes.empty?
end