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