rabbit 3.0.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/data/locale/en/LC_MESSAGES/rabbit.mo +0 -0
  3. data/data/locale/ja/LC_MESSAGES/rabbit.mo +0 -0
  4. data/doc/_config.yml +2 -2
  5. data/doc/en/faq.rd +4 -2
  6. data/doc/en/news.rd +91 -0
  7. data/doc/en/sample/hiki/rabbit.hiki +0 -4
  8. data/doc/en/sample/rd/rabbit.rd +0 -4
  9. data/doc/en/usage/rabbit-slide.rd +3 -3
  10. data/doc/index.html.en +1 -1
  11. data/doc/ja/faq.rd +2 -0
  12. data/doc/ja/news.rd +90 -0
  13. data/doc/ja/sample/hiki/rabbit.hiki +0 -4
  14. data/doc/ja/sample/rd/rabbit.rd +0 -4
  15. data/doc/ja/usage/rabbit-slide.rd +3 -3
  16. data/doc/ja/users.rd +7 -0
  17. data/lib/rabbit/action/toggle.rb +7 -0
  18. data/lib/rabbit/author-configuration.rb +3 -4
  19. data/lib/rabbit/canvas.rb +11 -1
  20. data/lib/rabbit/command/rabbit-slide.rb +59 -1
  21. data/lib/rabbit/command/rabbit-slide.ui +127 -49
  22. data/lib/rabbit/command/rabbit.rb +5 -9
  23. data/lib/rabbit/element/image.rb +78 -94
  24. data/lib/rabbit/element/video.rb +3 -11
  25. data/lib/rabbit/error.rb +2 -2
  26. data/lib/rabbit/frame.rb +102 -4
  27. data/lib/rabbit/gem-pusher.rb +28 -6
  28. data/lib/rabbit/image/base.rb +97 -26
  29. data/lib/rabbit/image/dia.rb +21 -6
  30. data/lib/rabbit/image/pdf.rb +1 -4
  31. data/lib/rabbit/image/svg.rb +1 -4
  32. data/lib/rabbit/image.rb +3 -4
  33. data/lib/rabbit/info-window.rb +106 -80
  34. data/lib/rabbit/keys.rb +6 -0
  35. data/lib/rabbit/menu.rb +2 -0
  36. data/lib/rabbit/parser/ext/charty.rb +58 -0
  37. data/lib/rabbit/parser/ext/image.rb +2 -1
  38. data/lib/rabbit/parser/rd/ext/block-verbatim.rb +13 -5
  39. data/lib/rabbit/progress.rb +1 -1
  40. data/lib/rabbit/properties.rb +141 -0
  41. data/lib/rabbit/rabbit.rb +3 -1
  42. data/lib/rabbit/relative-size.rb +28 -0
  43. data/lib/rabbit/renderer/base.rb +6 -0
  44. data/lib/rabbit/renderer/display/drawing-area-base.rb +0 -1
  45. data/lib/rabbit/renderer/display/drawing-area-primitive.rb +1 -0
  46. data/lib/rabbit/renderer/display/info.rb +6 -1
  47. data/lib/rabbit/renderer/display/key-handler.rb +27 -2
  48. data/lib/rabbit/renderer/engine/cairo.rb +24 -3
  49. data/lib/rabbit/renderer/screen.rb +0 -1
  50. data/lib/rabbit/slide-configuration.rb +12 -8
  51. data/lib/rabbit/task/slide.rb +3 -3
  52. data/lib/rabbit/theme/clear-blue/clear-blue.rb +3 -1
  53. data/lib/rabbit/theme/edge-info-toolkit/edge-info-toolkit.rb +12 -2
  54. data/lib/rabbit/theme/image-slide-number/image-slide-number.rb +1 -1
  55. data/lib/rabbit/theme/slide-footer-info/slide-footer-info.rb +2 -0
  56. data/lib/rabbit/theme/tag/tag.rb +9 -2
  57. data/lib/rabbit/theme-configuration.rb +3 -4
  58. data/lib/rabbit/version.rb +1 -1
  59. data/lib/rabbit/video-window.rb +14 -3
  60. data/lib/rabbit/yaml-loader.rb +39 -0
  61. data/po/en/rabbit.edit.po +82 -64
  62. data/po/en/rabbit.po +16 -2
  63. data/po/fr/rabbit.edit.po +81 -63
  64. data/po/fr/rabbit.po +15 -1
  65. data/po/ja/rabbit.edit.po +108 -65
  66. data/po/ja/rabbit.po +19 -3
  67. data/sample/can_rabbit.rd +0 -24
  68. data/sample/rabbit-en.hiki +0 -4
  69. data/sample/rabbit-en.rd +0 -4
  70. data/sample/rabbit.hiki +0 -4
  71. data/sample/rabbit.rd +0 -4
  72. data/test/test-slide-configuration.rb +3 -2
  73. metadata +27 -24
