xref: /haiku/src/add-ons/screen_savers/ifs/IFSSaver.cpp (revision 6229115bacb6fe085dcef68cbde071632e05bb68)
1 /*
2  * Copyright (c) 1997 by Massimino Pascal <Pascal.Massimon@ens.fr>
3  * Copyright 2006-2014, Haiku, Inc. All rights reserved.
4  *
5  * Distributed under the terms of the MIT License.
6  *
7  * Authors:
8  *		Stephan Aßmus, superstippi@gmx.de
9  *		Massimino Pascal, Pascal.Massimon@ens.fr
10  *		John Scipione, jscipione@gmail.com
11  */
12 #include <math.h>
13 #include <stdio.h>
14 
15 #include <Catalog.h>
16 #include <CheckBox.h>
17 #include <Slider.h>
18 #include <TextView.h>
19 
20 #include "IFSSaver.h"
21 
22 
23 #undef B_TRANSLATION_CONTEXT
24 #define B_TRANSLATION_CONTEXT "Screensaver IFS"
25 
26 
27 static const uint32 kMsgToggleAdditive		= 'tgad';
28 static const uint32 kMsgSetSpeed			= 'stsp';
29 
30 
31 //	#pragma mark - Instantiation function
32 
33 
34 extern "C" _EXPORT BScreenSaver*
instantiate_screen_saver(BMessage * message,image_id image)35 instantiate_screen_saver(BMessage *message, image_id image)
36 {
37 	return new IFSSaver(message, image);
38 }
39 
40 
41 //	#pragma mark - IFSSaver
42 
43 
IFSSaver(BMessage * message,image_id id)44 IFSSaver::IFSSaver(BMessage* message, image_id id)
45 	:
46 	BScreenSaver(message, id),
47 	BHandler("IFS Saver"),
48 	fIFS(NULL),
49 	fIsPreview(false),
50 	fLastDrawnFrame(0),
51 	fAdditive(false),
52 	fSpeed(6)
53 {
54 	fDirectInfo.bits = NULL;
55 	fDirectInfo.bytesPerRow = 0;
56 
57 	if (message == NULL)
58 		return;
59 
60 	if (message->FindBool("IFS additive", &fAdditive) != B_OK)
61 		fAdditive = false;
62 	if (message->FindInt32("IFS speed", &fSpeed) != B_OK)
63 		fSpeed = 6;
64 }
65 
66 
~IFSSaver()67 IFSSaver::~IFSSaver()
68 {
69 	if (Looper() != NULL)
70 		Looper()->RemoveHandler(this);
71 
72 	_Cleanup();
73 }
74 
75 
76 void
StartConfig(BView * view)77 IFSSaver::StartConfig(BView* view)
78 {
79 	BRect bounds = view->Bounds();
80 	bounds.InsetBy(10.0f, 10.0f);
81 	BRect frame(0.0f, 0.0f, bounds.Width(), 20.0f);
82 
83 	// the additive check box
84 	fAdditiveCB = new BCheckBox(frame, "additive setting",
85 		B_TRANSLATE("Render dots additive"), new BMessage(kMsgToggleAdditive),
86 		B_FOLLOW_LEFT | B_FOLLOW_BOTTOM);
87 
88 	fAdditiveCB->SetValue(fAdditive);
89 
90 	fAdditiveCB->ResizeToPreferred();
91 	bounds.bottom -= fAdditiveCB->Bounds().Height() * 2.0f;
92 	fAdditiveCB->MoveTo(bounds.LeftBottom());
93 
94 	view->AddChild(fAdditiveCB);
95 
96 	// the additive check box
97 	fSpeedS = new BSlider(frame, "speed setting",
98 		B_TRANSLATE("Morphing speed:"), new BMessage(kMsgSetSpeed), 1, 12,
99 		B_BLOCK_THUMB, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM);
100 
101 	fSpeedS->SetValue(fSpeed);
102 	fSpeedS->SetHashMarks(B_HASH_MARKS_BOTTOM);
103 	fSpeedS->SetHashMarkCount(12);
104 
105 	fSpeedS->ResizeToPreferred();
106 	bounds.bottom -= fSpeedS->Bounds().Height() + 15.0f;
107 	fSpeedS->MoveTo(bounds.LeftBottom());
108 
109 	view->AddChild(fSpeedS);
110 
111 	// the info text view
112 	BRect textRect = bounds;
113 	textRect.OffsetTo(0.0, 0.0);
114 	BTextView* textView = new BTextView(bounds, B_EMPTY_STRING, textRect,
115 		B_FOLLOW_ALL, B_WILL_DRAW);
116 	textView->SetViewColor(view->ViewColor());
117 
118 	BString aboutScreenSaver(B_TRANSLATE("%screenSaverName%\n\n"
119 		B_UTF8_COPYRIGHT " 1997 Massimino Pascal\n\n"
120 		"xscreensaver port by Stephan Aßmus\n"
121 		"<stippi@yellowbites.com>"));
122 	BString screenSaverName(B_TRANSLATE("Iterated Function System"));
123 
124 	aboutScreenSaver.ReplaceFirst("%screenSaverName%", screenSaverName);
125 	textView->Insert(aboutScreenSaver);
126 
127 	textView->SetStylable(true);
128 	textView->SetFontAndColor(0, screenSaverName.Length(), be_bold_font);
129 
130 	textView->MakeEditable(false);
131 
132 	view->AddChild(textView);
133 
134 	// make sure we receive messages from the views we added
135 	if (BWindow* window = view->Window())
136 		window->AddHandler(this);
137 
138 	fAdditiveCB->SetTarget(this);
139 	fSpeedS->SetTarget(this);
140 }
141 
142 
143 status_t
StartSaver(BView * view,bool preview)144 IFSSaver::StartSaver(BView* view, bool preview)
145 {
146 	display_mode mode;
147 	BScreen screen(B_MAIN_SCREEN_ID);
148 	screen.GetMode(&mode);
149 	float totalSize = mode.timing.h_total * mode.timing.v_total;
150 	float fps = mode.timing.pixel_clock * 1000.0f / totalSize;
151 
152 	SetTickSize((bigtime_t)floor(1000000.0 / fps + 0.5));
153 
154 	fIsPreview = preview;
155 
156 	if (view == NULL)
157 		return B_BAD_VALUE;
158 
159 	_Init(view->Bounds());
160 	if (fIFS == NULL)
161 		return B_ERROR;
162 
163 	fIFS->SetAdditive(fAdditive || fIsPreview);
164 	fIFS->SetSpeed(fSpeed);
165 
166 	return B_OK;
167 }
168 
169 
170 void
StopSaver()171 IFSSaver::StopSaver()
172 {
173 	_Cleanup();
174 }
175 
176 
177 void
DirectConnected(direct_buffer_info * info)178 IFSSaver::DirectConnected(direct_buffer_info* info)
179 {
180 	int32 request = info->buffer_state & B_DIRECT_MODE_MASK;
181 
182 	switch (request) {
183 		case B_DIRECT_START:
184 			fDirectInfo.bits = info->bits;
185 			fDirectInfo.bytesPerRow = info->bytes_per_row;
186 			fDirectInfo.bits_per_pixel = info->bits_per_pixel;
187 			fDirectInfo.format = info->pixel_format;
188 			fDirectInfo.bounds = info->window_bounds;
189 			break;
190 
191 		case B_DIRECT_STOP:
192 			fDirectInfo.bits = NULL;
193 			break;
194 	}
195 }
196 
197 
198 void
Draw(BView * view,int32 frame)199 IFSSaver::Draw(BView* view, int32 frame)
200 {
201 	if (frame == 0) {
202 		fLastDrawnFrame = -1;
203 		view->SetHighColor(0, 0, 0);
204 		view->FillRect(view->Bounds());
205 	}
206 
207 	int32 frames = frame - fLastDrawnFrame;
208 	if ((fIsPreview || fDirectInfo.bits == NULL) && fLocker.Lock()) {
209 		fIFS->Draw(view, NULL, frames);
210 
211 		fLastDrawnFrame = frame;
212 		fLocker.Unlock();
213 	}
214 }
215 
216 
217 void
DirectDraw(int32 frame)218 IFSSaver::DirectDraw(int32 frame)
219 {
220 	if (frame == 0)
221 		fLastDrawnFrame = -1;
222 
223 	if (!fIsPreview && fDirectInfo.bits != NULL) {
224 		fIFS->Draw(NULL, &fDirectInfo, frame - fLastDrawnFrame);
225 		fLastDrawnFrame = frame;
226 	}
227 }
228 
229 
230 status_t
SaveState(BMessage * into) const231 IFSSaver::SaveState(BMessage* into) const
232 {
233 	status_t ret = B_BAD_VALUE;
234 	if (into != NULL) {
235 		ret = into->AddBool("IFS additive", fAdditive);
236 		if (ret >= B_OK)
237 			ret = into->AddInt32("IFS speed", fSpeed);
238 	}
239 
240 	return ret;
241 }
242 
243 
244 void
MessageReceived(BMessage * message)245 IFSSaver::MessageReceived(BMessage* message)
246 {
247 	switch (message->what) {
248 		case kMsgToggleAdditive:
249 			if (fLocker.Lock() && fIFS != NULL) {
250 				fAdditive = fAdditiveCB->Value() == B_CONTROL_ON;
251 				fIFS->SetAdditive(fAdditive || fIsPreview);
252 				fLocker.Unlock();
253 			}
254 			break;
255 
256 		case kMsgSetSpeed:
257 			if (fLocker.Lock() && fIFS != NULL) {
258 				fSpeed = fSpeedS->Value();
259 				fIFS->SetSpeed(fSpeed);
260 				fLocker.Unlock();
261 			}
262 			break;
263 
264 		default:
265 			BHandler::MessageReceived(message);
266 	}
267 }
268 
269 
270 void
_Init(BRect bounds)271 IFSSaver::_Init(BRect bounds)
272 {
273 	if (fLocker.Lock()) {
274 		delete fIFS;
275 		fIFS = new IFS(bounds);
276 		fLocker.Unlock();
277 	}
278 }
279 
280 
281 void
_Cleanup()282 IFSSaver::_Cleanup()
283 {
284 	if (fLocker.Lock()) {
285 		delete fIFS;
286 		fIFS = NULL;
287 		fLocker.Unlock();
288 	}
289 }
290