Index: src/images/SkImageDecoder_Factory.cpp |
diff --git a/src/images/SkImageDecoder_Factory.cpp b/src/images/SkImageDecoder_Factory.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..457ec72e1d37cec8dd807ab1d7c40c03fdc65922 |
--- /dev/null |
+++ b/src/images/SkImageDecoder_Factory.cpp |
@@ -0,0 +1,128 @@ |
+/* |
+ * Copyright 2014 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "SkErrorInternals.h" |
+#include "SkImageDecoder.h" |
+#include "SkImageDecoder_libjpeg.h" |
+#include "SkImageDecoder_libwebp.h" |
+#include "SkImageDecoder_libico.h" |
+#include "SkImageDecoder_libbmp.h" |
+#include "SkImageDecoder_wbmp.h" |
+#include "SkMovie.h" |
+#include "SkStream.h" |
+ |
+#if defined(SK_BUILD_FOR_WIN) |
+#include "SkImageDecoder_WIC.h" |
+#endif |
+#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) |
+#include "SkImageDecoder_CG.h" |
+#endif |
+#if !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_WIN) |
+#include "SkImageDecoder_libpng.h" |
+#endif |
+#if !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_WIN) && \ |
+ !defined(SK_BUILD_FOR_NACL) |
+#include "SkImageDecoder_libgif.h" |
+#include "SkMovie_gif.h" |
+#endif |
+#if !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) |
+#include "SkImageDecoder_astc.h" |
+#include "SkImageDecoder_ktx.h" |
+#include "SkImageDecoder_pkm.h" |
+#endif |
+ |
+// This file is used for registration of SkImageDecoders. It also holds a function for checking all |
+// the the registered SkImageDecoders for one that matches an input SkStreamRewindable. |
+ |
+// The order of the factory functions defines the order image decoders are tested when decoding a |
+// stream. The first function is the first one tested, so the functions should be listed in order |
+// from the most likely to be used, to the least likely. JPEG and PNG should be the first two, for |
+// instance. |
+ |
+typedef SkImageDecoder* (*FactoryCreateFunc)(SkImageDecoder::Format); |
+typedef SkImageDecoder::Format (*FactoryDetectFormatFunc)(SkStreamRewindable*); |
+static const struct { |
+ const FactoryCreateFunc createFunc; |
+ const FactoryDetectFormatFunc detectFormatFunc; |
+} gDecoderFactoryFuncs[] = { |
+#if !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_WIN) |
+ { SkCreatePNGImageDecoder, SkDetectFormatPNGImageDecoder }, |
+#endif |
+ { SkCreateJPEGImageDecoder, SkDetectFormatJPEGImageDecoder }, |
+ { SkCreateWEBPImageDecoder, SkDetectFormatWEBPImageDecoder }, |
+ { SkCreateICOImageDecoder, SkDetectFormatICOImageDecoder }, |
+#if !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_WIN) && \ |
+ !defined(SK_BUILD_FOR_NACL) |
+ { SkCreateGIFImageDecoder, SkDetectFormatGIFImageDecoder }, |
+#endif |
+ { SkCreateBMPImageDecoder, SkDetectFormatBMPImageDecoder }, |
+#if !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) |
+ { SkCreateASTCImageDecoder, SkDetectFormatASTCImageDecoder }, |
+ { SkCreateKTXImageDecoder, SkDetectFormatKTXImageDecoder }, |
+ { SkCreatePKMImageDecoder, SkDetectFormatPKMImageDecoder }, |
+#endif |
+ { SkCreateWBMPImageDecoder, SkDetectFormatWBMPImageDecoder }, |
+#if defined(SK_BUILD_FOR_WIN) |
+ { SkCreateImageDecoder_WIC, SkDetectFormatImageDecoder_WIC } |
+#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) |
+ { SkCreateImageDecoder_CG, SkDetectFormatImageDecoder_CG } |
+#endif |
+}; |
+ |
+SkImageDecoder* SkImageDecoder::Factory(SkStreamRewindable* stream) { |
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gDecoderFactoryFuncs); ++i) { |
+ FactoryDetectFormatFunc detectFormatFunc = gDecoderFactoryFuncs[i].detectFormatFunc; |
+ Format format = detectFormatFunc(stream); |
+ |
+ // We rewind here, because we promise later when we call "decode", that the stream will be |
+ // at its beginning. |
+ bool rewindSuceeded = stream->rewind(); |
+ |
+ // Our image decoders require that rewind is supported so we fail early if we are given a |
+ // stream that does not support rewinding. |
+ if (!rewindSuceeded) { |
+ SkDEBUGF(("Unable to rewind the image stream.")); |
+ return NULL; |
+ } |
+ |
+ if (SkImageDecoder::kUnknown_Format != format) { |
+ FactoryCreateFunc createFunc = gDecoderFactoryFuncs[i].createFunc; |
+ SkImageDecoder* codec = createFunc(format); |
+ SkASSERT(NULL != codec); |
+ return codec; |
+ } |
+ } |
+ return NULL; |
+} |
+ |
+SkImageDecoder::Format SkImageDecoder::GetStreamFormat(SkStreamRewindable* stream) { |
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gDecoderFactoryFuncs); ++i) { |
+ FactoryDetectFormatFunc detectFormatFunc = gDecoderFactoryFuncs[i].detectFormatFunc; |
+ Format format = detectFormatFunc(stream); |
+ if (!stream->rewind()) { |
+ SkErrorInternals::SetError(kInvalidOperation_SkError, |
+ "Unable to rewind the image stream\n"); |
+ return kUnknown_Format; |
+ } |
+ if (format != kUnknown_Format) { |
+ return format; |
+ } |
+ } |
+ return kUnknown_Format; |
+} |
+ |
+SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) { |
+ SkMovie* movie = NULL; |
+#if !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_WIN) && \ |
+ !defined(SK_BUILD_FOR_NACL) |
+ movie = SkGIFMovieCreate(stream); |
+ if (NULL == movie) { |
+ stream->rewind(); |
+ } |
+#endif |
+ return movie; |
+} |