1.SkImage decoded procedure
SkImageDecoder.DecodeMemory/SkImageDecoder.DecodeFile
SkImageDecoder.DecodeStream
SkImageDecoder.decode
SkImageDecoder.onDecode
SkJPEGImageDecoder.onDecode(SkImageDecoder_libjpeg.cpp)
SkImageDecoder.return_flase(error)
2.factory mode
a.client use abs product in it's code.
client set the product to a specific one before use it.
b.client use the factory to get a specific product.
the key point is how we can get a specific product from the factory.
there are two imporant points here. first we should pass a parameter in;
second, how we can get different factory from the parameter.
3.SkImageDecoder's factory
in SkImageDecoder::DecodeStream, call
SkImageDecoder* codec = SkImageDecoder::Factory(stream);
to get a concrete ImageDecoder.
a. in SkImageDecoder_Factory.cpp
Factory use DecodeReg class, traversal a DecodeReg list
use "codec = curr->factory()(stream);" to find the decoder that match the stream.
b.how does curr->factory()(stream) works?
1)SkTRegistry defined in SkTRegistry.h
typedef SkTRegistry<SkImageDecoder*, SkStream*> DecodeReg;
//template class with two class parameters, first is SkImageDecoder, second is SKStream.
Factory factory() const { return fFact; }
Factory fFact;
template <typename T, typename P> class SkTRegistry :{
typedef T (*Factory)(P);...}
so curr->factory() will call a function pointer, input the SKStream and return SkImaageDecoer.
2)how is the pointer assigned?
SkTRegistry(Factory fact) {fFact = fact;...}
in the constructor function.
3)when is it called?
in every concrete factory we define the factory.
static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(DFactory);
static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(EFactory);
static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efactory);
static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory);
static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(DFactory);
static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
so we will call every decoder's Factory() when traversal the list and return the factory we want.
4)how is the coder above added in called when we just call curr->factory?
in SkImageDecoder_empty.cpp
add every in and call it.
SkImageDecoder.DecodeMemory/SkImageDecoder.DecodeFile
SkImageDecoder.DecodeStream
SkImageDecoder.decode
SkImageDecoder.onDecode
SkJPEGImageDecoder.onDecode(SkImageDecoder_libjpeg.cpp)
SkImageDecoder.return_flase(error)
2.factory mode
a.client use abs product in it's code.
client set the product to a specific one before use it.
b.client use the factory to get a specific product.
the key point is how we can get a specific product from the factory.
there are two imporant points here. first we should pass a parameter in;
second, how we can get different factory from the parameter.
3.SkImageDecoder's factory
in SkImageDecoder::DecodeStream, call
SkImageDecoder* codec = SkImageDecoder::Factory(stream);
to get a concrete ImageDecoder.
a. in SkImageDecoder_Factory.cpp
const DecodeReg* curr = DecodeReg::Head();
while (curr) {
codec = curr->factory()(stream);
// we rewind here, because we promise later when we call "decode", that
// the stream will be at its beginning.
stream->rewind();
if (codec) {
return codec;
}
curr = curr->next();
}
Factory use DecodeReg class, traversal a DecodeReg list
use "codec = curr->factory()(stream);" to find the decoder that match the stream.
b.how does curr->factory()(stream) works?
1)SkTRegistry defined in SkTRegistry.h
typedef SkTRegistry<SkImageDecoder*, SkStream*> DecodeReg;
//template class with two class parameters, first is SkImageDecoder, second is SKStream.
Factory factory() const { return fFact; }
Factory fFact;
template <typename T, typename P> class SkTRegistry :{
typedef T (*Factory)(P);...}
so curr->factory() will call a function pointer, input the SKStream and return SkImaageDecoer.
2)how is the pointer assigned?
SkTRegistry(Factory fact) {fFact = fact;...}
in the constructor function.
3)when is it called?
in every concrete factory we define the factory.
static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(DFactory);
static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(EFactory);
static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efactory);
static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory);
static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(DFactory);
static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
so we will call every decoder's Factory() when traversal the list and return the factory we want.
4)how is the coder above added in called when we just call curr->factory?
in SkImageDecoder_empty.cpp
SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
SkImageDecoder* codec = gPairs[i].fProc(stream);
stream->rewind();
if (NULL != codec) {
return codec;
}
}
return NULL;
}
add every in and call it.