zena 0.16.3 → 0.16.4

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 (84) hide show
  1. data/.gitignore +1 -0
  2. data/History.txt +11 -0
  3. data/app/controllers/nodes_controller.rb +1 -1
  4. data/app/controllers/versions_controller.rb +1 -1
  5. data/app/controllers/virtual_classes_controller.rb +29 -2
  6. data/app/models/cached_page.rb +3 -3
  7. data/app/models/document.rb +1 -20
  8. data/app/models/iformat.rb +4 -4
  9. data/app/models/image.rb +1 -1
  10. data/app/models/image_content.rb +5 -5
  11. data/app/models/node.rb +25 -0
  12. data/app/models/text_document_version.rb +11 -3
  13. data/app/models/virtual_class.rb +50 -0
  14. data/app/views/{nodes → sites}/404.html +0 -0
  15. data/app/views/templates/edit_tabs/_image.rhtml +1 -1
  16. data/app/views/versions/_list.rhtml +3 -1
  17. data/app/views/virtual_classes/_li.erb +2 -2
  18. data/app/views/virtual_classes/index.erb +9 -1
  19. data/bricks/tags/patch/node.rb +1 -1
  20. data/config/bricks.yml +1 -1
  21. data/config/gems.yml +4 -2
  22. data/db/migrate/047_change_default_link_id_to_zero.rb +1 -1
  23. data/db/migrate/20090825201159_insert_zero_link.rb +1 -1
  24. data/lib/bricks.rb +2 -2
  25. data/lib/bricks/requirements_validation.rb +13 -8
  26. data/lib/gettext_strings.rb +1 -0
  27. data/lib/tasks/zena.rake +15 -6
  28. data/lib/zena.rb +9 -3
  29. data/lib/{base_additions.rb → zena/base_additions.rb} +0 -0
  30. data/lib/{core_ext → zena/core_ext}/date_time.rb +0 -0
  31. data/lib/{core_ext → zena/core_ext}/dir.rb +0 -0
  32. data/lib/zena/core_ext/file_utils.rb +13 -0
  33. data/lib/{core_ext → zena/core_ext}/fixnum.rb +0 -0
  34. data/lib/{core_ext → zena/core_ext}/string.rb +0 -0
  35. data/lib/zena/deploy.rb +1 -1
  36. data/lib/zena/deploy/start.html +1 -1
  37. data/lib/zena/deploy/template.rb +5 -1
  38. data/lib/{fix_rails_layouts.rb → zena/fix_rails_layouts.rb} +0 -0
  39. data/lib/zena/info.rb +2 -2
  40. data/lib/zena/routes.rb +1 -1
  41. data/lib/zena/use/fixtures.rb +1 -1
  42. data/lib/zena/use/html_tags.rb +3 -3
  43. data/lib/zena/use/image_builder.rb +329 -0
  44. data/lib/zena/use/query_comment.rb +96 -0
  45. data/lib/zena/use/query_node.rb +408 -0
  46. data/lib/zena/use/query_node_finders.rb +91 -0
  47. data/lib/zena/use/rendering.rb +2 -2
  48. data/lib/{webdav_adapter.rb → zena/webdav_adapter.rb} +0 -0
  49. data/locale/de/LC_MESSAGES/zena.mo +0 -0
  50. data/locale/de/zena.po +1456 -0
  51. data/locale/en/LC_MESSAGES/zena.mo +0 -0
  52. data/locale/en/zena.po +626 -1197
  53. data/locale/fr/LC_MESSAGES/zena.mo +0 -0
  54. data/locale/fr/zena.po +895 -1221
  55. data/locale/zena.pot +527 -1027
  56. data/public/calendar/lang/calendar-de-utf8.js +128 -0
  57. data/public/calendar/menuarrow.gif +0 -0
  58. data/public/stylesheets/admin.css +2 -1
  59. data/test/custom_queries/complex.host.yml +1 -1
  60. data/test/fixtures/files/vclasses.yml +12 -0
  61. data/test/functional/virtual_classes_controller_test.rb +9 -0
  62. data/test/helpers/{node_query → query_node}/basic.yml +0 -0
  63. data/test/helpers/{node_query → query_node}/comments.yml +0 -0
  64. data/test/helpers/{node_query → query_node}/complex.yml +0 -0
  65. data/test/helpers/{node_query → query_node}/filters.yml +0 -0
  66. data/test/helpers/{node_query → query_node}/relations.yml +0 -0
  67. data/test/helpers/{node_query_test.rb → query_node_test.rb} +1 -2
  68. data/test/integration/navigation_test.rb +2 -0
  69. data/test/test_helper.rb +1 -1
  70. data/test/test_zena.rb +1 -1
  71. data/test/unit/core_ext_test.rb +3 -3
  72. data/test/unit/iformat_test.rb +3 -3
  73. data/test/unit/image_builder_test.rb +34 -34
  74. data/test/unit/node_test.rb +15 -1
  75. data/test/unit/virtual_class_test.rb +106 -0
  76. data/test/unit/zena/use/upload_test.rb +3 -3
  77. data/vendor/plugins/gettext_i18n_rails/tasks/gettext_rails_i18n.rake +3 -3
  78. data/zena.gemspec +36 -29
  79. data/zena_console.rb +33 -0
  80. metadata +30 -23
  81. data/lib/comment_query.rb +0 -92
  82. data/lib/image_builder.rb +0 -325
  83. data/lib/zena/use/node_query_finders.rb +0 -494
  84. data/vendor/bricks/20070122-172926.txt +0 -282
