bugfixes in new filter
[swftools.git] / spec / spec_helper.rb
blob4d74ee1c9962c636650012f47a06bf4af68a4be1
1 require 'spec'
2 require 'rubygems'
3 require 'RMagick'
5 class WrongColor < Exception
6   def initialize(pixel, is_color, desired_color)
7     @pixel = pixel
8     @is_color = is_color
9     @desired_color = desired_color
10   end
11   def to_s
12     "Wrong color at %s (is: %06x should be: %06x)" % [@pixel.to_s, @is_color, @desired_color]
13   end
14 end
15 class AreaError < Exception
16   def initialize(area,problem)
17     @area,@problem = area,problem
18   end
19   def to_s
20     "Area at #{@area} #{@problem}"
21   end
22 end
23 class PixelError < Exception
24   def initialize(p1, relation,p2)
25     @p1,@p2,@relation = p1,p2,relation
26   end
27   def to_s
28     "Pixel #{@p1} #{@relation} #{@p2}"
29   end
30 end
31 class ConversionFailed < Exception
32   def initialize(output,file)
33     @output = output
34     @file = file
35     @exists = File.exists?(file)
36   end
37   def to_s
38     puts "-"*26+" Conversion failed "+"-"*27
39     (puts @output) if @output
40     puts "file #{@file} doesn't exist" if not @exists
41     puts "-"*72
42   end
43 end
45 class Area
46   def initialize(x1,y1,x2,y2,file)
47     @x1,@y1,@x2,@y2,@file = x1,y1,x2,y2,file
48   end
49   def should_be_plain_colored
50     @rgb = @file.get_area(@x1,@y1,@x2,@y2) unless @rgb
51     @rgb.min == @rgb.max or raise AreaError.new(self,"is not plain colored: colors go from %06x to %06x" % [rgb_to_int(@rgb.min), rgb_to_int(@rgb.max)])
52   end
53   def should_not_be_plain_colored
54     @rgb = @file.get_area(@x1,@y1,@x2,@y2) unless @rgb
55     @rgb.min != @rgb.max or raise AreaError.new(self,"is plain colored")
56   end
57   def should_contain_text(text)
58     text2 = @file.get_text(@x1,@y1,@x2,@y2) 
59     text2 == text or raise AreaError.new(self, "doesn't contain text \"#{text}\" (found: \"#{text2}\")")
60   end
61   def should_contain_link(url)
62     links = @file.get_links(@x1,@y1,@x2,@y2) 
63     (links & [url]).empty? and raise AreaError.new(self, "doesn't contain url \"#{url}\"")
64   end
65   def to_s
66     "(#{@x1},#{@y1},#{@x2},#{@y2})"
67   end
68 end
70 def rgb_to_int(rgb)
71   # ImageMagick rgb triples are 16 bit
72   (rgb.reverse+[0]).map {|c| c>>8}.pack("CCCC").unpack("i")[0]
73 end
75 class Pixel
76   attr :rgb
77   def initialize(x,y,rgb)
78     @x,@y,@rgb = x,y,rgb
79   end
80   def should_be_of_color(color2)
81     color1 = rgb_to_int(@rgb)
82     color1 == color2 or raise WrongColor.new(self, color1, color2)
83   end
84   def should_be_brighter_than(pixel)
85     gray1 = @rgb.inject(0) {|sum,e| sum+e}
86     gray2 = pixel.rgb.inject(0) {|sum,e| sum+e}
87     gray1 > gray2 or raise PixelError.new(self,"is not brighter than",pixel)
88   end
89   def should_be_darker_than(pixel)
90     gray1 = @rgb.inject(0) {|sum,e| sum+e}
91     gray2 = pixel.rgb.inject(0) {|sum,e| sum+e}
92     gray1 < gray2 or raise PixelError.new(self,"is not less bright than",pixel)
93   end
94   def should_be_the_same_as(pixel)
95     @rgb == pixel.rgb or raise PixelError.new(self,"is not the same as",pixel)
96   end
97   def to_s
98     "(#{@x},#{@y})"
99   end
102 $tempfiles = []
103 Kernel.at_exit do
104   $tempfiles.each do |file|
105     `rm -f #{file}`
106   end
109 class DocFile
110   def initialize(filename, page)
111     @filename = filename
112     @page = page
113   end
114   def convert()
115     return if @swfname
116     @swfname = @filename.gsub(/.pdf$/i,"")+".swf"
117     $tempfiles += [@swfname]
118     `pdfinfo #{@filename}` =~ /Page size:\s*([0-9]+) x ([0-9]+) pts/
119     width,height = $1,$2
120     dpi = (72.0 * 612 / width.to_i).to_i
121     output = `pdf2swf -f -s poly2bitmap -s zoom=#{dpi} -p #{@page} #{@filename} -o #{@swfname} 2>&1`
122     #output = `pdf2swf -s zoom=#{dpi} --flatten -p #{@page} #{@filename} -o #{@swfname} 2>&1`
123     raise ConversionFailed.new(output,@swfname) unless File.exists?(@swfname)
124   end
125   def render()
126     return if @img
127     convert()
128     @pngname = @filename.gsub(/.pdf$/i,"")+".png"
129     begin
130       output = `swfrender #{@swfname} -o #{@pngname} 2>&1`
131       raise ConversionFailed.new(output,@pngname) unless File.exists?(@pngname)
132       @img = Magick::Image.read(@pngname).first
133     ensure
134       `rm -f #{@pngname}`
135     end
136   end
137   def get_text(x1,y1,x2,y2)
138     self.convert()
139     #puts "swfstrings -x #{x1} -y #{y1} -W #{x2-x1} -H #{y2-y1} #{@swfname}"
140     #puts `swfstrings -x #{x1} -y #{y1} -W #{x2-x1} -H #{y2-y1} #{@swfname}`
141     `swfstrings -x #{x1} -y #{y1} -W #{x2-x1} -H #{y2-y1} #{@swfname}`.chomp
142   end
143   def get_links(x1,y1,x2,y2)
144     self.convert()
145         t = `swfdump -a #{@swfname}`
146         links = t.scan(/GetUrl2? URL:"([^"]*)"/).inject([]) do |a,u| a + u end
147         t.scan(/name "url:([^"]*)"/).inject(links) do |a,u| a + u end
148   end
149   def get_area(x1,y1,x2,y2)
150     self.render()
151     data = @img.export_pixels(x1, y1, x2-x1, y2-y1, "RGB")
152     Array.new(data.size/3) { |i| data.slice(i*3,3) }
153   end
154   def area_at(x1,y1,x2,y2)
155     return Area.new(x1,y1,x2,y2,self)
156   end
157   def width()
158     self.render()
159     return @img.columns
160   end
161   def height()
162     self.render()
163     return @img.rows
164   end
165   def pixel_at(x,y)
166     self.render()
167     data = @img.export_pixels(x, y, 1, 1, "RGB")
168     return Pixel.new(x,y,data)
169   end
172 module  Spec::Example::ExampleGroupMethods 
173   alias :convert_file :example
176 class FileExampleGroup < Spec::Example::ExampleGroup
177   def area_at(x1,y1,x2,y2)
178     @file.area_at(x1,y1,x2,y2)
179   end
180   def width
181     @file.width
182   end
183   def height
184     @file.height
185   end
186   def pixel_at(x,y)
187     @file.pixel_at(x,y)
188   end  
191 Spec::Example::ExampleGroupFactory.default(FileExampleGroup)
193 Spec::Runner.configure do |config|
194   config.before do
195     input_file = File.join(File.dirname(__FILE__), description)
196     raise "Cannot find input file #{input_file}" unless File.exists?(input_file)
197     @file = DocFile.new(input_file, 1)
198   end