xref: /haiku/src/add-ons/screen_savers/spider/SpiderSaver.cpp (revision 197c60bf3e2cf8a50510a7bf3155670a64649da8)
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