vfs: check userland buffers before reading them.
[haiku.git] / src / tests / servers / app / newerClipping / drawing / DrawingEngine.cpp
bloba346ade9b294315de8eb43b240096839fea7534b
2 #include <stdio.h>
3 #include <stack.h>
5 #include <Region.h>
7 #include "AccelerantHWInterface.h"
8 #include "DirectWindowBuffer.h"
10 #include "DrawingEngine.h"
12 // constructor
13 DrawingEngine::DrawingEngine(AccelerantHWInterface* interface,
14 DirectWindowBuffer* buffer)
15 : fHWInterface(interface),
16 fBuffer(buffer),
17 fCurrentClipping()
21 // destructor
22 DrawingEngine::~DrawingEngine()
26 // Lock
27 bool
28 DrawingEngine::Lock()
30 return fHWInterface->Lock();
33 // Unlock
34 void
35 DrawingEngine::Unlock()
37 fHWInterface->Unlock();
40 // ConstrainClipping
41 void
42 DrawingEngine::ConstrainClipping(BRegion* region)
44 if (region)
45 fCurrentClipping = *region;
46 else
47 fCurrentClipping.MakeEmpty();
50 // StraightLine
51 bool
52 DrawingEngine::StraightLine(BPoint a, BPoint b, const rgb_color& c)
54 uint8* dst = (uint8*)fBuffer->Bits();
55 uint32 bpr = fBuffer->BytesPerRow();
57 if (dst && fCurrentClipping.Frame().IsValid()) {
59 int32 clipBoxCount = fCurrentClipping.CountRects();
61 uint32 color;
62 color = (255 << 24) | (c.red << 16) | (c.green << 8) | (c.blue);
64 if (a.x == b.x) {
65 // vertical
66 int32 x = (int32)a.x;
67 dst += x * 4;
68 int32 y1 = (int32)min_c(a.y, b.y);
69 int32 y2 = (int32)max_c(a.y, b.y);
70 // draw a line, iterate over clipping boxes
71 for (int32 i = 0; i < clipBoxCount; i++) {
72 clipping_rect rect = fCurrentClipping.RectAtInt(i);
74 if (rect.left <= x &&
75 rect.right >= x) {
76 int32 i = max_c(rect.top, y1);
77 int32 end = min_c(rect.bottom, y2);
78 uint8* handle = dst + i * bpr;
79 for (; i <= end; i++) {
80 *(uint32*)handle = color;
81 handle += bpr;
86 return true;
88 } else if (a.y == b.y) {
89 // horizontal
90 int32 y = (int32)a.y;
91 dst += y * bpr;
92 int32 x1 = (int32)min_c(a.x, b.x);
93 int32 x2 = (int32)max_c(a.x, b.x);
94 // draw a line, iterate over clipping boxes
95 for (int32 i = 0; i < clipBoxCount; i++) {
96 clipping_rect rect = fCurrentClipping.RectAtInt(i);
98 if (rect.top <= y &&
99 rect.bottom >= y) {
100 int32 i = max_c(rect.left, x1);
101 int32 end = min_c(rect.right, x2);
102 uint32* handle = (uint32*)(dst + i * 4);
103 for (; i <= end; i++) {
104 *handle++ = color;
109 return true;
112 return false;
115 // StrokeLine
116 void
117 DrawingEngine::StrokeLine(BPoint a, BPoint b, const rgb_color& color)
119 if (!StraightLine(a, b, color)) {
120 // ...
124 // StrokeRect
125 void
126 DrawingEngine::StrokeRect(BRect r, const rgb_color& color)
128 StrokeLine(r.LeftTop(), r.RightTop(), color);
129 StrokeLine(r.RightTop(), r.RightBottom(), color);
130 StrokeLine(r.RightBottom(), r.LeftBottom(), color);
131 StrokeLine(r.LeftBottom(), r.LeftTop(), color);
134 // FillRegion
135 void
136 DrawingEngine::FillRegion(BRegion *region, const rgb_color& color)
138 if (Lock()) {
139 // for speed reasons, expected to be already clipped
140 fHWInterface->FillRegion(*region, color);
142 Unlock();
146 // DrawString
147 void
148 DrawingEngine::DrawString(const char* string, BPoint baseLine,
149 const rgb_color& color)
156 struct node {
157 node()
159 pointers = NULL;
161 node(const BRect& r, int32 maxPointers)
163 init(r, maxPointers);
165 ~node()
167 delete [] pointers;
170 void init(const BRect& r, int32 maxPointers)
172 rect = r;
173 pointers = new node*[maxPointers];
174 in_degree = 0;
175 next_pointer = 0;
178 void push(node* node)
180 pointers[next_pointer] = node;
181 next_pointer++;
183 node* top()
185 return pointers[next_pointer];
187 node* pop()
189 node* ret = top();
190 next_pointer--;
191 return ret;
194 BRect rect;
195 int32 in_degree;
196 node** pointers;
197 int32 next_pointer;
200 bool
201 is_left_of(const BRect& a, const BRect& b)
203 return (a.right < b.left);
205 bool
206 is_above(const BRect& a, const BRect& b)
208 return (a.bottom < b.top);
211 void
212 DrawingEngine::CopyRegion(BRegion* region, int32 xOffset, int32 yOffset)
214 if (Lock()) {
216 int32 count = region->CountRects();
218 // TODO: make this step unnecessary
219 // (by using different stack impl inside node)
220 node nodes[count];
221 for (int32 i= 0; i < count; i++) {
222 nodes[i].init(region->RectAt(i), count);
225 for (int32 i = 0; i < count; i++) {
226 BRect a = region->RectAt(i);
227 for (int32 k = i + 1; k < count; k++) {
228 BRect b = region->RectAt(k);
229 int cmp = 0;
230 // compare horizontally
231 if (xOffset > 0) {
232 if (is_left_of(a, b)) {
233 cmp -= 1;
234 } else if (is_left_of(b, a)) {
235 cmp += 1;
237 } else if (xOffset < 0) {
238 if (is_left_of(a, b)) {
239 cmp += 1;
240 } else if (is_left_of(b, a)) {
241 cmp -= 1;
244 // compare vertically
245 if (yOffset > 0) {
246 if (is_above(a, b)) {
247 cmp -= 1;
248 } else if (is_above(b, a)) {
249 cmp += 1;
251 } else if (yOffset < 0) {
252 if (is_above(a, b)) {
253 cmp += 1;
254 } else if (is_above(b, a)) {
255 cmp -= 1;
258 // add appropriate node as successor
259 if (cmp > 0) {
260 nodes[i].push(&nodes[k]);
261 nodes[k].in_degree++;
262 } else if (cmp < 0) {
263 nodes[k].push(&nodes[i]);
264 nodes[i].in_degree++;
268 // put all nodes onto a stack that have an "indegree" count of zero
269 stack<node*> inDegreeZeroNodes;
270 for (int32 i = 0; i < count; i++) {
271 if (nodes[i].in_degree == 0) {
272 inDegreeZeroNodes.push(&nodes[i]);
275 // pop the rects from the stack, do the actual copy operation
276 // and decrease the "indegree" count of the other rects not
277 // currently on the stack and to which the current rect pointed
278 // to. If their "indegree" count reaches zero, put them onto the
279 // stack as well.
281 clipping_rect* sortedRectList = new clipping_rect[count];
282 int32 nextSortedIndex = 0;
284 while (!inDegreeZeroNodes.empty()) {
285 node* n = inDegreeZeroNodes.top();
286 inDegreeZeroNodes.pop();
288 sortedRectList[nextSortedIndex].left = (int32)n->rect.left;
289 sortedRectList[nextSortedIndex].top = (int32)n->rect.top;
290 sortedRectList[nextSortedIndex].right = (int32)n->rect.right;
291 sortedRectList[nextSortedIndex].bottom = (int32)n->rect.bottom;
292 nextSortedIndex++;
294 for (int32 k = 0; k < n->next_pointer; k++) {
295 n->pointers[k]->in_degree--;
296 if (n->pointers[k]->in_degree == 0)
297 inDegreeZeroNodes.push(n->pointers[k]);
301 // trigger the HW accelerated blit
302 fHWInterface->CopyRegion(sortedRectList, count, xOffset, yOffset);
304 delete[] sortedRectList;
306 Unlock();