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