summaryrefslogtreecommitdiff
path: root/image
diff options
context:
space:
mode:
Diffstat (limited to 'image')
-rw-r--r--image/DecoderFactory.cpp7
-rw-r--r--image/DecoderFactory.h1
-rw-r--r--image/IDecodingTask.cpp15
-rw-r--r--image/IDecodingTask.h8
-rw-r--r--image/Image.h2
-rw-r--r--image/ImageOps.cpp2
-rw-r--r--image/SourceBuffer.cpp14
-rw-r--r--image/SourceBuffer.h7
-rw-r--r--image/VectorImage.cpp9
-rw-r--r--image/VectorImage.h2
-rw-r--r--image/decoders/nsBMPDecoder.cpp17
-rw-r--r--image/decoders/nsBMPDecoder.h6
-rw-r--r--image/decoders/nsWebPDecoder.cpp4
13 files changed, 66 insertions, 28 deletions
diff --git a/image/DecoderFactory.cpp b/image/DecoderFactory.cpp
index 2085fb7c45..dffe4dc211 100644
--- a/image/DecoderFactory.cpp
+++ b/image/DecoderFactory.cpp
@@ -58,6 +58,10 @@ DecoderFactory::GetDecoderType(const char* aMimeType)
} else if (!strcmp(aMimeType, IMAGE_BMP_MS)) {
type = DecoderType::BMP;
+ // BMP_CLIPBOARD
+ } else if (!strcmp(aMimeType, IMAGE_BMP_MS_CLIPBOARD)) {
+ type = DecoderType::BMP_CLIPBOARD;
+
// ICO
} else if (!strcmp(aMimeType, IMAGE_ICO)) {
type = DecoderType::ICO;
@@ -100,6 +104,9 @@ DecoderFactory::GetDecoder(DecoderType aType,
case DecoderType::BMP:
decoder = new nsBMPDecoder(aImage);
break;
+ case DecoderType::BMP_CLIPBOARD:
+ decoder = new nsBMPDecoder(aImage, /* aForClipboard */ true);
+ break;
case DecoderType::ICO:
decoder = new nsICODecoder(aImage);
break;
diff --git a/image/DecoderFactory.h b/image/DecoderFactory.h
index f8cf64cc60..5638789ff6 100644
--- a/image/DecoderFactory.h
+++ b/image/DecoderFactory.h
@@ -34,6 +34,7 @@ enum class DecoderType
GIF,
JPEG,
BMP,
+ BMP_CLIPBOARD,
ICO,
ICON,
WEBP,
diff --git a/image/IDecodingTask.cpp b/image/IDecodingTask.cpp
index a067e7a7d1..6e2f039be1 100644
--- a/image/IDecodingTask.cpp
+++ b/image/IDecodingTask.cpp
@@ -142,8 +142,10 @@ MetadataDecodingTask::Run()
// AnonymousDecodingTask implementation.
///////////////////////////////////////////////////////////////////////////////
-AnonymousDecodingTask::AnonymousDecodingTask(NotNull<Decoder*> aDecoder)
+AnonymousDecodingTask::AnonymousDecodingTask(NotNull<Decoder*> aDecoder,
+ bool aResumable)
: mDecoder(aDecoder)
+ , mResumable(aResumable)
{ }
void
@@ -168,5 +170,16 @@ AnonymousDecodingTask::Run()
}
}
+void
+AnonymousDecodingTask::Resume()
+{
+ // Anonymous decoders normally get all their data at once. We have some situations
+ // where they don't. If explicitly requested, resuming should be supported.
+ if (mResumable) {
+ RefPtr<AnonymousDecodingTask> self(this);
+ NS_DispatchToMainThread(NS_NewRunnableFunction([self]() -> void { self->Run(); }));
+ }
+}
+
} // namespace image
} // namespace mozilla
diff --git a/image/IDecodingTask.h b/image/IDecodingTask.h
index 196ce5fdc4..3cbab5006f 100644
--- a/image/IDecodingTask.h
+++ b/image/IDecodingTask.h
@@ -102,22 +102,20 @@ class AnonymousDecodingTask final : public IDecodingTask
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AnonymousDecodingTask, override)
- explicit AnonymousDecodingTask(NotNull<Decoder*> aDecoder);
+ explicit AnonymousDecodingTask(NotNull<Decoder*> aDecoder, bool aResumable);
void Run() override;
bool ShouldPreferSyncRun() const override { return true; }
TaskPriority Priority() const override { return TaskPriority::eLow; }
- // Anonymous decoders normally get all their data at once. We have tests where
- // they don't; in these situations, the test re-runs them manually. So no
- // matter what, we don't want to resume by posting a task to the DecodePool.
- void Resume() override { }
+ void Resume() override;
private:
virtual ~AnonymousDecodingTask() { }
NotNull<RefPtr<Decoder>> mDecoder;
+ bool mResumable;
};
} // namespace image
diff --git a/image/Image.h b/image/Image.h
index bcabd1cc7b..98c5e8ca54 100644
--- a/image/Image.h
+++ b/image/Image.h
@@ -220,8 +220,6 @@ public:
virtual void SetHasError() = 0;
virtual ImageURL* GetURI() = 0;
-
- virtual void ReportUseCounters() { }
};
class ImageResource : public Image
diff --git a/image/ImageOps.cpp b/image/ImageOps.cpp
index addee7f155..ddd2f200e5 100644
--- a/image/ImageOps.cpp
+++ b/image/ImageOps.cpp
@@ -126,7 +126,7 @@ ImageOps::DecodeToSurface(nsIInputStream* aInputStream,
}
// Run the decoder synchronously.
- RefPtr<IDecodingTask> task = new AnonymousDecodingTask(WrapNotNull(decoder));
+ RefPtr<IDecodingTask> task = new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ false);
task->Run();
if (!decoder->GetDecodeDone() || decoder->HasError()) {
return nullptr;
diff --git a/image/SourceBuffer.cpp b/image/SourceBuffer.cpp
index de0719d451..de066e29fc 100644
--- a/image/SourceBuffer.cpp
+++ b/image/SourceBuffer.cpp
@@ -451,10 +451,18 @@ SourceBuffer::AppendFromInputStream(nsIInputStream* aInputStream,
uint32_t bytesRead;
nsresult rv = aInputStream->ReadSegments(AppendToSourceBuffer, this,
aCount, &bytesRead);
- if (!NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_ASSERT(bytesRead == aCount,
- "AppendToSourceBuffer should consume everything");
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ if (bytesRead == 0) {
+ // The loading of the image has been canceled.
+ return NS_ERROR_FAILURE;
}
+
+ MOZ_ASSERT(bytesRead == aCount,
+ "AppendToSourceBuffer should consume everything");
+
return rv;
}
diff --git a/image/SourceBuffer.h b/image/SourceBuffer.h
index 64727e65e2..6f2c74d33b 100644
--- a/image/SourceBuffer.h
+++ b/image/SourceBuffer.h
@@ -174,6 +174,13 @@ public:
return mState == READY ? mData.mIterating.mNextReadLength : 0;
}
+ /// If we're ready to read, returns whether or not everything available thus
+ /// far has been in the same contiguous buffer.
+ bool IsContiguous() const {
+ MOZ_ASSERT(mState == READY, "Calling IsContiguous() in the wrong state");
+ return mState == READY ? mData.mIterating.mChunk == 0 : false;
+ }
+
/// @return a count of the chunks we've advanced through.
uint32_t ChunkCount() const { return mChunkCount; }
diff --git a/image/VectorImage.cpp b/image/VectorImage.cpp
index 1e59b13fa7..3028c1c2ec 100644
--- a/image/VectorImage.cpp
+++ b/image/VectorImage.cpp
@@ -1337,15 +1337,6 @@ VectorImage::PropagateUseCounters(nsIDocument* aParentDocument)
}
}
-void
-VectorImage::ReportUseCounters()
-{
- nsIDocument* doc = mSVGDocumentWrapper->GetDocument();
- if (doc) {
- static_cast<nsDocument*>(doc)->ReportUseCounters();
- }
-}
-
nsIntSize
VectorImage::OptimalImageSizeForDest(const gfxSize& aDest,
uint32_t aWhichFrame,
diff --git a/image/VectorImage.h b/image/VectorImage.h
index e19aa939fb..bd4d393ed4 100644
--- a/image/VectorImage.h
+++ b/image/VectorImage.h
@@ -68,8 +68,6 @@ public:
void OnSVGDocumentLoaded();
void OnSVGDocumentError();
- virtual void ReportUseCounters() override;
-
protected:
explicit VectorImage(ImageURL* aURI = nullptr);
virtual ~VectorImage();
diff --git a/image/decoders/nsBMPDecoder.cpp b/image/decoders/nsBMPDecoder.cpp
index 42bb3486a8..fc79c223d6 100644
--- a/image/decoders/nsBMPDecoder.cpp
+++ b/image/decoders/nsBMPDecoder.cpp
@@ -185,9 +185,11 @@ nsBMPDecoder::nsBMPDecoder(RasterImage* aImage, State aState, size_t aLength)
{
}
-// Constructor for normal BMP files.
-nsBMPDecoder::nsBMPDecoder(RasterImage* aImage)
- : nsBMPDecoder(aImage, State::FILE_HEADER, FILE_HEADER_LENGTH)
+// Constructor for normal BMP files or from the clipboard.
+nsBMPDecoder::nsBMPDecoder(RasterImage* aImage, bool aForClipboard)
+ : nsBMPDecoder(aImage,
+ aForClipboard ? State::CLIPBOARD_HEADER : State::FILE_HEADER,
+ aForClipboard ? BIHSIZE_FIELD_LENGTH : FILE_HEADER_LENGTH)
{
}
@@ -455,6 +457,7 @@ nsBMPDecoder::DoDecode(SourceBufferIterator& aIterator, IResumable* aOnResume)
[=](State aState, const char* aData, size_t aLength) {
switch (aState) {
case State::FILE_HEADER: return ReadFileHeader(aData, aLength);
+ case State::CLIPBOARD_HEADER: return ReadClipboardHeader(aData, aLength);
case State::INFO_HEADER_SIZE: return ReadInfoHeaderSize(aData, aLength);
case State::INFO_HEADER_REST: return ReadInfoHeaderRest(aData, aLength);
case State::BITFIELDS: return ReadBitfields(aData, aLength);
@@ -488,6 +491,14 @@ nsBMPDecoder::ReadFileHeader(const char* aData, size_t aLength)
return Transition::To(State::INFO_HEADER_SIZE, BIHSIZE_FIELD_LENGTH);
}
+LexerTransition<nsBMPDecoder::State>
+nsBMPDecoder::ReadClipboardHeader(const char* aData, size_t aLength)
+{
+ // With the clipboard, the data offset is the header length.
+ mH.mDataOffset = LittleEndian::readUint32(aData);
+ return ReadInfoHeaderSize(aData, aLength);
+}
+
// We read the info header in two steps: (a) read the mBIHSize field to
// determine how long the header is; (b) read the rest of the header.
LexerTransition<nsBMPDecoder::State>
diff --git a/image/decoders/nsBMPDecoder.h b/image/decoders/nsBMPDecoder.h
index 0cf2af6890..2583816497 100644
--- a/image/decoders/nsBMPDecoder.h
+++ b/image/decoders/nsBMPDecoder.h
@@ -152,6 +152,7 @@ private:
enum class State {
FILE_HEADER,
+ CLIPBOARD_HEADER,
INFO_HEADER_SIZE,
INFO_HEADER_REST,
BITFIELDS,
@@ -164,8 +165,8 @@ private:
RLE_ABSOLUTE
};
- // This is the constructor used for normal BMP images.
- explicit nsBMPDecoder(RasterImage* aImage);
+ // This is the constructor used for normal and clipboard BMP images.
+ explicit nsBMPDecoder(RasterImage* aImage, bool aForClipboard = false);
// This is the constructor used for BMP resources in ICO images.
nsBMPDecoder(RasterImage* aImage, uint32_t aDataOffset);
@@ -180,6 +181,7 @@ private:
void FinishRow();
LexerTransition<State> ReadFileHeader(const char* aData, size_t aLength);
+ LexerTransition<State> ReadClipboardHeader(const char* aData, size_t aLength);
LexerTransition<State> ReadInfoHeaderSize(const char* aData, size_t aLength);
LexerTransition<State> ReadInfoHeaderRest(const char* aData, size_t aLength);
LexerTransition<State> ReadBitfields(const char* aData, size_t aLength);
diff --git a/image/decoders/nsWebPDecoder.cpp b/image/decoders/nsWebPDecoder.cpp
index 4f3cc8b2ad..3181e3a3ad 100644
--- a/image/decoders/nsWebPDecoder.cpp
+++ b/image/decoders/nsWebPDecoder.cpp
@@ -144,6 +144,10 @@ nsWebPDecoder::UpdateBuffer(SourceBufferIterator& aIterator,
switch (aState) {
case SourceBufferIterator::READY:
+ if(!aIterator.IsContiguous()) {
+ //We need to buffer. This should be rare, but expensive.
+ break;
+ }
if (!mData) {
// For as long as we hold onto an iterator, we know the data pointers
// to the chunks cannot change underneath us, so save the pointer to