3rdparty/licenseReport: Add seperate LGPL checks
[haiku.git] / src / add-ons / screen_savers / butterfly / Butterfly.cpp
blob99256b6699ae997ebf16f482ba465606dcd5e9b3
1 /*
2 * Copyright 2010-2011, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Geoffry Song, goffrie@gmail.com
7 * Ryan Leavengood, leavengood@gmail.com
8 */
11 #include "Butterfly.h"
13 #include <math.h>
14 #include <stdlib.h>
16 #include <Catalog.h>
17 #include <DefaultSettingsView.h>
18 #include <OS.h>
19 #include <View.h>
21 #undef B_TRANSLATION_CONTEXT
22 #define B_TRANSLATION_CONTEXT "Screensaver Butterfly"
25 extern "C" BScreenSaver*
26 instantiate_screen_saver(BMessage* archive, image_id imageId)
28 return new Butterfly(archive, imageId);
32 // #pragma mark -
35 Butterfly::Butterfly(BMessage* archive, image_id imageId)
37 BScreenSaver(archive, imageId)
42 void
43 Butterfly::StartConfig(BView* view)
45 BPrivate::BuildDefaultSettingsView(view, "Butterfly",
46 B_TRANSLATE("by Geoffry Song"));
50 status_t
51 Butterfly::StartSaver(BView* view, bool preview)
53 view->SetLowColor(0, 0, 0);
54 view->FillRect(view->Bounds(), B_SOLID_LOW);
55 view->SetDrawingMode(B_OP_ALPHA);
56 view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
57 view->SetLineMode(B_ROUND_CAP, B_ROUND_JOIN);
58 if (!preview)
59 view->SetPenSize(2.0);
61 SetTickSize(20000);
63 // Set fBase to a random radian value scaled by 1000. The scaling produces
64 // more interesting results.
65 srand48(system_time());
66 fBase = drand48() * 2 * M_PI * 1000;
68 // calculate transformation
69 BRect bounds = view->Bounds();
70 fScale = MIN(bounds.Width(), bounds.Height()) * 0.1f;
71 fTrans.Set(bounds.Width() * 0.5f, bounds.Height() * 0.5f);
72 fBounds = bounds;
74 fLast[0] = _Iterate();
75 fLast[1] = _Iterate();
76 fLast[2] = _Iterate();
78 return B_OK;
82 void
83 Butterfly::Draw(BView* view, int32 frame)
85 if (frame == 1024) {
86 // calculate bounding box ( (-5.92,-5.92) to (5.92, 5.92) )
87 fBounds.Set(-5.92f * fScale + fTrans.x, -5.92f * fScale + fTrans.y,
88 5.92f * fScale + fTrans.x, 5.92f * fScale + fTrans.y);
90 if ((frame & 3) == 0) {
91 // fade out
92 view->SetHighColor(0, 0, 0, 4);
93 view->FillRect(fBounds);
95 // create a color from a hue of (fBase * 15) degrees
96 view->SetHighColor(_HueToColor(fBase * 15));
97 BPoint p = _Iterate();
99 // cubic Hermite interpolation from fLast[1] to fLast[2]
100 // calculate tangents for a Catmull-Rom spline
101 //(these values need to be halved)
102 BPoint m1 = fLast[2] - fLast[0]; // tangent for fLast[1]
103 BPoint m2 = p - fLast[1]; // tangent for fLast[2]
105 // draw Bezier from fLast[1] to fLast[2] with control points
106 // fLast[1] + m1/3, fLast[2] - m2/3
107 m1.x /= 6;
108 m1.y /= 6;
109 m2.x /= 6;
110 m2.y /= 6;
111 BPoint control[4] = { fLast[1], fLast[1] + m1, fLast[2] - m2, fLast[2] };
112 view->StrokeBezier(control);
114 fLast[0] = fLast[1];
115 fLast[1] = fLast[2];
116 fLast[2] = p;
120 //! Convert from a hue in degrees to a fully saturated color
121 inline rgb_color
122 Butterfly::_HueToColor(float hue)
124 // convert from [0..360) to [0..1530)
125 int h = static_cast<int>(fmodf(hue, 360) * 4.25f);
126 int x = 255 - abs(h % 510 - 255);
128 rgb_color result = {0, 0, 0, 255};
129 if (h < 255) {
130 result.red = 255;
131 result.green = x;
132 } else if (h < 510) {
133 result.red = x;
134 result.green = 255;
135 } else if (h < 765) {
136 result.green = 255;
137 result.blue = x;
138 } else if (h < 1020) {
139 result.green = x;
140 result.blue = 255;
141 } else if (h < 1275) {
142 result.red = x;
143 result.blue = 255;
144 } else {
145 result.red = 255;
146 result.blue = x;
148 return result;
152 inline BPoint
153 Butterfly::_Iterate()
155 float r = powf(M_E, cosf(fBase)) - 2 * cosf(4 * fBase)
156 - powf(sinf(fBase / 12), 5);
157 // rotate and move it a bit
158 BPoint p(sinf(fBase * 1.01f) * r + cosf(fBase * 1.02f) * 0.2f,
159 cosf(fBase * 1.01f) * r + sinf(fBase * 1.02f) * 0.2f);
160 // transform to view coordinates
161 p.x *= fScale;
162 p.y *= fScale;
163 p += fTrans;
164 // move on
165 fBase += 0.05f;
166 return p;