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 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 68 69 fAdditiveCB->SetValue(fAdditive); 70 71 fAdditiveCB->ResizeToPreferred(); 72 bounds.bottom -= fAdditiveCB->Bounds().Height() * 2.0; 73 fAdditiveCB->MoveTo(bounds.LeftBottom()); 74 75 view->AddChild(fAdditiveCB); 76 77 // the additive check box 78 fSpeedS = new BSlider(frame, "speed setting", 79 "Morphing Speed:", 80 new BMessage(MSG_SET_SPEED), 81 1, 12, B_BLOCK_THUMB, 82 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM); 83 84 fSpeedS->SetValue(fSpeed); 85 fSpeedS->SetHashMarks(B_HASH_MARKS_BOTTOM); 86 fSpeedS->SetHashMarkCount(12); 87 88 fSpeedS->ResizeToPreferred(); 89 bounds.bottom -= fSpeedS->Bounds().Height() + 15.0; 90 fSpeedS->MoveTo(bounds.LeftBottom()); 91 92 view->AddChild(fSpeedS); 93 94 // the info text view 95 BRect textRect = bounds; 96 textRect.OffsetTo(0.0, 0.0); 97 BTextView* textView = new BTextView(bounds, B_EMPTY_STRING, textRect, 98 B_FOLLOW_ALL, B_WILL_DRAW); 99 textView->SetViewColor(view->ViewColor()); 100 textView->Insert("Iterated Function System\n\n" 101 ""B_UTF8_COPYRIGHT" 1997 Massimino Pascal\n\n" 102 "xscreensaver port by Stephan Aßmus\n" 103 "<stippi@yellowbites.com>"); 104 105 106 textView->SetStylable(true); 107 textView->SetFontAndColor(0, 24, be_bold_font); 108 // textView->SetFontAndColor(25, 255, be_plain_font); 109 110 textView->MakeEditable(false); 111 112 view->AddChild(textView); 113 114 // make sure we receive messages from the views we added 115 if (BWindow* window = view->Window()) 116 window->AddHandler(this); 117 118 fAdditiveCB->SetTarget(this); 119 fSpeedS->SetTarget(this); 120 } 121 122 // StartSaver 123 status_t 124 IFSSaver::StartSaver(BView *v, bool preview) 125 { 126 display_mode mode; 127 BScreen screen(B_MAIN_SCREEN_ID); 128 screen.GetMode(&mode); 129 float totalSize = mode.timing.h_total * mode.timing.v_total; 130 float fps = mode.timing.pixel_clock * 1000.0 / totalSize; 131 132 //printf("ticks per frame: %lldµs\n", (int64)floor(1000000.0 / fps + 0.5)); 133 SetTickSize((int64)floor(1000000.0 / fps + 0.5)); 134 135 fIsPreview = preview; 136 fBounds = v->Bounds(); 137 138 _Init(fBounds); 139 fIFS->SetAdditive(fIsPreview || fAdditive); 140 fIFS->SetSpeed(fSpeed); 141 142 return B_OK; 143 } 144 145 // StopSaver 146 void 147 IFSSaver::StopSaver() 148 { 149 _Cleanup(); 150 } 151 152 // DirectConnected 153 void 154 IFSSaver::DirectConnected(direct_buffer_info* info) 155 { 156 //printf("IFSSaver::DirectConnected()\n"); 157 int32 request = info->buffer_state & B_DIRECT_MODE_MASK; 158 switch (request) { 159 case B_DIRECT_START: 160 //printf("B_DIRECT_START\n"); 161 //printf(" bits_per_pixel: %ld\n", info->bits_per_pixel); 162 //printf(" bytes_per_row: %ld\n", info->bytes_per_row); 163 //printf(" pixel_format: %d\n", info->pixel_format); 164 //printf(" window_bounds: (%ld, %ld, %ld, %ld)\n", 165 // info->window_bounds.left, info->window_bounds.top, 166 // info->window_bounds.right, info->window_bounds.bottom); 167 fDirectInfo.bits = info->bits; 168 fDirectInfo.bytesPerRow = info->bytes_per_row; 169 fDirectInfo.bits_per_pixel = info->bits_per_pixel; 170 fDirectInfo.format = info->pixel_format; 171 fDirectInfo.bounds = info->window_bounds; 172 break; 173 case B_DIRECT_STOP: 174 fDirectInfo.bits = NULL; 175 break; 176 default: 177 break; 178 } 179 //printf("bits: %p\n", fDirectInfo.bits); 180 } 181 182 // Draw 183 void 184 IFSSaver::Draw(BView *view, int32 frame) 185 { 186 //printf("IFSSaver::Draw(%ld) (%ldx%ld)\n", frame, view->Bounds().IntegerWidth() + 1, view->Bounds().IntegerHeight() + 1); 187 if (frame == 0) { 188 fLastDrawnFrame = -1; 189 view->SetHighColor(0, 0, 0); 190 view->FillRect(view->Bounds()); 191 } 192 int32 frames = frame - fLastDrawnFrame; 193 if (fIsPreview || fDirectInfo.bits == NULL) { 194 fIFS->Draw(view, NULL, frames); 195 196 fLastDrawnFrame = frame; 197 } 198 } 199 200 // DirectDraw 201 void 202 IFSSaver::DirectDraw(int32 frame) 203 { 204 //bigtime_t now = system_time(); 205 //printf("IFSSaver::DirectDraw(%ld)\n", frame); 206 if (frame == 0) 207 fLastDrawnFrame = -1; 208 int32 frames = frame - fLastDrawnFrame; 209 if (fDirectInfo.bits) { 210 fIFS->Draw(NULL, &fDirectInfo, frames); 211 //printf("DirectDraw(): %lldµs\n", system_time() - now); 212 fLastDrawnFrame = frame; 213 } 214 } 215 216 // SaveState 217 status_t 218 IFSSaver::SaveState(BMessage* into) const 219 { 220 status_t ret = B_BAD_VALUE; 221 if (into) { 222 ret = into->AddBool("IFS additive", fAdditive); 223 if (ret >= B_OK) 224 ret = into->AddInt32("IFS speed", fSpeed); 225 } 226 return ret; 227 } 228 229 // MessageReceived 230 void 231 IFSSaver::MessageReceived(BMessage* message) 232 { 233 switch (message->what) { 234 case MSG_TOGGLE_ADDITIVE: 235 if (fLocker.Lock() && fIFS) { 236 fAdditive = fAdditiveCB->Value() == B_CONTROL_ON; 237 fIFS->SetAdditive(fAdditive || fIsPreview); 238 fLocker.Unlock(); 239 } 240 break; 241 case MSG_SET_SPEED: 242 if (fLocker.Lock() && fIFS) { 243 fSpeed = fSpeedS->Value(); 244 fIFS->SetSpeed(fSpeed); 245 fLocker.Unlock(); 246 } 247 break; 248 default: 249 BHandler::MessageReceived(message); 250 } 251 } 252 253 // _Init 254 void 255 IFSSaver::_Init(BRect bounds) 256 { 257 if (fLocker.Lock()) { 258 delete fIFS; 259 fIFS = new IFS(bounds); 260 fLocker.Unlock(); 261 } 262 } 263 264 // _Cleanup 265 void 266 IFSSaver::_Cleanup() 267 { 268 if (fLocker.Lock()) { 269 delete fIFS; 270 fIFS = NULL; 271 fLocker.Unlock(); 272 } 273 } 274 275