~mantas/pinta/stable

« back to all changes in this revision

Viewing changes to Pinta.Core/Effects/BitVector2DSurfaceAdapter.cs

  • Committer: Iain Lane
  • Date: 2010-03-13 18:20:18 UTC
  • mfrom: (1.1.2)
  • Revision ID: git-v1:1781694a68ecf232d0110c0b2f3d4a1b96c74ec2
Merge commit 'upstream/0.2'

Conflicts:
        debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/////////////////////////////////////////////////////////////////////////////////
 
2
// Paint.NET                                                                   //
 
3
// Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors.     //
 
4
// Portions Copyright (C) Microsoft Corporation. All Rights Reserved.          //
 
5
// See license-pdn.txt for full licensing and attribution details.             //
 
6
/////////////////////////////////////////////////////////////////////////////////
 
7
 
 
8
using System;
 
9
using Cairo;
 
10
 
 
11
namespace Pinta.Core
 
12
{
 
13
    /// <summary>
 
14
    /// Adapts a Surface class so it can be used as a two dimensional boolean array.
 
15
    /// Elements are stored compactly, such that each pixel stores 32 boolean values.
 
16
    /// However, the usable width is the same as that of the adapted surface.
 
17
    /// (in other words, a surface that is 100 pixels wide can still only store 100
 
18
    /// booleans per row)
 
19
    /// </summary>
 
20
    public sealed class BitVector2DSurfaceAdapter
 
21
        : IBitVector2D
 
22
    {
 
23
        private ImageSurface surface;
 
24
 
 
25
        public BitVector2DSurfaceAdapter (ImageSurface surface)
 
26
        {
 
27
            if (surface == null)
 
28
            {
 
29
                throw new ArgumentNullException("surface");
 
30
            }
 
31
 
 
32
            this.surface = surface;
 
33
        }
 
34
 
 
35
        public int Width
 
36
        {
 
37
            get
 
38
            {
 
39
                return surface.Width;
 
40
            }
 
41
        }
 
42
 
 
43
        public int Height
 
44
        {
 
45
            get
 
46
            {
 
47
                return surface.Height;
 
48
            }
 
49
        }
 
50
 
 
51
        public bool IsEmpty
 
52
        {
 
53
            get
 
54
            {
 
55
                return (Width == 0) || (Height == 0);
 
56
            }
 
57
        }
 
58
 
 
59
        public void Clear (bool newValue)
 
60
        {
 
61
                unsafe {
 
62
                        uint val = newValue ? 0xffffffff : 0;
 
63
 
 
64
                        for (int y = 0; y < Height; ++y) {
 
65
                                ColorBgra* row = surface.GetRowAddressUnchecked (y);
 
66
 
 
67
                                int w = (this.Width + 31) / 32;
 
68
 
 
69
                                while (w > 0) {
 
70
                                        row->Bgra = val;
 
71
                                        ++row;
 
72
                                        --w;
 
73
                                }
 
74
                        }
 
75
                }
 
76
        }
 
77
 
 
78
        public bool Get(int x, int y)
 
79
        {
 
80
            if (x < 0 || x >= this.Width)
 
81
            {
 
82
                throw new ArgumentOutOfRangeException("x");
 
83
            }
 
84
 
 
85
            if (y < 0 || y >= this.Height)
 
86
            {
 
87
                throw new ArgumentOutOfRangeException("y");
 
88
            }
 
89
 
 
90
            return GetUnchecked(x, y);
 
91
        }
 
92
 
 
93
        public unsafe bool GetUnchecked(int x, int y)
 
94
        {
 
95
            int cx = x / 32;
 
96
            int sx = x % 32;
 
97
            uint mask = surface.GetPointAddressUnchecked(cx, y)->Bgra;
 
98
            return 0 != (mask & (1 << sx));
 
99
        }
 
100
 
 
101
        public void Set(int x, int y, bool newValue)
 
102
        {
 
103
            if (x < 0 || x >= this.Width)
 
104
            {
 
105
                throw new ArgumentOutOfRangeException("x");
 
106
            }
 
107
 
 
108
            if (y < 0 || y >= this.Height)
 
109
            {
 
110
                throw new ArgumentOutOfRangeException("y");
 
111
            }
 
112
 
 
113
            SetUnchecked(x, y, newValue);
 
114
        }
 
115
 
 
116
        public void Set(Point pt, bool newValue)
 
117
        {
 
118
            Set(pt.X, pt.Y, newValue);
 
119
        }
 
120
 
 
121
        public void Set(Rectangle rect, bool newValue)
 
122
        {
 
123
            for (int y = (int)rect.Y; y < rect.GetBottom (); ++y)
 
124
            {
 
125
                for (int x = (int)rect.X; x < rect.GetRight (); ++x)
 
126
                {
 
127
                    Set(x, y, newValue);
 
128
                }
 
129
            }
 
130
        }
 
131
 
 
132
        public void Set(Scanline scan, bool newValue)
 
133
        {
 
134
            int x = scan.X;
 
135
 
 
136
            while (x < scan.X + scan.Length)
 
137
            {
 
138
                Set(x, scan.Y, newValue);
 
139
                ++x;
 
140
            }
 
141
        }
 
142
 
 
143
        //public void Set(PdnRegion region, bool newValue)
 
144
        //{
 
145
        //    foreach (Rectangle rect in region.GetRegionScansReadOnlyInt())
 
146
        //    {
 
147
        //        Set(rect, newValue);
 
148
        //    }
 
149
        //}
 
150
 
 
151
        public unsafe void SetUnchecked(int x, int y, bool newValue)
 
152
        {
 
153
            int cx = x / 32;
 
154
            int sx = x % 32;
 
155
            ColorBgra *ptr = surface.GetPointAddressUnchecked(cx, y);
 
156
            uint mask = ptr->Bgra;
 
157
            uint slice = ((uint)1 << sx);
 
158
            uint newMask;
 
159
            
 
160
            if (newValue)
 
161
            {
 
162
                newMask = mask | slice;
 
163
            }
 
164
            else
 
165
            {
 
166
                newMask = mask & ~slice;
 
167
            }
 
168
 
 
169
            ptr->Bgra = newMask;
 
170
        }
 
171
 
 
172
        public void Invert(int x, int y)
 
173
        {
 
174
            Set(x, y, !Get(x, y));
 
175
        }
 
176
 
 
177
        public void Invert(Point pt)
 
178
        {
 
179
            Invert(pt.X, pt.Y);
 
180
        }
 
181
 
 
182
        public void Invert(Rectangle rect)
 
183
        {
 
184
            for (int y = (int)rect.Y; y < rect.GetBottom (); ++y)
 
185
            {
 
186
                for (int x = (int)rect.X; x < rect.GetRight (); ++x)
 
187
                {
 
188
                    Invert(x, y);
 
189
                }
 
190
            }
 
191
        }
 
192
 
 
193
        public void Invert(Scanline scan)
 
194
        {
 
195
            int x = scan.X;
 
196
 
 
197
            while (x < scan.X + scan.Length)
 
198
            {
 
199
                Invert(x, scan.Y);
 
200
                ++x;
 
201
            }
 
202
        }
 
203
 
 
204
        //public void Invert(PdnRegion region)
 
205
        //{
 
206
        //    foreach (Rectangle rect in region.GetRegionScansReadOnlyInt())
 
207
        //    {
 
208
        //        Invert(rect);
 
209
        //    }        
 
210
        //}
 
211
 
 
212
        public bool this[Point pt]
 
213
        {
 
214
            get
 
215
            {
 
216
                return this[pt.X, pt.Y];
 
217
            }
 
218
 
 
219
            set
 
220
            {
 
221
                this[pt.X, pt.Y] = value;
 
222
            }
 
223
        }
 
224
 
 
225
        public bool this[int x, int y]
 
226
        {
 
227
            get
 
228
            {
 
229
                return Get(x, y);
 
230
            }
 
231
 
 
232
            set
 
233
            {
 
234
                Set(x, y, value);
 
235
            }
 
236
        }
 
237
 
 
238
        public BitVector2DSurfaceAdapter Clone()
 
239
        {
 
240
            ImageSurface clonedSurface = this.surface.Clone();
 
241
            return new BitVector2DSurfaceAdapter(clonedSurface);
 
242
        }
 
243
 
 
244
        object ICloneable.Clone()
 
245
        {
 
246
            return Clone();
 
247
        }
 
248
    }
 
249
}