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_TRANSLATION_CONTEXT 15 #define B_TRANSLATION_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 107 BString aboutScreenSaver(B_TRANSLATE("%screenSaverName%\n\n" 108 ""B_UTF8_COPYRIGHT" 1997 Massimino Pascal\n\n" 109 "xscreensaver port by Stephan Aßmus\n" 110 "<stippi@yellowbites.com>")); 111 BString screenSaverName(B_TRANSLATE("Iterated Function System")); 112 113 aboutScreenSaver.ReplaceFirst("%screenSaverName%", screenSaverName); 114 textView->Insert(aboutScreenSaver); 115 116 textView->SetStylable(true); 117 textView->SetFontAndColor(0, screenSaverName.Length(), be_bold_font); 118 // textView->SetFontAndColor(25, 255, be_plain_font); 119 120 textView->MakeEditable(false); 121 122 view->AddChild(textView); 123 124 // make sure we receive messages from the views we added 125 if (BWindow* window = view->Window()) 126 window->AddHandler(this); 127 128 fAdditiveCB->SetTarget(this); 129 fSpeedS->SetTarget(this); 130 } 131 132 // StartSaver 133 status_t 134 IFSSaver::StartSaver(BView *v, bool preview) 135 { 136 display_mode mode; 137 BScreen screen(B_MAIN_SCREEN_ID); 138 screen.GetMode(&mode); 139 float totalSize = mode.timing.h_total * mode.timing.v_total; 140 float fps = mode.timing.pixel_clock * 1000.0 / totalSize; 141 142 //printf("ticks per frame: %lldµs\n", (int64)floor(1000000.0 / fps + 0.5)); 143 SetTickSize((int64)floor(1000000.0 / fps + 0.5)); 144 145 fIsPreview = preview; 146 fBounds = v->Bounds(); 147 148 _Init(fBounds); 149 fIFS->SetAdditive(fIsPreview || fAdditive); 150 fIFS->SetSpeed(fSpeed); 151 152 return B_OK; 153 } 154 155 // StopSaver 156 void 157 IFSSaver::StopSaver() 158 { 159 _Cleanup(); 160 } 161 162 // DirectConnected 163 void 164 IFSSaver::DirectConnected(direct_buffer_info* info) 165 { 166 //printf("IFSSaver::DirectConnected()\n"); 167 int32 request = info->buffer_state & B_DIRECT_MODE_MASK; 168 switch (request) { 169 case B_DIRECT_START: 170 //printf("B_DIRECT_START\n"); 171 //printf(" bits_per_pixel: %ld\n", info->bits_per_pixel); 172 //printf(" bytes_per_row: %ld\n", info->bytes_per_row); 173 //printf(" pixel_format: %d\n", info->pixel_format); 174 //printf(" window_bounds: (%ld, %ld, %ld, %ld)\n", 175 // info->window_bounds.left, info->window_bounds.top, 176 // info->window_bounds.right, info->window_bounds.bottom); 177 fDirectInfo.bits = info->bits; 178 fDirectInfo.bytesPerRow = info->bytes_per_row; 179 fDirectInfo.bits_per_pixel = info->bits_per_pixel; 180 fDirectInfo.format = info->pixel_format; 181 fDirectInfo.bounds = info->window_bounds; 182 break; 183 case B_DIRECT_STOP: 184 fDirectInfo.bits = NULL; 185 break; 186 default: 187 break; 188 } 189 //printf("bits: %p\n", fDirectInfo.bits); 190 } 191 192 // Draw 193 void 194 IFSSaver::Draw(BView *view, int32 frame) 195 { 196 //printf("IFSSaver::Draw(%ld) (%ldx%ld)\n", frame, view->Bounds().IntegerWidth() + 1, view->Bounds().IntegerHeight() + 1); 197 if (frame == 0) { 198 fLastDrawnFrame = -1; 199 view->SetHighColor(0, 0, 0); 200 view->FillRect(view->Bounds()); 201 } 202 int32 frames = frame - fLastDrawnFrame; 203 if ((fIsPreview || fDirectInfo.bits == NULL) && fLocker.Lock()) { 204 fIFS->Draw(view, NULL, frames); 205 206 fLastDrawnFrame = frame; 207 fLocker.Unlock(); 208 } 209 } 210 211 // DirectDraw 212 void 213 IFSSaver::DirectDraw(int32 frame) 214 { 215 //bigtime_t now = system_time(); 216 //printf("IFSSaver::DirectDraw(%ld)\n", frame); 217 if (frame == 0) 218 fLastDrawnFrame = -1; 219 int32 frames = frame - fLastDrawnFrame; 220 if (fDirectInfo.bits) { 221 fIFS->Draw(NULL, &fDirectInfo, frames); 222 //printf("DirectDraw(): %lldµs\n", system_time() - now); 223 fLastDrawnFrame = frame; 224 } 225 } 226 227 // SaveState 228 status_t 229 IFSSaver::SaveState(BMessage* into) const 230 { 231 status_t ret = B_BAD_VALUE; 232 if (into) { 233 ret = into->AddBool("IFS additive", fAdditive); 234 if (ret >= B_OK) 235 ret = into->AddInt32("IFS speed", fSpeed); 236 } 237 return ret; 238 } 239 240 // MessageReceived 241 void 242 IFSSaver::MessageReceived(BMessage* message) 243 { 244 switch (message->what) { 245 case MSG_TOGGLE_ADDITIVE: 246 if (fLocker.Lock() && fIFS) { 247 fAdditive = fAdditiveCB->Value() == B_CONTROL_ON; 248 fIFS->SetAdditive(fAdditive || fIsPreview); 249 fLocker.Unlock(); 250 } 251 break; 252 case MSG_SET_SPEED: 253 if (fLocker.Lock() && fIFS) { 254 fSpeed = fSpeedS->Value(); 255 fIFS->SetSpeed(fSpeed); 256 fLocker.Unlock(); 257 } 258 break; 259 default: 260 BHandler::MessageReceived(message); 261 } 262 } 263 264 // _Init 265 void 266 IFSSaver::_Init(BRect bounds) 267 { 268 if (fLocker.Lock()) { 269 delete fIFS; 270 fIFS = new IFS(bounds); 271 fLocker.Unlock(); 272 } 273 } 274 275 // _Cleanup 276 void 277 IFSSaver::_Cleanup() 278 { 279 if (fLocker.Lock()) { 280 delete fIFS; 281 fIFS = NULL; 282 fLocker.Unlock(); 283 } 284 } 285 286