]> git.tdb.fi Git - libs/gui.git/commitdiff
Implement automatic registration of image loaders
authorMikko Rasa <tdb@tdb.fi>
Mon, 7 Oct 2013 18:13:15 +0000 (21:13 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 7 Oct 2013 18:13:15 +0000 (21:13 +0300)
source/graphics/devil/devilloader.cpp
source/graphics/devil/devilloader.h
source/graphics/imageloader.cpp
source/graphics/imageloader.h
source/graphics/png/pngloader.cpp
source/graphics/png/pngloader.h

index 392bde8f8099b08422f359d19086abe695097039..88beb04802d47025c2995d886d227d3d6dc3d78d 100644 (file)
@@ -59,6 +59,8 @@ int tell(void *handle)
 namespace Msp {
 namespace Graphics {
 
+ImageLoader::Register<DevilLoader> DevilLoader::reg;
+
 DevilLoader::DevilLoader(IO::Seekable &i):
        io(i)
 {
index 3b933ae2ff0cc9c0e52de2a7161a91b2c277f8e1..daab2a2bdc64b763575cc03886dfd11df9d52154 100644 (file)
@@ -12,10 +12,13 @@ private:
        IO::Base &io;
        unsigned id;
 
+       static Register<DevilLoader> reg;
+
 public:
        DevilLoader(IO::Seekable &);
        virtual ~DevilLoader();
 
+       static unsigned get_signature_size() { return 128; }
        static bool detect(const std::string &);
 
        virtual void load(Image::Data &);
index 6cdaef912e65062740c284559b3851c742bd102b..15f0e50f7e14b1142f2ce664f542d7f4fbcd7618 100644 (file)
@@ -2,18 +2,14 @@
 #include <msp/io/file.h>
 #include <msp/strings/format.h>
 #include "imageloader.h"
-#ifdef WITH_LIBPNG
-#include "png/pngloader.h"
-#endif
-#ifdef WITH_DEVIL
-#include "devil/devilloader.h"
-#endif
 
 using namespace std;
 
 namespace Msp {
 namespace Graphics {
 
+bool ImageLoader::registered_loaders_changed = false;
+
 ImageLoader::ImageLoader():
        source(0)
 { }
@@ -40,24 +36,25 @@ ImageLoader *ImageLoader::open_file(const string &fn)
 
 ImageLoader *ImageLoader::open_io(IO::Seekable &io)
 {
-       char sig_buf[8];
-       unsigned sig_len = io.read(sig_buf, sizeof(sig_buf));
-       string sig(sig_buf, sig_len);
-       io.seek(0, IO::S_BEG);
+       list<RegisterBase *> &loaders = get_registered_loaders();
+       if(registered_loaders_changed)
+       {
+               registered_loaders_changed = false;
+               loaders.sort(signature_size_compare);
+       }
+
+       vector<char> sig_buf(loaders.back()->get_signature_size());
+       unsigned sig_len = io.read(&sig_buf[0], sig_buf.size());
+       string signature(sig_buf.begin(), sig_buf.end());
 
-       // TODO register loader classes automatically
        ImageLoader *loader = 0;
-       if(0)
-               ;
-#ifdef WITH_LIBPNG
-       else if(PngLoader::detect(sig))
-               loader = new PngLoader(io);
-#endif
-#ifdef WITH_DEVIL
-       else if(DevilLoader::detect(sig))
-               loader = new DevilLoader(io);
-#endif
-       else
+       for(list<RegisterBase *>::const_iterator i=loaders.begin(); (!loader && i!=loaders.end()); ++i)
+               if((*i)->detect(signature))
+                       loader = (*i)->create(io);
+
+       io.seek(0, IO::S_BEG);
+
+       if(!loader)
        {
                string sig_hex;
                for(unsigned i=0; i<sig_len; ++i)
@@ -72,5 +69,24 @@ ImageLoader *ImageLoader::open_io(IO::Seekable &io)
        return loader;
 }
 
+
+ImageLoader::RegisterBase::RegisterBase()
+{
+       get_registered_loaders().push_back(this);
+       registered_loaders_changed = true;
+}
+
+
+list<ImageLoader::RegisterBase *> &ImageLoader::get_registered_loaders()
+{
+       static list<RegisterBase *> regs;
+       return regs;
+}
+
+bool ImageLoader::signature_size_compare(RegisterBase *r1, RegisterBase *r2)
+{
+       return r1->get_signature_size()<r2->get_signature_size();
+}
+
 } // namespace Graphics
 } // namespace Msp
index f953990c696458dffb587d0a3fd3889fe10b9975..c06a7592fcf75bc1cf9ea918ceae470424ad785d 100644 (file)
@@ -24,9 +24,36 @@ public:
 class ImageLoader
 {
 private:
-       IO::Base *source;
+       class RegisterBase
+       {
+       protected:
+               RegisterBase();
+       public:
+               virtual ~RegisterBase() { }
+
+               virtual unsigned get_signature_size() const = 0;
+               virtual bool detect(const std::string &) const = 0;
+               virtual ImageLoader *create(IO::Seekable &) const = 0;
+       };
+
 protected:
+       template<typename T>
+       class Register: RegisterBase
+       {
+       public:
+               virtual unsigned get_signature_size() const { return T::get_signature_size(); }
+               virtual bool detect(const std::string &s) const { return T::detect(s); }
+               virtual T *create(IO::Seekable &io) const { return new T(io); }
+       };
+
+private:
+       IO::Base *source;
 
+       static std::list<RegisterBase *> &get_registered_loaders();
+       static bool registered_loaders_changed;
+       static bool signature_size_compare(RegisterBase *, RegisterBase *);
+
+protected:
        ImageLoader();
 public:
        virtual ~ImageLoader();
index 3f2f95912da05dd068075064edca261b47f521ee..15684b1ea5e57dfd678ef91de6d0db0304384c21 100644 (file)
@@ -31,6 +31,8 @@ struct PngLoader::Private
        png_info *info;
 };
 
+ImageLoader::Register<PngLoader> PngLoader::reg;
+
 PngLoader::PngLoader(IO::Base &io, unsigned sig_bytes):
        priv(new Private)
 {
index a81c34c3c49811318ed4cd912b70a98a43c48780..683f4d37389d3e98189b7edeaf41876c716a6f94 100644 (file)
@@ -13,10 +13,13 @@ private:
 
        Private *priv;
 
+       static Register<PngLoader> reg;
+
 public:
        PngLoader(IO::Base &, unsigned = 0);
        virtual ~PngLoader();
 
+       static unsigned get_signature_size() { return 8; }
        static bool detect(const std::string &);
 
        virtual void load(Image::Data &);