1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #include "RemoteDrawingEngine.h" |
10 | #include "RemoteMessage.h" |
11 | |
12 | #include "BitmapDrawingEngine.h" |
13 | #include "DrawState.h" |
14 | |
15 | #include <Bitmap.h> |
16 | #include <utf8_functions.h> |
17 | |
18 | #include <new> |
19 | |
20 | |
21 | RemoteDrawingEngine::RemoteDrawingEngine(RemoteHWInterface* interface) |
22 | : |
23 | DrawingEngine(interface), |
24 | fHWInterface(interface), |
25 | fToken((uint32)this), |
26 | fExtendWidth(0), |
27 | fCallbackAdded(false), |
28 | fResultNotify(-1), |
29 | fStringWidthResult(0.0f), |
30 | fReadBitmapResult(NULL__null), |
31 | fBitmapDrawingEngine(NULL__null) |
32 | { |
33 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
34 | message.Start(RP_CREATE_STATE); |
35 | message.Add(fToken); |
36 | } |
37 | |
38 | |
39 | RemoteDrawingEngine::~RemoteDrawingEngine() |
40 | { |
41 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
42 | message.Start(RP_DELETE_STATE); |
43 | message.Add(fToken); |
44 | message.Flush(); |
45 | |
46 | delete fBitmapDrawingEngine; |
47 | |
48 | if (fCallbackAdded) |
49 | fHWInterface->RemoveCallback(fToken); |
50 | if (fResultNotify >= 0) |
51 | delete_sem(fResultNotify); |
52 | } |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | void |
59 | RemoteDrawingEngine::FrameBufferChanged() |
60 | { |
61 | |
62 | } |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | void |
69 | RemoteDrawingEngine::SetCopyToFrontEnabled(bool enabled) |
70 | { |
71 | DrawingEngine::SetCopyToFrontEnabled(enabled); |
72 | |
73 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
74 | message.Start(enabled ? RP_ENABLE_SYNC_DRAWING : RP_DISABLE_SYNC_DRAWING); |
75 | message.Add(fToken); |
76 | } |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | void |
84 | RemoteDrawingEngine::ConstrainClippingRegion(const BRegion* region) |
85 | { |
86 | if (fClippingRegion == *region) |
87 | return; |
88 | |
89 | fClippingRegion = *region; |
90 | |
91 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
92 | message.Start(RP_CONSTRAIN_CLIPPING_REGION); |
93 | message.Add(fToken); |
94 | message.AddRegion(*region); |
95 | } |
96 | |
97 | |
98 | void |
99 | RemoteDrawingEngine::SetDrawState(const DrawState* state, int32 xOffset, |
100 | int32 yOffset) |
101 | { |
102 | SetPenSize(state->PenSize()); |
103 | SetDrawingMode(state->GetDrawingMode()); |
104 | SetBlendingMode(state->AlphaSrcMode(), state->AlphaFncMode()); |
105 | SetPattern(state->GetPattern().GetPattern()); |
106 | SetStrokeMode(state->LineCapMode(), state->LineJoinMode(), |
107 | state->MiterLimit()); |
108 | SetHighColor(state->HighColor()); |
109 | SetLowColor(state->LowColor()); |
110 | SetFont(state->Font()); |
111 | |
112 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
113 | message.Start(RP_SET_OFFSETS); |
114 | message.Add(fToken); |
115 | message.Add(xOffset); |
116 | message.Add(yOffset); |
117 | } |
118 | |
119 | |
120 | void |
121 | RemoteDrawingEngine::SetHighColor(const rgb_color& color) |
122 | { |
123 | if (fState.HighColor() == color) |
124 | return; |
125 | |
126 | fState.SetHighColor(color); |
127 | |
128 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
129 | message.Start(RP_SET_HIGH_COLOR); |
130 | message.Add(fToken); |
131 | message.Add(color); |
132 | } |
133 | |
134 | |
135 | void |
136 | RemoteDrawingEngine::SetLowColor(const rgb_color& color) |
137 | { |
138 | if (fState.LowColor() == color) |
139 | return; |
140 | |
141 | fState.SetLowColor(color); |
142 | |
143 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
144 | message.Start(RP_SET_LOW_COLOR); |
145 | message.Add(fToken); |
146 | message.Add(color); |
147 | } |
148 | |
149 | |
150 | void |
151 | RemoteDrawingEngine::SetPenSize(float size) |
152 | { |
153 | if (fState.PenSize() == size) |
154 | return; |
155 | |
156 | fState.SetPenSize(size); |
157 | fExtendWidth = -(size / 2); |
158 | |
159 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
160 | message.Start(RP_SET_PEN_SIZE); |
161 | message.Add(fToken); |
162 | message.Add(size); |
163 | } |
164 | |
165 | |
166 | void |
167 | RemoteDrawingEngine::SetStrokeMode(cap_mode lineCap, join_mode joinMode, |
168 | float miterLimit) |
169 | { |
170 | if (fState.LineCapMode() == lineCap && fState.LineJoinMode() == joinMode |
171 | && fState.MiterLimit() == miterLimit) |
172 | return; |
173 | |
174 | fState.SetLineCapMode(lineCap); |
175 | fState.SetLineJoinMode(joinMode); |
176 | fState.SetMiterLimit(miterLimit); |
177 | |
178 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
179 | message.Start(RP_SET_STROKE_MODE); |
180 | message.Add(fToken); |
181 | message.Add(lineCap); |
182 | message.Add(joinMode); |
183 | message.Add(miterLimit); |
184 | } |
185 | |
186 | |
187 | void |
188 | RemoteDrawingEngine::SetBlendingMode(source_alpha sourceAlpha, |
189 | alpha_function alphaFunc) |
190 | { |
191 | if (fState.AlphaSrcMode() == sourceAlpha |
192 | && fState.AlphaFncMode() == alphaFunc) |
193 | return; |
194 | |
195 | fState.SetBlendingMode(sourceAlpha, alphaFunc); |
196 | |
197 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
198 | message.Start(RP_SET_BLENDING_MODE); |
199 | message.Add(fToken); |
200 | message.Add(sourceAlpha); |
201 | message.Add(alphaFunc); |
202 | } |
203 | |
204 | |
205 | void |
206 | RemoteDrawingEngine::SetPattern(const struct pattern& pattern) |
207 | { |
208 | if (fState.GetPattern() == pattern) |
209 | return; |
210 | |
211 | fState.SetPattern(pattern); |
212 | |
213 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
214 | message.Start(RP_SET_PATTERN); |
215 | message.Add(fToken); |
216 | message.Add(pattern); |
217 | } |
218 | |
219 | |
220 | void |
221 | RemoteDrawingEngine::SetDrawingMode(drawing_mode mode) |
222 | { |
223 | if (fState.GetDrawingMode() == mode) |
224 | return; |
225 | |
226 | fState.SetDrawingMode(mode); |
227 | |
228 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
229 | message.Start(RP_SET_DRAWING_MODE); |
230 | message.Add(fToken); |
231 | message.Add(mode); |
232 | } |
233 | |
234 | |
235 | void |
236 | RemoteDrawingEngine::SetDrawingMode(drawing_mode mode, drawing_mode& oldMode) |
237 | { |
238 | oldMode = fState.GetDrawingMode(); |
239 | SetDrawingMode(mode); |
240 | } |
241 | |
242 | |
243 | void |
244 | RemoteDrawingEngine::SetFont(const ServerFont& font) |
245 | { |
246 | if (fState.Font() == font) |
247 | return; |
248 | |
249 | fState.SetFont(font); |
250 | |
251 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
252 | message.Start(RP_SET_FONT); |
253 | message.Add(fToken); |
254 | message.AddFont(font); |
255 | } |
256 | |
257 | |
258 | void |
259 | RemoteDrawingEngine::SetFont(const DrawState* state) |
260 | { |
261 | SetFont(state->Font()); |
262 | } |
263 | |
264 | |
265 | |
266 | |
267 | |
268 | BRect |
269 | RemoteDrawingEngine::CopyRect(BRect rect, int32 xOffset, int32 yOffset) const |
270 | { |
271 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
272 | message.Start(RP_COPY_RECT_NO_CLIPPING); |
273 | message.Add(xOffset); |
274 | message.Add(yOffset); |
275 | message.Add(rect); |
276 | return rect.OffsetBySelf(xOffset, yOffset); |
277 | } |
278 | |
279 | |
280 | void |
281 | RemoteDrawingEngine::InvertRect(BRect rect) |
282 | { |
283 | if (!fClippingRegion.Intersects(rect)) |
284 | return; |
285 | |
286 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
287 | message.Start(RP_INVERT_RECT); |
288 | message.Add(fToken); |
289 | message.Add(rect); |
290 | } |
291 | |
292 | |
293 | void |
294 | RemoteDrawingEngine::DrawBitmap(ServerBitmap* bitmap, const BRect& _bitmapRect, |
295 | const BRect& _viewRect, uint32 options) |
296 | { |
297 | BRect bitmapRect = _bitmapRect; |
298 | BRect viewRect = _viewRect; |
299 | double xScale = (bitmapRect.Width() + 1) / (viewRect.Width() + 1); |
300 | double yScale = (bitmapRect.Height() + 1) / (viewRect.Height() + 1); |
301 | |
302 | |
303 | |
304 | BRect actualBitmapRect = bitmap->Bounds(); |
305 | if (bitmapRect.left < actualBitmapRect.left) { |
306 | float diff = actualBitmapRect.left - bitmapRect.left; |
307 | viewRect.left += diff / xScale; |
308 | bitmapRect.left = actualBitmapRect.left; |
309 | } |
310 | if (bitmapRect.top < actualBitmapRect.top) { |
311 | float diff = actualBitmapRect.top - bitmapRect.top; |
312 | viewRect.top += diff / yScale; |
313 | bitmapRect.top = actualBitmapRect.top; |
314 | } |
315 | if (bitmapRect.right > actualBitmapRect.right) { |
316 | float diff = bitmapRect.right - actualBitmapRect.right; |
317 | viewRect.right -= diff / xScale; |
318 | bitmapRect.right = actualBitmapRect.right; |
319 | } |
320 | if (bitmapRect.bottom > actualBitmapRect.bottom) { |
321 | float diff = bitmapRect.bottom - actualBitmapRect.bottom; |
322 | viewRect.bottom -= diff / yScale; |
323 | bitmapRect.bottom = actualBitmapRect.bottom; |
324 | } |
325 | |
326 | BRegion clippedRegion(viewRect); |
327 | clippedRegion.IntersectWith(&fClippingRegion); |
328 | |
329 | int32 rectCount = clippedRegion.CountRects(); |
330 | if (rectCount == 0) |
331 | return; |
332 | |
333 | if (rectCount > 1 || (rectCount == 1 && clippedRegion.RectAt(0) != viewRect) |
334 | || viewRect.Width() < bitmapRect.Width() |
335 | || viewRect.Height() < bitmapRect.Height()) { |
336 | UtilityBitmap** bitmaps; |
337 | if (_ExtractBitmapRegions(*bitmap, options, bitmapRect, viewRect, |
338 | xScale, yScale, clippedRegion, bitmaps) != B_OK((int)0)) { |
339 | return; |
340 | } |
341 | |
342 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
343 | message.Start(RP_DRAW_BITMAP_RECTS); |
344 | message.Add(fToken); |
345 | message.Add(options); |
346 | message.Add(bitmap->ColorSpace()); |
347 | message.Add(bitmap->Flags()); |
348 | message.Add(rectCount); |
349 | |
350 | for (int32 i = 0; i < rectCount; i++) { |
351 | message.Add(clippedRegion.RectAt(i)); |
352 | message.AddBitmap(*bitmaps[i], true); |
353 | delete bitmaps[i]; |
354 | } |
355 | |
356 | free(bitmaps); |
357 | return; |
358 | } |
359 | |
360 | |
361 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
362 | message.Start(RP_DRAW_BITMAP); |
363 | message.Add(fToken); |
364 | message.Add(bitmapRect); |
365 | message.Add(viewRect); |
366 | message.Add(options); |
367 | message.AddBitmap(*bitmap); |
368 | } |
369 | |
370 | |
371 | void |
372 | RemoteDrawingEngine::DrawArc(BRect rect, const float& angle, const float& span, |
373 | bool filled) |
374 | { |
375 | BRect bounds = rect; |
376 | if (!filled) |
377 | bounds.InsetBy(fExtendWidth, fExtendWidth); |
378 | |
379 | if (!fClippingRegion.Intersects(bounds)) |
380 | return; |
381 | |
382 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
383 | message.Start(filled ? RP_FILL_ARC : RP_STROKE_ARC); |
384 | message.Add(fToken); |
385 | message.Add(rect); |
386 | message.Add(angle); |
387 | message.Add(span); |
388 | } |
389 | |
390 | void |
391 | RemoteDrawingEngine::FillArc(BRect rect, const float& angle, const float& span, |
392 | const BGradient& gradient) |
393 | { |
394 | if (!fClippingRegion.Intersects(rect)) |
395 | return; |
396 | |
397 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
398 | message.Start(RP_FILL_ARC_GRADIENT); |
399 | message.Add(fToken); |
400 | message.Add(rect); |
401 | message.Add(angle); |
402 | message.Add(span); |
403 | message.AddGradient(gradient); |
404 | } |
405 | |
406 | |
407 | void |
408 | RemoteDrawingEngine::DrawBezier(BPoint* points, bool filled) |
409 | { |
410 | BRect bounds = _BuildBounds(points, 4); |
411 | if (!filled) |
412 | bounds.InsetBy(fExtendWidth, fExtendWidth); |
413 | |
414 | if (!fClippingRegion.Intersects(bounds)) |
415 | return; |
416 | |
417 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
418 | message.Start(filled ? RP_FILL_BEZIER : RP_STROKE_BEZIER); |
419 | message.Add(fToken); |
420 | message.AddList(points, 4); |
421 | } |
422 | |
423 | |
424 | void |
425 | RemoteDrawingEngine::FillBezier(BPoint* points, const BGradient& gradient) |
426 | { |
427 | BRect bounds = _BuildBounds(points, 4); |
428 | if (!fClippingRegion.Intersects(bounds)) |
429 | return; |
430 | |
431 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
432 | message.Start(RP_FILL_BEZIER_GRADIENT); |
433 | message.Add(fToken); |
434 | message.AddList(points, 4); |
435 | message.AddGradient(gradient); |
436 | } |
437 | |
438 | |
439 | void |
440 | RemoteDrawingEngine::DrawEllipse(BRect rect, bool filled) |
441 | { |
442 | BRect bounds = rect; |
443 | if (!filled) |
444 | bounds.InsetBy(fExtendWidth, fExtendWidth); |
445 | |
446 | if (!fClippingRegion.Intersects(bounds)) |
447 | return; |
448 | |
449 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
450 | message.Start(filled ? RP_FILL_ELLIPSE : RP_STROKE_ELLIPSE); |
451 | message.Add(fToken); |
452 | message.Add(rect); |
453 | } |
454 | |
455 | |
456 | void |
457 | RemoteDrawingEngine::FillEllipse(BRect rect, const BGradient& gradient) |
458 | { |
459 | if (!fClippingRegion.Intersects(rect)) |
460 | return; |
461 | |
462 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
463 | message.Start(RP_FILL_ELLIPSE_GRADIENT); |
464 | message.Add(fToken); |
465 | message.Add(rect); |
466 | message.AddGradient(gradient); |
467 | } |
468 | |
469 | |
470 | void |
471 | RemoteDrawingEngine::DrawPolygon(BPoint* pointList, int32 numPoints, |
472 | BRect bounds, bool filled, bool closed) |
473 | { |
474 | BRect clipBounds = bounds; |
475 | if (!filled) |
476 | clipBounds.InsetBy(fExtendWidth, fExtendWidth); |
477 | |
478 | if (!fClippingRegion.Intersects(clipBounds)) |
479 | return; |
480 | |
481 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
482 | message.Start(filled ? RP_FILL_POLYGON : RP_STROKE_POLYGON); |
483 | message.Add(fToken); |
484 | message.Add(bounds); |
485 | message.Add(closed); |
486 | message.Add(numPoints); |
487 | for (int32 i = 0; i < numPoints; i++) |
488 | message.Add(pointList[i]); |
489 | } |
490 | |
491 | |
492 | void |
493 | RemoteDrawingEngine::FillPolygon(BPoint* pointList, int32 numPoints, |
494 | BRect bounds, const BGradient& gradient, bool closed) |
495 | { |
496 | if (!fClippingRegion.Intersects(bounds)) |
497 | return; |
498 | |
499 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
500 | message.Start(RP_FILL_POLYGON_GRADIENT); |
501 | message.Add(fToken); |
502 | message.Add(bounds); |
503 | message.Add(closed); |
504 | message.Add(numPoints); |
505 | for (int32 i = 0; i < numPoints; i++) |
506 | message.Add(pointList[i]); |
507 | message.AddGradient(gradient); |
508 | } |
509 | |
510 | |
511 | |
512 | |
513 | |
514 | void |
515 | RemoteDrawingEngine::StrokePoint(const BPoint& point, const rgb_color& color) |
516 | { |
517 | BRect bounds(point, point); |
518 | bounds.InsetBy(fExtendWidth, fExtendWidth); |
519 | |
520 | if (!fClippingRegion.Intersects(bounds)) |
521 | return; |
522 | |
523 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
524 | message.Start(RP_STROKE_POINT_COLOR); |
525 | message.Add(fToken); |
526 | message.Add(point); |
527 | message.Add(color); |
528 | } |
529 | |
530 | |
531 | void |
532 | RemoteDrawingEngine::StrokeLine(const BPoint& start, const BPoint& end, |
533 | const rgb_color& color) |
534 | { |
535 | BPoint points[2] = { start, end }; |
536 | BRect bounds = _BuildBounds(points, 2); |
537 | |
538 | if (!fClippingRegion.Intersects(bounds)) |
539 | return; |
540 | |
541 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
542 | message.Start(RP_STROKE_LINE_1PX_COLOR); |
543 | message.Add(fToken); |
544 | message.AddList(points, 2); |
545 | message.Add(color); |
546 | } |
547 | |
548 | |
549 | void |
550 | RemoteDrawingEngine::StrokeRect(BRect rect, const rgb_color &color) |
551 | { |
552 | BRect bounds = rect; |
553 | bounds.InsetBy(fExtendWidth, fExtendWidth); |
554 | |
555 | if (!fClippingRegion.Intersects(bounds)) |
556 | return; |
557 | |
558 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
559 | message.Start(RP_STROKE_RECT_1PX_COLOR); |
560 | message.Add(fToken); |
561 | message.Add(rect); |
562 | message.Add(color); |
563 | } |
564 | |
565 | |
566 | void |
567 | RemoteDrawingEngine::FillRect(BRect rect, const rgb_color& color) |
568 | { |
569 | if (!fClippingRegion.Intersects(rect)) |
570 | return; |
571 | |
572 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
573 | message.Start(RP_FILL_RECT_COLOR); |
574 | message.Add(fToken); |
575 | message.Add(rect); |
576 | message.Add(color); |
577 | } |
578 | |
579 | |
580 | void |
581 | RemoteDrawingEngine::FillRegion(BRegion& region, const rgb_color& color) |
582 | { |
583 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
584 | message.Start(RP_FILL_REGION_COLOR_NO_CLIPPING); |
585 | message.AddRegion(region); |
586 | message.Add(color); |
587 | } |
588 | |
589 | |
590 | |
591 | |
592 | |
593 | void |
594 | RemoteDrawingEngine::StrokeRect(BRect rect) |
595 | { |
596 | BRect bounds = rect; |
597 | bounds.InsetBy(fExtendWidth, fExtendWidth); |
598 | |
599 | if (!fClippingRegion.Intersects(bounds)) |
600 | return; |
601 | |
602 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
603 | message.Start(RP_STROKE_RECT); |
604 | message.Add(fToken); |
605 | message.Add(rect); |
606 | } |
607 | |
608 | |
609 | void |
610 | RemoteDrawingEngine::FillRect(BRect rect) |
611 | { |
612 | if (!fClippingRegion.Intersects(rect)) |
613 | return; |
614 | |
615 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
616 | message.Start(RP_FILL_RECT); |
617 | message.Add(fToken); |
618 | message.Add(rect); |
619 | } |
620 | |
621 | |
622 | void |
623 | RemoteDrawingEngine::FillRect(BRect rect, const BGradient& gradient) |
624 | { |
625 | if (!fClippingRegion.Intersects(rect)) |
626 | return; |
627 | |
628 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
629 | message.Start(RP_FILL_RECT_GRADIENT); |
630 | message.Add(fToken); |
631 | message.Add(rect); |
632 | message.AddGradient(gradient); |
633 | } |
634 | |
635 | |
636 | void |
637 | RemoteDrawingEngine::FillRegion(BRegion& region) |
638 | { |
639 | BRegion clippedRegion = region; |
640 | clippedRegion.IntersectWith(&fClippingRegion); |
641 | if (clippedRegion.CountRects() == 0) |
642 | return; |
643 | |
644 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
645 | message.Start(RP_FILL_REGION); |
646 | message.Add(fToken); |
647 | message.AddRegion(clippedRegion.CountRects() < region.CountRects() |
648 | ? clippedRegion : region); |
649 | } |
650 | |
651 | |
652 | void |
653 | RemoteDrawingEngine::FillRegion(BRegion& region, const BGradient& gradient) |
654 | { |
655 | BRegion clippedRegion = region; |
656 | clippedRegion.IntersectWith(&fClippingRegion); |
657 | if (clippedRegion.CountRects() == 0) |
658 | return; |
659 | |
660 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
661 | message.Start(RP_FILL_REGION_GRADIENT); |
662 | message.Add(fToken); |
663 | message.AddRegion(clippedRegion.CountRects() < region.CountRects() |
664 | ? clippedRegion : region); |
665 | message.AddGradient(gradient); |
666 | } |
667 | |
668 | |
669 | void |
670 | RemoteDrawingEngine::DrawRoundRect(BRect rect, float xRadius, float yRadius, |
671 | bool filled) |
672 | { |
673 | BRect bounds = rect; |
674 | if (!filled) |
675 | bounds.InsetBy(fExtendWidth, fExtendWidth); |
676 | |
677 | if (!fClippingRegion.Intersects(bounds)) |
678 | return; |
679 | |
680 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
681 | message.Start(filled ? RP_FILL_ROUND_RECT : RP_STROKE_ROUND_RECT); |
682 | message.Add(fToken); |
683 | message.Add(rect); |
684 | message.Add(xRadius); |
685 | message.Add(yRadius); |
686 | } |
687 | |
688 | |
689 | void |
690 | RemoteDrawingEngine::FillRoundRect(BRect rect, float xRadius, float yRadius, |
691 | const BGradient& gradient) |
692 | { |
693 | if (!fClippingRegion.Intersects(rect)) |
694 | return; |
695 | |
696 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
697 | message.Start(RP_FILL_ROUND_RECT_GRADIENT); |
698 | message.Add(fToken); |
699 | message.Add(rect); |
700 | message.Add(xRadius); |
701 | message.Add(yRadius); |
702 | message.AddGradient(gradient); |
703 | } |
704 | |
705 | |
706 | void |
707 | RemoteDrawingEngine::DrawShape(const BRect& bounds, int32 opCount, |
708 | const uint32* opList, int32 pointCount, const BPoint* pointList, |
709 | bool filled, const BPoint& viewToScreenOffset, float viewScale) |
710 | { |
711 | BRect clipBounds = bounds; |
712 | if (!filled) |
713 | clipBounds.InsetBy(fExtendWidth, fExtendWidth); |
714 | |
715 | if (!fClippingRegion.Intersects(clipBounds)) |
716 | return; |
717 | |
718 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
719 | message.Start(filled ? RP_FILL_SHAPE : RP_STROKE_SHAPE); |
720 | message.Add(fToken); |
721 | message.Add(bounds); |
722 | message.Add(opCount); |
723 | message.AddList(opList, opCount); |
724 | message.Add(pointCount); |
725 | message.AddList(pointList, pointCount); |
726 | message.Add(viewToScreenOffset); |
727 | message.Add(viewScale); |
728 | } |
729 | |
730 | |
731 | void |
732 | RemoteDrawingEngine::FillShape(const BRect& bounds, int32 opCount, |
733 | const uint32* opList, int32 pointCount, const BPoint* pointList, |
734 | const BGradient& gradient, const BPoint& viewToScreenOffset, |
735 | float viewScale) |
736 | { |
737 | if (!fClippingRegion.Intersects(bounds)) |
738 | return; |
739 | |
740 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
741 | message.Start(RP_FILL_SHAPE_GRADIENT); |
742 | message.Add(fToken); |
743 | message.Add(bounds); |
744 | message.Add(opCount); |
745 | message.AddList(opList, opCount); |
746 | message.Add(pointCount); |
747 | message.AddList(pointList, pointCount); |
748 | message.AddGradient(gradient); |
749 | message.Add(viewToScreenOffset); |
750 | message.Add(viewScale); |
751 | } |
752 | |
753 | |
754 | void |
755 | RemoteDrawingEngine::DrawTriangle(BPoint* points, const BRect& bounds, |
756 | bool filled) |
757 | { |
758 | BRect clipBounds = bounds; |
759 | if (!filled) |
760 | clipBounds.InsetBy(fExtendWidth, fExtendWidth); |
761 | |
762 | if (!fClippingRegion.Intersects(clipBounds)) |
763 | return; |
764 | |
765 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
766 | message.Start(filled ? RP_FILL_TRIANGLE : RP_STROKE_TRIANGLE); |
767 | message.Add(fToken); |
768 | message.AddList(points, 3); |
769 | message.Add(bounds); |
770 | } |
771 | |
772 | |
773 | void |
774 | RemoteDrawingEngine::FillTriangle(BPoint* points, const BRect& bounds, |
775 | const BGradient& gradient) |
776 | { |
777 | if (!fClippingRegion.Intersects(bounds)) |
778 | return; |
779 | |
780 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
781 | message.Start(RP_FILL_TRIANGLE_GRADIENT); |
782 | message.Add(fToken); |
783 | message.Add(points[0]); |
784 | message.Add(points[1]); |
785 | message.Add(points[2]); |
786 | message.Add(bounds); |
787 | message.AddGradient(gradient); |
788 | } |
789 | |
790 | |
791 | void |
792 | RemoteDrawingEngine::StrokeLine(const BPoint &start, const BPoint &end) |
793 | { |
794 | BPoint points[2] = { start, end }; |
795 | BRect bounds = _BuildBounds(points, 2); |
796 | |
797 | if (!fClippingRegion.Intersects(bounds)) |
798 | return; |
799 | |
800 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
801 | message.Start(RP_STROKE_LINE); |
802 | message.Add(fToken); |
803 | message.AddList(points, 2); |
804 | } |
805 | |
806 | |
807 | void |
808 | RemoteDrawingEngine::StrokeLineArray(int32 numLines, |
809 | const ViewLineArrayInfo *lineData) |
810 | { |
811 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
812 | message.Start(RP_STROKE_LINE_ARRAY); |
813 | message.Add(fToken); |
814 | message.Add(numLines); |
815 | for (int32 i = 0; i < numLines; i++) |
816 | message.AddArrayLine(lineData[i]); |
817 | } |
818 | |
819 | |
820 | |
821 | |
822 | |
823 | BPoint |
824 | RemoteDrawingEngine::DrawString(const char* string, int32 length, |
825 | const BPoint& point, escapement_delta* delta) |
826 | { |
827 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
828 | |
829 | message.Start(RP_DRAW_STRING); |
830 | message.Add(fToken); |
831 | message.Add(point); |
832 | message.AddString(string, length); |
833 | message.Add(delta != NULL__null); |
834 | if (delta != NULL__null) |
835 | message.AddList(delta, length); |
836 | |
837 | status_t result = _AddCallback(); |
838 | if (message.Flush() != B_OK((int)0)) |
839 | return point; |
840 | |
841 | if (result != B_OK((int)0)) |
842 | return point; |
843 | |
844 | do { |
845 | result = acquire_sem_etc(fResultNotify, 1, B_RELATIVE_TIMEOUT, |
846 | 1 * 1000 * 1000); |
847 | } while (result == B_INTERRUPTED((-2147483647 - 1) + 10)); |
848 | |
849 | if (result != B_OK((int)0)) |
850 | return point; |
851 | |
852 | return fDrawStringResult; |
853 | } |
854 | |
855 | |
856 | BPoint |
857 | RemoteDrawingEngine::DrawString(const char* string, int32 length, |
858 | const BPoint* offsets) |
859 | { |
860 | |
861 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
862 | |
863 | message.Start(RP_DRAW_STRING_WITH_OFFSETS); |
864 | message.Add(fToken); |
865 | message.AddString(string, length); |
866 | message.AddList(offsets, UTF8CountChars(string, length)); |
867 | |
868 | status_t result = _AddCallback(); |
869 | if (message.Flush() != B_OK((int)0)) |
870 | return offsets[0]; |
871 | |
872 | if (result != B_OK((int)0)) |
873 | return offsets[0]; |
874 | |
875 | do { |
876 | result = acquire_sem_etc(fResultNotify, 1, B_RELATIVE_TIMEOUT, |
877 | 1 * 1000 * 1000); |
878 | } while (result == B_INTERRUPTED((-2147483647 - 1) + 10)); |
879 | |
880 | if (result != B_OK((int)0)) |
881 | return offsets[0]; |
882 | |
883 | return fDrawStringResult; |
884 | } |
885 | |
886 | |
887 | float |
888 | RemoteDrawingEngine::StringWidth(const char* string, int32 length, |
889 | escapement_delta* delta) |
890 | { |
891 | |
892 | return fState.Font().StringWidth(string, length, delta); |
893 | } |
894 | |
895 | |
896 | |
897 | |
898 | |
899 | status_t |
900 | RemoteDrawingEngine::ReadBitmap(ServerBitmap* bitmap, bool drawCursor, |
901 | BRect bounds) |
902 | { |
903 | if (_AddCallback() != B_OK((int)0)) |
904 | return B_UNSUPPORTED(((-2147483647 - 1) + 0x6000) + 14); |
905 | |
906 | RemoteMessage message(NULL__null, fHWInterface->SendBuffer()); |
907 | |
908 | message.Start(RP_READ_BITMAP); |
909 | message.Add(fToken); |
910 | message.Add(bounds); |
911 | message.Add(drawCursor); |
912 | if (message.Flush() != B_OK((int)0)) |
913 | return B_UNSUPPORTED(((-2147483647 - 1) + 0x6000) + 14); |
914 | |
915 | status_t result; |
916 | do { |
917 | result = acquire_sem_etc(fResultNotify, 1, B_RELATIVE_TIMEOUT, |
918 | 100 * 1000 * 1000); |
919 | } while (result == B_INTERRUPTED((-2147483647 - 1) + 10)); |
920 | |
921 | if (result != B_OK((int)0)) |
922 | return result; |
923 | |
924 | BBitmap* read = fReadBitmapResult; |
925 | if (read == NULL__null) |
926 | return B_UNSUPPORTED(((-2147483647 - 1) + 0x6000) + 14); |
927 | |
928 | result = bitmap->ImportBits(read->Bits(), read->BitsLength(), |
929 | read->BytesPerRow(), read->ColorSpace()); |
930 | delete read; |
931 | return result; |
932 | } |
933 | |
934 | |
935 | |
936 | |
937 | |
938 | status_t |
939 | RemoteDrawingEngine::_AddCallback() |
940 | { |
941 | if (fCallbackAdded) |
942 | return B_OK((int)0); |
943 | |
944 | if (fResultNotify < 0) |
945 | fResultNotify = create_sem(0, "drawing engine result"); |
946 | if (fResultNotify < 0) |
947 | return fResultNotify; |
948 | |
949 | status_t result = fHWInterface->AddCallback(fToken, &_DrawingEngineResult, |
950 | this); |
951 | |
952 | fCallbackAdded = result == B_OK((int)0); |
953 | return result; |
954 | } |
955 | |
956 | |
957 | bool |
958 | RemoteDrawingEngine::_DrawingEngineResult(void* cookie, RemoteMessage& message) |
959 | { |
960 | RemoteDrawingEngine* engine = (RemoteDrawingEngine*)cookie; |
961 | |
962 | switch (message.Code()) { |
963 | case RP_DRAW_STRING_RESULT: |
964 | if (message.Read(engine->fDrawStringResult) != B_OK((int)0)) |
965 | return false; |
966 | break; |
967 | |
968 | case RP_STRING_WIDTH_RESULT: |
969 | if (message.Read(engine->fStringWidthResult) != B_OK((int)0)) |
970 | return false; |
971 | break; |
972 | |
973 | case RP_READ_BITMAP_RESULT: |
974 | if (message.ReadBitmap(&engine->fReadBitmapResult) != B_OK((int)0)) |
975 | return false; |
976 | break; |
977 | |
978 | default: |
979 | return false; |
980 | } |
981 | |
982 | release_sem(engine->fResultNotify); |
983 | return true; |
984 | } |
985 | |
986 | |
987 | BRect |
988 | RemoteDrawingEngine::_BuildBounds(BPoint* points, int32 pointCount) |
989 | { |
990 | BRect bounds(1000000, 1000000, 0, 0); |
991 | for (int32 i = 0; i < pointCount; i++) { |
992 | bounds.left = min_c(bounds.left, points[i].x)((bounds.left)>(points[i].x)?(points[i].x):(bounds.left)); |
993 | bounds.top = min_c(bounds.top, points[i].y)((bounds.top)>(points[i].y)?(points[i].y):(bounds.top)); |
994 | bounds.right = max_c(bounds.right, points[i].x)((bounds.right)>(points[i].x)?(bounds.right):(points[i].x) ); |
995 | bounds.bottom = max_c(bounds.bottom, points[i].y)((bounds.bottom)>(points[i].y)?(bounds.bottom):(points[i]. y)); |
996 | } |
997 | |
998 | return bounds; |
999 | } |
1000 | |
1001 | |
1002 | status_t |
1003 | RemoteDrawingEngine::_ExtractBitmapRegions(ServerBitmap& bitmap, uint32 options, |
1004 | const BRect& bitmapRect, const BRect& viewRect, double xScale, |
1005 | double yScale, BRegion& region, UtilityBitmap**& bitmaps) |
1006 | { |
1007 | int32 rectCount = region.CountRects(); |
1008 | bitmaps = (UtilityBitmap**)malloc(rectCount * sizeof(UtilityBitmap*)); |
1009 | if (bitmaps == NULL__null) |
| |
1010 | return B_NO_MEMORY((-2147483647 - 1) + 0); |
1011 | |
1012 | for (int32 i = 0; i < rectCount; i++) { |
| 2 | | Assuming 'i' is < 'rectCount' | |
|
| 3 | | Loop condition is true. Entering loop body | |
|
| 10 | | Assuming 'i' is < 'rectCount' | |
|
| 11 | | Loop condition is true. Entering loop body | |
|
1013 | BRect sourceRect = region.RectAt(i).OffsetByCopy(-viewRect.LeftTop()); |
1014 | int32 targetWidth = (int32)(sourceRect.Width() + 1.5); |
1015 | int32 targetHeight = (int32)(sourceRect.Height() + 1.5); |
1016 | |
1017 | if (xScale != 1.0) { |
| |
| |
1018 | sourceRect.left = (int32)(sourceRect.left * xScale + 0.5); |
1019 | sourceRect.right = (int32)(sourceRect.right * xScale + 0.5); |
1020 | if (xScale < 1.0) |
1021 | targetWidth = (int32)(sourceRect.Width() + 1.5); |
1022 | } |
1023 | |
1024 | if (yScale != 1.0) { |
| |
| |
1025 | sourceRect.top = (int32)(sourceRect.top * yScale + 0.5); |
1026 | sourceRect.bottom = (int32)(sourceRect.bottom * yScale + 0.5); |
1027 | if (yScale < 1.0) |
1028 | targetHeight = (int32)(sourceRect.Height() + 1.5); |
1029 | } |
1030 | |
1031 | sourceRect.OffsetBy(bitmapRect.LeftTop()); |
1032 | |
1033 | |
1034 | status_t result = B_OK((int)0); |
1035 | if ((xScale > 1.0 || yScale > 1.0) |
1036 | && (targetWidth * targetHeight < (int32)(sourceRect.Width() + 1.5) |
1037 | * (int32)(sourceRect.Height() + 1.5))) { |
1038 | |
1039 | |
1040 | if (fBitmapDrawingEngine == NULL__null) { |
1041 | fBitmapDrawingEngine |
1042 | = new(std::nothrow) BitmapDrawingEngine(B_RGBA32); |
1043 | if (fBitmapDrawingEngine == NULL__null) |
1044 | result = B_NO_MEMORY((-2147483647 - 1) + 0); |
1045 | } |
1046 | |
1047 | if (result == B_OK((int)0)) { |
1048 | result = fBitmapDrawingEngine->SetSize(targetWidth, |
1049 | targetHeight); |
1050 | } |
1051 | |
1052 | if (result == B_OK((int)0)) { |
1053 | fBitmapDrawingEngine->SetDrawingMode(B_OP_COPY); |
1054 | |
1055 | switch (bitmap.ColorSpace()) { |
1056 | case B_RGBA32: |
1057 | case B_RGBA32_BIG: |
1058 | case B_RGBA15: |
1059 | case B_RGBA15_BIG: |
1060 | break; |
1061 | |
1062 | default: |
1063 | { |
1064 | |
1065 | |
1066 | |
1067 | |
1068 | |
1069 | |
1070 | |
1071 | |
1072 | rgb_color background = { 0, 0, 0, 0 }; |
1073 | fBitmapDrawingEngine->FillRect( |
1074 | BRect(0, 0, targetWidth - 1, targetHeight -1), |
1075 | background); |
1076 | fBitmapDrawingEngine->SetDrawingMode(B_OP_OVER); |
1077 | break; |
1078 | } |
1079 | } |
1080 | |
1081 | fBitmapDrawingEngine->DrawBitmap(&bitmap, sourceRect, |
1082 | BRect(0, 0, targetWidth - 1, targetHeight - 1), options); |
1083 | bitmaps[i] = fBitmapDrawingEngine->ExportToBitmap(targetWidth, |
1084 | targetHeight, bitmap.ColorSpace()); |
1085 | if (bitmaps[i] == NULL__null) |
1086 | result = B_NO_MEMORY((-2147483647 - 1) + 0); |
1087 | } |
1088 | } else { |
1089 | |
1090 | |
1091 | targetWidth = (int32)(sourceRect.Width() + 1.5); |
1092 | targetHeight = (int32)(sourceRect.Height() + 1.5); |
1093 | |
1094 | bitmaps[i] = new(std::nothrow) UtilityBitmap( |
1095 | BRect(0, 0, targetWidth - 1, targetHeight - 1), |
1096 | bitmap.ColorSpace(), 0); |
1097 | if (bitmaps[i] == NULL__null) |
| |
| |
1098 | result = B_NO_MEMORY((-2147483647 - 1) + 0); |
1099 | |
1100 | result = bitmaps[i]->ImportBits(bitmap.Bits(), bitmap.BitsLength(), |
| 15 | | Called C++ object pointer is null |
|
1101 | bitmap.BytesPerRow(), bitmap.ColorSpace(), sourceRect.LeftTop(), |
1102 | BPoint(0, 0), targetWidth, targetHeight); |
1103 | if (result != B_OK((int)0)) |
| 7 | | Assuming 'result' is equal to 0 | |
|
| |
1104 | delete bitmaps[i]; |
1105 | } |
1106 | |
1107 | if (result != B_OK((int)0)) { |
| |
1108 | for (int32 j = 0; j < i; j++) |
1109 | delete bitmaps[j]; |
1110 | free(bitmaps); |
1111 | return result; |
1112 | } |
1113 | } |
1114 | |
1115 | return B_OK((int)0); |
1116 | } |