Class: RComposite::LayerSet

Inherits:
Object
  • Object
show all
Defined in:
lib/rcomposite/layerset.rb

Direct Known Subclasses

Canvas

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, &block) ⇒ LayerSet

Returns a new instance of LayerSet.



6
7
8
9
10
11
12
13
# File 'lib/rcomposite/layerset.rb', line 6

def initialize(name, &block)
  @layers = []

  bounding_box
  @name = name

  self.instance_eval &block if block_given?
end

Instance Attribute Details

#bounding_heightObject (readonly)

Returns the value of attribute bounding_height.



4
5
6
# File 'lib/rcomposite/layerset.rb', line 4

def bounding_height
  @bounding_height
end

#bounding_widthObject (readonly)

Returns the value of attribute bounding_width.



4
5
6
# File 'lib/rcomposite/layerset.rb', line 4

def bounding_width
  @bounding_width
end

#layersObject

Returns the value of attribute layers.



3
4
5
# File 'lib/rcomposite/layerset.rb', line 3

def layers
  @layers
end

#max_xObject (readonly)

Returns the value of attribute max_x.



4
5
6
# File 'lib/rcomposite/layerset.rb', line 4

def max_x
  @max_x
end

#max_yObject (readonly)

Returns the value of attribute max_y.



4
5
6
# File 'lib/rcomposite/layerset.rb', line 4

def max_y
  @max_y
end

#min_xObject (readonly)

Returns the value of attribute min_x.



4
5
6
# File 'lib/rcomposite/layerset.rb', line 4

def min_x
  @min_x
end

#min_yObject (readonly)

Returns the value of attribute min_y.



4
5
6
# File 'lib/rcomposite/layerset.rb', line 4

def min_y
  @min_y
end

#nameObject (readonly)

Returns the value of attribute name.



4
5
6
# File 'lib/rcomposite/layerset.rb', line 4

def name
  @name
end

Instance Method Details

#add_layer(layer) ⇒ Object



110
111
112
113
# File 'lib/rcomposite/layerset.rb', line 110

def add_layer(layer)
  @layers << layer
  bounding_box
end

#adjustment_layer(type, *args, &block) ⇒ Object



67
68
69
70
71
72
73
74
75
# File 'lib/rcomposite/layerset.rb', line 67

def adjustment_layer(type, *args, &block) 
  layer = AdjustmentLayer.new type, *args
  @layers << layer

  # tie floating block methods (opacity, mode, offset, etc) to Layer object.
  layer.instance_eval &block if block_given?

  return layer
end

#bounding_boxObject



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
# File 'lib/rcomposite/layerset.rb', line 120

def bounding_box
  if @layers.size > 0
    x1 = []
    y1 = []
    x2 = []
    y2 = []
    @layers.each do |layer|
      x1 << layer.offset_x
      y1 << layer.offset_y
      x2 << layer.width + layer.offset_x 
      y2 << layer.height + layer.offset_y 
    end

    @min_x = x1.min
    @min_y = y1.min
    @max_x = x2.max
    @max_y = y2.max
    @bounding_width = @max_x - @min_x
    @bounding_height = @max_y - @min_y
  else
    @min_x = 0
    @min_y = 0
    @max_x = 0
    @max_y = 0
    @bounding_width = 0
    @boudning_height = 0
  end
end

#composite_layers(image, layers) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/rcomposite/layerset.rb', line 91

def composite_layers(image, layers) 
  layers.reverse.each do |layer| 
    case layer
      when RComposite::LayerSet
        image = composite_layers image, layer.layers
      when RComposite::Layer
        layer.merge_down image
    end     
  end     
  
  return image
end

#fill_layer(type, *args, &block) ⇒ Object



57
58
59
60
61
62
63
64
65
# File 'lib/rcomposite/layerset.rb', line 57

def fill_layer(type, *args, &block)
  layer = FillLayer.new type, *args
  @layers << layer

  # tie floating block methods (opacity, mode, offset, etc) to Layer object.
  layer.instance_eval &block if block_given?

  return layer
end

#flattenObject



77
78
79
80
81
82
83
84
85
# File 'lib/rcomposite/layerset.rb', line 77