@@ -3,7 +3,7 @@
3
3
  class ChangeDefaultLinkIdToZero < ActiveRecord::Migration
4
4
  def self.up
5
5
  Link.connection.execute "UPDATE #{Link.table_name} SET id = 0 WHERE id = -1"
6
- NodeQuery.insert_zero_link(Link)
6
+ Zena::Use::QueryNode.insert_zero_link(Link)
7
7
  end
8
8
 
9
9
  def self.down
@@ -1,6 +1,6 @@
1
1
  class InsertZeroLink < ActiveRecord::Migration
2
2
  def self.up
3
- NodeQuery.insert_zero_link(Link)
3
+ Zena::Use::QueryNode.insert_zero_link(Link)
4
4
  end
5
5
 
6
6
  def self.down
data/lib/bricks.rb CHANGED
@@ -1,5 +1,5 @@
1
- require File.join(File.dirname(__FILE__), '/bricks/requirements_validation')
2
- require File.join(File.dirname(__FILE__), '/bricks/loader')
1
+ require 'bricks/requirements_validation'
2
+ require 'bricks/loader'
3
3
 
4
4
  module Bricks
5
5
  extend Bricks::RequirementsValidation
@@ -3,17 +3,20 @@ require 'yaml'
3
3
  module Bricks
4
4
  module RequirementsValidation
5
5
  def requirement_errors(brick, requirements)
6
+ current_stderr = $stderr
7
+ $stderr = StringIO.new
6
8
  errors = []
7
9
  requirements.each do |k,v|
8
10
  case k
9
- when 'gem'
10
- v.split(',').each do |name|
11
- begin
12
- require name.strip
13
- rescue LoadError => err
14
- errors << "'#{name}' missing"
15
- end
16
- end
11
+ # bad idea, this is run before gem version configuration
12
+ # when 'gem'
13
+ # v.split(',').each do |name|
14
+ # begin
15
+ # require name.strip
16
+ # rescue LoadError => err
17
+ # errors << "'#{name}' missing"
18
+ # end
19
+ # end
17
20
  when 'file'
18
21
  v.split(',').each do |name|
19
22
  unless File.exist?("#{RAILS_ROOT}/#{name}")
@@ -28,6 +31,7 @@ module Bricks
28
31
  end
29
32
  end
30
33
  end
34
+ $stderr = current_stderr
31
35
  errors.empty? ? nil : errors
32
36
  end
33
37
 
@@ -37,6 +41,7 @@ module Bricks
37
41
  else
38
42
  raw_config = YAML.load_file("#{Zena::ROOT}/config/bricks.yml")[RAILS_ENV] || {}
39
43
  end
44
+
40
45
  config = {}
41
46
 
42
47
  raw_config.each do |brick, opts|
@@ -35,6 +35,7 @@ module Zena
35
35
  N_('site group')
36
36
  N_('btn_relation_add')
37
37
  N_('virtual_class_img')
38
+ N_('virtual_class_error_img')
38
39
  N_('btn_virtual_class_add')
39
40
 
40
41
  N_('posted by')
data/lib/tasks/zena.rake CHANGED
@@ -30,14 +30,14 @@ def symlink_assets(from, to)
30
30
  if File.exist?(trg) || File.symlink?(trg)
