Bug Summary

File:/boot/home/haiku/haiku/src/servers/app/drawing/interface/remote/RemoteDrawingEngine.cpp
Location:line 1100, column 13
Description:Called C++ object pointer is null

Annotated Source Code

1/*
2 * Copyright 2009-2010, Haiku, Inc.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Michael Lotz <mmlr@mlotz.ch>
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
21RemoteDrawingEngine::RemoteDrawingEngine(RemoteHWInterface* interface)
22 :
23 DrawingEngine(interface),
24 fHWInterface(interface),
25 fToken((uint32)this), // TODO: need to redo that for 64 bit
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
39RemoteDrawingEngine::~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// #pragma mark -
56
57
58void
59RemoteDrawingEngine::FrameBufferChanged()
60{
61 // Not allowed
62}
63
64
65// #pragma mark -
66
67
68void
69RemoteDrawingEngine::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// #pragma mark -
80
81
82//! the RemoteDrawingEngine needs to be locked!
83void
84RemoteDrawingEngine::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
98void
99RemoteDrawingEngine::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
120void
121RemoteDrawingEngine::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
135void
136RemoteDrawingEngine::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
150void
151RemoteDrawingEngine::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
166void
167RemoteDrawingEngine::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
187void
188RemoteDrawingEngine::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
205void
206RemoteDrawingEngine::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
220void
221RemoteDrawingEngine::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
235void
236RemoteDrawingEngine::SetDrawingMode(drawing_mode mode, drawing_mode& oldMode)
237{
238 oldMode = fState.GetDrawingMode();
239 SetDrawingMode(mode);
240}
241
242
243void
244RemoteDrawingEngine::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
258void
259RemoteDrawingEngine::SetFont(const DrawState* state)
260{
261 SetFont(state->Font());
262}
263
264
265// #pragma mark -
266
267
268BRect
269RemoteDrawingEngine::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
280void
281RemoteDrawingEngine::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
293void
294RemoteDrawingEngine::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 // constrain rect to passed bitmap bounds
303 // and transfer the changes to the viewRect with the right scale
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 // TODO: we may want to cache/checksum bitmaps
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
371void
372RemoteDrawingEngine::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
390void
391RemoteDrawingEngine::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
407void
408RemoteDrawingEngine::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
424void
425RemoteDrawingEngine::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
439void
440RemoteDrawingEngine::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
456void
457RemoteDrawingEngine::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
470void
471RemoteDrawingEngine::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
492void
493RemoteDrawingEngine::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// #pragma mark - rgb_color versions
512
513
514void
515RemoteDrawingEngine::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
531void
532RemoteDrawingEngine::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
549void
550RemoteDrawingEngine::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
566void
567RemoteDrawingEngine::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
580void
581RemoteDrawingEngine::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// #pragma mark - DrawState versions
591
592
593void
594RemoteDrawingEngine::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
609void
610RemoteDrawingEngine::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
622void
623RemoteDrawingEngine::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
636void
637RemoteDrawingEngine::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
652void
653RemoteDrawingEngine::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
669void
670RemoteDrawingEngine::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
689void
690RemoteDrawingEngine::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
706void
707RemoteDrawingEngine::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
731void
732RemoteDrawingEngine::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
754void
755RemoteDrawingEngine::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
773void
774RemoteDrawingEngine::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
791void
792RemoteDrawingEngine::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
807void
808RemoteDrawingEngine::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// #pragma mark - string functions
821
822
823BPoint
824RemoteDrawingEngine::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
856BPoint
857RemoteDrawingEngine::DrawString(const char* string, int32 length,
858 const BPoint* offsets)
859{
860 // Guaranteed to have at least one point.
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
887float
888RemoteDrawingEngine::StringWidth(const char* string, int32 length,
889 escapement_delta* delta)
890{
891 // TODO: decide if really needed and use callback if so
892 return fState.Font().StringWidth(string, length, delta);
893}
894
895
896// #pragma mark -
897
898
899status_t
900RemoteDrawingEngine::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// #pragma mark -
936
937
938status_t
939RemoteDrawingEngine::_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
957bool
958RemoteDrawingEngine::_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
987BRect
988RemoteDrawingEngine::_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
1002status_t
1003RemoteDrawingEngine::_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)
1
Taking false branch
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) {
4
Taking false branch
12
Taking false branch
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) {
5
Taking false branch
13
Taking false branch
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 // sourceRect is now the part of the bitmap we want copied
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 // the target bitmap is smaller than the source, scale it locally
1039 // and send over the smaller version to avoid sending any extra data
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 // we need to clear the background if there may be
1065 // transparency through transparent magic (we use
1066 // B_OP_COPY when we draw alpha enabled bitmaps, so we
1067 // don't need to clear there)
1068 // TODO: this is not actually correct, as we're going to
1069 // loose the transparency with the conversion to the
1070 // original non-alpha colorspace happening in
1071 // ExportToBitmap
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 // source is smaller or equal target, extract the relevant rects
1090 // directly without any scaling and conversion
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)
6
Taking false branch
14
Taking true branch
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
8
Taking false branch
1104 delete bitmaps[i];
1105 }
1106
1107 if (result != B_OK((int)0)) {
9
Taking false branch
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}