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 33 extern "C" _EXPORT BScreenSaver* 34 instantiate_screen_saver(BMessage* message, image_id image) 35 { 36 return new SpiderSaver(message, image); 37 } 38 39 40 // #pragma mark - SpiderSaver 41 42 43 SpiderSaver::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 77 SpiderSaver::~SpiderSaver() 78 { 79 _Cleanup(); 80 delete[] fQueues; 81 } 82 83 84 void 85 SpiderSaver::StartConfig(BView* view) 86 { 87 SpiderView* configView = new SpiderView(view->Bounds(), this, 88 fQueueNumber, fMaxPolyPoints, fMaxQueueDepth, fColor); 89 view->AddChild(configView); 90 } 91 92 93 status_t 94 SpiderSaver::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 106 void 107 SpiderSaver::StopSaver() 108 { 109 _Cleanup(); 110 } 111 112 113 void 114 SpiderSaver::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 133 status_t 134 SpiderSaver::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 149 void 150 SpiderSaver::SetQueueNumber(uint32 number) 151 { 152 fLocker.Lock(); 153 _Cleanup(); 154 fQueueNumber = number; 155 _Init(fBounds); 156 fLocker.Unlock(); 157 } 158 159 160 void 161 SpiderSaver::SetQueueDepth(uint32 maxDepth) 162 { 163 fLocker.Lock(); 164 _Cleanup(); 165 fMaxQueueDepth = maxDepth; 166 _Init(fBounds); 167 fLocker.Unlock(); 168 } 169 170 171 void 172 SpiderSaver::SetPolyPoints(uint32 maxPoints) 173 { 174 fLocker.Lock(); 175 _Cleanup(); 176 fMaxPolyPoints = maxPoints; 177 _Init(fBounds); 178 fLocker.Unlock(); 179 } 180 181 182 void 183 SpiderSaver::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 196 void 197 SpiderSaver::_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 218 void 219 SpiderSaver::_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 229 void 230 SpiderSaver::_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 258 void 259 SpiderSaver::_FreeBackBitmap() 260 { 261 if (fBackBitmap) { 262 delete fBackBitmap; 263 fBackBitmap = NULL; 264 fBackView = NULL; 265 } 266 } 267 268 269 void 270 SpiderSaver::_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 320 void 321 SpiderSaver::_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