1 /* 2 * Copyright 2001-2006, Haiku Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ingo Weinhold (bonefish@users.sf.net) 7 * DarkWyrm <bpmagic@columbus.rr.com> 8 * Stephan Aßmus <superstippi@gmx.de> 9 * Axel Dörfler, axeld@pinc-software.de 10 */ 11 12 /*! 13 BBitmap objects represent off-screen windows that 14 contain bitmap data. 15 */ 16 17 #include "ColorConversion.h" 18 #include "BitmapPrivate.h" 19 20 #include <Application.h> 21 #include <Bitmap.h> 22 #include <GraphicsDefs.h> 23 #include <Locker.h> 24 #include <View.h> 25 #include <Window.h> 26 27 #include <ApplicationPrivate.h> 28 #include <AppServerLink.h> 29 #include <ServerMemoryAllocator.h> 30 #include <ServerProtocol.h> 31 32 #include <algorithm> 33 #include <limits.h> 34 #include <new> 35 #include <stdio.h> 36 #include <stdlib.h> 37 38 39 // get_raw_bytes_per_row 40 /*! \brief Returns the number of bytes per row needed to store the actual 41 bitmap data (not including any padding) given a color space and a 42 row width. 43 \param colorSpace The color space. 44 \param width The width. 45 \return The number of bytes per row needed to store data for a row, or 46 0, if the color space is not supported. 47 */ 48 static inline 49 int32 50 get_raw_bytes_per_row(color_space colorSpace, int32 width) 51 { 52 int32 bpr = 0; 53 switch (colorSpace) { 54 // supported 55 case B_RGB32: case B_RGBA32: 56 case B_RGB32_BIG: case B_RGBA32_BIG: 57 case B_UVL32: case B_UVLA32: 58 case B_LAB32: case B_LABA32: 59 case B_HSI32: case B_HSIA32: 60 case B_HSV32: case B_HSVA32: 61 case B_HLS32: case B_HLSA32: 62 case B_CMY32: case B_CMYA32: case B_CMYK32: 63 bpr = 4 * width; 64 break; 65 case B_RGB24: case B_RGB24_BIG: 66 case B_UVL24: case B_LAB24: case B_HSI24: 67 case B_HSV24: case B_HLS24: case B_CMY24: 68 bpr = 3 * width; 69 break; 70 case B_RGB16: case B_RGB15: case B_RGBA15: 71 case B_RGB16_BIG: case B_RGB15_BIG: case B_RGBA15_BIG: 72 bpr = 2 * width; 73 break; 74 case B_CMAP8: case B_GRAY8: 75 bpr = width; 76 break; 77 case B_GRAY1: 78 bpr = (width + 7) / 8; 79 break; 80 case B_YCbCr422: case B_YUV422: 81 bpr = (width + 3) / 4 * 8; 82 break; 83 case B_YCbCr411: case B_YUV411: 84 bpr = (width + 3) / 4 * 6; 85 break; 86 case B_YCbCr444: case B_YUV444: 87 bpr = (width + 3) / 4 * 12; 88 break; 89 case B_YCbCr420: case B_YUV420: 90 bpr = (width + 3) / 4 * 6; 91 break; 92 // unsupported 93 case B_NO_COLOR_SPACE: 94 case B_YUV9: case B_YUV12: 95 break; 96 } 97 return bpr; 98 } 99 100 // get_bytes_per_row 101 /*! \brief Returns the number of bytes per row needed to store the bitmap 102 data (including any padding) given a color space and a row width. 103 \param colorSpace The color space. 104 \param width The width. 105 \return The number of bytes per row needed to store data for a row, or 106 0, if the color space is not supported. 107 */ 108 static inline 109 int32 110 get_bytes_per_row(color_space colorSpace, int32 width) 111 { 112 int32 bpr = get_raw_bytes_per_row(colorSpace, width); 113 // align to int32 114 bpr = (bpr + 3) & 0x7ffffffc; 115 return bpr; 116 } 117 118 119 // #pragma mark - 120 121 122 /*! \brief Creates and initializes a BBitmap. 123 \param bounds The bitmap dimensions. 124 \param flags Creation flags. 125 \param colorSpace The bitmap's color space. 126 \param bytesPerRow The number of bytes per row the bitmap should use. 127 \c B_ANY_BYTES_PER_ROW to let the constructor choose an appropriate 128 value. 129 \param screenID ??? 130 */ 131 BBitmap::BBitmap(BRect bounds, uint32 flags, color_space colorSpace, 132 int32 bytesPerRow, screen_id screenID) 133 : fBasePointer(NULL), 134 fSize(0), 135 fColorSpace(B_NO_COLOR_SPACE), 136 fBounds(0, 0, -1, -1), 137 fBytesPerRow(0), 138 fWindow(NULL), 139 fServerToken(-1), 140 fAreaOffset(-1), 141 fArea(-1), 142 fServerArea(-1), 143 fFlags(0), 144 fInitError(B_NO_INIT) 145 { 146 _InitObject(bounds, colorSpace, flags, bytesPerRow, screenID); 147 } 148 149 // constructor 150 /*! \brief Creates and initializes a BBitmap. 151 \param bounds The bitmap dimensions. 152 \param colorSpace The bitmap's color space. 153 \param acceptsViews \c true, if the bitmap shall accept BViews, i.e. if 154 it shall be possible to attach BView to the bitmap and draw into 155 it. 156 \param needsContiguous If \c true a physically contiguous chunk of memory 157 will be allocated. 158 */ 159 BBitmap::BBitmap(BRect bounds, color_space colorSpace, bool acceptsViews, 160 bool needsContiguous) 161 : fBasePointer(NULL), 162 fSize(0), 163 fColorSpace(B_NO_COLOR_SPACE), 164 fBounds(0, 0, -1, -1), 165 fBytesPerRow(0), 166 fWindow(NULL), 167 fServerToken(-1), 168 fAreaOffset(-1), 169 fArea(-1), 170 fServerArea(-1), 171 fFlags(0), 172 fInitError(B_NO_INIT) 173 { 174 int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 0) 175 | (needsContiguous ? B_BITMAP_IS_CONTIGUOUS : 0); 176 _InitObject(bounds, colorSpace, flags, B_ANY_BYTES_PER_ROW, 177 B_MAIN_SCREEN_ID); 178 179 } 180 181 // constructor 182 /*! \brief Creates a BBitmap as a clone of another bitmap. 183 \param source The source bitmap. 184 \param acceptsViews \c true, if the bitmap shall accept BViews, i.e. if 185 it shall be possible to attach BView to the bitmap and draw into 186 it. 187 \param needsContiguous If \c true a physically contiguous chunk of memory 188 will be allocated. 189 */ 190 BBitmap::BBitmap(const BBitmap *source, bool acceptsViews, 191 bool needsContiguous) 192 : fBasePointer(NULL), 193 fSize(0), 194 fColorSpace(B_NO_COLOR_SPACE), 195 fBounds(0, 0, -1, -1), 196 fBytesPerRow(0), 197 fWindow(NULL), 198 fServerToken(-1), 199 fAreaOffset(-1), 200 fArea(-1), 201 fServerArea(-1), 202 fFlags(0), 203 fInitError(B_NO_INIT) 204 { 205 if (source && source->IsValid()) { 206 int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 0) 207 | (needsContiguous ? B_BITMAP_IS_CONTIGUOUS : 0); 208 _InitObject(source->Bounds(), source->ColorSpace(), flags, 209 source->BytesPerRow(), B_MAIN_SCREEN_ID); 210 if (InitCheck() == B_OK) 211 memcpy(Bits(), source->Bits(), min_c(BitsLength(), source->BitsLength())); 212 } 213 } 214 215 // destructor 216 /*! \brief Frees all resources associated with this object. 217 */ 218 BBitmap::~BBitmap() 219 { 220 delete fWindow; 221 _CleanUp(); 222 } 223 224 // unarchiving constructor 225 /*! \brief Unarchives a bitmap from a BMessage. 226 \param data The archive. 227 */ 228 BBitmap::BBitmap(BMessage *data) 229 : BArchivable(data), 230 fBasePointer(NULL), 231 fSize(0), 232 fColorSpace(B_NO_COLOR_SPACE), 233 fBounds(0, 0, -1, -1), 234 fBytesPerRow(0), 235 fWindow(NULL), 236 fServerToken(-1), 237 fAreaOffset(-1), 238 fArea(-1), 239 fServerArea(-1), 240 fFlags(0), 241 fInitError(B_NO_INIT) 242 { 243 int32 flags; 244 if (data->FindInt32("_bmflags", &flags) != B_OK) { 245 // this bitmap is archived in some archaic format 246 flags = 0; 247 248 bool acceptsViews; 249 if (data->FindBool("_view_ok", &acceptsViews) == B_OK && acceptsViews) 250 flags |= B_BITMAP_ACCEPTS_VIEWS; 251 252 bool contiguous; 253 if (data->FindBool("_contiguous", &contiguous) == B_OK && contiguous) 254 flags |= B_BITMAP_IS_CONTIGUOUS; 255 } 256 257 int32 rowBytes; 258 if (data->FindInt32("_rowbytes", &rowBytes) != B_OK) { 259 rowBytes = -1; 260 // bytes per row are computed in InitObject(), then 261 } 262 263 BRect bounds; 264 color_space cspace; 265 if (data->FindRect("_frame", &bounds) == B_OK 266 && data->FindInt32("_cspace", (int32*)&cspace) == B_OK) { 267 _InitObject(bounds, cspace, flags, rowBytes, B_MAIN_SCREEN_ID); 268 } 269 270 if (InitCheck() == B_OK) { 271 ssize_t size; 272 const void *buffer; 273 if (data->FindData("_data", B_RAW_TYPE, &buffer, &size) == B_OK) { 274 if (size == BitsLength()) { 275 _AssertPointer(); 276 memcpy(fBasePointer, buffer, size); 277 } 278 } 279 } 280 281 if (fFlags & B_BITMAP_ACCEPTS_VIEWS) { 282 BMessage message; 283 int32 i = 0; 284 285 while (data->FindMessage("_views", i++, &message) == B_OK) { 286 if (BView *view = dynamic_cast<BView *>(instantiate_object(&message))) 287 AddChild(view); 288 } 289 } 290 } 291 292 // Instantiate 293 /*! \brief Instantiates a BBitmap from an archive. 294 \param data The archive. 295 \return A bitmap reconstructed from the archive or \c NULL, if an error 296 occured. 297 */ 298 BArchivable * 299 BBitmap::Instantiate(BMessage *data) 300 { 301 if (validate_instantiation(data, "BBitmap")) 302 return new BBitmap(data); 303 304 return NULL; 305 } 306 307 // Archive 308 /*! \brief Archives the BBitmap object. 309 \param data The archive. 310 \param deep \c true, if child object shall be archived as well, \c false 311 otherwise. 312 \return \c B_OK, if everything went fine, an error code otherwise. 313 */ 314 status_t 315 BBitmap::Archive(BMessage *data, bool deep) const 316 { 317 status_t ret = BArchivable::Archive(data, deep); 318 319 if (ret == B_OK) 320 ret = data->AddRect("_frame", fBounds); 321 322 if (ret == B_OK) 323 ret = data->AddInt32("_cspace", (int32)fColorSpace); 324 325 if (ret == B_OK) 326 ret = data->AddInt32("_bmflags", fFlags); 327 328 if (ret == B_OK) 329 ret = data->AddInt32("_rowbytes", fBytesPerRow); 330 331 if (ret == B_OK && deep) { 332 if (fFlags & B_BITMAP_ACCEPTS_VIEWS) { 333 BMessage views; 334 for (int32 i = 0; i < CountChildren(); i++) { 335 if (ChildAt(i)->Archive(&views, deep)) 336 ret = data->AddMessage("_views", &views); 337 views.MakeEmpty(); 338 if (ret < B_OK) 339 break; 340 } 341 } 342 // Note: R5 does not archive the data if B_BITMAP_IS_CONTIGNUOUS is 343 // true and it does save all formats as B_RAW_TYPE and it does save 344 // the data even if B_BITMAP_ACCEPTS_VIEWS is set (as opposed to 345 // the BeBook) 346 if (ret == B_OK) { 347 const_cast<BBitmap *>(this)->_AssertPointer(); 348 ret = data->AddData("_data", B_RAW_TYPE, fBasePointer, fSize); 349 } 350 } 351 352 if (ret == B_OK) 353 ret = data->AddString("class", "BBitmap"); 354 355 return ret; 356 } 357 358 // InitCheck 359 /*! \brief Returns the result from the construction. 360 \return \c B_OK, if the object is properly initialized, an error code 361 otherwise. 362 */ 363 status_t 364 BBitmap::InitCheck() const 365 { 366 return fInitError; 367 } 368 369 // IsValid 370 /*! \brief Returns whether or not the BBitmap object is valid. 371 \return \c true, if the object is properly initialized, \c false otherwise. 372 */ 373 bool 374 BBitmap::IsValid() const 375 { 376 return (InitCheck() == B_OK); 377 } 378 379 380 /*! 381 \brief Locks the bitmap bits so that they cannot be relocated. 382 383 This is currently only used for overlay bitmaps - whenever you 384 need to access their Bits(), you have to lock them first. 385 On resolution change overlay bitmaps can be relocated in memory; 386 using this call prevents you from accessing an invalid pointer 387 and clobbering memory that doesn't belong you. 388 */ 389 status_t 390 BBitmap::LockBits(uint32 *state) 391 { 392 if (fFlags & B_BITMAP_WILL_OVERLAY) { 393 overlay_client_data* data = (overlay_client_data*)fBasePointer; 394 395 status_t status; 396 do { 397 status = acquire_sem(data->lock); 398 } while (status == B_INTERRUPTED); 399 400 return status; 401 } 402 403 // NOTE: maybe this is used to prevent the app_server from 404 // drawing the bitmap yet? 405 // axeld: you mean for non overlays? 406 407 return B_ERROR; 408 } 409 410 411 /*! 412 \brief Unlocks the bitmap's buffer again. 413 Counterpart to LockBits(), see there for comments. 414 */ 415 void 416 BBitmap::UnlockBits() 417 { 418 if ((fFlags & B_BITMAP_WILL_OVERLAY) == 0) 419 return; 420 421 overlay_client_data* data = (overlay_client_data*)fBasePointer; 422 release_sem(data->lock); 423 } 424 425 // Area 426 /*! \brief Returns the ID of the area the bitmap data reside in. 427 \return The ID of the area the bitmap data reside in. 428 */ 429 area_id 430 BBitmap::Area() const 431 { 432 const_cast<BBitmap *>(this)->_AssertPointer(); 433 return fArea; 434 } 435 436 437 /*! \brief Returns the pointer to the bitmap data. 438 \return The pointer to the bitmap data. 439 */ 440 void * 441 BBitmap::Bits() const 442 { 443 const_cast<BBitmap *>(this)->_AssertPointer(); 444 445 if (fFlags & B_BITMAP_WILL_OVERLAY) { 446 overlay_client_data* data = (overlay_client_data*)fBasePointer; 447 return data->buffer; 448 } 449 450 return (void*)fBasePointer; 451 } 452 453 // BitsLength 454 /*! \brief Returns the size of the bitmap data. 455 \return The size of the bitmap data. 456 */ 457 int32 458 BBitmap::BitsLength() const 459 { 460 return fSize; 461 } 462 463 // BytesPerRow 464 /*! \brief Returns the number of bytes used to store a row of bitmap data. 465 \return The number of bytes used to store a row of bitmap data. 466 */ 467 int32 468 BBitmap::BytesPerRow() const 469 { 470 return fBytesPerRow; 471 } 472 473 // ColorSpace 474 /*! \brief Returns the bitmap's color space. 475 \return The bitmap's color space. 476 */ 477 color_space 478 BBitmap::ColorSpace() const 479 { 480 return fColorSpace; 481 } 482 483 // Bounds 484 /*! \brief Returns the bitmap's dimensions. 485 \return The bitmap's dimensions. 486 */ 487 BRect 488 BBitmap::Bounds() const 489 { 490 return fBounds; 491 } 492 493 // Flags 494 /*! \brief Returns the bitmap's creating flags. 495 496 This method informs about which flags have been used to create the 497 bitmap. It would for example tell you wether this is an overlay 498 bitmap. If bitmap creation succeeded, all flags are fulfilled. 499 500 \return The bitmap's creation flags. 501 */ 502 uint32 503 BBitmap::Flags() const 504 { 505 return fFlags; 506 } 507 508 509 // SetBits 510 /*! \brief Assigns data to the bitmap. 511 512 Data are directly written into the bitmap's data buffer, being converted 513 beforehand, if necessary. Some conversions work rather unintuitively: 514 - \c B_RGB32: The source buffer is supposed to contain \c B_RGB24_BIG 515 data without padding at the end of the rows. 516 - \c B_RGB32: The source buffer is supposed to contain \c B_CMAP8 517 data without padding at the end of the rows. 518 - other color spaces: The source buffer is supposed to contain data 519 according to the specified color space being rowwise padded to int32. 520 521 The currently supported source/target color spaces are 522 \c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}. 523 524 \note As this methods is apparently a bit strange to use, Haiku introduces 525 ImportBits() methods, which are recommended to be used instead. 526 527 \param data The data to be copied. 528 \param length The length in bytes of the data to be copied. 529 \param offset The offset (in bytes) relative to beginning of the bitmap 530 data specifying the position at which the source data shall be 531 written. 532 \param colorSpace Color space of the source data. 533 */ 534 void 535 BBitmap::SetBits(const void *data, int32 length, int32 offset, 536 color_space colorSpace) 537 { 538 status_t error = (InitCheck() == B_OK ? B_OK : B_NO_INIT); 539 // check params 540 if (error == B_OK && (data == NULL || offset > fSize || length < 0)) 541 error = B_BAD_VALUE; 542 int32 width = 0; 543 if (error == B_OK) 544 width = fBounds.IntegerWidth() + 1; 545 int32 inBPR = -1; 546 // tweaks to mimic R5 behavior 547 if (error == B_OK) { 548 // B_RGB32 means actually unpadded B_RGB24_BIG 549 if (colorSpace == B_RGB32) { 550 colorSpace = B_RGB24_BIG; 551 inBPR = width * 3; 552 // If in color space is B_CMAP8, but the bitmap's is another one, 553 // ignore source data row padding. 554 } else if (colorSpace == B_CMAP8 && fColorSpace != B_CMAP8) 555 inBPR = width; 556 } 557 // call the sane method, which does the actual work 558 if (error == B_OK) 559 error = ImportBits(data, length, inBPR, offset, colorSpace); 560 } 561 562 // ImportBits 563 /*! \brief Assigns data to the bitmap. 564 565 Data are directly written into the bitmap's data buffer, being converted 566 beforehand, if necessary. Unlike for SetBits(), the meaning of 567 \a colorSpace is exactly the expected one here, i.e. the source buffer 568 is supposed to contain data of that color space. \a bpr specifies how 569 many bytes the source contains per row. \c B_ANY_BYTES_PER_ROW can be 570 supplied, if standard padding to int32 is used. 571 572 The currently supported source/target color spaces are 573 \c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}. 574 575 \param data The data to be copied. 576 \param length The length in bytes of the data to be copied. 577 \param bpr The number of bytes per row in the source data. 578 \param offset The offset (in bytes) relative to beginning of the bitmap 579 data specifying the position at which the source data shall be 580 written. 581 \param colorSpace Color space of the source data. 582 \return 583 - \c B_OK: Everything went fine. 584 - \c B_BAD_VALUE: \c NULL \a data, invalid \a bpr or \a offset, or 585 unsupported \a colorSpace. 586 */ 587 status_t 588 BBitmap::ImportBits(const void *data, int32 length, int32 bpr, int32 offset, 589 color_space colorSpace) 590 { 591 _AssertPointer(); 592 593 if (InitCheck() != B_OK) 594 return B_NO_INIT; 595 596 if (!data || offset > fSize || length < 0) 597 return B_BAD_VALUE; 598 599 int32 width = fBounds.IntegerWidth() + 1; 600 if (bpr < 0) 601 bpr = get_bytes_per_row(colorSpace, width); 602 603 return BPrivate::ConvertBits(data, (uint8*)fBasePointer + offset, length, 604 fSize - offset, bpr, fBytesPerRow, colorSpace, fColorSpace, width, 605 fBounds.IntegerHeight() + 1); 606 } 607 608 609 /*! \brief Assigns data to the bitmap. 610 611 Allows for a BPoint offset in the source and in the bitmap. The region 612 of the source at \a from extending \a width and \a height is assigned 613 (and converted if necessary) to the bitmap at \a to. 614 615 The currently supported source/target color spaces are 616 \c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}. 617 618 \param data The data to be copied. 619 \param length The length in bytes of the data to be copied. 620 \param bpr The number of bytes per row in the source data. 621 \param colorSpace Color space of the source data. 622 \param from The offset in the source where reading should begin. 623 \param to The offset in the bitmap where the source should be written. 624 \param width The width (in pixels) to be imported. 625 \param height The height (in pixels) to be imported. 626 \return 627 - \c B_OK: Everything went fine. 628 - \c B_BAD_VALUE: \c NULL \a data, invalid \a bpr, unsupported 629 \a colorSpace or invalid width/height. 630 */ 631 status_t 632 BBitmap::ImportBits(const void *data, int32 length, int32 bpr, 633 color_space colorSpace, BPoint from, BPoint to, int32 width, int32 height) 634 { 635 _AssertPointer(); 636 637 if (InitCheck() != B_OK) 638 return B_NO_INIT; 639 640 if (!data || length < 0 || bpr < 0 || width < 0 || height < 0) 641 return B_BAD_VALUE; 642 643 if (bpr < 0) 644 bpr = get_bytes_per_row(colorSpace, fBounds.IntegerWidth() + 1); 645 646 return BPrivate::ConvertBits(data, fBasePointer, length, fSize, bpr, 647 fBytesPerRow, colorSpace, fColorSpace, from, to, width, height); 648 } 649 650 651 /*! \briefly Assigns another bitmap's data to this bitmap. 652 653 The supplied bitmap must have the exactly same dimensions as this bitmap. 654 Its data is converted to the color space of this bitmap. 655 656 The currently supported source/target color spaces are 657 \c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}. 658 659 \param bitmap The source bitmap. 660 \return 661 - \c B_OK: Everything went fine. 662 - \c B_BAD_VALUE: \c NULL \a bitmap, or \a bitmap has other dimensions, 663 or the conversion from or to one of the color spaces is not supported. 664 */ 665 status_t 666 BBitmap::ImportBits(const BBitmap *bitmap) 667 { 668 if (InitCheck() != B_OK) 669 return B_NO_INIT; 670 671 if (!bitmap || bitmap->InitCheck() != B_OK || bitmap->Bounds() != fBounds) 672 return B_BAD_VALUE; 673 674 return ImportBits(bitmap->Bits(), bitmap->BitsLength(), 675 bitmap->BytesPerRow(), 0, bitmap->ColorSpace()); 676 } 677 678 679 /*! \brief Assigns data to the bitmap. 680 681 Allows for a BPoint offset in the source and in the bitmap. The region 682 of the source at \a from extending \a width and \a height is assigned 683 (and converted if necessary) to the bitmap at \a to. The source bitmap is 684 clipped to the bitmap and they don't need to have the same dimensions. 685 686 The currently supported source/target color spaces are 687 \c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}. 688 689 \param bitmap The source bitmap. 690 \param from The offset in the source where reading should begin. 691 \param to The offset in the bitmap where the source should be written. 692 \param width The width (in pixels) to be imported. 693 \param height The height (in pixels) to be imported. 694 - \c B_OK: Everything went fine. 695 - \c B_BAD_VALUE: \c NULL \a bitmap, the conversion from or to one of 696 the color spaces is not supported, or invalid width/height. 697 */ 698 status_t 699 BBitmap::ImportBits(const BBitmap *bitmap, BPoint from, BPoint to, int32 width, 700 int32 height) 701 { 702 if (InitCheck() != B_OK) 703 return B_NO_INIT; 704 705 if (!bitmap || bitmap->InitCheck() != B_OK) 706 return B_BAD_VALUE; 707 708 return ImportBits(bitmap->Bits(), bitmap->BitsLength(), 709 bitmap->BytesPerRow(), bitmap->ColorSpace(), from, to, width, height); 710 } 711 712 713 /*! \brief Returns the overlay_restrictions structure for this bitmap 714 */ 715 status_t 716 BBitmap::GetOverlayRestrictions(overlay_restrictions *restrictions) const 717 { 718 if ((fFlags & B_BITMAP_WILL_OVERLAY) == 0) 719 return B_BAD_TYPE; 720 721 BPrivate::AppServerLink link; 722 723 link.StartMessage(AS_GET_BITMAP_OVERLAY_RESTRICTIONS); 724 link.Attach<int32>(fServerToken); 725 726 status_t status; 727 if (link.FlushWithReply(status) < B_OK) 728 return B_ERROR; 729 730 return status; 731 } 732 733 734 /*! \brief Adds a BView to the bitmap's view hierarchy. 735 736 The bitmap must accept views and the supplied view must not be child of 737 another parent. 738 739 \param view The view to be added. 740 */ 741 void 742 BBitmap::AddChild(BView *view) 743 { 744 if (fWindow != NULL) 745 fWindow->AddChild(view); 746 } 747 748 // RemoveChild 749 /*! \brief Removes a BView from the bitmap's view hierarchy. 750 \param view The view to be removed. 751 */ 752 bool 753 BBitmap::RemoveChild(BView *view) 754 { 755 return fWindow != NULL ? fWindow->RemoveChild(view) : false; 756 } 757 758 // CountChildren 759 /*! \brief Returns the number of BViews currently belonging to the bitmap. 760 \return The number of BViews currently belonging to the bitmap. 761 */ 762 int32 763 BBitmap::CountChildren() const 764 { 765 return fWindow != NULL ? fWindow->CountChildren() : 0; 766 } 767 768 // ChildAt 769 /*! \brief Returns the BView at a certain index in the bitmap's list of views. 770 \param index The index of the BView to be returned. 771 \return The BView at index \a index or \c NULL, if the index is out of 772 range. 773 */ 774 BView* 775 BBitmap::ChildAt(int32 index) const 776 { 777 return fWindow != NULL ? fWindow->ChildAt(index) : NULL; 778 } 779 780 // FindView 781 /*! \brief Returns a bitmap's BView with a certain name. 782 \param name The name of the BView to be returned. 783 \return The BView with the name \a name or \c NULL, if the bitmap doesn't 784 know a view with that name. 785 */ 786 BView* 787 BBitmap::FindView(const char *viewName) const 788 { 789 return fWindow != NULL ? fWindow->FindView(viewName) : NULL; 790 } 791 792 // FindView 793 /*! \brief Returns a bitmap's BView at a certain location. 794 \param point The location. 795 \return The BView with located at \a point or \c NULL, if the bitmap 796 doesn't know a view at this location. 797 */ 798 BView * 799 BBitmap::FindView(BPoint point) const 800 { 801 return fWindow != NULL ? fWindow->FindView(point) : NULL; 802 } 803 804 // Lock 805 /*! \brief Locks the off-screen window that belongs to the bitmap. 806 807 The bitmap must accept views, if locking should work. 808 809 \return \c true, if the lock was acquired successfully, \c false 810 otherwise. 811 */ 812 bool 813 BBitmap::Lock() 814 { 815 return fWindow != NULL ? fWindow->Lock() : false; 816 } 817 818 // Unlock 819 /*! \brief Unlocks the off-screen window that belongs to the bitmap. 820 821 The bitmap must accept views, if locking should work. 822 */ 823 void 824 BBitmap::Unlock() 825 { 826 if (fWindow != NULL) 827 fWindow->Unlock(); 828 } 829 830 // IsLocked 831 /*! \brief Returns whether or not the bitmap's off-screen window is locked. 832 833 The bitmap must accept views, if locking should work. 834 835 \return \c true, if the caller owns a lock , \c false otherwise. 836 */ 837 bool 838 BBitmap::IsLocked() const 839 { 840 return fWindow != NULL ? fWindow->IsLocked() : false; 841 } 842 843 // Perform 844 /*! \brief ??? 845 */ 846 status_t 847 BBitmap::Perform(perform_code d, void *arg) 848 { 849 return BArchivable::Perform(d, arg); 850 } 851 852 // FBC 853 void BBitmap::_ReservedBitmap1() {} 854 void BBitmap::_ReservedBitmap2() {} 855 void BBitmap::_ReservedBitmap3() {} 856 857 // copy constructor 858 /*! \brief Privatized copy constructor to prevent usage. 859 */ 860 BBitmap::BBitmap(const BBitmap &) 861 { 862 } 863 864 // = 865 /*! \brief Privatized assignment operator to prevent usage. 866 */ 867 BBitmap & 868 BBitmap::operator=(const BBitmap &) 869 { 870 return *this; 871 } 872 873 #if 0 874 // get_shared_pointer 875 /*! \brief ??? 876 */ 877 char * 878 BBitmap::get_shared_pointer() const 879 { 880 return NULL; // not implemented 881 } 882 #endif 883 884 int32 885 BBitmap::_ServerToken() const 886 { 887 return fServerToken; 888 } 889 890 891 /*! \brief Initializes the bitmap. 892 \param bounds The bitmap dimensions. 893 \param colorSpace The bitmap's color space. 894 \param flags Creation flags. 895 \param bytesPerRow The number of bytes per row the bitmap should use. 896 \c B_ANY_BYTES_PER_ROW to let the constructor choose an appropriate 897 value. 898 \param screenID ??? 899 */ 900 void 901 BBitmap::_InitObject(BRect bounds, color_space colorSpace, uint32 flags, 902 int32 bytesPerRow, screen_id screenID) 903 { 904 //printf("BBitmap::InitObject(bounds: BRect(%.1f, %.1f, %.1f, %.1f), format: %ld, flags: %ld, bpr: %ld\n", 905 // bounds.left, bounds.top, bounds.right, bounds.bottom, colorSpace, flags, bytesPerRow); 906 907 // TODO: Should we handle rounding of the "bounds" here? How does R5 behave? 908 909 status_t error = B_OK; 910 911 #ifdef RUN_WITHOUT_APP_SERVER 912 flags |= B_BITMAP_NO_SERVER_LINK; 913 #endif // RUN_WITHOUT_APP_SERVER 914 915 _CleanUp(); 916 917 // check params 918 if (!bounds.IsValid() || !bitmaps_support_space(colorSpace, NULL)) { 919 error = B_BAD_VALUE; 920 } else { 921 // bounds is in floats and might be valid but much larger than what we can handle 922 // the size could not be expressed in int32 923 double realSize = bounds.Width() * bounds.Height(); 924 if (realSize > (double)(INT_MAX / 4)) { 925 fprintf(stderr, "bitmap bounds is much too large: BRect(%.1f, %.1f, %.1f, %.1f)\n", 926 bounds.left, bounds.top, bounds.right, bounds.bottom); 927 error = B_BAD_VALUE; 928 } 929 } 930 if (error == B_OK) { 931 int32 bpr = get_bytes_per_row(colorSpace, bounds.IntegerWidth() + 1); 932 if (bytesPerRow < 0) 933 bytesPerRow = bpr; 934 else if (bytesPerRow < bpr) 935 // NOTE: How does R5 behave? 936 error = B_BAD_VALUE; 937 } 938 // allocate the bitmap buffer 939 if (error == B_OK) { 940 // NOTE: Maybe the code would look more robust if the 941 // "size" was not calculated here when we ask the server 942 // to allocate the bitmap. -Stephan 943 int32 size = bytesPerRow * (bounds.IntegerHeight() + 1); 944 945 if (flags & B_BITMAP_NO_SERVER_LINK) { 946 fBasePointer = (uint8*)malloc(size); 947 if (fBasePointer) { 948 fSize = size; 949 fColorSpace = colorSpace; 950 fBounds = bounds; 951 fBytesPerRow = bytesPerRow; 952 fFlags = flags; 953 } else 954 error = B_NO_MEMORY; 955 } else { 956 // Ask the server (via our owning application) to create a bitmap. 957 BPrivate::AppServerLink link; 958 959 // Attach Data: 960 // 1) BRect bounds 961 // 2) color_space space 962 // 3) int32 bitmap_flags 963 // 4) int32 bytes_per_row 964 // 5) int32 screen_id::id 965 link.StartMessage(AS_CREATE_BITMAP); 966 link.Attach<BRect>(bounds); 967 link.Attach<color_space>(colorSpace); 968 link.Attach<int32>((int32)flags); 969 link.Attach<int32>(bytesPerRow); 970 link.Attach<int32>(screenID.id); 971 972 if (link.FlushWithReply(error) == B_OK && error == B_OK) { 973 // server side success 974 // Get token 975 link.Read<int32>(&fServerToken); 976 977 uint8 allocationFlags; 978 link.Read<uint8>(&allocationFlags); 979 link.Read<area_id>(&fServerArea); 980 link.Read<int32>(&fAreaOffset); 981 982 BPrivate::ServerMemoryAllocator* allocator 983 = BApplication::Private::ServerAllocator(); 984 985 if (allocationFlags & kNewAllocatorArea) 986 error = allocator->AddArea(fServerArea, fArea, fBasePointer); 987 else { 988 error = allocator->AreaAndBaseFor(fServerArea, fArea, fBasePointer); 989 if (error == B_OK) 990 fBasePointer += fAreaOffset; 991 } 992 993 if (allocationFlags & kFramebuffer) { 994 // the base pointer will now point to an overlay_client_data structure 995 // bytes per row might be modified to match hardware constraints 996 link.Read<int32>(&bytesPerRow); 997 size = bytesPerRow * (bounds.IntegerHeight() + 1); 998 } 999 1000 if (fServerArea >= B_OK) { 1001 fSize = size; 1002 fColorSpace = colorSpace; 1003 fBounds = bounds; 1004 fBytesPerRow = bytesPerRow; 1005 fFlags = flags; 1006 } else 1007 error = fServerArea; 1008 } 1009 1010 if (error < B_OK) { 1011 fBasePointer = NULL; 1012 fServerToken = -1; 1013 fArea = -1; 1014 fServerArea = -1; 1015 fAreaOffset = -1; 1016 // NOTE: why not "0" in case of error? 1017 fFlags = flags; 1018 } 1019 } 1020 fWindow = NULL; 1021 } 1022 1023 fInitError = error; 1024 // TODO: on success, handle clearing to white if the flags say so. Needs to be 1025 // dependent on color space. 1026 1027 if (fInitError == B_OK) { 1028 if (flags & B_BITMAP_ACCEPTS_VIEWS) { 1029 fWindow = new BWindow(Bounds(), fServerToken); 1030 // A BWindow starts life locked and is unlocked 1031 // in Show(), but this window is never shown and 1032 // it's message loop is never started. 1033 fWindow->Unlock(); 1034 } 1035 } 1036 } 1037 1038 1039 /*! 1040 \brief Cleans up any memory allocated by the bitmap and 1041 informs the server to do so as well (if needed). 1042 */ 1043 void 1044 BBitmap::_CleanUp() 1045 { 1046 if (fBasePointer == NULL) 1047 return; 1048 1049 if (fFlags & B_BITMAP_NO_SERVER_LINK) { 1050 free(fBasePointer); 1051 } else { 1052 BPrivate::AppServerLink link; 1053 // AS_DELETE_BITMAP: 1054 // Attached Data: 1055 // 1) int32 server token 1056 link.StartMessage(AS_DELETE_BITMAP); 1057 link.Attach<int32>(fServerToken); 1058 link.Flush(); 1059 1060 // TODO: we may want to delete parts of the server memory areas here! 1061 1062 fArea = -1; 1063 fServerToken = -1; 1064 fAreaOffset = -1; 1065 } 1066 fBasePointer = NULL; 1067 } 1068 1069 1070 void 1071 BBitmap::_AssertPointer() 1072 { 1073 if (fBasePointer == NULL && fServerArea >= B_OK && fAreaOffset == -1) { 1074 // We lazily clone our own areas - if the bitmap is part of the usual 1075 // server memory area, or is a B_BITMAP_NO_SERVER_LINK bitmap, it already 1076 // has its data. 1077 fArea = clone_area("shared bitmap area", (void **)&fBasePointer, B_ANY_ADDRESS, 1078 B_READ_AREA | B_WRITE_AREA, fServerArea); 1079 } 1080 } 1081 1082