data/lib/rabbit/frame.rb CHANGED
@@ -2,13 +2,16 @@ require "forwardable"
2
2
  require "rabbit/gtk"
3
3
  require "rexml/text"
4
4
 
5
+ begin
6
+ require "vte3"
7
+ rescue LoadError
8
+ end
9
+
5
10
  require "rabbit/rabbit"
6
11
  require "rabbit/utils"
7
12
 
8
13
  module Rabbit
9
-
10
14
  class Frame
11
-
12
15
  include ScreenInfo
13
16
  extend Forwardable
14
17
 
@@ -31,6 +34,9 @@ module Rabbit
31
34
  @logger = logger
32
35
  @canvas = canvas
33
36
  @geometry = nil
37
+ @notebook = nil
38
+ @terminal = nil
39
+ @running = true
34
40
  end
35
41
 
36
42
  def destroyed?
@@ -38,6 +44,7 @@ module Rabbit
38
44
  end
39
45
 
40
46
  def quit
47
+ @running = false
41
48
  @window.destroy unless destroyed?
42
49
  @window = nil
43
50
  true
@@ -87,6 +94,8 @@ module Rabbit
87
94
  init_window(width, height, window_type)
88
95
  @fullscreen = false
89
96
  @main_window = main_window
97
+ @terminal.show if @terminal
98
+ @notebook.show if @notebook
90
99
  @window.show
91
100
  @canvas.post_init_gui
92
101
  end
@@ -99,6 +108,21 @@ module Rabbit
99
108
  true
100
109
  end
101
110
 
111
+ def toggle_terminal
112
+ return if @terminal.nil?
113
+ terminal_page = @notebook.page_num(@terminal)
114
+ if @notebook.current_page == terminal_page
115
+ @notebook.current_page = 0
116
+ else
117
+ @notebook.current_page = terminal_page
118
+ end
119
+ end
120
+
121
+ def in_terminal?
122
+ return false if @terminal.nil?
123
+ @notebook.current_page == @notebook.page_num(@terminal)
124
+ end
125
+
102
126
  private
103
127
  def init_window(width, height, window_type=nil)
104
128
  window_type ||= :toplevel
@@ -106,9 +130,29 @@ module Rabbit
106
130
  @window.set_default_size(width, height)
107
131
  @window.parse_geometry(@geometry) if @geometry
108
132
  @window.set_app_paintable(true)
133
+ if defined?(Vte::Terminal)
134
+ init_notebook
135
+ end
109
136
  set_window_signal
110
137
  setup_dnd
111
- @canvas.attach_to(self, @window)
138
+ @canvas.attach_to(self, @window, @notebook)
139
+ if defined?(Vte::Terminal)
140
+ init_terminal
141
+ end
142
+ end
143
+
144
+ def init_notebook
145
+ @notebook = Gtk::Notebook.new
146
+ @notebook.show_tabs = false
147
+ provider = Gtk::CssProvider.new
148
+ provider.load(data: <<-CSS)
149
+ notebook {
150
+ border-width: 0px;
151
+ }
152
+ CSS
153
+ @notebook.style_context.add_provider(provider,
154
+ Gtk::StyleProvider::PRIORITY_USER)
155
+ @window.add(@notebook)
112
156
  end
113
157
 
114
158
  def set_window_signal
