1"""
2Some tests for difficult wrapped graphics functions and methods
3
4NOTE: These require a WindowServer connection on MacOS X
5"""
6from PyObjCTools.TestSupport import *
7from AppKit import *
8from Foundation import *
9import array
10import sys
11
12
13class SimpleImage:
14    """
15    Helper class that makes it easier to access individual pixels in
16    a bitmap image
17    """
18    def __init__(self, image):
19        data = image.TIFFRepresentation()
20        bitmap = NSBitmapImageRep.imageRepWithData_(data)
21        self.bitmap = bitmap
22        self.data = bitmap.bitmapData()
23        self.rowbytes = bitmap.bytesPerRow()
24        self.pixbytes = bitmap.bitsPerPixel() // 8
25        self.rowCount = bitmap.pixelsHigh()
26
27        if bitmap.isPlanar():
28            raise ValueError("Planar image!")
29        if (bitmap.bitsPerPixel() % 8) != 0:
30            raise ValueError("bits per pixel isn't multiple of 8")
31
32    def width(self):
33        return self.bitmap.pixelsWide()
34
35    def height(self):
36        return self.bitmap.pixelsHigh()
37
38    def getPixel(self, x, y):
39        x = self.rowCount - 1 - x
40        rowOffset = x * self.rowbytes
41        pixelOffset = y * self.pixbytes
42        offset = rowOffset + pixelOffset
43
44        pixel = self.data[offset:offset + self.pixbytes]
45        return pixel
46
47class RectTest (TestCase):
48    def setUp(self):
49
50        # Force NSApp initialisation, needed for some of the tests
51        NSApplication.sharedApplication().activateIgnoringOtherApps_(0)
52
53
54
55        self.points = (
56            ((10,  0), ( 1,  1)),
57            ((10, 10), ( 1,  1)),
58            (( 0, 10), ( 1,  1)),
59            (( 0,  0), ( 1,  1)),
60            ((70, 70), (10, 10))
61        )
62
63        self.image = NSImage.alloc().initWithSize_((100, 100))
64
65    def makeArray(self, points):
66        if sys.maxsize > 2 ** 32:
67            code = 'd'
68        else:
69            code = 'f'
70
71        a = array.array(code, len(points) * [0, 0, 0, 0])
72        for i in range(len(points)):
73            p = points[i]
74            a[(i*4) + 0] = p[0][0]
75            a[(i*4) + 1] = p[0][1]
76            a[(i*4) + 2] = p[1][0]
77            a[(i*4) + 3] = p[1][1]
78
79        return a
80
81    def assertImagePoints(self, image, points):
82        """
83        Check that the image contains white pixels everywhere but at the
84        specified locations points is sequence of NSRect values.
85        """
86
87        img = SimpleImage(image)
88
89        allpoints = [ (x, y)
90                for x in range(img.width())
91                for y in range(img.height())
92        ]
93
94        # Check black points
95        if sys.version_info[0] == 2:
96            def getPixel(img, x, y):
97                return img.getPixel(x, y)
98
99        else:
100            def getPixel(img, x, y):
101                value = img.getPixel(x, y)
102                return bytes(value)
103
104        for ((x, y), (h, w)) in points:
105            for ox in range(w):
106                for oy in range(h):
107                    allpoints.remove((x+ox, y+oy))
108                    self.assertEqual(
109                        getPixel(img, x+ox, y+oy),
110                        b'\x00\x00\x00\xff',
111                        'Black pixel at %d,%d'%(x+ox, y+oy))
112
113        # And white points
114        for x, y in allpoints:
115            self.assertEqual(
116                getPixel(img, x, y),
117                b'\x00\x00\x00\x00',
118                'White pixel at %d,%d'%(x, y))
119
120
121    def tearDown(self):
122        pass
123
124
125    def test_NSRectFillList_tuple(self):
126        """
127        Check NSRectFillList with a tuple of NSRects
128        """
129        self.image.lockFocus()
130        NSRectFillList(self.points, len(self.points))
131        self.image.unlockFocus()
132
133        self.assertImagePoints(self.image, self.points)
134
135    def test_NSRectFillList_array(self):
136        """
137        Check NSRectFillList with a array.array of NSRects
138        """
139        self.image.lockFocus()
140        NSRectFillList(self.makeArray(self.points), len(self.points))
141        self.image.unlockFocus()
142
143
144if __name__ == "__main__":
145    main()
146