blob: f1eca3d03afb3b0a1297a4bb262d81c0575fd456 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
scroggo@google.com4c6adf92013-04-17 21:07:55 +00002 * Copyright 2013 The Android Open Source Project
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
scroggo@google.com39edf4c2013-04-25 17:33:51 +00008#include "SkErrorInternals.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +00009#include "SkImageDecoder.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#include "SkStream.h"
reed@android.com00bf85a2009-01-22 13:04:56 +000011#include "SkTRegistry.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000012
scroggo@google.com4c6adf92013-04-17 21:07:55 +000013// This file is used for registration of SkImageDecoders. It also holds a function
14// for checking all the the registered SkImageDecoders for one that matches an
15// input SkStream.
16
reed@android.com00bf85a2009-01-22 13:04:56 +000017typedef SkTRegistry<SkImageDecoder*, SkStream*> DecodeReg;
reed@android.com8a1c16f2008-12-17 15:59:43 +000018
agl@chromium.org4f9cdcc2010-06-10 21:32:00 +000019// N.B. You can't use "DecodeReg::gHead here" due to complex C++
20// corner cases.
21template DecodeReg* SkTRegistry<SkImageDecoder*, SkStream*>::gHead;
reed@android.com3c2b7e82009-01-27 01:43:36 +000022
scroggo@google.com4c6adf92013-04-17 21:07:55 +000023SkImageDecoder* image_decoder_from_stream(SkStream*);
24
25SkImageDecoder* image_decoder_from_stream(SkStream* stream) {
reed@android.comdfee5792010-04-15 14:24:50 +000026 SkImageDecoder* codec = NULL;
reed@android.com00bf85a2009-01-22 13:04:56 +000027 const DecodeReg* curr = DecodeReg::Head();
28 while (curr) {
reed@android.comdfee5792010-04-15 14:24:50 +000029 codec = curr->factory()(stream);
reed@android.coma16cb972009-06-18 20:26:58 +000030 // we rewind here, because we promise later when we call "decode", that
31 // the stream will be at its beginning.
djsollen@google.com50166522013-03-20 20:16:20 +000032 bool rewindSuceeded = stream->rewind();
33
34 // our image decoder's require that rewind is supported so we fail early
35 // if we are given a stream that does not support rewinding.
36 if (!rewindSuceeded) {
37 SkDEBUGF(("Unable to rewind the image stream."));
38 SkDELETE(codec);
39 return NULL;
40 }
41
reed@android.com00bf85a2009-01-22 13:04:56 +000042 if (codec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000043 return codec;
44 }
reed@android.com00bf85a2009-01-22 13:04:56 +000045 curr = curr->next();
reed@android.com8a1c16f2008-12-17 15:59:43 +000046 }
47 return NULL;
48}
scroggo@google.com39edf4c2013-04-25 17:33:51 +000049
50typedef SkTRegistry<SkImageDecoder::Format, SkStream*> FormatReg;
51
52template FormatReg* SkTRegistry<SkImageDecoder::Format, SkStream*>::gHead;
53
54SkImageDecoder::Format SkImageDecoder::GetStreamFormat(SkStream* stream) {
55 const FormatReg* curr = FormatReg::Head();
56 while (curr != NULL) {
57 Format format = curr->factory()(stream);
58 if (!stream->rewind()) {
59 SkErrorInternals::SetError(kInvalidOperation_SkError,
60 "Unable to rewind the image stream\n");
61 return kUnknown_Format;
62 }
63 if (format != kUnknown_Format) {
64 return format;
65 }
66 curr = curr->next();
67 }
68 return kUnknown_Format;
69}