1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/image/src/imgFrame.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,275 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef imgFrame_h 1.11 +#define imgFrame_h 1.12 + 1.13 +#include "mozilla/MemoryReporting.h" 1.14 +#include "mozilla/Mutex.h" 1.15 +#include "mozilla/VolatileBuffer.h" 1.16 +#include "nsRect.h" 1.17 +#include "nsPoint.h" 1.18 +#include "nsSize.h" 1.19 +#include "gfxPattern.h" 1.20 +#include "gfxDrawable.h" 1.21 +#include "gfxImageSurface.h" 1.22 +#if defined(XP_WIN) 1.23 +#include "gfxWindowsSurface.h" 1.24 +#elif defined(XP_MACOSX) 1.25 +#include "gfxQuartzImageSurface.h" 1.26 +#endif 1.27 +#include "nsAutoPtr.h" 1.28 +#include "imgIContainer.h" 1.29 +#include "gfxColor.h" 1.30 + 1.31 +/* 1.32 + * This creates a gfxImageSurface which will unlock the buffer on destruction 1.33 + */ 1.34 + 1.35 +class LockedImageSurface 1.36 +{ 1.37 +public: 1.38 + static gfxImageSurface * 1.39 + CreateSurface(mozilla::VolatileBuffer *vbuf, 1.40 + const gfxIntSize& size, 1.41 + gfxImageFormat format); 1.42 + static mozilla::TemporaryRef<mozilla::VolatileBuffer> 1.43 + AllocateBuffer(const gfxIntSize& size, gfxImageFormat format); 1.44 +}; 1.45 + 1.46 +class imgFrame 1.47 +{ 1.48 +public: 1.49 + imgFrame(); 1.50 + ~imgFrame(); 1.51 + 1.52 + nsresult Init(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight, gfxImageFormat aFormat, uint8_t aPaletteDepth = 0); 1.53 + nsresult Optimize(); 1.54 + 1.55 + bool Draw(gfxContext *aContext, GraphicsFilter aFilter, 1.56 + const gfxMatrix &aUserSpaceToImageSpace, const gfxRect& aFill, 1.57 + const nsIntMargin &aPadding, const nsIntRect &aSubimage, 1.58 + uint32_t aImageFlags = imgIContainer::FLAG_NONE); 1.59 + 1.60 + nsresult ImageUpdated(const nsIntRect &aUpdateRect); 1.61 + bool GetIsDirty() const; 1.62 + 1.63 + nsIntRect GetRect() const; 1.64 + gfxImageFormat GetFormat() const; 1.65 + bool GetNeedsBackground() const; 1.66 + uint32_t GetImageBytesPerRow() const; 1.67 + uint32_t GetImageDataLength() const; 1.68 + bool GetIsPaletted() const; 1.69 + bool GetHasAlpha() const; 1.70 + void GetImageData(uint8_t **aData, uint32_t *length) const; 1.71 + uint8_t* GetImageData() const; 1.72 + void GetPaletteData(uint32_t **aPalette, uint32_t *length) const; 1.73 + uint32_t* GetPaletteData() const; 1.74 + 1.75 + int32_t GetRawTimeout() const; 1.76 + void SetRawTimeout(int32_t aTimeout); 1.77 + 1.78 + int32_t GetFrameDisposalMethod() const; 1.79 + void SetFrameDisposalMethod(int32_t aFrameDisposalMethod); 1.80 + int32_t GetBlendMethod() const; 1.81 + void SetBlendMethod(int32_t aBlendMethod); 1.82 + bool ImageComplete() const; 1.83 + 1.84 + void SetHasNoAlpha(); 1.85 + void SetAsNonPremult(bool aIsNonPremult); 1.86 + 1.87 + bool GetCompositingFailed() const; 1.88 + void SetCompositingFailed(bool val); 1.89 + 1.90 + nsresult LockImageData(); 1.91 + nsresult UnlockImageData(); 1.92 + void ApplyDirtToSurfaces(); 1.93 + 1.94 + void SetDiscardable(); 1.95 + 1.96 + nsresult GetSurface(gfxASurface **aSurface) 1.97 + { 1.98 + *aSurface = ThebesSurface(); 1.99 + NS_IF_ADDREF(*aSurface); 1.100 + return NS_OK; 1.101 + } 1.102 + 1.103 + nsresult GetPattern(gfxPattern **aPattern) 1.104 + { 1.105 + if (mSinglePixel) 1.106 + *aPattern = new gfxPattern(mSinglePixelColor); 1.107 + else 1.108 + *aPattern = new gfxPattern(ThebesSurface()); 1.109 + NS_ADDREF(*aPattern); 1.110 + return NS_OK; 1.111 + } 1.112 + 1.113 + bool IsSinglePixel() 1.114 + { 1.115 + return mSinglePixel; 1.116 + } 1.117 + 1.118 + gfxASurface* CachedThebesSurface() 1.119 + { 1.120 + if (mOptSurface) 1.121 + return mOptSurface; 1.122 +#if defined(XP_WIN) 1.123 + if (mWinSurface) 1.124 + return mWinSurface; 1.125 +#elif defined(XP_MACOSX) 1.126 + if (mQuartzSurface) 1.127 + return mQuartzSurface; 1.128 +#endif 1.129 + if (mImageSurface) 1.130 + return mImageSurface; 1.131 + return nullptr; 1.132 + } 1.133 + 1.134 + gfxASurface* ThebesSurface() 1.135 + { 1.136 + gfxASurface *sur = CachedThebesSurface(); 1.137 + if (sur) 1.138 + return sur; 1.139 + if (mVBuf) { 1.140 + mozilla::VolatileBufferPtr<uint8_t> ref(mVBuf); 1.141 + if (ref.WasBufferPurged()) 1.142 + return nullptr; 1.143 + 1.144 + gfxImageSurface *imgSur = 1.145 + LockedImageSurface::CreateSurface(mVBuf, mSize, mFormat); 1.146 +#if defined(XP_MACOSX) 1.147 + // Manually addref and release to make sure the cairo surface isn't lost 1.148 + NS_ADDREF(imgSur); 1.149 + gfxQuartzImageSurface *quartzSur = new gfxQuartzImageSurface(imgSur); 1.150 + // quartzSur does not hold on to the gfxImageSurface 1.151 + NS_RELEASE(imgSur); 1.152 + return quartzSur; 1.153 +#else 1.154 + return imgSur; 1.155 +#endif 1.156 + } 1.157 + // We can return null here if we're single pixel optimized 1.158 + // or a paletted image. However, one has to check for paletted 1.159 + // image data first before attempting to get a surface, so 1.160 + // this is only valid for single pixel optimized images 1.161 + MOZ_ASSERT(mSinglePixel, "No image surface and not a single pixel!"); 1.162 + return nullptr; 1.163 + } 1.164 + 1.165 + size_t SizeOfExcludingThisWithComputedFallbackIfHeap( 1.166 + gfxMemoryLocation aLocation, 1.167 + mozilla::MallocSizeOf aMallocSizeOf) const; 1.168 + 1.169 + uint8_t GetPaletteDepth() const { return mPaletteDepth; } 1.170 + uint32_t PaletteDataLength() const { 1.171 + if (!mPaletteDepth) 1.172 + return 0; 1.173 + 1.174 + return ((1 << mPaletteDepth) * sizeof(uint32_t)); 1.175 + } 1.176 + 1.177 +private: // methods 1.178 + 1.179 + struct SurfaceWithFormat { 1.180 + nsRefPtr<gfxDrawable> mDrawable; 1.181 + gfxImageFormat mFormat; 1.182 + SurfaceWithFormat() {} 1.183 + SurfaceWithFormat(gfxDrawable* aDrawable, gfxImageFormat aFormat) 1.184 + : mDrawable(aDrawable), mFormat(aFormat) {} 1.185 + bool IsValid() { return !!mDrawable; } 1.186 + }; 1.187 + 1.188 + SurfaceWithFormat SurfaceForDrawing(bool aDoPadding, 1.189 + bool aDoPartialDecode, 1.190 + bool aDoTile, 1.191 + const nsIntMargin& aPadding, 1.192 + gfxMatrix& aUserSpaceToImageSpace, 1.193 + gfxRect& aFill, 1.194 + gfxRect& aSubimage, 1.195 + gfxRect& aSourceRect, 1.196 + gfxRect& aImageRect, 1.197 + gfxASurface* aSurface); 1.198 + 1.199 +private: // data 1.200 + nsRefPtr<gfxImageSurface> mImageSurface; 1.201 + nsRefPtr<gfxASurface> mOptSurface; 1.202 +#if defined(XP_WIN) 1.203 + nsRefPtr<gfxWindowsSurface> mWinSurface; 1.204 +#elif defined(XP_MACOSX) 1.205 + nsRefPtr<gfxQuartzImageSurface> mQuartzSurface; 1.206 +#endif 1.207 + 1.208 + nsRefPtr<gfxASurface> mDrawSurface; 1.209 + 1.210 + nsIntSize mSize; 1.211 + nsIntPoint mOffset; 1.212 + 1.213 + nsIntRect mDecoded; 1.214 + 1.215 + mutable mozilla::Mutex mDirtyMutex; 1.216 + 1.217 + // The palette and image data for images that are paletted, since Cairo 1.218 + // doesn't support these images. 1.219 + // The paletted data comes first, then the image data itself. 1.220 + // Total length is PaletteDataLength() + GetImageDataLength(). 1.221 + uint8_t* mPalettedImageData; 1.222 + 1.223 + // Note that the data stored in gfxRGBA is *non-alpha-premultiplied*. 1.224 + gfxRGBA mSinglePixelColor; 1.225 + 1.226 + int32_t mTimeout; // -1 means display forever 1.227 + int32_t mDisposalMethod; 1.228 + 1.229 + /** Indicates how many readers currently have locked this frame */ 1.230 + int32_t mLockCount; 1.231 + 1.232 + mozilla::RefPtr<mozilla::VolatileBuffer> mVBuf; 1.233 + 1.234 + gfxImageFormat mFormat; 1.235 + uint8_t mPaletteDepth; 1.236 + int8_t mBlendMethod; 1.237 + bool mSinglePixel; 1.238 + bool mFormatChanged; 1.239 + bool mCompositingFailed; 1.240 + bool mNonPremult; 1.241 + bool mDiscardable; 1.242 + 1.243 + /** Have we called DiscardTracker::InformAllocation()? */ 1.244 + bool mInformedDiscardTracker; 1.245 + 1.246 + bool mDirty; 1.247 +}; 1.248 + 1.249 +namespace mozilla { 1.250 +namespace image { 1.251 + // An RAII class to ensure it's easy to balance locks and unlocks on 1.252 + // imgFrames. 1.253 + class AutoFrameLocker 1.254 + { 1.255 + public: 1.256 + AutoFrameLocker(imgFrame* frame) 1.257 + : mFrame(frame) 1.258 + , mSucceeded(NS_SUCCEEDED(frame->LockImageData())) 1.259 + {} 1.260 + 1.261 + ~AutoFrameLocker() 1.262 + { 1.263 + if (mSucceeded) { 1.264 + mFrame->UnlockImageData(); 1.265 + } 1.266 + } 1.267 + 1.268 + // Whether the lock request succeeded. 1.269 + bool Succeeded() { return mSucceeded; } 1.270 + 1.271 + private: 1.272 + imgFrame* mFrame; 1.273 + bool mSucceeded; 1.274 + }; 1.275 +} 1.276 +} 1.277 + 1.278 +#endif /* imgFrame_h */