Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(681)

Unified Diff: src/images/SkGIFMovie.cpp

Issue 2449213004: Remove SkMovie and giflib (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « include/images/SkMovie.h ('k') | src/images/SkMovie.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/images/SkGIFMovie.cpp
diff --git a/src/images/SkGIFMovie.cpp b/src/images/SkGIFMovie.cpp
deleted file mode 100644
index 00df53d237ed1909210e778a5309a5d3d1835287..0000000000000000000000000000000000000000
--- 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);
« no previous file with comments | « include/images/SkMovie.h ('k') | src/images/SkMovie.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698