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_TRANSLATION_CONTEXT 22 #define B_TRANSLATION_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