xref: /haiku/src/add-ons/screen_savers/icons/IconsSaver.cpp (revision 72156a402f54ea4be9dc3e3e9704c612f7d9ad16)
1 /*
2 	Copyright 2009 Vincent Duvert, vincent.duvert@free.fr
3 	All rights reserved. Distributed under the terms of the MIT License.
4 */
5 
6 
7 #include "IconsSaver.h"
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 
12 #include <Bitmap.h>
13 #include <Catalog.h>
14 #include <MimeType.h>
15 #include <StringView.h>
16 
17 #include <BuildScreenSaverDefaultSettingsView.h>
18 
19 #include "IconDisplay.h"
20 
21 #undef B_TRANSLATE_CONTEXT
22 #define B_TRANSLATE_CONTEXT "Screensaver Icons"
23 
24 
25 #define MAX_ICONS 15
26 #define MAX_SIZE 20 // In percentage of the screen width
27 #define MIN_SIZE 5 // Same here
28 #define RAND_BETWEEN(a, b) ((rand() % ((b) - (a) + 1) + (a)))
29 
30 
31 const rgb_color kBackgroundColor = ui_color(B_DESKTOP_COLOR);
32 
33 
34 BScreenSaver* instantiate_screen_saver(BMessage* msg, image_id image)
35 {
36 	return new IconsSaver(msg, image);
37 }
38 
39 
40 IconsSaver::IconsSaver(BMessage* msg, image_id image)
41 	:
42 	BScreenSaver(msg, image),
43 	fVectorIconsCount(0),
44 	fIcons(NULL),
45 	fBackBitmap(NULL),
46 	fBackView(NULL),
47 	fMinSize(0),
48 	fMaxSize(0)
49 {
50 }
51 
52 
53 IconsSaver::~IconsSaver()
54 {
55 }
56 
57 
58 status_t
59 IconsSaver::StartSaver(BView *view, bool /*preview*/)
60 {
61 	if (fVectorIconsCount <= 0) {
62 		// Load the vector icons from the MIME types
63 		BMessage types;
64 		BMimeType::GetInstalledTypes(&types);
65 
66 		for (int32 index = 0 ; ; index++) {
67 			const char* type;
68 			if (types.FindString("types", index, &type) != B_OK)
69 				break;
70 
71 			BMimeType mimeType(type);
72 			uint8* vectorData = NULL;
73 			size_t size = 0;
74 
75 			if (mimeType.GetIcon(&vectorData, &size) != B_OK || size == 0)
76 				continue;
77 
78 			VectorIcon* icon = new VectorIcon;
79 			icon->data = vectorData;
80 			icon->size = size;
81 
82 			fVectorIcons.AddItem(icon);
83 		}
84 
85 		fVectorIconsCount = fVectorIcons.CountItems();
86 	}
87 
88 	srand(system_time() % INT_MAX);
89 
90 	BRect screenRect(0, 0, view->Frame().Width(), view->Frame().Height());
91 	fBackBitmap = new BBitmap(screenRect, B_RGBA32, true);
92 	if (!fBackBitmap->IsValid())
93 		return B_NO_MEMORY;
94 
95 	fBackView = new BView(screenRect, "back view", 0, 0);
96 	if (fBackView == NULL)
97 		return B_NO_MEMORY;
98 
99 	fBackView->SetViewColor(kBackgroundColor);
100 	fBackView->SetHighColor(kBackgroundColor);
101 
102 	fBackBitmap->AddChild(fBackView);
103 	if (fBackBitmap->Lock()) {
104 		fBackView->FillRect(fBackView->Frame());
105 		fBackView->SetDrawingMode(B_OP_ALPHA);
106 		fBackView->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
107 		fBackView->Sync();
108 		fBackBitmap->Unlock();
109 	}
110 
111 	fIcons = new IconDisplay[MAX_ICONS];
112 
113 	fMaxSize = (screenRect.IntegerWidth() * MAX_SIZE) / 100;
114 	fMinSize = (screenRect.IntegerWidth() * MIN_SIZE) / 100;
115 	if (fMaxSize > 255)
116 		fMaxSize = 255;
117 
118 	if (fMaxSize > screenRect.IntegerHeight())
119 		fMaxSize = screenRect.IntegerHeight();
120 
121 	if (fMinSize > fMaxSize)
122 		fMinSize = fMaxSize;
123 
124 	return B_OK;
125 }
126 
127 
128 void
129 IconsSaver::StopSaver()
130 {
131 	delete[] fIcons;
132 }
133 
134 
135 void
136 IconsSaver::Draw(BView *view, int32 frame)
137 {
138 	static int32 previousFrame = 0;
139 
140 	// Update drawing
141 	if (fBackBitmap->Lock()) {
142 		for (uint8 i = 0 ; i < MAX_ICONS ; i++) {
143 			fIcons[i].ClearOn(fBackView);
144 		}
145 
146 		int32 delta = frame - previousFrame;
147 
148 		for (uint8 i = 0 ; i < MAX_ICONS ; i++) {
149 			fIcons[i].DrawOn(fBackView, delta);
150 		}
151 		fBackView->Sync();
152 		fBackBitmap->Unlock();
153 	}
154 
155 	// Sync the view with the back buffer
156 	view->DrawBitmap(fBackBitmap);
157 	previousFrame = frame;
158 
159 	if (fVectorIconsCount <= 0)
160 		return;
161 
162 	// Restart one icon
163 	for (uint8 i = 0 ; i < MAX_ICONS ; i++) {
164 		if (!fIcons[i].IsRunning()) {
165 			uint16 size = RAND_BETWEEN(fMinSize, fMaxSize);
166 			uint16 maxX = view->Frame().IntegerWidth() - size;
167 			uint16 maxY = view->Frame().IntegerHeight() - size;
168 
169 			BRect iconFrame(0, 0, size, size);
170 			iconFrame.OffsetTo(RAND_BETWEEN(0, maxX), RAND_BETWEEN(0, maxY));
171 
172 			// Check that the icon doesn't overlap with others
173 			for (uint8 j = 0 ; j < MAX_ICONS ; j++) {
174 				if (fIcons[j].IsRunning() &&
175 					iconFrame.Intersects(fIcons[j].GetFrame()))
176 					return;
177 			}
178 
179 			int32 index = RAND_BETWEEN(0, fVectorIconsCount - 1);
180 
181 			fIcons[i].Run((VectorIcon*)fVectorIcons.ItemAt(index), iconFrame);
182 
183 			return;
184 		}
185 	}
186 }
187 
188 
189 void
190 IconsSaver::StartConfig(BView* view)
191 {
192 	BPrivate::BuildScreenSaverDefaultSettingsView(view, "Icons",
193 		B_TRANSLATE("by Vincent Duvert"));
194 }
195 
196