7 #include "AccelerantHWInterface.h"
8 #include "DirectWindowBuffer.h"
10 #include "DrawingEngine.h"
13 DrawingEngine::DrawingEngine(AccelerantHWInterface
* interface
,
14 DirectWindowBuffer
* buffer
)
15 : fHWInterface(interface
),
22 DrawingEngine::~DrawingEngine()
30 return fHWInterface
->Lock();
35 DrawingEngine::Unlock()
37 fHWInterface
->Unlock();
42 DrawingEngine::ConstrainClipping(BRegion
* region
)
45 fCurrentClipping
= *region
;
47 fCurrentClipping
.MakeEmpty();
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();
62 color
= (255 << 24) | (c
.red
<< 16) | (c
.green
<< 8) | (c
.blue
);
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
);
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
;
88 } else if (a
.y
== b
.y
) {
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
);
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
++) {
117 DrawingEngine::StrokeLine(BPoint a
, BPoint b
, const rgb_color
& color
)
119 if (!StraightLine(a
, b
, color
)) {
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
);
136 DrawingEngine::FillRegion(BRegion
*region
, const rgb_color
& color
)
139 // for speed reasons, expected to be already clipped
140 fHWInterface
->FillRegion(*region
, color
);
148 DrawingEngine::DrawString(const char* string
, BPoint baseLine
,
149 const rgb_color
& color
)
161 node(const BRect
& r
, int32 maxPointers
)
163 init(r
, maxPointers
);
170 void init(const BRect
& r
, int32 maxPointers
)
173 pointers
= new node
*[maxPointers
];
178 void push(node
* node
)
180 pointers
[next_pointer
] = node
;
185 return pointers
[next_pointer
];
201 is_left_of(const BRect
& a
, const BRect
& b
)
203 return (a
.right
< b
.left
);
206 is_above(const BRect
& a
, const BRect
& b
)
208 return (a
.bottom
< b
.top
);
212 DrawingEngine::CopyRegion(BRegion
* region
, int32 xOffset
, int32 yOffset
)
216 int32 count
= region
->CountRects();
218 // TODO: make this step unnecessary
219 // (by using different stack impl inside node)
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
);
230 // compare horizontally
232 if (is_left_of(a
, b
)) {
234 } else if (is_left_of(b
, a
)) {
237 } else if (xOffset
< 0) {
238 if (is_left_of(a
, b
)) {
240 } else if (is_left_of(b
, a
)) {
244 // compare vertically
246 if (is_above(a
, b
)) {
248 } else if (is_above(b
, a
)) {
251 } else if (yOffset
< 0) {
252 if (is_above(a
, b
)) {
254 } else if (is_above(b
, a
)) {
258 // add appropriate node as successor
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
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
;
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
;