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
This commit is contained in:
reed@android.com 2009-01-22 13:04:56 +00:00
parent 9db6087c0e
commit 00bf85a986
11 changed files with 157 additions and 136 deletions

View File

@ -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

View File

@ -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.

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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"
static SkImageDecoder* DFactory(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);
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
#ifdef SK_DEBUG
void SkImageDecoder::UnitTest() {
SkBitmap bm;
(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);

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;
}