OSDN Git Service

Add Go frontend, libgo library, and Go testsuite.
[pf3gnuchains/gcc-fork.git] / libgo / go / exp / draw / draw_test.go
1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package draw
6
7 import (
8         "image"
9         "testing"
10 )
11
12 func eq(c0, c1 image.Color) bool {
13         r0, g0, b0, a0 := c0.RGBA()
14         r1, g1, b1, a1 := c1.RGBA()
15         return r0 == r1 && g0 == g1 && b0 == b1 && a0 == a1
16 }
17
18 func fillBlue(alpha int) image.Image {
19         return image.NewColorImage(image.RGBAColor{0, 0, uint8(alpha), uint8(alpha)})
20 }
21
22 func fillAlpha(alpha int) image.Image {
23         return image.NewColorImage(image.AlphaColor{uint8(alpha)})
24 }
25
26 func vgradGreen(alpha int) image.Image {
27         m := image.NewRGBA(16, 16)
28         for y := 0; y < 16; y++ {
29                 for x := 0; x < 16; x++ {
30                         m.Set(x, y, image.RGBAColor{0, uint8(y * alpha / 15), 0, uint8(alpha)})
31                 }
32         }
33         return m
34 }
35
36 func vgradAlpha(alpha int) image.Image {
37         m := image.NewAlpha(16, 16)
38         for y := 0; y < 16; y++ {
39                 for x := 0; x < 16; x++ {
40                         m.Set(x, y, image.AlphaColor{uint8(y * alpha / 15)})
41                 }
42         }
43         return m
44 }
45
46 func hgradRed(alpha int) Image {
47         m := image.NewRGBA(16, 16)
48         for y := 0; y < 16; y++ {
49                 for x := 0; x < 16; x++ {
50                         m.Set(x, y, image.RGBAColor{uint8(x * alpha / 15), 0, 0, uint8(alpha)})
51                 }
52         }
53         return m
54 }
55
56 func gradYellow(alpha int) Image {
57         m := image.NewRGBA(16, 16)
58         for y := 0; y < 16; y++ {
59                 for x := 0; x < 16; x++ {
60                         m.Set(x, y, image.RGBAColor{uint8(x * alpha / 15), uint8(y * alpha / 15), 0, uint8(alpha)})
61                 }
62         }
63         return m
64 }
65
66 type drawTest struct {
67         desc     string
68         src      image.Image
69         mask     image.Image
70         op       Op
71         expected image.Color
72 }
73
74 var drawTests = []drawTest{
75         // Uniform mask (0% opaque).
76         {"nop", vgradGreen(255), fillAlpha(0), Over, image.RGBAColor{136, 0, 0, 255}},
77         {"clear", vgradGreen(255), fillAlpha(0), Src, image.RGBAColor{0, 0, 0, 0}},
78         // Uniform mask (100%, 75%, nil) and uniform source.
79         // At (x, y) == (8, 8):
80         // The destination pixel is {136, 0, 0, 255}.
81         // The source pixel is {0, 0, 90, 90}.
82         {"fill", fillBlue(90), fillAlpha(255), Over, image.RGBAColor{88, 0, 90, 255}},
83         {"fillSrc", fillBlue(90), fillAlpha(255), Src, image.RGBAColor{0, 0, 90, 90}},
84         {"fillAlpha", fillBlue(90), fillAlpha(192), Over, image.RGBAColor{100, 0, 68, 255}},
85         {"fillAlphaSrc", fillBlue(90), fillAlpha(192), Src, image.RGBAColor{0, 0, 68, 68}},
86         {"fillNil", fillBlue(90), nil, Over, image.RGBAColor{88, 0, 90, 255}},
87         {"fillNilSrc", fillBlue(90), nil, Src, image.RGBAColor{0, 0, 90, 90}},
88         // Uniform mask (100%, 75%, nil) and variable source.
89         // At (x, y) == (8, 8):
90         // The destination pixel is {136, 0, 0, 255}.
91         // The source pixel is {0, 48, 0, 90}.
92         {"copy", vgradGreen(90), fillAlpha(255), Over, image.RGBAColor{88, 48, 0, 255}},
93         {"copySrc", vgradGreen(90), fillAlpha(255), Src, image.RGBAColor{0, 48, 0, 90}},
94         {"copyAlpha", vgradGreen(90), fillAlpha(192), Over, image.RGBAColor{100, 36, 0, 255}},
95         {"copyAlphaSrc", vgradGreen(90), fillAlpha(192), Src, image.RGBAColor{0, 36, 0, 68}},
96         {"copyNil", vgradGreen(90), nil, Over, image.RGBAColor{88, 48, 0, 255}},
97         {"copyNilSrc", vgradGreen(90), nil, Src, image.RGBAColor{0, 48, 0, 90}},
98         // Variable mask and variable source.
99         // At (x, y) == (8, 8):
100         // The destination pixel is {136, 0, 0, 255}.
101         // The source pixel is {0, 0, 255, 255}.
102         // The mask pixel's alpha is 102, or 40%.
103         {"generic", fillBlue(255), vgradAlpha(192), Over, image.RGBAColor{81, 0, 102, 255}},
104         {"genericSrc", fillBlue(255), vgradAlpha(192), Src, image.RGBAColor{0, 0, 102, 102}},
105 }
106
107 func makeGolden(dst, src, mask image.Image, op Op) image.Image {
108         // Since golden is a newly allocated image, we don't have to check if the
109         // input source and mask images and the output golden image overlap.
110         b := dst.Bounds()
111         sx0 := src.Bounds().Min.X - b.Min.X
112         sy0 := src.Bounds().Min.Y - b.Min.Y
113         var mx0, my0 int
114         if mask != nil {
115                 mx0 = mask.Bounds().Min.X - b.Min.X
116                 my0 = mask.Bounds().Min.Y - b.Min.Y
117         }
118         golden := image.NewRGBA(b.Max.X, b.Max.Y)
119         for y := b.Min.Y; y < b.Max.Y; y++ {
120                 my, sy := my0+y, sy0+y
121                 for x := b.Min.X; x < b.Max.X; x++ {
122                         mx, sx := mx0+x, sx0+x
123                         const M = 1<<16 - 1
124                         var dr, dg, db, da uint32
125                         if op == Over {
126                                 dr, dg, db, da = dst.At(x, y).RGBA()
127                         }
128                         sr, sg, sb, sa := src.At(sx, sy).RGBA()
129                         ma := uint32(M)
130                         if mask != nil {
131                                 _, _, _, ma = mask.At(mx, my).RGBA()
132                         }
133                         a := M - (sa * ma / M)
134                         golden.Set(x, y, image.RGBA64Color{
135                                 uint16((dr*a + sr*ma) / M),
136                                 uint16((dg*a + sg*ma) / M),
137                                 uint16((db*a + sb*ma) / M),
138                                 uint16((da*a + sa*ma) / M),
139                         })
140                 }
141         }
142         golden.Rect = b
143         return golden
144 }
145
146 func TestDraw(t *testing.T) {
147 loop:
148         for _, test := range drawTests {
149                 dst := hgradRed(255)
150                 // Draw the (src, mask, op) onto a copy of dst using a slow but obviously correct implementation.
151                 golden := makeGolden(dst, test.src, test.mask, test.op)
152                 b := dst.Bounds()
153                 if !b.Eq(golden.Bounds()) {
154                         t.Errorf("draw %s: bounds %v versus %v", test.desc, dst.Bounds(), golden.Bounds())
155                         continue
156                 }
157                 // Draw the same combination onto the actual dst using the optimized DrawMask implementation.
158                 DrawMask(dst, b, test.src, image.ZP, test.mask, image.ZP, test.op)
159                 // Check that the resultant pixel at (8, 8) matches what we expect
160                 // (the expected value can be verified by hand).
161                 if !eq(dst.At(8, 8), test.expected) {
162                         t.Errorf("draw %s: at (8, 8) %v versus %v", test.desc, dst.At(8, 8), test.expected)
163                         continue
164                 }
165                 // Check that the resultant dst image matches the golden output.
166                 for y := b.Min.Y; y < b.Max.Y; y++ {
167                         for x := b.Min.X; x < b.Max.X; x++ {
168                                 if !eq(dst.At(x, y), golden.At(x, y)) {
169                                         t.Errorf("draw %s: at (%d, %d), %v versus golden %v", test.desc, x, y, dst.At(x, y), golden.At(x, y))
170                                         continue loop
171                                 }
172                         }
173                 }
174         }
175 }
176
177 func TestDrawOverlap(t *testing.T) {
178         for _, op := range []Op{Over, Src} {
179                 for yoff := -2; yoff <= 2; yoff++ {
180                 loop:
181                         for xoff := -2; xoff <= 2; xoff++ {
182                                 m := gradYellow(127).(*image.RGBA)
183                                 dst := &image.RGBA{
184                                         Pix:    m.Pix,
185                                         Stride: m.Stride,
186                                         Rect:   image.Rect(5, 5, 10, 10),
187                                 }
188                                 src := &image.RGBA{
189                                         Pix:    m.Pix,
190                                         Stride: m.Stride,
191                                         Rect:   image.Rect(5+xoff, 5+yoff, 10+xoff, 10+yoff),
192                                 }
193                                 // Draw the (src, mask, op) onto a copy of dst using a slow but obviously correct implementation.
194                                 golden := makeGolden(dst, src, nil, op)
195                                 b := dst.Bounds()
196                                 if !b.Eq(golden.Bounds()) {
197                                         t.Errorf("drawOverlap xoff=%d,yoff=%d: bounds %v versus %v", xoff, yoff, dst.Bounds(), golden.Bounds())
198                                         continue
199                                 }
200                                 // Draw the same combination onto the actual dst using the optimized DrawMask implementation.
201                                 DrawMask(dst, b, src, src.Bounds().Min, nil, image.ZP, op)
202                                 // Check that the resultant dst image matches the golden output.
203                                 for y := b.Min.Y; y < b.Max.Y; y++ {
204                                         for x := b.Min.X; x < b.Max.X; x++ {
205                                                 if !eq(dst.At(x, y), golden.At(x, y)) {
206                                                         t.Errorf("drawOverlap xoff=%d,yoff=%d: at (%d, %d), %v versus golden %v", xoff, yoff, x, y, dst.At(x, y), golden.At(x, y))
207                                                         continue loop
208                                                 }
209                                         }
210                                 }
211                         }
212                 }
213         }
214 }
215
216 // TestIssue836 verifies http://code.google.com/p/go/issues/detail?id=836.
217 func TestIssue836(t *testing.T) {
218         a := image.NewRGBA(1, 1)
219         b := image.NewRGBA(2, 2)
220         b.Set(0, 0, image.RGBAColor{0, 0, 0, 5})
221         b.Set(1, 0, image.RGBAColor{0, 0, 5, 5})
222         b.Set(0, 1, image.RGBAColor{0, 5, 0, 5})
223         b.Set(1, 1, image.RGBAColor{5, 0, 0, 5})
224         Draw(a, image.Rect(0, 0, 1, 1), b, image.Pt(1, 1))
225         if !eq(image.RGBAColor{5, 0, 0, 5}, a.At(0, 0)) {
226                 t.Errorf("Issue 836: want %v got %v", image.RGBAColor{5, 0, 0, 5}, a.At(0, 0))
227         }
228 }