xref: /haiku/src/servers/app/drawing/interface/remote/RemoteMessage.cpp (revision 83b1a68c52ba3e0e8796282759f694b7fdddf06d)
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 
9 #include "RemoteMessage.h"
10 
11 #ifndef CLIENT_COMPILE
12 #include "DrawState.h"
13 #include "ServerBitmap.h"
14 #include "ServerCursor.h"
15 #endif
16 
17 #include <Bitmap.h>
18 #include <Font.h>
19 #include <View.h>
20 
21 #include <Gradient.h>
22 #include <GradientLinear.h>
23 #include <GradientRadial.h>
24 #include <GradientRadialFocus.h>
25 #include <GradientDiamond.h>
26 #include <GradientConic.h>
27 
28 #include <new>
29 
30 
31 status_t
32 RemoteMessage::NextMessage(uint16& code)
33 {
34 	if (fDataLeft > 0) {
35 		// discard remainder of message
36 		int32 readSize = fSource->Read(NULL, fDataLeft);
37 		if (readSize < 0)
38 			return readSize;
39 	}
40 
41 	static const uint32 kHeaderSize = sizeof(uint16) + sizeof(uint32);
42 
43 	fDataLeft = kHeaderSize;
44 	Read(code);
45 	uint32 dataLeft;
46 	status_t result = Read(dataLeft);
47 	if (result != B_OK)
48 		return result;
49 
50 	if (dataLeft < kHeaderSize)
51 		return B_ERROR;
52 
53 	fDataLeft = dataLeft - kHeaderSize;
54 	fCode = code;
55 	return B_OK;
56 }
57 
58 
59 void
60 RemoteMessage::Cancel()
61 {
62 	fAvailable += fWriteIndex;
63 	fWriteIndex = 0;
64 }
65 
66 
67 #ifndef CLIENT_COMPILE
68 void
69 RemoteMessage::AddBitmap(const ServerBitmap& bitmap, bool minimal)
70 {
71 	Add(bitmap.Width());
72 	Add(bitmap.Height());
73 	Add(bitmap.BytesPerRow());
74 
75 	if (!minimal) {
76 		Add(bitmap.ColorSpace());
77 		Add(bitmap.Flags());
78 	}
79 
80 	uint32 bitsLength = bitmap.BitsLength();
81 	Add(bitsLength);
82 
83 	if (!_MakeSpace(bitsLength))
84 		return;
85 
86 	memcpy(fBuffer + fWriteIndex, bitmap.Bits(), bitsLength);
87 	fWriteIndex += bitsLength;
88 	fAvailable -= bitsLength;
89 }
90 
91 
92 void
93 RemoteMessage::AddFont(const ServerFont& font)
94 {
95 	Add(font.Direction());
96 	Add((uint8)font.Encoding());
97 	Add(font.Flags());
98 	Add((uint8)font.Spacing());
99 	Add(font.Shear());
100 	Add(font.Rotation());
101 	Add(font.FalseBoldWidth());
102 	Add(font.Size());
103 	Add(font.Face());
104 	Add(font.GetFamilyAndStyle());
105 }
106 
107 
108 void
109 RemoteMessage::AddDrawState(const DrawState& drawState)
110 {
111 	Add(drawState.PenSize());
112 	Add(drawState.SubPixelPrecise());
113 	Add(drawState.GetDrawingMode());
114 	Add(drawState.AlphaSrcMode());
115 	Add(drawState.AlphaFncMode());
116 	AddPattern(drawState.GetPattern());
117 	Add(drawState.LineCapMode());
118 	Add(drawState.LineJoinMode());
119 	Add(drawState.MiterLimit());
120 	Add(drawState.HighColor());
121 	Add(drawState.LowColor());
122 }
123 
124 
125 void
126 RemoteMessage::AddArrayLine(const ViewLineArrayInfo& line)
127 {
128 	Add(line.startPoint);
129 	Add(line.endPoint);
130 	Add(line.color);
131 }
132 
133 
134 void
135 RemoteMessage::AddCursor(const ServerCursor& cursor)
136 {
137 	Add(cursor.GetHotSpot());
138 	AddBitmap(cursor);
139 }
140 
141 
142 void
143 RemoteMessage::AddPattern(const Pattern& pattern)
144 {
145 	Add(pattern.GetPattern());
146 }
147 
148 #else // !CLIENT_COMPILE
149 
150 void
151 RemoteMessage::AddBitmap(const BBitmap& bitmap)
152 {
153 	BRect bounds = bitmap.Bounds();
154 	Add(bounds.IntegerWidth() + 1);
155 	Add(bounds.IntegerHeight() + 1);
156 	Add(bitmap.BytesPerRow());
157 	Add(bitmap.ColorSpace());
158 	Add(bitmap.Flags());
159 
160 	uint32 bitsLength = bitmap.BitsLength();
161 	Add(bitsLength);
162 
163 	if (!_MakeSpace(bitsLength))
164 		return;
165 
166 	memcpy(fBuffer + fWriteIndex, bitmap.Bits(), bitsLength);
167 	fWriteIndex += bitsLength;
168 	fAvailable -= bitsLength;
169 }
170 #endif // !CLIENT_COMPILE
171 
172 
173 void
174 RemoteMessage::AddGradient(const BGradient& gradient)
175 {
176 	Add(gradient.GetType());
177 
178 	switch (gradient.GetType()) {
179 		case BGradient::TYPE_NONE:
180 			break;
181 
182 		case BGradient::TYPE_LINEAR:
183 		{
184 			const BGradientLinear* linear
185 				= dynamic_cast<const BGradientLinear *>(&gradient);
186 			if (linear == NULL)
187 				return;
188 
189 			Add(linear->Start());
190 			Add(linear->End());
191 			break;
192 		}
193 
194 		case BGradient::TYPE_RADIAL:
195 		{
196 			const BGradientRadial* radial
197 				= dynamic_cast<const BGradientRadial *>(&gradient);
198 			if (radial == NULL)
199 				return;
200 
201 			Add(radial->Center());
202 			Add(radial->Radius());
203 			break;
204 		}
205 
206 		case BGradient::TYPE_RADIAL_FOCUS:
207 		{
208 			const BGradientRadialFocus* radialFocus
209 				= dynamic_cast<const BGradientRadialFocus *>(&gradient);
210 			if (radialFocus == NULL)
211 				return;
212 
213 			Add(radialFocus->Center());
214 			Add(radialFocus->Focal());
215 			Add(radialFocus->Radius());
216 			break;
217 		}
218 
219 		case BGradient::TYPE_DIAMOND:
220 		{
221 			const BGradientDiamond* diamond
222 				= dynamic_cast<const BGradientDiamond *>(&gradient);
223 			if (diamond == NULL)
224 				return;
225 
226 			Add(diamond->Center());
227 			break;
228 		}
229 
230 		case BGradient::TYPE_CONIC:
231 		{
232 			const BGradientConic* conic
233 				= dynamic_cast<const BGradientConic *>(&gradient);
234 			if (conic == NULL)
235 				return;
236 
237 			Add(conic->Center());
238 			Add(conic->Angle());
239 			break;
240 		}
241 	}
242 
243 	int32 stopCount = gradient.CountColorStops();
244 	Add(stopCount);
245 
246 	for (int32 i = 0; i < stopCount; i++) {
247 		BGradient::ColorStop* stop = gradient.ColorStopAt(i);
248 		if (stop == NULL)
249 			return;
250 
251 		Add(stop->color);
252 		Add(stop->offset);
253 	}
254 }
255 
256 
257 status_t
258 RemoteMessage::ReadString(char** _string, size_t& _length)
259 {
260 	uint32 length;
261 	status_t result = Read(length);
262 	if (result != B_OK)
263 		return result;
264 
265 	if (length > fDataLeft)
266 		return B_ERROR;
267 
268 	char *string = (char *)malloc(length + 1);
269 	if (string == NULL)
270 		return B_NO_MEMORY;
271 
272 	int32 readSize = fSource->Read(string, length);
273 	if (readSize < 0) {
274 		free(string);
275 		return readSize;
276 	}
277 
278 	if ((uint32)readSize != length) {
279 		free(string);
280 		return B_ERROR;
281 	}
282 
283 	fDataLeft -= readSize;
284 
285 	string[length] = 0;
286 	*_string = string;
287 	_length = length;
288 	return B_OK;
289 }
290 
291 
292 status_t
293 RemoteMessage::ReadBitmap(BBitmap** _bitmap, bool minimal,
294 	color_space colorSpace, uint32 flags)
295 {
296 	uint32 bitsLength;
297 	int32 width, height, bytesPerRow;
298 
299 	Read(width);
300 	Read(height);
301 	Read(bytesPerRow);
302 
303 	if (!minimal) {
304 		Read(colorSpace);
305 		Read(flags);
306 	}
307 
308 	Read(bitsLength);
309 
310 	if (bitsLength > fDataLeft)
311 		return B_ERROR;
312 
313 #ifndef CLIENT_COMPILE
314 	flags = B_BITMAP_NO_SERVER_LINK;
315 #endif
316 
317 	BBitmap *bitmap = new(std::nothrow) BBitmap(
318 		BRect(0, 0, width - 1, height - 1), flags, colorSpace, bytesPerRow);
319 	if (bitmap == NULL)
320 		return B_NO_MEMORY;
321 
322 	status_t result = bitmap->InitCheck();
323 	if (result != B_OK) {
324 		delete bitmap;
325 		return result;
326 	}
327 
328 	if (bitmap->BitsLength() < (int32)bitsLength) {
329 		delete bitmap;
330 		return B_ERROR;
331 	}
332 
333 	int32 readSize = fSource->Read(bitmap->Bits(), bitsLength);
334 	if ((uint32)readSize != bitsLength) {
335 		delete bitmap;
336 		return readSize < 0 ? readSize : B_ERROR;
337 	}
338 
339 	fDataLeft -= readSize;
340 	*_bitmap = bitmap;
341 	return B_OK;
342 }
343 
344 
345 status_t
346 RemoteMessage::ReadFontState(BFont& font)
347 {
348 	uint8 encoding, spacing;
349 	uint16 face;
350 	uint32 flags, familyAndStyle;
351 	font_direction direction;
352 	float falseBoldWidth, rotation, shear, size;
353 
354 	Read(direction);
355 	Read(encoding);
356 	Read(flags);
357 	Read(spacing);
358 	Read(shear);
359 	Read(rotation);
360 	Read(falseBoldWidth);
361 	Read(size);
362 	Read(face);
363 	status_t result = Read(familyAndStyle);
364 	if (result != B_OK)
365 		return result;
366 
367 	font.SetFamilyAndStyle(familyAndStyle);
368 	font.SetEncoding(encoding);
369 	font.SetFlags(flags);
370 	font.SetSpacing(spacing);
371 	font.SetShear(shear);
372 	font.SetRotation(rotation);
373 	font.SetFalseBoldWidth(falseBoldWidth);
374 	font.SetSize(size);
375 	font.SetFace(face);
376 	return B_OK;
377 }
378 
379 
380 status_t
381 RemoteMessage::ReadViewState(BView& view, ::pattern& pattern)
382 {
383 	bool subPixelPrecise;
384 	float penSize, miterLimit;
385 	drawing_mode drawingMode;
386 	source_alpha sourceAlpha;
387 	alpha_function alphaFunction;
388 	cap_mode capMode;
389 	join_mode joinMode;
390 	rgb_color highColor, lowColor;
391 
392 	Read(penSize);
393 	Read(subPixelPrecise);
394 	Read(drawingMode);
395 	Read(sourceAlpha);
396 	Read(alphaFunction);
397 	Read(pattern);
398 	Read(capMode);
399 	Read(joinMode);
400 	Read(miterLimit);
401 	Read(highColor);
402 	status_t result = Read(lowColor);
403 	if (result != B_OK)
404 		return result;
405 
406 	uint32 flags = view.Flags() & ~B_SUBPIXEL_PRECISE;
407 	view.SetFlags(flags | (subPixelPrecise ? B_SUBPIXEL_PRECISE : 0));
408 	view.SetPenSize(penSize);
409 	view.SetDrawingMode(drawingMode);
410 	view.SetBlendingMode(sourceAlpha, alphaFunction);
411 	view.SetLineMode(capMode, joinMode, miterLimit);
412 	view.SetHighColor(highColor);
413 	view.SetLowColor(lowColor);
414 	return B_OK;
415 }
416 
417 
418 status_t
419 RemoteMessage::ReadGradient(BGradient** _gradient)
420 {
421 	BGradient::Type type;
422 	Read(type);
423 
424 	BGradient *gradient = NULL;
425 	switch (type) {
426 		case BGradient::TYPE_NONE:
427 			break;
428 
429 		case BGradient::TYPE_LINEAR:
430 		{
431 			BPoint start, end;
432 
433 			Read(start);
434 			Read(end);
435 
436 			gradient = new(std::nothrow) BGradientLinear(start, end);
437 			break;
438 		}
439 
440 		case BGradient::TYPE_RADIAL:
441 		{
442 			BPoint center;
443 			float radius;
444 
445 			Read(center);
446 			Read(radius);
447 
448 			gradient = new(std::nothrow) BGradientRadial(center, radius);
449 			break;
450 		}
451 
452 		case BGradient::TYPE_RADIAL_FOCUS:
453 		{
454 			BPoint center, focal;
455 			float radius;
456 
457 			Read(center);
458 			Read(focal);
459 			Read(radius);
460 
461 			gradient = new(std::nothrow) BGradientRadialFocus(center, radius,
462 				focal);
463 			break;
464 		}
465 
466 		case BGradient::TYPE_DIAMOND:
467 		{
468 			BPoint center;
469 
470 			Read(center);
471 
472 			gradient = new(std::nothrow) BGradientDiamond(center);
473 			break;
474 		}
475 
476 		case BGradient::TYPE_CONIC:
477 		{
478 			BPoint center;
479 			float angle;
480 
481 			Read(center);
482 			Read(angle);
483 
484 			gradient = new(std::nothrow) BGradientConic(center, angle);
485 			break;
486 		}
487 	}
488 
489 	if (gradient == NULL)
490 		return B_NO_MEMORY;
491 
492 	int32 stopCount;
493 	status_t result = Read(stopCount);
494 	if (result != B_OK) {
495 		delete gradient;
496 		return result;
497 	}
498 
499 	for (int32 i = 0; i < stopCount; i++) {
500 		rgb_color color;
501 		float offset;
502 
503 		Read(color);
504 		result = Read(offset);
505 		if (result != B_OK)
506 			return result;
507 
508 		gradient->AddColor(color, offset);
509 	}
510 
511 	*_gradient = gradient;
512 	return B_OK;
513 }
514 
515 
516 status_t
517 RemoteMessage::ReadArrayLine(BPoint& startPoint, BPoint& endPoint,
518 	rgb_color& color)
519 {
520 	Read(startPoint);
521 	Read(endPoint);
522 	return Read(color);
523 }
524