painter 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README ADDED
File without changes
File without changes
@@ -0,0 +1,133 @@
1
+ require 'ffi'
2
+ require 'painter/image_struct'
3
+ require 'painter/stdio'
4
+ require 'painter/cgd2'
5
+ require 'painter/operation'
6
+ require 'painter/image'
7
+ require 'painter/font'
8
+ require 'painter/canvas'
9
+ require 'painter/color'
10
+ require 'painter/rect'
11
+ require 'painter/pixel'
12
+ require 'painter/text'
13
+ require 'painter/point'
14
+ require 'painter/line'
15
+
16
+ class Painter
17
+ attr_reader :image_pointer
18
+
19
+ def self.write(path, x, y, file_format)
20
+ instance = new
21
+ instance.initializeFromCreate(x,y)
22
+ yield instance
23
+ File.open(path, 'w') do |f|
24
+ instance.format(file_format) do |data|
25
+ f.write data
26
+ end
27
+ end
28
+ ensure
29
+ instance.release!
30
+ end
31
+
32
+ def self.open(path, format = nil)
33
+ instance = new
34
+ instance.initializeFromOpen(path, format)
35
+ yield instance
36
+ ensure
37
+ instance.release!
38
+ end
39
+
40
+ def release!
41
+ CGD2::gdImageDestroy(@image_pointer)
42
+ end
43
+
44
+ def degrees(n)
45
+ n * 2 * Math::PI / 360
46
+ end
47
+
48
+ ALPHA_MAX = 127
49
+ ALPHA_OPAQUE = 0
50
+ ALPHA_TRANSPARENT = 127
51
+ RGB_MAX = 255
52
+
53
+ def release(ptr)
54
+ CGD2::gdImageDestroy(ptr)
55
+ end
56
+
57
+ def initializeFromCreate(x, y, options = {})
58
+ @image_pointer = FFI::Pointer.new(CGD2::gdImageCreateTrueColor(x, y))
59
+ end
60
+
61
+
62
+ FORMAT_TO_FUNCTION = {
63
+ 'jpg' => :gdImageCreateFromJpeg,
64
+ 'png' => :gdImageCreateFromPng,
65
+ 'gif' => :gdImageCreateFromGif,
66
+ 'gd' => :gdImageCreateFromGd,
67
+ 'gd2' => :gdImageCreateFromGd2,
68
+ 'wbmp' => :gdImageCreateFromWBMP,
69
+ 'xbm' => :gdImageCreateFromXbm
70
+ }
71
+
72
+ def format_from_filename(path)
73
+ path[/\.([^.]*)$/, 1].downcase
74
+ end
75
+
76
+ def initializeFromOpen(path, format = nil)
77
+ f = Painter::Stdio.fopen(path, "rb")
78
+ format ||= format_from_filename(path)
79
+ function_name = FORMAT_TO_FUNCTION[format.to_s]
80
+ raise "Unknown format: #{format}" unless function_name
81
+ @image_pointer = CGD2.send(function_name, f)
82
+ Painter::Stdio.fclose(f)
83
+ end
84
+
85
+ def info
86
+ @info ||= Painter::ImageStruct.new @image_pointer
87
+ end
88
+
89
+ # Operations
90
+ {'pixel' => 'Pixel', 'rect' => 'Rect', 'text' => 'Text', 'line' => 'Line'}.each do |op, klass|
91
+ class_eval <<-END
92
+ def #{op}
93
+ #{op}_instance = #{klass}.new(self)
94
+ yield #{op}_instance
95
+ #{op}_instance.draw
96
+ end
97
+ END
98
+ end
99
+
100
+ def resize_to(destination)
101
+ CGD2::gdImageCopyResampled(destination.image_pointer, self.image_pointer,
102
+ 0, 0, 0, 0,
103
+ destination.info.x, destination.info.y, self.info.x, self.info.y)
104
+ end
105
+
106
+ OUTPUT_FORMAT_TO_FUNCTION = {
107
+ 'gif' => :gdImageGifPtr,
108
+ 'jpeg' => :gdImageJpegPtr,
109
+ 'jpg' => :gdImageJpegPtr,
110
+ 'png' => :gdImagePngPtr,
111
+ 'wbmp' => :gdImageWBMPPtr,
112
+ 'gd' => :gdImageGdPtr,
113
+ 'gd2' => :gdImageGd2
114
+ }
115
+ def format(file_format, quality = 100)
116
+ size = FFI::MemoryPointer.new(:pointer)
117
+ function_name = OUTPUT_FORMAT_TO_FUNCTION[file_format.to_s]
118
+ raise "Unknown format: #{file_format}" unless function_name
119
+ args = [@image_pointer, size]
120
+ if function_name == :gdImageJpegPtr
121
+ args << quality
122
+ end
123
+ begin
124
+ ip = CGD2.send(function_name, *args)
125
+ size = size.get_int(0)
126
+ data = ip.get_bytes(0, size)
127
+ yield data
128
+ ensure
129
+ CGD2::gdFree(ip)
130
+ end
131
+ end
132
+
133
+ end
@@ -0,0 +1,43 @@
1
+ class Painter
2
+ module CGD2
3
+ extend FFI::Library
4
+ local_path = ["/opt/local/lib/libgd.2.dylib", '/usr/lib/libgd.so.2'].detect do |lib|
5
+ File.exists?(lib)
6
+ end
7
+ ffi_lib local_path
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
+ attach_function :gdImageSetPixel, [:pointer, :int, :int, :int], :void
17
+ attach_function :gdImageLine, [:pointer, :int, :int, :int, :int, :int], :void
18
+
19
+ #char *gdImageStringFT(gdImagePtr im, int *brect, int fg, char *fontname, double ptsize, double angle, int x, int y, char *string) (FUNCTION)
20
+ attach_function :gdImageStringFT, [:pointer, :pointer, :int, :string, :double, :double, :int, :int, :string], :pointer
21
+
22
+ # void* gdImagePngPtr(gdImagePtr im, int *size) (FUNCTION)
23
+ [:gdImageGifPtr, :gdImagePngPtr, :gdImageWBMPPtr,
24
+ :gdImageGdPtr, :gdImageGd2].each do |format_function|
25
+ attach_function format_function, [:pointer, :pointer], :pointer
26
+ end
27
+
28
+ attach_function :gdImageJpegPtr, [:pointer, :pointer, :int], :pointer
29
+
30
+ [:gdImageCreateFromJpeg, :gdImageCreateFromPng, :gdImageCreateFromGif,
31
+ :gdImageCreateFromGd, :gdImageCreateFromGd2, :gdImageCreateFromWBMP,
32
+ :gdImageCreateFromXbm].each do |format_function|
33
+ attach_function format_function, [:pointer], :pointer
34
+ end
35
+
36
+ #Resizing
37
+ attach_function :gdImageCopyResampled, [:pointer, :pointer, :int, :int, :int, :int, :int, :int, :int, :int], :void
38
+
39
+ # gdImageDestroy(gdImagePtr im) (FUNCTION)
40
+ attach_function :gdImageDestroy, [:pointer], :void
41
+ attach_function :gdFree, [:pointer], :void
42
+ end
43
+ end
@@ -0,0 +1,110 @@
1
+ class Painter
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
@@ -0,0 +1,35 @@
1
+ class Painter
2
+ class ImageStruct < FFI::Struct
3
+ MAXCOLORS = 256
4
+ layout :pixels, :pointer,
5
+ :sx, :int,
6
+ :sy, :int,
7
+ :colorsTotal, :int,
8
+ :red, [:int, MAXCOLORS],
9
+ :green, [:int, MAXCOLORS],
10
+ :blue, [:int, MAXCOLORS],
11
+ :open, [:int, MAXCOLORS],
12
+ :transparent, :int,
13
+ :polyInts, :pointer,
14
+ :polyAllocated, :int,
15
+ :brush, :pointer,
16
+ :tile, :pointer,
17
+ :brushColorMap, [:int, MAXCOLORS],
18
+ :tileColorMap, [:int, MAXCOLORS],
19
+ :styleLength, :int,
20
+ :stylePos, :int,
21
+ :style, :pointer,
22
+ :interlace, :int,
23
+ :alpha, [:int, MAXCOLORS],
24
+ :trueColor, :int,
25
+ :tpixels, :pointer,
26
+ :alphaBlendingFlag, :int,
27
+ :saveAlphaFlag, :int
28
+ def x
29
+ self[:sx]
30
+ end
31
+ def y
32
+ self[:sy]
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,8 @@
1
+ class Painter
2
+ class Line < Operation
3
+ def draw
4
+ ::Painter::CGD2::gdImageLine(@image.image_pointer,
5
+ @_from.x, @_from.y, @_to.x, @_to.y, _color.rgba)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,45 @@
1
+ class Painter
2
+ class Operation
3
+ def self.pretty_accessor(*names)
4
+ names.each do |n|
5
+ attr_reader n.to_sym
6
+ class_eval <<-END
7
+ def #{n}(v)
8
+ @_#{n} = v
9
+ end
10
+ def _#{n}
11
+ @_#{n}
12
+ end
13
+ END
14
+ end
15
+ end
16
+ def initialize(i)
17
+ @image = i
18
+ end
19
+
20
+ pretty_accessor :at
21
+
22
+ %w[at from to].each do |point|
23
+ class_eval <<-END
24
+ def #{point}(x,y)
25
+ @_#{point} = Point.new(x,y)
26
+ end
27
+ END
28
+ end
29
+
30
+ def angle(n)
31
+ @_angle = (n * Math::PI / 180.0)
32
+ end
33
+
34
+ def _angle
35
+ @_angle || 0
36
+ end
37
+
38
+ def color(r,g,b,a = nil)
39
+ @_color = Painter::Color.new(r,g,b,a)
40
+ end
41
+ def _color
42
+ @_color || Painter::Color.new(1, 1, 1)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,8 @@
1
+ class Painter
2
+ class Pixel < Operation
3
+ def draw
4
+ ::Painter::CGD2::gdImageSetPixel(@image.image_pointer,
5
+ @_at.x, @_at.y, _color.rgba)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ class Painter
2
+ class Point < Struct.new(:x,:y)
3
+ end
4
+ end
@@ -0,0 +1,19 @@
1
+ class Painter
2
+ class Rect < Operation
3
+ pretty_accessor :bottomX, :bottomY
4
+
5
+ def topLeft(x,y)
6
+ @_topLeft = Point.new(x,y)
7
+ end
8
+
9
+ def bottomRight(x,y)
10
+ @_bottomRight = Point.new(x,y)
11
+ end
12
+
13
+ def draw
14
+ ::Painter::CGD2::gdImageFilledRectangle(@image.image_pointer,
15
+ @_topLeft.x, @_topLeft.y,
16
+ @_bottomRight.x, @_bottomRight.y, _color.rgba)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,8 @@
1
+ class Painter
2
+ module Stdio
3
+ extend FFI::Library
4
+ ffi_lib FFI::Library::LIBC
5
+ attach_function :fopen, [:string, :string], :pointer
6
+ attach_function :fclose, [:pointer], :int
7
+ end
8
+ end
@@ -0,0 +1,23 @@
1
+ class Painter
2
+ class Text < Operation
3
+ class BlankFontError < StandardError
4
+ end
5
+ class MissingFontError < StandardError
6
+ end
7
+ pretty_accessor :font, :size, :text, :point
8
+
9
+ def draw
10
+ raise BlankFontError if _font.nil?
11
+ raise MissingFontError, _font unless File.exists?(_font)
12
+ brect = FFI::MemoryPointer.new(:int, 8)
13
+ error = CGD2::gdImageStringFT(@image.image_pointer, brect, _color.rgba, _font,
14
+ _size.to_f, _angle.to_f, _at.x, _at.y, _text.gsub('&', '&amp;'))
15
+ raise "Drawing error: #{error}" unless error.null?
16
+ brect = brect.read_array_of_int(8)
17
+ { :lower_left => [brect[0], brect[1]],
18
+ :lower_right => [brect[2], brect[3]],
19
+ :upper_right => [brect[4], brect[5]],
20
+ :upper_left => [brect[6], brect[7]]}
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
2
+
3
+ describe Painter::Color do
4
+ it "should initialize from int" do
5
+ Painter::Color.new(50,100,200).rgba.should eql(3302600)
6
+ end
7
+
8
+ it "should initialize with []" do
9
+ Painter::Color[50,100,200].rgba.should eql(3302600)
10
+ end
11
+
12
+ it "should have to_i" do
13
+ color = Painter::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 = Painter::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 = Painter::Color[50,100,200]
31
+ color.send(color_name).should eql(value)
32
+ end
33
+ end
34
+
35
+
36
+ end
Binary file
Binary file
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
2
+
3
+ describe Painter::Image::TrueColor do
4
+ it_should_behave_like "painter"
5
+
6
+ before do
7
+ Painter::CGD2.stub!(:gdFree)
8
+ end
9
+
10
+ it "should generate png string" do
11
+ image = Painter::Image::TrueColor.new(100, 100)
12
+ Painter::CGD2.should_receive(:gdImagePngPtr).and_return(mock("Pointer", :get_bytes => ''))
13
+ image.png do |data|
14
+ data.size.should > 0
15
+ end
16
+ end
17
+
18
+ it "should read the image struct" do
19
+ Painter.open("#{File.dirname(__FILE__)}/fixtures/sample.jpg", :jpg) do |i|
20
+ i.info.x.should == 438
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
2
+
3
+ describe 'integration' do
4
+ it "should draw an image" do
5
+ srand(Time.now.to_i)
6
+ Painter.write("#{File.dirname(__FILE__)}/output/captcha.png", 200, 100, :png) do |painter|
7
+ painter.rect do |rect|
8
+ rect.color 255, 255, 255
9
+ rect.topLeft 0, 0
10
+ rect.bottomRight 200, 100
11
+ end
12
+ painter.text do |text|
13
+ text.font "#{File.dirname(__FILE__)}/fixtures/Vera.ttf"
14
+ text.at 10, 50
15
+ text.text "Hello World"
16
+ text.angle rand(20)
17
+ text.size 14
18
+ end
19
+ offset = rand(10)
20
+ 0.upto(300) do |i|
21
+ painter.pixel do |pixel|
22
+ pixel.at i, ((Math.sin((i + offset) / (4 * Math::PI)) * 30).to_i + 50)
23
+ pixel.color(rand(5), rand(5), rand(5))
24
+ end
25
+ end
26
+ painter.line do |line|
27
+ line.from 0, (25 + rand(50))
28
+ line.to 200, (25 + rand(50))
29
+ line.color rand(10), rand(10), rand(10)
30
+ end
31
+ end
32
+ end
33
+
34
+ it "should write to a variety of formats" do
35
+ [:jpg, :png, :wbmp, :gif].each do |format|
36
+ Painter.write("#{File.dirname(__FILE__)}/output/format.#{format}", 48, 48, format) do |output|
37
+ Painter.open("#{File.dirname(__FILE__)}/fixtures/sample.jpg", :jpg) do |source|
38
+ source.resize_to(output)
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ it "should resize images" do
45
+ Painter.write("#{File.dirname(__FILE__)}/output/resized.png", 48, 48, :png) do |output|
46
+ Painter.open("#{File.dirname(__FILE__)}/fixtures/sample.jpg", :jpg) do |source|
47
+ source.resize_to(output)
48
+ end
49
+ end
50
+ end
51
+
52
+ end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,27 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
2
+
3
+ describe "rect" do
4
+ it_should_behave_like "painter"
5
+ before(:each) do
6
+ @painter = Painter.new
7
+ @painter.initializeFromCreate(640, 480)
8
+ end
9
+
10
+ it "should call GD draw function" do
11
+ Painter::CGD2.should_receive(:gdImageFilledRectangle).with(@painter.image_pointer, 0, 0, 10, 10, @white.rgba)
12
+ @painter.rect do |rect|
13
+ rect.topLeft 0, 0
14
+ rect.bottomRight 10, 10
15
+ end
16
+ end
17
+
18
+ it "should convert Color to int" do
19
+ Painter::CGD2.should_receive(:gdImageFilledRectangle).with(@painter.image_pointer, 0, 0, 10, 10, @black.rgba)
20
+ @painter.rect do |rect|
21
+ rect.color 0, 0, 0
22
+ rect.topLeft 0, 0
23
+ rect.bottomRight 10, 10
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'rbconfig'
3
+ require 'spec'
4
+
5
+ $: << 'lib'
6
+ require 'painter'
7
+ describe "painter", :shared => true do
8
+ before(:each) do
9
+ @white = Painter::Color.new(1, 1, 1)
10
+ @black = Painter::Color.new(0, 0, 0)
11
+ end
12
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
2
+
3
+ describe "text" do
4
+ it_should_behave_like "painter"
5
+ before(:each) do
6
+ @painter = Painter.new
7
+ @painter.initializeFromCreate(640, 480)
8
+ end
9
+
10
+ it "should call C function on draw" do
11
+ Painter::CGD2.should_receive(:gdImageStringFT).
12
+ with(@painter.image_pointer, anything, @black.rgba, "#{File.dirname(__FILE__)}/fixtures/Vera.ttf", 14.0, 0.0, 100, 50, "Hello World").
13
+ and_return(mock("Pointer", :null? => true))
14
+ @painter.text do |text|
15
+ text.color 0, 0, 0
16
+ text.font "#{File.dirname(__FILE__)}/fixtures/Vera.ttf"
17
+ text.at 100, 50
18
+ text.text "Hello World"
19
+ text.angle 0
20
+ text.size 14
21
+ end
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: painter
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 4
10
+ version: 0.0.4
11
+ platform: ruby
12
+ authors:
13
+ - Ben Sandofsky
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-05-20 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: ffi
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: A clean wrapper around the GD2 graphics library, based on gd2-ffi
36
+ email: sandofsky@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - lib/painter/cgd2.rb
45
+ - lib/painter/color.rb
46
+ - lib/painter/image_struct.rb
47
+ - lib/painter/line.rb
48
+ - lib/painter/operation.rb
49
+ - lib/painter/pixel.rb
50
+ - lib/painter/point.rb
51
+ - lib/painter/rect.rb
52
+ - lib/painter/stdio.rb
53
+ - lib/painter/text.rb
54
+ - lib/painter.rb
55
+ - spec/color_spec.rb
56
+ - spec/fixtures/sample.jpg
57
+ - spec/fixtures/Vera.ttf
58
+ - spec/image_spec.rb
59
+ - spec/integration.rb
60
+ - spec/output/captcha.png
61
+ - spec/output/format.gif
62
+ - spec/output/format.jpg
63
+ - spec/output/format.png
64
+ - spec/output/format.wbmp
65
+ - spec/output/resized.png
66
+ - spec/rect_spec.rb
67
+ - spec/spec_helper.rb
68
+ - spec/text_spec.rb
69
+ - README
70
+ - Rakefile
71
+ has_rdoc: true
72
+ homepage: http://github.com/sandofsky/painter
73
+ licenses: []
74
+
75
+ post_install_message:
76
+ rdoc_options: []
77
+
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ hash: 3
95
+ segments:
96
+ - 0
97
+ version: "0"
98
+ requirements: []
99
+
100
+ rubyforge_project:
101
+ rubygems_version: 1.3.7
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: A clean wrapper around the GD2 graphics library, based on gd2-ffi
105
+ test_files:
106
+ - spec/color_spec.rb
107
+ - spec/image_spec.rb
108
+ - spec/image_spec.rb
109
+ - spec/rect_spec.rb
110
+ - spec/text_spec.rb
111
+ - spec/spec_helper.rb