Files
haiku-beta6/src/kits/interface/Bitmap.cpp
T
Michael Lotz b09e53fae0 Wrote a new color conversion engine. It's 2-5 times faster than the old one (depending on colorspaces) and about half in size.
I've put it into ColorConversion.cpp and moved PaletteConverter there too, cleaning up Bitmap.cpp.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16580 a95241bf-73f2-0310-859d-f6bbb57e9c96
2006-03-05 05:01:15 +00:00

916 lines
23 KiB
C++

/*
* Copyright 2001-2005, Haiku Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold ([email protected])
* DarkWyrm <[email protected]>
* Stephan Aßmus <[email protected]>
*/
/** BBitmap objects represent off-screen windows that
* contain bitmap data.
*/
#include <algorithm>
#include <limits.h>
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <Application.h>
#include <Bitmap.h>
#include <GraphicsDefs.h>
#include <Locker.h>
#include <View.h>
#include <Window.h>
#include "ColorConversion.h"
// Includes to be able to talk to the app_server
#include <ServerProtocol.h>
#include <AppServerLink.h>
// get_raw_bytes_per_row
/*! \brief Returns the number of bytes per row needed to store the actual
bitmap data (not including any padding) given a color space and a
row width.
\param colorSpace The color space.
\param width The width.
\return The number of bytes per row needed to store data for a row, or
0, if the color space is not supported.
*/
static inline
int32
get_raw_bytes_per_row(color_space colorSpace, int32 width)
{
int32 bpr = 0;
switch (colorSpace) {
// supported
case B_RGB32: case B_RGBA32:
case B_RGB32_BIG: case B_RGBA32_BIG:
case B_UVL32: case B_UVLA32:
case B_LAB32: case B_LABA32:
case B_HSI32: case B_HSIA32:
case B_HSV32: case B_HSVA32:
case B_HLS32: case B_HLSA32:
case B_CMY32: case B_CMYA32: case B_CMYK32:
bpr = 4 * width;
break;
case B_RGB24: case B_RGB24_BIG:
case B_UVL24: case B_LAB24: case B_HSI24:
case B_HSV24: case B_HLS24: case B_CMY24:
bpr = 3 * width;
break;
case B_RGB16: case B_RGB15: case B_RGBA15:
case B_RGB16_BIG: case B_RGB15_BIG: case B_RGBA15_BIG:
bpr = 2 * width;
break;
case B_CMAP8: case B_GRAY8:
bpr = width;
break;
case B_GRAY1:
bpr = (width + 7) / 8;
break;
case B_YCbCr422: case B_YUV422:
bpr = (width + 3) / 4 * 8;
break;
case B_YCbCr411: case B_YUV411:
bpr = (width + 3) / 4 * 6;
break;
case B_YCbCr444: case B_YUV444:
bpr = (width + 3) / 4 * 12;
break;
case B_YCbCr420: case B_YUV420:
bpr = (width + 3) / 4 * 6;
break;
// unsupported
case B_NO_COLOR_SPACE:
case B_YUV9: case B_YUV12:
break;
}
return bpr;
}
// get_bytes_per_row
/*! \brief Returns the number of bytes per row needed to store the bitmap
data (including any padding) given a color space and a row width.
\param colorSpace The color space.
\param width The width.
\return The number of bytes per row needed to store data for a row, or
0, if the color space is not supported.
*/
static inline
int32
get_bytes_per_row(color_space colorSpace, int32 width)
{
int32 bpr = get_raw_bytes_per_row(colorSpace, width);
// align to int32
bpr = (bpr + 3) & 0x7ffffffc;
return bpr;
}
// constructor
/*! \brief Creates and initializes a BBitmap.
\param bounds The bitmap dimensions.
\param flags Creation flags.
\param colorSpace The bitmap's color space.
\param bytesPerRow The number of bytes per row the bitmap should use.
\c B_ANY_BYTES_PER_ROW to let the constructor choose an appropriate
value.
\param screenID ???
*/
BBitmap::BBitmap(BRect bounds, uint32 flags, color_space colorSpace,
int32 bytesPerRow, screen_id screenID)
: fBasePtr(NULL),
fSize(0),
fColorSpace(B_NO_COLOR_SPACE),
fBounds(0, 0, -1, -1),
fBytesPerRow(0),
fWindow(NULL),
fServerToken(-1),
fAreaOffset(-1),
fArea(-1),
fOrigArea(-1),
fFlags(0),
fInitError(B_NO_INIT)
{
InitObject(bounds, colorSpace, flags, bytesPerRow, screenID);
}
// constructor
/*! \brief Creates and initializes a BBitmap.
\param bounds The bitmap dimensions.
\param colorSpace The bitmap's color space.
\param acceptsViews \c true, if the bitmap shall accept BViews, i.e. if
it shall be possible to attach BView to the bitmap and draw into
it.
\param needsContiguous If \c true a physically contiguous chunk of memory
will be allocated.
*/
BBitmap::BBitmap(BRect bounds, color_space colorSpace, bool acceptsViews,
bool needsContiguous)
: fBasePtr(NULL),
fSize(0),
fColorSpace(B_NO_COLOR_SPACE),
fBounds(0, 0, -1, -1),
fBytesPerRow(0),
fWindow(NULL),
fServerToken(-1),
fAreaOffset(-1),
fArea(-1),
fOrigArea(-1),
fFlags(0),
fInitError(B_NO_INIT)
{
int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 0)
| (needsContiguous ? B_BITMAP_IS_CONTIGUOUS : 0);
InitObject(bounds, colorSpace, flags, B_ANY_BYTES_PER_ROW,
B_MAIN_SCREEN_ID);
}
// constructor
/*! \brief Creates a BBitmap as a clone of another bitmap.
\param source The source bitmap.
\param acceptsViews \c true, if the bitmap shall accept BViews, i.e. if
it shall be possible to attach BView to the bitmap and draw into
it.
\param needsContiguous If \c true a physically contiguous chunk of memory
will be allocated.
*/
BBitmap::BBitmap(const BBitmap *source, bool acceptsViews,
bool needsContiguous)
: fBasePtr(NULL),
fSize(0),
fColorSpace(B_NO_COLOR_SPACE),
fBounds(0, 0, -1, -1),
fBytesPerRow(0),
fWindow(NULL),
fServerToken(-1),
fAreaOffset(-1),
fArea(-1),
fOrigArea(-1),
fFlags(0),
fInitError(B_NO_INIT)
{
if (source && source->IsValid()) {
int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 0)
| (needsContiguous ? B_BITMAP_IS_CONTIGUOUS : 0);
InitObject(source->Bounds(), source->ColorSpace(), flags,
source->BytesPerRow(), B_MAIN_SCREEN_ID);
if (InitCheck() == B_OK)
memcpy(Bits(), source->Bits(), BytesPerRow());
}
}
// destructor
/*! \brief Frees all resources associated with this object.
*/
BBitmap::~BBitmap()
{
delete fWindow;
CleanUp();
}
// unarchiving constructor
/*! \brief Unarchives a bitmap from a BMessage.
\param data The archive.
*/
BBitmap::BBitmap(BMessage *data)
: BArchivable(data),
fBasePtr(NULL),
fSize(0),
fColorSpace(B_NO_COLOR_SPACE),
fBounds(0, 0, -1, -1),
fBytesPerRow(0),
fWindow(NULL),
fServerToken(-1),
fAreaOffset(-1),
fArea(-1),
fOrigArea(-1),
fFlags(0),
fInitError(B_NO_INIT)
{
BRect bounds;
data->FindRect("_frame", &bounds);
color_space cspace;
data->FindInt32("_cspace", (int32 *)&cspace);
int32 flags = 0;
data->FindInt32("_bmflags", &flags);
int32 rowBytes = 0;
data->FindInt32("_rowbytes", &rowBytes);
InitObject(bounds, cspace, flags, rowBytes, B_MAIN_SCREEN_ID);
if (data->HasData("_data", B_RAW_TYPE) && InitCheck() == B_OK) {
AssertPtr();
ssize_t size = 0;
const void *buffer;
if (data->FindData("_data", B_RAW_TYPE, &buffer, &size) == B_OK)
memcpy(fBasePtr, buffer, size);
}
if (fFlags & B_BITMAP_ACCEPTS_VIEWS) {
BMessage message;
int32 i = 0;
while (data->FindMessage("_view", i++, &message) == B_OK) {
if (BView *view = dynamic_cast<BView *>(instantiate_object(&message)))
AddChild(view);
}
}
}
// Instantiate
/*! \brief Instantiates a BBitmap from an archive.
\param data The archive.
\return A bitmap reconstructed from the archive or \c NULL, if an error
occured.
*/
BArchivable *
BBitmap::Instantiate(BMessage *data)
{
if (validate_instantiation(data, "BBitmap"))
return new BBitmap(data);
return NULL;
}
// Archive
/*! \brief Archives the BBitmap object.
\param data The archive.
\param deep \c true, if child object shall be archived as well, \c false
otherwise.
\return \c B_OK, if everything went fine, an error code otherwise.
*/
status_t
BBitmap::Archive(BMessage *data, bool deep) const
{
BArchivable::Archive(data, deep);
data->AddRect("_frame", fBounds);
data->AddInt32("_cspace", (int32)fColorSpace);
data->AddInt32("_bmflags", fFlags);
data->AddInt32("_rowbytes", fBytesPerRow);
if (deep) {
if (fFlags & B_BITMAP_ACCEPTS_VIEWS) {
BMessage views;
for (int32 i = 0; i < CountChildren(); i++) {
if (ChildAt(i)->Archive(&views, deep))
data->AddMessage("_views", &views);
}
}
// Note: R5 does not archive the data if B_BITMAP_IS_CONTIGNUOUS is
// true and it does save all formats as B_RAW_TYPE and it does save
// the data even if B_BITMAP_ACCEPTS_VIEWS is set (as opposed to
// the BeBook)
const_cast<BBitmap *>(this)->AssertPtr();
data->AddData("_data", B_RAW_TYPE, fBasePtr, fSize);
}
return B_OK;
}
// InitCheck
/*! \brief Returns the result from the construction.
\return \c B_OK, if the object is properly initialized, an error code
otherwise.
*/
status_t
BBitmap::InitCheck() const
{
return fInitError;
}
// IsValid
/*! \brief Returns whether or not the BBitmap object is valid.
\return \c true, if the object is properly initialized, \c false otherwise.
*/
bool
BBitmap::IsValid() const
{
return (InitCheck() == B_OK);
}
// LockBits
/*! \brief ???
*/
status_t
BBitmap::LockBits(uint32 *state)
{
return B_ERROR;
}
// UnlockBits
/*! \brief ???
*/
void
BBitmap::UnlockBits()
{
}
// Area
/*! \brief Returns the ID of the area the bitmap data reside in.
\return The ID of the area the bitmap data reside in.
*/
area_id
BBitmap::Area() const
{
const_cast<BBitmap *>(this)->AssertPtr();
return fArea;
}
// Bits
/*! \brief Returns the pointer to the bitmap data.
\return The pointer to the bitmap data.
*/
void *
BBitmap::Bits() const
{
const_cast<BBitmap *>(this)->AssertPtr();
return fBasePtr;
}
// BitsLength
/*! \brief Returns the size of the bitmap data.
\return The size of the bitmap data.
*/
int32
BBitmap::BitsLength() const
{
return fSize;
}
// BytesPerRow
/*! \brief Returns the number of bytes used to store a row of bitmap data.
\return The number of bytes used to store a row of bitmap data.
*/
int32
BBitmap::BytesPerRow() const
{
return fBytesPerRow;
}
// ColorSpace
/*! \brief Returns the bitmap's color space.
\return The bitmap's color space.
*/
color_space
BBitmap::ColorSpace() const
{
return fColorSpace;
}
// Bounds
/*! \brief Returns the bitmap's dimensions.
\return The bitmap's dimensions.
*/
BRect
BBitmap::Bounds() const
{
return fBounds;
}
// SetBits
/*! \brief Assigns data to the bitmap.
Data are directly written into the bitmap's data buffer, being converted
beforehand, if necessary. Some conversions work rather unintuitively:
- \c B_RGB32: The source buffer is supposed to contain \c B_RGB24_BIG
data without padding at the end of the rows.
- \c B_RGB32: The source buffer is supposed to contain \c B_CMAP8
data without padding at the end of the rows.
- other color spaces: The source buffer is supposed to contain data
according to the specified color space being rowwise padded to int32.
The currently supported source/target color spaces are
\c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}.
\note As this methods is apparently a bit strange to use, Haiku introduces
ImportBits() methods, which are recommended to be used instead.
\param data The data to be copied.
\param length The length in bytes of the data to be copied.
\param offset The offset (in bytes) relative to beginning of the bitmap
data specifying the position at which the source data shall be
written.
\param colorSpace Color space of the source data.
*/
void
BBitmap::SetBits(const void *data, int32 length, int32 offset,
color_space colorSpace)
{
status_t error = (InitCheck() == B_OK ? B_OK : B_NO_INIT);
// check params
if (error == B_OK && (data == NULL || offset > fSize || length < 0))
error = B_BAD_VALUE;
int32 width = 0;
if (error == B_OK)
width = fBounds.IntegerWidth() + 1;
int32 inBPR = -1;
// tweaks to mimic R5 behavior
if (error == B_OK) {
// B_RGB32 means actually unpadded B_RGB24_BIG
if (colorSpace == B_RGB32) {
colorSpace = B_RGB24_BIG;
inBPR = width * 3;
// If in color space is B_CMAP8, but the bitmap's is another one,
// ignore source data row padding.
} else if (colorSpace == B_CMAP8 && fColorSpace != B_CMAP8)
inBPR = width;
}
// call the sane method, which does the actual work
if (error == B_OK)
error = ImportBits(data, length, inBPR, offset, colorSpace);
}
// ImportBits
/*! \brief Assigns data to the bitmap.
Data are directly written into the bitmap's data buffer, being converted
beforehand, if necessary. Unlike for SetBits(), the meaning of
\a colorSpace is exactly the expected one here, i.e. the source buffer
is supposed to contain data of that color space. \a bpr specifies how
many bytes the source contains per row. \c B_ANY_BYTES_PER_ROW can be
supplied, if standard padding to int32 is used.
The currently supported source/target color spaces are
\c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}.
\param data The data to be copied.
\param length The length in bytes of the data to be copied.
\param bpr The number of bytes per row in the source data.
\param offset The offset (in bytes) relative to beginning of the bitmap
data specifying the position at which the source data shall be
written.
\param colorSpace Color space of the source data.
\return
- \c B_OK: Everything went fine.
- \c B_BAD_VALUE: \c NULL \a data, invalid \a bpr or \a offset, or
unsupported \a colorSpace.
*/
status_t
BBitmap::ImportBits(const void *data, int32 length, int32 bpr, int32 offset,
color_space colorSpace)
{
AssertPtr();
if (InitCheck() != B_OK)
return B_NO_INIT;
if (!data || offset > fSize || length < 0)
return B_BAD_VALUE;
if (colorSpace == fColorSpace && bpr == fBytesPerRow) {
length = min(length, fSize - offset);
memcpy((char *)fBasePtr + offset, data, length);
return B_OK;
}
int32 width = fBounds.IntegerWidth() + 1;
if (bpr < 0)
bpr = get_bytes_per_row(colorSpace, width);
return BPrivate::ConvertBits(data, fBasePtr, bpr, fBytesPerRow,
colorSpace, fColorSpace, width, fBounds.IntegerHeight() + 1);
}
// ImportBits
/*! \briefly Assigns another bitmap's data to this bitmap.
The supplied bitmap must have the exactly same dimensions as this bitmap.
Its data is converted to the color space of this bitmap.
The currently supported source/target color spaces are
\c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}.
\param bitmap The source bitmap.
\return
- \c B_OK: Everything went fine.
- \c B_BAD_VALUE: \c NULL \a bitmap, or \a bitmap has other dimensions,
or the conversion from or to one of the color spaces is not supported.
*/
status_t
BBitmap::ImportBits(const BBitmap *bitmap)
{
if (InitCheck() != B_OK)
return B_NO_INIT;
if (!bitmap || bitmap->InitCheck() != B_OK || bitmap->Bounds() != fBounds)
return B_BAD_VALUE;
return ImportBits(bitmap->Bits(), bitmap->BitsLength(),
bitmap->BytesPerRow(), 0, bitmap->ColorSpace());
}
/*! \brief Returns the overlay_restrictions structure for this bitmap
*/
status_t
BBitmap::GetOverlayRestrictions(overlay_restrictions *restrictions) const
{
if ((fFlags & B_BITMAP_WILL_OVERLAY) == 0)
return B_BAD_TYPE;
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_BITMAP_OVERLAY_RESTRICTIONS);
link.Attach<int32>(fServerToken);
status_t status;
if (link.FlushWithReply(status) < B_OK)
return B_ERROR;
return status;
}
/*! \brief Adds a BView to the bitmap's view hierarchy.
The bitmap must accept views and the supplied view must not be child of
another parent.
\param view The view to be added.
*/
void
BBitmap::AddChild(BView *view)
{
if (fWindow != NULL)
fWindow->AddChild(view);
}
// RemoveChild
/*! \brief Removes a BView from the bitmap's view hierarchy.
\param view The view to be removed.
*/
bool
BBitmap::RemoveChild(BView *view)
{
return fWindow != NULL ? fWindow->RemoveChild(view) : false;
}
// CountChildren
/*! \brief Returns the number of BViews currently belonging to the bitmap.
\return The number of BViews currently belonging to the bitmap.
*/
int32
BBitmap::CountChildren() const
{
return fWindow != NULL ? fWindow->CountChildren() : 0;
}
// ChildAt
/*! \brief Returns the BView at a certain index in the bitmap's list of views.
\param index The index of the BView to be returned.
\return The BView at index \a index or \c NULL, if the index is out of
range.
*/
BView*
BBitmap::ChildAt(int32 index) const
{
return fWindow != NULL ? fWindow->ChildAt(index) : NULL;
}
// FindView
/*! \brief Returns a bitmap's BView with a certain name.
\param name The name of the BView to be returned.
\return The BView with the name \a name or \c NULL, if the bitmap doesn't
know a view with that name.
*/
BView*
BBitmap::FindView(const char *viewName) const
{
return fWindow != NULL ? fWindow->FindView(viewName) : NULL;
}
// FindView
/*! \brief Returns a bitmap's BView at a certain location.
\param point The location.
\return The BView with located at \a point or \c NULL, if the bitmap
doesn't know a view at this location.
*/
BView *
BBitmap::FindView(BPoint point) const
{
return fWindow != NULL ? fWindow->FindView(point) : NULL;
}
// Lock
/*! \brief Locks the off-screen window that belongs to the bitmap.
The bitmap must accept views, if locking should work.
\return \c true, if the lock was acquired successfully, \c false
otherwise.
*/
bool
BBitmap::Lock()
{
return fWindow != NULL ? fWindow->Lock() : false;
}
// Unlock
/*! \brief Unlocks the off-screen window that belongs to the bitmap.
The bitmap must accept views, if locking should work.
*/
void
BBitmap::Unlock()
{
if (fWindow != NULL)
fWindow->Unlock();
}
// IsLocked
/*! \brief Returns whether or not the bitmap's off-screen window is locked.
The bitmap must accept views, if locking should work.
\return \c true, if the caller owns a lock , \c false otherwise.
*/
bool
BBitmap::IsLocked() const
{
return fWindow != NULL ? fWindow->IsLocked() : false;
}
// Perform
/*! \brief ???
*/
status_t
BBitmap::Perform(perform_code d, void *arg)
{
return BArchivable::Perform(d, arg);
}
// FBC
void BBitmap::_ReservedBitmap1() {}
void BBitmap::_ReservedBitmap2() {}
void BBitmap::_ReservedBitmap3() {}
// copy constructor
/*! \brief Privatized copy constructor to prevent usage.
*/
BBitmap::BBitmap(const BBitmap &)
{
}
// =
/*! \brief Privatized assignment operator to prevent usage.
*/
BBitmap &
BBitmap::operator=(const BBitmap &)
{
return *this;
}
// get_shared_pointer
/*! \brief ???
*/
char *
BBitmap::get_shared_pointer() const
{
return NULL; // not implemented
}
// get_server_token
/*! \brief ???
*/
int32
BBitmap::get_server_token() const
{
return fServerToken;
}
// InitObject
/*! \brief Initializes the bitmap.
\param bounds The bitmap dimensions.
\param colorSpace The bitmap's color space.
\param flags Creation flags.
\param bytesPerRow The number of bytes per row the bitmap should use.
\c B_ANY_BYTES_PER_ROW to let the constructor choose an appropriate
value.
\param screenID ???
*/
void
BBitmap::InitObject(BRect bounds, color_space colorSpace, uint32 flags,
int32 bytesPerRow, screen_id screenID)
{
//printf("BBitmap::InitObject(bounds: BRect(%.1f, %.1f, %.1f, %.1f), format: %ld, flags: %ld, bpr: %ld\n",
// bounds.left, bounds.top, bounds.right, bounds.bottom, colorSpace, flags, bytesPerRow);
// TODO: Should we handle rounding of the "bounds" here? How does R5 behave?
status_t error = B_OK;
#ifdef RUN_WITHOUT_APP_SERVER
flags |= B_BITMAP_NO_SERVER_LINK;
#endif // RUN_WITHOUT_APP_SERVER
CleanUp();
// check params
if (!bounds.IsValid() || !bitmaps_support_space(colorSpace, NULL)) {
error = B_BAD_VALUE;
} else {
// bounds is in floats and might be valid but much larger than what we can handle
// the size could not be expressed in int32
double realSize = bounds.Width() * bounds.Height();
if (realSize > (double)(INT_MAX / 4)) {
fprintf(stderr, "bitmap bounds is much too large: BRect(%.1f, %.1f, %.1f, %.1f)\n",
bounds.left, bounds.top, bounds.right, bounds.bottom);
error = B_BAD_VALUE;
}
}
if (error == B_OK) {
int32 bpr = get_bytes_per_row(colorSpace, bounds.IntegerWidth() + 1);
if (bytesPerRow < 0)
bytesPerRow = bpr;
else if (bytesPerRow < bpr)
// NOTE: How does R5 behave?
error = B_BAD_VALUE;
}
// allocate the bitmap buffer
if (error == B_OK) {
// NOTE: Maybe the code would look more robust if the
// "size" was not calculated here when we ask the server
// to allocate the bitmap. -Stephan
int32 size = bytesPerRow * (bounds.IntegerHeight() + 1);
if (flags & B_BITMAP_NO_SERVER_LINK) {
fBasePtr = malloc(size);
if (fBasePtr) {
fSize = size;
fColorSpace = colorSpace;
fBounds = bounds;
fBytesPerRow = bytesPerRow;
fFlags = flags;
} else
error = B_NO_MEMORY;
} else {
// Ask the server (via our owning application) to create a bitmap.
BPrivate::AppServerLink link;
// Attach Data:
// 1) BRect bounds
// 2) color_space space
// 3) int32 bitmap_flags
// 4) int32 bytes_per_row
// 5) int32 screen_id::id
link.StartMessage(AS_CREATE_BITMAP);
link.Attach<BRect>(bounds);
link.Attach<color_space>(colorSpace);
link.Attach<int32>((int32)flags);
link.Attach<int32>(bytesPerRow);
link.Attach<int32>(screenID.id);
// Reply Data:
// 1) int32 server token
// 2) area_id id of the area in which the bitmap data resides
// 3) int32 area pointer offset used to calculate fBasePtr
error = B_ERROR;
if (link.FlushWithReply(error) == B_OK && error == B_OK) {
// server side success
// Get token
link.Read<int32>(&fServerToken);
link.Read<area_id>(&fOrigArea);
link.Read<int32>(&fAreaOffset);
if (fOrigArea >= B_OK) {
fSize = size;
fColorSpace = colorSpace;
fBounds = bounds;
fBytesPerRow = bytesPerRow;
fFlags = flags;
} else
error = fOrigArea;
}
if (error < B_OK) {
fBasePtr = NULL;
fServerToken = -1;
fArea = -1;
fOrigArea = -1;
fAreaOffset = -1;
// NOTE: why not "0" in case of error?
fFlags = flags;
}
}
fWindow = NULL;
}
fInitError = error;
// TODO: on success, handle clearing to white if the flags say so. Needs to be
// dependent on color space.
if (fInitError == B_OK) {
if (flags & B_BITMAP_ACCEPTS_VIEWS) {
fWindow = new BWindow(Bounds(), fServerToken);
// A BWindow starts life locked and is unlocked
// in Show(), but this window is never shown and
// it's message loop is never started.
fWindow->Unlock();
}
}
}
/*!
\brief Cleans up any memory allocated by the bitmap and
informs the server to do so as well (if needed).
*/
void
BBitmap::CleanUp()
{
if (fBasePtr == NULL)
return;
if (fFlags & B_BITMAP_NO_SERVER_LINK) {
free(fBasePtr);
} else {
BPrivate::AppServerLink link;
// AS_DELETE_BITMAP:
// Attached Data:
// 1) int32 server token
link.StartMessage(AS_DELETE_BITMAP);
link.Attach<int32>(fServerToken);
link.Flush();
if (fArea >= 0)
delete_area(fArea);
fArea = -1;
fServerToken = -1;
fAreaOffset = -1;
}
fBasePtr = NULL;
}
void
BBitmap::AssertPtr()
{
if (fBasePtr == NULL && fAreaOffset != -1 && InitCheck() == B_OK) {
// Offset was saved into "fArea" as we can't add
// any member variable due to Binary compatibility
// Get the area in which the data resides
fArea = clone_area("shared bitmap area", (void **)&fBasePtr, B_ANY_ADDRESS,
B_READ_AREA | B_WRITE_AREA, fOrigArea);
if (fArea >= B_OK) {
// Jump to the location in the area
fBasePtr = (int8 *)fBasePtr + fAreaOffset;
} else
fBasePtr = NULL;
}
}