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