1/* 2 * Copyright 2007-2014 Haiku, Inc. 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 10#include "SpiderSaver.h" 11 12#include <math.h> 13#include <stdio.h> 14#include <stdlib.h> 15#include <string.h> 16 17#include <Bitmap.h> 18#include <Catalog.h> 19#include <Message.h> 20 21#include "Polygon.h" 22#include "PolygonQueue.h" 23#include "SpiderView.h" 24 25 26#undef B_TRANSLATION_CONTEXT 27#define B_TRANSLATION_CONTEXT "Screensaver Spider" 28 29 30// #pragma mark - Instantiation function 31 32 33extern "C" _EXPORT BScreenSaver* 34instantiate_screen_saver(BMessage* message, image_id image) 35{ 36 return new SpiderSaver(message, image); 37} 38 39 40// #pragma mark - SpiderSaver 41 42 43SpiderSaver::SpiderSaver(BMessage* message, image_id id) 44 : 45 BScreenSaver(message, id), 46 fBackBitmap(NULL), 47 fBackView(NULL), 48 fQueues(new PolygonQueue*[MAX_QUEUE_NUMBER]), 49 fQueueNumber(20), 50 fMaxPolyPoints(MAX_POLY_POINTS), 51 fMaxQueueDepth(MAX_QUEUE_DEPTH), 52 fColor(RED), 53 fPreview(false) 54{ 55 for (int32 i = 0; i < MAX_QUEUE_NUMBER; i++) 56 fQueues[i] = NULL; 57 58 if (message != NULL) { 59 int32 value; 60 if (message->FindInt32("queue number", &value) == B_OK) 61 fQueueNumber = value; 62 63 if (message->FindInt32("poly points", &value) == B_OK) 64 fMaxPolyPoints = value; 65 66 if (message->FindInt32("queue depth", &value) == B_OK) 67 fMaxQueueDepth = value; 68 69 if (message->FindInt32("color", &value) == B_OK) 70 fColor = value; 71 } 72 73 srand48((long int)system_time()); 74} 75 76 77SpiderSaver::~SpiderSaver() 78{ 79 _Cleanup(); 80 delete[] fQueues; 81} 82 83 84void 85SpiderSaver::StartConfig(BView* view) 86{ 87 SpiderView* configView = new SpiderView(view->Bounds(), this, 88 fQueueNumber, fMaxPolyPoints, fMaxQueueDepth, fColor); 89 view->AddChild(configView); 90} 91 92 93status_t 94SpiderSaver::StartSaver(BView* view, bool preview) 95{ 96 SetTickSize(50000); 97 98 fPreview = preview; 99 fBounds = view->Bounds(); 100 _Init(fBounds); 101 102 return B_OK; 103} 104 105 106void 107SpiderSaver::StopSaver() 108{ 109 _Cleanup(); 110} 111 112 113void 114SpiderSaver::Draw(BView* view, int32 frame) 115{ 116 fLocker.Lock(); 117 for (uint32 i = 0; i < fQueueNumber; i++) { 118 if (fQueues[i]) 119 fQueues[i]->Step(); 120 } 121 if (fBackView) { 122 if (fBackBitmap->Lock()) { 123 _DrawInto(fBackView); 124 fBackView->Sync(); 125 fBackBitmap->Unlock(); 126 } 127 view->DrawBitmap(fBackBitmap, BPoint(0.0, 0.0)); 128 } 129 fLocker.Unlock(); 130} 131 132 133status_t 134SpiderSaver::SaveState(BMessage* into) const 135{ 136 if (into != NULL) { 137 into->AddInt32("queue number", (int32)fQueueNumber); 138 into->AddInt32("poly points", (int32)fMaxPolyPoints); 139 into->AddInt32("queue depth", (int32)fMaxQueueDepth); 140 into->AddInt32("color", (int32)fColor); 141 142 return B_OK; 143 } 144 145 return B_BAD_VALUE; 146} 147 148 149void 150SpiderSaver::SetQueueNumber(uint32 number) 151{ 152 fLocker.Lock(); 153 _Cleanup(); 154 fQueueNumber = number; 155 _Init(fBounds); 156 fLocker.Unlock(); 157} 158 159 160void 161SpiderSaver::SetQueueDepth(uint32 maxDepth) 162{ 163 fLocker.Lock(); 164 _Cleanup(); 165 fMaxQueueDepth = maxDepth; 166 _Init(fBounds); 167 fLocker.Unlock(); 168} 169 170 171void 172SpiderSaver::SetPolyPoints(uint32 maxPoints) 173{ 174 fLocker.Lock(); 175 _Cleanup(); 176 fMaxPolyPoints = maxPoints; 177 _Init(fBounds); 178 fLocker.Unlock(); 179} 180 181 182void 183SpiderSaver::SetColor(uint32 color) 184{ 185 fLocker.Lock(); 186 _Cleanup(); 187 fColor = color; 188 _Init(fBounds); 189 fLocker.Unlock(); 190} 191 192 193// #pragma mark - SpiderSaver private methods 194 195 196void 197SpiderSaver::_Init(BRect bounds) 198{ 199 _AllocBackBitmap(bounds.Width(), bounds.Height()); 200 uint32 minPoints = fMaxPolyPoints / 2; 201 uint32 maxPoints = fMaxPolyPoints; 202 uint32 minQueueDepth = fMaxQueueDepth / 2; 203 uint32 maxQueueDepth = fMaxQueueDepth; 204 205 if (fPreview) { 206 minQueueDepth /= 4; 207 maxQueueDepth /= 4; 208 } 209 210 for (uint32 i = 0; i < fQueueNumber; i++) { 211 fQueues[i] = new PolygonQueue(new Polygon(bounds, 212 minPoints + lrand48() % (maxPoints - minPoints)), 213 minQueueDepth + lrand48() % (maxQueueDepth - minQueueDepth)); 214 } 215} 216 217 218void 219SpiderSaver::_Cleanup() 220{ 221 _FreeBackBitmap(); 222 for (int32 i = 0; i < MAX_QUEUE_NUMBER; i++) { 223 delete fQueues[i]; 224 fQueues[i] = NULL; 225 } 226} 227 228 229void 230SpiderSaver::_AllocBackBitmap(float width, float height) 231{ 232 // sanity check 233 if (width <= 0.0 || height <= 0.0) 234 return; 235 236 BRect b(0.0, 0.0, width, height); 237 fBackBitmap = new(std::nothrow) BBitmap(b, B_RGB32, true); 238 if (!fBackBitmap) 239 return; 240 241 if (fBackBitmap->IsValid()) { 242 fBackView = new(std::nothrow) BView(b, 0, B_FOLLOW_NONE, B_WILL_DRAW); 243 if (fBackView == NULL) { 244 _FreeBackBitmap(); 245 fprintf(stderr, 246 "SpiderSaver::_AllocBackBitmap(): view allocation failed\n"); 247 return; 248 } 249 fBackBitmap->AddChild(fBackView); 250 memset(fBackBitmap->Bits(), 0, fBackBitmap->BitsLength()); 251 } else { 252 _FreeBackBitmap(); 253 fprintf(stderr, "SpiderSaver::_AllocBackBitmap(): bitmap invalid\n"); 254 } 255} 256 257 258void 259SpiderSaver::_FreeBackBitmap() 260{ 261 if (fBackBitmap) { 262 delete fBackBitmap; 263 fBackBitmap = NULL; 264 fBackView = NULL; 265 } 266} 267 268 269void 270SpiderSaver::_DrawInto(BView* view) 271{ 272 for (uint32 i = 0; i < fQueueNumber; i++) { 273 switch (fColor) { 274 case GREEN: 275 view->SetHighColor(1, 2, 1, 255); 276 break; 277 278 case BLUE: 279 view->SetHighColor(1, 1, 2, 255); 280 break; 281 282 case YELLOW: 283 view->SetHighColor(2, 2, 1, 255); 284 break; 285 286 case PURPLE: 287 view->SetHighColor(2, 1, 2, 255); 288 break; 289 290 case CYAN: 291 view->SetHighColor(1, 2, 2, 255); 292 break; 293 294 case GRAY: 295 view->SetHighColor(2, 2, 2, 255); 296 break; 297 298 case RED: 299 default: 300 view->SetHighColor(2, 1, 1, 255); 301 break; 302 } 303 304 if (fQueues[i] == NULL) 305 continue; 306 307 if (Polygon* p = fQueues[i]->Head()) { 308 view->SetDrawingMode(B_OP_ADD); 309 _DrawPolygon(p, view); 310 } 311 312 if (Polygon* p = fQueues[i]->Tail()) { 313 view->SetDrawingMode(B_OP_SUBTRACT); 314 _DrawPolygon(p, view); 315 } 316 } 317} 318 319 320void 321SpiderSaver::_DrawPolygon(Polygon* polygon, BView* view) 322{ 323 int32 pointCount = polygon->CountPoints(); 324 if (pointCount > 1) { 325 BPoint p = polygon->PointAt(0); 326 view->MovePenTo(p); 327 for (int32 i = 1; i < pointCount; i++) 328 view->StrokeLine(polygon->PointAt(i)); 329 330 view->StrokeLine(p); 331 } 332} 333