cairo 1.4.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of cairo might be problematic. Click here for more details.
- data/AUTHORS +4 -0
- data/COPYING +59 -0
- data/ChangeLog +792 -0
- data/GPL +340 -0
- data/NEWS +29 -0
- data/README +32 -0
- data/Rakefile +103 -0
- data/extconf.rb +115 -0
- data/pkg-config.rb +126 -0
- data/samples/pac.rb +106 -0
- data/samples/pac2.rb +177 -0
- data/samples/png.rb +43 -0
- data/samples/scalable.rb +58 -0
- data/samples/text-on-path.rb +61 -0
- data/samples/text2.rb +127 -0
- data/src/cairo.def +58 -0
- data/src/lib/cairo.rb +77 -0
- data/src/lib/cairo/context.rb +13 -0
- data/src/lib/cairo/context/circle.rb +9 -0
- data/src/lib/cairo/context/path.rb +127 -0
- data/src/lib/cairo/context/quad.rb +19 -0
- data/src/lib/cairo/context/rectangle.rb +33 -0
- data/src/rb_cairo.c +90 -0
- data/src/rb_cairo.h +180 -0
- data/src/rb_cairo_constants.c +342 -0
- data/src/rb_cairo_context.c +1403 -0
- data/src/rb_cairo_exception.c +192 -0
- data/src/rb_cairo_font_extents.c +124 -0
- data/src/rb_cairo_font_face.c +63 -0
- data/src/rb_cairo_font_options.c +195 -0
- data/src/rb_cairo_glyph.c +158 -0
- data/src/rb_cairo_matrix.c +257 -0
- data/src/rb_cairo_path.c +88 -0
- data/src/rb_cairo_pattern.c +480 -0
- data/src/rb_cairo_private.c +51 -0
- data/src/rb_cairo_private.h +23 -0
- data/src/rb_cairo_scaled_font.c +184 -0
- data/src/rb_cairo_surface.c +837 -0
- data/src/rb_cairo_text_extents.c +137 -0
- metadata +89 -0
data/extconf.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# vim: filetype=ruby:expandtab:shiftwidth=2:tabstop=8:softtabstop=2 :
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(".")
|
5
|
+
|
6
|
+
require 'English'
|
7
|
+
require 'mkmf'
|
8
|
+
require 'pkg-config'
|
9
|
+
require 'fileutils'
|
10
|
+
|
11
|
+
# from mkmf-gnome2.rb
|
12
|
+
STDOUT.print("checking for GCC... ")
|
13
|
+
STDOUT.flush
|
14
|
+
if macro_defined?("__GNUC__", "")
|
15
|
+
STDOUT.print "yes\n"
|
16
|
+
$CFLAGS += ' -Wall'
|
17
|
+
$cc_is_gcc = true
|
18
|
+
else
|
19
|
+
STDOUT.print "no\n"
|
20
|
+
$cc_is_gcc = false
|
21
|
+
end
|
22
|
+
|
23
|
+
def check_win32()
|
24
|
+
STDOUT.print("checking for Win32 OS... ")
|
25
|
+
STDOUT.flush
|
26
|
+
if /cygwin|mingw|mswin32/ =~ RUBY_PLATFORM
|
27
|
+
$defs << "-DRUBY_CAIRO_PLATFORM_WIN32"
|
28
|
+
STDOUT.print "yes\n"
|
29
|
+
if $cc_is_gcc
|
30
|
+
if /^2\./ =~ `#{Config::CONFIG['CC']} -dumpversion`.chomp
|
31
|
+
$CFLAGS += ' -fnative-struct'
|
32
|
+
else
|
33
|
+
$CFLAGS += ' -mms-bitfields'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
else
|
37
|
+
STDOUT.print "no\n"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def set_output_lib(target_name)
|
42
|
+
if /cygwin|mingw/ =~ RUBY_PLATFORM
|
43
|
+
filename = "libruby-#{target_name}.a"
|
44
|
+
if RUBY_VERSION > "1.8.0"
|
45
|
+
$DLDFLAGS << ",--out-implib=#{filename}" if filename
|
46
|
+
elsif RUBY_VERSION > "1.8"
|
47
|
+
$DLDFLAGS.gsub!(/ -Wl,--out-implib=[^ ]+/, '')
|
48
|
+
$DLDFLAGS << " -Wl,--out-implib=#{filename}" if filename
|
49
|
+
else
|
50
|
+
$DLDFLAGS.gsub!(/ --output-lib\s+[^ ]+/, '')
|
51
|
+
$DLDFLAGS << " --output-lib #{filename}" if filename
|
52
|
+
end
|
53
|
+
elsif /mswin32/ =~ RUBY_PLATFORM
|
54
|
+
filename = "libruby-#{target_name}.lib"
|
55
|
+
$DLDFLAGS.gsub!(/ --output-lib\s+[^ ]+/, '')
|
56
|
+
$DLDFLAGS.gsub!(/ \/IMPLIB:[^ ]+/, '')
|
57
|
+
$DLDFLAGS << " /IMPLIB:#{filename}" if filename
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def setup_win32(target_name)
|
62
|
+
check_win32
|
63
|
+
set_output_lib(target_name)
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
pkg = "cairo"
|
68
|
+
modname = "cairo"
|
69
|
+
ext_dir_name = "src"
|
70
|
+
srcdir = File.join(File.expand_path(File.dirname(__FILE__)), ext_dir_name)
|
71
|
+
major, minor, micro = 1, 2, 0
|
72
|
+
|
73
|
+
PKGConfig.have_package(pkg, major, minor, micro) or exit 1
|
74
|
+
|
75
|
+
setup_win32(File.basename(modname))
|
76
|
+
$defs << "-DRUBY_CAIRO_COMPILATION"
|
77
|
+
create_makefile(modname, srcdir)
|
78
|
+
|
79
|
+
makefile = File.read("Makefile")
|
80
|
+
File.open("Makefile", "w") do |f|
|
81
|
+
objs = []
|
82
|
+
co = nil
|
83
|
+
makefile.each do |line|
|
84
|
+
case line
|
85
|
+
when /^TARGET\s*=\s*/
|
86
|
+
f.print("TARGET = #{ext_dir_name}/#{$POSTMATCH}")
|
87
|
+
when /^(SRCS)\s*=\s*/
|
88
|
+
name = $1
|
89
|
+
vars = $POSTMATCH.split.collect {|var| "$(srcdir)/#{var}"}.join(" ")
|
90
|
+
f.puts("#{name} = #{vars}")
|
91
|
+
when /^(OBJS|CLEANLIBS|CLEANOBJS)\s*=\s*/
|
92
|
+
name = $1
|
93
|
+
vars = $POSTMATCH.split.collect {|var| "#{ext_dir_name}/#{var}"}
|
94
|
+
objs = vars if name == "OBJS"
|
95
|
+
vars = vars.join(" ")
|
96
|
+
f.puts("#{name} = #{vars}")
|
97
|
+
when /^\t\$\(CC\)/
|
98
|
+
line = "#{line.chomp} -o $@" if /-o/ !~ line
|
99
|
+
co = line
|
100
|
+
f.puts(line)
|
101
|
+
else
|
102
|
+
f.print(line)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
if co and !objs.empty?
|
107
|
+
f.puts
|
108
|
+
objs.each do |obj|
|
109
|
+
f.puts "#{obj}: $(srcdir)/#{File.basename(obj).sub(/.o$/, '.c')}"
|
110
|
+
f.puts co
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
FileUtils.mkdir_p(ext_dir_name)
|
data/pkg-config.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
#
|
2
|
+
# pkg-config.rb
|
3
|
+
#
|
4
|
+
# Wrapper of pkg-config tool.
|
5
|
+
#
|
6
|
+
# Copyright(C) 2003-2005 Ruby-GNOME2 Project.
|
7
|
+
#
|
8
|
+
# This program is licenced under the same
|
9
|
+
# license of Ruby-GNOME2.
|
10
|
+
#
|
11
|
+
|
12
|
+
require 'mkmf'
|
13
|
+
require 'shellwords'
|
14
|
+
|
15
|
+
module PKGConfig
|
16
|
+
@@cmd = with_config('pkg-config', ENV["PKG_CONFIG"] || 'pkg-config')
|
17
|
+
if /mswin32/ =~ RUBY_PLATFORM and /^cl\b/ =~ Config::CONFIG['CC']
|
18
|
+
@@cmd += ' --msvc-syntax'
|
19
|
+
end
|
20
|
+
|
21
|
+
@@list = {}
|
22
|
+
`#{@@cmd} --list-all`.chomp.split(/\n/).each{|v|
|
23
|
+
pkg, name, desc = /(\S+?)\s+(.*?)\s-\s(.*)/.match(v).to_a[1..3]
|
24
|
+
@@list[pkg] = [name, desc]
|
25
|
+
}
|
26
|
+
|
27
|
+
module_function
|
28
|
+
def exist?(pkg)
|
29
|
+
system("#{@@cmd} --exists #{pkg}")
|
30
|
+
end
|
31
|
+
|
32
|
+
def libs(pkg)
|
33
|
+
`#{@@cmd} --libs #{pkg}`.chomp
|
34
|
+
end
|
35
|
+
|
36
|
+
def libs_only_L(pkg)
|
37
|
+
`#{@@cmd} --libs-only-L #{pkg}`.chomp
|
38
|
+
end
|
39
|
+
|
40
|
+
def libs_only_l(pkg)
|
41
|
+
`#{@@cmd} --libs-only-l #{pkg}`.chomp
|
42
|
+
end
|
43
|
+
|
44
|
+
def cflags(pkg)
|
45
|
+
`#{@@cmd} --cflags #{pkg}`.chomp
|
46
|
+
end
|
47
|
+
|
48
|
+
def cflags_only_I(pkg)
|
49
|
+
`#{@@cmd} --cflags-only-I #{pkg}`.chomp
|
50
|
+
end
|
51
|
+
|
52
|
+
def cflags_only_other(pkg)
|
53
|
+
`#{@@cmd} --cflags-only-other #{pkg}`.chomp
|
54
|
+
end
|
55
|
+
|
56
|
+
def variable(pkg, var)
|
57
|
+
`#{@@cmd} --variable=#{var} #{pkg}`.chomp
|
58
|
+
end
|
59
|
+
|
60
|
+
def modversion(pkg)
|
61
|
+
`#{@@cmd} --modversion #{pkg}`.chomp
|
62
|
+
end
|
63
|
+
|
64
|
+
def version
|
65
|
+
`#{@@cmd} --version`.chomp
|
66
|
+
end
|
67
|
+
|
68
|
+
def list_all
|
69
|
+
# Returns [pkg, name, description]
|
70
|
+
@@list.keys.collect{|key| [key] + @@list[key]}.sort
|
71
|
+
end
|
72
|
+
|
73
|
+
def name(pkg)
|
74
|
+
@@list[pkg][0]
|
75
|
+
end
|
76
|
+
|
77
|
+
def description(pkg)
|
78
|
+
@@list[pkg][1]
|
79
|
+
end
|
80
|
+
|
81
|
+
def provides(pkg)
|
82
|
+
`#{@@cmd} --print-provides #{pkg}`.chomp
|
83
|
+
end
|
84
|
+
|
85
|
+
def requires(pkg)
|
86
|
+
`#{@@cmd} --print-requires #{pkg}`.chomp.gsub("\n", ", ")
|
87
|
+
end
|
88
|
+
|
89
|
+
def check_version?(pkg, major = 0, minor = 0, micro = 0)
|
90
|
+
return false unless exist?(pkg)
|
91
|
+
ver = modversion(pkg).split(".").collect{|item| item.to_i}
|
92
|
+
(0..2).each {|i| ver[i] = 0 unless ver[i]}
|
93
|
+
|
94
|
+
(ver[0] > major ||
|
95
|
+
(ver[0] == major && ver[1] > minor) ||
|
96
|
+
(ver[0] == major && ver[1] == minor &&
|
97
|
+
ver[2] >= micro))
|
98
|
+
end
|
99
|
+
|
100
|
+
def have_package(pkg, major = nil, minor = 0, micro = 0)
|
101
|
+
if major.nil?
|
102
|
+
STDOUT.print("checking for #{pkg}... ")
|
103
|
+
else
|
104
|
+
STDOUT.print("checking for #{pkg} version (>= #{major}.#{minor}.#{micro})... ")
|
105
|
+
end
|
106
|
+
major ||= 0
|
107
|
+
STDOUT.flush
|
108
|
+
if check_version?(pkg, major, minor, micro)
|
109
|
+
STDOUT.print "yes\n"
|
110
|
+
libraries = libs_only_l(pkg)
|
111
|
+
dldflags = libs(pkg)
|
112
|
+
dldflags = (Shellwords.shellwords(dldflags) - Shellwords.shellwords(libraries)).map{|s| /\s/ =~ s ? "\"#{s}\"" : s }.join(' ')
|
113
|
+
$libs += ' ' + libraries
|
114
|
+
if /mswin32/ =~ RUBY_PLATFORM
|
115
|
+
$DLDFLAGS += ' ' + dldflags
|
116
|
+
else
|
117
|
+
$LDFLAGS += ' ' + dldflags
|
118
|
+
end
|
119
|
+
$CFLAGS += ' ' + cflags(pkg)
|
120
|
+
true
|
121
|
+
else
|
122
|
+
STDOUT.print "no\n"
|
123
|
+
false
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/samples/pac.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
=begin
|
2
|
+
pac.rb - rcairo sample script.
|
3
|
+
|
4
|
+
Original: pac.rb in http://www.artima.com/rubycs/articles/pdf_writer3.html
|
5
|
+
=end
|
6
|
+
|
7
|
+
top = File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
8
|
+
src = File.join(top, "src")
|
9
|
+
$LOAD_PATH.unshift src
|
10
|
+
$LOAD_PATH.unshift File.join(src, "lib")
|
11
|
+
|
12
|
+
require "cairo"
|
13
|
+
|
14
|
+
WIDTH = 841.889763779528
|
15
|
+
HEIGHT = 595.275590551181
|
16
|
+
|
17
|
+
def pac(surface)
|
18
|
+
white = [1, 1, 1]
|
19
|
+
black = [0, 0, 0]
|
20
|
+
magenta = [1, 0, 1]
|
21
|
+
cyan = [0, 1, 1]
|
22
|
+
yellow = [1, 1, 0]
|
23
|
+
blue = [0, 0, 1]
|
24
|
+
|
25
|
+
cr = Cairo::Context.new(surface)
|
26
|
+
|
27
|
+
cr.set_source_rgb(*black)
|
28
|
+
cr.rectangle(0, 0, WIDTH, HEIGHT).fill
|
29
|
+
|
30
|
+
# Wall
|
31
|
+
cr.set_source_rgb(*magenta)
|
32
|
+
cr.rounded_rectangle(20, 80, 750, 20, 10)
|
33
|
+
cr.fill
|
34
|
+
cr.set_source_rgb(*cyan)
|
35
|
+
cr.rounded_rectangle(20, 80, 750, 20, 10)
|
36
|
+
cr.stroke
|
37
|
+
|
38
|
+
cr.set_source_rgb(*magenta)
|
39
|
+
cr.rounded_rectangle(20, 380, 750, 20, 10)
|
40
|
+
cr.fill
|
41
|
+
cr.set_source_rgb(*cyan)
|
42
|
+
cr.rounded_rectangle(20, 380, 750, 20, 10)
|
43
|
+
cr.stroke
|
44
|
+
|
45
|
+
# Body
|
46
|
+
cr.set_source_rgb(*yellow)
|
47
|
+
cr.fill do
|
48
|
+
cr.arc(150, 250, 100, 30 * (Math::PI / 180), 330 * (Math::PI / 180))
|
49
|
+
cr.line_to(150, 250)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Dot
|
53
|
+
cr.set_source_rgb(*yellow)
|
54
|
+
cr.circle(250, 250, 20).fill
|
55
|
+
cr.circle(300, 250, 10).fill
|
56
|
+
cr.circle(350, 250, 10).fill
|
57
|
+
cr.circle(400, 250, 10).fill
|
58
|
+
cr.circle(450, 250, 10).fill
|
59
|
+
|
60
|
+
# Ghost
|
61
|
+
cr.move_to(500, 350)
|
62
|
+
cr.line_to(500, 175)
|
63
|
+
cr.curve_to(550, 125, 600, 125, 650, 175)
|
64
|
+
cr.line_to(650, 350)
|
65
|
+
cr.line_to(625, 325)
|
66
|
+
cr.line_to(600, 350)
|
67
|
+
cr.line_to(575, 325)
|
68
|
+
cr.line_to(550, 350)
|
69
|
+
cr.line_to(525, 325)
|
70
|
+
cr.line_to(500, 350)
|
71
|
+
|
72
|
+
cr.set_source_rgb(*blue)
|
73
|
+
cr.fill_preserve
|
74
|
+
cr.set_source_rgb(*cyan)
|
75
|
+
cr.stroke
|
76
|
+
|
77
|
+
# Ghost Eyes
|
78
|
+
cr.set_source_rgb(*white)
|
79
|
+
cr.rectangle(525, 200, 25, 25).fill
|
80
|
+
cr.rectangle(575, 200, 25, 25).fill
|
81
|
+
|
82
|
+
cr.set_source_rgb(*black)
|
83
|
+
cr.rectangle(525, 215, 10, 10).fill
|
84
|
+
cr.rectangle(575, 215, 10, 10).fill
|
85
|
+
|
86
|
+
cr.show_page
|
87
|
+
end
|
88
|
+
|
89
|
+
surface = Cairo::ImageSurface.new(WIDTH, HEIGHT)
|
90
|
+
cr = pac(surface)
|
91
|
+
cr.target.write_to_png("pac.png")
|
92
|
+
|
93
|
+
def scalable_surface_output(surface_class_name, suffix)
|
94
|
+
if Cairo.const_defined?(surface_class_name)
|
95
|
+
surface_class = Cairo.const_get(surface_class_name)
|
96
|
+
surface = surface_class.new("pac.#{suffix}", WIDTH, HEIGHT)
|
97
|
+
cr = pac(surface)
|
98
|
+
cr.target.finish
|
99
|
+
else
|
100
|
+
puts("#{surface_class_name} isn't supported.")
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
scalable_surface_output("PSSurface", "ps")
|
105
|
+
scalable_surface_output("PDFSurface", "pdf")
|
106
|
+
scalable_surface_output("SVGSurface", "svg")
|
data/samples/pac2.rb
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
=begin
|
2
|
+
pac2.rb - rcairo sample script with #scale and #translate.
|
3
|
+
|
4
|
+
Original: pac.rb in http://www.artima.com/rubycs/articles/pdf_writer3.html
|
5
|
+
=end
|
6
|
+
|
7
|
+
top = File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
8
|
+
src = File.join(top, "src")
|
9
|
+
$LOAD_PATH.unshift src
|
10
|
+
$LOAD_PATH.unshift File.join(src, "lib")
|
11
|
+
|
12
|
+
require "cairo"
|
13
|
+
|
14
|
+
def pac(surface, width, height)
|
15
|
+
white = [1, 1, 1]
|
16
|
+
black = [0, 0, 0]
|
17
|
+
magenta = [1, 0, 1]
|
18
|
+
cyan = [0, 1, 1]
|
19
|
+
yellow = [1, 1, 0]
|
20
|
+
blue = [0, 0, 1]
|
21
|
+
|
22
|
+
cr = Cairo::Context.new(surface)
|
23
|
+
|
24
|
+
# NOTE: You may need to set line width when use Cairo::Context#scale
|
25
|
+
cr.set_line_width(cr.line_width / [width, height].max)
|
26
|
+
|
27
|
+
cr.scale(width, height)
|
28
|
+
|
29
|
+
cr.save do
|
30
|
+
cr.set_source_rgb(*black)
|
31
|
+
cr.rectangle(0, 0, 1, 1)
|
32
|
+
cr.fill
|
33
|
+
end
|
34
|
+
|
35
|
+
# Wall
|
36
|
+
wall_width = 0.89
|
37
|
+
wall_height = 0.03
|
38
|
+
wall_space = 0.5
|
39
|
+
wall_x = 0.02
|
40
|
+
wall1_y = 1 - 0.86
|
41
|
+
wall2_y = wall1_y + wall_space
|
42
|
+
wall_radius = 0.01
|
43
|
+
|
44
|
+
cr.set_source_rgb(*magenta)
|
45
|
+
cr.rounded_rectangle(wall_x, wall1_y, wall_width, wall_height, wall_radius)
|
46
|
+
cr.fill
|
47
|
+
cr.set_source_rgb(*cyan)
|
48
|
+
cr.rounded_rectangle(wall_x, wall1_y, wall_width, wall_height, wall_radius)
|
49
|
+
cr.stroke
|
50
|
+
|
51
|
+
cr.set_source_rgb(*magenta)
|
52
|
+
cr.rounded_rectangle(wall_x, wall2_y, wall_width, wall_height, wall_radius)
|
53
|
+
cr.fill
|
54
|
+
cr.set_source_rgb(*cyan)
|
55
|
+
cr.rounded_rectangle(wall_x, wall2_y, wall_width, wall_height, wall_radius)
|
56
|
+
cr.stroke
|
57
|
+
|
58
|
+
# Body
|
59
|
+
body_x = 0.17
|
60
|
+
body_y = 1 - 0.58
|
61
|
+
body_width = 0.23
|
62
|
+
body_height = 0.33
|
63
|
+
|
64
|
+
cr.save do
|
65
|
+
cr.translate(body_x, body_y)
|
66
|
+
cr.set_source_rgb(*yellow)
|
67
|
+
cr.scale(body_width, body_height)
|
68
|
+
cr.arc(0, 0, 0.5, 30 * (Math::PI / 180), 330 * (Math::PI / 180))
|
69
|
+
cr.line_to(0, 0)
|
70
|
+
cr.close_path
|
71
|
+
cr.fill
|
72
|
+
end
|
73
|
+
|
74
|
+
# Dot
|
75
|
+
dot_width = 0.02
|
76
|
+
dot_height = 0.03
|
77
|
+
small_dot_width = 0.01
|
78
|
+
small_dot_height = 0.015
|
79
|
+
dot_x = 0.29
|
80
|
+
dot_y = 1 - 0.58
|
81
|
+
dot_step = 0.05
|
82
|
+
|
83
|
+
cr.save do
|
84
|
+
cr.set_source_rgb(*yellow)
|
85
|
+
cr.save do
|
86
|
+
cr.translate(dot_x, dot_y)
|
87
|
+
cr.scale(dot_width, dot_height)
|
88
|
+
cr.circle(0, 0, 1).fill
|
89
|
+
end
|
90
|
+
|
91
|
+
4.times do |i|
|
92
|
+
cr.save do
|
93
|
+
cr.translate(dot_x + dot_step * (i + 1), dot_y)
|
94
|
+
cr.scale(small_dot_width, small_dot_height)
|
95
|
+
cr.circle(0, 0, 1).fill
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Ghost
|
101
|
+
ghost_x = 0.59
|
102
|
+
ghost_x_step = 0.03
|
103
|
+
ghost_y = 1 - 0.42
|
104
|
+
ghost_y_step = 0.04
|
105
|
+
ghost_width = 0.18
|
106
|
+
ghost_height = 0.29
|
107
|
+
ghost_radius= 0.08
|
108
|
+
cr.move_to(ghost_x, ghost_y)
|
109
|
+
cr.line_to(ghost_x, ghost_y - ghost_height)
|
110
|
+
cr.curve_to(ghost_x + ghost_width / 3.0,
|
111
|
+
ghost_y - ghost_height - ghost_radius,
|
112
|
+
ghost_x + ghost_width * (2.0 / 3.0),
|
113
|
+
ghost_y - ghost_height - ghost_radius,
|
114
|
+
ghost_x + ghost_width,
|
115
|
+
ghost_y - ghost_height)
|
116
|
+
cr.line_to(ghost_x + ghost_width, ghost_y)
|
117
|
+
i = 0
|
118
|
+
(ghost_x + ghost_width).step(ghost_x, -ghost_x_step) do |x|
|
119
|
+
cr.line_to(x, ghost_y + -ghost_y_step * (i % 2))
|
120
|
+
i += 1
|
121
|
+
end
|
122
|
+
cr.close_path
|
123
|
+
|
124
|
+
cr.set_source_rgb(*blue)
|
125
|
+
cr.fill_preserve
|
126
|
+
cr.set_source_rgb(*cyan)
|
127
|
+
cr.stroke
|
128
|
+
|
129
|
+
# Ghost Eyes
|
130
|
+
eye_x = 0.62
|
131
|
+
eye_y = 1 - 0.63
|
132
|
+
eye_space = 0.06
|
133
|
+
white_eye_width = 0.03
|
134
|
+
white_eye_height = 0.04
|
135
|
+
black_eye_width = 0.01
|
136
|
+
black_eye_height = 0.02
|
137
|
+
|
138
|
+
cr.set_source_rgb(*white)
|
139
|
+
cr.rectangle(eye_x, eye_y - white_eye_height,
|
140
|
+
white_eye_width, white_eye_height)
|
141
|
+
cr.fill
|
142
|
+
cr.rectangle(eye_x + eye_space, eye_y - white_eye_height,
|
143
|
+
white_eye_width, white_eye_height)
|
144
|
+
cr.fill
|
145
|
+
|
146
|
+
cr.set_source_rgb(*black)
|
147
|
+
cr.rectangle(eye_x, eye_y - black_eye_height,
|
148
|
+
black_eye_width, black_eye_height)
|
149
|
+
cr.fill
|
150
|
+
cr.rectangle(eye_x + eye_space, eye_y - black_eye_height,
|
151
|
+
black_eye_width, black_eye_height)
|
152
|
+
cr.fill
|
153
|
+
|
154
|
+
cr.show_page
|
155
|
+
end
|
156
|
+
|
157
|
+
width = 841.889763779528
|
158
|
+
height = 595.275590551181
|
159
|
+
|
160
|
+
surface = Cairo::ImageSurface.new(width, height)
|
161
|
+
cr = pac(surface, width, height)
|
162
|
+
cr.target.write_to_png("pac2.png")
|
163
|
+
|
164
|
+
scalable_surface_output = Proc.new do |surface_class_name, suffix|
|
165
|
+
if Cairo.const_defined?(surface_class_name)
|
166
|
+
surface_class = Cairo.const_get(surface_class_name)
|
167
|
+
surface = surface_class.new("pac2.#{suffix}", width, height)
|
168
|
+
cr = pac(surface, width, height)
|
169
|
+
cr.target.finish
|
170
|
+
else
|
171
|
+
puts("#{surface_class_name} isn't supported.")
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
scalable_surface_output.call("PSSurface", "ps")
|
176
|
+
scalable_surface_output.call("PDFSurface", "pdf")
|
177
|
+
scalable_surface_output.call("SVGSurface", "svg")
|