31
31
  File.unlink(trg)
32
32
  end
33
- FileUtils.ln_s(src, trg)
33
+ FileUtils.symlink_or_copy(src, trg)
34
34
  end
35
35
  else
36
36
  # ignore
37
37
  puts "Cannot install assets in #{to}/public/#{dir} (not a directory)"
38
38
  end
39
39
  else
40
- FileUtils.ln_s("#{from}/public/#{dir}", "#{to}/public/#{dir}")
40
+ FileUtils.symlink_or_copy("#{from}/public/#{dir}", "#{to}/public/#{dir}")
41
41
  end
42
42
  end
43
43
  end
@@ -440,11 +440,20 @@ namespace :zena do
440
440
  puts cmd
441
441
  system(cmd)
442
442
 
443
- system("#{Gem.win_platform? ? 'start' : 'open'} #{File.join(Zena::ROOT, 'lib/zena/deploy/start.html')}")
443
+ if RUBY_PLATFORM =~ /mswin32/
444
+ puts "\n\nOnce the server has started, you can open your web browser at:\n\n\n ====> http://localhost:3000 <====\n\n\n"
445
+ cmd = "ruby script/server -e #{ENV['RAILS_ENV']} -p 3000"
446
+ puts cmd
447
+ system cmd
448
+ else
449
+ cmd = "open #{File.join(Zena::ROOT, 'lib/zena/deploy/start.html').inspect}"
450
+ puts cmd
451
+ system(cmd)
444
452
 
445
- cmd = "script/server -e #{ENV['RAILS_ENV']} -p 3211"
446
- puts cmd
447
- exec cmd
453
+ cmd = "ruby script/server -e #{ENV['RAILS_ENV']} -p 3000"
454
+ puts cmd
455
+ exec cmd
456
+ end
448
457
  end
449
458
 
450
459
  end
data/lib/zena.rb CHANGED
@@ -5,6 +5,7 @@ require 'fileutils'
5
5
  require File.join(File.dirname(__FILE__), 'zena', 'info')
6
6
 
7
7
  def has_executable(*list)
8
+ return false if RUBY_PLATFORM =~ /mswin32/
8
9
  list.inject(true) do |s,e|