@@ -160,6 +204,47 @@ module Rabbit
160
204
  true
161
205
  end
162
206
  end
207
+
208
+ def init_terminal
209
+ @terminal = Vte::Terminal.new
210
+ # TODO: Support theme
211
+ terminal_font_description = ENV["RABBIT_TERMINAL_FONT_DESCRIPTION"]
212
+ if terminal_font_description
213
+ @terminal.font_desc =
214
+ Pango::FontDescription.new(terminal_font_description)
215
+ end
216
+ terminal_color_foreground = ENV["RABBIT_TERMINAL_COLOR_FOREGROUND"]
217
+ if terminal_color_foreground
218
+ @terminal.color_foreground = terminal_color_foreground
219
+ end
220
+ terminal_color_background = ENV["RABBIT_TERMINAL_COLOR_BACKGROUND"]
221
+ if terminal_color_background
222
+ @terminal.color_background = terminal_color_background
223
+ end
224
+ @terminal.enable_sixel = true if @terminal.respond_to?(:enable_sixel=)
225
+ @notebook.add(@terminal)
226
+ pid = nil
227
+ in_terminal = false
228
+ @notebook.signal_connect(:switch_page) do |_, page,|
229
+ if page == @terminal
230
+ if @running
231
+ pid = @terminal.spawn if pid.nil?
232
+ @canvas.pre_terminal unless in_terminal
233
+ in_terminal = true
234
+ end
235
+ else
236
+ @canvas.post_terminal if in_terminal
237
+ in_terminal = false
238
+ end
239
+ end
240
+ @terminal.signal_connect(:child_exited) do
241
+ pid = nil
242
+ terminal_page = @notebook.page_num(@terminal)
243
+ if @notebook.current_page == terminal_page
244
+ @canvas.activate("ToggleTerminal")
245
+ end
246
+ end
247
+ end
163
248
  end
164
249
 
165
250
  class NullFrame
@@ -184,10 +269,16 @@ module Rabbit
184
269
  def iconify_available?
185
270
  false
186
271
  end
272
+
273
+ def toggle_terminal
274
+ end
275
+
276
+ def in_terminal?
277
+ false
278
+ end
187
279
  end
188
280
 
189
281
  class EmbedFrame < Frame
190
-
191
282
  def update_title(new_title)
192
283
  end
193
284
 
@@ -199,6 +290,13 @@ module Rabbit
199
290
  false
200
291
  end
201
292
 
293
+ def toggle_terminal
294
+ end
295
+
296
+ def in_terminal?
297
+ false
298
+ end
299
+
202
300
  def init_gui(width, height, main_window, window_type=nil)
203
301
  @window = Gtk::EventBox.new
204
302
  @window.set_size_request(width, height)
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2016 Kouhei Sutou <kou@cozmixng.org>
1
+ # Copyright (C) 2016-2021 Sutou Kouhei <kou@cozmixng.org>
2
2
  #
3
3
  # This program is free software; you can redistribute it and/or modify
4
4
  # it under the terms of the GNU General Public License as published by
@@ -15,11 +15,11 @@
15
15
  # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
16
 
17
17
  require "rake"
18
- require "yaml"
19
18
  require "open-uri"
20
19
 
21
20
  require "rabbit/gettext"
22
21
  require "rabbit/password-reader"
22
+ require "rabbit/yaml-loader"
23
23
 
24
24
  module Rabbit
25
25
  class GemPusher
@@ -35,7 +35,7 @@ module Rabbit
35
35
  credentials_path = File.expand_path("~/.gem/credentials")
36
36
  credentials_path_exist = File.exist?(credentials_path)
37
37
  if credentials_path_exist
38
- credentials = YAML.load(File.read(credentials_path))
38
+ credentials = YAMLLoader.load(File.read(credentials_path))
39
39
  else
40
40
  credentials = {}
41
41
  end
@@ -57,10 +57,32 @@ module Rabbit
57
57
  prompt = _("Enter password on RubyGems.org [%{user}]: ") % {:user => @user}
58
58
  reader = PasswordReader.new(prompt)
59
59
  password = reader.read