def flatten
   flattened_image = render
   
   # clear layers and sets
   @layers.clear

   # only 1 flattened layer now   
   @layers << Layer.new(flattened_image)
end

#layer(options, &block) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/rcomposite/layerset.rb', line 41

def layer(options, &block) 
  if options.is_a? RComposite::Layer
    layer = options
  else
    layer = Layer.new options
  end

  # Add layer to render pipeline
  @layers << layer

  # tie floating block methods (opacity, mode, offset, etc) to Layer object.
  layer.instance_eval &block if block_given?

  return layer
end

#layer_set(ref, position = :bottom, &block) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/rcomposite/layerset.rb', line 19

def layer_set(ref, position = :bottom, &block) 
  if ref.is_a? RComposite::LayerSet
    # referencing a previously instanstiated LayerSet.
    set = ref 
  else    
    # creating a new LayerSet
    set = LayerSet.new ref  
  end     
  
  # Add layer set to render pipeline
  if position == :bottom
    @layers << set
  elsif position == :top
    @layers.unshift set
  end

  # tie floating block methods (layer, rotate, offset, etc) to LayerSet object.
  set.instance_eval &block if block_given?

  return set
end

#offset(x, y) ⇒ Object



149
150
151
152
153
154
155
156
157
# File 'lib/rcomposite/layerset.rb', line 149

def offset(x, y)
  bounding_box # recalculate bounding box
  shift_x = x - @min_x
  shift_y = y - @min_y
  @layers.each do |layer|
    layer.offset(layer.offset_x + shift_x, layer.offset_y + shift_y)
  end
  bounding_box
end

#remove_layer(layer) ⇒ Object



115
116
117
118
# File 'lib/rcomposite/layerset.rb', line 115

def remove_layer(layer)
  @layers.delete(layer)
  bounding_box
end

#renderObject



87
88
89
# File 'lib/rcomposite/layerset.rb', line 87

def render
  return composite_layers(@image.clone, @layers)
end

#rotate(degrees) ⇒ Object



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/rcomposite/layerset.rb', line 170

def rotate(degrees)
  bounding_box # recalculate bounding box
  bounding_mid_x = @bounding_width / 2
  bounding_mid_y = @bounding_height / 2
  @layers.each do |layer|
    layer_mid_x = (layer.width/2.0).round + layer.offset_x - @min_x - bounding_mid_x
    layer_mid_y = ((layer.height/2.0).round + layer.offset_y - @min_y - bounding_mid_y) * -1

    radians = (degrees * -1) / (180 / Math::PI)
    
    cos = Math.cos(radians)
    sin = Math.sin(radians)

    new_mid_x = ((layer_mid_x * cos) - (layer_mid_y * sin)).round
    new_mid_y = ((layer_mid_x * sin) + (layer_mid_y * cos)).round
  
    layer.rotate(degrees)

    new_offset_x = new_mid_x - (layer.width/2.0).round + @min_x + bounding_mid_x
    new_offset_y = new_mid_y * -1 - (layer.height/2.0).round + @min_y + bounding_mid_y

    layer.offset(new_offset_x, new_offset_y)
  end
  bounding_box
end

#save_as(filename) ⇒ Object



104
105
106
# File 'lib/rcomposite/layerset.rb', line 104

def save_as(filename)
  render.write(filename)
end

#scale(width, height) ⇒ Object



159
160
161
162
163
164
165
166
167
168
# File 'lib/rcomposite/layerset.rb', line 159

def scale(width, height)
  bounding_box # recalculate bounding box
  width_scale = width.to_f / bounding_width.to_f
  height_scale = height.to_f / bounding_height.to_f
  @layers.each do |layer|
    layer.image.scale!((layer.width * width_scale).round, (layer.height * height_scale).round) 
    layer.offset(((layer.offset_x - @min_x) * width_scale).round + @min_x, ((layer.offset_y - @min_y) * height_scale).round + @min_y)
  end
  bounding_box
end

#stack(&block) ⇒ Object



15
16
17
# File 'lib/rcomposite/layerset.rb', line 15

def stack(&block)
  self.instance_eval &block if block_given?
end