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