60
- open("https://rubygems.org/api/v1/api_key.yaml",
61
- :http_basic_authentication => [@user, password]) do |response|
62
- YAML.load(response.read)[:rubygems_api_key]
60
+ begin
61
+ URI.open("https://rubygems.org/api/v1/api_key.yaml",
62
+ :http_basic_authentication => [@user, password]) do |response|
63
+ YAMLLoader.load(response.read)[:rubygems_api_key]
64
+ end
65
+ rescue OpenURI::HTTPError => error
66
+ if mfa_error?(error)
67
+ prompt = _("Enter OTP on RubyGems.org [%{user}]: ") % {:user => @user}
68
+ # TODO: We don't need to hide input.
69
+ reader = PasswordReader.new(prompt)
70
+ otp = reader.read
71
+ URI.open("https://rubygems.org/api/v1/api_key.yaml",
72
+ :http_basic_authentication => [@user, password],
73
+ "OTP" => otp) do |response|
74
+ YAMLLoader.load(response.read)[:rubygems_api_key]
75
+ end
76
+ else
77
+ raise
78
+ end
63
79
  end
64
80
  end
81
+
82
+ def mfa_error?(error)
83
+ return false unless error.message.start_with?("401 ")
84
+ body = error.io.read
85
+ body.start_with?("You have enabled multifactor authentication")
86
+ end
65
87
  end
66
88
  end
@@ -1,7 +1,23 @@
1
+ # Copyright (C) 2004-2020 Sutou Kouhei <kou@cozmixng.org>
2
+ #
3
+ # This program is free software; you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation; either version 2 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License along
14
+ # with this program; if not, write to the Free Software Foundation, Inc.,
15
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
+
1
17
  require "gdk_pixbuf2"
2
18
 
3
- require "rabbit/utils"
4
19
  require "rabbit/image-data-loader"
20
+ require "rabbit/properties"
5
21
 
6
22
  module Rabbit
7
23
  module ImageManipulable
@@ -9,12 +25,16 @@ module Rabbit
9
25
  class Base
10
26
  extend ModuleLoader
11
27
 
12
- attr_reader :width, :height, :original_width, :original_height
28
+ attr_reader :filename
29
+ attr_reader :properties
30
+ attr_reader :original_width
31
+ attr_reader :original_height
13
32
  attr_reader :animation
14
33
 
15
34
  def initialize(filename, props)
16
35
  @filename = filename
17
- @props = normalize_props(props)
36
+ @properties = Properties.new(props)
37
+ initialize_keep_ratio
18
38
  @animation = nil
19
39
  @animation_iterator = nil
20
40
  @animation_timeout = nil
@@ -24,29 +44,57 @@ module Rabbit
24
44
  end
25
45
 
26
46
  def [](key)
27
- @props[normalize_prop_key(key)]
47
+ @properties[key]
28
48
  end
29
49
 
30
50
  def []=(key, value)
31
- @props[normalize_prop_key(key)] = value
51
+ @properties[key] = value
32
52
  end
33
53
 
34
- def keep_ratio
35
- self["keep_ratio"]
54
+ def keep_ratio?
55
+ @properties.keep_ratio
36
56
  end
57
+ # For backward compatibility
58
+ alias_method :keep_ratio, :keep_ratio?
37
59
 
38
60
  def keep_ratio=(value)
39
- self["keep_ratio"] = value
61
+ @properties.keep_ratio = value
40
62
  end
41
63
 
42
64
  def pixbuf
43
65
  @pixbuf
44
66
  end
45
67
 
68
+ def width
69
+ (relative_clip_width&.resolve(@width) || @width) -
70
+ (relative_clip_x&.resolve(@width) || 0)
71
+ end
72
+
73
+ def height
74
+ (relative_clip_height&.resolve(@height) || @height) -
75
+ (relative_clip_y&.resolve(@height) || 0)
76
+ end
77
+
78
+ def relative_clip_x
79
+ @properties.get_relative_size("relative_clip_x", @filename)
80
+ end
81
+
82
+ def relative_clip_y
83
+ @properties.get_relative_size("relative_clip_y", @filename)
84
+ end
85
+
86
+ def relative_clip_width
87
+ @properties.get_relative_size("relative_clip_width", @filename)
88
+ end
89
+
90
+ def relative_clip_height
91
+ @properties.get_relative_size("relative_clip_height", @filename)
92
+ end
93
+
46
94
  def resize(w, h)
