File: | src/add-ons/screen_savers/spider/SpiderSaver.cpp |
Location: | line 296, column 20 |
Description: | Called C++ object pointer is null |
1 | /* | |||
2 | * Copyright 2007-2009, 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 | #include "SpiderSaver.h" | |||
9 | ||||
10 | #include <math.h> | |||
11 | #include <stdio.h> | |||
12 | #include <stdlib.h> | |||
13 | #include <string.h> | |||
14 | ||||
15 | #include <Bitmap.h> | |||
16 | #include <Catalog.h> | |||
17 | #include <Message.h> | |||
18 | #include <Menu.h> | |||
19 | #include <MenuField.h> | |||
20 | #include <MenuItem.h> | |||
21 | #include <Slider.h> | |||
22 | #include <StringView.h> | |||
23 | ||||
24 | #include "Polygon.h" | |||
25 | #include "PolygonQueue.h" | |||
26 | ||||
27 | #undef B_TRANSLATION_CONTEXT"Screensaver Spider" | |||
28 | #define B_TRANSLATION_CONTEXT"Screensaver Spider" "Screensaver Spider" | |||
29 | ||||
30 | enum { | |||
31 | MSG_QUEUE_NUMBER = 'qunm', | |||
32 | MSG_POLY_NUMBER = 'plnm', | |||
33 | MSG_QUEUE_DEPTH = 'qudp', | |||
34 | MSG_COLOR = 'colr', | |||
35 | }; | |||
36 | ||||
37 | #define MIN_POLY_POINTS3 3 | |||
38 | #define MAX_POLY_POINTS10 10 | |||
39 | #define MIN_QUEUE_DEPTH40 40 | |||
40 | #define MAX_QUEUE_DEPTH160 160 | |||
41 | #define MAX_QUEUE_NUMBER40 40 | |||
42 | ||||
43 | enum { | |||
44 | RED = 1, | |||
45 | GREEN = 2, | |||
46 | BLUE = 3, | |||
47 | YELLOW = 4, | |||
48 | PURPLE = 5, | |||
49 | CYAN = 6, | |||
50 | GRAY = 7, | |||
51 | }; | |||
52 | ||||
53 | // MAIN INSTANTIATION FUNCTION | |||
54 | extern "C" _EXPORT BScreenSaver* | |||
55 | instantiate_screen_saver(BMessage *message, image_id image) | |||
56 | { | |||
57 | return new SpiderSaver(message, image); | |||
58 | } | |||
59 | ||||
60 | // constructor | |||
61 | SpiderSaver::SpiderSaver(BMessage *message, image_id id) | |||
62 | : BScreenSaver(message, id), | |||
63 | fBackBitmap(NULL__null), | |||
64 | fBackView(NULL__null), | |||
65 | fQueues(new PolygonQueue*[MAX_QUEUE_NUMBER40]), | |||
66 | fQueueNumber(20), | |||
67 | fMaxPolyPoints(MAX_POLY_POINTS10), | |||
68 | fMaxQueueDepth(MAX_QUEUE_DEPTH160), | |||
69 | fColor(RED) | |||
70 | { | |||
71 | for (int32 i = 0; i < MAX_QUEUE_NUMBER40; i++) | |||
72 | fQueues[i] = NULL__null; | |||
73 | if (message) { | |||
74 | int32 value; | |||
75 | if (message->FindInt32("queue number", &value) == B_OK((int)0)) | |||
76 | fQueueNumber = value; | |||
77 | if (message->FindInt32("poly points", &value) == B_OK((int)0)) | |||
78 | fMaxPolyPoints = value; | |||
79 | if (message->FindInt32("queue depth", &value) == B_OK((int)0)) | |||
80 | fMaxQueueDepth = value; | |||
81 | if (message->FindInt32("color", &value) == B_OK((int)0)) | |||
82 | fColor = value; | |||
83 | } | |||
84 | srand48((long int)system_time()); | |||
85 | } | |||
86 | ||||
87 | // destructor | |||
88 | SpiderSaver::~SpiderSaver() | |||
89 | { | |||
90 | _Cleanup(); | |||
91 | delete[] fQueues; | |||
92 | } | |||
93 | ||||
94 | // StartConfig | |||
95 | void | |||
96 | SpiderSaver::StartConfig(BView *view) | |||
97 | { | |||
98 | SpiderView* configView = new SpiderView(view->Bounds(), this, | |||
99 | fQueueNumber, fMaxPolyPoints, fMaxQueueDepth, fColor); | |||
100 | view->AddChild(configView); | |||
101 | } | |||
102 | ||||
103 | // StartSaver | |||
104 | status_t | |||
105 | SpiderSaver::StartSaver(BView *v, bool preview) | |||
106 | { | |||
107 | SetTickSize(50000); | |||
108 | ||||
109 | fPreview = preview; | |||
110 | fBounds = v->Bounds(); | |||
111 | _Init(fBounds); | |||
112 | ||||
113 | return B_OK((int)0); | |||
114 | } | |||
115 | ||||
116 | // StopSaver | |||
117 | void | |||
118 | SpiderSaver::StopSaver() | |||
119 | { | |||
120 | _Cleanup(); | |||
121 | } | |||
122 | ||||
123 | // Draw | |||
124 | void | |||
125 | SpiderSaver::Draw(BView *view, int32 frame) | |||
126 | { | |||
127 | fLocker.Lock(); | |||
128 | for (uint32 i = 0; i < fQueueNumber; i++) { | |||
| ||||
129 | if (fQueues[i]) | |||
130 | fQueues[i]->Step(); | |||
131 | } | |||
132 | if (fBackView) { | |||
133 | if (fBackBitmap->Lock()) { | |||
134 | _DrawInto(fBackView); | |||
135 | fBackView->Sync(); | |||
136 | fBackBitmap->Unlock(); | |||
137 | } | |||
138 | view->DrawBitmap(fBackBitmap, BPoint(0.0, 0.0)); | |||
139 | } | |||
140 | fLocker.Unlock(); | |||
141 | } | |||
142 | ||||
143 | // SaveState | |||
144 | status_t | |||
145 | SpiderSaver::SaveState(BMessage* into) const | |||
146 | { | |||
147 | if (into) { | |||
148 | into->AddInt32("queue number", (int32)fQueueNumber); | |||
149 | into->AddInt32("poly points", (int32)fMaxPolyPoints); | |||
150 | into->AddInt32("queue depth", (int32)fMaxQueueDepth); | |||
151 | into->AddInt32("color", (int32)fColor); | |||
152 | return B_OK((int)0); | |||
153 | } | |||
154 | return B_BAD_VALUE((-2147483647 - 1) + 5); | |||
155 | } | |||
156 | ||||
157 | // SetQueueNumber | |||
158 | void | |||
159 | SpiderSaver::SetQueueNumber(uint32 number) | |||
160 | { | |||
161 | fLocker.Lock(); | |||
162 | _Cleanup(); | |||
163 | fQueueNumber = number; | |||
164 | _Init(fBounds); | |||
165 | fLocker.Unlock(); | |||
166 | } | |||
167 | ||||
168 | // SetQueueDepth | |||
169 | void | |||
170 | SpiderSaver::SetQueueDepth(uint32 maxDepth) | |||
171 | { | |||
172 | fLocker.Lock(); | |||
173 | _Cleanup(); | |||
174 | fMaxQueueDepth = maxDepth; | |||
175 | _Init(fBounds); | |||
176 | fLocker.Unlock(); | |||
177 | } | |||
178 | ||||
179 | // SetPolyPoints | |||
180 | void | |||
181 | SpiderSaver::SetPolyPoints(uint32 maxPoints) | |||
182 | { | |||
183 | fLocker.Lock(); | |||
184 | _Cleanup(); | |||
185 | fMaxPolyPoints = maxPoints; | |||
186 | _Init(fBounds); | |||
187 | fLocker.Unlock(); | |||
188 | } | |||
189 | ||||
190 | // SetColor | |||
191 | void | |||
192 | SpiderSaver::SetColor(uint32 color) | |||
193 | { | |||
194 | fLocker.Lock(); | |||
195 | _Cleanup(); | |||
196 | fColor = color; | |||
197 | _Init(fBounds); | |||
198 | fLocker.Unlock(); | |||
199 | } | |||
200 | ||||
201 | // _Init | |||
202 | void | |||
203 | SpiderSaver::_Init(BRect bounds) | |||
204 | { | |||
205 | _AllocBackBitmap(bounds.Width(), bounds.Height()); | |||
206 | uint32 minPoints = fMaxPolyPoints / 2; | |||
207 | uint32 maxPoints = fMaxPolyPoints; | |||
208 | uint32 minQueueDepth = fMaxQueueDepth / 2; | |||
209 | uint32 maxQueueDepth = fMaxQueueDepth; | |||
210 | if (fPreview) { | |||
211 | minQueueDepth /= 4; | |||
212 | maxQueueDepth /= 4; | |||
213 | } | |||
214 | for (uint32 i = 0; i < fQueueNumber; i++) | |||
215 | fQueues[i] = new PolygonQueue(new Polygon(bounds, minPoints | |||
216 | + lrand48() | |||
217 | % (maxPoints | |||
218 | - minPoints)), | |||
219 | minQueueDepth + lrand48() % (maxQueueDepth | |||
220 | - minQueueDepth)); | |||
221 | } | |||
222 | ||||
223 | // _Cleanup | |||
224 | void | |||
225 | SpiderSaver::_Cleanup() | |||
226 | { | |||
227 | _FreeBackBitmap(); | |||
228 | for (int32 i = 0; i < MAX_QUEUE_NUMBER40; i++) { | |||
229 | delete fQueues[i]; | |||
230 | fQueues[i] = NULL__null; | |||
231 | } | |||
232 | } | |||
233 | ||||
234 | // _AllocBackBitmap | |||
235 | void | |||
236 | SpiderSaver::_AllocBackBitmap(float width, float height) | |||
237 | { | |||
238 | // sanity check | |||
239 | if (width <= 0.0 || height <= 0.0) | |||
240 | return; | |||
241 | ||||
242 | BRect b(0.0, 0.0, width, height); | |||
243 | fBackBitmap = new BBitmap(b, B_RGB32, true); | |||
244 | if (!fBackBitmap) | |||
245 | return; | |||
246 | if (fBackBitmap->IsValid()) { | |||
247 | fBackView = new BView(b, 0, B_FOLLOW_NONE0, B_WILL_DRAW); | |||
248 | fBackBitmap->AddChild(fBackView); | |||
249 | memset(fBackBitmap->Bits(), 0, fBackBitmap->BitsLength()); | |||
250 | } else { | |||
251 | _FreeBackBitmap(); | |||
252 | fprintf(stderr, "SpiderSaver::_AllocBackBitmap(): bitmap invalid\n"); | |||
253 | } | |||
254 | } | |||
255 | ||||
256 | // _FreeBackBitmap | |||
257 | void | |||
258 | SpiderSaver::_FreeBackBitmap() | |||
259 | { | |||
260 | if (fBackBitmap) { | |||
261 | delete fBackBitmap; | |||
262 | fBackBitmap = NULL__null; | |||
263 | fBackView = NULL__null; | |||
264 | } | |||
265 | } | |||
266 | ||||
267 | // _DrawInto | |||
268 | void | |||
269 | SpiderSaver::_DrawInto(BView *view) | |||
270 | { | |||
271 | for (uint32 i = 0; i < fQueueNumber; i++) { | |||
272 | switch (fColor) { | |||
273 | case GREEN: | |||
274 | view->SetHighColor(1, 2, 1, 255); | |||
275 | break; | |||
276 | case BLUE: | |||
277 | view->SetHighColor(1, 1, 2, 255); | |||
278 | break; | |||
279 | case YELLOW: | |||
280 | view->SetHighColor(2, 2, 1, 255); | |||
281 | break; | |||
282 | case PURPLE: | |||
283 | view->SetHighColor(2, 1, 2, 255); | |||
284 | break; | |||
285 | case CYAN: | |||
286 | view->SetHighColor(1, 2, 2, 255); | |||
287 | break; | |||
288 | case GRAY: | |||
289 | view->SetHighColor(2, 2, 2, 255); | |||
290 | break; | |||
291 | case RED: | |||
292 | default: | |||
293 | view->SetHighColor(2, 1, 1, 255); | |||
294 | break; | |||
295 | } | |||
296 | if (Polygon* p = fQueues[i]->Head()) { | |||
| ||||
297 | view->SetDrawingMode(B_OP_ADD); | |||
298 | _DrawPolygon(p, view); | |||
299 | } | |||
300 | if (Polygon* p = fQueues[i]->Tail()) { | |||
301 | view->SetDrawingMode(B_OP_SUBTRACT); | |||
302 | _DrawPolygon(p, view); | |||
303 | } | |||
304 | } | |||
305 | } | |||
306 | ||||
307 | // _DrawPolygon | |||
308 | void | |||
309 | SpiderSaver::_DrawPolygon(Polygon* polygon, BView *view) | |||
310 | { | |||
311 | int32 pointCount = polygon->CountPoints(); | |||
312 | if (pointCount > 1) { | |||
313 | BPoint p = polygon->PointAt(0); | |||
314 | view->MovePenTo(p); | |||
315 | for (int32 i = 1; i < pointCount; i++) | |||
316 | view->StrokeLine(polygon->PointAt(i)); | |||
317 | view->StrokeLine(p); | |||
318 | } | |||
319 | } | |||
320 | ||||
321 | // constructor | |||
322 | SpiderView::SpiderView(BRect frame, SpiderSaver* saver, | |||
323 | uint32 queueNumber, uint32 maxPolyPoints, | |||
324 | uint32 maxQueueDepth, uint32 color) | |||
325 | : BView(frame, "spider view", B_FOLLOW_NONE0, B_WILL_DRAW | B_PULSE_NEEDED), | |||
326 | fSaver(saver) | |||
327 | { | |||
328 | SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); | |||
329 | ||||
330 | frame.OffsetTo(0.0, 0.0); | |||
331 | frame.InsetBy(10.0, 5.0); | |||
332 | ||||
333 | float viewHeight = floorf(frame.Height() / 5.0); | |||
334 | ||||
335 | // title stuff | |||
336 | font_height fh; | |||
337 | be_bold_font->GetHeight(&fh); | |||
338 | float fontHeight = fh.ascent + fh.descent + 5.0; | |||
339 | frame.bottom = frame.top + fontHeight; | |||
340 | BStringView* title = new BStringView(frame, B_EMPTY_STRING, | |||
341 | B_TRANSLATE("Spider by stippi")BLocaleRoster::Default()->GetCatalog()->GetString(("Spider by stippi" ), "Screensaver Spider")); | |||
342 | title->SetFont(be_bold_font); | |||
343 | AddChild(title); | |||
344 | ||||
345 | be_plain_font->GetHeight(&fh); | |||
346 | fontHeight = fh.ascent + fh.descent + 5.0; | |||
347 | frame.top = frame.bottom; | |||
348 | frame.bottom = frame.top + fontHeight; | |||
349 | title = new BStringView(frame, B_EMPTY_STRING, B_TRANSLATE("for bonefish")BLocaleRoster::Default()->GetCatalog()->GetString(("for bonefish" ), "Screensaver Spider")); | |||
350 | BFont font(be_plain_font); | |||
351 | font.SetShear(110.0); | |||
352 | title->SetFont(&font); | |||
353 | title->SetAlignment(B_ALIGN_CENTER); | |||
354 | AddChild(title); | |||
355 | ||||
356 | // controls | |||
357 | frame.top = 10.0; | |||
358 | frame.bottom = frame.top + viewHeight; | |||
359 | frame.OffsetBy(0.0, viewHeight); | |||
360 | fQueueNumberS = new BSlider(frame, "queue number", | |||
361 | B_TRANSLATE("Max. polygon count")BLocaleRoster::Default()->GetCatalog()->GetString(("Max. polygon count" ), "Screensaver Spider"), new BMessage(MSG_QUEUE_NUMBER), | |||
362 | 1, MAX_QUEUE_NUMBER40); | |||
363 | fQueueNumberS->SetHashMarks(B_HASH_MARKS_BOTTOM); | |||
364 | fQueueNumberS->SetHashMarkCount((MAX_QUEUE_NUMBER40 - 1) / 2 + 1); | |||
365 | fQueueNumberS->SetValue(queueNumber); | |||
366 | AddChild(fQueueNumberS); | |||
367 | frame.OffsetBy(0.0, viewHeight); | |||
368 | fPolyNumberS = new BSlider(frame, "poly points", | |||
369 | B_TRANSLATE("Max. points per polygon")BLocaleRoster::Default()->GetCatalog()->GetString(("Max. points per polygon" ), "Screensaver Spider"), new BMessage(MSG_POLY_NUMBER), | |||
370 | MIN_POLY_POINTS3, MAX_POLY_POINTS10); | |||
371 | fPolyNumberS->SetHashMarks(B_HASH_MARKS_BOTTOM); | |||
372 | fPolyNumberS->SetHashMarkCount(MAX_POLY_POINTS10 - MIN_POLY_POINTS3 + 1); | |||
373 | fPolyNumberS->SetValue(maxPolyPoints); | |||
374 | AddChild(fPolyNumberS); | |||
375 | frame.OffsetBy(0.0, viewHeight); | |||
376 | fQueueDepthS = new BSlider(frame, "queue depth", B_TRANSLATE("Trail depth")BLocaleRoster::Default()->GetCatalog()->GetString(("Trail depth" ), "Screensaver Spider"), | |||
377 | new BMessage(MSG_QUEUE_DEPTH), MIN_QUEUE_DEPTH40, MAX_QUEUE_DEPTH160); | |||
378 | fQueueDepthS->SetHashMarks(B_HASH_MARKS_BOTTOM); | |||
379 | fQueueDepthS->SetHashMarkCount((MAX_QUEUE_DEPTH160 - MIN_QUEUE_DEPTH40) / 4 + 1); | |||
380 | fQueueDepthS->SetValue(maxQueueDepth); | |||
381 | AddChild(fQueueDepthS); | |||
382 | ||||
383 | BMenu* menu = new BMenu(B_TRANSLATE("Color")BLocaleRoster::Default()->GetCatalog()->GetString(("Color" ), "Screensaver Spider")); | |||
384 | BMessage* message = new BMessage(MSG_COLOR); | |||
385 | message->AddInt32("color", RED); | |||
386 | BMenuItem* item = new BMenuItem(B_TRANSLATE("Red")BLocaleRoster::Default()->GetCatalog()->GetString(("Red" ), "Screensaver Spider"), message); | |||
387 | if (color == RED) | |||
388 | item->SetMarked(true); | |||
389 | menu->AddItem(item); | |||
390 | message = new BMessage(MSG_COLOR); | |||
391 | message->AddInt32("color", GREEN); | |||
392 | item = new BMenuItem(B_TRANSLATE("Green")BLocaleRoster::Default()->GetCatalog()->GetString(("Green" ), "Screensaver Spider"), message); | |||
393 | if (color == GREEN) | |||
394 | item->SetMarked(true); | |||
395 | menu->AddItem(item); | |||
396 | message = new BMessage(MSG_COLOR); | |||
397 | message->AddInt32("color", BLUE); | |||
398 | item = new BMenuItem(B_TRANSLATE("Blue")BLocaleRoster::Default()->GetCatalog()->GetString(("Blue" ), "Screensaver Spider"), message); | |||
399 | if (color == BLUE) | |||
400 | item->SetMarked(true); | |||
401 | menu->AddItem(item); | |||
402 | message = new BMessage(MSG_COLOR); | |||
403 | message->AddInt32("color", YELLOW); | |||
404 | item = new BMenuItem(B_TRANSLATE("Yellow")BLocaleRoster::Default()->GetCatalog()->GetString(("Yellow" ), "Screensaver Spider"), message); | |||
405 | if (color == YELLOW) | |||
406 | item->SetMarked(true); | |||
407 | menu->AddItem(item); | |||
408 | message = new BMessage(MSG_COLOR); | |||
409 | message->AddInt32("color", PURPLE); | |||
410 | item = new BMenuItem(B_TRANSLATE("Purple")BLocaleRoster::Default()->GetCatalog()->GetString(("Purple" ), "Screensaver Spider"), message); | |||
411 | if (color == PURPLE) | |||
412 | item->SetMarked(true); | |||
413 | menu->AddItem(item); | |||
414 | message = new BMessage(MSG_COLOR); | |||
415 | message->AddInt32("color", CYAN); | |||
416 | item = new BMenuItem(B_TRANSLATE("Cyan")BLocaleRoster::Default()->GetCatalog()->GetString(("Cyan" ), "Screensaver Spider"), message); | |||
417 | if (color == CYAN) | |||
418 | item->SetMarked(true); | |||
419 | menu->AddItem(item); | |||
420 | message = new BMessage(MSG_COLOR); | |||
421 | message->AddInt32("color", GRAY); | |||
422 | item = new BMenuItem(B_TRANSLATE("Gray")BLocaleRoster::Default()->GetCatalog()->GetString(("Gray" ), "Screensaver Spider"), message); | |||
423 | if (color == GRAY) | |||
424 | item->SetMarked(true); | |||
425 | menu->AddItem(item); | |||
426 | ||||
427 | menu->SetLabelFromMarked(true); | |||
428 | menu->SetRadioMode(true); | |||
429 | ||||
430 | frame.OffsetBy(0.0, viewHeight); | |||
431 | fColorMF = new BMenuField(frame, "color", B_TRANSLATE("Color")BLocaleRoster::Default()->GetCatalog()->GetString(("Color" ), "Screensaver Spider"), menu); | |||
432 | fColorMF->SetDivider(fColorMF->StringWidth(B_TRANSLATE("Color")BLocaleRoster::Default()->GetCatalog()->GetString(("Color" ), "Screensaver Spider")) + 5.0); | |||
433 | AddChild(fColorMF); | |||
434 | } | |||
435 | ||||
436 | // destructor | |||
437 | SpiderView::~SpiderView() | |||
438 | { | |||
439 | } | |||
440 | ||||
441 | // AttachedToWindow | |||
442 | void | |||
443 | SpiderView::AttachedToWindow() | |||
444 | { | |||
445 | fQueueNumberS->SetTarget(this); | |||
446 | fPolyNumberS->SetTarget(this); | |||
447 | fQueueDepthS->SetTarget(this); | |||
448 | fColorMF->Menu()->SetTargetForItems(this); | |||
449 | } | |||
450 | ||||
451 | // MessageReceived | |||
452 | void | |||
453 | SpiderView::MessageReceived(BMessage* message) | |||
454 | { | |||
455 | switch (message->what) { | |||
456 | case MSG_QUEUE_NUMBER: | |||
457 | fSaver->SetQueueNumber(fQueueNumberS->Value()); | |||
458 | break; | |||
459 | case MSG_POLY_NUMBER: | |||
460 | fSaver->SetPolyPoints(fPolyNumberS->Value()); | |||
461 | break; | |||
462 | case MSG_QUEUE_DEPTH: | |||
463 | fSaver->SetQueueDepth(fQueueDepthS->Value()); | |||
464 | break; | |||
465 | case MSG_COLOR: { | |||
466 | uint32 color; | |||
467 | if (message->FindInt32("color", (int32*)&color) == B_OK((int)0)) | |||
468 | fSaver->SetColor(color); | |||
469 | break; | |||
470 | } | |||
471 | default: | |||
472 | BView::MessageReceived(message); | |||
473 | break; | |||
474 | } | |||
475 | } | |||
476 |