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