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