spatrik-gd2-ffi 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +39 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/gd2-ffi.gemspec +57 -0
- data/lib/gd2/canvas.rb +34 -0
- data/lib/gd2/cgd2.rb +26 -0
- data/lib/gd2/color.rb +110 -0
- data/lib/gd2/font.rb +95 -0
- data/lib/gd2/image.rb +36 -0
- data/lib/gd2-ffi.rb +17 -0
- data/spec/Vera.ttf +0 -0
- data/spec/canvas_spec.rb +71 -0
- data/spec/color_spec.rb +36 -0
- data/spec/image_spec.rb +13 -0
- data/spec/spec_helper.rb +6 -0
- data/test.rb +50 -0
- metadata +72 -0
data/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
gd2-ffi
|
2
|
+
=======
|
3
|
+
|
4
|
+
gd2-ffi is ruby bindings for gd2, implemented with [FFI][FFI]
|
5
|
+
|
6
|
+
[FFI]: http://kenai.com
|
7
|
+
|
8
|
+
The bindings are currently very incomplete, only including what I need for a certain project (Creating truecolor images, drawing rectangles, drawing TrueType fonts).
|
9
|
+
|
10
|
+
It follows the same API as the [gd2 gem][GD2-GEM]
|
11
|
+
|
12
|
+
[GD2-GEM]: http://gd2.rubyforge.org/
|
13
|
+
|
14
|
+
The reason for building this gem is that the other gd2 gem had problems with segfaulting on some linux boxes, and it was more fun and quicker to learn FFI than debug dlopen (Which I have no idea how it works) :)¨
|
15
|
+
|
16
|
+
License
|
17
|
+
-------
|
18
|
+
|
19
|
+
The MIT License
|
20
|
+
|
21
|
+
Copyright (c) 2009 Patrik Stenmark
|
22
|
+
|
23
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
24
|
+
of this software and associated documentation files (the "Software"), to deal
|
25
|
+
in the Software without restriction, including without limitation the rights
|
26
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
27
|
+
copies of the Software, and to permit persons to whom the Software is
|
28
|
+
furnished to do so, subject to the following conditions:
|
29
|
+
|
30
|
+
The above copyright notice and this permission notice shall be included in
|
31
|
+
all copies or substantial portions of the Software.
|
32
|
+
|
33
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
34
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
35
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
36
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
37
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
38
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
39
|
+
THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "gd2-ffi"
|
8
|
+
gem.summary = %Q{gd2-ffi is ruby bindings for gd2, implemented with ffi}
|
9
|
+
gem.description = %Q{gd2-ffi is ruby bindings for gd2, implemented with ffi}
|
10
|
+
gem.email = "patrik.stenmark@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/spatrik/gd2-ffi"
|
12
|
+
gem.authors = ["Patrik Stenmark"]
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'spec/rake/spectask'
|
21
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
22
|
+
spec.libs << 'lib' << 'spec'
|
23
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
24
|
+
end
|
25
|
+
|
26
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
27
|
+
spec.libs << 'lib' << 'spec'
|
28
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
29
|
+
spec.rcov = true
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
task :default => :spec
|
36
|
+
|
37
|
+
require 'rake/rdoctask'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
if File.exist?('VERSION')
|
40
|
+
version = File.read('VERSION')
|
41
|
+
else
|
42
|
+
version = ""
|
43
|
+
end
|
44
|
+
|
45
|
+
rdoc.rdoc_dir = 'rdoc'
|
46
|
+
rdoc.title = "test #{version}"
|
47
|
+
rdoc.rdoc_files.include('README*')
|
48
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.3
|
data/gd2-ffi.gemspec
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{gd2-ffi}
|
8
|
+
s.version = "0.0.3"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Patrik Stenmark"]
|
12
|
+
s.date = %q{2009-08-05}
|
13
|
+
s.description = %q{gd2-ffi is ruby bindings for gd2, implemented with ffi}
|
14
|
+
s.email = %q{patrik.stenmark@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.md"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
"README.md",
|
20
|
+
"Rakefile",
|
21
|
+
"VERSION",
|
22
|
+
"gd2-ffi.gemspec",
|
23
|
+
"lib/gd2-ffi.rb",
|
24
|
+
"lib/gd2/canvas.rb",
|
25
|
+
"lib/gd2/cgd2.rb",
|
26
|
+
"lib/gd2/color.rb",
|
27
|
+
"lib/gd2/font.rb",
|
28
|
+
"lib/gd2/image.rb",
|
29
|
+
"spec/Vera.ttf",
|
30
|
+
"spec/canvas_spec.rb",
|
31
|
+
"spec/color_spec.rb",
|
32
|
+
"spec/image_spec.rb",
|
33
|
+
"spec/spec_helper.rb",
|
34
|
+
"test.rb"
|
35
|
+
]
|
36
|
+
s.homepage = %q{http://github.com/spatrik/gd2-ffi}
|
37
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
38
|
+
s.require_paths = ["lib"]
|
39
|
+
s.rubygems_version = %q{1.3.5}
|
40
|
+
s.summary = %q{gd2-ffi is ruby bindings for gd2, implemented with ffi}
|
41
|
+
s.test_files = [
|
42
|
+
"spec/canvas_spec.rb",
|
43
|
+
"spec/color_spec.rb",
|
44
|
+
"spec/image_spec.rb",
|
45
|
+
"spec/spec_helper.rb"
|
46
|
+
]
|
47
|
+
|
48
|
+
if s.respond_to? :specification_version then
|
49
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
50
|
+
s.specification_version = 3
|
51
|
+
|
52
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
53
|
+
else
|
54
|
+
end
|
55
|
+
else
|
56
|
+
end
|
57
|
+
end
|
data/lib/gd2/canvas.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module GD2
|
2
|
+
class Canvas
|
3
|
+
class Point
|
4
|
+
attr_accessor :x, :y
|
5
|
+
def initialize(x, y)
|
6
|
+
@x, @y = x, y
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Text
|
11
|
+
def initialize(font, point, angle, string)
|
12
|
+
@font, @point, @angle, @string = font, point, angle, string
|
13
|
+
end
|
14
|
+
|
15
|
+
def draw(image, color)
|
16
|
+
color = color.is_a?(Color) ? color.rgba : color
|
17
|
+
@font.draw(image.image_ptr, @point.x, @point.y, @angle, @string, color)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class FilledRectangle
|
22
|
+
def initialize(point1, point2)
|
23
|
+
@p1, @p2 = point1, point2
|
24
|
+
end
|
25
|
+
|
26
|
+
def draw(image, color)
|
27
|
+
color = color.is_a?(GD2::Color) ? color.rgba : color
|
28
|
+
|
29
|
+
CGD2::gdImageFilledRectangle(image.image_ptr, @p1.x, @p1.y, @p2.x, @p2.y, color)
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/gd2/cgd2.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module CGD2
|
2
|
+
|
3
|
+
def self.lib_paths
|
4
|
+
["/opt/local/lib/libgd.2.dylib", '/usr/lib/libgd.so.2']
|
5
|
+
end
|
6
|
+
extend FFI::Library
|
7
|
+
ffi_lib *lib_paths
|
8
|
+
|
9
|
+
# BGD_DECLARE(gdImagePtr) gdImageCreate (int sx, int sy)
|
10
|
+
attach_function :gdImageCreate, [:int, :int], :pointer
|
11
|
+
attach_function :gdImageCreateTrueColor, [:int, :int], :pointer
|
12
|
+
|
13
|
+
# void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color) (FUNCTION)
|
14
|
+
attach_function :gdImageFilledRectangle, [:pointer, :int, :int, :int, :int, :int], :void
|
15
|
+
|
16
|
+
#char *gdImageStringFT(gdImagePtr im, int *brect, int fg, char *fontname, double ptsize, double angle, int x, int y, char *string) (FUNCTION)
|
17
|
+
attach_function :gdImageStringFT, [:pointer, :pointer, :int, :string, :double, :double, :int, :int, :string], :pointer
|
18
|
+
|
19
|
+
# void* gdImagePngPtr(gdImagePtr im, int *size) (FUNCTION)
|
20
|
+
attach_function :gdImagePngPtr, [:pointer, :pointer], :pointer
|
21
|
+
|
22
|
+
# gdImageDestroy(gdImagePtr im) (FUNCTION)
|
23
|
+
attach_function :gdImageDestroy, [:pointer], :void
|
24
|
+
|
25
|
+
attach_function :gdFree, [:pointer], :void
|
26
|
+
end
|
data/lib/gd2/color.rb
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
module GD2
|
2
|
+
class Color
|
3
|
+
attr_reader :rgba
|
4
|
+
alias :to_i :rgba
|
5
|
+
class << self
|
6
|
+
alias [] new
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(r, g, b, a = ALPHA_OPAQUE)
|
10
|
+
r = self.class.normalize(r, RGB_MAX, :red)
|
11
|
+
g = self.class.normalize(g, RGB_MAX, :green)
|
12
|
+
b = self.class.normalize(b, RGB_MAX, :blue)
|
13
|
+
a = self.class.normalize(a, ALPHA_MAX, :alpha)
|
14
|
+
|
15
|
+
init_with_rgba(self.class.pack(r, g, b, a))
|
16
|
+
end
|
17
|
+
|
18
|
+
def init_with_rgba(rgba, index = nil, palette = nil) #:nodoc:
|
19
|
+
@rgba = rgba
|
20
|
+
@index = index
|
21
|
+
@palette = palette
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.pack(r, g, b, a) #:nodoc:
|
26
|
+
(a << 24) + (r << 16) + (g << 8) + b
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_s
|
30
|
+
s = 'RGB'
|
31
|
+
s += "A" if alpha != ALPHA_OPAQUE
|
32
|
+
s += "[#{@index}]" if @index
|
33
|
+
s += '#' + [red, green, blue].map { |e| '%02X' % e }.join('')
|
34
|
+
s += '%02X' % alpha if alpha != ALPHA_OPAQUE
|
35
|
+
s
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def self.normalize(value, max, component = nil) #:nodoc:
|
40
|
+
case value
|
41
|
+
when Integer
|
42
|
+
(value < 0) ? 0 : (value > max) ? max : value
|
43
|
+
when Float
|
44
|
+
normalize((value * max).round, max, component)
|
45
|
+
when Color
|
46
|
+
value.send(component)
|
47
|
+
else
|
48
|
+
return normalize(value.to_i, max) if value.respond_to?(:to_i)
|
49
|
+
raise TypeError
|
50
|
+
end
|
51
|
+
end
|
52
|
+
# Return the red component of this color (0..RGB_MAX).
|
53
|
+
def red
|
54
|
+
(rgba & 0xFF0000) >> 16
|
55
|
+
end
|
56
|
+
alias r red
|
57
|
+
|
58
|
+
# Modify the red component of this color. If this color is associated
|
59
|
+
# with a palette entry, this also modifies the palette.
|
60
|
+
#def red=(value)
|
61
|
+
# self.rgba = (rgba & ~0xFF0000) |
|
62
|
+
# (self.class.normalize(value, RGB_MAX, :red) << 16)
|
63
|
+
#end
|
64
|
+
#alias r= red=
|
65
|
+
|
66
|
+
# Return the green component of this color (0..RGB_MAX).
|
67
|
+
def green
|
68
|
+
(rgba & 0x00FF00) >> 8
|
69
|
+
end
|
70
|
+
alias g green
|
71
|
+
|
72
|
+
# Modify the green component of this color. If this color is associated
|
73
|
+
# with a palette entry, this also modifies the palette.
|
74
|
+
#def green=(value)
|
75
|
+
# self.rgba = (rgba & ~0x00FF00) |
|
76
|
+
# (self.class.normalize(value, RGB_MAX, :green) << 8)
|
77
|
+
#end
|
78
|
+
#alias g= green=
|
79
|
+
|
80
|
+
# Return the blue component of this color (0..RGB_MAX).
|
81
|
+
def blue
|
82
|
+
rgba & 0x0000FF
|
83
|
+
end
|
84
|
+
alias b blue
|
85
|
+
|
86
|
+
# Modify the blue component of this color. If this color is associated
|
87
|
+
# with a palette entry, this also modifies the palette.
|
88
|
+
#def blue=(value)
|
89
|
+
# self.rgba = (rgba & ~0x0000FF) |
|
90
|
+
# self.class.normalize(value, RGB_MAX, :blue)
|
91
|
+
#end
|
92
|
+
#alias b= blue=
|
93
|
+
|
94
|
+
# Return the alpha component of this color (0..ALPHA_MAX).
|
95
|
+
def alpha
|
96
|
+
(rgba & 0x7F000000) >> 24
|
97
|
+
end
|
98
|
+
alias a alpha
|
99
|
+
|
100
|
+
# Modify the alpha component of this color. If this color is associated
|
101
|
+
# with a palette entry, this also modifies the palette.
|
102
|
+
def alpha=(value)
|
103
|
+
self.rgba = (rgba & ~0xFF000000) |
|
104
|
+
(self.class.normalize(value, ALPHA_MAX, :alpha) << 24)
|
105
|
+
end
|
106
|
+
alias a= alpha=
|
107
|
+
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
data/lib/gd2/font.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
module GD2
|
2
|
+
class Font
|
3
|
+
class TrueType
|
4
|
+
|
5
|
+
class FreeTypeError < StandardError ; end
|
6
|
+
def initialize(fontname, ptsize, options = {})
|
7
|
+
@fontname, @ptsize = fontname, ptsize
|
8
|
+
|
9
|
+
# since no start of cache, no register!
|
10
|
+
# do the font path getting?
|
11
|
+
end
|
12
|
+
|
13
|
+
def draw(image_ptr, x, y, angle, string, fg)
|
14
|
+
brect = FFI::MemoryPointer.new(:int, 8)
|
15
|
+
string = string.gsub('&', '&')
|
16
|
+
error = CGD2::gdImageStringFT(image_ptr, brect, fg, @fontname, @ptsize, angle.to_f, x, y, string)
|
17
|
+
|
18
|
+
|
19
|
+
raise FreeTypeError, error unless error.null?
|
20
|
+
|
21
|
+
brect = brect.read_array_of_int(8)
|
22
|
+
|
23
|
+
{ :lower_left => [brect[0], brect[1]],
|
24
|
+
:lower_right => [brect[2], brect[3]],
|
25
|
+
:upper_right => [brect[4], brect[5]],
|
26
|
+
:upper_left => [brect[6], brect[7]]
|
27
|
+
#:position => position
|
28
|
+
}
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return a hash describing the rectangle that would enclose the given
|
33
|
+
# string rendered in this font at the given angle. The returned hash
|
34
|
+
# contains the following keys:
|
35
|
+
#
|
36
|
+
# - :lower_left => The [x, y] coordinates of the lower left corner.
|
37
|
+
# - :lower_right => The [x, y] coordinates of the lower right corner.
|
38
|
+
# - :upper_right => The [x, y] coordinates of the upper right corner.
|
39
|
+
# - :upper_left => The [x, y] coordinates of the upper left corner.
|
40
|
+
# - :position => An array of floating point character position offsets for
|
41
|
+
# each character of the +string+, beginning with 0.0. The array also
|
42
|
+
# includes a final position indicating where the last character ends.
|
43
|
+
#
|
44
|
+
# The _upper_, _lower_, _left_, and _right_ references are relative to the
|
45
|
+
# text of the +string+, regardless of the +angle+.
|
46
|
+
def bounding_rectangle(string, angle = 0.0)
|
47
|
+
data = draw(nil, 0, 0, angle, string, 0)
|
48
|
+
|
49
|
+
#if string.length == 1
|
50
|
+
# # gd annoyingly fails to provide xshow data for strings of length 1
|
51
|
+
# position = draw(nil, 0, 0, angle, string + ' ', 0)[:position]
|
52
|
+
# data[:position] = position[0...-1]
|
53
|
+
#end
|
54
|
+
|
55
|
+
data
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
#def draw(image_ptr, x, y, angle, string, fg) #:nodoc:
|
64
|
+
# brect = Array.new(8) { 0 }
|
65
|
+
# strex = strex(true)
|
66
|
+
# r, rs = SYM[:gdImageStringFTEx].call(image_ptr,
|
67
|
+
# brect, fg, @fontname, @ptsize, angle.to_f, x, y,
|
68
|
+
# string.gsub('&', '&'), strex)
|
69
|
+
# raise FreeTypeError, r if r
|
70
|
+
#
|
71
|
+
# brect = rs[1].to_a('I', 8)
|
72
|
+
#
|
73
|
+
# if xshow = strex[:xshow]
|
74
|
+
# xshow.free = SYM[:gdFree]
|
75
|
+
# xshow = xshow.to_s.split(' ').map { |e| e.to_f }
|
76
|
+
# else
|
77
|
+
# xshow = []
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
# sum = 0.0
|
81
|
+
# position = Array.new(xshow.length + 1)
|
82
|
+
# xshow.each_with_index do |advance, i|
|
83
|
+
# position[i] = sum
|
84
|
+
# sum += advance
|
85
|
+
# end
|
86
|
+
# position[-1] = sum
|
87
|
+
#
|
88
|
+
# { :lower_left => [brect[0], brect[1]],
|
89
|
+
# :lower_right => [brect[2], brect[3]],
|
90
|
+
# :upper_right => [brect[4], brect[5]],
|
91
|
+
# :upper_left => [brect[6], brect[7]],
|
92
|
+
# :position => position
|
93
|
+
# }
|
94
|
+
#end
|
95
|
+
#
|
data/lib/gd2/image.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module GD2
|
2
|
+
class Image
|
3
|
+
attr_reader :image_ptr
|
4
|
+
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
class Image::IndexedColor < Image
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
class Image::TrueColor < Image
|
13
|
+
def release(ptr)
|
14
|
+
CGD2::gdImageDestroy(ptr)
|
15
|
+
end
|
16
|
+
def initialize(w, h)
|
17
|
+
@image_ptr = FFI::AutoPointer.new(
|
18
|
+
CGD2::gdImageCreateTrueColor(w, h),
|
19
|
+
self.method(:release)
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def png
|
24
|
+
size = FFI::MemoryPointer.new(:pointer)
|
25
|
+
png_pointer = CGD2.gdImagePngPtr(@image_ptr, size)
|
26
|
+
|
27
|
+
size = size.get_int(0)
|
28
|
+
|
29
|
+
png = png_pointer.get_bytes(0, size)
|
30
|
+
|
31
|
+
CGD2::gdFree(png_pointer)
|
32
|
+
|
33
|
+
png
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/gd2-ffi.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ffi'
|
3
|
+
|
4
|
+
require 'gd2/cgd2'
|
5
|
+
require 'gd2/image'
|
6
|
+
require 'gd2/font'
|
7
|
+
require 'gd2/canvas'
|
8
|
+
require 'gd2/color'
|
9
|
+
|
10
|
+
module GD2
|
11
|
+
|
12
|
+
ALPHA_MAX = 127
|
13
|
+
ALPHA_OPAQUE = 0
|
14
|
+
ALPHA_TRANSPARENT = 127
|
15
|
+
|
16
|
+
RGB_MAX = 255
|
17
|
+
end
|
data/spec/Vera.ttf
ADDED
Binary file
|
data/spec/canvas_spec.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe "Canvas" do
|
4
|
+
before do
|
5
|
+
@image = GD2::Image::TrueColor.new(100, 100)
|
6
|
+
@black = GD2::Color[0,0,0]
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "FilledRectangle" do
|
10
|
+
it "should intitialze by two gd points" do
|
11
|
+
p1 = GD2::Canvas::Point.new(0,0)
|
12
|
+
p2 = GD2::Canvas::Point.new(10,10)
|
13
|
+
GD2::Canvas::FilledRectangle.new(p1, p2)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should call GD draw function" do
|
17
|
+
CGD2.should_receive(:gdImageFilledRectangle).with(anything, 0, 0, 10, 10, 0)
|
18
|
+
p1 = GD2::Canvas::Point.new(0,0)
|
19
|
+
p2 = GD2::Canvas::Point.new(10,10)
|
20
|
+
|
21
|
+
rect = GD2::Canvas::FilledRectangle.new(p1, p2)
|
22
|
+
|
23
|
+
rect.draw(@image, @black.to_i)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should convert Color to int" do
|
27
|
+
CGD2.should_receive(:gdImageFilledRectangle).with(anything, 0, 0, 10, 10, 0)
|
28
|
+
p1 = GD2::Canvas::Point.new(0,0)
|
29
|
+
p2 = GD2::Canvas::Point.new(10,10)
|
30
|
+
|
31
|
+
rect = GD2::Canvas::FilledRectangle.new(p1, p2)
|
32
|
+
|
33
|
+
rect.draw(@image, @black)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "TrueType" do
|
38
|
+
it "should find out the font path"
|
39
|
+
|
40
|
+
it "should call C function on draw" do
|
41
|
+
font = GD2::Font::TrueType.new(
|
42
|
+
"Vera.ttf",
|
43
|
+
10.0
|
44
|
+
)
|
45
|
+
|
46
|
+
p_text = GD2::Canvas::Point.new(1,2)
|
47
|
+
|
48
|
+
|
49
|
+
CGD2.should_receive(:gdImageStringFT).with(anything, anything, @black.to_i, "Vera.ttf", 10.0, 0.0, 1, 2, "foobar").and_return(mock("Pointer", :null? => true))
|
50
|
+
|
51
|
+
text = GD2::Canvas::Text.new(font, p_text, 0, "foobar")
|
52
|
+
text.draw(@image, @black)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should raise a FreeTypeError if the C call is unsuccesful" do
|
56
|
+
font = GD2::Font::TrueType.new(
|
57
|
+
"Vera.ttf",
|
58
|
+
10.0
|
59
|
+
)
|
60
|
+
|
61
|
+
p_text = GD2::Canvas::Point.new(1,2)
|
62
|
+
text = GD2::Canvas::Text.new(font, p_text, 0, "foobar")
|
63
|
+
|
64
|
+
CGD2.stub!(:gdImageStringFT).and_return(mock("Nullpointer", :null? => false))
|
65
|
+
lambda {
|
66
|
+
text.draw(@image, @black)
|
67
|
+
|
68
|
+
}.should raise_error(GD2::Font::TrueType::FreeTypeError)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/spec/color_spec.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe GD2::Color do
|
4
|
+
it "should initialize from int" do
|
5
|
+
GD2::Color.new(50,100,200).rgba.should eql(3302600)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should initialize with []" do
|
9
|
+
GD2::Color[50,100,200].rgba.should eql(3302600)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should have to_i" do
|
13
|
+
color = GD2::Color[50,100,200]
|
14
|
+
color.rgba.should eql(3302600)
|
15
|
+
color.to_i.should eql(color.rgba)
|
16
|
+
end
|
17
|
+
|
18
|
+
[
|
19
|
+
[:red, 50],
|
20
|
+
[:green, 100],
|
21
|
+
[:blue, 200]
|
22
|
+
].each do |color_name, value|
|
23
|
+
it "should return the #{color_name} value" do
|
24
|
+
color = GD2::Color[50,100,200]
|
25
|
+
color.send(color_name).should eql(value)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should return color #{color_name} by first letter" do
|
29
|
+
color_name = color_name.to_s[0..0].to_sym
|
30
|
+
color = GD2::Color[50,100,200]
|
31
|
+
color.send(color_name).should eql(value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
end
|
data/spec/image_spec.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe GD2::Image::TrueColor do
|
4
|
+
before do
|
5
|
+
CGD2.stub!(:gdFree)
|
6
|
+
end
|
7
|
+
it "should generate png string" do
|
8
|
+
image = GD2::Image::TrueColor.new(100, 100)
|
9
|
+
CGD2.should_receive(:gdImagePngPtr).and_return(mock("Pointer", :get_bytes => ''))
|
10
|
+
|
11
|
+
image.png
|
12
|
+
end
|
13
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/test.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
$: << 'lib'
|
2
|
+
require 'gd2'
|
3
|
+
image_height = 100
|
4
|
+
image_width = 200
|
5
|
+
|
6
|
+
options = {
|
7
|
+
:offset_x => 1,
|
8
|
+
:margin => 10,
|
9
|
+
:offset_y => 10,
|
10
|
+
:line_spacing => 2
|
11
|
+
}
|
12
|
+
line = "foobar"
|
13
|
+
|
14
|
+
|
15
|
+
font = GD2::Font::TrueType.new(
|
16
|
+
"Vera.ttf",
|
17
|
+
10.0
|
18
|
+
)
|
19
|
+
|
20
|
+
black = GD2::Color[0.0, 0.0, 0.0]
|
21
|
+
|
22
|
+
p1 = GD2::Canvas::Point.new(0,0)
|
23
|
+
p2 = GD2::Canvas::Point.new(image_width, image_height)
|
24
|
+
p3 = GD2::Canvas::Point.new(image_width, 0)
|
25
|
+
p4 = GD2::Canvas::Point.new(image_width * 2, image_height)
|
26
|
+
|
27
|
+
bg_rect = GD2::Canvas::FilledRectangle.new(p1, p2)
|
28
|
+
bg_rect_sprite = GD2::Canvas::FilledRectangle.new(p3, p4)
|
29
|
+
|
30
|
+
white = GD2::Color[1.0, 1.0, 1.0]
|
31
|
+
yellow = GD2::Color[1.0, 0.8, 0.0]
|
32
|
+
|
33
|
+
p_text = GD2::Canvas::Point.new(
|
34
|
+
options[:offset_x] + options[:margin],
|
35
|
+
options[:offset_y] + options[:line_spacing] * (0 + 1))
|
36
|
+
|
37
|
+
image = GD2::Image::TrueColor.new(image_width * 2, image_height)
|
38
|
+
bg_rect.draw(image, white.to_i)
|
39
|
+
bg_rect_sprite.draw(image, yellow.to_i)
|
40
|
+
|
41
|
+
text = GD2::Canvas::Text.new(font, p_text, 0, line)
|
42
|
+
begin
|
43
|
+
text.draw(image, black)
|
44
|
+
rescue => e
|
45
|
+
puts e.message
|
46
|
+
end
|
47
|
+
|
48
|
+
File.open("foo.png", "wb") do |file|
|
49
|
+
file.write(image.png)
|
50
|
+
end
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spatrik-gd2-ffi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Patrik Stenmark
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-08-05 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: gd2-ffi is ruby bindings for gd2, implemented with ffi
|
17
|
+
email: patrik.stenmark@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.md
|
24
|
+
files:
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- VERSION
|
28
|
+
- gd2-ffi.gemspec
|
29
|
+
- lib/gd2-ffi.rb
|
30
|
+
- lib/gd2/canvas.rb
|
31
|
+
- lib/gd2/cgd2.rb
|
32
|
+
- lib/gd2/color.rb
|
33
|
+
- lib/gd2/font.rb
|
34
|
+
- lib/gd2/image.rb
|
35
|
+
- spec/Vera.ttf
|
36
|
+
- spec/canvas_spec.rb
|
37
|
+
- spec/color_spec.rb
|
38
|
+
- spec/image_spec.rb
|
39
|
+
- spec/spec_helper.rb
|
40
|
+
- test.rb
|
41
|
+
has_rdoc: false
|
42
|
+
homepage: http://github.com/spatrik/gd2-ffi
|
43
|
+
licenses:
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options:
|
46
|
+
- --charset=UTF-8
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
version:
|
61
|
+
requirements: []
|
62
|
+
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 1.3.5
|
65
|
+
signing_key:
|
66
|
+
specification_version: 3
|
67
|
+
summary: gd2-ffi is ruby bindings for gd2, implemented with ffi
|
68
|
+
test_files:
|
69
|
+
- spec/canvas_spec.rb
|
70
|
+
- spec/color_spec.rb
|
71
|
+
- spec/image_spec.rb
|
72
|
+
- spec/spec_helper.rb
|