michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozilla_imagelib_FrameSequence_h_ michael@0: #define mozilla_imagelib_FrameSequence_h_ michael@0: michael@0: #include "nsTArray.h" michael@0: #include "mozilla/MemoryReporting.h" michael@0: #include "gfxTypes.h" michael@0: #include "imgFrame.h" michael@0: michael@0: namespace mozilla { michael@0: namespace image { michael@0: michael@0: /** michael@0: * FrameDataPair is a slightly-smart tuple of (frame, raw frame data) where the michael@0: * raw frame data is allowed to be (and is, initially) null. michael@0: * michael@0: * If you call LockAndGetData, you will be able to call GetFrameData() on that michael@0: * instance, and when the FrameDataPair is destructed, the imgFrame lock will michael@0: * be unlocked. michael@0: */ michael@0: class FrameDataPair michael@0: { michael@0: public: michael@0: explicit FrameDataPair(imgFrame* frame) michael@0: : mFrame(frame) michael@0: , mFrameData(nullptr) michael@0: {} michael@0: michael@0: FrameDataPair() michael@0: : mFrame(nullptr) michael@0: , mFrameData(nullptr) michael@0: {} michael@0: michael@0: FrameDataPair(FrameDataPair& other) michael@0: { michael@0: mFrame = other.mFrame; michael@0: mFrameData = other.mFrameData; michael@0: michael@0: // since mFrame is an nsAutoPtr, the assignment operator above actually michael@0: // nulls out other.mFrame. In order to fully assume ownership over the michael@0: // frame, we also null out the other's mFrameData. michael@0: other.mFrameData = nullptr; michael@0: } michael@0: michael@0: ~FrameDataPair() michael@0: { michael@0: if (mFrameData) { michael@0: mFrame->UnlockImageData(); michael@0: } michael@0: } michael@0: michael@0: // Lock the frame and store its mFrameData. The frame will be unlocked (and michael@0: // deleted) when this FrameDataPair is deleted. michael@0: void LockAndGetData() michael@0: { michael@0: if (mFrame) { michael@0: if (NS_SUCCEEDED(mFrame->LockImageData())) { michael@0: if (mFrame->GetIsPaletted()) { michael@0: mFrameData = reinterpret_cast(mFrame->GetPaletteData()); michael@0: } else { michael@0: mFrameData = mFrame->GetImageData(); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: michael@0: // Null out this FrameDataPair and return its frame. You must ensure the michael@0: // frame will be deleted separately. michael@0: imgFrame* Forget() michael@0: { michael@0: if (mFrameData) { michael@0: mFrame->UnlockImageData(); michael@0: } michael@0: michael@0: imgFrame* frame = mFrame.forget(); michael@0: mFrameData = nullptr; michael@0: return frame; michael@0: } michael@0: michael@0: bool HasFrameData() const michael@0: { michael@0: if (mFrameData) { michael@0: MOZ_ASSERT(!!mFrame); michael@0: } michael@0: return !!mFrameData; michael@0: } michael@0: michael@0: uint8_t* GetFrameData() const michael@0: { michael@0: return mFrameData; michael@0: } michael@0: michael@0: imgFrame* GetFrame() const michael@0: { michael@0: return mFrame; michael@0: } michael@0: michael@0: // Resets this FrameDataPair to work with a different frame. Takes ownership michael@0: // of the frame, deleting the old frame (if any). michael@0: void SetFrame(imgFrame* frame) michael@0: { michael@0: if (mFrameData) { michael@0: mFrame->UnlockImageData(); michael@0: } michael@0: michael@0: mFrame = frame; michael@0: mFrameData = nullptr; michael@0: } michael@0: michael@0: operator imgFrame*() const michael@0: { michael@0: return GetFrame(); michael@0: } michael@0: michael@0: imgFrame* operator->() const michael@0: { michael@0: return GetFrame(); michael@0: } michael@0: michael@0: bool operator==(imgFrame* other) const michael@0: { michael@0: return mFrame == other; michael@0: } michael@0: michael@0: private: michael@0: nsAutoPtr mFrame; michael@0: uint8_t* mFrameData; michael@0: }; michael@0: michael@0: /** michael@0: * FrameSequence stores image frames (and their associated raw data pointers). michael@0: * It is little more than a smart array. michael@0: */ michael@0: class FrameSequence michael@0: { michael@0: public: michael@0: michael@0: ~FrameSequence(); michael@0: michael@0: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FrameSequence) michael@0: michael@0: /** michael@0: * Get the read-only (frame, data) pair at index aIndex. michael@0: */ michael@0: const FrameDataPair& GetFrame(uint32_t aIndex) const; michael@0: michael@0: /** michael@0: * Insert a frame into the array. FrameSequence takes ownership of the frame. michael@0: */ michael@0: void InsertFrame(uint32_t framenum, imgFrame* aFrame); michael@0: michael@0: /** michael@0: * Remove (and delete) the frame at index framenum. michael@0: */ michael@0: void RemoveFrame(uint32_t framenum); michael@0: michael@0: /** michael@0: * Swap aFrame with the frame at sequence framenum, and return that frame. michael@0: * You take ownership over the frame returned. michael@0: */ michael@0: imgFrame* SwapFrame(uint32_t framenum, imgFrame* aFrame); michael@0: michael@0: /** michael@0: * Remove (and delete) all frames. michael@0: */ michael@0: void ClearFrames(); michael@0: michael@0: /* The total number of frames in this image. */ michael@0: uint32_t GetNumFrames() const; michael@0: michael@0: size_t SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation, michael@0: mozilla::MallocSizeOf aMallocSizeOf) const; michael@0: michael@0: private: // data michael@0: //! All the frames of the image michael@0: nsTArray mFrames; michael@0: }; michael@0: michael@0: } // namespace image michael@0: } // namespace mozilla michael@0: michael@0: #endif /* mozilla_imagelib_FrameSequence_h_ */