1/*
2 * Copyright 2009, Haiku, Inc.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Michael Lotz <mmlr@mlotz.ch>
7 */
8#ifndef REMOTE_MESSAGE_H
9#define REMOTE_MESSAGE_H
10
11#ifndef CLIENT_COMPILE
12#	include "PatternHandler.h"
13#	include <ViewPrivate.h>
14#endif
15
16#include "StreamingRingBuffer.h"
17
18#include <GraphicsDefs.h>
19#include <Region.h>
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25class BBitmap;
26class BFont;
27class BGradient;
28class BView;
29class DrawState;
30class Pattern;
31class RemotePainter;
32class ServerBitmap;
33class ServerCursor;
34class ServerFont;
35class ViewLineArrayInfo;
36
37enum {
38	RP_INIT_CONNECTION = 1,
39	RP_UPDATE_DISPLAY_MODE,
40	RP_CLOSE_CONNECTION,
41
42	RP_CREATE_STATE = 20,
43	RP_DELETE_STATE,
44	RP_ENABLE_SYNC_DRAWING,
45	RP_DISABLE_SYNC_DRAWING,
46	RP_INVALIDATE_RECT,
47	RP_INVALIDATE_REGION,
48
49	RP_SET_OFFSETS = 40,
50	RP_SET_HIGH_COLOR,
51	RP_SET_LOW_COLOR,
52	RP_SET_PEN_SIZE,
53	RP_SET_STROKE_MODE,
54	RP_SET_BLENDING_MODE,
55	RP_SET_PATTERN,
56	RP_SET_DRAWING_MODE,
57	RP_SET_FONT,
58
59	RP_CONSTRAIN_CLIPPING_REGION = 60,
60	RP_COPY_RECT_NO_CLIPPING,
61	RP_INVERT_RECT,
62	RP_DRAW_BITMAP,
63	RP_DRAW_BITMAP_RECTS,
64
65	RP_STROKE_ARC = 80,
66	RP_STROKE_BEZIER,
67	RP_STROKE_ELLIPSE,
68	RP_STROKE_POLYGON,
69	RP_STROKE_RECT,
70	RP_STROKE_ROUND_RECT,
71	RP_STROKE_SHAPE,
72	RP_STROKE_TRIANGLE,
73	RP_STROKE_LINE,
74	RP_STROKE_LINE_ARRAY,
75
76	RP_FILL_ARC = 100,
77	RP_FILL_BEZIER,
78	RP_FILL_ELLIPSE,
79	RP_FILL_POLYGON,
80	RP_FILL_RECT,
81	RP_FILL_ROUND_RECT,
82	RP_FILL_SHAPE,
83	RP_FILL_TRIANGLE,
84	RP_FILL_REGION,
85
86	RP_FILL_ARC_GRADIENT = 120,
87	RP_FILL_BEZIER_GRADIENT,
88	RP_FILL_ELLIPSE_GRADIENT,
89	RP_FILL_POLYGON_GRADIENT,
90	RP_FILL_RECT_GRADIENT,
91	RP_FILL_ROUND_RECT_GRADIENT,
92	RP_FILL_SHAPE_GRADIENT,
93	RP_FILL_TRIANGLE_GRADIENT,
94	RP_FILL_REGION_GRADIENT,
95
96	RP_STROKE_POINT_COLOR = 140,
97	RP_STROKE_LINE_1PX_COLOR,
98	RP_STROKE_RECT_1PX_COLOR,
99
100	RP_FILL_RECT_COLOR = 160,
101	RP_FILL_REGION_COLOR_NO_CLIPPING,
102
103	RP_DRAW_STRING = 180,
104	RP_DRAW_STRING_WITH_OFFSETS,
105	RP_DRAW_STRING_RESULT,
106	RP_STRING_WIDTH,
107	RP_STRING_WIDTH_RESULT,
108	RP_READ_BITMAP,
109	RP_READ_BITMAP_RESULT,
110
111	RP_SET_CURSOR = 200,
112	RP_SET_CURSOR_VISIBLE,
113	RP_MOVE_CURSOR_TO,
114
115	RP_MOUSE_MOVED = 220,
116	RP_MOUSE_DOWN,
117	RP_MOUSE_UP,
118	RP_MOUSE_WHEEL_CHANGED,
119
120	RP_KEY_DOWN = 240,
121	RP_KEY_UP,
122	RP_UNMAPPED_KEY_DOWN,
123	RP_UNMAPPED_KEY_UP,
124	RP_MODIFIERS_CHANGED
125};
126
127
128class RemoteMessage {
129public:
130								RemoteMessage(StreamingRingBuffer* source,
131									StreamingRingBuffer *target);
132								~RemoteMessage();
133
134		void					Start(uint16 code);
135		status_t				Flush();
136		void					Cancel();
137
138		status_t				NextMessage(uint16& code);
139		uint16					Code() { return fCode; }
140		uint32					DataLeft() { return fDataLeft; }
141
142		template<typename T>
143		void					Add(const T& value);
144
145		void					AddString(const char* string, size_t length);
146		void					AddRegion(const BRegion& region);
147		void					AddGradient(const BGradient& gradient);
148
149#ifndef CLIENT_COMPILE
150		void					AddBitmap(const ServerBitmap& bitmap,
151									bool minimal = false);
152		void					AddFont(const ServerFont& font);
153		void					AddPattern(const Pattern& pattern);
154		void					AddDrawState(const DrawState& drawState);
155		void					AddArrayLine(const ViewLineArrayInfo& line);
156		void					AddCursor(const ServerCursor& cursor);
157#else
158		void					AddBitmap(const BBitmap& bitmap);
159#endif
160
161		template<typename T>
162		void					AddList(const T* array, int32 count);
163
164		template<typename T>
165		status_t				Read(T& value);
166
167		status_t				ReadRegion(BRegion& region);
168		status_t				ReadFontState(BFont& font);
169									// sets font state
170		status_t				ReadViewState(BView& view, ::pattern& pattern);
171									// sets viewstate and returns pattern
172
173		status_t				ReadString(char** _string, size_t& length);
174		status_t				ReadBitmap(BBitmap** _bitmap,
175									bool minimal = false,
176									color_space colorSpace = B_RGB32,
177									uint32 flags = 0);
178		status_t				ReadGradient(BGradient** _gradient);
179		status_t				ReadArrayLine(BPoint& startPoint,
180									BPoint& endPoint, rgb_color& color);
181
182		template<typename T>
183		status_t				ReadList(T* array, int32 count);
184
185private:
186		bool					_MakeSpace(size_t size);
187
188		StreamingRingBuffer*	fSource;
189		StreamingRingBuffer*	fTarget;
190
191		uint8*					fBuffer;
192		size_t					fAvailable;
193		size_t					fWriteIndex;
194		uint32					fDataLeft;
195		uint16					fCode;
196};
197
198
199inline
200RemoteMessage::RemoteMessage(StreamingRingBuffer* source,
201	StreamingRingBuffer* target)
202	:
203	fSource(source),
204	fTarget(target),
205	fBuffer(NULL),
206	fAvailable(0),
207	fWriteIndex(0),
208	fDataLeft(0)
209{
210}
211
212
213inline
214RemoteMessage::~RemoteMessage()
215{
216	if (fWriteIndex > 0)
217		Flush();
218	free(fBuffer);
219}
220
221
222inline void
223RemoteMessage::Start(uint16 code)
224{
225	if (fWriteIndex > 0)
226		Flush();
227
228	Add(code);
229
230	uint32 sizeDummy = 0;
231	Add(sizeDummy);
232}
233
234
235inline status_t
236RemoteMessage::Flush()
237{
238	if (fWriteIndex == 0)
239		return B_NO_INIT;
240
241	uint32 length = fWriteIndex;
242	fAvailable += fWriteIndex;
243	fWriteIndex = 0;
244
245	memcpy(fBuffer + sizeof(uint16), &length, sizeof(uint32));
246	return fTarget->Write(fBuffer, length);
247}
248
249
250template<typename T>
251inline void
252RemoteMessage::Add(const T& value)
253{
254	if (!_MakeSpace(sizeof(T)))
255		return;
256
257	memcpy(fBuffer + fWriteIndex, &value, sizeof(T));
258	fWriteIndex += sizeof(T);
259	fAvailable -= sizeof(T);
260}
261
262
263inline void
264RemoteMessage::AddString(const char* string, size_t length)
265{
266	Add(length);
267	if (length > fAvailable && !_MakeSpace(length))
268		return;
269
270	memcpy(fBuffer + fWriteIndex, string, length);
271	fWriteIndex += length;
272	fAvailable -= length;
273}
274
275
276inline void
277RemoteMessage::AddRegion(const BRegion& region)
278{
279	int32 rectCount = region.CountRects();
280	Add(rectCount);
281
282	for (int32 i = 0; i < rectCount; i++)
283		Add(region.RectAt(i));
284}
285
286
287template<typename T>
288inline void
289RemoteMessage::AddList(const T* array, int32 count)
290{
291	for (int32 i = 0; i < count; i++)
292		Add(array[i]);
293}
294
295
296template<typename T>
297inline status_t
298RemoteMessage::Read(T& value)
299{
300	if (fDataLeft < sizeof(T))
301		return B_ERROR;
302
303	int32 readSize = fSource->Read(&value, sizeof(T));
304	if (readSize < 0)
305		return readSize;
306
307	if (readSize != sizeof(T))
308		return B_ERROR;
309
310	fDataLeft -= sizeof(T);
311	return B_OK;
312}
313
314
315inline status_t
316RemoteMessage::ReadRegion(BRegion& region)
317{
318	region.MakeEmpty();
319
320	int32 rectCount;
321	Read(rectCount);
322
323	for (int32 i = 0; i < rectCount; i++) {
324		BRect rect;
325		status_t result = Read(rect);
326		if (result != B_OK)
327			return result;
328
329		region.Include(rect);
330	}
331
332	return B_OK;
333}
334
335
336template<typename T>
337inline status_t
338RemoteMessage::ReadList(T* array, int32 count)
339{
340	for (int32 i = 0; i < count; i++) {
341		status_t result = Read(array[i]);
342		if (result != B_OK)
343			return result;
344	}
345
346	return B_OK;
347}
348
349
350inline bool
351RemoteMessage::_MakeSpace(size_t size)
352{
353	if (fAvailable >= size)
354		return true;
355
356	size_t extraSize = size + 20;
357	uint8 *newBuffer = (uint8*)realloc(fBuffer, fWriteIndex + extraSize);
358	if (newBuffer == NULL)
359		return false;
360
361	fAvailable = extraSize;
362	fBuffer = newBuffer;
363	return true;
364}
365
366#endif // REMOTE_MESSAGE_H
367