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