implemented bitmap checks in test framwork
[swftools.git] / spec / spec_helper.rb
1 require 'spec'
2 require 'rubygems'
3 require 'RMagick'
4
5 class WrongColor < Exception
6     def initialize(pixel)
7         @pixel = pixel
8     end
9     def to_s
10         "Wrong color at #{@pixel}"
11     end
12 end
13 class AreaError < Exception
14     def initialize(area,problem)
15         @area,@problem = area,problem
16     end
17     def to_s
18         "Area at #{@area} #{@problem}"
19     end
20 end
21 class PixelError < Exception
22     def initialize(p1, relation,p2)
23         @p1,@p2,@relation = p1,p2,relation
24     end
25     def to_s
26         "Pixel #{@p1} #{@relation} #{@p2}"
27     end
28 end
29 class ConversionFailed < Exception
30     def initialize(output,file)
31         @output = output
32         @file = file
33         @exists = File.exists?(file)
34     end
35     def to_s
36         puts "-"*26+" Conversion failed "+"-"*27
37         (puts @output) if @output
38         puts "file #{@file} doesn't exist" if not @exists
39         puts "-"*72
40     end
41 end
42
43 class Area
44     def initialize(x1,y1,x2,y2,data)
45         @x1,@y1,@x2,@y2 = x1,y1,x2,y2
46         @rgb = Array.new(data.size/3) do |i| data.slice(i*3,3) end
47     end
48     def should_be_plain_colored
49         @rgb.minmax == [@rgb[0],@rgb[0]] or raise AreaError.new(self,"is not plain colored")
50     end
51     def should_not_be_plain_colored
52         @rgb.minmax != [@rgb[0],@rgb[0]] or raise AreaError.new(self,"is plain colored")
53     end
54     def to_s
55         "(#{@x1},#{@y1},#{@x2},#{@y2})"
56     end
57 end
58
59 def rgb_to_int(rgb)
60     # ImageMagick rgb triples are 16 bit
61     (rgb.reverse+[0]).map {|c| c>>8}.pack("CCCC").unpack("i")[0]
62 end
63
64 class Pixel
65     attr :rgb
66     def initialize(x,y,rgb)
67         @x,@y,@rgb = x,y,rgb
68     end
69     def should_be_of_color(color2)
70         color1 = rgb_to_int(@rgb)
71         color1 == color2 or raise WrongColor.new(self)
72     end
73     def should_be_brighter_than(pixel)
74         gray1 = @rgb.inject(0) {|sum,e| sum+e}
75         gray2 = pixel.rgb.inject(0) {|sum,e| sum+e}
76         gray1 > gray2 or raise PixelError.new(self,"is not brighter than",pixel)
77     end
78     def should_be_less_bright_than(pixel)
79         gray1 = @rgb.inject(0) {|sum,e| sum+e}
80         gray2 = pixel.rgb.inject(0) {|sum,e| sum+e}
81         gray1 < gray2 or raise PixelError.new(self,"is not less bright than",pixel)
82     end
83     def should_be_the_same_as(pixel)
84         @rgb == pixel.rgb or raise PixelError.new(self,"is not the same as",pixel)
85     end
86     def to_s
87         "(#{@x},#{@y})"
88     end
89 end
90 class DocFile
91     def initialize(filename, page)
92         @filename = filename
93         @page = page
94     end
95     def load()
96         @swfname = @filename.gsub(/.pdf$/i,"")+".swf"
97         @pngname = @filename.gsub(/.pdf$/i,"")+".png"
98         begin
99             output = `pdf2swf --flatten -p #{@page} #{@filename} -o #{@swfname} 2>&1`
100             raise ConversionFailed.new(output,@swfname) unless File.exists?(@swfname)
101             output = `swfrender --legacy #{@swfname} -o #{@pngname} 2>&1`
102             raise ConversionFailed.new(output,@pngname) unless File.exists?(@pngname)
103             @img = Magick::Image.read(@pngname).first
104         ensure
105             `rm -f #{@swfname}`
106             `rm -f #{@pngname}`
107         end
108     end
109     def area_at(x1,y1,x2,y2)
110         self.load()
111         data = @img.export_pixels(x1, y1, x2-x1, y2-y1, "RGB")
112         return Area.new(x1,y1,x2,y2,data)
113     end
114     def width()
115         self.load()
116         return @img.columns
117     end
118     def height()
119         self.load()
120         return @img.rows
121     end
122     def pixel_at(x,y)
123         self.load()
124         data = @img.export_pixels(x, y, 1, 1, "RGB")
125         return Pixel.new(x,y,data)
126     end
127 end
128
129 module Spec
130     module Example
131         module ExampleMethods
132            def area_at(x1,y1,x2,y2)
133                @file.area_at(x1,y1,x2,y2)
134            end
135            def width
136                @file.width
137            end
138            def height
139                @file.height
140            end
141            def pixel_at(x,y)
142                @file.pixel_at(x,y)
143            end
144            def initialize(proxy,&impl)
145
146                # overriding the initialize() function saves us from having to
147                # set up the document in the test. The bad news, however, is that
148                # we have to be very careful not to raise exceptions here-
149                # rspec would miss those.
150
151                @_proxy = proxy
152                @_implementation = impl
153                @_backtrace = caller
154                @file = DocFile.new(proxy.description, (proxy.options[:page] or 1))
155            end
156         end
157         module ExampleGroupMethods
158             alias :convert_file :example
159             def page(nr)
160                 nr
161             end
162         end
163     end
164 end
165
166