2 * Copyright 2009-2010, Haiku, Inc.
3 * Distributed under the terms of the MIT License.
6 * Michael Lotz <mmlr@mlotz.ch>
9 #include "RemoteDrawingEngine.h"
10 #include "RemoteMessage.h"
12 #include "BitmapDrawingEngine.h"
13 #include "DrawState.h"
14 #include "ServerTokenSpace.h"
17 #include <utf8_functions.h>
22 #define TRACE(x...) /*debug_printf("RemoteDrawingEngine: " x)*/
23 #define TRACE_ALWAYS(x...) debug_printf("RemoteDrawingEngine: " x)
24 #define TRACE_ERROR(x...) debug_printf("RemoteDrawingEngine: " x)
27 RemoteDrawingEngine::RemoteDrawingEngine(RemoteHWInterface
* interface
)
29 DrawingEngine(interface
),
30 fHWInterface(interface
),
31 fToken(gTokenSpace
.NewToken(kRemoteDrawingEngineToken
, this)),
33 fCallbackAdded(false),
35 fStringWidthResult(0.0f
),
36 fReadBitmapResult(NULL
),
37 fBitmapDrawingEngine(NULL
)
39 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
40 message
.Start(RP_CREATE_STATE
);
45 RemoteDrawingEngine::~RemoteDrawingEngine()
47 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
48 message
.Start(RP_DELETE_STATE
);
52 delete fBitmapDrawingEngine
;
55 fHWInterface
->RemoveCallback(fToken
);
56 if (fResultNotify
>= 0)
57 delete_sem(fResultNotify
);
65 RemoteDrawingEngine::FrameBufferChanged()
75 RemoteDrawingEngine::SetCopyToFrontEnabled(bool enabled
)
77 DrawingEngine::SetCopyToFrontEnabled(enabled
);
79 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
80 message
.Start(enabled
? RP_ENABLE_SYNC_DRAWING
: RP_DISABLE_SYNC_DRAWING
);
88 //! the RemoteDrawingEngine needs to be locked!
90 RemoteDrawingEngine::ConstrainClippingRegion(const BRegion
* region
)
92 if (fClippingRegion
== *region
)
95 fClippingRegion
= *region
;
97 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
98 message
.Start(RP_CONSTRAIN_CLIPPING_REGION
);
100 message
.AddRegion(*region
);
105 RemoteDrawingEngine::SetDrawState(const DrawState
* state
, int32 xOffset
,
108 SetPenSize(state
->PenSize());
109 SetDrawingMode(state
->GetDrawingMode());
110 SetBlendingMode(state
->AlphaSrcMode(), state
->AlphaFncMode());
111 SetPattern(state
->GetPattern().GetPattern());
112 SetStrokeMode(state
->LineCapMode(), state
->LineJoinMode(),
113 state
->MiterLimit());
114 SetHighColor(state
->HighColor());
115 SetLowColor(state
->LowColor());
116 SetFont(state
->Font());
117 SetTransform(state
->CombinedTransform());
119 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
120 message
.Start(RP_SET_OFFSETS
);
122 message
.Add(xOffset
);
123 message
.Add(yOffset
);
128 RemoteDrawingEngine::SetHighColor(const rgb_color
& color
)
130 if (fState
.HighColor() == color
)
133 fState
.SetHighColor(color
);
135 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
136 message
.Start(RP_SET_HIGH_COLOR
);
143 RemoteDrawingEngine::SetLowColor(const rgb_color
& color
)
145 if (fState
.LowColor() == color
)
148 fState
.SetLowColor(color
);
150 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
151 message
.Start(RP_SET_LOW_COLOR
);
158 RemoteDrawingEngine::SetPenSize(float size
)
160 if (fState
.PenSize() == size
)
163 fState
.SetPenSize(size
);
164 fExtendWidth
= -(size
/ 2);
166 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
167 message
.Start(RP_SET_PEN_SIZE
);
174 RemoteDrawingEngine::SetStrokeMode(cap_mode lineCap
, join_mode joinMode
,
177 if (fState
.LineCapMode() == lineCap
&& fState
.LineJoinMode() == joinMode
178 && fState
.MiterLimit() == miterLimit
)
181 fState
.SetLineCapMode(lineCap
);
182 fState
.SetLineJoinMode(joinMode
);
183 fState
.SetMiterLimit(miterLimit
);
185 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
186 message
.Start(RP_SET_STROKE_MODE
);
188 message
.Add(lineCap
);
189 message
.Add(joinMode
);
190 message
.Add(miterLimit
);
195 RemoteDrawingEngine::SetBlendingMode(source_alpha sourceAlpha
,
196 alpha_function alphaFunc
)
198 if (fState
.AlphaSrcMode() == sourceAlpha
199 && fState
.AlphaFncMode() == alphaFunc
)
202 fState
.SetBlendingMode(sourceAlpha
, alphaFunc
);
204 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
205 message
.Start(RP_SET_BLENDING_MODE
);
207 message
.Add(sourceAlpha
);
208 message
.Add(alphaFunc
);
213 RemoteDrawingEngine::SetPattern(const struct pattern
& pattern
)
215 if (fState
.GetPattern() == pattern
)
218 fState
.SetPattern(pattern
);
220 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
221 message
.Start(RP_SET_PATTERN
);
223 message
.Add(pattern
);
228 RemoteDrawingEngine::SetDrawingMode(drawing_mode mode
)
230 if (fState
.GetDrawingMode() == mode
)
233 fState
.SetDrawingMode(mode
);
235 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
236 message
.Start(RP_SET_DRAWING_MODE
);
243 RemoteDrawingEngine::SetDrawingMode(drawing_mode mode
, drawing_mode
& oldMode
)
245 oldMode
= fState
.GetDrawingMode();
246 SetDrawingMode(mode
);
251 RemoteDrawingEngine::SetFont(const ServerFont
& font
)
253 if (fState
.Font() == font
)
256 fState
.SetFont(font
);
258 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
259 message
.Start(RP_SET_FONT
);
261 message
.AddFont(font
);
266 RemoteDrawingEngine::SetFont(const DrawState
* state
)
268 SetFont(state
->Font());
273 RemoteDrawingEngine::SetTransform(const BAffineTransform
& transform
)
275 if (fState
.Transform() == transform
)
278 fState
.SetTransform(transform
);
280 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
281 message
.Start(RP_SET_TRANSFORM
);
283 message
.AddTransform(transform
);
291 RemoteDrawingEngine::CopyRect(BRect rect
, int32 xOffset
, int32 yOffset
) const
293 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
294 message
.Start(RP_COPY_RECT_NO_CLIPPING
);
295 message
.Add(xOffset
);
296 message
.Add(yOffset
);
298 return rect
.OffsetBySelf(xOffset
, yOffset
);
303 RemoteDrawingEngine::InvertRect(BRect rect
)
305 if (!fClippingRegion
.Intersects(rect
))
308 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
309 message
.Start(RP_INVERT_RECT
);
316 RemoteDrawingEngine::DrawBitmap(ServerBitmap
* bitmap
, const BRect
& _bitmapRect
,
317 const BRect
& _viewRect
, uint32 options
)
319 BRect bitmapRect
= _bitmapRect
;
320 BRect viewRect
= _viewRect
;
321 double xScale
= (bitmapRect
.Width() + 1) / (viewRect
.Width() + 1);
322 double yScale
= (bitmapRect
.Height() + 1) / (viewRect
.Height() + 1);
324 // constrain rect to passed bitmap bounds
325 // and transfer the changes to the viewRect with the right scale
326 BRect actualBitmapRect
= bitmap
->Bounds();
327 if (bitmapRect
.left
< actualBitmapRect
.left
) {
328 float diff
= actualBitmapRect
.left
- bitmapRect
.left
;
329 viewRect
.left
+= diff
/ xScale
;
330 bitmapRect
.left
= actualBitmapRect
.left
;
332 if (bitmapRect
.top
< actualBitmapRect
.top
) {
333 float diff
= actualBitmapRect
.top
- bitmapRect
.top
;
334 viewRect
.top
+= diff
/ yScale
;
335 bitmapRect
.top
= actualBitmapRect
.top
;
337 if (bitmapRect
.right
> actualBitmapRect
.right
) {
338 float diff
= bitmapRect
.right
- actualBitmapRect
.right
;
339 viewRect
.right
-= diff
/ xScale
;
340 bitmapRect
.right
= actualBitmapRect
.right
;
342 if (bitmapRect
.bottom
> actualBitmapRect
.bottom
) {
343 float diff
= bitmapRect
.bottom
- actualBitmapRect
.bottom
;
344 viewRect
.bottom
-= diff
/ yScale
;
345 bitmapRect
.bottom
= actualBitmapRect
.bottom
;
348 BRegion
clippedRegion(viewRect
);
349 clippedRegion
.IntersectWith(&fClippingRegion
);
351 int32 rectCount
= clippedRegion
.CountRects();
355 if (rectCount
> 1 || (rectCount
== 1 && clippedRegion
.RectAt(0) != viewRect
)
356 || viewRect
.Width() < bitmapRect
.Width()
357 || viewRect
.Height() < bitmapRect
.Height()) {
358 UtilityBitmap
** bitmaps
;
359 if (_ExtractBitmapRegions(*bitmap
, options
, bitmapRect
, viewRect
,
360 xScale
, yScale
, clippedRegion
, bitmaps
) != B_OK
) {
364 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
365 message
.Start(RP_DRAW_BITMAP_RECTS
);
367 message
.Add(options
);
368 message
.Add(bitmap
->ColorSpace());
369 message
.Add(bitmap
->Flags());
370 message
.Add(rectCount
);
372 for (int32 i
= 0; i
< rectCount
; i
++) {
373 message
.Add(clippedRegion
.RectAt(i
));
374 message
.AddBitmap(*bitmaps
[i
], true);
382 // TODO: we may want to cache/checksum bitmaps
383 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
384 message
.Start(RP_DRAW_BITMAP
);
386 message
.Add(bitmapRect
);
387 message
.Add(viewRect
);
388 message
.Add(options
);
389 message
.AddBitmap(*bitmap
);
394 RemoteDrawingEngine::DrawArc(BRect rect
, const float& angle
, const float& span
,
399 bounds
.InsetBy(fExtendWidth
, fExtendWidth
);
401 if (!fClippingRegion
.Intersects(bounds
))
404 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
405 message
.Start(filled
? RP_FILL_ARC
: RP_STROKE_ARC
);
413 RemoteDrawingEngine::FillArc(BRect rect
, const float& angle
, const float& span
,
414 const BGradient
& gradient
)
416 if (!fClippingRegion
.Intersects(rect
))
419 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
420 message
.Start(RP_FILL_ARC_GRADIENT
);
425 message
.AddGradient(gradient
);
430 RemoteDrawingEngine::DrawBezier(BPoint
* points
, bool filled
)
432 BRect bounds
= _BuildBounds(points
, 4);
434 bounds
.InsetBy(fExtendWidth
, fExtendWidth
);
436 if (!fClippingRegion
.Intersects(bounds
))
439 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
440 message
.Start(filled
? RP_FILL_BEZIER
: RP_STROKE_BEZIER
);
442 message
.AddList(points
, 4);
447 RemoteDrawingEngine::FillBezier(BPoint
* points
, const BGradient
& gradient
)
449 BRect bounds
= _BuildBounds(points
, 4);
450 if (!fClippingRegion
.Intersects(bounds
))
453 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
454 message
.Start(RP_FILL_BEZIER_GRADIENT
);
456 message
.AddList(points
, 4);
457 message
.AddGradient(gradient
);
462 RemoteDrawingEngine::DrawEllipse(BRect rect
, bool filled
)
466 bounds
.InsetBy(fExtendWidth
, fExtendWidth
);
468 if (!fClippingRegion
.Intersects(bounds
))
471 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
472 message
.Start(filled
? RP_FILL_ELLIPSE
: RP_STROKE_ELLIPSE
);
479 RemoteDrawingEngine::FillEllipse(BRect rect
, const BGradient
& gradient
)
481 if (!fClippingRegion
.Intersects(rect
))
484 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
485 message
.Start(RP_FILL_ELLIPSE_GRADIENT
);
488 message
.AddGradient(gradient
);
493 RemoteDrawingEngine::DrawPolygon(BPoint
* pointList
, int32 numPoints
,
494 BRect bounds
, bool filled
, bool closed
)
496 BRect clipBounds
= bounds
;
498 clipBounds
.InsetBy(fExtendWidth
, fExtendWidth
);
500 if (!fClippingRegion
.Intersects(clipBounds
))
503 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
504 message
.Start(filled
? RP_FILL_POLYGON
: RP_STROKE_POLYGON
);
508 message
.Add(numPoints
);
509 for (int32 i
= 0; i
< numPoints
; i
++)
510 message
.Add(pointList
[i
]);
515 RemoteDrawingEngine::FillPolygon(BPoint
* pointList
, int32 numPoints
,
516 BRect bounds
, const BGradient
& gradient
, bool closed
)
518 if (!fClippingRegion
.Intersects(bounds
))
521 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
522 message
.Start(RP_FILL_POLYGON_GRADIENT
);
526 message
.Add(numPoints
);
527 for (int32 i
= 0; i
< numPoints
; i
++)
528 message
.Add(pointList
[i
]);
529 message
.AddGradient(gradient
);
533 // #pragma mark - rgb_color versions
537 RemoteDrawingEngine::StrokePoint(const BPoint
& point
, const rgb_color
& color
)
539 BRect
bounds(point
, point
);
540 bounds
.InsetBy(fExtendWidth
, fExtendWidth
);
542 if (!fClippingRegion
.Intersects(bounds
))
545 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
546 message
.Start(RP_STROKE_POINT_COLOR
);
554 RemoteDrawingEngine::StrokeLine(const BPoint
& start
, const BPoint
& end
,
555 const rgb_color
& color
)
557 BPoint points
[2] = { start
, end
};
558 BRect bounds
= _BuildBounds(points
, 2);
560 if (!fClippingRegion
.Intersects(bounds
))
563 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
564 message
.Start(RP_STROKE_LINE_1PX_COLOR
);
566 message
.AddList(points
, 2);
572 RemoteDrawingEngine::StrokeRect(BRect rect
, const rgb_color
&color
)
575 bounds
.InsetBy(fExtendWidth
, fExtendWidth
);
577 if (!fClippingRegion
.Intersects(bounds
))
580 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
581 message
.Start(RP_STROKE_RECT_1PX_COLOR
);
589 RemoteDrawingEngine::FillRect(BRect rect
, const rgb_color
& color
)
591 if (!fClippingRegion
.Intersects(rect
))
594 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
595 message
.Start(RP_FILL_RECT_COLOR
);
603 RemoteDrawingEngine::FillRegion(BRegion
& region
, const rgb_color
& color
)
605 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
606 message
.Start(RP_FILL_REGION_COLOR_NO_CLIPPING
);
607 message
.AddRegion(region
);
612 // #pragma mark - DrawState versions
616 RemoteDrawingEngine::StrokeRect(BRect rect
)
619 bounds
.InsetBy(fExtendWidth
, fExtendWidth
);
621 if (!fClippingRegion
.Intersects(bounds
))
624 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
625 message
.Start(RP_STROKE_RECT
);
632 RemoteDrawingEngine::FillRect(BRect rect
)
634 if (!fClippingRegion
.Intersects(rect
))
637 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
638 message
.Start(RP_FILL_RECT
);
645 RemoteDrawingEngine::FillRect(BRect rect
, const BGradient
& gradient
)
647 if (!fClippingRegion
.Intersects(rect
))
650 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
651 message
.Start(RP_FILL_RECT_GRADIENT
);
654 message
.AddGradient(gradient
);
659 RemoteDrawingEngine::FillRegion(BRegion
& region
)
661 BRegion clippedRegion
= region
;
662 clippedRegion
.IntersectWith(&fClippingRegion
);
663 if (clippedRegion
.CountRects() == 0)
666 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
667 message
.Start(RP_FILL_REGION
);
669 message
.AddRegion(clippedRegion
.CountRects() < region
.CountRects()
670 ? clippedRegion
: region
);
675 RemoteDrawingEngine::FillRegion(BRegion
& region
, const BGradient
& gradient
)
677 BRegion clippedRegion
= region
;
678 clippedRegion
.IntersectWith(&fClippingRegion
);
679 if (clippedRegion
.CountRects() == 0)
682 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
683 message
.Start(RP_FILL_REGION_GRADIENT
);
685 message
.AddRegion(clippedRegion
.CountRects() < region
.CountRects()
686 ? clippedRegion
: region
);
687 message
.AddGradient(gradient
);
692 RemoteDrawingEngine::DrawRoundRect(BRect rect
, float xRadius
, float yRadius
,
697 bounds
.InsetBy(fExtendWidth
, fExtendWidth
);
699 if (!fClippingRegion
.Intersects(bounds
))
702 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
703 message
.Start(filled
? RP_FILL_ROUND_RECT
: RP_STROKE_ROUND_RECT
);
706 message
.Add(xRadius
);
707 message
.Add(yRadius
);
712 RemoteDrawingEngine::FillRoundRect(BRect rect
, float xRadius
, float yRadius
,
713 const BGradient
& gradient
)
715 if (!fClippingRegion
.Intersects(rect
))
718 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
719 message
.Start(RP_FILL_ROUND_RECT_GRADIENT
);
722 message
.Add(xRadius
);
723 message
.Add(yRadius
);
724 message
.AddGradient(gradient
);
729 RemoteDrawingEngine::DrawShape(const BRect
& bounds
, int32 opCount
,
730 const uint32
* opList
, int32 pointCount
, const BPoint
* pointList
,
731 bool filled
, const BPoint
& viewToScreenOffset
, float viewScale
)
733 BRect clipBounds
= bounds
;
735 clipBounds
.InsetBy(fExtendWidth
, fExtendWidth
);
737 if (!fClippingRegion
.Intersects(clipBounds
))
740 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
741 message
.Start(filled
? RP_FILL_SHAPE
: RP_STROKE_SHAPE
);
744 message
.Add(opCount
);
745 message
.AddList(opList
, opCount
);
746 message
.Add(pointCount
);
747 message
.AddList(pointList
, pointCount
);
748 message
.Add(viewToScreenOffset
);
749 message
.Add(viewScale
);
754 RemoteDrawingEngine::FillShape(const BRect
& bounds
, int32 opCount
,
755 const uint32
* opList
, int32 pointCount
, const BPoint
* pointList
,
756 const BGradient
& gradient
, const BPoint
& viewToScreenOffset
,
759 if (!fClippingRegion
.Intersects(bounds
))
762 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
763 message
.Start(RP_FILL_SHAPE_GRADIENT
);
766 message
.Add(opCount
);
767 message
.AddList(opList
, opCount
);
768 message
.Add(pointCount
);
769 message
.AddList(pointList
, pointCount
);
770 message
.Add(viewToScreenOffset
);
771 message
.Add(viewScale
);
772 message
.AddGradient(gradient
);
777 RemoteDrawingEngine::DrawTriangle(BPoint
* points
, const BRect
& bounds
,
780 BRect clipBounds
= bounds
;
782 clipBounds
.InsetBy(fExtendWidth
, fExtendWidth
);
784 if (!fClippingRegion
.Intersects(clipBounds
))
787 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
788 message
.Start(filled
? RP_FILL_TRIANGLE
: RP_STROKE_TRIANGLE
);
790 message
.AddList(points
, 3);
796 RemoteDrawingEngine::FillTriangle(BPoint
* points
, const BRect
& bounds
,
797 const BGradient
& gradient
)
799 if (!fClippingRegion
.Intersects(bounds
))
802 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
803 message
.Start(RP_FILL_TRIANGLE_GRADIENT
);
805 message
.AddList(points
, 3);
807 message
.AddGradient(gradient
);
812 RemoteDrawingEngine::StrokeLine(const BPoint
&start
, const BPoint
&end
)
814 BPoint points
[2] = { start
, end
};
815 BRect bounds
= _BuildBounds(points
, 2);
817 if (!fClippingRegion
.Intersects(bounds
))
820 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
821 message
.Start(RP_STROKE_LINE
);
823 message
.AddList(points
, 2);
828 RemoteDrawingEngine::StrokeLineArray(int32 numLines
,
829 const ViewLineArrayInfo
*lineData
)
831 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
832 message
.Start(RP_STROKE_LINE_ARRAY
);
834 message
.Add(numLines
);
835 for (int32 i
= 0; i
< numLines
; i
++)
836 message
.AddArrayLine(lineData
[i
]);
840 // #pragma mark - string functions
844 RemoteDrawingEngine::DrawString(const char* string
, int32 length
,
845 const BPoint
& point
, escapement_delta
* delta
)
847 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
849 message
.Start(RP_DRAW_STRING
);
852 message
.AddString(string
, length
);
853 message
.Add(delta
!= NULL
);
855 message
.AddList(delta
, length
);
857 status_t result
= _AddCallback();
858 if (message
.Flush() != B_OK
)
865 result
= acquire_sem_etc(fResultNotify
, 1, B_RELATIVE_TIMEOUT
,
867 } while (result
== B_INTERRUPTED
);
872 return fDrawStringResult
;
877 RemoteDrawingEngine::DrawString(const char* string
, int32 length
,
878 const BPoint
* offsets
)
880 // Guaranteed to have at least one point.
881 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
883 message
.Start(RP_DRAW_STRING_WITH_OFFSETS
);
885 message
.AddString(string
, length
);
886 message
.AddList(offsets
, UTF8CountChars(string
, length
));
888 status_t result
= _AddCallback();
889 if (message
.Flush() != B_OK
)
896 result
= acquire_sem_etc(fResultNotify
, 1, B_RELATIVE_TIMEOUT
,
898 } while (result
== B_INTERRUPTED
);
903 return fDrawStringResult
;
908 RemoteDrawingEngine::StringWidth(const char* string
, int32 length
,
909 escapement_delta
* delta
)
911 // TODO: Decide if really needed.
914 if (_AddCallback() != B_OK
)
917 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
919 message
.Start(RP_STRING_WIDTH
);
921 message
.AddString(string
, length
);
922 // TODO: Support escapement delta.
924 if (message
.Flush() != B_OK
)
929 result
= acquire_sem_etc(fResultNotify
, 1, B_RELATIVE_TIMEOUT
,
931 } while (result
== B_INTERRUPTED
);
936 return fStringWidthResult
;
939 // Fall back to local calculation.
940 return fState
.Font().StringWidth(string
, length
, delta
);
948 RemoteDrawingEngine::ReadBitmap(ServerBitmap
* bitmap
, bool drawCursor
,
951 if (_AddCallback() != B_OK
)
952 return B_UNSUPPORTED
;
954 RemoteMessage
message(NULL
, fHWInterface
->SendBuffer());
956 message
.Start(RP_READ_BITMAP
);
959 message
.Add(drawCursor
);
960 if (message
.Flush() != B_OK
)
961 return B_UNSUPPORTED
;
965 result
= acquire_sem_etc(fResultNotify
, 1, B_RELATIVE_TIMEOUT
,
967 } while (result
== B_INTERRUPTED
);
972 BBitmap
* read
= fReadBitmapResult
;
974 return B_UNSUPPORTED
;
976 result
= bitmap
->ImportBits(read
->Bits(), read
->BitsLength(),
977 read
->BytesPerRow(), read
->ColorSpace());
987 RemoteDrawingEngine::_AddCallback()
992 if (fResultNotify
< 0)
993 fResultNotify
= create_sem(0, "drawing engine result");
994 if (fResultNotify
< 0)
995 return fResultNotify
;
997 status_t result
= fHWInterface
->AddCallback(fToken
, &_DrawingEngineResult
,
1000 fCallbackAdded
= result
== B_OK
;
1006 RemoteDrawingEngine::_DrawingEngineResult(void* cookie
, RemoteMessage
& message
)
1008 RemoteDrawingEngine
* engine
= (RemoteDrawingEngine
*)cookie
;
1010 switch (message
.Code()) {
1011 case RP_DRAW_STRING_RESULT
:
1013 status_t result
= message
.Read(engine
->fDrawStringResult
);
1014 if (result
!= B_OK
) {
1015 TRACE_ERROR("failed to read draw string result: %s\n",
1023 case RP_STRING_WIDTH_RESULT
:
1025 status_t result
= message
.Read(engine
->fStringWidthResult
);
1026 if (result
!= B_OK
) {
1027 TRACE_ERROR("failed to read string width result: %s\n",
1035 case RP_READ_BITMAP_RESULT
:
1037 status_t result
= message
.ReadBitmap(&engine
->fReadBitmapResult
);
1038 if (result
!= B_OK
) {
1039 TRACE_ERROR("failed to read bitmap of read bitmap result: %s\n",
1051 release_sem(engine
->fResultNotify
);
1057 RemoteDrawingEngine::_BuildBounds(BPoint
* points
, int32 pointCount
)
1059 BRect
bounds(1000000, 1000000, 0, 0);
1060 for (int32 i
= 0; i
< pointCount
; i
++) {
1061 bounds
.left
= min_c(bounds
.left
, points
[i
].x
);
1062 bounds
.top
= min_c(bounds
.top
, points
[i
].y
);
1063 bounds
.right
= max_c(bounds
.right
, points
[i
].x
);
1064 bounds
.bottom
= max_c(bounds
.bottom
, points
[i
].y
);
1072 RemoteDrawingEngine::_ExtractBitmapRegions(ServerBitmap
& bitmap
, uint32 options
,
1073 const BRect
& bitmapRect
, const BRect
& viewRect
, double xScale
,
1074 double yScale
, BRegion
& region
, UtilityBitmap
**& bitmaps
)
1076 int32 rectCount
= region
.CountRects();
1077 bitmaps
= (UtilityBitmap
**)malloc(rectCount
* sizeof(UtilityBitmap
*));
1078 if (bitmaps
== NULL
)
1081 for (int32 i
= 0; i
< rectCount
; i
++) {
1082 BRect sourceRect
= region
.RectAt(i
).OffsetByCopy(-viewRect
.LeftTop());
1083 int32 targetWidth
= (int32
)(sourceRect
.Width() + 1.5);
1084 int32 targetHeight
= (int32
)(sourceRect
.Height() + 1.5);
1086 if (xScale
!= 1.0) {
1087 sourceRect
.left
= (int32
)(sourceRect
.left
* xScale
+ 0.5);
1088 sourceRect
.right
= (int32
)(sourceRect
.right
* xScale
+ 0.5);
1090 targetWidth
= (int32
)(sourceRect
.Width() + 1.5);
1093 if (yScale
!= 1.0) {
1094 sourceRect
.top
= (int32
)(sourceRect
.top
* yScale
+ 0.5);
1095 sourceRect
.bottom
= (int32
)(sourceRect
.bottom
* yScale
+ 0.5);
1097 targetHeight
= (int32
)(sourceRect
.Height() + 1.5);
1100 sourceRect
.OffsetBy(bitmapRect
.LeftTop());
1101 // sourceRect is now the part of the bitmap we want copied
1103 status_t result
= B_OK
;
1104 if ((xScale
> 1.0 || yScale
> 1.0)
1105 && (targetWidth
* targetHeight
< (int32
)(sourceRect
.Width() + 1.5)
1106 * (int32
)(sourceRect
.Height() + 1.5))) {
1107 // the target bitmap is smaller than the source, scale it locally
1108 // and send over the smaller version to avoid sending any extra data
1109 if (fBitmapDrawingEngine
== NULL
) {
1110 fBitmapDrawingEngine
1111 = new(std::nothrow
) BitmapDrawingEngine(B_RGBA32
);
1112 if (fBitmapDrawingEngine
== NULL
)
1113 result
= B_NO_MEMORY
;
1116 if (result
== B_OK
) {
1117 result
= fBitmapDrawingEngine
->SetSize(targetWidth
,
1121 if (result
== B_OK
) {
1122 fBitmapDrawingEngine
->SetDrawingMode(B_OP_COPY
);
1124 switch (bitmap
.ColorSpace()) {
1133 // we need to clear the background if there may be
1134 // transparency through transparent magic (we use
1135 // B_OP_COPY when we draw alpha enabled bitmaps, so we
1136 // don't need to clear there)
1137 // TODO: this is not actually correct, as we're going to
1138 // loose the transparency with the conversion to the
1139 // original non-alpha colorspace happening in
1141 rgb_color background
= { 0, 0, 0, 0 };
1142 fBitmapDrawingEngine
->FillRect(
1143 BRect(0, 0, targetWidth
- 1, targetHeight
-1),
1145 fBitmapDrawingEngine
->SetDrawingMode(B_OP_OVER
);
1150 fBitmapDrawingEngine
->DrawBitmap(&bitmap
, sourceRect
,
1151 BRect(0, 0, targetWidth
- 1, targetHeight
- 1), options
);
1152 bitmaps
[i
] = fBitmapDrawingEngine
->ExportToBitmap(targetWidth
,
1153 targetHeight
, bitmap
.ColorSpace());
1154 if (bitmaps
[i
] == NULL
)
1155 result
= B_NO_MEMORY
;
1158 // source is smaller or equal target, extract the relevant rects
1159 // directly without any scaling and conversion
1160 targetWidth
= (int32
)(sourceRect
.Width() + 1.5);
1161 targetHeight
= (int32
)(sourceRect
.Height() + 1.5);
1163 bitmaps
[i
] = new(std::nothrow
) UtilityBitmap(
1164 BRect(0, 0, targetWidth
- 1, targetHeight
- 1),
1165 bitmap
.ColorSpace(), 0);
1166 if (bitmaps
[i
] == NULL
) {
1167 result
= B_NO_MEMORY
;
1169 result
= bitmaps
[i
]->ImportBits(bitmap
.Bits(),
1170 bitmap
.BitsLength(), bitmap
.BytesPerRow(),
1171 bitmap
.ColorSpace(), sourceRect
.LeftTop(),
1172 BPoint(0, 0), targetWidth
, targetHeight
);
1173 if (result
!= B_OK
) {
1180 if (result
!= B_OK
) {
1181 for (int32 j
= 0; j
< i
; j
++)