/* * Copyright (c) 1997 by Massimino Pascal * Copyright 2006-2014, Haiku, Inc. All rights reserved. * * Distributed under the terms of the MIT License. * * Authors: * Stephan Aßmus, superstippi@gmx.de * Massimino Pascal, Pascal.Massimon@ens.fr * John Scipione, jscipione@gmail.com */ #include #include #include #include #include #include #include "IFSSaver.h" #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "Screensaver IFS" static const uint32 kMsgToggleAdditive = 'tgad'; static const uint32 kMsgSetSpeed = 'stsp'; // #pragma mark - Instantiation function extern "C" _EXPORT BScreenSaver* instantiate_screen_saver(BMessage *message, image_id image) { return new IFSSaver(message, image); } // #pragma mark - IFSSaver IFSSaver::IFSSaver(BMessage* message, image_id id) : BScreenSaver(message, id), BHandler("IFS Saver"), fIFS(NULL), fIsPreview(false), fLastDrawnFrame(0), fAdditive(false), fSpeed(6) { fDirectInfo.bits = NULL; fDirectInfo.bytesPerRow = 0; if (message == NULL) return; if (message->FindBool("IFS additive", &fAdditive) != B_OK) fAdditive = false; if (message->FindInt32("IFS speed", &fSpeed) != B_OK) fSpeed = 6; } IFSSaver::~IFSSaver() { if (Looper() != NULL) Looper()->RemoveHandler(this); _Cleanup(); } void IFSSaver::StartConfig(BView* view) { BRect bounds = view->Bounds(); bounds.InsetBy(10.0f, 10.0f); BRect frame(0.0f, 0.0f, bounds.Width(), 20.0f); // the additive check box fAdditiveCB = new BCheckBox(frame, "additive setting", B_TRANSLATE("Render dots additive"), new BMessage(kMsgToggleAdditive), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); fAdditiveCB->SetValue(fAdditive); fAdditiveCB->ResizeToPreferred(); bounds.bottom -= fAdditiveCB->Bounds().Height() * 2.0f; fAdditiveCB->MoveTo(bounds.LeftBottom()); view->AddChild(fAdditiveCB); // the additive check box fSpeedS = new BSlider(frame, "speed setting", B_TRANSLATE("Morphing speed:"), new BMessage(kMsgSetSpeed), 1, 12, B_BLOCK_THUMB, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM); fSpeedS->SetValue(fSpeed); fSpeedS->SetHashMarks(B_HASH_MARKS_BOTTOM); fSpeedS->SetHashMarkCount(12); fSpeedS->ResizeToPreferred(); bounds.bottom -= fSpeedS->Bounds().Height() + 15.0f; fSpeedS->MoveTo(bounds.LeftBottom()); view->AddChild(fSpeedS); // the info text view BRect textRect = bounds; textRect.OffsetTo(0.0, 0.0); BTextView* textView = new BTextView(bounds, B_EMPTY_STRING, textRect, B_FOLLOW_ALL, B_WILL_DRAW); textView->SetViewColor(view->ViewColor()); BString aboutScreenSaver(B_TRANSLATE("%screenSaverName%\n\n" B_UTF8_COPYRIGHT " 1997 Massimino Pascal\n\n" "xscreensaver port by Stephan Aßmus\n" "")); BString screenSaverName(B_TRANSLATE("Iterated Function System")); aboutScreenSaver.ReplaceFirst("%screenSaverName%", screenSaverName); textView->Insert(aboutScreenSaver); textView->SetStylable(true); textView->SetFontAndColor(0, screenSaverName.Length(), be_bold_font); textView->MakeEditable(false); view->AddChild(textView); // make sure we receive messages from the views we added if (BWindow* window = view->Window()) window->AddHandler(this); fAdditiveCB->SetTarget(this); fSpeedS->SetTarget(this); } status_t IFSSaver::StartSaver(BView* view, bool preview) { display_mode mode; BScreen screen(B_MAIN_SCREEN_ID); screen.GetMode(&mode); float totalSize = mode.timing.h_total * mode.timing.v_total; float fps = mode.timing.pixel_clock * 1000.0f / totalSize; SetTickSize((bigtime_t)floor(1000000.0 / fps + 0.5)); fIsPreview = preview; if (view == NULL) return B_BAD_VALUE; _Init(view->Bounds()); if (fIFS == NULL) return B_ERROR; fIFS->SetAdditive(fAdditive || fIsPreview); fIFS->SetSpeed(fSpeed); return B_OK; } void IFSSaver::StopSaver() { _Cleanup(); } void IFSSaver::DirectConnected(direct_buffer_info* info) { int32 request = info->buffer_state & B_DIRECT_MODE_MASK; switch (request) { case B_DIRECT_START: fDirectInfo.bits = info->bits; fDirectInfo.bytesPerRow = info->bytes_per_row; fDirectInfo.bits_per_pixel = info->bits_per_pixel; fDirectInfo.format = info->pixel_format; fDirectInfo.bounds = info->window_bounds; break; case B_DIRECT_STOP: fDirectInfo.bits = NULL; break; } } void IFSSaver::Draw(BView* view, int32 frame) { if (frame == 0) { fLastDrawnFrame = -1; view->SetHighColor(0, 0, 0); view->FillRect(view->Bounds()); } int32 frames = frame - fLastDrawnFrame; if ((fIsPreview || fDirectInfo.bits == NULL) && fLocker.Lock()) { fIFS->Draw(view, NULL, frames); fLastDrawnFrame = frame; fLocker.Unlock(); } } void IFSSaver::DirectDraw(int32 frame) { if (frame == 0) fLastDrawnFrame = -1; if (!fIsPreview && fDirectInfo.bits != NULL) { fIFS->Draw(NULL, &fDirectInfo, frame - fLastDrawnFrame); fLastDrawnFrame = frame; } } status_t IFSSaver::SaveState(BMessage* into) const { status_t ret = B_BAD_VALUE; if (into != NULL) { ret = into->AddBool("IFS additive", fAdditive); if (ret >= B_OK) ret = into->AddInt32("IFS speed", fSpeed); } return ret; } void IFSSaver::MessageReceived(BMessage* message) { switch (message->what) { case kMsgToggleAdditive: if (fLocker.Lock() && fIFS != NULL) { fAdditive = fAdditiveCB->Value() == B_CONTROL_ON; fIFS->SetAdditive(fAdditive || fIsPreview); fLocker.Unlock(); } break; case kMsgSetSpeed: if (fLocker.Lock() && fIFS != NULL) { fSpeed = fSpeedS->Value(); fIFS->SetSpeed(fSpeed); fLocker.Unlock(); } break; default: BHandler::MessageReceived(message); } } void IFSSaver::_Init(BRect bounds) { if (fLocker.Lock()) { delete fIFS; fIFS = new IFS(bounds); fLocker.Unlock(); } } void IFSSaver::_Cleanup() { if (fLocker.Lock()) { delete fIFS; fIFS = NULL; fLocker.Unlock(); } }