xref: /haiku/src/servers/app/drawing/interface/remote/RemoteMessage.h (revision 2b76973fa2401f7a5edf68e6470f3d3210cbcff3)
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 
25 class BBitmap;
26 class BFont;
27 class BGradient;
28 class BView;
29 class DrawState;
30 class Pattern;
31 class RemotePainter;
32 class ServerBitmap;
33 class ServerCursor;
34 class ServerFont;
35 class ViewLineArrayInfo;
36 
37 enum {
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 
128 class RemoteMessage {
129 public:
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 
185 private:
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 
199 inline
200 RemoteMessage::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 
213 inline
214 RemoteMessage::~RemoteMessage()
215 {
216 	if (fWriteIndex > 0)
217 		Flush();
218 	free(fBuffer);
219 }
220 
221 
222 inline void
223 RemoteMessage::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 
235 inline status_t
236 RemoteMessage::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 
250 template<typename T>
251 inline void
252 RemoteMessage::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 
263 inline void
264 RemoteMessage::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 
276 inline void
277 RemoteMessage::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 
287 template<typename T>
288 inline void
289 RemoteMessage::AddList(const T* array, int32 count)
290 {
291 	for (int32 i = 0; i < count; i++)
292 		Add(array[i]);
293 }
294 
295 
296 template<typename T>
297 inline status_t
298 RemoteMessage::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 
315 inline status_t
316 RemoteMessage::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 
336 template<typename T>
337 inline status_t
338 RemoteMessage::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 
350 inline bool
351 RemoteMessage::_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