9
10
  s && !(`which #{e} || echo 'no #{e}'` =~ /^no #{e}/)
10
11
  end
@@ -50,7 +51,7 @@ module Zena
50
51
  end
51
52
 
52
53
  # FIXME: make this explicit in models
53
- ActiveRecord::Base.send :include, Zena::Use::NodeQueryFinders::AddUseNodeQueryMethod
54
+ ActiveRecord::Base.send :include, Zena::Use::QueryNodeFinders::AddUseQueryNodeMethod
54
55
  ActiveRecord::Base.send :include, Zena::Acts::Secure
55
56
  ActionController::Base.send :include, Zena::Acts::Secure
56
57
 
@@ -87,6 +88,11 @@ module Zena
87
88
  gem_configuration.each do |gem_name, gem_config|
88
89
  if gem_config
89
90
  if gem_config['optional']
91
+ if brick_name = gem_config['brick']
92
+ unless Bricks::CONFIG[brick_name]
93
+ next
94
+ end
95
+ end
90
96
  begin
91
97
  gem gem_name, gem_config['version']
92
98
  rescue LoadError
@@ -132,7 +138,7 @@ module Zena
132
138
 
133
139
  def load_custom_extensions
134
140
  #FIXME: cleanup all these hacks !
135
- lib_path = File.join(Zena::ROOT, 'lib')
141
+ lib_path = File.join(Zena::ROOT, 'lib/zena')
136
142
  Dir.foreach(File.join(lib_path, 'core_ext')) do |f|
137
143
  next unless f =~ /\.rb\Z/
138
144
  require File.join(lib_path, 'core_ext', f)
@@ -178,7 +184,6 @@ module Zena
178
184
  add_load_paths(config)
179
185
  config_gems(config)
180
186
  load_plugins if RAILS_ROOT != Zena::ROOT
181
- load_custom_extensions
182
187
  include_modules
183
188
  load_bricks
184
189
  set_default_timezone(config)
@@ -407,4 +412,5 @@ end
407
412
  Zena::EXT_TO_TYPE, Zena::TYPE_TO_EXT = make_hashes(EXT_TYPE)
408
413
  Zena.add_load_paths
409
414
  Zena.gems_setup
415
+ Zena.load_custom_extensions
410
416
  require 'rubyless'
File without changes
File without changes
File without changes
@@ -0,0 +1,13 @@
1
+ # This file provides a portable way to symlink, reverting to copy if symlinks are not supported.
2
+
3
+ FileUtils
4
+
5
+ if RUBY_PLATFORM =~ /mswin32/
6
+ class << FileUtils
7
+ alias symlink_or_copy cp_r
8
+ end
9
+ else
10
+ class << FileUtils
11
+ alias symlink_or_copy ln_s
12
+ end
13
+ end
File without changes
File without changes
data/lib/zena/deploy.rb CHANGED
@@ -121,7 +121,7 @@ Capistrano::Configuration.instance(:must_exist).load do
121
121
  end
122
122
 
123
123
  #========================== MANAGE HOST =========================#
124
- desc "create a new site"
124
+ desc "create a new site [-s host='...' -s pass='...' -s lang='...']"
125
125
  task :mksite, :roles => :app do
126
126
  run "#{in_current} rake zena:mksite HOST='#{self[:host]}' PASSWORD='#{self[:pass]}' RAILS_ENV='production' LANG='#{self[:lang] || 'en'}'"
127
127
  create_vhost
@@ -32,7 +32,7 @@ new PeriodicalExecuter(function(pe) {
32
32
  counter -= 1;
33
33
  if (counter == 0) {
34
34
  pe.stop();
35
- window.location.href = 'http://localhost:3211';
35
+ window.location.href = 'http://localhost:3000';
36
36
  } else {
37
37
  $('counter').update(counter);
38
38
  $('counter').show();
@@ -2,7 +2,11 @@ require 'digest/sha1'
2
2
  require 'zena/info'
3
3
  # This is a rails template to generate a basic zena application
4
4
 
5
- run 'rm public/index.html'
5
+ if RUBY_PLATFORM =~ /mswin32/
6
+ run "del public\\index.html"
7
+ else
8
+ run "rm public/index.html"
9
+ end
6
10
 
7
11
  gem 'zena', :version => Zena::VERSION
8
12
  route 'map.zen_routes'
data/lib/zena/info.rb CHANGED
@@ -5,11 +5,11 @@ end
5
5
 
6
6
  AUTHENTICATED_PREFIX = "oo"
7
7
  PASSWORD_SALT = "jf93jfnvnas09093nas0923" # type anything here (but change this line !)
8
- ZENA_CALENDAR_LANGS = ["en", "fr"] # FIXME: build this dynamically from existing files
8
+ ZENA_CALENDAR_LANGS = ["en", "fr", "de"] # FIXME: build this dynamically from existing files
9
9
  ENABLE_XSENDFILE = false
10
10
 
11
11
  module Zena
12
- VERSION = '0.16.3'
12
+ VERSION = '0.16.4'
13
13
  REVISION = 1336
14
14
  ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
15
15
  end
data/lib/zena/routes.rb CHANGED
@@ -52,7 +52,7 @@ module Zena
52
52
  :member => { :crop_form => :get }
53
53
 
54
54
  resources :relations
55
- resources :virtual_classes
55
+ resources :virtual_classes, :collection => {:import => :post}
56
56
  resources :sites,
57
57
  :member => { :clear_cache => :post }
58
58
  resources :comments,
@@ -131,7 +131,7 @@ module Zena
131
131
  unless File.exist?("#{SITES_ROOT}/test.host/public")
132
132
  FileUtils::mkpath("#{SITES_ROOT}/test.host/public")
133
133
  ['images', 'calendar', 'stylesheets', 'javascripts'].each do |dir|
134
- FileUtils.ln_s("../../../public/#{dir}", "#{SITES_ROOT}/test.host/public/#{dir}")
134
+ FileUtils.symlink_or_copy("../../../public/#{dir}", "#{SITES_ROOT}/test.host/public/#{dir}")
135
135
  end
136
136
  end
137
137
 
@@ -163,7 +163,7 @@ module Zena
163
163
 
164
164
  if opts[:mode] && (format = Iformat[opts[:mode]]) && format[:size] != :keep
165
165
  # resize image
166
- img = ImageBuilder.new(:path=>"#{RAILS_ROOT}/public#{res[:src]}", :width=>32, :height=>32)
166
+ img = Zena::Use::ImageBuilder.new(:path=>"#{RAILS_ROOT}/public#{res[:src]}", :width=>32, :height=>32)
167
167
  img.transform!(format)
168
168
  if (img.width == res[:width] && img.height == res[:height])
169
169
  # ignore mode
@@ -377,10 +377,10 @@ module Zena
377
377
  # else
378
378
  # "<a href='/login'>#{_('login')}</a>"
379
379
  # end
380
- link_to "login", login_url
380
+ link_to _("login"), login_url
381
381
  else
382
382
  # "<a href='/logout'>#{_('logout')}</a>"
383
- link_to "logout", logout_url
383
+ link_to _("logout"), logout_url
384
384
  end
385
385
  end
386
386
 
@@ -0,0 +1,329 @@
1
+ require 'tempfile'
2
+ require 'digest/sha1'
3
+ unless defined?(Magick)
4
+ begin
5
+ # this works on the deb box
6
+ require 'RMagick'
7
+ rescue LoadError
8
+ begin
9
+ # this works on my Mac
10
+ require 'rmagick'
11
+ rescue LoadError
12
+ puts "ImageMagick not found. Using dummy."
13
+ require 'ftools'
14
+ # Create a dummy magick module
15
+ module Magick
16
+ CenterGravity = OverCompositeOp = MaxRGB = NorthGravity = SouthGravity = nil
17
+ class << self
18
+ end
19
+ class ZenaDummy
20
+ def initialize(*a)
21
+ end
22
+ def method_missing(meth, *args)
23
+ # do nothing
24
+ end
25
+ end
26
+ class Image < ZenaDummy
27
+ end
28
+ class ImageList < ZenaDummy
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ module Zena
36
+ module Use
37
+ class ImageBuilder
38
+ DEFAULT_FORMATS = {
39
+ 'tiny' => { :name=>'tiny', :size=>:force, :width=>16, :height=>16 , :gravity=>Magick::CenterGravity },
40
+ 'mini' => { :name=>'mini', :size=>:force, :width=>32, :height=>32 , :gravity=>Magick::CenterGravity },
41
+ 'square' => { :name=>'square', :size=>:limit, :width=>180, :height=>180, :gravity=>Magick::CenterGravity },
42
+ 'med' => { :name=>'med', :size=>:limit, :width=>280, :height=>186, :gravity=>Magick::CenterGravity },
43
+ 'top' => { :name=>'top', :size=>:force, :width=>280, :height=>186, :gravity => Magick::NorthGravity },
44
+ 'low' => { :name=>'low', :size=>:force, :width=>280, :height=>186, :gravity => Magick::SouthGravity },
45
+ 'side' => { :name=>'side', :size=>:force, :width=>220, :height=>500, :gravity=>Magick::CenterGravity },
46
+ 'std' => { :name=>'std', :size=>:limit, :width=>600, :height=>400, :gravity=>Magick::CenterGravity },
47
+ 'pv' => { :name=>'pv', :size=>:force, :width=>70, :height=>70 , :gravity=>Magick::CenterGravity },
48
+ 'edit' => { :name=>'edit', :size=>:limit, :width=>400, :height=>400, :gravity=>Magick::CenterGravity },
49
+ 'full' => { :name=>'full', :size=>:keep , :gravity=>Magick::CenterGravity },
50
+ nil => { :name=>'full', :size=>:keep , :gravity=>Magick::CenterGravity },
51
+ }.freeze
52
+ # 'sepia'=> { :size=>:limit, :width=>280, :ratio=>2/3.0, :post=>Proc.new {|img| img.sepiatone(Magick::MaxRGB * 0.8)}},
53
+
54
+ class << self
55
+ def image_content_type?(content_type)
56
+ content_type =~ /image/
57
+ end
58
+
59
+ def dummy?
60
+ Magick.const_defined?(:ZenaDummy)
61
+ end
62
+
63
+ def hash_id(format)
64
+ Digest::SHA1.hexdigest("#{format[:name]}#{format[:size]}#{format[:width]}#{format[:height]}#{format[:gravity]}")[0..9].to_i(16)
65
+ end
66
+
67
+ DEFAULT_FORMATS.each do |k, v|
68
+ v[:hash_id] = Zena::Use::ImageBuilder.hash_id(v)
69
+ v.freeze
70
+ end
71
+ end
72
+
73
+ def initialize(h)
74
+ params = {:height=>nil, :width=>nil, :path=>nil, :file=>nil, :actions=>[]}.merge(h)
75
+
76
+ params.each do |k,v|
77
+ case k
78
+ when :height
79
+ @height = v if v
80
+ when :width
81
+ @width = v if v
82
+ when :path
83
+ @path = v if v
84
+ when :file
85
+ @file = v if v
86
+ when :actions
87
+ if v.kind_of?(Array)
88
+ @actions = v
89
+ else
90
+ raise StandardError, "Bad actions format"
91
+ end
92
+ else
93
+ raise StandardError, "Bad parameter (#{k})"
94
+ end
95
+ end
96
+ unless @width && @height || dummy?
97
+ if @img = build_image_from_file_or_path
98
+ @width = @img.columns
99
+ @height = @img.rows
100
+ end
101
+ end
102
+ end
103
+
104
+ def dummy?
105
+ Zena::Use::ImageBuilder.dummy? || (!@path && !@img && !@file)
106
+ end
107
+
108
+ def read
109
+ return nil if dummy?
110
+ render_img
111
+ @img.to_blob
112
+ end
113
+
114
+ def write(path)
115
+ return false if dummy?
116
+ render_img
117
+ @img.write(path)
118
+ end
119
+
120
+ def rows
121
+ return nil unless @height || !dummy?
122
+ (@height ||= render_img.rows).round
123
+ end
124
+
125
+ def columns
126
+ return nil unless @width || !dummy?
127
+ (@width ||= render_img.columns).round
128
+ end
129
+
130
+ alias height rows
131
+ alias width columns
132
+
133
+ def resize!(s)
134
+ # we do not zoom pixels
135
+ return unless s < 1.0
136
+ @img = nil # reset current rendered image
137
+ @width *= s
138
+ @height *= s
139
+ @actions << Proc.new {|img| img.resize!(s) }
140
+ end
141
+
142
+ def crop!(x,y,w,h)
143
+ @img = nil # reset current rendered image
144
+ @width = [@width -x, w].min
145
+ @height = [@height-y, h].min
146
+ @actions << Proc.new {|img| img.crop!(x,y,[@img.columns-x, w].min,[@img.rows-y, h].min, true) }
147
+ end
148
+
149
+ def format=(fmt)
150
+ return unless !dummy? && Magick.formats[fmt.upcase] =~ /w/
151
+ @actions << Proc.new {|img| img.format = fmt.upcase; img }
152
+ end
153
+
154
+ def format
155
+ render_img.format
156
+ end
157
+
158
+ def exif
159
+ @exif ||= ExifData.new(render_img.get_exif_by_entry)
160
+ end
161
+
162
+ def max_filesize=(size)
163
+ @actions << Proc.new {|img| do_limit!(size) }
164
+ end
165
+
166
+ def do_limit!(size)
167
+ return @img if @filesize <= size
168
+
169
+ # Check real size
170
+ tmp_path = Tempfile.new('tmp_img').path
171
+ @img.write('jpeg:' + tmp_path)
172
+
173
+ return @img if File.stat(tmp_path).size <= size
174
+
175
+ # Change type to JPG and quality to 80
176
+ if (@img.format == 'JPG' || @img.format == 'JPEG') && @img.quality > 80
177
+ @img.write('jpeg:' + tmp_path) { self.quality = 80 }
178
+ else
179
+ @img.format = 'JPG'
180
+ @img.write('jpeg:' + tmp_path) { self.quality = 80 }
181
+ end
182
+ ratio = File.stat(tmp_path).size.to_f / size
183
+
184
+ return @img = Magick::ImageList.new(tmp_path) if ratio <= 1.0
185
+
186
+ # Not enough ? Resize.
187
+ ratio = 1.0 / Math.sqrt(ratio)
188
+ @width *= ratio
189
+ @height *= ratio
190
+ @img.resize!(ratio)
191
+ @img
192
+ end
193
+
194
+ def crop_min!(w,h,gravity=Magick::CenterGravity)
195
+ @img = nil # reset current rendered image
196
+ @width = [@width ,w].min
197
+ @height = [@height,h].min
198
+ @actions << Proc.new {|img| img.crop!(gravity,[@img.columns,w].min,[@img.rows,h].min, true) }
199
+ end
200
+
201
+ def set_background!(opacity,w,h)
202
+ @img = nil # reset current rendered image
203
+ @width = [@width ,w].max
204
+ @height = [@height,h].max
205
+ @actions << Proc.new do |img|
206
+ bg = Magick::Image.new(w,h)
207
+ bg.opacity = opacity
208
+ bg.format = img.format
209
+ img = bg.composite(img, Magick::CenterGravity, Magick::OverCompositeOp)
210
+ end
211
+ end
212
+
213
+ # Transform into another format. If nil : do nothing.
214
+ def transform!(tformat=nil)
215
+ return self unless tformat
216
+ @img = nil
217
+ format = { :size=>:limit, :gravity=>Magick::CenterGravity }.merge(tformat)
218
+ @pre, @post = format[:pre], format[:post]
219
+
220
+ if format[:size] == :keep
221
+ h,w = @height, @width
222
+ else
223
+ h,w = format[:height], format[:width]
224
+ end
225
+ if format[:scale]
226
+ if h || w
227
+ # scale is a pre-zoom before crop
228
+ scale = format[:scale]
229
+ else
230
+ # we resize to scale
231
+ h,w = @height*format[:scale], @width*format[:scale]
232
+ # but we do not zoom
233
+ scale = 1.0
234
+ # ignore ':size' format if not height nor width was given
235
+ format[:size] = :force
236
+ end
237
+ else
238
+ scale = 1.0
239
+ end
240
+ if format[:ratio] && h && !w
241
+ w = h / format[:ratio]
242
+ elsif format[:ratio] && w && !h
243
+ h = w * format[:ratio]
244
+ end
245
+
246
+ pw,ph = @width, @height
247
+ if [w,h,pw,ph].include?(nil) || [w,h,pw,ph].min <= 0
248
+ # image size or thumb size is null (no image processing tool used, no idea on image size)
249
+ if format[:size] == :keep
250
+ @height, @width = nil, nil
251
+ else
252
+ @height, @width = h, w
253
+ end
254
+ return self
255
+ end
256
+
257
+ case format[:size]
258
+ when :force
259
+ crop_scale = [w.to_f/pw, h.to_f/ph].max
260
+ if crop_scale > 1.0
261
+ # we do not zoom. Fill with transparent background.
262
+ crop_min!(w,h,format[:gravity])
263
+ set_background!(Magick::MaxRGB, w, h)
264
+ else
265
+ resize!(crop_scale * scale)
266
+ crop_min!(w, h,format[:gravity])
267
+ end
268
+ when :force_no_crop
269
+ crop_scale = [w.to_f/pw, h.to_f/ph].min
270
+ resize!(crop_scale * scale)
271
+ crop_min!(w, h,format[:gravity])
272
+ set_background!(Magick::MaxRGB, w, h)
273
+ when :limit
274
+ crop_scale = [w.to_f/pw, h.to_f/ph].min
275
+ resize!(crop_scale * scale)
276
+ crop_min!(w, h,format[:gravity])
277
+ when :keep
278
+ end
279
+ self
280
+ end
281
+
282
+ def render_img
283
+ raise IOError, 'MagickDummy cannot render image' if Zena::Use::ImageBuilder.dummy?
284
+ unless @img
285
+ unless @img = build_image_from_file_or_path
286
+ raise IOError, 'Cannot render image without path or file'
287
+ end
288
+ if @pre
289
+ @pre = [@pre].flatten
290
+ @pre.each do |a|
291
+ @img = a.call(@img)
292
+ end
293
+ end
294
+
295
+ if @actions
296
+ @actions.each do |a|
297
+ @img = a.call(@img)
298
+ end
299
+ end
300
+
301
+ if @post
302
+ @post = [@post].flatten
303
+ @post.each do |a|
304
+ @img = a.call(@img)
305
+ end
306
+ end
307
+ end
308
+ @img
309
+ end
310
+
311
+ def build_image_from_file_or_path
312
+ if @file || @path
313
+ if @file.kind_of?(StringIO)
314
+ img = Magick::ImageList.new
315
+ @file.rewind
316
+ img.from_blob(@file.read)
317
+ @file.rewind
318
+ @filesize = @file.size
319
+ img
320
+ else
321
+ img = Magick::ImageList.new(@file ? @file.path : @path)
322
+ @filesize = img.filesize
323
+ img
324
+ end
325
+ end
326
+ end
327
+ end # ImageBuilder
328
+ end # Use
329
+ end # Zena