From 21b0c47700f1b570b6129384ce0b96a0c6b48ffd Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 7 Oct 2013 21:13:15 +0300 Subject: [PATCH] Implement automatic registration of image loaders --- source/graphics/devil/devilloader.cpp | 2 + source/graphics/devil/devilloader.h | 3 ++ source/graphics/imageloader.cpp | 60 +++++++++++++++++---------- source/graphics/imageloader.h | 29 ++++++++++++- source/graphics/png/pngloader.cpp | 2 + source/graphics/png/pngloader.h | 3 ++ 6 files changed, 76 insertions(+), 23 deletions(-) diff --git a/source/graphics/devil/devilloader.cpp b/source/graphics/devil/devilloader.cpp index 392bde8..88beb04 100644 --- a/source/graphics/devil/devilloader.cpp +++ b/source/graphics/devil/devilloader.cpp @@ -59,6 +59,8 @@ int tell(void *handle) namespace Msp { namespace Graphics { +ImageLoader::Register DevilLoader::reg; + DevilLoader::DevilLoader(IO::Seekable &i): io(i) { diff --git a/source/graphics/devil/devilloader.h b/source/graphics/devil/devilloader.h index 3b933ae..daab2a2 100644 --- a/source/graphics/devil/devilloader.h +++ b/source/graphics/devil/devilloader.h @@ -12,10 +12,13 @@ private: IO::Base &io; unsigned id; + static Register 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 &); diff --git a/source/graphics/imageloader.cpp b/source/graphics/imageloader.cpp index 6cdaef9..15f0e50 100644 --- a/source/graphics/imageloader.cpp +++ b/source/graphics/imageloader.cpp @@ -2,18 +2,14 @@ #include #include #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 &loaders = get_registered_loaders(); + if(registered_loaders_changed) + { + registered_loaders_changed = false; + loaders.sort(signature_size_compare); + } + + vector 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::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 &ImageLoader::get_registered_loaders() +{ + static list regs; + return regs; +} + +bool ImageLoader::signature_size_compare(RegisterBase *r1, RegisterBase *r2) +{ + return r1->get_signature_size()get_signature_size(); +} + } // namespace Graphics } // namespace Msp diff --git a/source/graphics/imageloader.h b/source/graphics/imageloader.h index f953990..c06a759 100644 --- a/source/graphics/imageloader.h +++ b/source/graphics/imageloader.h @@ -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 + 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 &get_registered_loaders(); + static bool registered_loaders_changed; + static bool signature_size_compare(RegisterBase *, RegisterBase *); + +protected: ImageLoader(); public: virtual ~ImageLoader(); diff --git a/source/graphics/png/pngloader.cpp b/source/graphics/png/pngloader.cpp index 3f2f959..15684b1 100644 --- a/source/graphics/png/pngloader.cpp +++ b/source/graphics/png/pngloader.cpp @@ -31,6 +31,8 @@ struct PngLoader::Private png_info *info; }; +ImageLoader::Register PngLoader::reg; + PngLoader::PngLoader(IO::Base &io, unsigned sig_bytes): priv(new Private) { diff --git a/source/graphics/png/pngloader.h b/source/graphics/png/pngloader.h index a81c34c..683f4d3 100644 --- a/source/graphics/png/pngloader.h +++ b/source/graphics/png/pngloader.h @@ -13,10 +13,13 @@ private: Private *priv; + static Register 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 &); -- 2.45.2