зеркало из 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);
|
||||
|
||||
void extractAlpha(SkBitmap* dst) const {
|
||||
this->extractAlpha(dst, NULL, NULL);
|
||||
this->extractAlpha(dst, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
void flatten(SkFlattenableWriteBuffer&) const;
|
||||
|
|
|
@ -855,7 +855,7 @@ private:
|
|||
|
||||
void descriptorProc(const SkMatrix* deviceMatrix,
|
||||
void (*proc)(const SkDescriptor*, void*),
|
||||
void* context) const;
|
||||
void* context, bool ignoreGamma = false) const;
|
||||
|
||||
const SkRect& computeStrokeFastBounds(const SkRect& orig,
|
||||
SkRect* storage) const;
|
||||
|
|
|
@ -119,6 +119,18 @@ public:
|
|||
virtual Factory getFactory() const { return NULL; }
|
||||
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 const char* FactoryToName(Factory);
|
||||
static void Register(const char name[], Factory);
|
||||
|
|
|
@ -177,6 +177,11 @@ public:
|
|||
*/
|
||||
virtual void setMemory(const void* data, size_t length,
|
||||
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();
|
||||
virtual bool rewind();
|
||||
virtual size_t read(void* buffer, size_t size);
|
||||
|
|
|
@ -62,8 +62,10 @@ private:
|
|||
// See also SkTScopedPtr.
|
||||
template <typename T> class SkAutoTDelete : SkNoncopyable {
|
||||
public:
|
||||
SkAutoTDelete(T* obj) : fObj(obj) {}
|
||||
~SkAutoTDelete() { delete fObj; }
|
||||
SkAutoTDelete(T* obj, bool deleteWhenDone = true) : fObj(obj) {
|
||||
fDeleteWhenDone = deleteWhenDone;
|
||||
}
|
||||
~SkAutoTDelete() { if (fDeleteWhenDone) delete fObj; }
|
||||
|
||||
T* get() const { return fObj; }
|
||||
void free() { delete fObj; fObj = NULL; }
|
||||
|
@ -71,6 +73,7 @@ public:
|
|||
|
||||
private:
|
||||
T* fObj;
|
||||
bool fDeleteWhenDone;
|
||||
};
|
||||
|
||||
template <typename T> class SkAutoTDeleteArray : SkNoncopyable {
|
||||
|
|
|
@ -57,6 +57,12 @@ public:
|
|||
*/
|
||||
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; }
|
||||
// returns the factory parameter
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
const void* fMemoryBase;
|
||||
void* fMemoryBase;
|
||||
size_t fMemoryBaseSize;
|
||||
bool fUnrefStream;
|
||||
SkImageDecoder* fDecoder;
|
||||
enum {
|
||||
kBufferSize = 1024
|
||||
|
|
|
@ -1186,7 +1186,7 @@ static bool GetBitmapAlpha(const SkBitmap& src, uint8_t SK_RESTRICT alpha[],
|
|||
#include "SkMatrix.h"
|
||||
|
||||
void SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
|
||||
SkIPoint* offset) const {
|
||||
Allocator *allocator, SkIPoint* offset) const {
|
||||
SkDEBUGCODE(this->validate();)
|
||||
|
||||
SkMatrix identity;
|
||||
|
@ -1210,7 +1210,7 @@ void SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
|
|||
NO_FILTER_CASE:
|
||||
dst->setConfig(SkBitmap::kA8_Config, this->width(), this->height(),
|
||||
srcM.fRowBytes);
|
||||
dst->allocPixels();
|
||||
dst->allocPixels(allocator, NULL);
|
||||
GetBitmapAlpha(*this, dst->getAddr8(0, 0), srcM.fRowBytes);
|
||||
if (offset) {
|
||||
offset->set(0, 0);
|
||||
|
@ -1229,7 +1229,7 @@ void SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
|
|||
|
||||
dst->setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(),
|
||||
dstM.fBounds.height(), dstM.fRowBytes);
|
||||
dst->allocPixels();
|
||||
dst->allocPixels(allocator, NULL);
|
||||
memcpy(dst->getPixels(), dstM.fImage, dstM.computeImageSize());
|
||||
if (offset) {
|
||||
offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include "SkColorPriv.h"
|
||||
#include "SkUtils.h"
|
||||
|
||||
#define UNROLL
|
||||
|
||||
static void S32_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst,
|
||||
const SkPMColor* SK_RESTRICT src,
|
||||
int count, U8CPU alpha) {
|
||||
|
@ -16,11 +18,28 @@ static void S32_Blend_BlitRow32(SkPMColor* SK_RESTRICT dst,
|
|||
if (count > 0) {
|
||||
unsigned src_scale = SkAlpha255To256(alpha);
|
||||
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 {
|
||||
*dst = SkAlphaMulQ(*src, src_scale) + SkAlphaMulQ(*dst, dst_scale);
|
||||
src += 1;
|
||||
dst += 1;
|
||||
} while (--count > 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,6 +50,21 @@ static void S32A_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst,
|
|||
int count, U8CPU alpha) {
|
||||
SkASSERT(255 == alpha);
|
||||
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 {
|
||||
#ifdef TEST_SRC_ALPHA
|
||||
SkPMColor sc = *src;
|
||||
|
@ -48,6 +82,7 @@ static void S32A_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst,
|
|||
src += 1;
|
||||
dst += 1;
|
||||
} while (--count > 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,11 +91,27 @@ static void S32A_Blend_BlitRow32(SkPMColor* SK_RESTRICT dst,
|
|||
int count, U8CPU alpha) {
|
||||
SkASSERT(alpha <= 255);
|
||||
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 {
|
||||
*dst = SkBlendARGB32(*src, *dst, alpha);
|
||||
src += 1;
|
||||
dst += 1;
|
||||
} 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() {
|
||||
SkSafeUnref(fXfermode);
|
||||
if (fXfermode) SkSafeUnref(fXfermode);
|
||||
sk_free(fBuffer);
|
||||
}
|
||||
|
||||
|
@ -342,7 +342,9 @@ void SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
|
|||
|
||||
while (--height >= 0) {
|
||||
fShader->shadeSpan(x, y, span, width);
|
||||
fXfermode->xferA8(device, span, width, alpha);
|
||||
if (fXfermode) {
|
||||
fXfermode->xferA8(device, span, width, alpha);
|
||||
}
|
||||
|
||||
y += 1;
|
||||
device += fDevice.rowBytes();
|
||||
|
|
|
@ -1233,10 +1233,14 @@ void SkScalerContext::MakeRec(const SkPaint& paint,
|
|||
|
||||
void SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
|
||||
void (*proc)(const SkDescriptor*, void*),
|
||||
void* context) const {
|
||||
void* context, bool ignoreGamma) const {
|
||||
SkScalerContext::Rec rec;
|
||||
|
||||
SkScalerContext::MakeRec(*this, deviceMatrix, &rec);
|
||||
if (ignoreGamma) {
|
||||
rec.fFlags &= ~(SkScalerContext::kGammaForBlack_Flag |
|
||||
SkScalerContext::kGammaForWhite_Flag);
|
||||
}
|
||||
|
||||
size_t descSize = sizeof(rec);
|
||||
int entryCount = 1;
|
||||
|
@ -1645,4 +1649,3 @@ const SkPath* SkTextToPathIter::next(SkScalar* xpos) {
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -128,3 +128,10 @@ const char* SkPixelRef::FactoryToName(Factory fact) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void SkPixelRef::globalRef(void* data) {
|
||||
this->ref();
|
||||
}
|
||||
|
||||
void SkPixelRef::globalUnref() {
|
||||
this->unref();
|
||||
}
|
||||
|
|
|
@ -272,6 +272,18 @@ SkMemoryStream::~SkMemoryStream()
|
|||
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)
|
||||
{
|
||||
if (fWeOwnTheData)
|
||||
|
|
|
@ -74,8 +74,8 @@ SkPixelRef* SkFlipPixelRef::Create(SkFlattenableReadBuffer& buffer) {
|
|||
return SkNEW_ARGS(SkFlipPixelRef, (buffer));
|
||||
}
|
||||
|
||||
static SkPixelRef::Registrar::Registrar reg("SkFlipPixelRef",
|
||||
SkFlipPixelRef::Create);
|
||||
static SkPixelRef::Registrar reg("SkFlipPixelRef",
|
||||
SkFlipPixelRef::Create);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -125,4 +125,3 @@ void SkFlipPixelRef::CopyBitsFromAddr(const SkBitmap& dst, const SkRegion& clip,
|
|||
iter.next();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,4 +71,3 @@ SkMovie* SkMovie::DecodeStream(SkStream* stream) {
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -117,6 +117,11 @@ static const ColorMapObject* find_colormap(const GifFileType* gif) {
|
|||
if (NULL == cmap) {
|
||||
cmap = gif->SColorMap;
|
||||
}
|
||||
|
||||
if (NULL == cmap) {
|
||||
// no colormap found
|
||||
return NULL;
|
||||
}
|
||||
// some sanity checks
|
||||
if (cmap && ((unsigned)cmap->ColorCount > 256 ||
|
||||
cmap->ColorCount != (1 << cmap->BitsPerPixel))) {
|
||||
|
|
|
@ -223,13 +223,9 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
|
|||
if (config == SkBitmap::kARGB_8888_Config) {
|
||||
cinfo.out_color_space = JCS_RGBA_8888;
|
||||
} else if (config == SkBitmap::kRGB_565_Config) {
|
||||
if (sampleSize == 1) {
|
||||
// SkScaledBitmapSampler can't handle RGB_565 yet,
|
||||
// so don't even try.
|
||||
cinfo.out_color_space = JCS_RGB_565;
|
||||
if (this->getDitherImage()) {
|
||||
cinfo.dither_mode = JDITHER_ORDERED;
|
||||
}
|
||||
cinfo.out_color_space = JCS_RGB_565;
|
||||
if (this->getDitherImage()) {
|
||||
cinfo.dither_mode = JDITHER_ORDERED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -319,8 +315,8 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
|
|||
#ifdef ANDROID_RGB
|
||||
} else if (JCS_RGBA_8888 == cinfo.out_color_space) {
|
||||
sc = SkScaledBitmapSampler::kRGBX;
|
||||
//} else if (JCS_RGB_565 == cinfo.out_color_space) {
|
||||
// sc = SkScaledBitmapSampler::kRGB_565;
|
||||
} else if (JCS_RGB_565 == cinfo.out_color_space) {
|
||||
sc = SkScaledBitmapSampler::kRGB_565;
|
||||
#endif
|
||||
} else if (1 == cinfo.out_color_components &&
|
||||
JCS_GRAYSCALE == cinfo.out_color_space) {
|
||||
|
|
|
@ -57,6 +57,16 @@ bool SkImageRef::getInfo(SkBitmap* bitmap) {
|
|||
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* fact) {
|
||||
SkRefCnt_SafeAssign(fFactory, fact);
|
||||
|
|
|
@ -50,8 +50,8 @@ SkPixelRef* SkImageRef_GlobalPool::Create(SkFlattenableReadBuffer& buffer) {
|
|||
return SkNEW_ARGS(SkImageRef_GlobalPool, (buffer));
|
||||
}
|
||||
|
||||
static SkPixelRef::Registrar::Registrar reg("SkImageRef_GlobalPool",
|
||||
SkImageRef_GlobalPool::Create);
|
||||
static SkPixelRef::Registrar reg("SkImageRef_GlobalPool",
|
||||
SkImageRef_GlobalPool::Create);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// global imagerefpool wrappers
|
||||
|
@ -80,4 +80,3 @@ void SkImageRef_GlobalPool::DumpPool() {
|
|||
SkAutoMutexAcquire ac(gImageRefMutex);
|
||||
gGlobalImageRefPool.dump();
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,24 @@ static void sk_init_source(j_decompress_ptr cinfo) {
|
|||
skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
|
||||
src->next_input_byte = (const JOCTET*)src->fBuffer;
|
||||
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) {
|
||||
|
@ -35,6 +53,7 @@ static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
src->current_offset += bytes;
|
||||
src->next_input_byte = (const JOCTET*)src->fBuffer;
|
||||
src->bytes_in_buffer = bytes;
|
||||
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);
|
||||
return;
|
||||
}
|
||||
src->current_offset += bytes;
|
||||
bytesToSkip -= bytes;
|
||||
}
|
||||
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) {
|
||||
skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
|
||||
src->next_input_byte = (const JOCTET*)src->fMemoryBase;
|
||||
src->start_input_byte = (const JOCTET*)src->fMemoryBase;
|
||||
src->bytes_in_buffer = src->fMemoryBaseSize;
|
||||
src->current_offset = src->fMemoryBaseSize;
|
||||
}
|
||||
|
||||
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;
|
||||
const void* baseAddr = stream->getMemoryBase();
|
||||
if (baseAddr && false) {
|
||||
fMemoryBase = baseAddr;
|
||||
fMemoryBaseSize = stream->getLength();
|
||||
size_t bufferSize = 4096;
|
||||
size_t len;
|
||||
fMemoryBase = NULL;
|
||||
fUnrefStream = ownStream;
|
||||
fMemoryBaseSize = 0;
|
||||
|
||||
init_source = skmem_init_source;
|
||||
fill_input_buffer = skmem_fill_input_buffer;
|
||||
skip_input_data = skmem_skip_input_data;
|
||||
resync_to_restart = skmem_resync_to_restart;
|
||||
term_source = skmem_term_source;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
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;
|
||||
seek_input_data = sk_seek_input_data;
|
||||
// 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) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "SkColorPriv.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkTemplates.h"
|
||||
#include "SkUtils.h"
|
||||
|
||||
#include "gif_lib.h"
|
||||
|
||||
|
@ -35,7 +36,9 @@ protected:
|
|||
|
||||
private:
|
||||
GifFileType* fGIF;
|
||||
SavedImage* fCurrSavedImage;
|
||||
int fCurrIndex;
|
||||
int fLastDrawIndex;
|
||||
SkBitmap fBackup;
|
||||
};
|
||||
|
||||
static int Decode(GifFileType* fileType, GifByteType* out, int size) {
|
||||
|
@ -54,7 +57,8 @@ SkGIFMovie::SkGIFMovie(SkStream* stream)
|
|||
DGifCloseFile(fGIF);
|
||||
fGIF = NULL;
|
||||
}
|
||||
fCurrSavedImage = NULL;
|
||||
fCurrIndex = -1;
|
||||
fLastDrawIndex = -1;
|
||||
}
|
||||
|
||||
SkGIFMovie::~SkGIFMovie()
|
||||
|
@ -105,29 +109,242 @@ bool SkGIFMovie::onSetTime(SkMSec time)
|
|||
dur += savedimage_duration(&fGIF->SavedImages[i]);
|
||||
if (dur >= time)
|
||||
{
|
||||
SavedImage* prev = fCurrSavedImage;
|
||||
fCurrSavedImage = &fGIF->SavedImages[i];
|
||||
return prev != fCurrSavedImage;
|
||||
fCurrIndex = i;
|
||||
return fLastDrawIndex != fCurrIndex;
|
||||
}
|
||||
}
|
||||
fCurrSavedImage = &fGIF->SavedImages[fGIF->ImageCount - 1];
|
||||
fCurrIndex = fGIF->ImageCount - 1;
|
||||
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)
|
||||
{
|
||||
GifFileType* gif = fGIF;
|
||||
const GifFileType* gif = fGIF;
|
||||
if (NULL == gif)
|
||||
return false;
|
||||
|
||||
// should we check for the Image cmap or the global (SColorMap) first?
|
||||
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");
|
||||
if (gif->ImageCount < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -137,76 +354,79 @@ bool SkGIFMovie::onGetBitmap(SkBitmap* bm)
|
|||
return false;
|
||||
}
|
||||
|
||||
SavedImage* gif_image = fCurrSavedImage;
|
||||
SkBitmap::Config config = SkBitmap::kIndex8_Config;
|
||||
|
||||
SkColorTable* colorTable = SkNEW_ARGS(SkColorTable, (cmap->ColorCount));
|
||||
SkAutoUnref aur(colorTable);
|
||||
|
||||
bm->setConfig(config, width, height, 0);
|
||||
if (!bm->allocPixels(colorTable)) {
|
||||
return false;
|
||||
// no need to draw
|
||||
if (fLastDrawIndex >= 0 && fLastDrawIndex == fCurrIndex) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int transparent = -1;
|
||||
for (int i = 0; i < gif_image->ExtensionBlockCount; ++i) {
|
||||
ExtensionBlock* eb = gif_image->ExtensionBlocks + i;
|
||||
if (eb->Function == 0xF9 &&
|
||||
eb->ByteCount == 4) {
|
||||
bool has_transparency = ((eb->Bytes[0] & 1) == 1);
|
||||
if (has_transparency) {
|
||||
transparent = (unsigned char)eb->Bytes[3];
|
||||
int startIndex = fLastDrawIndex + 1;
|
||||
if (fLastDrawIndex < 0 || !bm->readyToDraw()) {
|
||||
// first time
|
||||
|
||||
startIndex = 0;
|
||||
|
||||
// create bitmap
|
||||
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();
|
||||
|
||||
if (transparent >= 0)
|
||||
memset(colorPtr, 0, cmap->ColorCount * 4);
|
||||
else
|
||||
colorTable->setFlags(colorTable->getFlags() | SkColorTable::kColorsAreOpaque_Flag);
|
||||
|
||||
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);
|
||||
int lastIndex = fCurrIndex;
|
||||
if (lastIndex < 0) {
|
||||
// first time
|
||||
lastIndex = 0;
|
||||
} else if (lastIndex > fGIF->ImageCount - 1) {
|
||||
// this block must not be reached.
|
||||
lastIndex = fGIF->ImageCount - 1;
|
||||
}
|
||||
colorTable->unlockColors(true);
|
||||
|
||||
unsigned char* in = (unsigned char*)gif_image->RasterBits;
|
||||
unsigned char* out = bm->getAddr8(0, 0);
|
||||
if (gif->Image.Interlace) {
|
||||
|
||||
// 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);
|
||||
SkColor bgColor = SkPackARGB32(0, 0, 0, 0);
|
||||
if (gif->SColorMap != NULL) {
|
||||
const GifColorType& col = gif->SColorMap->Colors[fGIF->SBackGroundColor];
|
||||
bgColor = SkColorSetARGB(0xFF, col.Red, col.Green, col.Blue);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -93,6 +93,18 @@ static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow,
|
|||
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,
|
||||
const uint8_t* SK_RESTRICT src,
|
||||
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_RGBA_D8888, Sample_RGBA_D8888,
|
||||
Sample_Index_D8888, Sample_Index_D8888,
|
||||
NULL, NULL,
|
||||
// 565 (no alpha distinction)
|
||||
Sample_Gray_D565, Sample_Gray_D565_D,
|
||||
Sample_RGBx_D565, Sample_RGBx_D565_D,
|
||||
Sample_RGBx_D565, Sample_RGBx_D565_D,
|
||||
Sample_Index_D565, Sample_Index_D565_D,
|
||||
Sample_D565_D565, Sample_D565_D565,
|
||||
// 4444
|
||||
Sample_Gray_D4444, Sample_Gray_D4444_D,
|
||||
Sample_RGBx_D4444, Sample_RGBx_D4444_D,
|
||||
Sample_RGBA_D4444, Sample_RGBA_D4444_D,
|
||||
Sample_Index_D4444, Sample_Index_D4444_D,
|
||||
NULL, NULL,
|
||||
// Index8
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
Sample_Index_DI, Sample_Index_DI,
|
||||
NULL, NULL,
|
||||
};
|
||||
|
||||
fCTable = ctable;
|
||||
|
@ -379,6 +395,10 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither,
|
|||
fSrcPixelSize = 1;
|
||||
index += 6;
|
||||
break;
|
||||
case SkScaledBitmapSampler::kRGB_565:
|
||||
fSrcPixelSize = 2;
|
||||
index += 8;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -388,13 +408,13 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither,
|
|||
index += 0;
|
||||
break;
|
||||
case SkBitmap::kRGB_565_Config:
|
||||
index += 8;
|
||||
index += 10;
|
||||
break;
|
||||
case SkBitmap::kARGB_4444_Config:
|
||||
index += 16;
|
||||
index += 20;
|
||||
break;
|
||||
case SkBitmap::kIndex8_Config:
|
||||
index += 24;
|
||||
index += 30;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -21,7 +21,8 @@ public:
|
|||
kIndex, // 1 byte per pixel
|
||||
kRGB, // 3 bytes per pixel
|
||||
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,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "SkImageRef_ashmem.h"
|
||||
#include "SkImageDecoder.h"
|
||||
#include "SkFlattenable.h"
|
||||
#include "SkThread.h"
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
@ -36,7 +37,7 @@ SkImageRef_ashmem::SkImageRef_ashmem(SkStream* stream,
|
|||
}
|
||||
|
||||
SkImageRef_ashmem::~SkImageRef_ashmem() {
|
||||
fCT->safeUnref();
|
||||
SkSafeUnref(fCT);
|
||||
this->closeFD();
|
||||
}
|
||||
|
||||
|
@ -201,3 +202,36 @@ void SkImageRef_ashmem::onUnlockPixels() {
|
|||
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);
|
||||
virtual ~SkImageRef_ashmem();
|
||||
|
||||
// overrides
|
||||
virtual void flatten(SkFlattenableWriteBuffer&) const;
|
||||
virtual Factory getFactory() const {
|
||||
return Create;
|
||||
}
|
||||
static SkPixelRef* Create(SkFlattenableReadBuffer&);
|
||||
|
||||
protected:
|
||||
virtual bool onDecode(SkImageDecoder* codec, SkStream* stream,
|
||||
SkBitmap* bitmap, SkBitmap::Config config,
|
||||
|
@ -24,6 +31,7 @@ protected:
|
|||
virtual void onUnlockPixels();
|
||||
|
||||
private:
|
||||
SkImageRef_ashmem(SkFlattenableReadBuffer&);
|
||||
void closeFD();
|
||||
|
||||
SkColorTable* fCT;
|
||||
|
|
|
@ -235,15 +235,27 @@ static void drawNineViaRects(SkCanvas* canvas, const SkRect& dst,
|
|||
const int32_t srcY[4] = {
|
||||
0, margins.fTop, bitmap.height() - margins.fBottom, bitmap.height()
|
||||
};
|
||||
const SkScalar dstX[4] = {
|
||||
SkScalar dstX[4] = {
|
||||
dst.fLeft, dst.fLeft + SkIntToScalar(margins.fLeft),
|
||||
dst.fRight - SkIntToScalar(margins.fRight), dst.fRight
|
||||
};
|
||||
const SkScalar dstY[4] = {
|
||||
SkScalar dstY[4] = {
|
||||
dst.fTop, dst.fTop + SkIntToScalar(margins.fTop),
|
||||
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;
|
||||
SkRect d;
|
||||
for (int y = 0; y < 3; y++) {
|
||||
|
@ -278,6 +290,17 @@ void SkNinePatch::DrawNine(SkCanvas* canvas, const SkRect& bounds,
|
|||
xDivs[1] = bitmap.width() - margins.fRight;
|
||||
yDivs[0] = margins.fTop;
|
||||
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,
|
||||
xDivs, 2, yDivs, 2, paint);
|
||||
|
|
Загрузка…
Ссылка в новой задаче