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