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
NextMessage(uint16 & code)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
Cancel()82 RemoteMessage::Cancel()
83 {
84 fAvailable += fWriteIndex;
85 fWriteIndex = 0;
86 }
87
88
89 #ifndef CLIENT_COMPILE
90 void
AddBitmap(const ServerBitmap & bitmap,bool minimal)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
AddFont(const ServerFont & font)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
AddDrawState(const DrawState & drawState)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
AddArrayLine(const ViewLineArrayInfo & line)148 RemoteMessage::AddArrayLine(const ViewLineArrayInfo& line)
149 {
150 Add(line.startPoint);
151 Add(line.endPoint);
152 Add(line.color);
153 }
154
155
156 void
AddCursor(const ServerCursor & cursor)157 RemoteMessage::AddCursor(const ServerCursor& cursor)
158 {
159 Add(cursor.GetHotSpot());
160 AddBitmap(cursor);
161 }
162
163
164 void
AddPattern(const Pattern & pattern)165 RemoteMessage::AddPattern(const Pattern& pattern)
166 {
167 Add(pattern.GetPattern());
168 }
169
170 #else // !CLIENT_COMPILE
171
172 void
AddBitmap(const BBitmap & bitmap)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
AddGradient(const BGradient & gradient)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
AddTransform(const BAffineTransform & transform)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
ReadString(char ** _string,size_t & _length)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
ReadBitmap(BBitmap ** _bitmap,bool minimal,color_space colorSpace,uint32 flags)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
ReadFontState(BFont & font)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
ReadViewState(BView & view,::pattern & pattern)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
ReadGradient(BGradient ** _gradient)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
ReadTransform(BAffineTransform & transform)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
ReadArrayLine(BPoint & startPoint,BPoint & endPoint,rgb_color & color)582 RemoteMessage::ReadArrayLine(BPoint& startPoint, BPoint& endPoint,
583 rgb_color& color)
584 {
585 Read(startPoint);
586 Read(endPoint);
587 return Read(color);
588 }
589