Icons Screensaver: Grab vector icons via query, fixes #10166

Iterate through each BFS volume and find vector icon data in apps
using a BFS query. Cap off at 128 total icons, we could get more if
desired. Default install comes with ~100 at present.

Make sure we have at least 20 icons (15 display at a time) before we
start drawing icons.

Rename VectorIcon to vector_icon and treat it like the POD struct that it is.
Also add a type_code parame to vector_icon that should be set to
B_VECTOR_ICON.

Some style fixes also included, e.g. turned defines into static const int32’s.
This commit is contained in:
John Scipione
2014-01-22 20:43:22 -05:00
parent 3cbb1132f8
commit 0def0b0d62
4 changed files with 98 additions and 58 deletions
@@ -42,7 +42,7 @@ IconDisplay::~IconDisplay()
void void
IconDisplay::Run(VectorIcon* icon, BRect frame) IconDisplay::Run(vector_icon* icon, BRect frame)
{ {
delete fBitmap; delete fBitmap;
+10 -7
View File
@@ -12,11 +12,14 @@
#include <Rect.h> #include <Rect.h>
#include <SupportDefs.h>
#include <View.h> #include <View.h>
struct VectorIcon {
uint8* data; struct vector_icon {
size_t size; uint8* data;
size_t size;
type_code type;
}; };
@@ -27,10 +30,10 @@ class IconDisplay {
public: public:
IconDisplay(); IconDisplay();
~IconDisplay(); ~IconDisplay();
void Run(VectorIcon* icon, BRect frame); void Run(vector_icon* icon, BRect frame);
inline bool IsRunning() { return fIsRunning; }; inline bool IsRunning() const { return fIsRunning; };
inline BRect GetFrame() { return fFrame; }; inline BRect GetFrame() const { return fFrame; };
void ClearOn(BView* view); void ClearOn(BView* view);
void DrawOn(BView* view, uint32 delta); void DrawOn(BView* view, uint32 delta);
+82 -45
View File
@@ -16,8 +16,14 @@
#include <Bitmap.h> #include <Bitmap.h>
#include <Catalog.h> #include <Catalog.h>
#include <Entry.h>
#include <MimeType.h> #include <MimeType.h>
#include <Node.h>
#include <NodeInfo.h>
#include <StringView.h> #include <StringView.h>
#include <Query.h>
#include <Volume.h>
#include <VolumeRoster.h>
#include <BuildScreenSaverDefaultSettingsView.h> #include <BuildScreenSaverDefaultSettingsView.h>
@@ -28,12 +34,18 @@
#define B_TRANSLATION_CONTEXT "Screensaver Icons" #define B_TRANSLATION_CONTEXT "Screensaver Icons"
#define MAX_ICONS 15
#define MAX_SIZE 20 // In percentage of the screen width
#define MIN_SIZE 5 // Same here
#define RAND_BETWEEN(a, b) ((rand() % ((b) - (a) + 1) + (a))) #define RAND_BETWEEN(a, b) ((rand() % ((b) - (a) + 1) + (a)))
static const int32 kMaxConcurrentIcons = 15;
static const int32 kMinIconWidthPercentage = 5;
// percentage of the screen width
static const int32 kMaxIconWidthPercentage = 20;
// same here
static const int32 kMinIconCount = 20;
static const int32 kMaxIconCount = 128;
const rgb_color kBackgroundColor = ui_color(B_DESKTOP_COLOR); const rgb_color kBackgroundColor = ui_color(B_DESKTOP_COLOR);
@@ -67,32 +79,8 @@ IconsSaver::~IconsSaver()
status_t status_t
IconsSaver::StartSaver(BView* view, bool /*preview*/) IconsSaver::StartSaver(BView* view, bool /*preview*/)
{ {
if (fVectorIconsCount <= 0) { if (fVectorIcons.CountItems() < kMinIconCount)
// Load the vector icons from the MIME types _GetVectorIcons();
BMessage types;
BMimeType::GetInstalledTypes(&types);
for (int32 index = 0 ; ; index++) {
const char* type;
if (types.FindString("types", index, &type) != B_OK)
break;
BMimeType mimeType(type);
uint8* vectorData = NULL;
size_t size = 0;
if (mimeType.GetIcon(&vectorData, &size) != B_OK || size == 0)
continue;
VectorIcon* icon = new VectorIcon;
icon->data = vectorData;
icon->size = size;
fVectorIcons.AddItem(icon);
}
fVectorIconsCount = fVectorIcons.CountItems();
}
srand(system_time() % INT_MAX); srand(system_time() % INT_MAX);
@@ -117,10 +105,10 @@ IconsSaver::StartSaver(BView* view, bool /*preview*/)
fBackBitmap->Unlock(); fBackBitmap->Unlock();
} }
fIcons = new IconDisplay[MAX_ICONS]; fIcons = new IconDisplay[kMaxConcurrentIcons];
fMaxSize = (screenRect.IntegerWidth() * MAX_SIZE) / 100; fMaxSize = (screenRect.IntegerWidth() * kMaxIconWidthPercentage) / 100;
fMinSize = (screenRect.IntegerWidth() * MIN_SIZE) / 100; fMinSize = (screenRect.IntegerWidth() * kMinIconWidthPercentage) / 100;
if (fMaxSize > 255) if (fMaxSize > 255)
fMaxSize = 255; fMaxSize = 255;
@@ -148,15 +136,13 @@ IconsSaver::Draw(BView* view, int32 frame)
// update drawing // update drawing
if (fBackBitmap->Lock()) { if (fBackBitmap->Lock()) {
for (uint8 i = 0 ; i < MAX_ICONS ; i++) { for (uint8 i = 0 ; i < kMaxConcurrentIcons ; i++)
fIcons[i].ClearOn(fBackView); fIcons[i].ClearOn(fBackView);
}
int32 delta = frame - previousFrame; int32 delta = frame - previousFrame;
for (uint8 i = 0 ; i < kMaxConcurrentIcons ; i++)
for (uint8 i = 0 ; i < MAX_ICONS ; i++) {
fIcons[i].DrawOn(fBackView, delta); fIcons[i].DrawOn(fBackView, delta);
}
fBackView->Sync(); fBackView->Sync();
fBackBitmap->Unlock(); fBackBitmap->Unlock();
} }
@@ -165,11 +151,11 @@ IconsSaver::Draw(BView* view, int32 frame)
view->DrawBitmap(fBackBitmap); view->DrawBitmap(fBackBitmap);
previousFrame = frame; previousFrame = frame;
if (fVectorIconsCount <= 0) if (fVectorIcons.CountItems() < kMinIconCount)
return; return;
// Restart one icon // restart one icon
for (uint8 i = 0 ; i < MAX_ICONS ; i++) { for (uint8 i = 0 ; i < kMaxConcurrentIcons ; i++) {
if (!fIcons[i].IsRunning()) { if (!fIcons[i].IsRunning()) {
uint16 size = RAND_BETWEEN(fMinSize, fMaxSize); uint16 size = RAND_BETWEEN(fMinSize, fMaxSize);
uint16 maxX = view->Frame().IntegerWidth() - size; uint16 maxX = view->Frame().IntegerWidth() - size;
@@ -179,16 +165,14 @@ IconsSaver::Draw(BView* view, int32 frame)
iconFrame.OffsetTo(RAND_BETWEEN(0, maxX), RAND_BETWEEN(0, maxY)); iconFrame.OffsetTo(RAND_BETWEEN(0, maxX), RAND_BETWEEN(0, maxY));
// Check that the icon doesn't overlap with others // Check that the icon doesn't overlap with others
for (uint8 j = 0 ; j < MAX_ICONS ; j++) { for (uint8 j = 0 ; j < kMaxConcurrentIcons ; j++) {
if (fIcons[j].IsRunning() && if (fIcons[j].IsRunning() &&
iconFrame.Intersects(fIcons[j].GetFrame())) iconFrame.Intersects(fIcons[j].GetFrame()))
return; return;
} }
int32 index = RAND_BETWEEN(0, fVectorIconsCount - 1); int32 index = RAND_BETWEEN(0, fVectorIcons.CountItems() - 1);
fIcons[i].Run((vector_icon*)fVectorIcons.ItemAt(index), iconFrame);
fIcons[i].Run((VectorIcon*)fVectorIcons.ItemAt(index), iconFrame);
return; return;
} }
} }
@@ -202,3 +186,56 @@ IconsSaver::StartConfig(BView* view)
B_TRANSLATE("by Vincent Duvert")); B_TRANSLATE("by Vincent Duvert"));
} }
// #pragma mark - IconsSaver private methods
void
IconsSaver::_GetVectorIcons()
{
BVolumeRoster volumeRoster;
BVolume volume;
while (volumeRoster.GetNextVolume(&volume) == B_OK) {
if (!volume.KnowsAttr() || !volume.KnowsMime() || !volume.KnowsQuery())
continue;
BQuery query;
query.SetVolume(&volume);
query.SetPredicate("BEOS:APP_SIG=*");
query.Fetch();
entry_ref ref;
while (query.GetNextRef(&ref) == B_OK) {
BFile file(&ref, B_READ_ONLY);
if (file.InitCheck() != B_OK)
continue;
struct vector_icon* icon
= (struct vector_icon*)malloc(sizeof(struct vector_icon));
if (icon == NULL)
continue;
BNode node(&ref);
BNodeInfo nodeInfo(&node);
if (nodeInfo.InitCheck() != B_OK
|| nodeInfo.GetIcon(&icon->data, &icon->size, &icon->type)
!= B_OK) {
// didn't find an icon
continue;
}
if (icon->type != B_VECTOR_ICON_TYPE) {
// found an icon, but it's not a vector icon
delete icon;
continue;
}
// found a vector icon, add it to the list
fVectorIcons.AddItem(icon);
if (fVectorIcons.CountItems() >= kMaxIconCount) {
// this is enough to choose from, stop eating memory...
return;
}
}
}
}
+5 -5
View File
@@ -31,13 +31,13 @@ public:
virtual void StartConfig(BView* view); virtual void StartConfig(BView* view);
private: private:
BList fVectorIcons; void _GetVectorIcons();
int32 fVectorIconsCount;
IconDisplay* fIcons;
BBitmap* fBackBitmap; BList fVectorIcons;
BView* fBackView; IconDisplay* fIcons;
BBitmap* fBackBitmap;
BView* fBackView;
uint16 fMinSize; uint16 fMinSize;
uint16 fMaxSize; uint16 fMaxSize;