1 2#include <stdio.h> 3#include <stack.h> 4 5#include <Region.h> 6 7#include "AccelerantHWInterface.h" 8#include "DirectWindowBuffer.h" 9 10#include "DrawingEngine.h" 11 12// constructor 13DrawingEngine::DrawingEngine(AccelerantHWInterface* interface, 14 DirectWindowBuffer* buffer) 15 : fHWInterface(interface), 16 fBuffer(buffer), 17 fCurrentClipping() 18{ 19} 20 21// destructor 22DrawingEngine::~DrawingEngine() 23{ 24} 25 26// Lock 27bool 28DrawingEngine::Lock() 29{ 30 return fHWInterface->Lock(); 31} 32 33// Unlock 34void 35DrawingEngine::Unlock() 36{ 37 fHWInterface->Unlock(); 38} 39 40// ConstrainClipping 41void 42DrawingEngine::ConstrainClipping(BRegion* region) 43{ 44 if (region) 45 fCurrentClipping = *region; 46 else 47 fCurrentClipping.MakeEmpty(); 48} 49 50// StraightLine 51bool 52DrawingEngine::StraightLine(BPoint a, BPoint b, const rgb_color& c) 53{ 54 uint8* dst = (uint8*)fBuffer->Bits(); 55 uint32 bpr = fBuffer->BytesPerRow(); 56 57 if (dst && fCurrentClipping.Frame().IsValid()) { 58 59 int32 clipBoxCount = fCurrentClipping.CountRects(); 60 61 uint32 color; 62 color = (255 << 24) | (c.red << 16) | (c.green << 8) | (c.blue); 63 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); 73 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; 82 } 83 } 84 } 85 86 return true; 87 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); 97 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; 105 } 106 } 107 } 108 109 return true; 110 } 111 } 112 return false; 113} 114 115// StrokeLine 116void 117DrawingEngine::StrokeLine(BPoint a, BPoint b, const rgb_color& color) 118{ 119 if (!StraightLine(a, b, color)) { 120 // ... 121 } 122} 123 124// StrokeRect 125void 126DrawingEngine::StrokeRect(BRect r, const rgb_color& color) 127{ 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); 132} 133 134// FillRegion 135void 136DrawingEngine::FillRegion(BRegion *region, const rgb_color& color) 137{ 138 if (Lock()) { 139 // for speed reasons, expected to be already clipped 140 fHWInterface->FillRegion(*region, color); 141 142 Unlock(); 143 } 144} 145 146// DrawString 147void 148DrawingEngine::DrawString(const char* string, BPoint baseLine, 149 const rgb_color& color) 150{ 151} 152 153 154 155 156struct node { 157 node() 158 { 159 pointers = NULL; 160 } 161 node(const BRect& r, int32 maxPointers) 162 { 163 init(r, maxPointers); 164 } 165 ~node() 166 { 167 delete [] pointers; 168 } 169 170 void init(const BRect& r, int32 maxPointers) 171 { 172 rect = r; 173 pointers = new node*[maxPointers]; 174 in_degree = 0; 175 next_pointer = 0; 176 } 177 178 void push(node* node) 179 { 180 pointers[next_pointer] = node; 181 next_pointer++; 182 } 183 node* top() 184 { 185 return pointers[next_pointer]; 186 } 187 node* pop() 188 { 189 node* ret = top(); 190 next_pointer--; 191 return ret; 192 } 193 194 BRect rect; 195 int32 in_degree; 196 node** pointers; 197 int32 next_pointer; 198}; 199 200bool 201is_left_of(const BRect& a, const BRect& b) 202{ 203 return (a.right < b.left); 204} 205bool 206is_above(const BRect& a, const BRect& b) 207{ 208 return (a.bottom < b.top); 209} 210 211void 212DrawingEngine::CopyRegion(BRegion* region, int32 xOffset, int32 yOffset) 213{ 214 if (Lock()) { 215 216 int32 count = region->CountRects(); 217 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); 223 } 224 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; 236 } 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; 242 } 243 } 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; 250 } 251 } else if (yOffset < 0) { 252 if (is_above(a, b)) { 253 cmp += 1; 254 } else if (is_above(b, a)) { 255 cmp -= 1; 256 } 257 } 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++; 265 } 266 } 267 } 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]); 273 } 274 } 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. 280 281 clipping_rect* sortedRectList = new clipping_rect[count]; 282 int32 nextSortedIndex = 0; 283 284 while (!inDegreeZeroNodes.empty()) { 285 node* n = inDegreeZeroNodes.top(); 286 inDegreeZeroNodes.pop(); 287 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++; 293 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]); 298 } 299 } 300 301 // trigger the HW accelerated blit 302 fHWInterface->CopyRegion(sortedRectList, count, xOffset, yOffset); 303 304 delete[] sortedRectList; 305 306 Unlock(); 307 } 308} 309