2 * Copyright 2001-2009, Haiku Inc.
3 * Distributed under the terms of the MIT License.
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
13 /*! BBitmap objects represent off-screen windows that
27 #include <Application.h>
28 #include <GraphicsDefs.h>
33 #include <ApplicationPrivate.h>
34 #include <AppServerLink.h>
36 #include <ObjectList.h>
37 #include <ServerMemoryAllocator.h>
38 #include <ServerProtocol.h>
40 #include "ColorConversion.h"
41 #include "BitmapPrivate.h"
44 using namespace BPrivate
;
47 static BObjectList
<BBitmap
> sBitmapList
;
48 static BLocker sBitmapListLock
;
52 reconnect_bitmaps_to_app_server()
54 BAutolock
_(sBitmapListLock
);
55 for (int32 i
= 0; i
< sBitmapList
.CountItems(); i
++) {
56 BBitmap::Private
bitmap(sBitmapList
.ItemAt(i
));
57 bitmap
.ReconnectToAppServer();
62 BBitmap::Private::Private(BBitmap
* bitmap
)
70 BBitmap::Private::ReconnectToAppServer()
72 fBitmap
->_ReconnectToAppServer();
76 /*! \brief Returns the number of bytes per row needed to store the actual
77 bitmap data (not including any padding) given a color space and a
79 \param colorSpace The color space.
80 \param width The width.
81 \return The number of bytes per row needed to store data for a row, or
82 0, if the color space is not supported.
85 get_raw_bytes_per_row(color_space colorSpace
, int32 width
)
90 case B_RGB32
: case B_RGBA32
:
91 case B_RGB32_BIG
: case B_RGBA32_BIG
:
92 case B_UVL32
: case B_UVLA32
:
93 case B_LAB32
: case B_LABA32
:
94 case B_HSI32
: case B_HSIA32
:
95 case B_HSV32
: case B_HSVA32
:
96 case B_HLS32
: case B_HLSA32
:
97 case B_CMY32
: case B_CMYA32
: case B_CMYK32
:
100 case B_RGB24
: case B_RGB24_BIG
:
101 case B_UVL24
: case B_LAB24
: case B_HSI24
:
102 case B_HSV24
: case B_HLS24
: case B_CMY24
:
105 case B_RGB16
: case B_RGB15
: case B_RGBA15
:
106 case B_RGB16_BIG
: case B_RGB15_BIG
: case B_RGBA15_BIG
:
109 case B_CMAP8
: case B_GRAY8
:
113 bpr
= (width
+ 7) / 8;
115 case B_YCbCr422
: case B_YUV422
:
116 bpr
= (width
+ 3) / 4 * 8;
118 case B_YCbCr411
: case B_YUV411
:
119 bpr
= (width
+ 3) / 4 * 6;
121 case B_YCbCr444
: case B_YUV444
:
122 bpr
= (width
+ 3) / 4 * 12;
124 case B_YCbCr420
: case B_YUV420
:
125 bpr
= (width
+ 3) / 4 * 6;
128 bpr
= (width
+ 15) / 16 * 18;
131 case B_NO_COLOR_SPACE
:
141 /*! \brief Returns the number of bytes per row needed to store the bitmap
142 data (including any padding) given a color space and a row width.
143 \param colorSpace The color space.
144 \param width The width.
145 \return The number of bytes per row needed to store data for a row, or
146 0, if the color space is not supported.
149 get_bytes_per_row(color_space colorSpace
, int32 width
)
151 int32 bpr
= get_raw_bytes_per_row(colorSpace
, width
);
153 bpr
= (bpr
+ 3) & 0x7ffffffc;
157 } // namespace BPrivate
163 /*! \brief Creates and initializes a BBitmap.
164 \param bounds The bitmap dimensions.
165 \param flags Creation flags.
166 \param colorSpace The bitmap's color space.
167 \param bytesPerRow The number of bytes per row the bitmap should use.
168 \c B_ANY_BYTES_PER_ROW to let the constructor choose an appropriate
172 BBitmap::BBitmap(BRect bounds
, uint32 flags
, color_space colorSpace
,
173 int32 bytesPerRow
, screen_id screenID
)
177 fColorSpace(B_NO_COLOR_SPACE
),
178 fBounds(0, 0, -1, -1),
186 fInitError(B_NO_INIT
)
188 _InitObject(bounds
, colorSpace
, flags
, bytesPerRow
, screenID
);
192 /*! \brief Creates and initializes a BBitmap.
193 \param bounds The bitmap dimensions.
194 \param colorSpace The bitmap's color space.
195 \param acceptsViews \c true, if the bitmap shall accept BViews, i.e. if
196 it shall be possible to attach BView to the bitmap and draw into
198 \param needsContiguous If \c true a physically contiguous chunk of memory
201 BBitmap::BBitmap(BRect bounds
, color_space colorSpace
, bool acceptsViews
,
202 bool needsContiguous
)
206 fColorSpace(B_NO_COLOR_SPACE
),
207 fBounds(0, 0, -1, -1),
215 fInitError(B_NO_INIT
)
217 int32 flags
= (acceptsViews
? B_BITMAP_ACCEPTS_VIEWS
: 0)
218 | (needsContiguous
? B_BITMAP_IS_CONTIGUOUS
: 0);
219 _InitObject(bounds
, colorSpace
, flags
, B_ANY_BYTES_PER_ROW
,
224 /*! \brief Creates a BBitmap as a clone of another bitmap.
225 \param source The source bitmap.
226 \param acceptsViews \c true, if the bitmap shall accept BViews, i.e. if
227 it shall be possible to attach BView to the bitmap and draw into
229 \param needsContiguous If \c true a physically contiguous chunk of memory
232 BBitmap::BBitmap(const BBitmap
* source
, bool acceptsViews
, bool needsContiguous
)
236 fColorSpace(B_NO_COLOR_SPACE
),
237 fBounds(0, 0, -1, -1),
245 fInitError(B_NO_INIT
)
247 if (source
&& source
->IsValid()) {
248 int32 flags
= (acceptsViews
? B_BITMAP_ACCEPTS_VIEWS
: 0)
249 | (needsContiguous
? B_BITMAP_IS_CONTIGUOUS
: 0);
250 _InitObject(source
->Bounds(), source
->ColorSpace(), flags
,
251 source
->BytesPerRow(), B_MAIN_SCREEN_ID
);
252 if (InitCheck() == B_OK
) {
253 memcpy(Bits(), source
->Bits(), min_c(BitsLength(),
254 source
->BitsLength()));
260 BBitmap::BBitmap(const BBitmap
& source
, uint32 flags
)
264 fColorSpace(B_NO_COLOR_SPACE
),
265 fBounds(0, 0, -1, -1),
273 fInitError(B_NO_INIT
)
275 if (!source
.IsValid())
278 _InitObject(source
.Bounds(), source
.ColorSpace(), flags
,
279 source
.BytesPerRow(), B_MAIN_SCREEN_ID
);
281 if (InitCheck() == B_OK
)
282 memcpy(Bits(), source
.Bits(), min_c(BitsLength(), source
.BitsLength()));
286 BBitmap::BBitmap(const BBitmap
& source
)
290 fColorSpace(B_NO_COLOR_SPACE
),
291 fBounds(0, 0, -1, -1),
299 fInitError(B_NO_INIT
)
305 /*! \brief Frees all resources associated with this object.
313 /*! \brief Unarchives a bitmap from a BMessage.
314 \param data The archive.
316 BBitmap::BBitmap(BMessage
* data
)
321 fColorSpace(B_NO_COLOR_SPACE
),
322 fBounds(0, 0, -1, -1),
330 fInitError(B_NO_INIT
)
333 if (data
->FindInt32("_bmflags", &flags
) != B_OK
) {
334 // this bitmap is archived in some archaic format
338 if (data
->FindBool("_view_ok", &acceptsViews
) == B_OK
&& acceptsViews
)
339 flags
|= B_BITMAP_ACCEPTS_VIEWS
;
342 if (data
->FindBool("_contiguous", &contiguous
) == B_OK
&& contiguous
)
343 flags
|= B_BITMAP_IS_CONTIGUOUS
;
347 if (data
->FindInt32("_rowbytes", &rowBytes
) != B_OK
) {
349 // bytes per row are computed in InitObject(), then
354 if (data
->FindRect("_frame", &bounds
) == B_OK
355 && data
->FindInt32("_cspace", (int32
*)&cspace
) == B_OK
) {
356 _InitObject(bounds
, cspace
, flags
, rowBytes
, B_MAIN_SCREEN_ID
);
359 if (InitCheck() == B_OK
) {
362 if (data
->FindData("_data", B_RAW_TYPE
, &buffer
, &size
) == B_OK
) {
363 if (size
== BitsLength()) {
365 memcpy(fBasePointer
, buffer
, size
);
370 if ((fFlags
& B_BITMAP_ACCEPTS_VIEWS
) != 0) {
374 while (data
->FindMessage("_views", i
++, &message
) == B_OK
) {
376 = dynamic_cast<BView
*>(instantiate_object(&message
)))
383 /*! \brief Instantiates a BBitmap from an archive.
384 \param data The archive.
385 \return A bitmap reconstructed from the archive or \c NULL, if an error
389 BBitmap::Instantiate(BMessage
* data
)
391 if (validate_instantiation(data
, "BBitmap"))
392 return new BBitmap(data
);
398 /*! \brief Archives the BBitmap object.
399 \param data The archive.
400 \param deep \c true, if child object shall be archived as well, \c false
402 \return \c B_OK, if everything went fine, an error code otherwise.
405 BBitmap::Archive(BMessage
* data
, bool deep
) const
407 status_t ret
= BArchivable::Archive(data
, deep
);
410 ret
= data
->AddRect("_frame", fBounds
);
413 ret
= data
->AddInt32("_cspace", (int32
)fColorSpace
);
416 ret
= data
->AddInt32("_bmflags", fFlags
);
419 ret
= data
->AddInt32("_rowbytes", fBytesPerRow
);
421 if (ret
== B_OK
&& deep
) {
422 if ((fFlags
& B_BITMAP_ACCEPTS_VIEWS
) != 0) {
424 for (int32 i
= 0; i
< CountChildren(); i
++) {
425 if (ChildAt(i
)->Archive(&views
, deep
))
426 ret
= data
->AddMessage("_views", &views
);
432 // Note: R5 does not archive the data if B_BITMAP_IS_CONTIGUOUS is
433 // true and it does save all formats as B_RAW_TYPE and it does save
434 // the data even if B_BITMAP_ACCEPTS_VIEWS is set (as opposed to
437 const_cast<BBitmap
*>(this)->_AssertPointer();
438 ret
= data
->AddData("_data", B_RAW_TYPE
, fBasePointer
, fSize
);
446 /*! \brief Returns the result from the construction.
447 \return \c B_OK, if the object is properly initialized, an error code
451 BBitmap::InitCheck() const
457 /*! \brief Returns whether or not the BBitmap object is valid.
458 \return \c true, if the object is properly initialized, \c false otherwise.
461 BBitmap::IsValid() const
463 return InitCheck() == B_OK
;
467 /*! \brief Locks the bitmap bits so that they cannot be relocated.
469 This is currently only used for overlay bitmaps - whenever you
470 need to access their Bits(), you have to lock them first.
471 On resolution change overlay bitmaps can be relocated in memory;
472 using this call prevents you from accessing an invalid pointer
473 and clobbering memory that doesn't belong you.
476 BBitmap::LockBits(uint32
* state
)
478 // TODO: how do we fill the "state"?
479 // It would be more or less useful to report what kind of bitmap
480 // we got (ie. overlay, placeholder, or non-overlay)
481 if ((fFlags
& B_BITMAP_WILL_OVERLAY
) != 0) {
482 overlay_client_data
* data
= (overlay_client_data
*)fBasePointer
;
486 status
= acquire_sem(data
->lock
);
487 } while (status
== B_INTERRUPTED
);
489 if (data
->buffer
== NULL
) {
490 // the app_server does not grant us access to the frame buffer
491 // right now - let's release the lock and fail
492 release_sem_etc(data
->lock
, 1, B_DO_NOT_RESCHEDULE
);
498 // NOTE: maybe this is used to prevent the app_server from
499 // drawing the bitmap yet?
500 // axeld: you mean for non overlays?
506 /*! \brief Unlocks the bitmap's buffer again.
507 Counterpart to LockBits(), see there for comments.
510 BBitmap::UnlockBits()
512 if ((fFlags
& B_BITMAP_WILL_OVERLAY
) == 0)
515 overlay_client_data
* data
= (overlay_client_data
*)fBasePointer
;
516 release_sem_etc(data
->lock
, 1, B_DO_NOT_RESCHEDULE
);
520 /*! \brief Returns the ID of the area the bitmap data reside in.
521 \return The ID of the area the bitmap data reside in.
524 BBitmap::Area() const
526 const_cast<BBitmap
*>(this)->_AssertPointer();
531 /*! \brief Returns the pointer to the bitmap data.
532 \return The pointer to the bitmap data.
535 BBitmap::Bits() const
537 const_cast<BBitmap
*>(this)->_AssertPointer();
539 if ((fFlags
& B_BITMAP_WILL_OVERLAY
) != 0) {
540 overlay_client_data
* data
= (overlay_client_data
*)fBasePointer
;
544 return (void*)fBasePointer
;
548 /*! \brief Returns the size of the bitmap data.
549 \return The size of the bitmap data.
552 BBitmap::BitsLength() const
558 /*! \brief Returns the number of bytes used to store a row of bitmap data.
559 \return The number of bytes used to store a row of bitmap data.
562 BBitmap::BytesPerRow() const
568 /*! \brief Returns the bitmap's color space.
569 \return The bitmap's color space.
572 BBitmap::ColorSpace() const
578 /*! \brief Returns the bitmap's dimensions.
579 \return The bitmap's dimensions.
582 BBitmap::Bounds() const
588 /*! \brief Returns the bitmap's creating flags.
590 This method informs about which flags have been used to create the
591 bitmap. It would for example tell you whether this is an overlay
592 bitmap. If bitmap creation succeeded, all flags are fulfilled.
594 \return The bitmap's creation flags.
597 BBitmap::Flags() const
603 /*! \brief Assigns data to the bitmap.
605 Data are directly written into the bitmap's data buffer, being converted
606 beforehand, if necessary. Some conversions work rather unintuitively:
607 - \c B_RGB32: The source buffer is supposed to contain \c B_RGB24_BIG
608 data without padding at the end of the rows.
609 - \c B_RGB32: The source buffer is supposed to contain \c B_CMAP8
610 data without padding at the end of the rows.
611 - other color spaces: The source buffer is supposed to contain data
612 according to the specified color space being rowwise padded to int32.
614 The currently supported source/target color spaces are
615 \c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}.
617 \note As this methods is apparently a bit strange to use, Haiku introduces
618 ImportBits() methods, which are recommended to be used instead.
620 \param data The data to be copied.
621 \param length The length in bytes of the data to be copied.
622 \param offset The offset (in bytes) relative to beginning of the bitmap
623 data specifying the position at which the source data shall be
625 \param colorSpace Color space of the source data.
628 BBitmap::SetBits(const void* data
, int32 length
, int32 offset
,
629 color_space colorSpace
)
631 status_t error
= (InitCheck() == B_OK
? B_OK
: B_NO_INIT
);
633 if (error
== B_OK
&& (data
== NULL
|| offset
> fSize
|| length
< 0))
637 width
= fBounds
.IntegerWidth() + 1;
639 // tweaks to mimic R5 behavior
641 if (colorSpace
== B_RGB32
) {
642 // B_RGB32 means actually unpadded B_RGB24_BIG
643 colorSpace
= B_RGB24_BIG
;
645 } else if (colorSpace
== B_CMAP8
&& fColorSpace
!= B_CMAP8
) {
646 // If in color space is B_CMAP8, but the bitmap's is another one,
647 // ignore source data row padding.
651 // call the sane method, which does the actual work
652 error
= ImportBits(data
, length
, inBPR
, offset
, colorSpace
);
657 /*! \brief Assigns data to the bitmap.
659 Data are directly written into the bitmap's data buffer, being converted
660 beforehand, if necessary. Unlike for SetBits(), the meaning of
661 \a colorSpace is exactly the expected one here, i.e. the source buffer
662 is supposed to contain data of that color space. \a bpr specifies how
663 many bytes the source contains per row. \c B_ANY_BYTES_PER_ROW can be
664 supplied, if standard padding to int32 is used.
666 The currently supported source/target color spaces are
667 \c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}.
669 \param data The data to be copied.
670 \param length The length in bytes of the data to be copied.
671 \param bpr The number of bytes per row in the source data.
672 \param offset The offset (in bytes) relative to beginning of the bitmap
673 data specifying the position at which the source data shall be
675 \param colorSpace Color space of the source data.
677 - \c B_OK: Everything went fine.
678 - \c B_BAD_VALUE: \c NULL \a data, invalid \a bpr or \a offset, or
679 unsupported \a colorSpace.
682 BBitmap::ImportBits(const void* data
, int32 length
, int32 bpr
, int32 offset
,
683 color_space colorSpace
)
687 if (InitCheck() != B_OK
)
690 if (!data
|| offset
> fSize
|| length
< 0)
693 int32 width
= fBounds
.IntegerWidth() + 1;
695 if (bpr
== B_ANY_BYTES_PER_ROW
)
696 bpr
= get_bytes_per_row(colorSpace
, width
);
701 return BPrivate::ConvertBits(data
, (uint8
*)fBasePointer
+ offset
, length
,
702 fSize
- offset
, bpr
, fBytesPerRow
, colorSpace
, fColorSpace
, width
,
703 fBounds
.IntegerHeight() + 1);
707 /*! \brief Assigns data to the bitmap.
709 Allows for a BPoint offset in the source and in the bitmap. The region
710 of the source at \a from extending \a width and \a height is assigned
711 (and converted if necessary) to the bitmap at \a to.
713 The currently supported source/target color spaces are
714 \c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}.
716 \param data The data to be copied.
717 \param length The length in bytes of the data to be copied.
718 \param bpr The number of bytes per row in the source data.
719 \param colorSpace Color space of the source data.
720 \param from The offset in the source where reading should begin.
721 \param to The offset in the bitmap where the source should be written.
722 \param width The width (in pixels) to be imported.
723 \param height The height (in pixels) to be imported.
725 - \c B_OK: Everything went fine.
726 - \c B_BAD_VALUE: \c NULL \a data, invalid \a bpr, unsupported
727 \a colorSpace or invalid width/height.
730 BBitmap::ImportBits(const void* data
, int32 length
, int32 bpr
,
731 color_space colorSpace
, BPoint from
, BPoint to
, int32 width
, int32 height
)
735 if (InitCheck() != B_OK
)
738 if (!data
|| length
< 0 || width
< 0 || height
< 0)
742 if (bpr
== B_ANY_BYTES_PER_ROW
)
743 bpr
= get_bytes_per_row(colorSpace
, fBounds
.IntegerWidth() + 1);
748 return BPrivate::ConvertBits(data
, fBasePointer
, length
, fSize
, bpr
,
749 fBytesPerRow
, colorSpace
, fColorSpace
, from
, to
, width
, height
);
753 /*! \briefly Assigns another bitmap's data to this bitmap.
755 The supplied bitmap must have the exactly same dimensions as this bitmap.
756 Its data is converted to the color space of this bitmap.
758 The currently supported source/target color spaces are
759 \c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}.
761 \param bitmap The source bitmap.
763 - \c B_OK: Everything went fine.
764 - \c B_BAD_VALUE: \c NULL \a bitmap, or \a bitmap has other dimensions,
765 or the conversion from or to one of the color spaces is not supported.
768 BBitmap::ImportBits(const BBitmap
* bitmap
)
770 if (InitCheck() != B_OK
)
773 if (!bitmap
|| bitmap
->InitCheck() != B_OK
|| bitmap
->Bounds() != fBounds
)
776 return ImportBits(bitmap
->Bits(), bitmap
->BitsLength(),
777 bitmap
->BytesPerRow(), 0, bitmap
->ColorSpace());
781 /*! \brief Assigns data to the bitmap.
783 Allows for a BPoint offset in the source and in the bitmap. The region
784 of the source at \a from extending \a width and \a height is assigned
785 (and converted if necessary) to the bitmap at \a to. The source bitmap is
786 clipped to the bitmap and they don't need to have the same dimensions.
788 The currently supported source/target color spaces are
789 \c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}.
791 \param bitmap The source bitmap.
792 \param from The offset in the source where reading should begin.
793 \param to The offset in the bitmap where the source should be written.
794 \param width The width (in pixels) to be imported.
795 \param height The height (in pixels) to be imported.
796 - \c B_OK: Everything went fine.
797 - \c B_BAD_VALUE: \c NULL \a bitmap, the conversion from or to one of
798 the color spaces is not supported, or invalid width/height.
801 BBitmap::ImportBits(const BBitmap
* bitmap
, BPoint from
, BPoint to
, int32 width
,
804 if (InitCheck() != B_OK
)
807 if (!bitmap
|| bitmap
->InitCheck() != B_OK
)
810 return ImportBits(bitmap
->Bits(), bitmap
->BitsLength(),
811 bitmap
->BytesPerRow(), bitmap
->ColorSpace(), from
, to
, width
, height
);
815 /*! \brief Returns the overlay_restrictions structure for this bitmap
818 BBitmap::GetOverlayRestrictions(overlay_restrictions
* restrictions
) const
820 if ((fFlags
& B_BITMAP_WILL_OVERLAY
) == 0)
823 BPrivate::AppServerLink link
;
825 link
.StartMessage(AS_GET_BITMAP_OVERLAY_RESTRICTIONS
);
826 link
.Attach
<int32
>(fServerToken
);
829 if (link
.FlushWithReply(status
) < B_OK
)
832 link
.Read(restrictions
, sizeof(overlay_restrictions
));
837 /*! \brief Adds a BView to the bitmap's view hierarchy.
839 The bitmap must accept views and the supplied view must not be child of
842 \param view The view to be added.
845 BBitmap::AddChild(BView
* view
)
848 fWindow
->AddChild(view
);
852 /*! \brief Removes a BView from the bitmap's view hierarchy.
853 \param view The view to be removed.
856 BBitmap::RemoveChild(BView
* view
)
858 return fWindow
!= NULL
? fWindow
->RemoveChild(view
) : false;
862 /*! \brief Returns the number of BViews currently belonging to the bitmap.
863 \return The number of BViews currently belonging to the bitmap.
866 BBitmap::CountChildren() const
868 return fWindow
!= NULL
? fWindow
->CountChildren() : 0;
872 /*! \brief Returns the BView at a certain index in the bitmap's list of views.
873 \param index The index of the BView to be returned.
874 \return The BView at index \a index or \c NULL, if the index is out of
878 BBitmap::ChildAt(int32 index
) const
880 return fWindow
!= NULL
? fWindow
->ChildAt(index
) : NULL
;
884 /*! \brief Returns a bitmap's BView with a certain name.
885 \param name The name of the BView to be returned.
886 \return The BView with the name \a name or \c NULL, if the bitmap doesn't
887 know a view with that name.
890 BBitmap::FindView(const char* viewName
) const
892 return fWindow
!= NULL
? fWindow
->FindView(viewName
) : NULL
;
896 /*! \brief Returns a bitmap's BView at a certain location.
897 \param point The location.
898 \return The BView with located at \a point or \c NULL, if the bitmap
899 doesn't know a view at this location.
902 BBitmap::FindView(BPoint point
) const
904 return fWindow
!= NULL
? fWindow
->FindView(point
) : NULL
;
908 /*! \brief Locks the off-screen window that belongs to the bitmap.
910 The bitmap must accept views, if locking should work.
912 \return \c true, if the lock was acquired successfully, \c false
918 return fWindow
!= NULL
? fWindow
->Lock() : false;
922 /*! \brief Unlocks the off-screen window that belongs to the bitmap.
924 The bitmap must accept views, if locking should work.
934 /*! \brief Returns whether or not the bitmap's off-screen window is locked.
936 The bitmap must accept views, if locking should work.
938 \return \c true, if the caller owns a lock , \c false otherwise.
941 BBitmap::IsLocked() const
943 return fWindow
!= NULL
? fWindow
->IsLocked() : false;
948 BBitmap::operator=(const BBitmap
& source
)
951 fInitError
= B_NO_INIT
;
953 if (!source
.IsValid())
956 _InitObject(source
.Bounds(), source
.ColorSpace(), source
.Flags(),
957 source
.BytesPerRow(), B_MAIN_SCREEN_ID
);
958 if (InitCheck() == B_OK
)
959 memcpy(Bits(), source
.Bits(), min_c(BitsLength(), source
.BitsLength()));
966 BBitmap::Perform(perform_code d
, void* arg
)
968 return BArchivable::Perform(d
, arg
);
972 void BBitmap::_ReservedBitmap1() {}
973 void BBitmap::_ReservedBitmap2() {}
974 void BBitmap::_ReservedBitmap3() {}
978 // get_shared_pointer
982 BBitmap::get_shared_pointer() const
984 return NULL
; // not implemented
989 BBitmap::_ServerToken() const
995 /*! \brief Initializes the bitmap.
996 \param bounds The bitmap dimensions.
997 \param colorSpace The bitmap's color space.
998 \param flags Creation flags.
999 \param bytesPerRow The number of bytes per row the bitmap should use.
1000 \c B_ANY_BYTES_PER_ROW to let the constructor choose an appropriate
1005 BBitmap::_InitObject(BRect bounds
, color_space colorSpace
, uint32 flags
,
1006 int32 bytesPerRow
, screen_id screenID
)
1008 //printf("BBitmap::InitObject(bounds: BRect(%.1f, %.1f, %.1f, %.1f), format: %ld, flags: %ld, bpr: %ld\n",
1009 // bounds.left, bounds.top, bounds.right, bounds.bottom, colorSpace, flags, bytesPerRow);
1011 // TODO: Should we handle rounding of the "bounds" here? How does R5 behave?
1013 status_t error
= B_OK
;
1015 #ifdef RUN_WITHOUT_APP_SERVER
1016 flags
|= B_BITMAP_NO_SERVER_LINK
;
1017 #endif // RUN_WITHOUT_APP_SERVER
1022 if (!bounds
.IsValid() || !bitmaps_support_space(colorSpace
, NULL
)) {
1023 error
= B_BAD_VALUE
;
1025 // bounds is in floats and might be valid but much larger than what we
1026 // can handle the size could not be expressed in int32
1027 double realSize
= bounds
.Width() * bounds
.Height();
1028 if (realSize
> (double)(INT_MAX
/ 4)) {
1029 fprintf(stderr
, "bitmap bounds is much too large: "
1030 "BRect(%.1f, %.1f, %.1f, %.1f)\n",
1031 bounds
.left
, bounds
.top
, bounds
.right
, bounds
.bottom
);
1032 error
= B_BAD_VALUE
;
1035 if (error
== B_OK
) {
1036 int32 bpr
= get_bytes_per_row(colorSpace
, bounds
.IntegerWidth() + 1);
1037 if (bytesPerRow
< 0)
1039 else if (bytesPerRow
< bpr
)
1040 // NOTE: How does R5 behave?
1041 error
= B_BAD_VALUE
;
1043 // allocate the bitmap buffer
1044 if (error
== B_OK
) {
1045 // TODO: Let the app_server return the size when it allocated the bitmap
1046 int32 size
= bytesPerRow
* (bounds
.IntegerHeight() + 1);
1048 if ((flags
& B_BITMAP_NO_SERVER_LINK
) != 0) {
1049 fBasePointer
= (uint8
*)malloc(size
);
1052 fColorSpace
= colorSpace
;
1054 fBytesPerRow
= bytesPerRow
;
1057 error
= B_NO_MEMORY
;
1059 // Ask the server (via our owning application) to create a bitmap.
1060 BPrivate::AppServerLink link
;
1064 // 2) color_space space
1065 // 3) int32 bitmap_flags
1066 // 4) int32 bytes_per_row
1067 // 5) int32 screen_id::id
1068 link
.StartMessage(AS_CREATE_BITMAP
);
1069 link
.Attach
<BRect
>(bounds
);
1070 link
.Attach
<color_space
>(colorSpace
);
1071 link
.Attach
<uint32
>(flags
);
1072 link
.Attach
<int32
>(bytesPerRow
);
1073 link
.Attach
<int32
>(screenID
.id
);
1075 if (link
.FlushWithReply(error
) == B_OK
&& error
== B_OK
) {
1076 // server side success
1078 link
.Read
<int32
>(&fServerToken
);
1080 uint8 allocationFlags
;
1081 link
.Read
<uint8
>(&allocationFlags
);
1082 link
.Read
<area_id
>(&fServerArea
);
1083 link
.Read
<int32
>(&fAreaOffset
);
1085 BPrivate::ServerMemoryAllocator
* allocator
1086 = BApplication::Private::ServerAllocator();
1088 if ((allocationFlags
& kNewAllocatorArea
) != 0) {
1089 error
= allocator
->AddArea(fServerArea
, fArea
,
1090 fBasePointer
, size
);
1092 error
= allocator
->AreaAndBaseFor(fServerArea
, fArea
,
1095 fBasePointer
+= fAreaOffset
;
1098 if ((allocationFlags
& kFramebuffer
) != 0) {
1099 // The base pointer will now point to an overlay_client_data
1100 // structure bytes per row might be modified to match
1101 // hardware constraints
1102 link
.Read
<int32
>(&bytesPerRow
);
1103 size
= bytesPerRow
* (bounds
.IntegerHeight() + 1);
1106 if (fServerArea
>= B_OK
) {
1108 fColorSpace
= colorSpace
;
1110 fBytesPerRow
= bytesPerRow
;
1113 error
= fServerArea
;
1117 fBasePointer
= NULL
;
1122 // NOTE: why not "0" in case of error?
1125 BAutolock
_(sBitmapListLock
);
1126 sBitmapList
.AddItem(this);
1134 if (fInitError
== B_OK
) {
1135 // clear to white if the flags say so.
1136 if (flags
& (B_BITMAP_CLEAR_TO_WHITE
| B_BITMAP_ACCEPTS_VIEWS
)) {
1137 if (fColorSpace
== B_CMAP8
) {
1138 // "255" is the "transparent magic" index for B_CMAP8 bitmaps
1139 // use the correct index for "white"
1140 memset(fBasePointer
, 65, fSize
);
1142 // should work for most colorspaces
1143 memset(fBasePointer
, 0xff, fSize
);
1146 // TODO: Creating an offscreen window with a non32 bit bitmap
1147 // copies the current content of the bitmap to a back buffer.
1148 // So at this point the bitmap has to be already cleared to white.
1149 // Better move the above code to the server so the problem looks more
1151 if (flags
& B_BITMAP_ACCEPTS_VIEWS
) {
1152 fWindow
= new(std::nothrow
) BWindow(Bounds(), fServerToken
);
1154 // A BWindow starts life locked and is unlocked
1155 // in Show(), but this window is never shown and
1156 // it's message loop is never started.
1159 fInitError
= B_NO_MEMORY
;
1165 /*! \brief Cleans up any memory allocated by the bitmap and
1166 informs the server to do so as well (if needed).
1171 if (fWindow
!= NULL
) {
1172 if (fWindow
->Lock())
1175 // this will leak fWindow if it couldn't be locked
1178 if (fBasePointer
== NULL
)
1181 if ((fFlags
& B_BITMAP_NO_SERVER_LINK
) != 0) {
1183 } else if (fServerToken
!= -1) {
1184 BPrivate::AppServerLink link
;
1185 // AS_DELETE_BITMAP:
1187 // 1) int32 server token
1188 link
.StartMessage(AS_DELETE_BITMAP
);
1189 link
.Attach
<int32
>(fServerToken
);
1192 // The server areas are deleted via kMsgDeleteServerMemoryArea message
1198 BAutolock
_(sBitmapListLock
);
1199 sBitmapList
.RemoveItem(this);
1201 fBasePointer
= NULL
;
1206 BBitmap::_AssertPointer()
1208 if (fBasePointer
== NULL
&& fServerArea
>= B_OK
&& fAreaOffset
== -1) {
1209 // We lazily clone our own areas - if the bitmap is part of the usual
1210 // server memory area, or is a B_BITMAP_NO_SERVER_LINK bitmap, it
1211 // already has its data.
1212 fArea
= clone_area("shared bitmap area", (void**)&fBasePointer
,
1213 B_ANY_ADDRESS
, B_READ_AREA
| B_WRITE_AREA
, fServerArea
);
1219 BBitmap::_ReconnectToAppServer()
1221 BPrivate::AppServerLink link
;
1223 link
.StartMessage(AS_RECONNECT_BITMAP
);
1224 link
.Attach
<BRect
>(fBounds
);
1225 link
.Attach
<color_space
>(fColorSpace
);
1226 link
.Attach
<uint32
>(fFlags
);
1227 link
.Attach
<int32
>(fBytesPerRow
);
1228 link
.Attach
<int32
>(0);
1229 link
.Attach
<int32
>(fArea
);
1230 link
.Attach
<int32
>(fAreaOffset
);
1233 if (link
.FlushWithReply(error
) == B_OK
&& error
== B_OK
) {
1234 // server side success
1236 link
.Read
<int32
>(&fServerToken
);
1238 link
.Read
<area_id
>(&fServerArea
);