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