зеркало из https://github.com/mozilla/moz-skia.git
merge from android tree:
- optional parameters added to descriptorProc and allocPixels - clip options to image decoders - check for xfermode in blitter_a8 - UNROLL loops in blitrow reviewed by reed@google.com git-svn-id: http://skia.googlecode.com/svn/trunk@841 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
819c921b04
Коммит
57f4969724
|
@ -462,10 +462,15 @@ public:
|
||||||
int extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy);
|
int extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy);
|
||||||
|
|
||||||
void extractAlpha(SkBitmap* dst) const {
|
void extractAlpha(SkBitmap* dst) const {
|
||||||
this->extractAlpha(dst, NULL, NULL);
|
this->extractAlpha(dst, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void extractAlpha(SkBitmap* dst, const SkPaint* paint,
|
void extractAlpha(SkBitmap* dst, const SkPaint* paint,
|
||||||
|
SkIPoint* offset) const {
|
||||||
|
this->extractAlpha(dst, paint, NULL, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void extractAlpha(SkBitmap* dst, const SkPaint* paint, Allocator* allocator,
|
||||||
SkIPoint* offset) const;
|
SkIPoint* offset) const;
|
||||||
|
|
||||||
void flatten(SkFlattenableWriteBuffer&) const;
|
void flatten(SkFlattenableWriteBuffer&) const;
|
||||||
|
|
|
@ -855,7 +855,7 @@ private:
|
||||||
|
|
||||||
void descriptorProc(const SkMatrix* deviceMatrix,
|
void descriptorProc(const SkMatrix* deviceMatrix,
|
||||||
void (*proc)(const SkDescriptor*, void*),
|
void (*proc)(const SkDescriptor*, void*),
|
||||||
void* context) const;
|
void* context, bool ignoreGamma = false) const;
|
||||||
|
|
||||||
const SkRect& computeStrokeFastBounds(const SkRect& orig,
|
const SkRect& computeStrokeFastBounds(const SkRect& orig,
|
||||||
SkRect* storage) const;
|
SkRect* storage) const;
|
||||||
|
|
|
@ -119,6 +119,18 @@ public:
|
||||||
virtual Factory getFactory() const { return NULL; }
|
virtual Factory getFactory() const { return NULL; }
|
||||||
virtual void flatten(SkFlattenableWriteBuffer&) const;
|
virtual void flatten(SkFlattenableWriteBuffer&) const;
|
||||||
|
|
||||||
|
/** Acquire a "global" ref on this object.
|
||||||
|
* The default implementation just calls ref(), but subclasses can override
|
||||||
|
* this method to implement additional behavior.
|
||||||
|
*/
|
||||||
|
virtual void globalRef(void* data=NULL);
|
||||||
|
|
||||||
|
/** Release a "global" ref on this object.
|
||||||
|
* The default implementation just calls unref(), but subclasses can override
|
||||||
|
* this method to implement additional behavior.
|
||||||
|
*/
|
||||||
|
virtual void globalUnref();
|
||||||
|
|
||||||
static Factory NameToFactory(const char name[]);
|
static Factory NameToFactory(const char name[]);
|
||||||
static const char* FactoryToName(Factory);
|
static const char* FactoryToName(Factory);
|
||||||
static void Register(const char name[], Factory);
|
static void Register(const char name[], Factory);
|
||||||
|
|
|
@ -177,6 +177,11 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void setMemory(const void* data, size_t length,
|
virtual void setMemory(const void* data, size_t length,
|
||||||
bool copyData = false);
|
bool copyData = false);
|
||||||
|
/** Replace any memory buffer with the specified buffer. The caller
|
||||||
|
must have allocated data with sk_malloc or sk_realloc, since it
|
||||||
|
will be freed with sk_free.
|
||||||
|
*/
|
||||||
|
void setMemoryOwned(const void* data, size_t length);
|
||||||
void skipToAlign4();
|
void skipToAlign4();
|
||||||
virtual bool rewind();
|
virtual bool rewind();
|
||||||
virtual size_t read(void* buffer, size_t size);
|
virtual size_t read(void* buffer, size_t size);
|
||||||
|
|
|
@ -62,8 +62,10 @@ private:
|
||||||
// See also SkTScopedPtr.
|
// See also SkTScopedPtr.
|
||||||
template <typename T> class SkAutoTDelete : SkNoncopyable {
|
template <typename T> class SkAutoTDelete : SkNoncopyable {
|
||||||
public:
|
public:
|
||||||
SkAutoTDelete(T* obj) : fObj(obj) {}
|
SkAutoTDelete(T* obj, bool deleteWhenDone = true) : fObj(obj) {
|
||||||
~SkAutoTDelete() { delete fObj; }
|
fDeleteWhenDone = deleteWhenDone;
|
||||||
|
}
|
||||||
|
~SkAutoTDelete() { if (fDeleteWhenDone) delete fObj; }
|
||||||
|
|
||||||
T* get() const { return fObj; }
|
T* get() const { return fObj; }
|
||||||
void free() { delete fObj; fObj = NULL; }
|
void free() { delete fObj; fObj = NULL; }
|
||||||
|
@ -71,6 +73,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T* fObj;
|
T* fObj;
|
||||||
|
bool fDeleteWhenDone;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T> class SkAutoTDeleteArray : SkNoncopyable {
|
template <typename T> class SkAutoTDeleteArray : SkNoncopyable {
|
||||||
|
|
|
@ -57,6 +57,12 @@ public:
|
||||||
*/
|
*/
|
||||||
bool getInfo(SkBitmap* bm);
|
bool getInfo(SkBitmap* bm);
|
||||||
|
|
||||||
|
/** Return true if the image can be decoded and is opaque. Calling this
|
||||||
|
method will decode and set the pixels in the specified bitmap and
|
||||||
|
sets the isOpaque flag.
|
||||||
|
*/
|
||||||
|
bool isOpaque(SkBitmap* bm);
|
||||||
|
|
||||||
SkImageDecoderFactory* getDecoderFactory() const { return fFactory; }
|
SkImageDecoderFactory* getDecoderFactory() const { return fFactory; }
|
||||||
// returns the factory parameter
|
// returns the factory parameter
|
||||||
SkImageDecoderFactory* setDecoderFactory(SkImageDecoderFactory*);
|
SkImageDecoderFactory* setDecoderFactory(SkImageDecoderFactory*);
|
||||||
|
|
|
@ -41,11 +41,13 @@ void skjpeg_error_exit(j_common_ptr cinfo);
|
||||||
/* Our source struct for directing jpeg to our stream object.
|
/* Our source struct for directing jpeg to our stream object.
|
||||||
*/
|
*/
|
||||||
struct skjpeg_source_mgr : jpeg_source_mgr {
|
struct skjpeg_source_mgr : jpeg_source_mgr {
|
||||||
skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder);
|
skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder, bool ownStream);
|
||||||
|
~skjpeg_source_mgr();
|
||||||
|
|
||||||
SkStream* fStream;
|
SkStream* fStream;
|
||||||
const void* fMemoryBase;
|
void* fMemoryBase;
|
||||||
size_t fMemoryBaseSize;
|
size_t fMemoryBaseSize;
|
||||||
|
bool fUnrefStream;
|
||||||
SkImageDecoder* fDecoder;
|
SkImageDecoder* fDecoder;
|
||||||
enum {
|
enum {
|
||||||
kBufferSize = 1024
|
kBufferSize = 1024
|
||||||
|
|
|
@ -1186,7 +1186,7 @@ static bool GetBitmapAlpha(const SkBitmap& src, uint8_t SK_RESTRICT alpha[],
|
||||||
#include "SkMatrix.h"
|
#include "SkMatrix.h"
|
||||||
|
|
||||||
void SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
|
void SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
|
||||||
SkIPoint* offset) const {
|
Allocator *allocator, SkIPoint* offset) const {
|
||||||
SkDEBUGCODE(this->validate();)
|
SkDEBUGCODE(this->validate();)
|
||||||
|
|
||||||
SkMatrix identity;
|
SkMatrix identity;
|
||||||
|
@ -1210,7 +1210,7 @@ void SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
|
||||||
NO_FILTER_CASE:
|
NO_FILTER_CASE:
|
||||||
dst->setConfig(SkBitmap::kA8_Config, this->width(), this->height(),
|
dst->setConfig(SkBitmap::kA8_Config, this->width(), this->height(),
|
||||||
srcM.fRowBytes);
|
srcM.fRowBytes);
|
||||||
dst->allocPixels();
|
dst->allocPixels(allocator, NULL);
|
||||||
GetBitmapAlpha(*this, dst->getAddr8(0, 0), srcM.fRowBytes);
|
GetBitmapAlpha(*this, dst->getAddr8(0, 0), srcM.fRowBytes);
|
||||||
if (offset) {
|
if (offset) {
|
||||||
offset->set(0, 0);
|
offset->set(0, 0);
|
||||||
|
@ -1229,7 +1229,7 @@ void SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
|
||||||
|
|
||||||
dst->setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(),
|
dst->setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(),
|
||||||
dstM.fBounds.height(), dstM.fRowBytes);
|
dstM.fBounds.height(), dstM.fRowBytes);
|
||||||
dst->allocPixels();
|
dst->allocPixels(allocator, NULL);
|
||||||
memcpy(dst->getPixels(), dstM.fImage, dstM.computeImageSize());
|
memcpy(dst->getPixels(), dstM.fImage, dstM.computeImageSize());
|
||||||
if (offset) {
|
if (offset) {
|
||||||
offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
|
offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include "SkColorPriv.h"
|
#include "SkColorPriv.h"
|
||||||
#include "SkUtils.h"
|
#include "SkUtils.h"
|
||||||
|
|
||||||
|
#define UNROLL
|
||||||
|
|
||||||
static void S32_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst,
|
static void S32_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst,
|
||||||
const SkPMColor* SK_RESTRICT src,
|
const SkPMColor* SK_RESTRICT src,
|
||||||
int count, U8CPU alpha) {
|
int count, U8CPU alpha) {
|
||||||
|
@ -16,11 +18,28 @@ static void S32_Blend_BlitRow32(SkPMColor* SK_RESTRICT dst,
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
unsigned src_scale = SkAlpha255To256(alpha);
|
unsigned src_scale = SkAlpha255To256(alpha);
|
||||||
unsigned dst_scale = 256 - src_scale;
|
unsigned dst_scale = 256 - src_scale;
|
||||||
|
|
||||||
|
#ifdef UNROLL
|
||||||
|
if (count & 1) {
|
||||||
|
*dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale);
|
||||||
|
dst += 1;
|
||||||
|
count -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SkPMColor* SK_RESTRICT srcEnd = src + count;
|
||||||
|
while (src != srcEnd) {
|
||||||
|
*dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale);
|
||||||
|
dst += 1;
|
||||||
|
*dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale);
|
||||||
|
dst += 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
do {
|
do {
|
||||||
*dst = SkAlphaMulQ(*src, src_scale) + SkAlphaMulQ(*dst, dst_scale);
|
*dst = SkAlphaMulQ(*src, src_scale) + SkAlphaMulQ(*dst, dst_scale);
|
||||||
src += 1;
|
src += 1;
|
||||||
dst += 1;
|
dst += 1;
|
||||||
} while (--count > 0);
|
} while (--count > 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +50,21 @@ static void S32A_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst,
|
||||||
int count, U8CPU alpha) {
|
int count, U8CPU alpha) {
|
||||||
SkASSERT(255 == alpha);
|
SkASSERT(255 == alpha);
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
|
#ifdef UNROLL
|
||||||
|
if (count & 1) {
|
||||||
|
*dst = SkPMSrcOver(*(src++), *dst);
|
||||||
|
dst += 1;
|
||||||
|
count -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SkPMColor* SK_RESTRICT srcEnd = src + count;
|
||||||
|
while (src != srcEnd) {
|
||||||
|
*dst = SkPMSrcOver(*(src++), *dst);
|
||||||
|
dst += 1;
|
||||||
|
*dst = SkPMSrcOver(*(src++), *dst);
|
||||||
|
dst += 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
do {
|
do {
|
||||||
#ifdef TEST_SRC_ALPHA
|
#ifdef TEST_SRC_ALPHA
|
||||||
SkPMColor sc = *src;
|
SkPMColor sc = *src;
|
||||||
|
@ -48,6 +82,7 @@ static void S32A_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst,
|
||||||
src += 1;
|
src += 1;
|
||||||
dst += 1;
|
dst += 1;
|
||||||
} while (--count > 0);
|
} while (--count > 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,11 +91,27 @@ static void S32A_Blend_BlitRow32(SkPMColor* SK_RESTRICT dst,
|
||||||
int count, U8CPU alpha) {
|
int count, U8CPU alpha) {
|
||||||
SkASSERT(alpha <= 255);
|
SkASSERT(alpha <= 255);
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
|
#ifdef UNROLL
|
||||||
|
if (count & 1) {
|
||||||
|
*dst = SkBlendARGB32(*(src++), *dst, alpha);
|
||||||
|
dst += 1;
|
||||||
|
count -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SkPMColor* SK_RESTRICT srcEnd = src + count;
|
||||||
|
while (src != srcEnd) {
|
||||||
|
*dst = SkBlendARGB32(*(src++), *dst, alpha);
|
||||||
|
dst += 1;
|
||||||
|
*dst = SkBlendARGB32(*(src++), *dst, alpha);
|
||||||
|
dst += 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
do {
|
do {
|
||||||
*dst = SkBlendARGB32(*src, *dst, alpha);
|
*dst = SkBlendARGB32(*src, *dst, alpha);
|
||||||
src += 1;
|
src += 1;
|
||||||
dst += 1;
|
dst += 1;
|
||||||
} while (--count > 0);
|
} while (--count > 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -249,7 +249,7 @@ SkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint&
|
||||||
}
|
}
|
||||||
|
|
||||||
SkA8_Shader_Blitter::~SkA8_Shader_Blitter() {
|
SkA8_Shader_Blitter::~SkA8_Shader_Blitter() {
|
||||||
SkSafeUnref(fXfermode);
|
if (fXfermode) SkSafeUnref(fXfermode);
|
||||||
sk_free(fBuffer);
|
sk_free(fBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,7 +342,9 @@ void SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
|
||||||
|
|
||||||
while (--height >= 0) {
|
while (--height >= 0) {
|
||||||
fShader->shadeSpan(x, y, span, width);
|
fShader->shadeSpan(x, y, span, width);
|
||||||
fXfermode->xferA8(device, span, width, alpha);
|
if (fXfermode) {
|
||||||
|
fXfermode->xferA8(device, span, width, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
y += 1;
|
y += 1;
|
||||||
device += fDevice.rowBytes();
|
device += fDevice.rowBytes();
|
||||||
|
|
|
@ -1233,10 +1233,14 @@ void SkScalerContext::MakeRec(const SkPaint& paint,
|
||||||
|
|
||||||
void SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
|
void SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
|
||||||
void (*proc)(const SkDescriptor*, void*),
|
void (*proc)(const SkDescriptor*, void*),
|
||||||
void* context) const {
|
void* context, bool ignoreGamma) const {
|
||||||
SkScalerContext::Rec rec;
|
SkScalerContext::Rec rec;
|
||||||
|
|
||||||
SkScalerContext::MakeRec(*this, deviceMatrix, &rec);
|
SkScalerContext::MakeRec(*this, deviceMatrix, &rec);
|
||||||
|
if (ignoreGamma) {
|
||||||
|
rec.fFlags &= ~(SkScalerContext::kGammaForBlack_Flag |
|
||||||
|
SkScalerContext::kGammaForWhite_Flag);
|
||||||
|
}
|
||||||
|
|
||||||
size_t descSize = sizeof(rec);
|
size_t descSize = sizeof(rec);
|
||||||
int entryCount = 1;
|
int entryCount = 1;
|
||||||
|
@ -1645,4 +1649,3 @@ const SkPath* SkTextToPathIter::next(SkScalar* xpos) {
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,3 +128,10 @@ const char* SkPixelRef::FactoryToName(Factory fact) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkPixelRef::globalRef(void* data) {
|
||||||
|
this->ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkPixelRef::globalUnref() {
|
||||||
|
this->unref();
|
||||||
|
}
|
||||||
|
|
|
@ -272,6 +272,18 @@ SkMemoryStream::~SkMemoryStream()
|
||||||
sk_free((void*)fSrc);
|
sk_free((void*)fSrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkMemoryStream::setMemoryOwned(const void* src, size_t size)
|
||||||
|
{
|
||||||
|
if (fWeOwnTheData)
|
||||||
|
sk_free((void*)fSrc);
|
||||||
|
|
||||||
|
fSize = size;
|
||||||
|
fOffset = 0;
|
||||||
|
fWeOwnTheData = true;
|
||||||
|
|
||||||
|
fSrc = src;
|
||||||
|
}
|
||||||
|
|
||||||
void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData)
|
void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData)
|
||||||
{
|
{
|
||||||
if (fWeOwnTheData)
|
if (fWeOwnTheData)
|
||||||
|
|
|
@ -74,8 +74,8 @@ SkPixelRef* SkFlipPixelRef::Create(SkFlattenableReadBuffer& buffer) {
|
||||||
return SkNEW_ARGS(SkFlipPixelRef, (buffer));
|
return SkNEW_ARGS(SkFlipPixelRef, (buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
static SkPixelRef::Registrar::Registrar reg("SkFlipPixelRef",
|
static SkPixelRef::Registrar reg("SkFlipPixelRef",
|
||||||
SkFlipPixelRef::Create);
|
SkFlipPixelRef::Create);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -125,4 +125,3 @@ void SkFlipPixelRef::CopyBitsFromAddr(const SkBitmap& dst, const SkRegion& clip,
|
||||||
iter.next();
|
iter.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,4 +71,3 @@ SkMovie* SkMovie::DecodeStream(SkStream* stream) {
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,11 @@ static const ColorMapObject* find_colormap(const GifFileType* gif) {
|
||||||
if (NULL == cmap) {
|
if (NULL == cmap) {
|
||||||
cmap = gif->SColorMap;
|
cmap = gif->SColorMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (NULL == cmap) {
|
||||||
|
// no colormap found
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
// some sanity checks
|
// some sanity checks
|
||||||
if (cmap && ((unsigned)cmap->ColorCount > 256 ||
|
if (cmap && ((unsigned)cmap->ColorCount > 256 ||
|
||||||
cmap->ColorCount != (1 << cmap->BitsPerPixel))) {
|
cmap->ColorCount != (1 << cmap->BitsPerPixel))) {
|
||||||
|
|
|
@ -223,13 +223,9 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
|
||||||
if (config == SkBitmap::kARGB_8888_Config) {
|
if (config == SkBitmap::kARGB_8888_Config) {
|
||||||
cinfo.out_color_space = JCS_RGBA_8888;
|
cinfo.out_color_space = JCS_RGBA_8888;
|
||||||
} else if (config == SkBitmap::kRGB_565_Config) {
|
} else if (config == SkBitmap::kRGB_565_Config) {
|
||||||
if (sampleSize == 1) {
|
cinfo.out_color_space = JCS_RGB_565;
|
||||||
// SkScaledBitmapSampler can't handle RGB_565 yet,
|
if (this->getDitherImage()) {
|
||||||
// so don't even try.
|
cinfo.dither_mode = JDITHER_ORDERED;
|
||||||
cinfo.out_color_space = JCS_RGB_565;
|
|
||||||
if (this->getDitherImage()) {
|
|
||||||
cinfo.dither_mode = JDITHER_ORDERED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -319,8 +315,8 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
|
||||||
#ifdef ANDROID_RGB
|
#ifdef ANDROID_RGB
|
||||||
} else if (JCS_RGBA_8888 == cinfo.out_color_space) {
|
} else if (JCS_RGBA_8888 == cinfo.out_color_space) {
|
||||||
sc = SkScaledBitmapSampler::kRGBX;
|
sc = SkScaledBitmapSampler::kRGBX;
|
||||||
//} else if (JCS_RGB_565 == cinfo.out_color_space) {
|
} else if (JCS_RGB_565 == cinfo.out_color_space) {
|
||||||
// sc = SkScaledBitmapSampler::kRGB_565;
|
sc = SkScaledBitmapSampler::kRGB_565;
|
||||||
#endif
|
#endif
|
||||||
} else if (1 == cinfo.out_color_components &&
|
} else if (1 == cinfo.out_color_components &&
|
||||||
JCS_GRAYSCALE == cinfo.out_color_space) {
|
JCS_GRAYSCALE == cinfo.out_color_space) {
|
||||||
|
|
|
@ -57,6 +57,16 @@ bool SkImageRef::getInfo(SkBitmap* bitmap) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SkImageRef::isOpaque(SkBitmap* bitmap) {
|
||||||
|
if (bitmap && bitmap->pixelRef() == this) {
|
||||||
|
bitmap->lockPixels();
|
||||||
|
bitmap->setIsOpaque(fBitmap.isOpaque());
|
||||||
|
bitmap->unlockPixels();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
SkImageDecoderFactory* SkImageRef::setDecoderFactory(
|
SkImageDecoderFactory* SkImageRef::setDecoderFactory(
|
||||||
SkImageDecoderFactory* fact) {
|
SkImageDecoderFactory* fact) {
|
||||||
SkRefCnt_SafeAssign(fFactory, fact);
|
SkRefCnt_SafeAssign(fFactory, fact);
|
||||||
|
|
|
@ -50,8 +50,8 @@ SkPixelRef* SkImageRef_GlobalPool::Create(SkFlattenableReadBuffer& buffer) {
|
||||||
return SkNEW_ARGS(SkImageRef_GlobalPool, (buffer));
|
return SkNEW_ARGS(SkImageRef_GlobalPool, (buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
static SkPixelRef::Registrar::Registrar reg("SkImageRef_GlobalPool",
|
static SkPixelRef::Registrar reg("SkImageRef_GlobalPool",
|
||||||
SkImageRef_GlobalPool::Create);
|
SkImageRef_GlobalPool::Create);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// global imagerefpool wrappers
|
// global imagerefpool wrappers
|
||||||
|
@ -80,4 +80,3 @@ void SkImageRef_GlobalPool::DumpPool() {
|
||||||
SkAutoMutexAcquire ac(gImageRefMutex);
|
SkAutoMutexAcquire ac(gImageRefMutex);
|
||||||
gGlobalImageRefPool.dump();
|
gGlobalImageRefPool.dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,24 @@ static void sk_init_source(j_decompress_ptr cinfo) {
|
||||||
skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
|
skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
|
||||||
src->next_input_byte = (const JOCTET*)src->fBuffer;
|
src->next_input_byte = (const JOCTET*)src->fBuffer;
|
||||||
src->bytes_in_buffer = 0;
|
src->bytes_in_buffer = 0;
|
||||||
|
src->current_offset = 0;
|
||||||
|
src->fStream->rewind();
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean sk_seek_input_data(j_decompress_ptr cinfo, long byte_offset) {
|
||||||
|
skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
|
||||||
|
|
||||||
|
if (byte_offset > src->current_offset) {
|
||||||
|
(void)src->fStream->skip(byte_offset - src->current_offset);
|
||||||
|
} else {
|
||||||
|
src->fStream->rewind();
|
||||||
|
(void)src->fStream->skip(byte_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
src->current_offset = byte_offset;
|
||||||
|
src->next_input_byte = (const JOCTET*)src->fBuffer;
|
||||||
|
src->bytes_in_buffer = 0;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) {
|
static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) {
|
||||||
|
@ -35,6 +53,7 @@ static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
src->current_offset += bytes;
|
||||||
src->next_input_byte = (const JOCTET*)src->fBuffer;
|
src->next_input_byte = (const JOCTET*)src->fBuffer;
|
||||||
src->bytes_in_buffer = bytes;
|
src->bytes_in_buffer = bytes;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -52,6 +71,7 @@ static void sk_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
|
||||||
cinfo->err->error_exit((j_common_ptr)cinfo);
|
cinfo->err->error_exit((j_common_ptr)cinfo);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
src->current_offset += bytes;
|
||||||
bytesToSkip -= bytes;
|
bytesToSkip -= bytes;
|
||||||
}
|
}
|
||||||
src->next_input_byte = (const JOCTET*)src->fBuffer;
|
src->next_input_byte = (const JOCTET*)src->fBuffer;
|
||||||
|
@ -83,7 +103,9 @@ static void sk_term_source(j_decompress_ptr /*cinfo*/) {}
|
||||||
static void skmem_init_source(j_decompress_ptr cinfo) {
|
static void skmem_init_source(j_decompress_ptr cinfo) {
|
||||||
skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
|
skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
|
||||||
src->next_input_byte = (const JOCTET*)src->fMemoryBase;
|
src->next_input_byte = (const JOCTET*)src->fMemoryBase;
|
||||||
|
src->start_input_byte = (const JOCTET*)src->fMemoryBase;
|
||||||
src->bytes_in_buffer = src->fMemoryBaseSize;
|
src->bytes_in_buffer = src->fMemoryBaseSize;
|
||||||
|
src->current_offset = src->fMemoryBaseSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean skmem_fill_input_buffer(j_decompress_ptr cinfo) {
|
static boolean skmem_fill_input_buffer(j_decompress_ptr cinfo) {
|
||||||
|
@ -108,31 +130,34 @@ static void skmem_term_source(j_decompress_ptr /*cinfo*/) {}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder) : fStream(stream) {
|
skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder,
|
||||||
|
bool ownStream) : fStream(stream) {
|
||||||
fDecoder = decoder;
|
fDecoder = decoder;
|
||||||
const void* baseAddr = stream->getMemoryBase();
|
const void* baseAddr = stream->getMemoryBase();
|
||||||
if (baseAddr && false) {
|
size_t bufferSize = 4096;
|
||||||
fMemoryBase = baseAddr;
|
size_t len;
|
||||||
fMemoryBaseSize = stream->getLength();
|
fMemoryBase = NULL;
|
||||||
|
fUnrefStream = ownStream;
|
||||||
|
fMemoryBaseSize = 0;
|
||||||
|
|
||||||
init_source = skmem_init_source;
|
init_source = sk_init_source;
|
||||||
fill_input_buffer = skmem_fill_input_buffer;
|
fill_input_buffer = sk_fill_input_buffer;
|
||||||
skip_input_data = skmem_skip_input_data;
|
skip_input_data = sk_skip_input_data;
|
||||||
resync_to_restart = skmem_resync_to_restart;
|
resync_to_restart = sk_resync_to_restart;
|
||||||
term_source = skmem_term_source;
|
term_source = sk_term_source;
|
||||||
} else {
|
seek_input_data = sk_seek_input_data;
|
||||||
fMemoryBase = NULL;
|
|
||||||
fMemoryBaseSize = 0;
|
|
||||||
|
|
||||||
init_source = sk_init_source;
|
|
||||||
fill_input_buffer = sk_fill_input_buffer;
|
|
||||||
skip_input_data = sk_skip_input_data;
|
|
||||||
resync_to_restart = sk_resync_to_restart;
|
|
||||||
term_source = sk_term_source;
|
|
||||||
}
|
|
||||||
// SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize);
|
// SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skjpeg_source_mgr::~skjpeg_source_mgr() {
|
||||||
|
if (fMemoryBase) {
|
||||||
|
sk_free(fMemoryBase);
|
||||||
|
}
|
||||||
|
if (fUnrefStream) {
|
||||||
|
fStream->unref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static void sk_init_destination(j_compress_ptr cinfo) {
|
static void sk_init_destination(j_compress_ptr cinfo) {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "SkColorPriv.h"
|
#include "SkColorPriv.h"
|
||||||
#include "SkStream.h"
|
#include "SkStream.h"
|
||||||
#include "SkTemplates.h"
|
#include "SkTemplates.h"
|
||||||
|
#include "SkUtils.h"
|
||||||
|
|
||||||
#include "gif_lib.h"
|
#include "gif_lib.h"
|
||||||
|
|
||||||
|
@ -35,7 +36,9 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GifFileType* fGIF;
|
GifFileType* fGIF;
|
||||||
SavedImage* fCurrSavedImage;
|
int fCurrIndex;
|
||||||
|
int fLastDrawIndex;
|
||||||
|
SkBitmap fBackup;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int Decode(GifFileType* fileType, GifByteType* out, int size) {
|
static int Decode(GifFileType* fileType, GifByteType* out, int size) {
|
||||||
|
@ -54,7 +57,8 @@ SkGIFMovie::SkGIFMovie(SkStream* stream)
|
||||||
DGifCloseFile(fGIF);
|
DGifCloseFile(fGIF);
|
||||||
fGIF = NULL;
|
fGIF = NULL;
|
||||||
}
|
}
|
||||||
fCurrSavedImage = NULL;
|
fCurrIndex = -1;
|
||||||
|
fLastDrawIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkGIFMovie::~SkGIFMovie()
|
SkGIFMovie::~SkGIFMovie()
|
||||||
|
@ -105,29 +109,242 @@ bool SkGIFMovie::onSetTime(SkMSec time)
|
||||||
dur += savedimage_duration(&fGIF->SavedImages[i]);
|
dur += savedimage_duration(&fGIF->SavedImages[i]);
|
||||||
if (dur >= time)
|
if (dur >= time)
|
||||||
{
|
{
|
||||||
SavedImage* prev = fCurrSavedImage;
|
fCurrIndex = i;
|
||||||
fCurrSavedImage = &fGIF->SavedImages[i];
|
return fLastDrawIndex != fCurrIndex;
|
||||||
return prev != fCurrSavedImage;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fCurrSavedImage = &fGIF->SavedImages[fGIF->ImageCount - 1];
|
fCurrIndex = fGIF->ImageCount - 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void copyLine(uint32_t* dst, const unsigned char* src, const ColorMapObject* cmap,
|
||||||
|
int transparent, int width)
|
||||||
|
{
|
||||||
|
for (; width > 0; width--, src++, dst++) {
|
||||||
|
if (*src != transparent) {
|
||||||
|
const GifColorType& col = cmap->Colors[*src];
|
||||||
|
*dst = SkPackARGB32(0xFF, col.Red, col.Green, col.Blue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copyInterlaceGroup(SkBitmap* bm, const unsigned char*& src,
|
||||||
|
const ColorMapObject* cmap, int transparent, int copyWidth,
|
||||||
|
int copyHeight, const GifImageDesc& imageDesc, int rowStep,
|
||||||
|
int startRow)
|
||||||
|
{
|
||||||
|
int row;
|
||||||
|
// every 'rowStep'th row, starting with row 'startRow'
|
||||||
|
for (row = startRow; row < copyHeight; row += rowStep) {
|
||||||
|
uint32_t* dst = bm->getAddr32(imageDesc.Left, imageDesc.Top + row);
|
||||||
|
copyLine(dst, src, cmap, transparent, copyWidth);
|
||||||
|
src += imageDesc.Width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pad for rest height
|
||||||
|
src += imageDesc.Width * ((imageDesc.Height - row + rowStep - 1) / rowStep);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blitInterlace(SkBitmap* bm, const SavedImage* frame, const ColorMapObject* cmap,
|
||||||
|
int transparent)
|
||||||
|
{
|
||||||
|
int width = bm->width();
|
||||||
|
int height = bm->height();
|
||||||
|
GifWord copyWidth = frame->ImageDesc.Width;
|
||||||
|
if (frame->ImageDesc.Left + copyWidth > width) {
|
||||||
|
copyWidth = width - frame->ImageDesc.Left;
|
||||||
|
}
|
||||||
|
|
||||||
|
GifWord copyHeight = frame->ImageDesc.Height;
|
||||||
|
if (frame->ImageDesc.Top + copyHeight > height) {
|
||||||
|
copyHeight = height - frame->ImageDesc.Top;
|
||||||
|
}
|
||||||
|
|
||||||
|
// deinterlace
|
||||||
|
const unsigned char* src = (unsigned char*)frame->RasterBits;
|
||||||
|
|
||||||
|
// group 1 - every 8th row, starting with row 0
|
||||||
|
copyInterlaceGroup(bm, src, cmap, transparent, copyWidth, copyHeight, frame->ImageDesc, 8, 0);
|
||||||
|
|
||||||
|
// group 2 - every 8th row, starting with row 4
|
||||||
|
copyInterlaceGroup(bm, src, cmap, transparent, copyWidth, copyHeight, frame->ImageDesc, 8, 4);
|
||||||
|
|
||||||
|
// group 3 - every 4th row, starting with row 2
|
||||||
|
copyInterlaceGroup(bm, src, cmap, transparent, copyWidth, copyHeight, frame->ImageDesc, 4, 2);
|
||||||
|
|
||||||
|
copyInterlaceGroup(bm, src, cmap, transparent, copyWidth, copyHeight, frame->ImageDesc, 2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blitNormal(SkBitmap* bm, const SavedImage* frame, const ColorMapObject* cmap,
|
||||||
|
int transparent)
|
||||||
|
{
|
||||||
|
int width = bm->width();
|
||||||
|
int height = bm->height();
|
||||||
|
const unsigned char* src = (unsigned char*)frame->RasterBits;
|
||||||
|
uint32_t* dst = bm->getAddr32(frame->ImageDesc.Left, frame->ImageDesc.Top);
|
||||||
|
GifWord copyWidth = frame->ImageDesc.Width;
|
||||||
|
if (frame->ImageDesc.Left + copyWidth > width) {
|
||||||
|
copyWidth = width - frame->ImageDesc.Left;
|
||||||
|
}
|
||||||
|
|
||||||
|
GifWord copyHeight = frame->ImageDesc.Height;
|
||||||
|
if (frame->ImageDesc.Top + copyHeight > height) {
|
||||||
|
copyHeight = height - frame->ImageDesc.Top;
|
||||||
|
}
|
||||||
|
|
||||||
|
int srcPad, dstPad;
|
||||||
|
dstPad = width - copyWidth;
|
||||||
|
srcPad = frame->ImageDesc.Width - copyWidth;
|
||||||
|
for (; copyHeight > 0; copyHeight--) {
|
||||||
|
copyLine(dst, src, cmap, transparent, copyWidth);
|
||||||
|
src += frame->ImageDesc.Width;
|
||||||
|
dst += width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fillRect(SkBitmap* bm, GifWord left, GifWord top, GifWord width, GifWord height,
|
||||||
|
uint32_t col)
|
||||||
|
{
|
||||||
|
int bmWidth = bm->width();
|
||||||
|
int bmHeight = bm->height();
|
||||||
|
uint32_t* dst = bm->getAddr32(left, top);
|
||||||
|
GifWord copyWidth = width;
|
||||||
|
if (left + copyWidth > bmWidth) {
|
||||||
|
copyWidth = bmWidth - left;
|
||||||
|
}
|
||||||
|
|
||||||
|
GifWord copyHeight = height;
|
||||||
|
if (top + copyHeight > bmHeight) {
|
||||||
|
copyHeight = bmHeight - top;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; copyHeight > 0; copyHeight--) {
|
||||||
|
sk_memset32(dst, col, copyWidth);
|
||||||
|
dst += bmWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawFrame(SkBitmap* bm, const SavedImage* frame, const ColorMapObject* cmap)
|
||||||
|
{
|
||||||
|
int transparent = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < frame->ExtensionBlockCount; ++i) {
|
||||||
|
ExtensionBlock* eb = frame->ExtensionBlocks + i;
|
||||||
|
if (eb->Function == GRAPHICS_EXT_FUNC_CODE &&
|
||||||
|
eb->ByteCount == 4) {
|
||||||
|
bool has_transparency = ((eb->Bytes[0] & 1) == 1);
|
||||||
|
if (has_transparency) {
|
||||||
|
transparent = (unsigned char)eb->Bytes[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame->ImageDesc.ColorMap != NULL) {
|
||||||
|
// use local color table
|
||||||
|
cmap = frame->ImageDesc.ColorMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmap == NULL || cmap->ColorCount != (1 << cmap->BitsPerPixel)) {
|
||||||
|
SkASSERT(!"bad colortable setup");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame->ImageDesc.Interlace) {
|
||||||
|
blitInterlace(bm, frame, cmap, transparent);
|
||||||
|
} else {
|
||||||
|
blitNormal(bm, frame, cmap, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool checkIfWillBeCleared(const SavedImage* frame)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < frame->ExtensionBlockCount; ++i) {
|
||||||
|
ExtensionBlock* eb = frame->ExtensionBlocks + i;
|
||||||
|
if (eb->Function == GRAPHICS_EXT_FUNC_CODE &&
|
||||||
|
eb->ByteCount == 4) {
|
||||||
|
// check disposal method
|
||||||
|
int disposal = ((eb->Bytes[0] >> 2) & 7);
|
||||||
|
if (disposal == 2 || disposal == 3) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void getTransparencyAndDisposalMethod(const SavedImage* frame, bool* trans, int* disposal)
|
||||||
|
{
|
||||||
|
*trans = false;
|
||||||
|
*disposal = 0;
|
||||||
|
for (int i = 0; i < frame->ExtensionBlockCount; ++i) {
|
||||||
|
ExtensionBlock* eb = frame->ExtensionBlocks + i;
|
||||||
|
if (eb->Function == GRAPHICS_EXT_FUNC_CODE &&
|
||||||
|
eb->ByteCount == 4) {
|
||||||
|
*trans = ((eb->Bytes[0] & 1) == 1);
|
||||||
|
*disposal = ((eb->Bytes[0] >> 2) & 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true if area of 'target' is completely covers area of 'covered'
|
||||||
|
static bool checkIfCover(const SavedImage* target, const SavedImage* covered)
|
||||||
|
{
|
||||||
|
if (target->ImageDesc.Left <= covered->ImageDesc.Left
|
||||||
|
&& covered->ImageDesc.Left + covered->ImageDesc.Width <=
|
||||||
|
target->ImageDesc.Left + target->ImageDesc.Width
|
||||||
|
&& target->ImageDesc.Top <= covered->ImageDesc.Top
|
||||||
|
&& covered->ImageDesc.Top + covered->ImageDesc.Height <=
|
||||||
|
target->ImageDesc.Top + target->ImageDesc.Height) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disposeFrameIfNeeded(SkBitmap* bm, const SavedImage* cur, const SavedImage* next,
|
||||||
|
SkBitmap* backup, SkColor color)
|
||||||
|
{
|
||||||
|
// We can skip disposal process if next frame is not transparent
|
||||||
|
// and completely covers current area
|
||||||
|
bool curTrans;
|
||||||
|
int curDisposal;
|
||||||
|
getTransparencyAndDisposalMethod(cur, &curTrans, &curDisposal);
|
||||||
|
bool nextTrans;
|
||||||
|
int nextDisposal;
|
||||||
|
getTransparencyAndDisposalMethod(next, &nextTrans, &nextDisposal);
|
||||||
|
if ((curDisposal == 2 || curDisposal == 3)
|
||||||
|
&& (nextTrans || !checkIfCover(next, cur))) {
|
||||||
|
switch (curDisposal) {
|
||||||
|
// restore to background color
|
||||||
|
// -> 'background' means background under this image.
|
||||||
|
case 2:
|
||||||
|
fillRect(bm, cur->ImageDesc.Left, cur->ImageDesc.Top,
|
||||||
|
cur->ImageDesc.Width, cur->ImageDesc.Height,
|
||||||
|
color);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// restore to previous
|
||||||
|
case 3:
|
||||||
|
bm->swap(*backup);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save current image if next frame's disposal method == 3
|
||||||
|
if (nextDisposal == 3) {
|
||||||
|
const uint32_t* src = bm->getAddr32(0, 0);
|
||||||
|
uint32_t* dst = backup->getAddr32(0, 0);
|
||||||
|
int cnt = bm->width() * bm->height();
|
||||||
|
memcpy(dst, src, cnt*sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool SkGIFMovie::onGetBitmap(SkBitmap* bm)
|
bool SkGIFMovie::onGetBitmap(SkBitmap* bm)
|
||||||
{
|
{
|
||||||
GifFileType* gif = fGIF;
|
const GifFileType* gif = fGIF;
|
||||||
if (NULL == gif)
|
if (NULL == gif)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// should we check for the Image cmap or the global (SColorMap) first?
|
if (gif->ImageCount < 1) {
|
||||||
ColorMapObject* cmap = gif->SColorMap;
|
|
||||||
if (cmap == NULL)
|
|
||||||
cmap = gif->Image.ColorMap;
|
|
||||||
|
|
||||||
if (cmap == NULL || gif->ImageCount < 1 || cmap->ColorCount != (1 << cmap->BitsPerPixel))
|
|
||||||
{
|
|
||||||
SkASSERT(!"bad colortable setup");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,76 +354,79 @@ bool SkGIFMovie::onGetBitmap(SkBitmap* bm)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SavedImage* gif_image = fCurrSavedImage;
|
// no need to draw
|
||||||
SkBitmap::Config config = SkBitmap::kIndex8_Config;
|
if (fLastDrawIndex >= 0 && fLastDrawIndex == fCurrIndex) {
|
||||||
|
return true;
|
||||||
SkColorTable* colorTable = SkNEW_ARGS(SkColorTable, (cmap->ColorCount));
|
|
||||||
SkAutoUnref aur(colorTable);
|
|
||||||
|
|
||||||
bm->setConfig(config, width, height, 0);
|
|
||||||
if (!bm->allocPixels(colorTable)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int transparent = -1;
|
int startIndex = fLastDrawIndex + 1;
|
||||||
for (int i = 0; i < gif_image->ExtensionBlockCount; ++i) {
|
if (fLastDrawIndex < 0 || !bm->readyToDraw()) {
|
||||||
ExtensionBlock* eb = gif_image->ExtensionBlocks + i;
|
// first time
|
||||||
if (eb->Function == 0xF9 &&
|
|
||||||
eb->ByteCount == 4) {
|
startIndex = 0;
|
||||||
bool has_transparency = ((eb->Bytes[0] & 1) == 1);
|
|
||||||
if (has_transparency) {
|
// create bitmap
|
||||||
transparent = (unsigned char)eb->Bytes[3];
|
bm->setConfig(SkBitmap::kARGB_8888_Config, width, height, 0);
|
||||||
|
if (!bm->allocPixels(NULL)) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
// create bitmap for backup
|
||||||
|
fBackup.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0);
|
||||||
|
if (!fBackup.allocPixels(NULL)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (startIndex > fCurrIndex) {
|
||||||
|
// rewind to 1st frame for repeat
|
||||||
|
startIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkPMColor* colorPtr = colorTable->lockColors();
|
int lastIndex = fCurrIndex;
|
||||||
|
if (lastIndex < 0) {
|
||||||
if (transparent >= 0)
|
// first time
|
||||||
memset(colorPtr, 0, cmap->ColorCount * 4);
|
lastIndex = 0;
|
||||||
else
|
} else if (lastIndex > fGIF->ImageCount - 1) {
|
||||||
colorTable->setFlags(colorTable->getFlags() | SkColorTable::kColorsAreOpaque_Flag);
|
// this block must not be reached.
|
||||||
|
lastIndex = fGIF->ImageCount - 1;
|
||||||
for (int index = 0; index < cmap->ColorCount; index++)
|
|
||||||
{
|
|
||||||
if (transparent != index)
|
|
||||||
colorPtr[index] = SkPackARGB32(0xFF, cmap->Colors[index].Red,
|
|
||||||
cmap->Colors[index].Green, cmap->Colors[index].Blue);
|
|
||||||
}
|
}
|
||||||
colorTable->unlockColors(true);
|
|
||||||
|
|
||||||
unsigned char* in = (unsigned char*)gif_image->RasterBits;
|
SkColor bgColor = SkPackARGB32(0, 0, 0, 0);
|
||||||
unsigned char* out = bm->getAddr8(0, 0);
|
if (gif->SColorMap != NULL) {
|
||||||
if (gif->Image.Interlace) {
|
const GifColorType& col = gif->SColorMap->Colors[fGIF->SBackGroundColor];
|
||||||
|
bgColor = SkColorSetARGB(0xFF, col.Red, col.Green, col.Blue);
|
||||||
// deinterlace
|
|
||||||
int row;
|
|
||||||
// group 1 - every 8th row, starting with row 0
|
|
||||||
for (row = 0; row < height; row += 8) {
|
|
||||||
memcpy(out + width * row, in, width);
|
|
||||||
in += width;
|
|
||||||
}
|
|
||||||
|
|
||||||
// group 2 - every 8th row, starting with row 4
|
|
||||||
for (row = 4; row < height; row += 8) {
|
|
||||||
memcpy(out + width * row, in, width);
|
|
||||||
in += width;
|
|
||||||
}
|
|
||||||
|
|
||||||
// group 3 - every 4th row, starting with row 2
|
|
||||||
for (row = 2; row < height; row += 4) {
|
|
||||||
memcpy(out + width * row, in, width);
|
|
||||||
in += width;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (row = 1; row < height; row += 2) {
|
|
||||||
memcpy(out + width * row, in, width);
|
|
||||||
in += width;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
memcpy(out, in, width * height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SkColor paintingColor = SkPackARGB32(0, 0, 0, 0);
|
||||||
|
// draw each frames - not intelligent way
|
||||||
|
for (int i = startIndex; i <= lastIndex; i++) {
|
||||||
|
const SavedImage* cur = &fGIF->SavedImages[i];
|
||||||
|
if (i == 0) {
|
||||||
|
bool trans;
|
||||||
|
int disposal;
|
||||||
|
getTransparencyAndDisposalMethod(cur, &trans, &disposal);
|
||||||
|
if (!trans && gif->SColorMap != NULL) {
|
||||||
|
paintingColor = bgColor;
|
||||||
|
} else {
|
||||||
|
paintingColor = SkColorSetARGB(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bm->eraseColor(paintingColor);
|
||||||
|
fBackup.eraseColor(paintingColor);
|
||||||
|
} else {
|
||||||
|
// Dispose previous frame before move to next frame.
|
||||||
|
const SavedImage* prev = &fGIF->SavedImages[i-1];
|
||||||
|
disposeFrameIfNeeded(bm, prev, cur, &fBackup, paintingColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw frame
|
||||||
|
// We can skip this process if this index is not last and disposal
|
||||||
|
// method == 2 or method == 3
|
||||||
|
if (i == lastIndex || !checkIfWillBeCleared(cur)) {
|
||||||
|
drawFrame(bm, cur, gif->SColorMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// save index
|
||||||
|
fLastDrawIndex = lastIndex;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,18 @@ static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool Sample_D565_D565(void* SK_RESTRICT dstRow,
|
||||||
|
const uint8_t* SK_RESTRICT src,
|
||||||
|
int width, int deltaSrc, int, const SkPMColor[]) {
|
||||||
|
uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
|
||||||
|
uint16_t* SK_RESTRICT castedSrc = (uint16_t*) src;
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
dst[x] = castedSrc[0];
|
||||||
|
castedSrc += deltaSrc >> 1;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow,
|
static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow,
|
||||||
const uint8_t* SK_RESTRICT src,
|
const uint8_t* SK_RESTRICT src,
|
||||||
int width, int deltaSrc, int y, const SkPMColor[]) {
|
int width, int deltaSrc, int y, const SkPMColor[]) {
|
||||||
|
@ -335,21 +347,25 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither,
|
||||||
Sample_RGBx_D8888, Sample_RGBx_D8888,
|
Sample_RGBx_D8888, Sample_RGBx_D8888,
|
||||||
Sample_RGBA_D8888, Sample_RGBA_D8888,
|
Sample_RGBA_D8888, Sample_RGBA_D8888,
|
||||||
Sample_Index_D8888, Sample_Index_D8888,
|
Sample_Index_D8888, Sample_Index_D8888,
|
||||||
|
NULL, NULL,
|
||||||
// 565 (no alpha distinction)
|
// 565 (no alpha distinction)
|
||||||
Sample_Gray_D565, Sample_Gray_D565_D,
|
Sample_Gray_D565, Sample_Gray_D565_D,
|
||||||
Sample_RGBx_D565, Sample_RGBx_D565_D,
|
Sample_RGBx_D565, Sample_RGBx_D565_D,
|
||||||
Sample_RGBx_D565, Sample_RGBx_D565_D,
|
Sample_RGBx_D565, Sample_RGBx_D565_D,
|
||||||
Sample_Index_D565, Sample_Index_D565_D,
|
Sample_Index_D565, Sample_Index_D565_D,
|
||||||
|
Sample_D565_D565, Sample_D565_D565,
|
||||||
// 4444
|
// 4444
|
||||||
Sample_Gray_D4444, Sample_Gray_D4444_D,
|
Sample_Gray_D4444, Sample_Gray_D4444_D,
|
||||||
Sample_RGBx_D4444, Sample_RGBx_D4444_D,
|
Sample_RGBx_D4444, Sample_RGBx_D4444_D,
|
||||||
Sample_RGBA_D4444, Sample_RGBA_D4444_D,
|
Sample_RGBA_D4444, Sample_RGBA_D4444_D,
|
||||||
Sample_Index_D4444, Sample_Index_D4444_D,
|
Sample_Index_D4444, Sample_Index_D4444_D,
|
||||||
|
NULL, NULL,
|
||||||
// Index8
|
// Index8
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
Sample_Index_DI, Sample_Index_DI,
|
Sample_Index_DI, Sample_Index_DI,
|
||||||
|
NULL, NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
fCTable = ctable;
|
fCTable = ctable;
|
||||||
|
@ -379,6 +395,10 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither,
|
||||||
fSrcPixelSize = 1;
|
fSrcPixelSize = 1;
|
||||||
index += 6;
|
index += 6;
|
||||||
break;
|
break;
|
||||||
|
case SkScaledBitmapSampler::kRGB_565:
|
||||||
|
fSrcPixelSize = 2;
|
||||||
|
index += 8;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -388,13 +408,13 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither,
|
||||||
index += 0;
|
index += 0;
|
||||||
break;
|
break;
|
||||||
case SkBitmap::kRGB_565_Config:
|
case SkBitmap::kRGB_565_Config:
|
||||||
index += 8;
|
index += 10;
|
||||||
break;
|
break;
|
||||||
case SkBitmap::kARGB_4444_Config:
|
case SkBitmap::kARGB_4444_Config:
|
||||||
index += 16;
|
index += 20;
|
||||||
break;
|
break;
|
||||||
case SkBitmap::kIndex8_Config:
|
case SkBitmap::kIndex8_Config:
|
||||||
index += 24;
|
index += 30;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -21,7 +21,8 @@ public:
|
||||||
kIndex, // 1 byte per pixel
|
kIndex, // 1 byte per pixel
|
||||||
kRGB, // 3 bytes per pixel
|
kRGB, // 3 bytes per pixel
|
||||||
kRGBX, // 4 byes per pixel (ignore 4th)
|
kRGBX, // 4 byes per pixel (ignore 4th)
|
||||||
kRGBA // 4 bytes per pixel
|
kRGBA, // 4 bytes per pixel
|
||||||
|
kRGB_565 // 2 bytes per pixel
|
||||||
};
|
};
|
||||||
|
|
||||||
// Given a dst bitmap (with pixels already allocated) and a src-config,
|
// Given a dst bitmap (with pixels already allocated) and a src-config,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "SkImageRef_ashmem.h"
|
#include "SkImageRef_ashmem.h"
|
||||||
#include "SkImageDecoder.h"
|
#include "SkImageDecoder.h"
|
||||||
|
#include "SkFlattenable.h"
|
||||||
#include "SkThread.h"
|
#include "SkThread.h"
|
||||||
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
@ -36,7 +37,7 @@ SkImageRef_ashmem::SkImageRef_ashmem(SkStream* stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
SkImageRef_ashmem::~SkImageRef_ashmem() {
|
SkImageRef_ashmem::~SkImageRef_ashmem() {
|
||||||
fCT->safeUnref();
|
SkSafeUnref(fCT);
|
||||||
this->closeFD();
|
this->closeFD();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,3 +202,36 @@ void SkImageRef_ashmem::onUnlockPixels() {
|
||||||
fBitmap.setPixels(NULL, NULL);
|
fBitmap.setPixels(NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkImageRef_ashmem::flatten(SkFlattenableWriteBuffer& buffer) const {
|
||||||
|
this->INHERITED::flatten(buffer);
|
||||||
|
const char* uri = getURI();
|
||||||
|
if (uri) {
|
||||||
|
size_t len = strlen(uri);
|
||||||
|
buffer.write32(len);
|
||||||
|
buffer.writePad(uri, len);
|
||||||
|
} else {
|
||||||
|
buffer.write32(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SkImageRef_ashmem::SkImageRef_ashmem(SkFlattenableReadBuffer& buffer)
|
||||||
|
: INHERITED(buffer) {
|
||||||
|
fRec.fFD = -1;
|
||||||
|
fRec.fAddr = NULL;
|
||||||
|
fRec.fSize = 0;
|
||||||
|
fRec.fPinned = false;
|
||||||
|
fCT = NULL;
|
||||||
|
size_t length = buffer.readU32();
|
||||||
|
if (length) {
|
||||||
|
char* buf = (char*) malloc(length);
|
||||||
|
buffer.read(buf, length);
|
||||||
|
setURI(buf, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SkPixelRef* SkImageRef_ashmem::Create(SkFlattenableReadBuffer& buffer) {
|
||||||
|
return SkNEW_ARGS(SkImageRef_ashmem, (buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
static SkPixelRef::Registrar reg("SkImageRef_ashmem",
|
||||||
|
SkImageRef_ashmem::Create);
|
||||||
|
|
|
@ -15,6 +15,13 @@ public:
|
||||||
SkImageRef_ashmem(SkStream*, SkBitmap::Config, int sampleSize = 1);
|
SkImageRef_ashmem(SkStream*, SkBitmap::Config, int sampleSize = 1);
|
||||||
virtual ~SkImageRef_ashmem();
|
virtual ~SkImageRef_ashmem();
|
||||||
|
|
||||||
|
// overrides
|
||||||
|
virtual void flatten(SkFlattenableWriteBuffer&) const;
|
||||||
|
virtual Factory getFactory() const {
|
||||||
|
return Create;
|
||||||
|
}
|
||||||
|
static SkPixelRef* Create(SkFlattenableReadBuffer&);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool onDecode(SkImageDecoder* codec, SkStream* stream,
|
virtual bool onDecode(SkImageDecoder* codec, SkStream* stream,
|
||||||
SkBitmap* bitmap, SkBitmap::Config config,
|
SkBitmap* bitmap, SkBitmap::Config config,
|
||||||
|
@ -24,6 +31,7 @@ protected:
|
||||||
virtual void onUnlockPixels();
|
virtual void onUnlockPixels();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
SkImageRef_ashmem(SkFlattenableReadBuffer&);
|
||||||
void closeFD();
|
void closeFD();
|
||||||
|
|
||||||
SkColorTable* fCT;
|
SkColorTable* fCT;
|
||||||
|
|
|
@ -235,15 +235,27 @@ static void drawNineViaRects(SkCanvas* canvas, const SkRect& dst,
|
||||||
const int32_t srcY[4] = {
|
const int32_t srcY[4] = {
|
||||||
0, margins.fTop, bitmap.height() - margins.fBottom, bitmap.height()
|
0, margins.fTop, bitmap.height() - margins.fBottom, bitmap.height()
|
||||||
};
|
};
|
||||||
const SkScalar dstX[4] = {
|
SkScalar dstX[4] = {
|
||||||
dst.fLeft, dst.fLeft + SkIntToScalar(margins.fLeft),
|
dst.fLeft, dst.fLeft + SkIntToScalar(margins.fLeft),
|
||||||
dst.fRight - SkIntToScalar(margins.fRight), dst.fRight
|
dst.fRight - SkIntToScalar(margins.fRight), dst.fRight
|
||||||
};
|
};
|
||||||
const SkScalar dstY[4] = {
|
SkScalar dstY[4] = {
|
||||||
dst.fTop, dst.fTop + SkIntToScalar(margins.fTop),
|
dst.fTop, dst.fTop + SkIntToScalar(margins.fTop),
|
||||||
dst.fBottom - SkIntToScalar(margins.fBottom), dst.fBottom
|
dst.fBottom - SkIntToScalar(margins.fBottom), dst.fBottom
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (dstX[1] > dstX[2]) {
|
||||||
|
dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * SkIntToScalar(margins.fLeft) /
|
||||||
|
(SkIntToScalar(margins.fLeft) + SkIntToScalar(margins.fRight));
|
||||||
|
dstX[2] = dstX[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dstY[1] > dstY[2]) {
|
||||||
|
dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * SkIntToScalar(margins.fTop) /
|
||||||
|
(SkIntToScalar(margins.fTop) + SkIntToScalar(margins.fBottom));
|
||||||
|
dstY[2] = dstY[1];
|
||||||
|
}
|
||||||
|
|
||||||
SkIRect s;
|
SkIRect s;
|
||||||
SkRect d;
|
SkRect d;
|
||||||
for (int y = 0; y < 3; y++) {
|
for (int y = 0; y < 3; y++) {
|
||||||
|
@ -279,6 +291,17 @@ void SkNinePatch::DrawNine(SkCanvas* canvas, const SkRect& bounds,
|
||||||
yDivs[0] = margins.fTop;
|
yDivs[0] = margins.fTop;
|
||||||
yDivs[1] = bitmap.height() - margins.fBottom;
|
yDivs[1] = bitmap.height() - margins.fBottom;
|
||||||
|
|
||||||
|
if (xDivs[0] > xDivs[1]) {
|
||||||
|
xDivs[0] = bitmap.width() * margins.fLeft /
|
||||||
|
(margins.fLeft + margins.fRight);
|
||||||
|
xDivs[1] = xDivs[0];
|
||||||
|
}
|
||||||
|
if (yDivs[0] > yDivs[1]) {
|
||||||
|
yDivs[0] = bitmap.height() * margins.fTop /
|
||||||
|
(margins.fTop + margins.fBottom);
|
||||||
|
yDivs[1] = yDivs[0];
|
||||||
|
}
|
||||||
|
|
||||||
SkNinePatch::DrawMesh(canvas, bounds, bitmap,
|
SkNinePatch::DrawMesh(canvas, bounds, bitmap,
|
||||||
xDivs, 2, yDivs, 2, paint);
|
xDivs, 2, yDivs, 2, paint);
|
||||||
} else {
|
} else {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче