1/* 2 * Copyright 2006, Haiku. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan A��mus <superstippi@gmx.de> 7 */ 8 9#include "Canvas.h" 10 11#include <new> 12#include <stdio.h> 13 14#include <Bitmap.h> 15#include <Entry.h> 16#include <Message.h> 17 18#include "Layer.h" 19 20using std::nothrow; 21 22// constructor 23Canvas::Canvas(BRect frame) 24 : BList(10), 25 fBounds(frame) 26{ 27} 28 29// destructor 30Canvas::~Canvas() 31{ 32 MakeEmpty(); 33} 34 35// IsValid 36bool 37Canvas::IsValid() const 38{ 39 return fBounds.IsValid(); 40} 41 42// MakeEmpty 43void 44Canvas::MakeEmpty() 45{ 46 int32 count = CountLayers(); 47 for (int32 i = 0; i < count; i++) 48 delete LayerAtFast(i); 49 BList::MakeEmpty(); 50} 51 52// AddLayer 53bool 54Canvas::AddLayer(Layer* layer) 55{ 56 return AddLayer(layer, CountLayers()); 57} 58 59// AddLayer 60bool 61Canvas::AddLayer(Layer* layer, int32 index) 62{ 63 return layer && AddItem((void*)layer, index); 64} 65 66// RemoveLayer 67Layer* 68Canvas::RemoveLayer(int32 index) 69{ 70 return (Layer*)RemoveItem(index); 71} 72 73// RemoveLayer 74bool 75Canvas::RemoveLayer(Layer* layer) 76{ 77 return RemoveItem((void*)layer); 78} 79 80// LayerAt 81Layer* 82Canvas::LayerAt(int32 index) const 83{ 84 return (Layer*)ItemAt(index); 85} 86 87// LayerAtFast 88Layer* 89Canvas::LayerAtFast(int32 index) const 90{ 91 return (Layer*)ItemAtFast(index); 92} 93 94// IndexOf 95int32 96Canvas::IndexOf(Layer* layer) const 97{ 98 return BList::IndexOf((void*)layer); 99} 100 101// CountLayers 102int32 103Canvas::CountLayers() const 104{ 105 return CountItems(); 106} 107 108// HasLayer 109bool 110Canvas::HasLayer(Layer* layer) const 111{ 112 return HasItem((void*)layer); 113} 114 115// SetBounds 116void 117Canvas::SetBounds(BRect bounds) 118{ 119 if (bounds.IsValid()) 120 fBounds = bounds; 121} 122 123// Bounds 124BRect 125Canvas::Bounds() const 126{ 127 return fBounds; 128} 129 130// Compose 131void 132Canvas::Compose(BBitmap* into, BRect area) const 133{ 134 if (into && into->IsValid() 135 && area.IsValid() && area.Intersects(into->Bounds())) { 136 area = area & into->Bounds(); 137 int32 count = CountLayers(); 138 for (int32 i = count - 1; Layer* layer = LayerAt(i); i--) { 139 layer->Compose(into, area); 140 } 141 } 142} 143 144// Bitmap 145BBitmap* 146Canvas::Bitmap() const 147{ 148 BBitmap* bitmap = new BBitmap(fBounds, 0, B_RGBA32); 149 if (!bitmap->IsValid()) { 150 delete bitmap; 151 return NULL; 152 } 153 154 // this bitmap is uninitialized, clear to black/fully transparent 155 memset(bitmap->Bits(), 0, bitmap->BitsLength()); 156 Compose(bitmap, fBounds); 157 // remove image data where alpha = 0 to improve compression later on 158 uint8* bits = (uint8*)bitmap->Bits(); 159 uint32 bpr = bitmap->BytesPerRow(); 160 uint32 width = bitmap->Bounds().IntegerWidth() + 1; 161 uint32 height = bitmap->Bounds().IntegerHeight() + 1; 162 while (height > 0) { 163 uint8* bitsHandle = bits; 164 for (uint32 x = 0; x < width; x++) { 165 if (!bitsHandle[3]) { 166 bitsHandle[0] = 0; 167 bitsHandle[1] = 0; 168 bitsHandle[2] = 0; 169 } 170 bitsHandle += 4; 171 } 172 bits += bpr; 173 height--; 174 } 175 176 return bitmap; 177} 178 179 180 181static const char* LAYER_KEY = "layer"; 182static const char* BOUNDS_KEY = "bounds"; 183 184// Unarchive 185status_t 186Canvas::Unarchive(const BMessage* archive) 187{ 188 if (!archive) 189 return B_BAD_VALUE; 190 191 // restore bounds 192 BRect bounds; 193 if (archive->FindRect(BOUNDS_KEY, &bounds) < B_OK) 194 return B_ERROR; 195 196 fBounds = bounds; 197 // restore each layer 198 BMessage layerMessage; 199 for (int32 i = 0; 200 archive->FindMessage(LAYER_KEY, i, &layerMessage) == B_OK; 201 i++) { 202 203 Layer* layer = new (nothrow) Layer(); 204 if (!layer || layer->Unarchive(&layerMessage) < B_OK 205 || !AddLayer(layer)) { 206 delete layer; 207 return B_NO_MEMORY; 208 } 209 } 210 211 return B_OK; 212} 213 214