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
41status_t
42RemoteMessage::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
81void
82RemoteMessage::Cancel()
83{
84	fAvailable += fWriteIndex;
85	fWriteIndex = 0;
86}
87
88
89#ifndef CLIENT_COMPILE
90void
91RemoteMessage::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
114void
115RemoteMessage::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
130void
131RemoteMessage::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
147void
148RemoteMessage::AddArrayLine(const ViewLineArrayInfo& line)
149{
150	Add(line.startPoint);
151	Add(line.endPoint);
152	Add(line.color);
153}
154
155
156void
157RemoteMessage::AddCursor(const ServerCursor& cursor)
158{
159	Add(cursor.GetHotSpot());
160	AddBitmap(cursor);
161}
162
163
164void
165RemoteMessage::AddPattern(const Pattern& pattern)
166{
167	Add(pattern.GetPattern());
168}
169
170#else // !CLIENT_COMPILE
171
172void
173RemoteMessage::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
195void
196RemoteMessage::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
279void
280RemoteMessage::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
297status_t
298RemoteMessage::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
332status_t
333RemoteMessage::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
385status_t
386RemoteMessage::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
421status_t
422RemoteMessage::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
459status_t
460RemoteMessage::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
559status_t
560RemoteMessage::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
581status_t
582RemoteMessage::ReadArrayLine(BPoint& startPoint, BPoint& endPoint,
583	rgb_color& color)
584{
585	Read(startPoint);
586	Read(endPoint);
587	return Read(color);
588}
589