diff --git a/src/add-ons/screen_savers/icons/IconDisplay.cpp b/src/add-ons/screen_savers/icons/IconDisplay.cpp index 52de1dbc66..3c3ca0b9f7 100644 --- a/src/add-ons/screen_savers/icons/IconDisplay.cpp +++ b/src/add-ons/screen_savers/icons/IconDisplay.cpp @@ -42,7 +42,7 @@ IconDisplay::~IconDisplay() void -IconDisplay::Run(VectorIcon* icon, BRect frame) +IconDisplay::Run(vector_icon* icon, BRect frame) { delete fBitmap; diff --git a/src/add-ons/screen_savers/icons/IconDisplay.h b/src/add-ons/screen_savers/icons/IconDisplay.h index 67f8d3d56c..d077753603 100644 --- a/src/add-ons/screen_savers/icons/IconDisplay.h +++ b/src/add-ons/screen_savers/icons/IconDisplay.h @@ -12,11 +12,14 @@ #include +#include #include -struct VectorIcon { - uint8* data; - size_t size; + +struct vector_icon { + uint8* data; + size_t size; + type_code type; }; @@ -27,10 +30,10 @@ class IconDisplay { public: IconDisplay(); ~IconDisplay(); - - void Run(VectorIcon* icon, BRect frame); - inline bool IsRunning() { return fIsRunning; }; - inline BRect GetFrame() { return fFrame; }; + + void Run(vector_icon* icon, BRect frame); + inline bool IsRunning() const { return fIsRunning; }; + inline BRect GetFrame() const { return fFrame; }; void ClearOn(BView* view); void DrawOn(BView* view, uint32 delta); diff --git a/src/add-ons/screen_savers/icons/IconsSaver.cpp b/src/add-ons/screen_savers/icons/IconsSaver.cpp index a58e553d74..8f23d45130 100644 --- a/src/add-ons/screen_savers/icons/IconsSaver.cpp +++ b/src/add-ons/screen_savers/icons/IconsSaver.cpp @@ -16,8 +16,14 @@ #include #include +#include #include +#include +#include #include +#include +#include +#include #include @@ -28,12 +34,18 @@ #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))) +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); @@ -67,32 +79,8 @@ IconsSaver::~IconsSaver() status_t IconsSaver::StartSaver(BView* view, bool /*preview*/) { - if (fVectorIconsCount <= 0) { - // Load the vector icons from the MIME types - 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(); - } + if (fVectorIcons.CountItems() < kMinIconCount) + _GetVectorIcons(); srand(system_time() % INT_MAX); @@ -117,10 +105,10 @@ IconsSaver::StartSaver(BView* view, bool /*preview*/) fBackBitmap->Unlock(); } - fIcons = new IconDisplay[MAX_ICONS]; + fIcons = new IconDisplay[kMaxConcurrentIcons]; - fMaxSize = (screenRect.IntegerWidth() * MAX_SIZE) / 100; - fMinSize = (screenRect.IntegerWidth() * MIN_SIZE) / 100; + fMaxSize = (screenRect.IntegerWidth() * kMaxIconWidthPercentage) / 100; + fMinSize = (screenRect.IntegerWidth() * kMinIconWidthPercentage) / 100; if (fMaxSize > 255) fMaxSize = 255; @@ -148,15 +136,13 @@ IconsSaver::Draw(BView* view, int32 frame) // update drawing if (fBackBitmap->Lock()) { - for (uint8 i = 0 ; i < MAX_ICONS ; i++) { + for (uint8 i = 0 ; i < kMaxConcurrentIcons ; i++) fIcons[i].ClearOn(fBackView); - } int32 delta = frame - previousFrame; - - for (uint8 i = 0 ; i < MAX_ICONS ; i++) { + for (uint8 i = 0 ; i < kMaxConcurrentIcons ; i++) fIcons[i].DrawOn(fBackView, delta); - } + fBackView->Sync(); fBackBitmap->Unlock(); } @@ -165,11 +151,11 @@ IconsSaver::Draw(BView* view, int32 frame) view->DrawBitmap(fBackBitmap); previousFrame = frame; - if (fVectorIconsCount <= 0) + if (fVectorIcons.CountItems() < kMinIconCount) return; - // Restart one icon - for (uint8 i = 0 ; i < MAX_ICONS ; i++) { + // restart one icon + for (uint8 i = 0 ; i < kMaxConcurrentIcons ; i++) { if (!fIcons[i].IsRunning()) { uint16 size = RAND_BETWEEN(fMinSize, fMaxSize); 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)); // 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() && iconFrame.Intersects(fIcons[j].GetFrame())) return; } - int32 index = RAND_BETWEEN(0, fVectorIconsCount - 1); - - fIcons[i].Run((VectorIcon*)fVectorIcons.ItemAt(index), iconFrame); - + int32 index = RAND_BETWEEN(0, fVectorIcons.CountItems() - 1); + fIcons[i].Run((vector_icon*)fVectorIcons.ItemAt(index), iconFrame); return; } } @@ -202,3 +186,56 @@ IconsSaver::StartConfig(BView* view) 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; + } + } + } +} diff --git a/src/add-ons/screen_savers/icons/IconsSaver.h b/src/add-ons/screen_savers/icons/IconsSaver.h index 82431ff5ef..6def51b8d6 100644 --- a/src/add-ons/screen_savers/icons/IconsSaver.h +++ b/src/add-ons/screen_savers/icons/IconsSaver.h @@ -31,13 +31,13 @@ public: virtual void StartConfig(BView* view); private: - BList fVectorIcons; - int32 fVectorIconsCount; - IconDisplay* fIcons; + void _GetVectorIcons(); - BBitmap* fBackBitmap; - BView* fBackView; + BList fVectorIcons; + IconDisplay* fIcons; + BBitmap* fBackBitmap; + BView* fBackView; uint16 fMinSize; uint16 fMaxSize;