diff --git a/src/add-ons/screen_savers/Jamfile b/src/add-ons/screen_savers/Jamfile index 90afb17062..0e787928f9 100644 --- a/src/add-ons/screen_savers/Jamfile +++ b/src/add-ons/screen_savers/Jamfile @@ -1,4 +1,5 @@ SubDir HAIKU_TOP src add-ons screen_savers ; SubInclude HAIKU_TOP src add-ons screen_savers haiku ; +SubInclude HAIKU_TOP src add-ons screen_savers ifs ; SubInclude HAIKU_TOP src add-ons screen_savers slideshowsaver ; diff --git a/src/add-ons/screen_savers/ifs/IFS.cpp b/src/add-ons/screen_savers/ifs/IFS.cpp new file mode 100644 index 0000000000..36f0a315ee --- /dev/null +++ b/src/add-ons/screen_savers/ifs/IFS.cpp @@ -0,0 +1,661 @@ +/* + * Copyright 2006, Haiku. + * Copyright (c) 1997 by Massimino Pascal + * + * Distributed under the terms of the MIT License. + * + * Authors: + * Massimino Pascal + * Stephan Aßmus + */ + +/*! When shown ifs, Diana Rose (4 years old) said, "It looks like dancing." + */ + +#include "IFS.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include // for getpid() +#include // for gettimeofday() + +using std::nothrow; + +#define HALF 0 + +// The following 'random' numbers are taken from CRC, 18th Edition, page 622. +// Each array element was taken from the corresponding line in the table, +// except that a[0] was from line 100. 8s and 9s in the table were simply +// skipped. The high order digit was taken mod 4. + +#define VectorSize 55 +static unsigned int a[VectorSize] = { + 035340171546, 010401501101, 022364657325, 024130436022, 002167303062, // 5 + 037570375137, 037210607110, 016272055420, 023011770546, 017143426366, // 10 + 014753657433, 021657231332, 023553406142, 004236526362, 010365611275, // 14 + 007117336710, 011051276551, 002362132524, 001011540233, 012162531646, // 20 + 007056762337, 006631245521, 014164542224, 032633236305, 023342700176, // 25 + 002433062234, 015257225043, 026762051606, 000742573230, 005366042132, // 30 + 012126416411, 000520471171, 000725646277, 020116577576, 025765742604, // 35 + 007633473735, 015674255275, 017555634041, 006503154145, 021576344247, // 40 + 014577627653, 002707523333, 034146376720, 030060227734, 013765414060, // 45 + 036072251540, 007255221037, 024364674123, 006200353166, 010126373326, // 50 + 015664104320, 016401041535, 016215305520, 033115351014, 017411670323 // 55 +}; + +static int i1, i2; + +// ya_random +unsigned int +ya_random (void) +{ + register int ret = a[i1] + a[i2]; + a[i1] = ret; + if (++i1 >= VectorSize) i1 = 0; + if (++i2 >= VectorSize) i2 = 0; + return ret; +} + +// ya_rand_init +void +ya_rand_init(unsigned int seed) +{ + int i; + if (seed == 0) + { + struct timeval tp; + struct timezone tzp; + gettimeofday(&tp, &tzp); + /* ignore overflow */ + seed = (999*tp.tv_sec) + (1001*tp.tv_usec) + (1003 * getpid()); + } + + a[0] += seed; + for (i = 1; i < VectorSize; i++) + { + seed = a[i-1]*1001 + seed*999; + a[i] += seed; + } + + i1 = a[0] % VectorSize; + i2 = (i1 + 024) % VectorSize; +} + +#define random() ya_random() +#define RAND_MAX 0xFFFFFFFF + +#define FLOAT_TO_INT(x) (int32)( (float)(UNIT)*(x) ) + +#define LRAND() ((long) (random() & 0x7fffffff)) +#define NRAND(n) ((int) (LRAND() % (n))) +#define MAXRAND (2147483648.0) // unsigned 1<<31 as a float +#define SRAND(n) // already seeded by screenhack.c TODO: ?!? is it? + + +// gauss_rand +static float +gauss_rand(float c, float A, float S) +{ + float y; + + y = (float) LRAND() / MAXRAND; + y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S)); + if (NRAND(2)) + return (c + y); + return (c - y); +} + +// half_gauss_rand +static float +half_gauss_rand(float c, float A, float S) +{ + float y; + + y = (float) LRAND() / MAXRAND; + y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S)); + return (c + y); +} + +// transform +inline void +transform(SIMI* Simi, int32 xo, int32 yo, int32* x, int32* y) +{ + int32 xx, yy; + + xo = xo - Simi->Cx; + xo = (xo * Simi->R) / UNIT; + yo = yo - Simi->Cy; + yo = (yo * Simi->R) / UNIT; + + xx = xo - Simi->Cx; + xx = (xx * Simi->R2) / UNIT; + yy = -yo - Simi->Cy; + yy = (yy * Simi->R2) / UNIT; + + *x = ((xo * Simi->Ct - yo * Simi->St + xx * Simi->Ct2 - yy * Simi->St2) / UNIT) + Simi->Cx; + *y = ((xo * Simi->St + yo * Simi->Ct + xx * Simi->St2 + yy * Simi->Ct2) / UNIT) + Simi->Cy; +} + + +// constructor +IFS::IFS(BRect bounds) + : fRoot(NULL), + fAdditive(false), + fCurrentMarkValue(1) +{ + ya_rand_init(system_time()); + + int i; + FRACTAL *Fractal; + + if (fRoot == NULL) { + fRoot = (FRACTAL*) calloc(1, sizeof (FRACTAL)); + if (fRoot == NULL) + return; + } + Fractal = fRoot; + + _FreeBuffers(Fractal); + i = (NRAND(4)) + 2; // Number of centers + switch (i) { + case 3: + Fractal->Depth = fAdditive ? MAX_DEPTH_3 + 1 : MAX_DEPTH_3; + Fractal->r_mean = .6; + Fractal->dr_mean = .4; + Fractal->dr2_mean = .3; + break; + + case 4: + Fractal->Depth = MAX_DEPTH_4; + Fractal->r_mean = .5; + Fractal->dr_mean = .4; + Fractal->dr2_mean = .3; + break; + + case 5: + Fractal->Depth = MAX_DEPTH_5; + Fractal->r_mean = .5; + Fractal->dr_mean = .4; + Fractal->dr2_mean = .3; + break; + + default: + case 2: + Fractal->Depth = fAdditive ? MAX_DEPTH_2 + 1 : MAX_DEPTH_2; + Fractal->r_mean = .7; + Fractal->dr_mean = .3; + Fractal->dr2_mean = .4; + break; + } + // fprintf( stderr, "N=%d\n", i ); + Fractal->Nb_Simi = i; + Fractal->Max_Pt = Fractal->Nb_Simi - 1; + for (i = 0; i <= Fractal->Depth + 2; ++i) + Fractal->Max_Pt *= Fractal->Nb_Simi; + + if ((Fractal->buffer1 = (Point *) calloc(Fractal->Max_Pt, + sizeof (Point))) == NULL) { + _FreeIFS(Fractal); + return; + } + if ((Fractal->buffer2 = (Point *) calloc(Fractal->Max_Pt, + sizeof (Point))) == NULL) { + _FreeIFS(Fractal); + return; + } + Fractal->Speed = 6; +#if HALF + Fractal->Width = bounds.IntegerWidth() / 2 + 1; + Fractal->Height = bounds.IntegerHeight() / 2 + 1; +#else + Fractal->Width = bounds.IntegerWidth() + 1; + Fractal->Height = bounds.IntegerHeight() + 1; +#endif + Fractal->Cur_Pt = 0; + Fractal->Count = 0; + Fractal->Lx = (Fractal->Width - 1) / 2; + Fractal->Ly = (Fractal->Height - 1) / 2; + Fractal->Col = NRAND(Fractal->Width * Fractal->Height - 1) + 1; + + _RandomSimis(Fractal, Fractal->Components, 5 * MAX_SIMI); + + delete Fractal->bitmap; + Fractal->bitmap = new (nothrow) BBitmap(BRect(0.0, 0.0, + Fractal->Width - 1, + Fractal->Height - 1), + 0, + B_RGB32); + delete Fractal->markBitmap; + Fractal->markBitmap = new (nothrow) BBitmap(BRect(0.0, 0.0, + Fractal->Width - 1, + Fractal->Height - 1), + 0, + B_GRAY8); + // Allocation checked + if (Fractal->bitmap != NULL && Fractal->bitmap->IsValid()) { + memset(Fractal->bitmap->Bits(), 0, Fractal->bitmap->BitsLength()); + } else { + delete Fractal->bitmap; + Fractal->bitmap = NULL; + } + if (Fractal->markBitmap != NULL && Fractal->markBitmap->IsValid()) { + memset(Fractal->markBitmap->Bits(), 0, Fractal->markBitmap->BitsLength()); + } else { + delete Fractal->markBitmap; + Fractal->markBitmap = NULL; + } +} + +// destructor +IFS::~IFS() +{ + if (fRoot != NULL) { + _FreeIFS(fRoot); + free((void*) fRoot); + } +} + +// Draw +void +IFS::Draw(BView* view, const buffer_info* info, int32 frames) +{ +//bigtime_t now = system_time(); + int i; + float u, uu, v, vv, u0, u1, u2, u3; + SIMI *S, *S1, *S2, *S3, *S4; + FRACTAL *F; + + if (fRoot == NULL) + return; + F = fRoot; + if (F->buffer1 == NULL) + return; + +//if (frames > 1) +// printf("skipping %ld frames\n", frames); + + // do this as many times as necessary to calculate the missing frames + // so the animation doesn't jerk when we miss a few frames + for (int32 frame = 0; frame < frames; frame++) { + + u = (float) (F->Count) * (float) (F->Speed) / 1000.0; + uu = u * u; + v = 1.0 - u; + vv = v * v; + u0 = vv * v; + u1 = 3.0 * vv * u; + u2 = 3.0 * v * uu; + u3 = u * uu; + + S = F->Components; + S1 = S + F->Nb_Simi; + S2 = S1 + F->Nb_Simi; + S3 = S2 + F->Nb_Simi; + S4 = S3 + F->Nb_Simi; + + for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) { + S->c_x = u0 * S1->c_x + u1 * S2->c_x + u2 * S3->c_x + u3 * S4->c_x; + S->c_y = u0 * S1->c_y + u1 * S2->c_y + u2 * S3->c_y + u3 * S4->c_y; + S->r = u0 * S1->r + u1 * S2->r + u2 * S3->r + u3 * S4->r; + S->r2 = u0 * S1->r2 + u1 * S2->r2 + u2 * S3->r2 + u3 * S4->r2; + S->A = u0 * S1->A + u1 * S2->A + u2 * S3->A + u3 * S4->A; + S->A2 = u0 * S1->A2 + u1 * S2->A2 + u2 * S3->A2 + u3 * S4->A2; + } + +//bigtime_t beforeDraw = system_time(); + if (frame == frames - 1) + _DrawFractal(view, info); + +//bigtime_t draw = system_time() - beforeDraw; + + if (F->Count >= 1000 / F->Speed) { + S = F->Components; + S1 = S + F->Nb_Simi; + S2 = S1 + F->Nb_Simi; + S3 = S2 + F->Nb_Simi; + S4 = S3 + F->Nb_Simi; + + for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) { + S2->c_x = 2.0 * S4->c_x - S3->c_x; + S2->c_y = 2.0 * S4->c_y - S3->c_y; + S2->r = 2.0 * S4->r - S3->r; + S2->r2 = 2.0 * S4->r2 - S3->r2; + S2->A = 2.0 * S4->A - S3->A; + S2->A2 = 2.0 * S4->A2 - S3->A2; + + *S1 = *S4; + } + _RandomSimis(F, F->Components + 3 * F->Nb_Simi, F->Nb_Simi); + + _RandomSimis(F, F->Components + 4 * F->Nb_Simi, F->Nb_Simi); + + F->Count = 0; + } else + F->Count++; +// F->Col++; +//bigtime_t finish = (system_time() - now) - draw; +//if (info) +//printf("draw: %lld\nnon-draw: %lld\n\n", draw, finish); + } + +} + +// SetAdditive +void +IFS::SetAdditive(bool additive) +{ + fAdditive = additive; +} + +// SetSpeed +void +IFS::SetSpeed(int32 speed) +{ + if (fRoot && speed > 0 && speed <= 12) + fRoot->Speed = speed; +} + +// Draw +void +IFS::_DrawFractal(BView* view, const buffer_info* info) +{ + FRACTAL* F = fRoot; + int i, j; + int32 x, y, xo, yo; + SIMI* Cur, *Simi; + + for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) { + Cur->Cx = FLOAT_TO_INT(Cur->c_x); + Cur->Cy = FLOAT_TO_INT(Cur->c_y); + + Cur->Ct = FLOAT_TO_INT(cos(Cur->A)); + Cur->St = FLOAT_TO_INT(sin(Cur->A)); + Cur->Ct2 = FLOAT_TO_INT(cos(Cur->A2)); + Cur->St2 = FLOAT_TO_INT(sin(Cur->A2)); + + Cur->R = FLOAT_TO_INT(Cur->r); + Cur->R2 = FLOAT_TO_INT(Cur->r2); + } + + + fCurrentPoint = 0; + fCurrentFractal = F; + fPointBuffer = F->buffer2; + for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) { + xo = Cur->Cx; + yo = Cur->Cy; + for (Simi = F->Components, j = F->Nb_Simi; j; --j, Simi++) { + if (Simi == Cur) + continue; + transform(Simi, xo, yo, &x, &y); + _Trace(F, x, y); + } + } + + if (F->bitmap != NULL && F->markBitmap != NULL) { + uint8* bits = (uint8*)F->bitmap->Bits(); + uint32 bpr = F->bitmap->BytesPerRow(); + uint8* markBits = (uint8*)F->markBitmap->Bits(); + uint32 markBPR = F->markBitmap->BytesPerRow(); + int32 minX = F->Width; + int32 minY = F->Height; + int32 maxX = 0; + int32 maxY = 0; + // Erase previous dots from bitmap, + // but only if we're not in BDirectWindow mode, + // since the dots will have been erased already + if (!info) { + if (F->Cur_Pt) { + for (int32 i = 0; i < F->Cur_Pt; i++) { + Point p = F->buffer1[i]; + if (p.x >= 0 && p.x < F->Width + && p.y >= 0 && p.y < F->Height) { + int32 offset = bpr * p.y + p.x * 4; + *(uint32*)&bits[offset] = 0; + if (minX > p.x) + minX = p.x; + if (minY > p.y) + minY = p.y; + if (maxX < p.x) + maxX = p.x; + if (maxY < p.y) + maxY = p.y; + } + } + } + } + // draw the new dots into the bitmap + if (fCurrentPoint) { + if (info) { + for (int32 i = 0; i < fCurrentPoint; i++) { + Point p = F->buffer2[i]; + if (p.x >= 0 && p.x < F->Width + && p.y >= 0 && p.y < F->Height) { + int32 offset = bpr * p.y + p.x * 4; + if (fAdditive) { + if (bits[offset + 0] < 255) { + bits[offset + 0] += 51; + bits[offset + 1] += 51; + bits[offset + 2] += 51; + } + } else { + *(uint32*)&bits[offset] = 0xffffffff; + } + } + } + } else { + // in this version, remember the bounds rectangle + for (int32 i = 0; i < fCurrentPoint; i++) { + Point p = F->buffer2[i]; + if (p.x >= 0 && p.x < F->Width + && p.y >= 0 && p.y < F->Height) { + int32 offset = bpr * p.y + p.x * 4; + if (fAdditive) { + if (bits[offset + 0] < 255) { + bits[offset + 0] += 15; + bits[offset + 1] += 15; + bits[offset + 2] += 15; + } + } else { + *(uint32*)&bits[offset] = 0xffffffff; + } + if (minX > p.x) + minX = p.x; + if (minY > p.y) + minY = p.y; + if (maxX < p.x) + maxX = p.x; + if (maxY < p.y) + maxY = p.y; + } + } + } + } + if (info && info->bits) { + + uint8* screenBits = (uint8*)info->bits; + uint32 screenBPR = info->bytesPerRow; + int32 left = info->bounds.left; + int32 top = info->bounds.top; + int32 bpp = info->bits_per_pixel; + screenBits += left * bpp + top * bpr; + + int32 screenWidth = info->bounds.right - left; + int32 screenHeight = info->bounds.bottom - top; + +//printf("using BDirectWindow (%p %dx%d)\n", this, F->Width, F->Height); + // redraw the previous points on screen + // with the contents of the current bitmap + // + // draw the new points, erasing the bitmap as we go + int32 maxPoints = max_c(F->Cur_Pt, fCurrentPoint); + if (maxPoints > 0) { + +// BScreen screen(B_MAIN_SCREEN_ID); +// screen.WaitForRetrace(); + + for (int32 i = 0; i < maxPoints; i++) { + // copy previous points (black) + if (i < F->Cur_Pt) { + Point p = F->buffer1[i]; + if (p.x >= 0 && p.x < F->Width && p.x < screenWidth + && p.y >= 0 && p.y < F->Height && p.y < screenHeight) { + int32 markOffset = markBPR * p.y + p.x; + if (markBits[markOffset] != fCurrentMarkValue) { + int32 offset = bpr * p.y + p.x * 4; + // copy the pixel to the screen + uint32* src = (uint32*)&bits[offset]; + if (bpp == 32) { + int32 screenOffset = screenBPR * p.y + p.x * 4; + *(uint32*)&screenBits[screenOffset] = *src; + } else if (bpp == 16) { + int32 screenOffset = screenBPR * p.y + p.x * 2; + *(uint16*)&screenBits[screenOffset] = + (uint16)(((bits[offset + 2] & 0xf8) << 8) | + ((bits[offset + 1] & 0xfc) << 3) | + (bits[offset] >> 3)); + } else if (bpp == 15) { + int32 screenOffset = screenBPR * p.y + p.x * 2; + *(uint16*)&screenBits[screenOffset] = + (uint16)(((bits[offset + 2] & 0xf8) << 7) | + ((bits[offset + 1] & 0xf8) << 2) | + (bits[offset] >> 3)); + } else if (bpp == 8) { + int32 screenOffset = screenBPR * p.y + p.x; + screenBits[screenOffset] = bits[offset]; + } + *src = 0; + markBits[markOffset] = fCurrentMarkValue; + } // else it means the pixel has been copied already + } + } + // copy current points (white) and erase them from the bitmap + if (i < fCurrentPoint) { + Point p = F->buffer2[i]; + if (p.x >= 0 && p.x < F->Width && p.x < screenWidth + && p.y >= 0 && p.y < F->Height && p.y < screenHeight) { + int32 markOffset = markBPR * p.y + p.x; + int32 offset = bpr * p.y + p.x * 4; + // copy the pixel to the screen + uint32* src = (uint32*)&bits[offset]; + if (markBits[markOffset] != fCurrentMarkValue) { + if (bpp == 32) { + int32 screenOffset = screenBPR * p.y + p.x * 4; + *(uint32*)&screenBits[screenOffset] = *src; + } else if (bpp == 16) { + int32 screenOffset = screenBPR * p.y + p.x * 2; + *(uint16*)&screenBits[screenOffset] = + (uint16)(((bits[offset + 2] & 0xf8) << 8) | + ((bits[offset + 1] & 0xfc) << 3) | + (bits[offset] >> 3)); + } else if (bpp == 15) { + int32 screenOffset = screenBPR * p.y + p.x * 2; + *(uint16*)&screenBits[screenOffset] = + (uint16)(((bits[offset + 2] & 0xf8) << 7) | + ((bits[offset + 1] & 0xf8) << 2) | + (bits[offset] >> 3)); + } else if (bpp == 1) { + int32 screenOffset = screenBPR * p.y + p.x; + screenBits[screenOffset] = bits[offset]; + } + markBits[markOffset] = fCurrentMarkValue; + } // else it means the pixel has been copied already + *src = 0; + } + } + } + } + } else { +//printf("using BView (%p %dx%d)\n", this, F->Width, F->Height); + // if not in BDirectWindow mode, draw the bitmap + BRect b(minX, minY, maxX, maxY); + view->DrawBitmapAsync(F->bitmap, b, b); + } + } + + // flip buffers + F->Cur_Pt = fCurrentPoint; + fPointBuffer = F->buffer1; + F->buffer1 = F->buffer2; + F->buffer2 = fPointBuffer; + if (fCurrentMarkValue == 255) + fCurrentMarkValue = 0; + else + fCurrentMarkValue++; +} + +// _Trace +void +IFS::_Trace(FRACTAL* F, int32 xo, int32 yo) +{ + int32 x, y, i; + SIMI* Cur; + + Cur = fCurrentFractal->Components; + for (i = fCurrentFractal->Nb_Simi; i; --i, Cur++) { + transform(Cur, xo, yo, &x, &y); + // fPointBuffer->x = F->Lx + (x * F->Lx / (UNIT * 2)); + // fPointBuffer->y = F->Ly - (y * F->Ly / (UNIT * 2)); + fPointBuffer->x = (UNIT * 2 + x) * F->Lx / (UNIT * 2); + fPointBuffer->y = (UNIT * 2 - y) * F->Ly / (UNIT * 2); + fPointBuffer++; + fCurrentPoint++; + + if (F->Depth && ((x - xo) >> 4) && ((y - yo) >> 4)) { + F->Depth--; + _Trace(F, x, y); + F->Depth++; + } + } +} + +// _RandomSimis +void +IFS::_RandomSimis(FRACTAL* f, SIMI* cur, int i) const +{ + while (i--) { + cur->c_x = gauss_rand(0.0, .8, 4.0); + cur->c_y = gauss_rand(0.0, .8, 4.0); + cur->r = gauss_rand(f->r_mean, f->dr_mean, 3.0); + cur->r2 = half_gauss_rand(0.0,f->dr2_mean, 2.0); + cur->A = gauss_rand(0.0, 360.0, 4.0) * (M_PI / 180.0); + cur->A2 = gauss_rand(0.0, 360.0, 4.0) * (M_PI / 180.0); + cur++; + } +} + +// _FreeBuffers +void +IFS::_FreeBuffers(FRACTAL *f) +{ + if (f->buffer1) { + free((void*) f->buffer1); + f->buffer1 = (Point*)NULL; + } + if (f->buffer2) { + free((void*) f->buffer2); + f->buffer2 = (Point*)NULL; + } +} + +// _FreeIFS +void +IFS::_FreeIFS(FRACTAL* f) +{ + _FreeBuffers(f); + delete f->bitmap; + f->bitmap = NULL; + delete f->markBitmap; + f->markBitmap = NULL; +} + + + diff --git a/src/add-ons/screen_savers/ifs/IFS.h b/src/add-ons/screen_savers/ifs/IFS.h new file mode 100644 index 0000000000..cf9d036b79 --- /dev/null +++ b/src/add-ons/screen_savers/ifs/IFS.h @@ -0,0 +1,93 @@ +// Polygon.h + +#ifndef IFS_H +#define IFS_H + +#include +#include +#include +#include + +typedef struct Similitude_Struct SIMI; +typedef struct Fractal_Struct FRACTAL; + +#define FIX 12 +#define UNIT ( 1< +#include + +#include +#include +#include + +#include "IFSSaver.h" + +enum { + MSG_TOGGLE_ADDITIVE = 'tgad', + MSG_SET_SPEED = 'stsp', +}; + +// MAIN INSTANTIATION FUNCTION +extern "C" _EXPORT BScreenSaver* +instantiate_screen_saver(BMessage *message, image_id image) +{ + return new IFSSaver(message, image); +} + +// constructor +IFSSaver::IFSSaver(BMessage *message, image_id id) + : BScreenSaver(message, id), + BHandler("IFS Saver"), + fIFS(NULL), + fIsPreview(false), + fBounds(0.0, 0.0, -1.0, -1.0), + fLastDrawnFrame(0), + fAdditive(false), + fSpeed(6) +{ + fDirectInfo.bits = NULL; + fDirectInfo.bytesPerRow = 0; + + if (message) { + if (message->FindBool("IFS additive", &fAdditive) < B_OK) + fAdditive = false; + if (message->FindInt32("IFS speed", &fSpeed) < B_OK) + fSpeed = 6; + } +} + +// destructor +IFSSaver::~IFSSaver() +{ + if (Looper()) { + Looper()->RemoveHandler(this); + } + _Cleanup(); +} + +// StartConfig +void +IFSSaver::StartConfig(BView *view) +{ + BRect bounds = view->Bounds(); + bounds.InsetBy(10.0, 10.0); + BRect frame(0.0, 0.0, bounds.Width(), 20.0); + + // the additive check box + fAdditiveCB = new BCheckBox(frame, "additive setting", + "Render dots additive", + new BMessage(MSG_TOGGLE_ADDITIVE)); + + fAdditiveCB->SetValue(fAdditive); + + fAdditiveCB->ResizeToPreferred(); + bounds.bottom -= fAdditiveCB->Bounds().Height() * 2.0; + fAdditiveCB->MoveTo(bounds.LeftBottom()); + + view->AddChild(fAdditiveCB); + + // the additive check box + fSpeedS = new BSlider(frame, "speed setting", + "Morphing Speed:", + new BMessage(MSG_SET_SPEED), + 1, 12); + + fSpeedS->SetValue(fSpeed); + fSpeedS->SetHashMarks(B_HASH_MARKS_BOTTOM); + fSpeedS->SetHashMarkCount(12); + + fSpeedS->ResizeToPreferred(); + bounds.bottom -= fSpeedS->Bounds().Height() + 15.0; + 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()); + textView->Insert("Iterated Function System\n\n" + ""B_UTF8_COPYRIGHT" 1997 Massimino Pascal\n\n" + "xscreensaver port by Stephan Aßmus\n" + ""); + + + textView->SetStylable(true); + textView->SetFontAndColor(0, 24, be_bold_font); +// textView->SetFontAndColor(25, 255, be_plain_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); +} + +// StartSaver +status_t +IFSSaver::StartSaver(BView *v, 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.0 / totalSize; + +//printf("ticks per frame: %lldµs\n", (int64)floor(1000000.0 / fps + 0.5)); + SetTickSize((int64)floor(1000000.0 / fps + 0.5)); + + fIsPreview = preview; + fBounds = v->Bounds(); + + _Init(fBounds); + fIFS->SetAdditive(fIsPreview || fAdditive); + fIFS->SetSpeed(fSpeed); + + return B_OK; +} + +// StopSaver +void +IFSSaver::StopSaver() +{ + _Cleanup(); +} + +// DirectConnected +void +IFSSaver::DirectConnected(direct_buffer_info* info) +{ +//printf("IFSSaver::DirectConnected()\n"); + int32 request = info->buffer_state & B_DIRECT_MODE_MASK; + switch (request) { + case B_DIRECT_START: +//printf("B_DIRECT_START\n"); +//printf(" bits_per_pixel: %ld\n", info->bits_per_pixel); +//printf(" bytes_per_row: %ld\n", info->bytes_per_row); +//printf(" pixel_format: %d\n", info->pixel_format); +//printf(" window_bounds: (%ld, %ld, %ld, %ld)\n", +// info->window_bounds.left, info->window_bounds.top, +// info->window_bounds.right, info->window_bounds.bottom); + 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; + default: + break; + } +//printf("bits: %p\n", fDirectInfo.bits); +} + +// Draw +void +IFSSaver::Draw(BView *view, int32 frame) +{ +//printf("IFSSaver::Draw(%ld) (%ldx%ld)\n", frame, view->Bounds().IntegerWidth() + 1, view->Bounds().IntegerHeight() + 1); + if (frame == 0) { + fLastDrawnFrame = -1; + view->SetHighColor(0, 0, 0); + view->FillRect(view->Bounds()); + } + int32 frames = frame - fLastDrawnFrame; + if (fIsPreview || fDirectInfo.bits == NULL) { + fIFS->Draw(view, NULL, frames); + + fLastDrawnFrame = frame; + } +} + +// DirectDraw +void +IFSSaver::DirectDraw(int32 frame) +{ +//bigtime_t now = system_time(); +//printf("IFSSaver::DirectDraw(%ld)\n", frame); + if (frame == 0) + fLastDrawnFrame = -1; + int32 frames = frame - fLastDrawnFrame; + if (fDirectInfo.bits) { + fIFS->Draw(NULL, &fDirectInfo, frames); +//printf("DirectDraw(): %lldµs\n", system_time() - now); + fLastDrawnFrame = frame; + } +} + +// SaveState +status_t +IFSSaver::SaveState(BMessage* into) const +{ + status_t ret = B_BAD_VALUE; + if (into) { + ret = into->AddBool("IFS additive", fAdditive); + if (ret >= B_OK) + ret = into->AddInt32("IFS speed", fSpeed); + } + return ret; +} + +// MessageReceived +void +IFSSaver::MessageReceived(BMessage* message) +{ + switch (message->what) { + case MSG_TOGGLE_ADDITIVE: + if (fLocker.Lock() && fIFS) { + fAdditive = fAdditiveCB->Value() == B_CONTROL_ON; + fIFS->SetAdditive(fAdditive || fIsPreview); + fLocker.Unlock(); + } + break; + case MSG_SET_SPEED: + if (fLocker.Lock() && fIFS) { + fSpeed = fSpeedS->Value(); + fIFS->SetSpeed(fSpeed); + fLocker.Unlock(); + } + break; + default: + BHandler::MessageReceived(message); + } +} + +// _Init +void +IFSSaver::_Init(BRect bounds) +{ + if (fLocker.Lock()) { + delete fIFS; + fIFS = new IFS(bounds); + fLocker.Unlock(); + } +} + +// _Cleanup +void +IFSSaver::_Cleanup() +{ + if (fLocker.Lock()) { + delete fIFS; + fIFS = NULL; + fLocker.Unlock(); + } +} + diff --git a/src/add-ons/screen_savers/ifs/IFSSaver.h b/src/add-ons/screen_savers/ifs/IFSSaver.h new file mode 100644 index 0000000000..7776c757d4 --- /dev/null +++ b/src/add-ons/screen_savers/ifs/IFSSaver.h @@ -0,0 +1,59 @@ +// IFSSaver.h + +#ifndef IFS_SAVER_H +#define IFS_SAVER_H + +#include +// on PPC the full path is needed +#include +#include + +#include "IFS.h" + +class BCheckBox; +class BSlider; + +class IFSSaver : public BScreenSaver, public BHandler { + public: + IFSSaver(BMessage *message, + image_id image); + virtual ~IFSSaver(); + + // BScreenSaver + virtual void StartConfig(BView *view); + virtual status_t StartSaver(BView *view, bool preview); + virtual void StopSaver(); + + virtual void DirectConnected(direct_buffer_info* info); + virtual void Draw(BView* view, int32 frame); + virtual void DirectDraw(int32 frame); + + virtual status_t SaveState(BMessage* into) const; + + // BHandler + virtual void MessageReceived(BMessage* message); + + private: + void _Init(BRect bounds); + void _Cleanup(); + + IFS* fIFS; + + bool fIsPreview; + BRect fBounds; + + BLocker fLocker; + + BCheckBox* fAdditiveCB; + BSlider* fSpeedS; + + buffer_info fDirectInfo; + int32 fLastDrawnFrame; + + // config settings + bool fAdditive; + int32 fSpeed; +}; + + +#endif // IFS_SAVER_H diff --git a/src/add-ons/screen_savers/ifs/Jamfile b/src/add-ons/screen_savers/ifs/Jamfile new file mode 100644 index 0000000000..ee7f27b990 --- /dev/null +++ b/src/add-ons/screen_savers/ifs/Jamfile @@ -0,0 +1,11 @@ +SubDir HAIKU_TOP src add-ons screen_savers ifs ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +ScreenSaver IFS : + IFS.cpp + IFSSaver.cpp + + : libbe.so libscreensaver.so +; + diff --git a/src/add-ons/screen_savers/ifs/makefile b/src/add-ons/screen_savers/ifs/makefile new file mode 100644 index 0000000000..d2d6181922 --- /dev/null +++ b/src/add-ons/screen_savers/ifs/makefile @@ -0,0 +1,110 @@ +## BeOS Generic Makefile v2.1 ## + +## Fill in this file to specify the project being created, and the referenced +## makefile-engine will do all of the hard work for you. This handles both +## Intel and PowerPC builds of the BeOS. + +## Application Specific Settings --------------------------------------------- + +# specify the name of the binary +NAME= ../IFS + +# specify the type of binary +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel Driver +TYPE= SHARED + +# add support for new Pe and Eddie features +# to fill in generic makefile + +#%{ +# @src->@ + +# specify the source files to use +# full paths or paths relative to the makefile can be included +# all files, regardless of directory, will have their object +# files created in the common object directory. +# Note that this means this makefile will not work correctly +# if two source files with the same name (source.c or source.cpp) +# are included from different directories. Also note that spaces +# in folder names do not work well with this makefile. +SRCS= IFS.cpp IFSSaver.cpp + +# specify the resource files to use +# full path or a relative path to the resource file can be used. +RSRCS= IFS.rsrc + +# @<-src@ +#%} + +# end support for Pe and Eddie + +# specify additional libraries to link against +# there are two acceptable forms of library specifications +# - if your library follows the naming pattern of: +# libXXX.so or libXXX.a you can simply specify XXX +# library: libbe.so entry: be +# +# - if your library does not follow the standard library +# naming scheme you need to specify the path to the library +# and it's name +# library: my_lib.a entry: my_lib.a or path/my_lib.a +LIBS= be screensaver stdc++.r4 + +# specify additional paths to directories following the standard +# libXXX.so or libXXX.a naming scheme. You can specify full paths +# or paths relative to the makefile. The paths included may not +# be recursive, so include all of the paths where libraries can +# be found. Directories where source files are found are +# automatically included. +LIBPATHS= + +# additional paths to look for system headers +# thes use the form: #include
+# source file directories are NOT auto-included here +SYSTEM_INCLUDE_PATHS = + +# additional paths to look for local headers +# thes use the form: #include "header" +# source file directories are automatically included +LOCAL_INCLUDE_PATHS = + +# specify the level of optimization that you desire +# NONE, SOME, FULL +OPTIMIZE= FULL + +# specify any preprocessor symbols to be defined. The symbols will not +# have their values set automatically; you must supply the value (if any) +# to use. For example, setting DEFINES to "DEBUG=1" will cause the +# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" +# would pass "-DDEBUG" on the compiler's command line. +DEFINES= + +# specify special warning levels +# if unspecified default warnings will be used +# NONE = supress all warnings +# ALL = enable all warnings +WARNINGS = ALL + +# specify whether image symbols will be created +# so that stack crawls in the debugger are meaningful +# if TRUE symbols will be created +SYMBOLS = + +# specify debug settings +# if TRUE will allow application to be run from a source-level +# debugger. Note that this will disable all optimzation. +DEBUGGER = FALSE + +# specify additional compiler flags for all files +COMPILER_FLAGS = + +# specify additional linker flags +LINKER_FLAGS = + + +## include the makefile-engine +include /boot/develop/etc/makefile-engine +