GIF: Use SkTArray instead of std::vector

Speculative fix for a memory regression seen in Chromium. Chromium
previously used a WTF::Vector, which has a growth factor of 1.5, as does
SkTArray. Depending on the implementation of std::vector, this may slow
the allocation of memory.

Bug: 758946
Change-Id: I323390027467e32a6c66667c927fae0aba292446
Reviewed-on: https://skia-review.googlesource.com/40777
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Leon Scroggins <scroggo@google.com>
This commit is contained in:
Leon Scroggins III 2017-08-30 10:09:42 -04:00 committed by Skia Commit-Bot
parent 64dc4f6d4f
commit e750391c34
2 changed files with 14 additions and 17 deletions

View File

@ -344,7 +344,7 @@ sk_sp<SkColorTable> SkGIFColorMap::buildTable(SkStreamBuffer* streamBuffer, SkCo
}
sk_sp<SkColorTable> SkGifImageReader::getColorTable(SkColorType colorType, int index) {
if (index < 0 || static_cast<size_t>(index) >= m_frames.size()) {
if (index < 0 || index >= m_frames.count()) {
return nullptr;
}
@ -382,8 +382,7 @@ bool SkGIFFrameContext::decode(SkStreamBuffer* streamBuffer, SkGifCodec* client,
}
// Some bad GIFs have extra blocks beyond the last row, which we don't want to decode.
while (static_cast<size_t>(m_currentLzwBlock) < m_lzwBlocks.size()
&& m_lzwContext->hasRemainingRows()) {
while (m_currentLzwBlock < m_lzwBlocks.count() && m_lzwContext->hasRemainingRows()) {
const auto& block = m_lzwBlocks[m_currentLzwBlock];
const size_t len = block.blockSize;
@ -430,7 +429,7 @@ SkCodec::Result SkGifImageReader::parse(SkGifImageReader::SkGIFParseQuery query)
// SkGIFSizeQuery and SkGIFFrameCountQuery are negative, so this is only meaningful when >= 0.
const int lastFrameToParse = (int) query;
if (lastFrameToParse >= 0 && (int) m_frames.size() > lastFrameToParse
if (lastFrameToParse >= 0 && m_frames.count() > lastFrameToParse
&& m_frames[lastFrameToParse]->isComplete()) {
// We have already parsed this frame.
return SkCodec::kSuccess;
@ -823,7 +822,7 @@ SkCodec::Result SkGifImageReader::parse(SkGifImageReader::SkGIFParseQuery query)
// decode all rows but we treat it as frame complete.
m_frames.back()->setComplete();
GETN(1, SkGIFImageStart);
if (lastFrameToParse >= 0 && (int) m_frames.size() > lastFrameToParse) {
if (lastFrameToParse >= 0 && m_frames.count() > lastFrameToParse) {
m_streamBuffer.flush();
return SkCodec::kSuccess;
}
@ -874,9 +873,8 @@ bool SkGifImageReader::hasTransparency(int transparentPixel, bool isLocalColorma
void SkGifImageReader::addFrameIfNecessary()
{
if (m_frames.empty() || m_frames.back()->isComplete()) {
const size_t i = m_frames.size();
std::unique_ptr<SkGIFFrameContext> frame(new SkGIFFrameContext(this, static_cast<int>(i)));
m_frames.push_back(std::move(frame));
const int i = m_frames.count();
m_frames.emplace_back(new SkGIFFrameContext(this, i));
}
}

View File

@ -52,7 +52,6 @@ class SkGifCodec;
#include "SkStreamBuffer.h"
#include "../private/SkTArray.h"
#include <memory>
#include <vector>
typedef SkTArray<unsigned char, true> SkGIFRow;
@ -218,7 +217,7 @@ public:
void addLzwBlock(size_t position, size_t size)
{
m_lzwBlocks.push_back(SkGIFLZWBlock(position, size));
m_lzwBlocks.emplace_back(position, size);
}
bool decode(SkStreamBuffer*, SkGifCodec* client, bool* frameDecoded);
@ -265,7 +264,7 @@ private:
std::unique_ptr<SkGIFLZWContext> m_lzwContext;
// LZW blocks for this frame.
std::vector<SkGIFLZWBlock> m_lzwBlocks;
SkTArray<SkGIFLZWBlock> m_lzwBlocks;
SkGIFColorMap m_localColorMap;
@ -321,7 +320,7 @@ public:
int imagesCount() const
{
const size_t frames = m_frames.size();
const int frames = m_frames.count();
if (!frames) {
return 0;
}
@ -331,7 +330,7 @@ public:
// possibly SkGIFImageHeader) but before reading the color table. This
// ensures that we do not count a frame before we know its required
// frame.
return static_cast<int>(m_frames.back()->reachedStartOfData() ? frames : frames - 1);
return m_frames.back()->reachedStartOfData() ? frames : frames - 1;
}
int loopCount() const {
if (cLoopCountNotSeen == m_loopCount) {
@ -347,12 +346,12 @@ public:
const SkGIFFrameContext* frameContext(int index) const
{
return index >= 0 && index < static_cast<int>(m_frames.size())
return index >= 0 && index < m_frames.count()
? m_frames[index].get() : nullptr;
}
void clearDecodeState() {
for (size_t index = 0; index < m_frames.size(); index++) {
for (int index = 0; index < m_frames.count(); index++) {
m_frames[index]->clearDecodeState();
}
}
@ -381,7 +380,7 @@ private:
void addFrameIfNecessary();
bool currentFrameIsFirstFrame() const
{
return m_frames.empty() || (m_frames.size() == 1u && !m_frames[0]->isComplete());
return m_frames.empty() || (m_frames.count() == 1 && !m_frames[0]->isComplete());
}
// Unowned pointer
@ -398,7 +397,7 @@ private:
static constexpr int cLoopCountNotSeen = -2;
int m_loopCount; // Netscape specific extension block to control the number of animation loops a GIF renders.
std::vector<std::unique_ptr<SkGIFFrameContext>> m_frames;
SkTArray<std::unique_ptr<SkGIFFrameContext>> m_frames;
SkStreamBuffer m_streamBuffer;
bool m_parseCompleted;