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