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