dynamic_images 1.0.0
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.
- 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
|