47
95
  if w.nil? and h.nil?
48
96
  return
49
- elsif keep_ratio
97
+ elsif keep_ratio?
50
98
  if w and h.nil?
51
99
  h = (original_height * w.to_f / original_width).ceil
52
100
  elsif w.nil? and h
@@ -65,10 +113,7 @@ module Rabbit
65
113
  end
66
114
 
67
115
  def draw(canvas, x, y, params={})
68
- default_params = {
69
- :width => width,
70
- :height => height,
71
- }
116
+ default_params = default_draw_params(x, y)
72
117
  target_pixbuf = pixbuf
73
118
  if @animation_iterator
74
119
  @animation_iterator.advance
@@ -79,20 +124,15 @@ module Rabbit
79
124
  end
80
125
 
81
126
  private
82
- def normalize_props(props)
83
- normalized_props = {}
84
- (props || {}).each do |key, value|
85
- normalized_props[normalize_prop_key(key)] = value
86
- end
87
- keep_ratio_key = normalize_prop_key("keep_ratio")
88
- unless normalized_props.has_key?(keep_ratio_key)
89
- normalized_props[keep_ratio_key] = true
127
+ def initialize_keep_ratio
128
+ return unless @properties["keep_ratio"].nil?
129
+ # For backward compatibility
130
+ keep_scale = @properties["keep_scale"]
131
+ if keep_scale.nil?
132
+ @properties["keep_ratio"] = true
133
+ else
134
+ @properties["keep_ratio"] = keep_scale
90
135
  end
91
- normalized_props
92
- end
93
-
94
- def normalize_prop_key(key)
95
- key.to_s.gsub(/-/, "_")
96
136
  end
97
137
 
98
138
  def load_data(data)
@@ -129,6 +169,37 @@ module Rabbit
129
169
  end
130
170
  end
131
171
  end
172
+
173
+ def default_draw_params(x, y)
174
+ _relative_clip_x = relative_clip_x
175
+ _relative_clip_y = relative_clip_y
176
+ _relative_clip_width = relative_clip_width
177
+ _relative_clip_height = relative_clip_height
178
+ if _relative_clip_x or
179
+ _relative_clip_y or
180
+ _relative_clip_width or
181
+ _relative_clip_height
182
+ clip_x = _relative_clip_x&.resolve(@width) || 0
183
+ clip_y = _relative_clip_y&.resolve(@height) || 0
184
+ clip_width = _relative_clip_width&.resolve(@width) || @width
185
+ clip_height = _relative_clip_height&.resolve(@height) || @height
186
+ uncliped_width = width - (clip_width - clip_x) + @width
187
+ uncliped_height = height - (clip_height - clip_y) + @height
188
+ {
189
+ width: uncliped_width,
190
+ height: uncliped_height,
191
+ clip_x: x + clip_x,
192
+ clip_y: y + clip_y,
193
+ clip_width: clip_width,
194
+ clip_height: clip_height,
195
+ }
196
+ else
197
+ {
198
+ width: width,
199
+ height: height,
200
+ }
201
+ end
202
+ end
132
203
  end
133
204
  end
134
205
  end
@@ -1,6 +1,21 @@
1
+ # Copyright (C) 2004-2020 Sutou Kouhei <kou@cozmixng.org>
2
+ #
3
+ # This program is free software; you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation; either version 2 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License along
14
+ # with this program; if not, write to the Free Software Foundation, Inc.,
15
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
+
1
17
  require "forwardable"
2
18
 
3
- require "rabbit/utils"
4
19
  require "rabbit/image/base"
5
20
 
6
21
  module Rabbit
@@ -33,26 +48,26 @@ module Rabbit
33
48
  end
34
49
  end
35
50
 
