dynamic_images 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +27 -0
- data/README.rdoc +104 -0
- data/README_USAGE.rdoc +67 -0
- data/Rakefile +14 -0
- data/dynamic_images.gemspec +35 -0
- data/examples/gtk_window.rb +39 -0
- data/examples/named_colors_table.rb +13 -0
- data/init.rb +6 -0
- data/lib/dynamic_image.rb +240 -0
- data/lib/elements/block_element.rb +224 -0
- data/lib/elements/element_interface.rb +320 -0
- data/lib/elements/image_element.rb +82 -0
- data/lib/elements/table_cell_element.rb +34 -0
- data/lib/elements/table_element.rb +220 -0
- data/lib/elements/text_element.rb +195 -0
- data/lib/parsers/xml.dtd +154 -0
- data/lib/parsers/xml_parser.rb +135 -0
- data/lib/render_image.rb +60 -0
- data/lib/sources/color_source.rb +97 -0
- data/lib/sources/gradient_source.rb +200 -0
- data/lib/sources/source_factory.rb +36 -0
- data/test/asym.rb +54 -0
- data/test/performance.1.rb +86 -0
- data/test/performance.2.rb +159 -0
- data/test/performance.3.rb +236 -0
- data/test/performance.rb +51 -0
- data/test/units1.rb +185 -0
- data/test/units2.rb +162 -0
- metadata +115 -0
data/Manifest
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
README.rdoc
|
2
|
+
README_USAGE.rdoc
|
3
|
+
Rakefile
|
4
|
+
examples/gtk_window.rb
|
5
|
+
examples/named_colors_table.rb
|
6
|
+
init.rb
|
7
|
+
lib/dynamic_image.rb
|
8
|
+
lib/elements/block_element.rb
|
9
|
+
lib/elements/element_interface.rb
|
10
|
+
lib/elements/image_element.rb
|
11
|
+
lib/elements/table_cell_element.rb
|
12
|
+
lib/elements/table_element.rb
|
13
|
+
lib/elements/text_element.rb
|
14
|
+
lib/parsers/xml.dtd
|
15
|
+
lib/parsers/xml_parser.rb
|
16
|
+
lib/render_image.rb
|
17
|
+
lib/sources/color_source.rb
|
18
|
+
lib/sources/gradient_source.rb
|
19
|
+
lib/sources/source_factory.rb
|
20
|
+
test/asym.rb
|
21
|
+
test/performance.1.rb
|
22
|
+
test/performance.2.rb
|
23
|
+
test/performance.3.rb
|
24
|
+
test/performance.rb
|
25
|
+
test/units1.rb
|
26
|
+
test/units2.rb
|
27
|
+
Manifest
|
data/README.rdoc
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
= Dynamic Images
|
2
|
+
|
3
|
+
Ruby library providing image rendering described by dynamic templates
|
4
|
+
|
5
|
+
== Dependencies
|
6
|
+
|
7
|
+
Library is using these libraries:
|
8
|
+
* cairo
|
9
|
+
* pango
|
10
|
+
* rexml
|
11
|
+
|
12
|
+
== How to install & use
|
13
|
+
|
14
|
+
Download this repository and place it into your folder.
|
15
|
+
|
16
|
+
Require init.rb file from library's folder.
|
17
|
+
|
18
|
+
Optionaly you can load gtk2 libraty too. It's supporting another image formats.
|
19
|
+
|
20
|
+
For more information how to use or about elements read documentation.
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
= Usage of Library
|
26
|
+
|
27
|
+
== In general about options
|
28
|
+
Options should be in base given as hash. Format of keys in hash is not fixed. You can use +Symbol+ as good as +String+. There is also no difference between "-" and "_" chars.
|
29
|
+
|
30
|
+
If option accepts more arguments you can specify they in +Array+ and also in +String+. In case you choose +String+ it's necessary to seperate arguments by space char.
|
31
|
+
|
32
|
+
=== Example
|
33
|
+
These <tt>Hash</tt>es are considered as absolutelly same.
|
34
|
+
* <tt>{:vertical_align => :middle}</tt>, <tt>{'vertical_align' => 'middle'}</tt>, <tt>{"vertical-align" => :middle}</tt>, <tt>{:vertical_align => "middle"}</tt>, <tt>{:vertical_align => :middle}</tt>, etc.
|
35
|
+
* <tt>{:to_fit => [:crop, :sentences, 3, :resize]}</tt>, <tt>{:to_fit => "crop sentences 3 resize"}</tt>, <tt>{'to-fit' => "crop sentences 3 resize"}</tt>, etc.
|
36
|
+
|
37
|
+
== Passing a Block
|
38
|
+
In block you can accept object to call methods on it or if you don't accept any argument, block is called in object instance.
|
39
|
+
|
40
|
+
=== Example
|
41
|
+
These examples are considered as same.
|
42
|
+
DynamicImage.new do |img|
|
43
|
+
img.text "<b>Warning</b>"
|
44
|
+
img.save! "warning.png"
|
45
|
+
end
|
46
|
+
|
47
|
+
DynamicImage.new do
|
48
|
+
text "<b>Warning</b>"
|
49
|
+
save! "warning.png"
|
50
|
+
end
|
51
|
+
|
52
|
+
== Image formats
|
53
|
+
In base you can save and load all as PNG images. You can enable more formats by loading gtk library. DynamicImage will automatically detect it's loaded.
|
54
|
+
|
55
|
+
require 'gtk2'
|
56
|
+
|
57
|
+
== Using with Rails
|
58
|
+
To use within Rails application just download this library as plugin.
|
59
|
+
|
60
|
+
rails plugin install git://github.com/malis/dynamic_images.git
|
61
|
+
|
62
|
+
You need to add <tt>cairo</tt> and <tt>pango</tt> gems to your Gemfile or environment.rb file.
|
63
|
+
|
64
|
+
Then just update your controller like this:
|
65
|
+
|
66
|
+
def show
|
67
|
+
@article = Article.find(params[:id])
|
68
|
+
respond_to do |format|
|
69
|
+
format.html
|
70
|
+
format.png { render_image } #or render_image("show.jpg"), find more in doc
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
Do not forgot to add mime types for used image formats to your environment file.
|
75
|
+
|
76
|
+
Mime::Type.register "image/png", :png
|
77
|
+
|
78
|
+
Create view articles/show.png.xml.erb like this:
|
79
|
+
|
80
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
81
|
+
<!DOCTYPE dynamic_images PUBLIC "-//malis//dynamic_images//EN" "https://raw.github.com/malis/dynamic_images/master/lib/parsers/xml.dtd">
|
82
|
+
<dynamic_images>
|
83
|
+
<dynamic_image width="500" align="center" background="blue 0.5">
|
84
|
+
<text font="Arial bold 20"><%= @article.title %></text>
|
85
|
+
<text indent="30"><%= @article.text %></text>
|
86
|
+
</dynamic_image>
|
87
|
+
</dynamic_images>
|
88
|
+
|
89
|
+
That's all!
|
90
|
+
|
91
|
+
Library is tested under Rails 2.3.11 (ruby 1.8.7) and 3.1.1 (ruby 1.9.2)
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
== Copying
|
101
|
+
Copyright (c) 2012 Dominik Mališ
|
102
|
+
|
103
|
+
This program is free software.
|
104
|
+
You can distribute/modify this program under the terms of the GNU LESSER GENERAL PUBLIC LICENSE.
|
data/README_USAGE.rdoc
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
= Usage of Library
|
2
|
+
|
3
|
+
== In general about options
|
4
|
+
Options should be in base given as hash. Format of keys in hash is not fixed. You can use +Symbol+ as good as +String+. There is also no difference between "-" and "_" chars.
|
5
|
+
|
6
|
+
If option accepts more arguments you can specify they in +Array+ and also in +String+. In case you choose +String+ it's necessary to seperate arguments by space char.
|
7
|
+
|
8
|
+
=== Example
|
9
|
+
These <tt>Hash</tt>es are considered as absolutelly same.
|
10
|
+
* <tt>{:vertical_align => :middle}</tt>, <tt>{'vertical_align' => 'middle'}</tt>, <tt>{"vertical-align" => :middle}</tt>, <tt>{:vertical_align => "middle"}</tt>, <tt>{:vertical_align => :middle}</tt>, etc.
|
11
|
+
* <tt>{:to_fit => [:crop, :sentences, 3, :resize]}</tt>, <tt>{:to_fit => "crop sentences 3 resize"}</tt>, <tt>{'to-fit' => "crop sentences 3 resize"}</tt>, etc.
|
12
|
+
|
13
|
+
== Passing a Block
|
14
|
+
In block you can accept object to call methods on it or if you don't accept any argument, block is called in object instance.
|
15
|
+
|
16
|
+
=== Example
|
17
|
+
These examples are considered as same.
|
18
|
+
DynamicImage.new do |img|
|
19
|
+
img.text "<b>Warning</b>"
|
20
|
+
img.save! "warning.png"
|
21
|
+
end
|
22
|
+
|
23
|
+
DynamicImage.new do
|
24
|
+
text "<b>Warning</b>"
|
25
|
+
save! "warning.png"
|
26
|
+
end
|
27
|
+
|
28
|
+
== Image formats
|
29
|
+
In base you can save and load all as PNG images. You can enable more formats by loading gtk library. DynamicImage will automatically detect it's loaded.
|
30
|
+
|
31
|
+
require 'gtk2'
|
32
|
+
|
33
|
+
== Using with Rails
|
34
|
+
To use within Rails application just download this library as plugin.
|
35
|
+
|
36
|
+
rails plugin install git://github.com/malis/dynamic_images.git
|
37
|
+
|
38
|
+
You need to add <tt>cairo</tt> and <tt>pango</tt> gems to your Gemfile or environment.rb file.
|
39
|
+
|
40
|
+
Then just update your controller like this:
|
41
|
+
|
42
|
+
def show
|
43
|
+
@article = Article.find(params[:id])
|
44
|
+
respond_to do |format|
|
45
|
+
format.html
|
46
|
+
format.png { render_image } #or render_image("show.jpg"), find more in doc
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
Do not forgot to add mime types for used image formats to your environment file.
|
51
|
+
|
52
|
+
Mime::Type.register "image/png", :png
|
53
|
+
|
54
|
+
Create view articles/show.png.xml.erb like this:
|
55
|
+
|
56
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
57
|
+
<!DOCTYPE dynamic_images PUBLIC "-//malis//dynamic_images//EN" "https://raw.github.com/malis/dynamic_images/master/lib/parsers/xml.dtd">
|
58
|
+
<dynamic_images>
|
59
|
+
<dynamic_image width="500" align="center" background="blue 0.5">
|
60
|
+
<text font="Arial bold 20"><%= @article.title %></text>
|
61
|
+
<text indent="30"><%= @article.text %></text>
|
62
|
+
</dynamic_image>
|
63
|
+
</dynamic_images>
|
64
|
+
|
65
|
+
That's all!
|
66
|
+
|
67
|
+
Library is tested under Rails 2.3.11 (ruby 1.8.7) and 3.1.1 (ruby 1.9.2)
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('dynamic_images', '1.0.0') do |p|
|
6
|
+
p.description = "Ruby library providing image rendering described by dynamic templates"
|
7
|
+
p.url = "http://github.com/malis/dynamic_images"
|
8
|
+
p.author = "Dominik Malis"
|
9
|
+
p.email = "dominik.malis@gmail.com"
|
10
|
+
p.ignore_pattern = ["tmp/*", "script/*"]
|
11
|
+
p.runtime_dependencies = ["cairo", "pango"]
|
12
|
+
end
|
13
|
+
|
14
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "dynamic_images"
|
5
|
+
s.version = "1.0.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Dominik Malis"]
|
9
|
+
s.date = "2012-06-19"
|
10
|
+
s.description = "Ruby library providing image rendering described by dynamic templates"
|
11
|
+
s.email = "dominik.malis@gmail.com"
|
12
|
+
s.extra_rdoc_files = ["README.rdoc", "README_USAGE.rdoc", "lib/dynamic_image.rb", "lib/elements/block_element.rb", "lib/elements/element_interface.rb", "lib/elements/image_element.rb", "lib/elements/table_cell_element.rb", "lib/elements/table_element.rb", "lib/elements/text_element.rb", "lib/parsers/xml.dtd", "lib/parsers/xml_parser.rb", "lib/render_image.rb", "lib/sources/color_source.rb", "lib/sources/gradient_source.rb", "lib/sources/source_factory.rb"]
|
13
|
+
s.files = ["README.rdoc", "README_USAGE.rdoc", "Rakefile", "examples/gtk_window.rb", "examples/named_colors_table.rb", "init.rb", "lib/dynamic_image.rb", "lib/elements/block_element.rb", "lib/elements/element_interface.rb", "lib/elements/image_element.rb", "lib/elements/table_cell_element.rb", "lib/elements/table_element.rb", "lib/elements/text_element.rb", "lib/parsers/xml.dtd", "lib/parsers/xml_parser.rb", "lib/render_image.rb", "lib/sources/color_source.rb", "lib/sources/gradient_source.rb", "lib/sources/source_factory.rb", "test/asym.rb", "test/performance.1.rb", "test/performance.2.rb", "test/performance.3.rb", "test/performance.rb", "test/units1.rb", "test/units2.rb", "Manifest", "dynamic_images.gemspec"]
|
14
|
+
s.homepage = "http://github.com/malis/dynamic_images"
|
15
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Dynamic_images", "--main", "README_USAGE.rdoc"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = "dynamic_images"
|
18
|
+
s.rubygems_version = "1.8.10"
|
19
|
+
s.summary = "Ruby library providing image rendering described by dynamic templates"
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
s.specification_version = 3
|
23
|
+
|
24
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
25
|
+
s.add_runtime_dependency(%q<cairo>, [">= 0"])
|
26
|
+
s.add_runtime_dependency(%q<pango>, [">= 0"])
|
27
|
+
else
|
28
|
+
s.add_dependency(%q<cairo>, [">= 0"])
|
29
|
+
s.add_dependency(%q<pango>, [">= 0"])
|
30
|
+
end
|
31
|
+
else
|
32
|
+
s.add_dependency(%q<cairo>, [">= 0"])
|
33
|
+
s.add_dependency(%q<pango>, [">= 0"])
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'gtk2'
|
3
|
+
require File.dirname(__FILE__) + '/../init.rb'
|
4
|
+
|
5
|
+
class Win < Gtk::Window
|
6
|
+
def initialize
|
7
|
+
super
|
8
|
+
set_title "DynamicImage Gtk Test"
|
9
|
+
signal_connect "destroy" do
|
10
|
+
Gtk.main_quit
|
11
|
+
end
|
12
|
+
resize 300, 300
|
13
|
+
|
14
|
+
@darea = Gtk::DrawingArea.new
|
15
|
+
@darea.signal_connect "expose-event" do
|
16
|
+
expose
|
17
|
+
end
|
18
|
+
add @darea
|
19
|
+
|
20
|
+
show_all
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def expose
|
25
|
+
w = allocation.width
|
26
|
+
h = allocation.height
|
27
|
+
|
28
|
+
DynamicImage.from @darea.window.create_cairo_context do
|
29
|
+
block :w => w, :h => h, :bg => [:gradient_radial_repeat, "225deg", "50%", "0%", :lime, "50%", :red, "100%", :orange], :align => :center, :valign => :middle do
|
30
|
+
text "Try to resize me!", :font => "Arial bold 48", :color => [:gradient_repeat, "0%", :blue, "100%", :yellow]
|
31
|
+
end
|
32
|
+
save!
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
Gtk.init
|
38
|
+
window = Win.new
|
39
|
+
Gtk.main
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require File.dirname(__FILE__) + '/../init.rb'
|
3
|
+
|
4
|
+
DynamicImage.new do
|
5
|
+
table :cols => 9 do
|
6
|
+
for color in DynamicImageSources::ColorSource.named_colors
|
7
|
+
cell :padding => 5, :margin => 2, :background => color do
|
8
|
+
text color
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
save! "named_colors_table.png"
|
13
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1,240 @@
|
|
1
|
+
require 'cairo'
|
2
|
+
require 'pango'
|
3
|
+
require File.dirname(__FILE__) + '/elements/block_element.rb'
|
4
|
+
require File.dirname(__FILE__) + '/parsers/xml_parser.rb'
|
5
|
+
|
6
|
+
# DynamicImage provides interface to create an image in ruby code.
|
7
|
+
#
|
8
|
+
# :include:../README_USAGE.rdoc
|
9
|
+
class DynamicImage < DynamicImageElements::BlockElement
|
10
|
+
# Gets original Cairo::Context of Cairo::ImageSurface object if width and height was given in options or it's created from existing source.
|
11
|
+
attr_reader :context
|
12
|
+
|
13
|
+
# DynamicImage accepts options +Hash+. If block is given destroy method is called automatically after a block if source of image isn't Cairo object. Otherwise you have to call destroy manually.
|
14
|
+
#
|
15
|
+
# === Options
|
16
|
+
# Image accepts also all options like BlockElement. See it first.
|
17
|
+
#
|
18
|
+
# [:auto_destroy]
|
19
|
+
# Sets whether to automatically destroy surface if you are using block. Default is true.
|
20
|
+
#
|
21
|
+
# [:format]
|
22
|
+
# Sets the memory format of image data.
|
23
|
+
#
|
24
|
+
# Valid values are :a1, :a8, :rgb24 and :argb32. See http://www.cairographics.org/manual/cairo-Image-Surfaces.html#cairo-format-t for details.
|
25
|
+
#
|
26
|
+
# [:from_source]
|
27
|
+
# Creates new DynamicImage from given source if it's supported. It has same behavior as DynamicImage.from.
|
28
|
+
#
|
29
|
+
def initialize(options = {}, &block) # :yields: block_element
|
30
|
+
treat_options options
|
31
|
+
@options = options
|
32
|
+
use_options :margin
|
33
|
+
use_options :padding
|
34
|
+
if options[:width] && options[:height] || options[:from_source]
|
35
|
+
[:width, :height].each {|key| @options[key] = nil } if options[:from_source] #remove forbidden options
|
36
|
+
create_surface
|
37
|
+
end
|
38
|
+
super options, &block
|
39
|
+
destroy_by_block if block
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
def create_surface(use_from_source = true)
|
44
|
+
if @options[:from_source] && use_from_source
|
45
|
+
if @options[:from_source].is_a? Cairo::Surface
|
46
|
+
set_surface_and_context @options[:from_source]
|
47
|
+
@options[:auto_destroy] = false
|
48
|
+
elsif @options[:from_source].is_a? Cairo::Context
|
49
|
+
set_surface_and_context nil, @options[:from_source]
|
50
|
+
@options[:auto_destroy] = false
|
51
|
+
elsif @options[:from_source].to_s =~ /\.png$/i
|
52
|
+
image = Cairo::ImageSurface.from_png @options[:from_source]
|
53
|
+
set_surface_and_context image
|
54
|
+
set_width image.width, false
|
55
|
+
set_height image.height, false
|
56
|
+
else
|
57
|
+
if defined? Gdk
|
58
|
+
pixbuf = Gdk::Pixbuf.new @options[:from_source]
|
59
|
+
set_width pixbuf.width, false
|
60
|
+
set_height pixbuf.height, false
|
61
|
+
create_surface false
|
62
|
+
context.save
|
63
|
+
context.set_source_pixbuf pixbuf, 0, 0
|
64
|
+
context.rectangle 0, 0, pixbuf.width, pixbuf.height
|
65
|
+
context.clip
|
66
|
+
context.paint
|
67
|
+
context.restore
|
68
|
+
else
|
69
|
+
raise "Unsupported source format of: #{@options[:from_source]}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
else
|
73
|
+
w, h = @options[:width].to_i, @options[:height].to_i
|
74
|
+
if @padding
|
75
|
+
w += @padding[1] + @padding[3]
|
76
|
+
h += @padding[0] + @padding[2]
|
77
|
+
end
|
78
|
+
if @margin
|
79
|
+
w += @margin[1] + @margin[3]
|
80
|
+
h += @margin[0] + @margin[2]
|
81
|
+
end
|
82
|
+
if @border && !@border.empty?
|
83
|
+
w += @border[:left][0].to_i if @border[:left]
|
84
|
+
w += @border[:right][0].to_i if @border[:right]
|
85
|
+
h += @border[:top][0].to_i if @border[:top]
|
86
|
+
h += @border[:bottom][0].to_i if @border[:bottom]
|
87
|
+
end
|
88
|
+
surface_args = [w, h]
|
89
|
+
surface_args.unshift({
|
90
|
+
:a1 => Cairo::Format::A1,
|
91
|
+
:a8 => Cairo::Format::A8,
|
92
|
+
:rgb24 => Cairo::Format::RGB24,
|
93
|
+
:argb32 => Cairo::Format::ARGB32
|
94
|
+
}[@options[:format].to_sym]) if @options[:format]
|
95
|
+
@surface = Cairo::ImageSurface.new *surface_args
|
96
|
+
@context = Cairo::Context.new @surface
|
97
|
+
@context.set_antialias({
|
98
|
+
:default => Cairo::ANTIALIAS_DEFAULT,
|
99
|
+
:gray => Cairo::ANTIALIAS_GRAY,
|
100
|
+
:none => Cairo::ANTIALIAS_NONE,
|
101
|
+
:subpixel => Cairo::ANTIALIAS_SUBPIXEL
|
102
|
+
}[@options[:antialias].to_sym]) if @options[:antialias]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def set_surface_and_context(surface, context = nil)
|
107
|
+
@surface = surface
|
108
|
+
@context = context || Cairo::Context.new(surface)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Call this if block is given to destroy surface
|
112
|
+
def destroy_by_block
|
113
|
+
self.destroy if @options[:auto_destroy] != false
|
114
|
+
end
|
115
|
+
|
116
|
+
public
|
117
|
+
# Gets left and bottom borders of drawing canvas
|
118
|
+
def canvas_border
|
119
|
+
x, y = [@options[:width], @options[:height]]
|
120
|
+
if @padding
|
121
|
+
x += @padding[3]
|
122
|
+
y += @padding[0]
|
123
|
+
end
|
124
|
+
if @margin
|
125
|
+
x += @margin[3]
|
126
|
+
y += @margin[0]
|
127
|
+
end
|
128
|
+
if @border && !@border.empty?
|
129
|
+
x += @border[:left][0].to_i if @border[:left]
|
130
|
+
y += @border[:top][0].to_i if @border[:top]
|
131
|
+
end
|
132
|
+
[x, y]
|
133
|
+
end
|
134
|
+
|
135
|
+
# Creates new DynamicImage from given source if it's supported. Use it in same way as DynamicImage.new.
|
136
|
+
#
|
137
|
+
# PNG is always supported as source.
|
138
|
+
#
|
139
|
+
# If there is +Gdk+ loaded you can use any from <tt>Gdk::Pixbuf.formats</tt> as source. By default, "jpeg", "png" and "ico" are possible file formats to load from, but more formats may be installed.
|
140
|
+
#
|
141
|
+
def self.from(source, options = {}, &block) # :yields: block_element
|
142
|
+
options[:from_source] = source
|
143
|
+
DynamicImage.new options, &block
|
144
|
+
end
|
145
|
+
|
146
|
+
# Saves image into file or given IO object (you have to speficify :format option like file extension, f.e. <tt>png</tt>). Image will be drawed only if no file is given. It's usable when you drawing into prepared Cairo object.
|
147
|
+
#
|
148
|
+
# Block can be given to draw into context directly.
|
149
|
+
#
|
150
|
+
# PNG format is always supported.
|
151
|
+
#
|
152
|
+
# If there is +Gdk+ loaded you can use any from <tt>Gdk::Pixbuf.formats</tt> as source. By default, "jpeg", "png" and "ico" are possible file formats to save in, but more formats may be installed.
|
153
|
+
#
|
154
|
+
# When saving into JPEG format you can pass :quality into options. Valid values are in 0 - 100.
|
155
|
+
#
|
156
|
+
def save!(file = nil, options = {}, &block) # :yields: context
|
157
|
+
treat_options options
|
158
|
+
unless context
|
159
|
+
canvas_size = final_size
|
160
|
+
canvas_size[0] = @options[:width] if @options[:width]
|
161
|
+
canvas_size[1] = @options[:height] if @options[:height]
|
162
|
+
set_width canvas_size[0], false
|
163
|
+
set_height canvas_size[1], false
|
164
|
+
create_surface
|
165
|
+
end
|
166
|
+
draw!
|
167
|
+
block.call context if block
|
168
|
+
write_to file, options if file
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
def write_to(file, options)
|
173
|
+
ext = options[:format]
|
174
|
+
ext ||= file.scan(/\.([a-z]+)$/i).flatten.first.downcase
|
175
|
+
if ext.to_s == "png"
|
176
|
+
context.target.write_to_png file
|
177
|
+
else
|
178
|
+
raise "Unsupported file type #{ext}" unless defined? Gdk
|
179
|
+
w, h = @options[:width], @options[:height]
|
180
|
+
pixmap = Gdk::Pixmap.new nil, w, h, 24
|
181
|
+
context = pixmap.create_cairo_context
|
182
|
+
context.set_source @context.target, 0, 0
|
183
|
+
context.paint
|
184
|
+
#pixbuf = Gdk::Pixbuf.new gtk.gdk.COLORSPACE_RGB, True, 8, w, h
|
185
|
+
pixbuf = Gdk::Pixbuf.from_drawable Gdk::Colormap.system, pixmap, 0, 0, w, h
|
186
|
+
begin
|
187
|
+
format = Gdk::Pixbuf.formats.select{|f| f.extensions.include? ext.to_s}.first.name
|
188
|
+
rescue
|
189
|
+
raise "Unsupported file type #{ext}"
|
190
|
+
end
|
191
|
+
pixbuf.save file, format, (format == "jpeg" && options[:quality] ? {'quality' => options[:quality]} : {})
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
public
|
196
|
+
# Saves image content into more images if content is bigger than given image size.
|
197
|
+
# Image is cut between elements in first level of elements hierarchy. In case of table it's cut between rows of table.
|
198
|
+
#
|
199
|
+
# Method accepts limit of pages to be rendered. If no number is given or 0 is passed it's not limited.
|
200
|
+
# Give a block returning filename or given IO object (you have to speficify :format option like file extension, f.e. <tt>png</tt>) to saving in it. Block provides index of page which is currently rendered. Index starting at 0.
|
201
|
+
#
|
202
|
+
# PNG format is always supported.
|
203
|
+
#
|
204
|
+
# If there is +Gdk+ loaded you can use any from <tt>Gdk::Pixbuf.formats</tt> as source. By default, "jpeg", "png" and "ico" are possible file formats to save in, but more formats may be installed.
|
205
|
+
#
|
206
|
+
# When saving into JPEG format you can pass :quality into options. Valid values are in 0 - 100.
|
207
|
+
#
|
208
|
+
# === Example
|
209
|
+
# save_endless 4 do |index|
|
210
|
+
# "image-#{index}.png"
|
211
|
+
# end
|
212
|
+
#
|
213
|
+
def save_endless!(limit = 0, options = {}, &block) # :yields: index
|
214
|
+
raise "Width and height must be set when you saving endless" unless @options[:width] || @options[:height]
|
215
|
+
treat_options options
|
216
|
+
@drawing_endless = index = 0
|
217
|
+
loop do
|
218
|
+
draw! 0, 0, index
|
219
|
+
write_to block.call(index), options
|
220
|
+
destroy
|
221
|
+
create_surface
|
222
|
+
index += 1
|
223
|
+
@drawing_endless = index
|
224
|
+
break if index == limit || is_drawed?
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# Gets index of drawing endless from canvas
|
229
|
+
def drawing_endless #:nodoc:
|
230
|
+
@drawing_endless
|
231
|
+
end
|
232
|
+
|
233
|
+
# Destroys source objects to free a memory. It's important to call this method when it's finished to avoid a memory leaks.
|
234
|
+
#
|
235
|
+
# If you passed a block to DynamicImage.new or DynamicImage.from it's called automatically after block is finished.
|
236
|
+
def destroy
|
237
|
+
@surface.destroy if @surface
|
238
|
+
@context.destroy if @context
|
239
|
+
end
|
240
|
+
end
|