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*
instantiate_screen_saver(BMessage * message,image_id image)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
SpiderSaver(BMessage * message,image_id id)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
~SpiderSaver()77 SpiderSaver::~SpiderSaver()
78 {
79 _Cleanup();
80 delete[] fQueues;
81 }
82
83
84 void
StartConfig(BView * view)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
StartSaver(BView * view,bool preview)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
StopSaver()107 SpiderSaver::StopSaver()
108 {
109 _Cleanup();
110 }
111
112
113 void
Draw(BView * view,int32 frame)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
SaveState(BMessage * into) const134 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
SetQueueNumber(uint32 number)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
SetQueueDepth(uint32 maxDepth)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
SetPolyPoints(uint32 maxPoints)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
SetColor(uint32 color)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
_Init(BRect bounds)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
_Cleanup()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
_AllocBackBitmap(float width,float height)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
_FreeBackBitmap()259 SpiderSaver::_FreeBackBitmap()
260 {
261 if (fBackBitmap) {
262 delete fBackBitmap;
263 fBackBitmap = NULL;
264 fBackView = NULL;
265 }
266 }
267
268
269 void
_DrawInto(BView * view)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
_DrawPolygon(Polygon * polygon,BView * view)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