36
- def_delegators(:@svg_loader, :keep_ratio, :keep_ratio=)
51
+ def_delegators(:@svg_loader, :keep_ratio, :keep_ratio?, :keep_ratio=)
37
52
  def_delegators(:@svg_loader, :pixbuf, :internal_pixbuf)
38
53
  def_delegators(:@svg_loader, :width, :height)
39
54
  def_delegators(:@svg_loader, :original_width, :original_height)
40
55
  def_delegators(:@svg_loader, :resize, :ensure_resize)
41
56
  def_delegators(:@svg_loader, :update_size)
42
57
 
43
- def initialize(filename, keep_ratio)
44
- init_svg_loader(filename, keep_ratio)
58
+ def initialize(filename, props)
59
+ init_svg_loader(filename, props)
45
60
  super
46
61
  end
47
62
 
48
63
  private
49
- def init_svg_loader(filename, keep_ratio)
64
+ def init_svg_loader(filename, props)
50
65
  @svg_file = Tempfile.new(["rabbit-loader-dia", ".svg"])
51
66
  args = ["--export=#{@svg_file.path}"]
52
67
  args << "--filter=svg"
53
68
  args << filename
54
69
  if DIA_COMMANDS.any? {|dia| run(dia, *args)}
55
- @svg_loader = SVG.new(@svg_file.path, keep_ratio)
70
+ @svg_loader = SVG.new(@svg_file.path, props)
56
71
  else
57
72
  raise DiaCanNotHandleError.new("dia #{args.join(' ')}",
58
73
  DIA_COMMANDS)
@@ -25,10 +25,7 @@ module Rabbit
25
25
 
26
26
  def draw(canvas, x, y, params={})
27
27
  if @document
28
- default_params = {
29
- :width => width,
30
- :height => height,
31
- }
28
+ default_params = default_draw_params(x, y)
32
29
  canvas.draw_poppler_page(page, x, y, default_params.merge(params))
33
30
  else
34
31
  super
@@ -42,10 +42,7 @@ module Rabbit
42
42
 
43
43
  def draw(canvas, x, y, params={})
44
44
  if @handle
45
- default_params = {
46
- :width => width,
47
- :height => height,
48
- }
45
+ default_params = default_draw_params(x, y)
49
46
  canvas.draw_rsvg_handle(@handle, x, y, default_params.merge(params))
50
47
  else
51
48
  super
data/lib/rabbit/image.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2004-2017 Kouhei Sutou <kou@cozmixng.org>
1
+ # Copyright (C) 2004-2020 Sutou Kouhei <kou@cozmixng.org>
2
2
  #
3
3
  # This program is free software; you can redistribute it and/or modify
4
4
  # it under the terms of the GNU General Public License as published by
@@ -16,7 +16,6 @@
16
16
 
17
17
  require "forwardable"
18
18
  require "tempfile"
19
- require 'thread'
20
19
 
21
20
  require "rabbit/image/default"
22
21
  require "rabbit/image/dia"
@@ -29,12 +28,13 @@ module Rabbit
29
28
  module ImageManipulable
30
29
  extend Forwardable
31
30
 
32
- def_delegators(:@loader, :keep_ratio, :keep_ratio=)
31
+ def_delegators(:@loader, :keep_ratio, :keep_ratio?, :keep_ratio=)
33
32
  def_delegators(:@loader, :x_aspect_ratio, :y_aspect_ratio)
34
33
  def_delegators(:@loader, :pixbuf, :width, :height)
35
34
  def_delegators(:@loader, :original_width, :original_height)
36
35
  def_delegators(:@loader, :resize, :draw)
37
36
  def_delegators(:@loader, :[], :[]=)
37
+ def_delegators(:@loader, :properties)
38
38
  alias_method :scale, :resize
39
39
 
40
40
  def initialize(filename, props=nil, *args, &block)
@@ -42,7 +42,6 @@ module Rabbit
42
42
  raise ImageFileDoesNotExistError.new(filename)
43
43
  end
44
44
  super(*args, &block)
45
- props = Utils.stringify_hash_key(props) if props
46
45
  @loader = Base.find_loader(filename).new(filename, props)
47
46
  end
48
47
  end