dragonfly 0.8.6 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of dragonfly might be problematic. Click here for more details.
- data/{.specopts → .rspec} +0 -1
- data/.yardopts +6 -2
- data/Gemfile +14 -13
- data/History.md +47 -9
- data/README.md +25 -5
- data/Rakefile +37 -79
- data/VERSION +1 -1
- data/dragonfly.gemspec +140 -89
- data/extra_docs/Analysers.md +8 -48
- data/extra_docs/Configuration.md +40 -25
- data/extra_docs/Couch.md +49 -0
- data/extra_docs/DataStorage.md +94 -24
- data/extra_docs/Encoding.md +6 -35
- data/extra_docs/ExampleUseCases.md +113 -0
- data/extra_docs/GeneralUsage.md +7 -23
- data/extra_docs/Generators.md +15 -49
- data/extra_docs/Heroku.md +7 -8
- data/extra_docs/ImageMagick.md +126 -0
- data/extra_docs/MimeTypes.md +3 -3
- data/extra_docs/Models.md +163 -0
- data/extra_docs/Mongo.md +1 -4
- data/extra_docs/Processing.md +7 -60
- data/extra_docs/Rails2.md +3 -1
- data/extra_docs/Rails3.md +2 -10
- data/extra_docs/ServingRemotely.md +83 -0
- data/extra_docs/Sinatra.md +3 -3
- data/extra_docs/URLs.md +60 -33
- data/features/rails_3.0.5.feature +8 -0
- data/features/steps/rails_steps.rb +7 -18
- data/features/support/env.rb +10 -37
- data/features/support/setup.rb +32 -0
- data/fixtures/rails_3.0.5/files/app/models/album.rb +5 -0
- data/fixtures/rails_3.0.5/files/app/views/albums/new.html.erb +7 -0
- data/fixtures/{files → rails_3.0.5/files}/app/views/albums/show.html.erb +2 -0
- data/fixtures/{files → rails_3.0.5/files}/config/initializers/dragonfly.rb +0 -0
- data/fixtures/rails_3.0.5/files/features/manage_album_images.feature +38 -0
- data/fixtures/rails_3.0.5/files/features/step_definitions/helper_steps.rb +7 -0
- data/fixtures/{files → rails_3.0.5/files}/features/step_definitions/image_steps.rb +11 -1
- data/fixtures/{files → rails_3.0.5/files}/features/support/paths.rb +2 -0
- data/fixtures/{files → rails_3.0.5/files}/features/text_images.feature +0 -0
- data/fixtures/{rails_3.0.3 → rails_3.0.5}/template.rb +2 -2
- data/irbrc.rb +2 -1
- data/lib/dragonfly.rb +7 -0
- data/lib/dragonfly/active_model_extensions/attachment.rb +134 -46
- data/lib/dragonfly/active_model_extensions/attachment_class_methods.rb +144 -0
- data/lib/dragonfly/active_model_extensions/class_methods.rb +62 -9
- data/lib/dragonfly/active_model_extensions/instance_methods.rb +2 -2
- data/lib/dragonfly/active_model_extensions/validations.rb +10 -6
- data/lib/dragonfly/analyser.rb +0 -1
- data/lib/dragonfly/analysis/file_command_analyser.rb +1 -1
- data/lib/dragonfly/analysis/image_magick_analyser.rb +2 -43
- data/lib/dragonfly/app.rb +64 -55
- data/lib/dragonfly/config/heroku.rb +1 -1
- data/lib/dragonfly/config/image_magick.rb +2 -37
- data/lib/dragonfly/config/rails.rb +5 -2
- data/lib/dragonfly/configurable.rb +115 -35
- data/lib/dragonfly/core_ext/object.rb +1 -1
- data/lib/dragonfly/core_ext/string.rb +1 -1
- data/lib/dragonfly/data_storage/couch_data_store.rb +84 -0
- data/lib/dragonfly/data_storage/file_data_store.rb +43 -18
- data/lib/dragonfly/data_storage/mongo_data_store.rb +8 -4
- data/lib/dragonfly/data_storage/s3data_store.rb +82 -38
- data/lib/dragonfly/encoding/image_magick_encoder.rb +2 -53
- data/lib/dragonfly/function_manager.rb +4 -2
- data/lib/dragonfly/generation/image_magick_generator.rb +2 -136
- data/lib/dragonfly/hash_with_css_style_keys.rb +21 -0
- data/lib/dragonfly/image_magick/analyser.rb +51 -0
- data/lib/dragonfly/image_magick/config.rb +44 -0
- data/lib/dragonfly/{encoding/r_magick_encoder.rb → image_magick/encoder.rb} +10 -14
- data/lib/dragonfly/image_magick/generator.rb +145 -0
- data/lib/dragonfly/image_magick/processor.rb +104 -0
- data/lib/dragonfly/image_magick/utils.rb +72 -0
- data/lib/dragonfly/image_magick_utils.rb +2 -79
- data/lib/dragonfly/job.rb +152 -90
- data/lib/dragonfly/middleware.rb +5 -19
- data/lib/dragonfly/processing/image_magick_processor.rb +2 -95
- data/lib/dragonfly/rails/images.rb +15 -10
- data/lib/dragonfly/response.rb +26 -12
- data/lib/dragonfly/serializer.rb +1 -4
- data/lib/dragonfly/server.rb +103 -0
- data/lib/dragonfly/temp_object.rb +56 -101
- data/lib/dragonfly/url_mapper.rb +78 -0
- data/spec/dragonfly/active_model_extensions/model_spec.rb +772 -65
- data/spec/dragonfly/active_model_extensions/spec_helper.rb +90 -10
- data/spec/dragonfly/analyser_spec.rb +1 -1
- data/spec/dragonfly/analysis/file_command_analyser_spec.rb +5 -14
- data/spec/dragonfly/app_spec.rb +35 -180
- data/spec/dragonfly/configurable_spec.rb +259 -18
- data/spec/dragonfly/core_ext/string_spec.rb +2 -2
- data/spec/dragonfly/core_ext/symbol_spec.rb +1 -1
- data/spec/dragonfly/data_storage/couch_data_store_spec.rb +84 -0
- data/spec/dragonfly/data_storage/file_data_store_spec.rb +149 -22
- data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +21 -2
- data/spec/dragonfly/data_storage/s3_data_store_spec.rb +207 -43
- data/spec/dragonfly/data_storage/{data_store_spec.rb → shared_data_store_examples.rb} +16 -15
- data/spec/dragonfly/function_manager_spec.rb +2 -2
- data/spec/dragonfly/{generation/hash_with_css_style_keys_spec.rb → hash_with_css_style_keys_spec.rb} +2 -2
- data/spec/dragonfly/{analysis/shared_analyser_spec.rb → image_magick/analyser_spec.rb} +19 -6
- data/spec/dragonfly/{encoding/image_magick_encoder_spec.rb → image_magick/encoder_spec.rb} +2 -2
- data/spec/dragonfly/image_magick/generator_spec.rb +172 -0
- data/spec/dragonfly/{processing/shared_processing_spec.rb → image_magick/processor_spec.rb} +55 -6
- data/spec/dragonfly/image_magick/utils_spec.rb +18 -0
- data/spec/dragonfly/job_builder_spec.rb +1 -1
- data/spec/dragonfly/job_definitions_spec.rb +1 -1
- data/spec/dragonfly/job_endpoint_spec.rb +26 -3
- data/spec/dragonfly/job_spec.rb +426 -208
- data/spec/dragonfly/loggable_spec.rb +2 -2
- data/spec/dragonfly/middleware_spec.rb +5 -26
- data/spec/dragonfly/routed_endpoint_spec.rb +1 -1
- data/spec/dragonfly/serializer_spec.rb +1 -14
- data/spec/dragonfly/server_spec.rb +261 -0
- data/spec/dragonfly/simple_cache_spec.rb +1 -1
- data/spec/dragonfly/temp_object_spec.rb +84 -130
- data/spec/dragonfly/url_mapper_spec.rb +130 -0
- data/spec/functional/deprecations_spec.rb +51 -0
- data/spec/functional/image_magick_app_spec.rb +27 -0
- data/spec/functional/model_urls_spec.rb +85 -0
- data/spec/functional/remote_on_the_fly_spec.rb +51 -0
- data/spec/functional/to_response_spec.rb +31 -0
- data/spec/spec_helper.rb +12 -22
- data/spec/{argument_matchers.rb → support/argument_matchers.rb} +0 -0
- data/spec/{image_matchers.rb → support/image_matchers.rb} +4 -4
- data/spec/support/simple_matchers.rb +53 -0
- data/yard/handlers/configurable_attr_handler.rb +2 -2
- data/yard/templates/default/fulldoc/html/css/common.css +12 -10
- data/yard/templates/default/layout/html/layout.erb +6 -0
- metadata +267 -308
- data/Gemfile.rails.2.3.5 +0 -20
- data/features/3.0.3.feature +0 -8
- data/features/rails_2.3.5.feature +0 -7
- data/fixtures/files/app/models/album.rb +0 -3
- data/fixtures/files/app/views/albums/new.html.erb +0 -4
- data/fixtures/files/features/manage_album_images.feature +0 -12
- data/fixtures/rails_2.3.5/template.rb +0 -10
- data/lib/dragonfly/analysis/r_magick_analyser.rb +0 -63
- data/lib/dragonfly/config/r_magick.rb +0 -46
- data/lib/dragonfly/generation/hash_with_css_style_keys.rb +0 -23
- data/lib/dragonfly/generation/r_magick_generator.rb +0 -155
- data/lib/dragonfly/processing/r_magick_processor.rb +0 -126
- data/lib/dragonfly/r_magick_utils.rb +0 -48
- data/lib/dragonfly/simple_endpoint.rb +0 -76
- data/spec/dragonfly/active_model_extensions/active_model_setup.rb +0 -97
- data/spec/dragonfly/active_model_extensions/active_record_setup.rb +0 -85
- data/spec/dragonfly/analysis/image_magick_analyser_spec.rb +0 -15
- data/spec/dragonfly/analysis/r_magick_analyser_spec.rb +0 -31
- data/spec/dragonfly/config/r_magick_spec.rb +0 -29
- data/spec/dragonfly/encoding/r_magick_encoder_spec.rb +0 -41
- data/spec/dragonfly/generation/image_magick_generator_spec.rb +0 -12
- data/spec/dragonfly/generation/r_magick_generator_spec.rb +0 -28
- data/spec/dragonfly/generation/shared_generator_spec.rb +0 -91
- data/spec/dragonfly/image_magick_utils_spec.rb +0 -16
- data/spec/dragonfly/processing/image_magick_processor_spec.rb +0 -29
- data/spec/dragonfly/processing/r_magick_processor_spec.rb +0 -30
- data/spec/dragonfly/simple_endpoint_spec.rb +0 -97
- data/spec/simple_matchers.rb +0 -44
@@ -12,6 +12,8 @@ module Dragonfly
|
|
12
12
|
configurable_attr :database, 'dragonfly'
|
13
13
|
configurable_attr :username
|
14
14
|
configurable_attr :password
|
15
|
+
configurable_attr :connection
|
16
|
+
configurable_attr :db
|
15
17
|
|
16
18
|
# Mongo gem deprecated ObjectID in favour of ObjectId
|
17
19
|
OBJECT_ID = defined?(BSON::ObjectId) ? BSON::ObjectId : BSON::ObjectID
|
@@ -23,12 +25,14 @@ module Dragonfly
|
|
23
25
|
self.database = opts[:database] if opts[:database]
|
24
26
|
self.username = opts[:username]
|
25
27
|
self.password = opts[:password]
|
28
|
+
self.connection = opts[:connection]
|
29
|
+
self.db = opts[:db]
|
26
30
|
end
|
27
31
|
|
28
32
|
def store(temp_object, opts={})
|
29
33
|
ensure_authenticated!
|
30
34
|
temp_object.file do |f|
|
31
|
-
mongo_id = grid.put(f, :metadata => marshal_encode(
|
35
|
+
mongo_id = grid.put(f, :metadata => marshal_encode(opts[:meta] || {}))
|
32
36
|
mongo_id.to_s
|
33
37
|
end
|
34
38
|
end
|
@@ -36,11 +40,11 @@ module Dragonfly
|
|
36
40
|
def retrieve(uid)
|
37
41
|
ensure_authenticated!
|
38
42
|
grid_io = grid.get(bson_id(uid))
|
39
|
-
|
40
|
-
|
43
|
+
meta = marshal_decode(grid_io.metadata)
|
44
|
+
meta.merge!(:stored_at => grid_io.upload_date)
|
41
45
|
[
|
42
46
|
grid_io.read,
|
43
|
-
|
47
|
+
meta
|
44
48
|
]
|
45
49
|
rescue Mongo::GridFileNotFound, INVALID_OBJECT_ID => e
|
46
50
|
raise DataNotFound, "#{e} - #{uid}"
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'fog'
|
2
2
|
|
3
3
|
module Dragonfly
|
4
4
|
module DataStorage
|
@@ -6,88 +6,132 @@ module Dragonfly
|
|
6
6
|
class S3DataStore
|
7
7
|
|
8
8
|
include Configurable
|
9
|
-
include AWS::S3
|
10
9
|
include Serializer
|
11
10
|
|
12
11
|
configurable_attr :bucket_name
|
13
12
|
configurable_attr :access_key_id
|
14
13
|
configurable_attr :secret_access_key
|
15
14
|
configurable_attr :use_filesystem, true
|
15
|
+
configurable_attr :region
|
16
|
+
configurable_attr :storage_headers, {'x-amz-acl' => 'public-read'}
|
17
|
+
|
18
|
+
REGIONS = {
|
19
|
+
'us-east-1' => 's3.amazonaws.com', #default
|
20
|
+
'eu-west-1' => 's3-eu-west-1.amazonaws.com',
|
21
|
+
'ap-southeast-1' => 's3-ap-southeast-1.amazonaws.com',
|
22
|
+
'us-west-1' => 's3-us-west-1.amazonaws.com'
|
23
|
+
}
|
16
24
|
|
17
25
|
def initialize(opts={})
|
18
26
|
self.bucket_name = opts[:bucket_name]
|
19
27
|
self.access_key_id = opts[:access_key_id]
|
20
28
|
self.secret_access_key = opts[:secret_access_key]
|
21
|
-
|
22
|
-
|
23
|
-
def connect!
|
24
|
-
AWS::S3::Base.establish_connection!(
|
25
|
-
:access_key_id => access_key_id,
|
26
|
-
:secret_access_key => secret_access_key
|
27
|
-
)
|
28
|
-
end
|
29
|
-
|
30
|
-
def create_bucket!
|
31
|
-
Bucket.create(bucket_name) unless bucket_names.include?(bucket_name)
|
29
|
+
self.region = opts[:region]
|
32
30
|
end
|
33
31
|
|
34
32
|
def store(temp_object, opts={})
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
ensure_configured
|
34
|
+
ensure_bucket_initialized
|
35
|
+
|
36
|
+
meta = opts[:meta] || {}
|
37
|
+
headers = opts[:headers] || {}
|
38
|
+
uid = opts[:path] || generate_uid(meta[:name] || temp_object.original_filename || 'file')
|
39
|
+
|
38
40
|
if use_filesystem
|
39
41
|
temp_object.file do |f|
|
40
|
-
|
42
|
+
storage.put_object(bucket_name, uid, f, full_storage_headers(headers, meta))
|
41
43
|
end
|
42
44
|
else
|
43
|
-
|
45
|
+
storage.put_object(bucket_name, uid, temp_object.data, full_storage_headers(headers, meta))
|
44
46
|
end
|
47
|
+
|
45
48
|
uid
|
46
49
|
end
|
47
50
|
|
48
51
|
def retrieve(uid)
|
49
|
-
|
50
|
-
|
52
|
+
ensure_configured
|
53
|
+
response = storage.get_object(bucket_name, uid)
|
51
54
|
[
|
52
|
-
|
53
|
-
parse_s3_metadata(
|
55
|
+
response.body,
|
56
|
+
parse_s3_metadata(response.headers)
|
54
57
|
]
|
55
|
-
rescue
|
58
|
+
rescue Excon::Errors::NotFound => e
|
56
59
|
raise DataNotFound, "#{e} - #{uid}"
|
57
60
|
end
|
58
61
|
|
59
62
|
def destroy(uid)
|
60
|
-
|
61
|
-
|
62
|
-
rescue AWS::S3::NoSuchKey => e
|
63
|
+
storage.delete_object(bucket_name, uid)
|
64
|
+
rescue Excon::Errors::NotFound => e
|
63
65
|
raise DataNotFound, "#{e} - #{uid}"
|
64
66
|
end
|
65
67
|
|
68
|
+
def url_for(uid, opts={})
|
69
|
+
if opts && opts[:expires]
|
70
|
+
storage.get_object_url(bucket_name, uid, opts[:expires])
|
71
|
+
else
|
72
|
+
"http://#{bucket_name}.s3.amazonaws.com/#{uid}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def domain
|
77
|
+
REGIONS[get_region]
|
78
|
+
end
|
79
|
+
|
80
|
+
def storage
|
81
|
+
@storage ||= Fog::Storage.new(
|
82
|
+
:provider => 'AWS',
|
83
|
+
:aws_access_key_id => access_key_id,
|
84
|
+
:aws_secret_access_key => secret_access_key,
|
85
|
+
:region => region
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
89
|
+
def bucket_exists?
|
90
|
+
storage.get_bucket_location(bucket_name)
|
91
|
+
true
|
92
|
+
rescue Excon::Errors::NotFound => e
|
93
|
+
false
|
94
|
+
end
|
95
|
+
|
66
96
|
private
|
67
97
|
|
68
|
-
def
|
69
|
-
|
98
|
+
def ensure_configured
|
99
|
+
unless @configured
|
100
|
+
[:bucket_name, :access_key_id, :secret_access_key].each do |attr|
|
101
|
+
raise NotConfigured, "You need to configure #{self.class.name} with #{attr}" if send(attr).nil?
|
102
|
+
end
|
103
|
+
@configured = true
|
104
|
+
end
|
70
105
|
end
|
71
106
|
|
72
|
-
def
|
73
|
-
unless @
|
74
|
-
|
75
|
-
|
76
|
-
@initialized = true
|
107
|
+
def ensure_bucket_initialized
|
108
|
+
unless @bucket_initialized
|
109
|
+
storage.put_bucket(bucket_name, 'LocationConstraint' => region) unless bucket_exists?
|
110
|
+
@bucket_initialized = true
|
77
111
|
end
|
78
112
|
end
|
79
113
|
|
114
|
+
def get_region
|
115
|
+
reg = region || 'us-east-1'
|
116
|
+
raise "Invalid region #{reg} - should be one of #{valid_regions.join(', ')}" unless valid_regions.include?(reg)
|
117
|
+
reg
|
118
|
+
end
|
119
|
+
|
80
120
|
def generate_uid(name)
|
81
121
|
"#{Time.now.strftime '%Y/%m/%d/%H/%M/%S'}/#{rand(1000)}/#{name.gsub(/[^\w.]+/, '_')}"
|
82
122
|
end
|
83
123
|
|
84
|
-
def
|
85
|
-
{'x-amz-meta-extra' => marshal_encode(
|
124
|
+
def full_storage_headers(headers, meta)
|
125
|
+
{'x-amz-meta-extra' => marshal_encode(meta)}.merge(storage_headers).merge(headers)
|
126
|
+
end
|
127
|
+
|
128
|
+
def parse_s3_metadata(headers)
|
129
|
+
encoded_meta = headers['x-amz-meta-extra']
|
130
|
+
(marshal_decode(encoded_meta) if encoded_meta) || {}
|
86
131
|
end
|
87
132
|
|
88
|
-
def
|
89
|
-
|
90
|
-
marshal_decode(extra_data) if extra_data
|
133
|
+
def valid_regions
|
134
|
+
REGIONS.keys
|
91
135
|
end
|
92
136
|
|
93
137
|
end
|
@@ -1,57 +1,6 @@
|
|
1
1
|
module Dragonfly
|
2
2
|
module Encoding
|
3
|
-
|
4
|
-
|
5
|
-
include Configurable
|
6
|
-
include ImageMagickUtils
|
7
|
-
|
8
|
-
configurable_attr :supported_formats, [
|
9
|
-
:ai,
|
10
|
-
:bmp,
|
11
|
-
:eps,
|
12
|
-
:gif,
|
13
|
-
:gif87,
|
14
|
-
:ico,
|
15
|
-
:j2c,
|
16
|
-
:jp2,
|
17
|
-
:jpeg,
|
18
|
-
:jpg,
|
19
|
-
:pbm,
|
20
|
-
:pcd,
|
21
|
-
:pct,
|
22
|
-
:pcx,
|
23
|
-
:pdf,
|
24
|
-
:pict,
|
25
|
-
:pjpeg,
|
26
|
-
:png,
|
27
|
-
:png24,
|
28
|
-
:png32,
|
29
|
-
:png8,
|
30
|
-
:pnm,
|
31
|
-
:ppm,
|
32
|
-
:ps,
|
33
|
-
:psd,
|
34
|
-
:ras,
|
35
|
-
:tga,
|
36
|
-
:tiff,
|
37
|
-
:wbmp,
|
38
|
-
:xbm,
|
39
|
-
:xpm,
|
40
|
-
:xwd
|
41
|
-
]
|
42
|
-
|
43
|
-
def encode(temp_object, format, args='')
|
44
|
-
format = format.to_s.downcase
|
45
|
-
throw :unable_to_handle unless supported_formats.include?(format.to_sym)
|
46
|
-
details = identify(temp_object)
|
47
|
-
|
48
|
-
if details[:format] == format.to_sym && args.empty?
|
49
|
-
temp_object
|
50
|
-
else
|
51
|
-
convert(temp_object, args, format)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
3
|
+
puts "WARNING: Dragonfly::Encoding::ImageMagickEncoder is DEPRECATED and will soon be removed. Please use Dragonfly::ImageMagick::Encoder instead."
|
4
|
+
ImageMagickEncoder = ImageMagick::Encoder
|
56
5
|
end
|
57
6
|
end
|
@@ -6,6 +6,7 @@ module Dragonfly
|
|
6
6
|
class UnableToHandle < NotImplementedError; end
|
7
7
|
|
8
8
|
include Loggable
|
9
|
+
include Configurable
|
9
10
|
|
10
11
|
def initialize
|
11
12
|
@functions = {}
|
@@ -23,6 +24,7 @@ module Dragonfly
|
|
23
24
|
obj = klass.new(*args)
|
24
25
|
obj.configure(&block) if block
|
25
26
|
obj.use_same_log_as(self) if obj.is_a?(Loggable)
|
27
|
+
obj.use_as_fallback_config(self) if obj.is_a?(Configurable)
|
26
28
|
methods_to_add(obj).each do |meth|
|
27
29
|
add meth.to_sym, obj.method(meth)
|
28
30
|
end
|
@@ -58,8 +60,8 @@ module Dragonfly
|
|
58
60
|
def methods_to_add(obj)
|
59
61
|
if obj.is_a?(Configurable)
|
60
62
|
obj.public_methods(false) -
|
61
|
-
obj.
|
62
|
-
[:
|
63
|
+
obj.config_methods.map{|meth| meth.to_method_name} -
|
64
|
+
[:configured_class.to_method_name] # Hacky - there must be a better way...
|
63
65
|
else
|
64
66
|
obj.public_methods(false)
|
65
67
|
end
|
@@ -1,140 +1,6 @@
|
|
1
1
|
module Dragonfly
|
2
2
|
module Generation
|
3
|
-
|
4
|
-
|
5
|
-
FONT_STYLES = {
|
6
|
-
'normal' => 'normal',
|
7
|
-
'italic' => 'italic',
|
8
|
-
'oblique' => 'oblique'
|
9
|
-
}
|
10
|
-
|
11
|
-
FONT_STRETCHES = {
|
12
|
-
'normal' => 'normal',
|
13
|
-
'semi-condensed' => 'semi-condensed',
|
14
|
-
'condensed' => 'condensed',
|
15
|
-
'extra-condensed' => 'extra-condensed',
|
16
|
-
'ultra-condensed' => 'ultra-condensed',
|
17
|
-
'semi-expanded' => 'semi-expanded',
|
18
|
-
'expanded' => 'expanded',
|
19
|
-
'extra-expanded' => 'extra-expanded',
|
20
|
-
'ultra-expanded' => 'ultra-expanded'
|
21
|
-
}
|
22
|
-
|
23
|
-
FONT_WEIGHTS = {
|
24
|
-
'normal' => 'normal',
|
25
|
-
'bold' => 'bold',
|
26
|
-
'bolder' => 'bolder',
|
27
|
-
'lighter' => 'lighter',
|
28
|
-
'100' => 100,
|
29
|
-
'200' => 200,
|
30
|
-
'300' => 300,
|
31
|
-
'400' => 400,
|
32
|
-
'500' => 500,
|
33
|
-
'600' => 600,
|
34
|
-
'700' => 700,
|
35
|
-
'800' => 800,
|
36
|
-
'900' => 900
|
37
|
-
}
|
38
|
-
|
39
|
-
include ImageMagickUtils
|
40
|
-
include Configurable
|
41
|
-
|
42
|
-
def plasma(width, height, format='png')
|
43
|
-
tempfile = new_tempfile(format)
|
44
|
-
run "#{convert_command} -size #{width}x#{height} plasma:fractal #{tempfile.path}"
|
45
|
-
[
|
46
|
-
tempfile,
|
47
|
-
{:format => format.to_sym, :name => "plasma.#{format}"}
|
48
|
-
]
|
49
|
-
end
|
50
|
-
|
51
|
-
def text(string, opts={})
|
52
|
-
opts = HashWithCssStyleKeys[opts]
|
53
|
-
args = []
|
54
|
-
format = (opts[:format] || :png)
|
55
|
-
background = opts[:background_color] || 'none'
|
56
|
-
font_size = (opts[:font_size] || 12).to_i
|
57
|
-
escaped_string = "\"#{string.gsub(/"/, '\"')}\""
|
58
|
-
|
59
|
-
# Settings
|
60
|
-
args.push("-gravity NorthWest")
|
61
|
-
args.push("-antialias")
|
62
|
-
args.push("-pointsize #{font_size}")
|
63
|
-
args.push("-font '#{opts[:font]}'") if opts[:font]
|
64
|
-
args.push("-family '#{opts[:font_family]}'") if opts[:font_family]
|
65
|
-
args.push("-fill #{opts[:color]}") if opts[:color]
|
66
|
-
args.push("-stroke #{opts[:stroke_color]}") if opts[:stroke_color]
|
67
|
-
args.push("-style #{FONT_STYLES[opts[:font_style]]}") if opts[:font_style]
|
68
|
-
args.push("-stretch #{FONT_STRETCHES[opts[:font_stretch]]}") if opts[:font_stretch]
|
69
|
-
args.push("-weight #{FONT_WEIGHTS[opts[:font_weight]]}") if opts[:font_weight]
|
70
|
-
args.push("-background #{background}")
|
71
|
-
args.push("label:#{escaped_string}")
|
72
|
-
|
73
|
-
# Padding
|
74
|
-
pt, pr, pb, pl = parse_padding_string(opts[:padding]) if opts[:padding]
|
75
|
-
padding_top = (opts[:padding_top] || pt || 0)
|
76
|
-
padding_right = (opts[:padding_right] || pr || 0)
|
77
|
-
padding_bottom = (opts[:padding_bottom] || pb || 0)
|
78
|
-
padding_left = (opts[:padding_left] || pl || 0)
|
79
|
-
|
80
|
-
tempfile = new_tempfile(format)
|
81
|
-
run "#{convert_command} #{args.join(' ')} #{tempfile.path}"
|
82
|
-
|
83
|
-
if (padding_top || padding_right || padding_bottom || padding_left)
|
84
|
-
attrs = identify(tempfile)
|
85
|
-
text_width = attrs[:width].to_i
|
86
|
-
text_height = attrs[:height].to_i
|
87
|
-
width = padding_left + text_width + padding_right
|
88
|
-
height = padding_top + text_height + padding_bottom
|
89
|
-
|
90
|
-
args = args.slice(0, args.length - 2)
|
91
|
-
args.push("-size #{width}x#{height}")
|
92
|
-
args.push("xc:#{background}")
|
93
|
-
args.push("-annotate 0x0+#{padding_left}+#{padding_top} #{escaped_string}")
|
94
|
-
run "#{convert_command} #{args.join(' ')} #{tempfile.path}"
|
95
|
-
end
|
96
|
-
|
97
|
-
[
|
98
|
-
tempfile,
|
99
|
-
{:format => format, :name => "text.#{format}"}
|
100
|
-
]
|
101
|
-
end
|
102
|
-
|
103
|
-
private
|
104
|
-
|
105
|
-
# Use css-style padding declaration, i.e.
|
106
|
-
# 10 (all sides)
|
107
|
-
# 10 5 (top/bottom, left/right)
|
108
|
-
# 10 5 10 (top, left/right, bottom)
|
109
|
-
# 10 5 10 5 (top, right, bottom, left)
|
110
|
-
def parse_padding_string(str)
|
111
|
-
padding_parts = str.gsub('px','').split(/\s+/).map{|px| px.to_i}
|
112
|
-
case padding_parts.size
|
113
|
-
when 1
|
114
|
-
p = padding_parts.first
|
115
|
-
[p,p,p,p]
|
116
|
-
when 2
|
117
|
-
p,q = padding_parts
|
118
|
-
[p,q,p,q]
|
119
|
-
when 3
|
120
|
-
p,q,r = padding_parts
|
121
|
-
[p,q,r,q]
|
122
|
-
when 4
|
123
|
-
padding_parts
|
124
|
-
else raise ArgumentError, "Couldn't parse padding string '#{str}' - should be a css-style string"
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def scale_factor_for(font_size)
|
129
|
-
# Scale approximately to 64 if below
|
130
|
-
min_size = 64
|
131
|
-
if font_size < min_size
|
132
|
-
(min_size.to_f / font_size).ceil
|
133
|
-
else
|
134
|
-
1
|
135
|
-
end.to_f
|
136
|
-
end
|
137
|
-
|
138
|
-
end
|
3
|
+
puts "WARNING: Dragonfly::Generation::ImageMagickGenerator is DEPRECATED and will soon be removed. Please use Dragonfly::ImageMagick::Generator instead."
|
4
|
+
ImageMagickGenerator = ImageMagick::Generator
|
139
5
|
end
|
140
6
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Dragonfly
|
2
|
+
|
3
|
+
# HashWithCssStyleKeys is solely for being able to access a hash
|
4
|
+
# which has css-style keys (e.g. 'font-size') with the underscore
|
5
|
+
# symbol version
|
6
|
+
# @example
|
7
|
+
# opts = {'font-size' => '23px', :color => 'white'}
|
8
|
+
# opts = HashWithCssStyleKeys[opts]
|
9
|
+
# opts[:font_size] # ===> '23px'
|
10
|
+
# opts[:color] # ===> 'white'
|
11
|
+
class HashWithCssStyleKeys < Hash
|
12
|
+
def [](key)
|
13
|
+
super || (
|
14
|
+
str_key = key.to_s
|
15
|
+
css_key = str_key.gsub('_','-')
|
16
|
+
super(str_key) || super(css_key) || super(css_key.to_sym)
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|