#include "Canvas.h"
#include <new>
#include <stdio.h>
#include <Bitmap.h>
#include <Entry.h>
#include <Message.h>
#include "Layer.h"
using std::nothrow;
Canvas::Canvas(BRect frame)
: BList(10),
fBounds(frame)
{
}
Canvas::~Canvas()
{
MakeEmpty();
}
bool
Canvas::IsValid() const
{
return fBounds.IsValid();
}
void
Canvas::MakeEmpty()
{
int32 count = CountLayers();
for (int32 i = 0; i < count; i++)
delete LayerAtFast(i);
BList::MakeEmpty();
}
bool
Canvas::AddLayer(Layer* layer)
{
return AddLayer(layer, CountLayers());
}
bool
Canvas::AddLayer(Layer* layer, int32 index)
{
return layer && AddItem((void*)layer, index);
}
Layer*
Canvas::RemoveLayer(int32 index)
{
return (Layer*)RemoveItem(index);
}
bool
Canvas::RemoveLayer(Layer* layer)
{
return RemoveItem((void*)layer);
}
Layer*
Canvas::LayerAt(int32 index) const
{
return (Layer*)ItemAt(index);
}
Layer*
Canvas::LayerAtFast(int32 index) const
{
return (Layer*)ItemAtFast(index);
}
int32
Canvas::IndexOf(Layer* layer) const
{
return BList::IndexOf((void*)layer);
}
int32
Canvas::CountLayers() const
{
return CountItems();
}
bool
Canvas::HasLayer(Layer* layer) const
{
return HasItem((void*)layer);
}
void
Canvas::SetBounds(BRect bounds)
{
if (bounds.IsValid())
fBounds = bounds;
}
BRect
Canvas::Bounds() const
{
return fBounds;
}
void
Canvas::Compose(BBitmap* into, BRect area) const
{
if (into && into->IsValid()
&& area.IsValid() && area.Intersects(into->Bounds())) {
area = area & into->Bounds();
int32 count = CountLayers();
for (int32 i = count - 1; Layer* layer = LayerAt(i); i--) {
layer->Compose(into, area);
}
}
}
BBitmap*
Canvas::Bitmap() const
{
BBitmap* bitmap = new BBitmap(fBounds, 0, B_RGBA32);
if (!bitmap->IsValid()) {
delete bitmap;
return NULL;
}
memset(bitmap->Bits(), 0, bitmap->BitsLength());
Compose(bitmap, fBounds);
uint8* bits = (uint8*)bitmap->Bits();
uint32 bpr = bitmap->BytesPerRow();
uint32 width = bitmap->Bounds().IntegerWidth() + 1;
uint32 height = bitmap->Bounds().IntegerHeight() + 1;
while (height > 0) {
uint8* bitsHandle = bits;
for (uint32 x = 0; x < width; x++) {
if (!bitsHandle[3]) {
bitsHandle[0] = 0;
bitsHandle[1] = 0;
bitsHandle[2] = 0;
}
bitsHandle += 4;
}
bits += bpr;
height--;
}
return bitmap;
}
static const char* LAYER_KEY = "layer";
static const char* BOUNDS_KEY = "bounds";
status_t
Canvas::Unarchive(const BMessage* archive)
{
if (!archive)
return B_BAD_VALUE;
BRect bounds;
if (archive->FindRect(BOUNDS_KEY, &bounds) < B_OK)
return B_ERROR;
fBounds = bounds;
BMessage layerMessage;
for (int32 i = 0;
archive->FindMessage(LAYER_KEY, i, &layerMessage) == B_OK;
i++) {
Layer* layer = new (nothrow) Layer();
if (!layer || layer->Unarchive(&layerMessage) < B_OK
|| !AddLayer(layer)) {
delete layer;
return B_NO_MEMORY;
}
}
return B_OK;
}