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:
parent
9db6087c0e
commit
00bf85a986
50
include/core/SkTRegistry.h
Normal file
50
include/core/SkTRegistry.h
Normal 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
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user