1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
|
/* -*- mode: C++; tab-width: 4 -*- */
/* ===================================================================== *\
Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
All rights reserved.
This file is part of the Palm OS Emulator.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
\* ===================================================================== */
#ifndef EmRegion_h
#define EmRegion_h
/*
EmRegion is a cross-platform region class. It provides for the following needs:
- A common API that can be used on both Mac and Windows
- An internal 32-bit representation so that regions can be calculated
in a 32-bit coordinate plane.
- Automatic management of heap structures so that you don't have to
remember to call DisposeRgn or DeleteObject.
Use regions as you would something like EmRect. Create them on the stack,
declare them as data members, pass them by reference, etc. For instance,
ScriptViewCore uses regions as follows to determine the highlight area:
{
EmRegion scratch;
EmRect aRect;
// The selection's bounding rectangle
aRect = ...; // Calculate full bounds
highlight = aRect;
// ... minus beginning of the first line
aRect = ...; // Calculate leading area to subtract
scratch = aRect;
highlight.Subtract(scratch);
// ... and the end of the last line
aRect = ...; // Calculate trailing area to subtract
scratch = aRect;
highlight.Subtract(scratch);
}
If you need to decompose the region into a series of rectangles, you can use
the EmRegionRectIterator class for this. It can be used as follows:
EmRegionRectIterator iter(*this);
EmRect r;
while (iter.Next(r))
{
// ...do something with the rect...
}
This region class is based on the region class from ET++ 3.2.2, used by
permission from AndrŽ Weinand:
Regions: yes sure, just use the code and send me the bugs!
--andre
P.S.: my official life-long mail address is weinand@acm.org
*/
#include "EmPoint.h" // EmPoint
#include "EmRect.h" // EmRect
#include "EmRefCounted.h"
class EmRegion
{
public:
EmRegion (void);
// Creates a region spanning {0, 0, 0, 0}.
EmRegion (const EmRect& r);
// Creates a region spanning the given rectangle.
EmRegion (const EmRegion& r);
// Copy constructor. The internal data is copied via an internal
// reference counted object, so cloning regions is quick.
~EmRegion (void);
EmRegion& operator= (const EmRegion& r);
EmRegion& operator= (const EmRect& r);
// Assignment operator. Similar to copy constructor. There is also
// a version that takes an EmRect as an r-value.
void BeEmpty (void);
// Quickly empty out a region so that you don't have to do anything
// goofy like assigning a NULL rectangle to it.
const EmRect& Bounds (void) const;
// Returns an EmRect containing the bounds of the region.
long GetRects (EmRect* r) const;
// Decompose the region into a set of rectangles, returning the
// number of rectangles. You pass in a pointer to a buffer that
// will receive the rectangles. If you pass in NULL, no rectangles
// will be returned, but you'll still get the rectangle count.
// You should probably use a region iterator instead of this method
// if you want to mess with the rectangles.
Bool IsEmpty (void) const;
// Returns whether or not the region encompases any area.
Bool IsEqual (const EmRegion& r2) const;
// Compares two regions, returning whether or not they encompass
// the same area (set of pixels).
Bool Contains (const EmPoint& p) const;
// Returns whether or not the given point is in the interior of
// the area described by the region. Testing is performed on the
// normal half-open interval.
friend inline Bool operator== (const EmRegion& r1, const EmRegion& r2);
friend inline Bool operator!= (const EmRegion& r1, const EmRegion& r2);
// Shortcuts for the IsEqual method
void Offset (const EmPoint&);
void Offset (EmCoord dx, EmCoord dy);
// Offset the region by the given deltas. Positive deltas move
// the region down and to the right.
void Inset (const EmPoint&);
void Inset (EmCoord dx, EmCoord dy);
// Inset the region by the given deltas. Positive deltas move
// the region inward.
EmRegion& UnionWith (const EmRegion&);
EmRegion& IntersectWith(const EmRegion&);
EmRegion& Subtract (const EmRegion&);
EmRegion& XorWith (const EmRegion&);
// Modify the region in place. Note that XorWith is synthesized from
// the other operations, so it's not quite as effiecient as it
// could be.
friend inline EmRegion Union (const EmRegion& r1, const EmRegion& r2);
friend inline EmRegion Intersection(const EmRegion& r1, const EmRegion& r2);
friend inline EmRegion Difference (const EmRegion& r1, const EmRegion& r2);
friend inline EmRegion Xor (const EmRegion& r1, const EmRegion& r2);
// Versions of the previous four operations, with the difference
// being that neither of the given regions are modified. Instead,
// a new region containing the result is returned.
private:
enum EOpcode
{
eUnion = 0,
eDifference = 1,
eRevDifference = 2,
eIntersection = 3
};
EmRegion (const EmCoord* s, long len);
EmCoord* GetBuf (void) const;
long Length (void) const;
static EmRegion RegionOp (EOpcode code, const EmRegion& r1, const EmRegion& r2);
friend class EmRegionRectIterator;
class EmRegionImpl : public EmRefCounted
{
public:
EmRegionImpl (void);
EmRegionImpl (const EmCoord* s, long len);
EmRegionImpl (const EmRect& r);
EmRegionImpl (const EmRegion& r);
~EmRegionImpl (void);
Bool operator== (const EmRegionImpl& other) const;
long GetRects (EmRect* r) const;
Bool IsEqual (const EmRegionImpl&) const;
Bool Contains (const EmPoint& p) const;
void Offset (EmCoord dx, EmCoord dy);
protected:
void CalcBounds (void);
protected:
friend class EmRegion;
EmRect fBounds;
long fCapacity;
EmCoord* fBuf;
EmCoord fRectBuf[7];
};
EmRefCounter<EmRegionImpl> fImpl;
};
class EmRegionRectIterator
{
public:
EmRegionRectIterator (const EmRegion& r);
void Reset (void);
Bool Next (EmRect& r);
private:
EmRegion fRegion;
EmCoord* fBufPtr;
long fNext;
};
#endif // EmRegion_h
|