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