aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-01-22 13:04:56 +0000
committerGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-01-22 13:04:56 +0000
commit00bf85a98675c9d0c3150bbeb0a3d7198ad8f21f (patch)
treeb4b522fd859aa3e3dcc2f20061bddbe348b850e4
parent9db6087c0e8be71e50aa09106759a868cb9597dc (diff)
pull from android: use registry to build up list of image codecs
git-svn-id: http://skia.googlecode.com/svn/trunk@76 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--include/core/SkTRegistry.h50
-rw-r--r--include/images/SkImageDecoder.h6
-rw-r--r--src/images/SkImageDecoder_libbmp.cpp6
-rw-r--r--src/images/SkImageDecoder_libgif.cpp5
-rw-r--r--src/images/SkImageDecoder_libico.cpp38
-rw-r--r--src/images/SkImageDecoder_libjpeg.cpp50
-rw-r--r--src/images/SkImageDecoder_libpng.cpp29
-rw-r--r--src/images/SkImageDecoder_wbmp.cpp25
-rw-r--r--src/ports/SkImageDecoder_CG.cpp4
-rw-r--r--src/ports/SkImageDecoder_Factory.cpp57
-rw-r--r--src/ports/SkImageEncoder_Factory.cpp19
11 files changed, 155 insertions, 134 deletions
diff --git a/include/core/SkTRegistry.h b/include/core/SkTRegistry.h
new file mode 100644
index 0000000000..83c08de171
--- /dev/null
+++ b/include/core/SkTRegistry.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkTRegistry_DEFINED
+#define SkTRegistry_DEFINED
+
+#include "SkTypes.h"
+
+/** Template class that registers itself (in the constructor) into a linked-list
+ and provides a function-pointer. This can be used to auto-register a set of
+ services, e.g. a set of image codecs.
+ */
+template <typename T, typename P> class SkTRegistry : SkNoncopyable {
+public:
+ typedef T (*Factory)(P);
+
+ SkTRegistry(Factory fact) {
+ fFact = fact;
+ fChain = gHead;
+ gHead = this;
+ }
+
+ static const SkTRegistry* Head() { return gHead; }
+
+ const SkTRegistry* next() const { return fChain; }
+ Factory factory() const { return fFact; }
+
+private:
+ Factory fFact;
+ SkTRegistry* fChain;
+
+ static SkTRegistry* gHead;
+};
+
+template <typename T, typename P> SkTRegistry<T, P>* SkTRegistry<T, P>::gHead;
+
+#endif
diff --git a/include/images/SkImageDecoder.h b/include/images/SkImageDecoder.h
index 5b91c51fdd..3ea6198e33 100644
--- a/include/images/SkImageDecoder.h
+++ b/include/images/SkImageDecoder.h
@@ -199,12 +199,6 @@ public:
kDecodePixels_Mode);
}
- /* Given a format, return true if there is a currently installed decoder
- for that format. Since a given build may not include all codecs (to save
- code-size), this may return false.
- */
- static bool SupportsFormat(Format);
-
/** Return the default config for the running device.
Currently this used as a suggestion to image decoders that need to guess
what config they should decode into.
diff --git a/src/images/SkImageDecoder_libbmp.cpp b/src/images/SkImageDecoder_libbmp.cpp
index 32a7a6de42..a4dcbf6174 100644
--- a/src/images/SkImageDecoder_libbmp.cpp
+++ b/src/images/SkImageDecoder_libbmp.cpp
@@ -20,6 +20,7 @@
#include "SkStream.h"
#include "SkColorPriv.h"
#include "SkTDArray.h"
+#include "SkTRegistry.h"
class SkBMPImageDecoder : public SkImageDecoder {
public:
@@ -34,8 +35,7 @@ protected:
SkBitmap::Config pref, Mode mode);
};
-SkImageDecoder* SkImageDecoder_BMP_Factory(SkStream*);
-SkImageDecoder* SkImageDecoder_BMP_Factory(SkStream* stream) {
+static SkImageDecoder* Factory(SkStream* stream) {
static const char kBmpMagic[] = { 'B', 'M' };
size_t len = stream->getLength();
@@ -49,6 +49,8 @@ SkImageDecoder* SkImageDecoder_BMP_Factory(SkStream* stream) {
return NULL;
}
+static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
+
///////////////////////////////////////////////////////////////////////////////
class SkBmpDecoderCallback : public image_codec::BmpDecoderCallback {
diff --git a/src/images/SkImageDecoder_libgif.cpp b/src/images/SkImageDecoder_libgif.cpp
index 519366a18e..ed8817ab86 100644
--- a/src/images/SkImageDecoder_libgif.cpp
+++ b/src/images/SkImageDecoder_libgif.cpp
@@ -326,7 +326,9 @@ DONE:
///////////////////////////////////////////////////////////////////////////////
-SkImageDecoder* SkImageDecoder_GIF_Factory(SkStream* stream) {
+#include "SkTRegistry.h"
+
+static SkImageDecoder* Factory(SkStream* stream) {
char buf[GIF_STAMP_LEN];
if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) {
if (memcmp(GIF_STAMP, buf, GIF_STAMP_LEN) == 0 ||
@@ -338,3 +340,4 @@ SkImageDecoder* SkImageDecoder_GIF_Factory(SkStream* stream) {
return NULL;
}
+static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
diff --git a/src/images/SkImageDecoder_libico.cpp b/src/images/SkImageDecoder_libico.cpp
index b179a6b61a..9f21e13256 100644
--- a/src/images/SkImageDecoder_libico.cpp
+++ b/src/images/SkImageDecoder_libico.cpp
@@ -44,23 +44,6 @@ protected:
/////////////////////////////////////////////////////////////////////////////////////////
-SkImageDecoder* SkImageDecoder_ICO_Factory(SkStream*);
-SkImageDecoder* SkImageDecoder_ICO_Factory(SkStream* stream)
-{
- //i'm going to check if we basically have 0,0,1,0 (reserved = 0, type = 1)
- //is that required and sufficient?
- SkAutoMalloc autoMal(4);
- unsigned char* buf = (unsigned char*)autoMal.get();
- stream->read((void*)buf, 4);
- int reserved = read2Bytes(buf, 0);
- int type = read2Bytes(buf, 2);
- if (reserved != 0 || type != 1) //it's not an ico
- return NULL;
- return SkNEW(SkICOImageDecoder);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
SkICOImageDecoder::SkICOImageDecoder()
{
}
@@ -386,3 +369,24 @@ static void editPixelBit32(const int pixelNo, const unsigned char* buf,
*address = SkPackARGB32(alpha, red & alpha, green & alpha, blue & alpha);
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#include "SkTRegistry.h"
+
+static SkImageDecoder* Factory(SkStream* stream) {
+ // Check to see if the first four bytes are 0,0,1,0
+ // FIXME: Is that required and sufficient?
+ SkAutoMalloc autoMal(4);
+ unsigned char* buf = (unsigned char*)autoMal.get();
+ stream->read((void*)buf, 4);
+ int reserved = read2Bytes(buf, 0);
+ int type = read2Bytes(buf, 2);
+ if (reserved != 0 || type != 1) {
+ // This stream does not represent an ICO image.
+ return NULL;
+ }
+ return SkNEW(SkICOImageDecoder);
+}
+
+static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
+
diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp
index 51339971ac..018c96c353 100644
--- a/src/images/SkImageDecoder_libjpeg.cpp
+++ b/src/images/SkImageDecoder_libjpeg.cpp
@@ -51,24 +51,6 @@ protected:
SkBitmap::Config pref, Mode);
};
-SkImageDecoder* SkImageDecoder_JPEG_Factory(SkStream* stream) {
- static const char gHeader[] = { 0xFF, 0xD8, 0xFF };
- static const size_t HEADER_SIZE = sizeof(gHeader);
-
- char buffer[HEADER_SIZE];
- size_t len = stream->read(buffer, HEADER_SIZE);
-
- if (len != HEADER_SIZE) {
- return NULL; // can't read enough
- }
-
- if (memcmp(buffer, gHeader, HEADER_SIZE)) {
- return NULL;
- }
-
- return SkNEW(SkJPEGImageDecoder);
-}
-
//////////////////////////////////////////////////////////////////////////
#include "SkTime.h"
@@ -789,20 +771,30 @@ protected:
}
};
-SkImageEncoder* SkImageEncoder_JPEG_Factory();
-SkImageEncoder* SkImageEncoder_JPEG_Factory() {
- return SkNEW(SkJPEGImageEncoder);
-}
+///////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////
+#include "SkTRegistry.h"
-#ifdef SK_DEBUG
+static SkImageDecoder* DFactory(SkStream* stream) {
+ static const char gHeader[] = { 0xFF, 0xD8, 0xFF };
+ static const size_t HEADER_SIZE = sizeof(gHeader);
-void SkImageDecoder::UnitTest() {
- SkBitmap bm;
+ char buffer[HEADER_SIZE];
+ size_t len = stream->read(buffer, HEADER_SIZE);
+
+ if (len != HEADER_SIZE) {
+ return NULL; // can't read enough
+ }
+ if (memcmp(buffer, gHeader, HEADER_SIZE)) {
+ return NULL;
+ }
+ return SkNEW(SkJPEGImageDecoder);
+}
- (void)SkImageDecoder::DecodeFile("logo.jpg", &bm);
+static SkImageEncoder* EFactory(SkImageEncoder::Type t) {
+ return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
}
-#endif
+static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(DFactory);
+static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(EFactory);
+
diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp
index fedb8df19f..b616eee918 100644
--- a/src/images/SkImageDecoder_libpng.cpp
+++ b/src/images/SkImageDecoder_libpng.cpp
@@ -58,15 +58,6 @@ private:
png_infop info_ptr;
};
-SkImageDecoder* SkImageDecoder_PNG_Factory(SkStream* stream) {
- char buf[PNG_BYTES_TO_CHECK];
- if (stream->read(buf, PNG_BYTES_TO_CHECK) == PNG_BYTES_TO_CHECK &&
- !png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) {
- return SkNEW(SkPNGImageDecoder);
- }
- return NULL;
-}
-
static void sk_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) {
SkStream* sk_stream = (SkStream*) png_ptr->io_ptr;
size_t bytes = sk_stream->read(data, length);
@@ -787,8 +778,22 @@ bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap,
return true;
}
-SkImageEncoder* SkImageEncoder_PNG_Factory();
-SkImageEncoder* SkImageEncoder_PNG_Factory() {
- return SkNEW(SkPNGImageEncoder);
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkTRegistry.h"
+
+static SkImageDecoder* DFactory(SkStream* stream) {
+ char buf[PNG_BYTES_TO_CHECK];
+ if (stream->read(buf, PNG_BYTES_TO_CHECK) == PNG_BYTES_TO_CHECK &&
+ !png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) {
+ return SkNEW(SkPNGImageDecoder);
+ }
+ return NULL;
+}
+
+static SkImageEncoder* EFactory(SkImageEncoder::Type t) {
+ return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL;
}
+static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(EFactory);
+static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(DFactory);
diff --git a/src/images/SkImageDecoder_wbmp.cpp b/src/images/SkImageDecoder_wbmp.cpp
index 9d188f6016..ac242ea22f 100644
--- a/src/images/SkImageDecoder_wbmp.cpp
+++ b/src/images/SkImageDecoder_wbmp.cpp
@@ -77,16 +77,6 @@ struct wbmp_head {
}
};
-SkImageDecoder* SkImageDecoder_WBMP_Factory(SkStream* stream)
-{
- wbmp_head head;
-
- if (head.init(stream)) {
- return SkNEW(SkWBMPImageDecoder);
- }
- return NULL;
-}
-
static void expand_bits_to_bytes(uint8_t dst[], const uint8_t src[], int bits)
{
int bytes = bits >> 3;
@@ -165,3 +155,18 @@ bool SkWBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap,
return true;
}
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkTRegistry.h"
+
+static SkImageDecoder* Factory(SkStream* stream) {
+ wbmp_head head;
+
+ if (head.init(stream)) {
+ return SkNEW(SkWBMPImageDecoder);
+ }
+ return NULL;
+}
+
+static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
+
diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp
index 5594eac91a..7f8b26c2c5 100644
--- a/src/ports/SkImageDecoder_CG.cpp
+++ b/src/ports/SkImageDecoder_CG.cpp
@@ -94,10 +94,6 @@ SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
return SkNEW(SkImageDecoder_CG);
}
-bool SkImageDecoder::SupportsFormat(Format format) {
- return true;
-}
-
/////////////////////////////////////////////////////////////////////////
SkMovie* SkMovie::DecodeStream(SkStream* stream) {
diff --git a/src/ports/SkImageDecoder_Factory.cpp b/src/ports/SkImageDecoder_Factory.cpp
index 5c45a43ec5..33009812fd 100644
--- a/src/ports/SkImageDecoder_Factory.cpp
+++ b/src/ports/SkImageDecoder_Factory.cpp
@@ -18,67 +18,36 @@
#include "SkImageDecoder.h"
#include "SkMovie.h"
#include "SkStream.h"
+#include "SkTRegistry.h"
-extern SkImageDecoder* SkImageDecoder_GIF_Factory(SkStream*);
-extern SkImageDecoder* SkImageDecoder_BMP_Factory(SkStream*);
-extern SkImageDecoder* SkImageDecoder_ICO_Factory(SkStream*);
-extern SkImageDecoder* SkImageDecoder_PNG_Factory(SkStream*);
-extern SkImageDecoder* SkImageDecoder_WBMP_Factory(SkStream*);
-extern SkImageDecoder* SkImageDecoder_JPEG_Factory(SkStream*);
-
-typedef SkImageDecoder* (*SkImageDecoderFactoryProc)(SkStream*);
-
-struct CodecFormat {
- SkImageDecoderFactoryProc fProc;
- SkImageDecoder::Format fFormat;
-};
-
-static const CodecFormat gPairs[] = {
- { SkImageDecoder_GIF_Factory, SkImageDecoder::kGIF_Format },
- { SkImageDecoder_PNG_Factory, SkImageDecoder::kPNG_Format },
- { SkImageDecoder_ICO_Factory, SkImageDecoder::kICO_Format },
- { SkImageDecoder_WBMP_Factory, SkImageDecoder::kWBMP_Format },
- { SkImageDecoder_BMP_Factory, SkImageDecoder::kBMP_Format },
- { SkImageDecoder_JPEG_Factory, SkImageDecoder::kJPEG_Format }
-};
+typedef SkTRegistry<SkImageDecoder*, SkStream*> DecodeReg;
SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
- for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
- SkImageDecoder* codec = gPairs[i].fProc(stream);
+ const DecodeReg* curr = DecodeReg::Head();
+ while (curr) {
+ SkImageDecoder* codec = curr->factory()(stream);
stream->rewind();
- if (NULL != codec) {
+ if (codec) {
return codec;
}
+ curr = curr->next();
}
return NULL;
}
-bool SkImageDecoder::SupportsFormat(Format format) {
- for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
- if (gPairs[i].fFormat == format) {
- return true;
- }
- }
- return false;
-}
-
/////////////////////////////////////////////////////////////////////////
-typedef SkMovie* (*SkMovieFactoryProc)(SkStream*);
-
-extern SkMovie* SkMovie_GIF_Factory(SkStream*);
-
-static const SkMovieFactoryProc gMovieProcs[] = {
- SkMovie_GIF_Factory
-};
+typedef SkTRegistry<SkMovie*, SkStream*> MovieReg;
SkMovie* SkMovie::DecodeStream(SkStream* stream) {
- for (unsigned i = 0; i < SK_ARRAY_COUNT(gMovieProcs); i++) {
- SkMovie* movie = gMovieProcs[i](stream);
- if (NULL != movie) {
+ const MovieReg* curr = MovieReg::Head();
+ while (curr) {
+ SkMovie* movie = curr->factory()(stream);
+ if (movie) {
return movie;
}
stream->rewind();
+ curr = curr->next();
}
return NULL;
}
diff --git a/src/ports/SkImageEncoder_Factory.cpp b/src/ports/SkImageEncoder_Factory.cpp
index cdd7c0409f..f44cd8fa30 100644
--- a/src/ports/SkImageEncoder_Factory.cpp
+++ b/src/ports/SkImageEncoder_Factory.cpp
@@ -15,18 +15,19 @@
*/
#include "SkImageEncoder.h"
+#include "SkTRegistry.h"
-extern SkImageEncoder* SkImageEncoder_JPEG_Factory();
-extern SkImageEncoder* SkImageEncoder_PNG_Factory();
+typedef SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> EncodeReg;
SkImageEncoder* SkImageEncoder::Create(Type t) {
- switch (t) {
- case kJPEG_Type:
- return SkImageEncoder_JPEG_Factory();
- case kPNG_Type:
- return SkImageEncoder_PNG_Factory();
- default:
- return NULL;
+ const EncodeReg* curr = EncodeReg::Head();
+ while (curr) {
+ SkImageEncoder* codec = curr->factory()(t);
+ if (codec) {
+ return codec;
+ }
+ curr = curr->next();
}
+ return NULL;
}