1 /* 2 * Copyright 2009 Vincent Duvert, vincent.duvert@free.fr 3 * Copyright 2014 Haiku, Inc. All rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 * 7 * Authors: 8 * Vincent Duvert, vincent.duvert@free.fr 9 * John Scipione, jscipione@gmail.com 10 */ 11 12 13 #include "IconsSaver.h" 14 15 #include <stdlib.h> 16 17 #include <Bitmap.h> 18 #include <Catalog.h> 19 #include <DefaultSettingsView.h> 20 #include <MimeType.h> 21 22 #include "IconDisplay.h" 23 #include "VectorIcon.h" 24 25 26 #undef B_TRANSLATION_CONTEXT 27 #define B_TRANSLATION_CONTEXT "Screensaver Icons" 28 29 30 #define RAND_BETWEEN(a, b) ((rand() % ((b) - (a) + 1) + (a))) 31 32 33 static const int32 kMaxConcurrentIcons = 15; 34 static const int32 kMinIconWidthPercentage = 5; 35 // percentage of the screen width 36 static const int32 kMaxIconWidthPercentage = 20; 37 // same here 38 static const int32 kMinIconCount = 20; 39 static const int32 kMaxIconCount = 384; 40 41 42 const rgb_color kBackgroundColor = ui_color(B_DESKTOP_COLOR); 43 44 45 BScreenSaver* instantiate_screen_saver(BMessage* msg, image_id image) 46 { 47 return new IconsSaver(msg, image); 48 } 49 50 51 // #pragma mark - IconsSaver 52 53 54 IconsSaver::IconsSaver(BMessage* archive, image_id image) 55 : 56 BScreenSaver(archive, image), 57 fIcons(NULL), 58 fBackBitmap(NULL), 59 fBackView(NULL), 60 fMinSize(0), 61 fMaxSize(0) 62 { 63 } 64 65 66 IconsSaver::~IconsSaver() 67 { 68 } 69 70 71 status_t 72 IconsSaver::StartSaver(BView* view, bool /*preview*/) 73 { 74 if (fVectorIcons.CountItems() < kMinIconCount) 75 _GetVectorIcons(); 76 77 srand(system_time() % INT_MAX); 78 79 BRect screenRect(0, 0, view->Frame().Width(), view->Frame().Height()); 80 fBackBitmap = new BBitmap(screenRect, B_RGBA32, true); 81 if (!fBackBitmap->IsValid()) 82 return B_NO_MEMORY; 83 84 fBackView = new BView(screenRect, "back view", 0, 0); 85 if (fBackView == NULL) 86 return B_NO_MEMORY; 87 88 fBackView->SetViewColor(kBackgroundColor); 89 fBackView->SetHighColor(kBackgroundColor); 90 91 fBackBitmap->AddChild(fBackView); 92 if (fBackBitmap->Lock()) { 93 fBackView->FillRect(fBackView->Frame()); 94 fBackView->SetDrawingMode(B_OP_ALPHA); 95 fBackView->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); 96 fBackView->Sync(); 97 fBackBitmap->Unlock(); 98 } 99 100 fIcons = new IconDisplay[kMaxConcurrentIcons]; 101 102 fMaxSize = (screenRect.IntegerWidth() * kMaxIconWidthPercentage) / 100; 103 fMinSize = (screenRect.IntegerWidth() * kMinIconWidthPercentage) / 100; 104 if (fMaxSize > 255) 105 fMaxSize = 255; 106 107 if (fMaxSize > screenRect.IntegerHeight()) 108 fMaxSize = screenRect.IntegerHeight(); 109 110 if (fMinSize > fMaxSize) 111 fMinSize = fMaxSize; 112 113 return B_OK; 114 } 115 116 117 void 118 IconsSaver::StopSaver() 119 { 120 delete[] fIcons; 121 fIcons = NULL; 122 } 123 124 125 void 126 IconsSaver::Draw(BView* view, int32 frame) 127 { 128 static int32 previousFrame = 0; 129 130 // update drawing 131 if (fBackBitmap->Lock()) { 132 for (uint8 i = 0 ; i < kMaxConcurrentIcons ; i++) 133 fIcons[i].ClearOn(fBackView); 134 135 int32 delta = frame - previousFrame; 136 for (uint8 i = 0 ; i < kMaxConcurrentIcons ; i++) 137 fIcons[i].DrawOn(fBackView, delta); 138 139 fBackView->Sync(); 140 fBackBitmap->Unlock(); 141 } 142 143 // sync the view with the back buffer 144 view->DrawBitmap(fBackBitmap); 145 previousFrame = frame; 146 147 if (fVectorIcons.CountItems() < kMinIconCount) 148 return; 149 150 // restart one icon 151 for (uint8 i = 0 ; i < kMaxConcurrentIcons ; i++) { 152 if (!fIcons[i].IsRunning()) { 153 uint16 size = RAND_BETWEEN(fMinSize, fMaxSize); 154 uint16 maxX = view->Frame().IntegerWidth() - size; 155 uint16 maxY = view->Frame().IntegerHeight() - size; 156 157 BRect iconFrame(0, 0, size, size); 158 iconFrame.OffsetTo(RAND_BETWEEN(0, maxX), RAND_BETWEEN(0, maxY)); 159 160 // Check that the icon doesn't overlap with others 161 for (uint8 j = 0 ; j < kMaxConcurrentIcons ; j++) { 162 if (fIcons[j].IsRunning() && 163 iconFrame.Intersects(fIcons[j].GetFrame())) 164 return; 165 } 166 167 int32 index = RAND_BETWEEN(0, fVectorIcons.CountItems() - 1); 168 fIcons[i].Run(fVectorIcons.ItemAt(index), iconFrame); 169 return; 170 } 171 } 172 } 173 174 175 void 176 IconsSaver::StartConfig(BView* view) 177 { 178 BPrivate::BuildDefaultSettingsView(view, "Icons", 179 B_TRANSLATE("by Vincent Duvert")); 180 } 181 182 183 // #pragma mark - IconsSaver private methods 184 185 186 void 187 IconsSaver::_GetVectorIcons() 188 { 189 // Load vector icons from the MIME type database 190 BMessage types; 191 if (BMimeType::GetInstalledTypes(&types) != B_OK) 192 return; 193 194 const char* type; 195 for (int32 i = 0; types.FindString("types", i, &type) == B_OK; i++) { 196 BMimeType mimeType(type); 197 if (mimeType.InitCheck() != B_OK) 198 continue; 199 200 uint8* data; 201 size_t size; 202 203 if (mimeType.GetIcon(&data, &size) != B_OK) { 204 // didn't find an icon 205 continue; 206 } 207 208 vector_icon* icon = (vector_icon*)malloc(sizeof(vector_icon)); 209 if (icon == NULL) { 210 // ran out of memory, delete the icon data 211 delete[] data; 212 continue; 213 } 214 215 icon->data = data; 216 icon->size = size; 217 218 // found a vector icon, add it to the list 219 fVectorIcons.AddItem(icon); 220 if (fVectorIcons.CountItems() >= kMaxIconCount) { 221 // this is enough to choose from, stop eating memory... 222 return; 223 } 224 } 225 } 226