xref: /haiku/src/servers/app/drawing/interface/remote/RemoteMessage.cpp (revision bb83316a5811a550c4f850d07fa8e328e7ac0a94)
1 /*
2  * Copyright 2009-2019, 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 direction;
389 	uint8 encoding;
390 	uint8 spacing;
391 	uint16 face;
392 	uint32 flags, familyAndStyle;
393 	float falseBoldWidth, rotation, shear, size;
394 
395 	Read(direction);
396 	Read(encoding);
397 	Read(flags);
398 	Read(spacing);
399 	Read(shear);
400 	Read(rotation);
401 	Read(falseBoldWidth);
402 	Read(size);
403 	Read(face);
404 	status_t result = Read(familyAndStyle);
405 	if (result != B_OK)
406 		return result;
407 
408 	font.SetFamilyAndStyle(familyAndStyle);
409 	font.SetEncoding(encoding);
410 	font.SetFlags(flags);
411 	font.SetSpacing(spacing);
412 	font.SetShear(shear);
413 	font.SetRotation(rotation);
414 	font.SetFalseBoldWidth(falseBoldWidth);
415 	font.SetSize(size);
416 	font.SetFace(face);
417 	return B_OK;
418 }
419 
420 
421 status_t
422 RemoteMessage::ReadViewState(BView& view, ::pattern& pattern)
423 {
424 	bool subPixelPrecise;
425 	float penSize, miterLimit;
426 	drawing_mode drawingMode;
427 	source_alpha sourceAlpha;
428 	alpha_function alphaFunction;
429 	cap_mode capMode;
430 	join_mode joinMode;
431 	rgb_color highColor, lowColor;
432 
433 	Read(penSize);
434 	Read(subPixelPrecise);
435 	Read(drawingMode);
436 	Read(sourceAlpha);
437 	Read(alphaFunction);
438 	Read(pattern);
439 	Read(capMode);
440 	Read(joinMode);
441 	Read(miterLimit);
442 	Read(highColor);
443 	status_t result = Read(lowColor);
444 	if (result != B_OK)
445 		return result;
446 
447 	uint32 flags = view.Flags() & ~B_SUBPIXEL_PRECISE;
448 	view.SetFlags(flags | (subPixelPrecise ? B_SUBPIXEL_PRECISE : 0));
449 	view.SetPenSize(penSize);
450 	view.SetDrawingMode(drawingMode);
451 	view.SetBlendingMode(sourceAlpha, alphaFunction);
452 	view.SetLineMode(capMode, joinMode, miterLimit);
453 	view.SetHighColor(highColor);
454 	view.SetLowColor(lowColor);
455 	return B_OK;
456 }
457 
458 
459 status_t
460 RemoteMessage::ReadGradient(BGradient** _gradient)
461 {
462 	BGradient::Type type;
463 	Read(type);
464 
465 	BGradient *gradient = NULL;
466 	switch (type) {
467 		case BGradient::TYPE_NONE:
468 			break;
469 
470 		case BGradient::TYPE_LINEAR:
471 		{
472 			BPoint start, end;
473 
474 			Read(start);
475 			Read(end);
476 
477 			gradient = new(std::nothrow) BGradientLinear(start, end);
478 			break;
479 		}
480 
481 		case BGradient::TYPE_RADIAL:
482 		{
483 			BPoint center;
484 			float radius;
485 
486 			Read(center);
487 			Read(radius);
488 
489 			gradient = new(std::nothrow) BGradientRadial(center, radius);
490 			break;
491 		}
492 
493 		case BGradient::TYPE_RADIAL_FOCUS:
494 		{
495 			BPoint center, focal;
496 			float radius;
497 
498 			Read(center);
499 			Read(focal);
500 			Read(radius);
501 
502 			gradient = new(std::nothrow) BGradientRadialFocus(center, radius,
503 				focal);
504 			break;
505 		}
506 
507 		case BGradient::TYPE_DIAMOND:
508 		{
509 			BPoint center;
510 
511 			Read(center);
512 
513 			gradient = new(std::nothrow) BGradientDiamond(center);
514 			break;
515 		}
516 
517 		case BGradient::TYPE_CONIC:
518 		{
519 			BPoint center;
520 			float angle;
521 
522 			Read(center);
523 			Read(angle);
524 
525 			gradient = new(std::nothrow) BGradientConic(center, angle);
526 			break;
527 		}
528 	}
529 
530 	if (gradient == NULL)
531 		return B_NO_MEMORY;
532 
533 	int32 stopCount;
534 	status_t result = Read(stopCount);
535 	if (result != B_OK) {
536 		delete gradient;
537 		return result;
538 	}
539 
540 	for (int32 i = 0; i < stopCount; i++) {
541 		rgb_color color;
542 		float offset;
543 
544 		Read(color);
545 		result = Read(offset);
546 		if (result != B_OK) {
547 			delete gradient;
548 			return result;
549 		}
550 
551 		gradient->AddColor(color, offset);
552 	}
553 
554 	*_gradient = gradient;
555 	return B_OK;
556 }
557 
558 
559 status_t
560 RemoteMessage::ReadTransform(BAffineTransform& transform)
561 {
562 	bool isIdentity;
563 	status_t result = Read(isIdentity);
564 	if (result != B_OK)
565 		return result;
566 
567 	if (isIdentity) {
568 		transform = BAffineTransform();
569 		return B_OK;
570 	}
571 
572 	Read(transform.sx);
573 	Read(transform.shy);
574 	Read(transform.shx);
575 	Read(transform.sy);
576 	Read(transform.tx);
577 	return Read(transform.ty);
578 }
579 
580 
581 status_t
582 RemoteMessage::ReadArrayLine(BPoint& startPoint, BPoint& endPoint,
583 	rgb_color& color)
584 {
585 	Read(startPoint);
586 	Read(endPoint);
587 	return Read(color);
588 }
589