diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/images/SkGIFMovie.cpp | 451 | ||||
-rw-r--r-- | src/images/SkMovie.cpp | 94 | ||||
-rw-r--r-- | src/images/SkMovie_FactoryDefault.cpp | 26 | ||||
-rw-r--r-- | src/ports/SkImageEncoder_none.cpp | 9 |
4 files changed, 0 insertions, 580 deletions
diff --git a/src/images/SkGIFMovie.cpp b/src/images/SkGIFMovie.cpp deleted file mode 100644 index 00df53d237..0000000000 --- a/src/images/SkGIFMovie.cpp +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Copyright 2006 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - - -#include "SkMovie.h" -#include "SkColor.h" -#include "SkColorPriv.h" -#include "SkStream.h" -#include "SkTemplates.h" -#include "SkUtils.h" - -#include "gif_lib.h" - -#if GIFLIB_MAJOR < 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 0) -#define DGifCloseFile(a, b) DGifCloseFile(a) -#endif - -class SkGIFMovie : public SkMovie { -public: - SkGIFMovie(SkStream* stream); - virtual ~SkGIFMovie(); - -protected: - virtual bool onGetInfo(Info*); - virtual bool onSetTime(SkMSec); - virtual bool onGetBitmap(SkBitmap*); - -private: - GifFileType* fGIF; - int fCurrIndex; - int fLastDrawIndex; - SkBitmap fBackup; - SkColor fPaintingColor; -}; - -static int Decode(GifFileType* fileType, GifByteType* out, int size) { - SkStream* stream = (SkStream*) fileType->UserData; - return (int) stream->read(out, size); -} - -SkGIFMovie::SkGIFMovie(SkStream* stream) -{ -#if GIFLIB_MAJOR < 5 - fGIF = DGifOpen( stream, Decode ); -#else - fGIF = DGifOpen( stream, Decode, nullptr ); -#endif - if (nullptr == fGIF) - return; - - if (DGifSlurp(fGIF) != GIF_OK) - { - DGifCloseFile(fGIF, nullptr); - fGIF = nullptr; - } - fCurrIndex = -1; - fLastDrawIndex = -1; - fPaintingColor = SkPackARGB32(0, 0, 0, 0); -} - -SkGIFMovie::~SkGIFMovie() -{ - if (fGIF) - DGifCloseFile(fGIF, nullptr); -} - -static SkMSec savedimage_duration(const SavedImage* image) -{ - for (int j = 0; j < image->ExtensionBlockCount; j++) - { - if (image->ExtensionBlocks[j].Function == GRAPHICS_EXT_FUNC_CODE) - { - SkASSERT(image->ExtensionBlocks[j].ByteCount >= 4); - const uint8_t* b = (const uint8_t*)image->ExtensionBlocks[j].Bytes; - return ((b[2] << 8) | b[1]) * 10; - } - } - return 0; -} - -bool SkGIFMovie::onGetInfo(Info* info) -{ - if (nullptr == fGIF) - return false; - - SkMSec dur = 0; - for (int i = 0; i < fGIF->ImageCount; i++) - dur += savedimage_duration(&fGIF->SavedImages[i]); - - info->fDuration = dur; - info->fWidth = fGIF->SWidth; - info->fHeight = fGIF->SHeight; - info->fIsOpaque = false; // how to compute? - return true; -} - -bool SkGIFMovie::onSetTime(SkMSec time) -{ - if (nullptr == fGIF) - return false; - - SkMSec dur = 0; - for (int i = 0; i < fGIF->ImageCount; i++) - { - dur += savedimage_duration(&fGIF->SavedImages[i]); - if (dur >= time) - { - fCurrIndex = i; - return fLastDrawIndex != fCurrIndex; - } - } - 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); - } - } -} - -#if GIFLIB_MAJOR < 5 -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); -} -#endif - -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; - } - - 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 != nullptr) { - // use local color table - cmap = frame->ImageDesc.ColorMap; - } - - if (cmap == nullptr || cmap->ColorCount != (1 << cmap->BitsPerPixel)) { - SkDEBUGFAIL("bad colortable setup"); - return; - } - -#if GIFLIB_MAJOR < 5 - // before GIFLIB 5, de-interlacing wasn't done by library at load time - if (frame->ImageDesc.Interlace) { - blitInterlace(bm, frame, cmap, transparent); - return; - } -#endif - - 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) -{ - const GifFileType* gif = fGIF; - if (nullptr == gif) - return false; - - if (gif->ImageCount < 1) { - return false; - } - - const int width = gif->SWidth; - const int height = gif->SHeight; - if (width <= 0 || height <= 0) { - return false; - } - - // no need to draw - if (fLastDrawIndex >= 0 && fLastDrawIndex == fCurrIndex) { - return true; - } - - int startIndex = fLastDrawIndex + 1; - if (fLastDrawIndex < 0 || !bm->readyToDraw()) { - // first time - - startIndex = 0; - - // create bitmap - if (!bm->tryAllocN32Pixels(width, height)) { - return false; - } - // create bitmap for backup - if (!fBackup.tryAllocN32Pixels(width, height)) { - return false; - } - } else if (startIndex > fCurrIndex) { - // rewind to 1st frame for repeat - startIndex = 0; - } - - 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; - } - - SkColor bgColor = SkPackARGB32(0, 0, 0, 0); - if (gif->SColorMap != nullptr) { - const GifColorType& col = gif->SColorMap->Colors[fGIF->SBackGroundColor]; - bgColor = SkColorSetARGB(0xFF, col.Red, col.Green, col.Blue); - } - - // 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 != nullptr) { - fPaintingColor = bgColor; - } else { - fPaintingColor = SkColorSetARGB(0, 0, 0, 0); - } - - bm->eraseColor(fPaintingColor); - fBackup.eraseColor(fPaintingColor); - } else { - // Dispose previous frame before move to next frame. - const SavedImage* prev = &fGIF->SavedImages[i-1]; - disposeFrameIfNeeded(bm, prev, cur, &fBackup, fPaintingColor); - } - - // 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; -} - -/////////////////////////////////////////////////////////////////////////////// - -#include "SkTRegistry.h" - -SkMovie* Factory(SkStreamRewindable* stream) { - char buf[GIF_STAMP_LEN]; - if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) { - if (memcmp(GIF_STAMP, buf, GIF_STAMP_LEN) == 0 || - memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 || - memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0) { - // must rewind here, since our construct wants to re-read the data - stream->rewind(); - return new SkGIFMovie(stream); - } - } - return nullptr; -} - -static SkTRegistry<SkMovie*(*)(SkStreamRewindable*)> gReg(Factory); diff --git a/src/images/SkMovie.cpp b/src/images/SkMovie.cpp deleted file mode 100644 index a0a37dcffa..0000000000 --- a/src/images/SkMovie.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "SkMovie.h" -#include "SkCanvas.h" -#include "SkPaint.h" - -// We should never see this in normal operation since our time values are -// 0-based. So we use it as a sentinal. -#define UNINITIALIZED_MSEC ((SkMSec)-1) - -SkMovie::SkMovie() -{ - fInfo.fDuration = UNINITIALIZED_MSEC; // uninitialized - fCurrTime = UNINITIALIZED_MSEC; // uninitialized - fNeedBitmap = true; -} - -void SkMovie::ensureInfo() -{ - if (fInfo.fDuration == UNINITIALIZED_MSEC && !this->onGetInfo(&fInfo)) - memset(&fInfo, 0, sizeof(fInfo)); // failure -} - -SkMSec SkMovie::duration() -{ - this->ensureInfo(); - return fInfo.fDuration; -} - -int SkMovie::width() -{ - this->ensureInfo(); - return fInfo.fWidth; -} - -int SkMovie::height() -{ - this->ensureInfo(); - return fInfo.fHeight; -} - -int SkMovie::isOpaque() -{ - this->ensureInfo(); - return fInfo.fIsOpaque; -} - -bool SkMovie::setTime(SkMSec time) -{ - SkMSec dur = this->duration(); - if (time > dur) - time = dur; - - bool changed = false; - if (time != fCurrTime) - { - fCurrTime = time; - changed = this->onSetTime(time); - fNeedBitmap |= changed; - } - return changed; -} - -const SkBitmap& SkMovie::bitmap() -{ - if (fCurrTime == UNINITIALIZED_MSEC) // uninitialized - this->setTime(0); - - if (fNeedBitmap) - { - if (!this->onGetBitmap(&fBitmap)) // failure - fBitmap.reset(); - fNeedBitmap = false; - } - return fBitmap; -} - -//////////////////////////////////////////////////////////////////// - -#include "SkStream.h" - -SkMovie* SkMovie::DecodeMemory(const void* data, size_t length) { - SkMemoryStream stream(data, length, false); - return SkMovie::DecodeStream(&stream); -} - -SkMovie* SkMovie::DecodeFile(const char path[]) { - std::unique_ptr<SkStreamRewindable> stream = SkStream::MakeFromFile(path); - return stream ? SkMovie::DecodeStream(stream.get()) : nullptr; -} diff --git a/src/images/SkMovie_FactoryDefault.cpp b/src/images/SkMovie_FactoryDefault.cpp deleted file mode 100644 index 84ae78a880..0000000000 --- a/src/images/SkMovie_FactoryDefault.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2006 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkMovie.h" -#include "SkStream.h" - -typedef SkTRegistry<SkMovie*(*)(SkStreamRewindable*)> MovieReg; - -SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) { - const MovieReg* curr = MovieReg::Head(); - while (curr) { - SkMovie* movie = curr->factory()(stream); - if (movie) { - return movie; - } - // we must rewind only if we got nullptr, since we gave the stream to the - // movie, who may have already started reading from it - stream->rewind(); - curr = curr->next(); - } - return nullptr; -} diff --git a/src/ports/SkImageEncoder_none.cpp b/src/ports/SkImageEncoder_none.cpp index c7d4b92425..327a220111 100644 --- a/src/ports/SkImageEncoder_none.cpp +++ b/src/ports/SkImageEncoder_none.cpp @@ -8,20 +8,11 @@ #include "SkBitmap.h" #include "SkImage.h" #include "SkImageEncoder.h" -#include "SkMovie.h" #include "SkPixelSerializer.h" #include "SkStream.h" ///////////////////////////////////////////////////////////////////////// -// Empty implementation for SkMovie. - -SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) { - return nullptr; -} - -///////////////////////////////////////////////////////////////////////// - // Empty implementations for SkImageEncoder. SkImageEncoder* SkImageEncoder::Create(Type t) { |