2007-03-22 10:30:00 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
2012-05-21 04:12:37 -07:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2014-04-15 11:02:23 -07:00
|
|
|
// Must #include ImageLogging.h before any IPDL-generated files or other files that #include prlog.h
|
2012-04-03 14:57:22 -07:00
|
|
|
#include "ImageLogging.h"
|
2014-04-15 11:02:23 -07:00
|
|
|
|
|
|
|
#include "RasterImage.h"
|
|
|
|
|
|
|
|
#include "base/histogram.h"
|
|
|
|
#include "gfxPlatform.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsComponentManagerUtils.h"
|
2012-07-27 07:03:27 -07:00
|
|
|
#include "nsError.h"
|
2010-08-22 19:30:46 -07:00
|
|
|
#include "Decoder.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsAutoPtr.h"
|
2007-10-18 17:36:34 -07:00
|
|
|
#include "prenv.h"
|
2013-03-01 15:17:24 -08:00
|
|
|
#include "prsystem.h"
|
2012-08-19 12:33:25 -07:00
|
|
|
#include "ImageContainer.h"
|
2014-08-22 13:12:38 -07:00
|
|
|
#include "ImageRegion.h"
|
2012-08-19 12:33:25 -07:00
|
|
|
#include "Layers.h"
|
2013-01-10 19:38:34 -08:00
|
|
|
#include "nsPresContext.h"
|
2015-01-12 01:20:23 -08:00
|
|
|
#include "SourceBuffer.h"
|
2014-09-19 14:53:29 -07:00
|
|
|
#include "SurfaceCache.h"
|
2013-07-15 11:38:59 -07:00
|
|
|
#include "FrameAnimator.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-08-22 19:30:45 -07:00
|
|
|
#include "nsPNGDecoder.h"
|
|
|
|
#include "nsGIFDecoder2.h"
|
|
|
|
#include "nsJPEGDecoder.h"
|
|
|
|
#include "nsBMPDecoder.h"
|
|
|
|
#include "nsICODecoder.h"
|
|
|
|
#include "nsIconDecoder.h"
|
2013-03-19 23:03:07 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "gfxContext.h"
|
|
|
|
|
2014-04-15 11:02:23 -07:00
|
|
|
#include "mozilla/gfx/2D.h"
|
|
|
|
#include "mozilla/RefPtr.h"
|
2014-09-12 01:12:55 -07:00
|
|
|
#include "mozilla/Move.h"
|
2013-06-23 05:03:39 -07:00
|
|
|
#include "mozilla/MemoryReporting.h"
|
2013-03-01 15:17:24 -08:00
|
|
|
#include "mozilla/Services.h"
|
2013-07-30 07:25:31 -07:00
|
|
|
#include <stdint.h>
|
2012-01-11 00:23:07 -08:00
|
|
|
#include "mozilla/Telemetry.h"
|
|
|
|
#include "mozilla/TimeStamp.h"
|
2012-02-09 12:04:30 -08:00
|
|
|
#include "mozilla/ClearOnShutdown.h"
|
2012-04-03 14:57:22 -07:00
|
|
|
#include "mozilla/gfx/Scale.h"
|
|
|
|
|
2013-03-18 07:25:50 -07:00
|
|
|
#include "GeckoProfiler.h"
|
2013-09-07 06:01:08 -07:00
|
|
|
#include "gfx2DGlue.h"
|
2014-09-22 14:30:20 -07:00
|
|
|
#include "gfxPrefs.h"
|
2013-01-15 04:22:03 -08:00
|
|
|
#include <algorithm>
|
2012-10-03 13:36:26 -07:00
|
|
|
|
2014-07-10 08:00:31 -07:00
|
|
|
namespace mozilla {
|
|
|
|
|
|
|
|
using namespace gfx;
|
|
|
|
using namespace layers;
|
|
|
|
|
|
|
|
namespace image {
|
2014-10-15 13:52:20 -07:00
|
|
|
|
2014-07-28 14:27:39 -07:00
|
|
|
using std::ceil;
|
2014-10-15 13:52:20 -07:00
|
|
|
using std::min;
|
2010-08-13 21:09:49 -07:00
|
|
|
|
2011-01-12 17:45:13 -08:00
|
|
|
// a mask for flags that will affect the decoding
|
|
|
|
#define DECODE_FLAGS_MASK (imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA | imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION)
|
|
|
|
#define DECODE_FLAGS_DEFAULT 0
|
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
static uint32_t
|
|
|
|
DecodeFlags(uint32_t aFlags)
|
|
|
|
{
|
|
|
|
return aFlags & DECODE_FLAGS_MASK;
|
|
|
|
}
|
|
|
|
|
2013-01-03 13:06:08 -08:00
|
|
|
// The maximum number of times any one RasterImage was decoded. This is only
|
|
|
|
// used for statistics.
|
|
|
|
static int32_t sMaxDecodeCount = 0;
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
/* We define our own error checking macros here for 2 reasons:
|
|
|
|
*
|
|
|
|
* 1) Most of the failures we encounter here will (hopefully) be
|
|
|
|
* the result of decoding failures (ie, bad data) and not code
|
|
|
|
* failures. As such, we don't want to clutter up debug consoles
|
|
|
|
* with spurious messages about NS_ENSURE_SUCCESS failures.
|
|
|
|
*
|
|
|
|
* 2) We want to set the internal error flag, shutdown properly,
|
|
|
|
* and end up in an error state.
|
|
|
|
*
|
|
|
|
* So this macro should be called when the desired failure behavior
|
|
|
|
* is to put the container into an error state and return failure.
|
|
|
|
* It goes without saying that macro won't compile outside of a
|
2010-08-13 21:09:49 -07:00
|
|
|
* non-static RasterImage method.
|
2009-09-12 15:44:18 -07:00
|
|
|
*/
|
|
|
|
#define LOG_CONTAINER_ERROR \
|
|
|
|
PR_BEGIN_MACRO \
|
2012-10-29 16:32:10 -07:00
|
|
|
PR_LOG (GetImgLog(), PR_LOG_ERROR, \
|
2010-08-13 21:09:49 -07:00
|
|
|
("RasterImage: [this=%p] Error " \
|
2009-09-12 15:44:18 -07:00
|
|
|
"detected at line %u for image of " \
|
|
|
|
"type %s\n", this, __LINE__, \
|
|
|
|
mSourceDataMimeType.get())); \
|
|
|
|
PR_END_MACRO
|
|
|
|
|
|
|
|
#define CONTAINER_ENSURE_SUCCESS(status) \
|
|
|
|
PR_BEGIN_MACRO \
|
|
|
|
nsresult _status = status; /* eval once */ \
|
2012-08-14 02:10:41 -07:00
|
|
|
if (NS_FAILED(_status)) { \
|
2009-09-12 15:44:18 -07:00
|
|
|
LOG_CONTAINER_ERROR; \
|
|
|
|
DoError(); \
|
|
|
|
return _status; \
|
|
|
|
} \
|
|
|
|
PR_END_MACRO
|
|
|
|
|
|
|
|
#define CONTAINER_ENSURE_TRUE(arg, rv) \
|
|
|
|
PR_BEGIN_MACRO \
|
|
|
|
if (!(arg)) { \
|
|
|
|
LOG_CONTAINER_ERROR; \
|
|
|
|
DoError(); \
|
|
|
|
return rv; \
|
|
|
|
} \
|
|
|
|
PR_END_MACRO
|
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
class ScaleRunner : public nsRunnable
|
2012-10-12 15:24:47 -07:00
|
|
|
{
|
2014-09-19 14:53:29 -07:00
|
|
|
enum ScaleState
|
|
|
|
{
|
|
|
|
eNew,
|
|
|
|
eReady,
|
|
|
|
eFinish,
|
|
|
|
eFinishWithError
|
|
|
|
};
|
|
|
|
|
2013-01-04 19:55:23 -08:00
|
|
|
public:
|
2014-09-19 14:53:29 -07:00
|
|
|
ScaleRunner(RasterImage* aImage,
|
|
|
|
uint32_t aImageFlags,
|
|
|
|
const nsIntSize& aSize,
|
|
|
|
RawAccessFrameRef&& aSrcRef)
|
|
|
|
: mImage(aImage)
|
|
|
|
, mSrcRef(Move(aSrcRef))
|
|
|
|
, mDstSize(aSize)
|
|
|
|
, mImageFlags(aImageFlags)
|
|
|
|
, mState(eNew)
|
2012-10-12 15:24:47 -07:00
|
|
|
{
|
2014-09-19 14:53:29 -07:00
|
|
|
MOZ_ASSERT(!mSrcRef->GetIsPaletted());
|
2014-08-22 13:12:38 -07:00
|
|
|
MOZ_ASSERT(aSize.width > 0 && aSize.height > 0);
|
2012-10-12 15:24:47 -07:00
|
|
|
}
|
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
bool Init()
|
2012-10-12 15:24:47 -07:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2014-09-19 14:53:29 -07:00
|
|
|
MOZ_ASSERT(mState == eNew, "Calling Init() twice?");
|
2012-10-12 15:24:47 -07:00
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
// We'll need a destination frame. It's unconditionally ARGB32 because
|
|
|
|
// that's what the scaler outputs.
|
|
|
|
nsRefPtr<imgFrame> tentativeDstFrame = new imgFrame();
|
|
|
|
nsresult rv =
|
|
|
|
tentativeDstFrame->InitForDecoder(mDstSize, SurfaceFormat::B8G8R8A8);
|
|
|
|
if (NS_FAILED(rv)) {
|
2012-10-12 15:24:47 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
// We need a strong reference to the raw data for the destination frame.
|
|
|
|
// (We already got one for the source frame in the constructor.)
|
|
|
|
RawAccessFrameRef tentativeDstRef = tentativeDstFrame->RawAccessRef();
|
|
|
|
if (!tentativeDstRef) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-09-12 01:12:55 -07:00
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
// Everything worked, so commit to these objects and mark ourselves ready.
|
|
|
|
mDstRef = Move(tentativeDstRef);
|
|
|
|
mState = eReady;
|
2014-09-16 22:30:11 -07:00
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
// Insert the new surface into the cache immediately. We need to do this so
|
|
|
|
// that we won't start multiple scaling jobs for the same size.
|
|
|
|
SurfaceCache::Insert(mDstRef.get(), ImageKey(mImage.get()),
|
2015-01-07 01:40:23 -08:00
|
|
|
RasterSurfaceKey(mDstSize.ToIntSize(), mImageFlags, 0),
|
2014-11-26 13:22:10 -08:00
|
|
|
Lifetime::Transient);
|
2012-10-12 15:24:47 -07:00
|
|
|
|
2014-09-12 01:12:55 -07:00
|
|
|
return true;
|
2012-10-12 15:24:47 -07:00
|
|
|
}
|
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
NS_IMETHOD Run() MOZ_OVERRIDE
|
2012-10-12 15:24:47 -07:00
|
|
|
{
|
2014-09-19 14:53:29 -07:00
|
|
|
if (mState == eReady) {
|
|
|
|
// Collect information from the frames that we need to scale.
|
2015-01-08 00:04:31 -08:00
|
|
|
ScalingData srcData = mSrcRef->GetScalingData();
|
|
|
|
ScalingData dstData = mDstRef->GetScalingData();
|
2014-09-16 22:30:11 -07:00
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
// Actually do the scaling.
|
|
|
|
bool succeeded =
|
2015-01-08 00:04:31 -08:00
|
|
|
gfx::Scale(srcData.mRawData, srcData.mSize.width, srcData.mSize.height,
|
|
|
|
srcData.mBytesPerRow, dstData.mRawData, mDstSize.width,
|
|
|
|
mDstSize.height, dstData.mBytesPerRow, srcData.mFormat);
|
2014-09-16 22:30:11 -07:00
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
if (succeeded) {
|
|
|
|
// Mark the frame as complete and discardable.
|
|
|
|
mDstRef->ImageUpdated(mDstRef->GetRect());
|
2015-01-11 19:28:02 -08:00
|
|
|
MOZ_ASSERT(mDstRef->IsImageComplete(),
|
2014-09-19 14:53:29 -07:00
|
|
|
"Incomplete, but just updated the entire frame");
|
|
|
|
}
|
2014-09-16 22:30:11 -07:00
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
// We need to send notifications and release our references on the main
|
|
|
|
// thread, so finish up there.
|
|
|
|
mState = succeeded ? eFinish : eFinishWithError;
|
|
|
|
NS_DispatchToMainThread(this);
|
|
|
|
} else if (mState == eFinish) {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(mDstRef, "Should have a valid scaled frame");
|
|
|
|
|
|
|
|
// Notify, so observers can redraw.
|
|
|
|
nsRefPtr<RasterImage> image = mImage.get();
|
|
|
|
if (image) {
|
|
|
|
image->NotifyNewScaledFrame();
|
2012-10-12 15:24:47 -07:00
|
|
|
}
|
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
// We're done, so release everything.
|
|
|
|
mSrcRef.reset();
|
|
|
|
mDstRef.reset();
|
|
|
|
} else if (mState == eFinishWithError) {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
NS_WARNING("HQ scaling failed");
|
|
|
|
|
|
|
|
// Remove the frame from the cache since we know we don't need it.
|
2014-11-26 13:22:10 -08:00
|
|
|
SurfaceCache::RemoveSurface(ImageKey(mImage.get()),
|
|
|
|
RasterSurfaceKey(mDstSize.ToIntSize(),
|
2015-01-07 01:40:23 -08:00
|
|
|
mImageFlags, 0));
|
2014-09-19 14:53:29 -07:00
|
|
|
|
|
|
|
// Release everything we're holding, too.
|
|
|
|
mSrcRef.reset();
|
|
|
|
mDstRef.reset();
|
|
|
|
} else {
|
|
|
|
// mState must be eNew, which is invalid in Run().
|
|
|
|
MOZ_ASSERT(false, "Need to call Init() before dispatching");
|
2014-09-14 23:17:28 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
private:
|
|
|
|
virtual ~ScaleRunner()
|
2014-09-16 22:30:11 -07:00
|
|
|
{
|
2014-09-19 14:53:29 -07:00
|
|
|
MOZ_ASSERT(!mSrcRef && !mDstRef,
|
|
|
|
"Should have released strong refs in Run()");
|
2012-10-12 15:24:47 -07:00
|
|
|
}
|
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
WeakPtr<RasterImage> mImage;
|
|
|
|
RawAccessFrameRef mSrcRef;
|
|
|
|
RawAccessFrameRef mDstRef;
|
|
|
|
const nsIntSize mDstSize;
|
|
|
|
uint32_t mImageFlags;
|
|
|
|
ScaleState mState;
|
2012-10-12 15:24:47 -07:00
|
|
|
};
|
|
|
|
|
2012-04-03 14:57:22 -07:00
|
|
|
static nsCOMPtr<nsIThread> sScaleWorkerThread = nullptr;
|
|
|
|
|
2010-09-07 17:34:18 -07:00
|
|
|
#ifndef DEBUG
|
2014-04-27 00:06:00 -07:00
|
|
|
NS_IMPL_ISUPPORTS(RasterImage, imgIContainer, nsIProperties)
|
2010-09-07 17:34:18 -07:00
|
|
|
#else
|
2014-04-27 00:06:00 -07:00
|
|
|
NS_IMPL_ISUPPORTS(RasterImage, imgIContainer, nsIProperties,
|
|
|
|
imgIContainerDebug)
|
2010-09-07 17:34:18 -07:00
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
//******************************************************************************
|
2014-11-14 20:10:47 -08:00
|
|
|
RasterImage::RasterImage(ProgressTracker* aProgressTracker,
|
2013-09-28 11:28:42 -07:00
|
|
|
ImageURL* aURI /* = nullptr */) :
|
2013-09-28 11:28:44 -07:00
|
|
|
ImageResource(aURI), // invoke superclass's constructor
|
2007-03-22 10:30:00 -07:00
|
|
|
mSize(0,0),
|
2010-05-12 14:41:47 -07:00
|
|
|
mLockCount(0),
|
2011-09-08 11:05:11 -07:00
|
|
|
mDecodeCount(0),
|
2014-02-28 13:43:14 -08:00
|
|
|
mRequestedSampleSize(0),
|
2010-09-07 17:34:18 -07:00
|
|
|
#ifdef DEBUG
|
|
|
|
mFramesNotified(0),
|
|
|
|
#endif
|
2015-01-12 01:20:23 -08:00
|
|
|
mSourceBuffer(new SourceBuffer()),
|
2015-01-07 01:40:23 -08:00
|
|
|
mFrameCount(0),
|
2014-11-14 20:10:47 -08:00
|
|
|
mNotifyProgress(NoProgress),
|
2013-11-26 17:22:44 -08:00
|
|
|
mNotifying(false),
|
2011-10-17 07:59:28 -07:00
|
|
|
mHasSize(false),
|
|
|
|
mDecodeOnDraw(false),
|
2015-01-07 01:37:20 -08:00
|
|
|
mTransient(false),
|
2011-10-17 07:59:28 -07:00
|
|
|
mDiscardable(false),
|
|
|
|
mHasSourceData(false),
|
|
|
|
mHasBeenDecoded(false),
|
2014-11-26 13:22:10 -08:00
|
|
|
mPendingAnimation(false),
|
2012-09-17 18:53:37 -07:00
|
|
|
mAnimationFinished(false),
|
2015-01-12 01:20:23 -08:00
|
|
|
mWantFullDecode(false)
|
2009-09-12 15:44:18 -07:00
|
|
|
{
|
2014-11-14 20:10:47 -08:00
|
|
|
mProgressTrackerInit = new ProgressTrackerInit(this, aProgressTracker);
|
2013-09-28 11:28:44 -07:00
|
|
|
|
2011-09-08 11:05:11 -07:00
|
|
|
Telemetry::GetHistogramById(Telemetry::IMAGE_DECODE_COUNT)->Add(0);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::~RasterImage()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2015-01-12 01:20:23 -08:00
|
|
|
// Make sure our SourceBuffer is marked as complete. This will ensure that any
|
|
|
|
// outstanding decoders terminate.
|
|
|
|
if (!mSourceBuffer->IsComplete()) {
|
|
|
|
mSourceBuffer->Complete(NS_ERROR_ABORT);
|
2009-09-12 15:44:18 -07:00
|
|
|
}
|
|
|
|
|
2014-11-26 13:22:10 -08:00
|
|
|
// Release all frames from the surface cache.
|
2014-11-26 13:22:10 -08:00
|
|
|
SurfaceCache::RemoveImage(ImageKey(this));
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2013-02-13 14:03:37 -08:00
|
|
|
/* static */ void
|
2012-09-26 08:33:06 -07:00
|
|
|
RasterImage::Initialize()
|
|
|
|
{
|
|
|
|
// Create our singletons now, so we don't have to worry about what thread
|
|
|
|
// they're created on.
|
2013-03-01 15:17:24 -08:00
|
|
|
DecodePool::Singleton();
|
2012-09-26 08:33:06 -07:00
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2013-02-12 19:00:03 -08:00
|
|
|
RasterImage::Init(const char* aMimeType,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aFlags)
|
2009-09-12 15:44:18 -07:00
|
|
|
{
|
|
|
|
// We don't support re-initialization
|
|
|
|
if (mInitialized)
|
|
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
|
|
|
|
|
|
// Not sure an error can happen before init, but be safe
|
|
|
|
if (mError)
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aMimeType);
|
|
|
|
|
|
|
|
// We must be non-discardable and non-decode-on-draw for
|
2015-01-07 01:37:20 -08:00
|
|
|
// transient images.
|
|
|
|
MOZ_ASSERT(!(aFlags & INIT_FLAG_TRANSIENT) ||
|
|
|
|
(!(aFlags & INIT_FLAG_DISCARDABLE) &&
|
2015-01-12 03:24:25 -08:00
|
|
|
!(aFlags & INIT_FLAG_DECODE_ON_DRAW),
|
|
|
|
!(aFlags & INIT_FLAG_DOWNSCALE_DURING_DECODE)),
|
|
|
|
"Illegal init flags for transient image");
|
2008-01-19 00:10:26 -08:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Store initialization data
|
|
|
|
mSourceDataMimeType.Assign(aMimeType);
|
2010-05-25 15:27:29 -07:00
|
|
|
mDiscardable = !!(aFlags & INIT_FLAG_DISCARDABLE);
|
|
|
|
mDecodeOnDraw = !!(aFlags & INIT_FLAG_DECODE_ON_DRAW);
|
2015-01-07 01:37:20 -08:00
|
|
|
mTransient = !!(aFlags & INIT_FLAG_TRANSIENT);
|
2015-01-12 03:24:25 -08:00
|
|
|
mDownscaleDuringDecode = !!(aFlags & INIT_FLAG_DOWNSCALE_DURING_DECODE);
|
|
|
|
|
|
|
|
#ifndef MOZ_ENABLE_SKIA
|
|
|
|
// Downscale-during-decode requires Skia.
|
|
|
|
mDownscaleDuringDecode = false;
|
|
|
|
#endif
|
2009-09-12 15:44:18 -07:00
|
|
|
|
2014-11-26 13:22:10 -08:00
|
|
|
// Lock this image's surfaces in the SurfaceCache if we're not discardable.
|
|
|
|
if (!mDiscardable) {
|
|
|
|
SurfaceCache::LockImage(ImageKey(this));
|
|
|
|
}
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// Create the initial size decoder.
|
|
|
|
nsresult rv = Decode(DecodeStrategy::ASYNC, DECODE_FLAGS_DEFAULT,
|
|
|
|
/* aDoSizeDecode = */ true);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
2013-02-01 11:36:39 -08:00
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Mark us as initialized
|
2011-10-17 07:59:28 -07:00
|
|
|
mInitialized = true;
|
2009-09-12 15:44:18 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-11-09 13:39:15 -08:00
|
|
|
//******************************************************************************
|
2011-11-09 13:39:16 -08:00
|
|
|
// [notxpcom] void requestRefresh ([const] in TimeStamp aTime);
|
2011-11-09 13:39:15 -08:00
|
|
|
NS_IMETHODIMP_(void)
|
2014-06-16 15:25:43 -07:00
|
|
|
RasterImage::RequestRefresh(const TimeStamp& aTime)
|
2011-11-09 13:39:15 -08:00
|
|
|
{
|
2014-05-08 11:37:39 -07:00
|
|
|
if (HadRecentRefresh(aTime)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-09-03 13:20:15 -07:00
|
|
|
EvaluateAnimation();
|
|
|
|
|
|
|
|
if (!mAnimating) {
|
2011-11-09 13:39:16 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-07-15 11:38:59 -07:00
|
|
|
FrameAnimator::RefreshResult res;
|
|
|
|
if (mAnim) {
|
|
|
|
res = mAnim->RequestRefresh(aTime);
|
2011-11-09 13:39:16 -08:00
|
|
|
}
|
|
|
|
|
2013-07-15 11:38:59 -07:00
|
|
|
if (res.frameAdvanced) {
|
2011-11-09 13:39:16 -08:00
|
|
|
// Notify listeners that our frame has actually changed, but do this only
|
|
|
|
// once for all frames that we've now passed (if AdvanceFrame() was called
|
|
|
|
// more than once).
|
|
|
|
#ifdef DEBUG
|
|
|
|
mFramesNotified++;
|
|
|
|
#endif
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
NotifyProgress(NoProgress, res.dirtyRect);
|
2013-07-15 11:38:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (res.animationFinished) {
|
|
|
|
mAnimationFinished = true;
|
|
|
|
EvaluateAnimation();
|
2011-11-09 13:39:16 -08:00
|
|
|
}
|
2011-11-09 13:39:15 -08:00
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
//******************************************************************************
|
2012-08-22 08:56:38 -07:00
|
|
|
/* readonly attribute int32_t width; */
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
RasterImage::GetWidth(int32_t *aWidth)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-03-19 22:54:30 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aWidth);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-10-06 15:18:52 -07:00
|
|
|
if (mError) {
|
|
|
|
*aWidth = 0;
|
2009-09-12 15:44:18 -07:00
|
|
|
return NS_ERROR_FAILURE;
|
2010-10-06 15:18:52 -07:00
|
|
|
}
|
2009-09-12 15:44:18 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
*aWidth = mSize.width;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
2012-08-22 08:56:38 -07:00
|
|
|
/* readonly attribute int32_t height; */
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
RasterImage::GetHeight(int32_t *aHeight)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-03-19 22:54:30 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aHeight);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-10-06 15:18:52 -07:00
|
|
|
if (mError) {
|
|
|
|
*aHeight = 0;
|
2009-09-12 15:44:18 -07:00
|
|
|
return NS_ERROR_FAILURE;
|
2010-10-06 15:18:52 -07:00
|
|
|
}
|
2009-09-12 15:44:18 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
*aHeight = mSize.height;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2013-03-01 15:17:24 -08:00
|
|
|
|
2013-01-10 19:38:34 -08:00
|
|
|
//******************************************************************************
|
|
|
|
/* [noscript] readonly attribute nsSize intrinsicSize; */
|
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::GetIntrinsicSize(nsSize* aSize)
|
|
|
|
{
|
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
*aSize = nsSize(nsPresContext::CSSPixelsToAppUnits(mSize.width),
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(mSize.height));
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
/* [noscript] readonly attribute nsSize intrinsicRatio; */
|
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::GetIntrinsicRatio(nsSize* aRatio)
|
|
|
|
{
|
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
*aRatio = nsSize(mSize.width, mSize.height);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2013-08-25 00:19:42 -07:00
|
|
|
NS_IMETHODIMP_(Orientation)
|
|
|
|
RasterImage::GetOrientation()
|
|
|
|
{
|
|
|
|
return mOrientation;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
//******************************************************************************
|
|
|
|
/* unsigned short GetType(); */
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
RasterImage::GetType(uint16_t *aType)
|
2010-08-13 21:09:49 -07:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aType);
|
|
|
|
|
2010-12-07 10:40:28 -08:00
|
|
|
*aType = GetType();
|
2010-08-13 21:09:49 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-12-07 10:40:28 -08:00
|
|
|
//******************************************************************************
|
2012-08-22 08:56:38 -07:00
|
|
|
/* [noscript, notxpcom] uint16_t GetType(); */
|
|
|
|
NS_IMETHODIMP_(uint16_t)
|
2010-12-07 10:40:28 -08:00
|
|
|
RasterImage::GetType()
|
|
|
|
{
|
|
|
|
return imgIContainer::TYPE_RASTER;
|
|
|
|
}
|
|
|
|
|
2014-11-26 13:22:10 -08:00
|
|
|
DrawableFrameRef
|
|
|
|
RasterImage::LookupFrameInternal(uint32_t aFrameNum,
|
|
|
|
const nsIntSize& aSize,
|
|
|
|
uint32_t aFlags)
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2015-01-07 01:40:23 -08:00
|
|
|
if (!mAnim) {
|
|
|
|
NS_ASSERTION(aFrameNum == 0,
|
|
|
|
"Don't ask for a frame > 0 if we're not animated!");
|
|
|
|
aFrameNum = 0;
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
}
|
2014-11-26 13:22:10 -08:00
|
|
|
|
2015-01-07 01:40:23 -08:00
|
|
|
if (mAnim && aFrameNum > 0) {
|
|
|
|
MOZ_ASSERT(DecodeFlags(aFlags) == DECODE_FLAGS_DEFAULT,
|
|
|
|
"Can't composite frames with non-default decode flags");
|
2015-01-07 13:07:23 -08:00
|
|
|
return mAnim->GetCompositedFrame(aFrameNum);
|
2015-01-07 01:40:23 -08:00
|
|
|
}
|
2014-11-26 13:22:10 -08:00
|
|
|
|
|
|
|
return SurfaceCache::Lookup(ImageKey(this),
|
|
|
|
RasterSurfaceKey(aSize.ToIntSize(),
|
2015-01-07 01:40:23 -08:00
|
|
|
DecodeFlags(aFlags),
|
|
|
|
aFrameNum));
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
}
|
|
|
|
|
2014-09-12 18:29:27 -07:00
|
|
|
DrawableFrameRef
|
2014-09-26 18:50:24 -07:00
|
|
|
RasterImage::LookupFrame(uint32_t aFrameNum,
|
2014-11-26 13:22:10 -08:00
|
|
|
const nsIntSize& aSize,
|
2014-09-26 18:50:24 -07:00
|
|
|
uint32_t aFlags,
|
|
|
|
bool aShouldSyncNotify /* = true */)
|
2011-07-21 11:14:41 -07:00
|
|
|
{
|
2014-11-26 13:22:10 -08:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
DrawableFrameRef ref = LookupFrameInternal(aFrameNum, aSize, aFlags);
|
2014-09-12 18:29:27 -07:00
|
|
|
|
2015-01-07 01:40:23 -08:00
|
|
|
if (!ref && IsOpaque() && aFrameNum == 0) {
|
2014-11-27 19:56:00 -08:00
|
|
|
// We can use non-premultiplied alpha frames when premultipled alpha is
|
|
|
|
// requested, or vice versa, if this image is opaque. Try again with the bit
|
|
|
|
// toggled.
|
|
|
|
ref = LookupFrameInternal(aFrameNum, aSize,
|
|
|
|
aFlags ^ FLAG_DECODE_NO_PREMULTIPLY_ALPHA);
|
|
|
|
}
|
|
|
|
|
2014-09-12 18:29:27 -07:00
|
|
|
if (!ref) {
|
2014-11-27 19:56:00 -08:00
|
|
|
// The OS threw this frame away. We need to redecode if we can.
|
2014-09-12 18:29:27 -07:00
|
|
|
MOZ_ASSERT(!mAnim, "Animated frames should be locked");
|
2014-09-26 18:50:24 -07:00
|
|
|
|
2014-11-27 19:56:00 -08:00
|
|
|
WantDecodedFrames(aFlags, aShouldSyncNotify);
|
|
|
|
|
2015-01-11 19:28:02 -08:00
|
|
|
// If we were able to sync decode, we should already have the frame. If we
|
|
|
|
// had to decode asynchronously, maybe we've gotten lucky.
|
2014-11-27 19:56:00 -08:00
|
|
|
ref = LookupFrameInternal(aFrameNum, aSize, aFlags);
|
2014-09-26 18:50:24 -07:00
|
|
|
|
|
|
|
if (!ref) {
|
|
|
|
// We didn't successfully redecode, so just fail.
|
|
|
|
return DrawableFrameRef();
|
2014-09-24 14:26:13 -07:00
|
|
|
}
|
2013-04-04 15:05:19 -07:00
|
|
|
}
|
2009-11-12 15:18:40 -08:00
|
|
|
|
2014-09-12 18:29:27 -07:00
|
|
|
if (ref->GetCompositingFailed()) {
|
|
|
|
return DrawableFrameRef();
|
|
|
|
}
|
2013-07-26 07:41:57 -07:00
|
|
|
|
2015-01-07 01:40:23 -08:00
|
|
|
MOZ_ASSERT(!ref || !ref->GetIsPaletted(), "Should not have paletted frame");
|
|
|
|
|
2015-01-11 19:28:02 -08:00
|
|
|
// Sync decoding guarantees that we got the frame, but if it's owned by an
|
|
|
|
// async decoder that's currently running, the contents of the frame may not
|
|
|
|
// be available yet. Make sure we get everything.
|
|
|
|
if (ref && mHasSourceData && aShouldSyncNotify &&
|
|
|
|
(aFlags & FLAG_SYNC_DECODE)) {
|
|
|
|
ref->WaitUntilComplete();
|
|
|
|
}
|
|
|
|
|
2014-09-12 18:29:27 -07:00
|
|
|
return ref;
|
2009-11-12 15:18:40 -08:00
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t
|
2014-09-12 18:29:27 -07:00
|
|
|
RasterImage::GetCurrentFrameIndex() const
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2014-09-12 18:29:27 -07:00
|
|
|
if (mAnim) {
|
2013-07-15 11:38:59 -07:00
|
|
|
return mAnim->GetCurrentAnimationFrameIndex();
|
2014-09-12 18:29:27 -07:00
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-12 18:29:27 -07:00
|
|
|
uint32_t
|
|
|
|
RasterImage::GetRequestedFrameIndex(uint32_t aWhichFrame) const
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2014-09-12 18:29:27 -07:00
|
|
|
return aWhichFrame == FRAME_FIRST ? 0 : GetCurrentFrameIndex();
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2014-11-10 12:37:35 -08:00
|
|
|
nsIntRect
|
|
|
|
RasterImage::GetFirstFrameRect()
|
|
|
|
{
|
|
|
|
if (mAnim) {
|
|
|
|
return mAnim->GetFirstFrameRefreshArea();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fall back to our size. This is implicitly zero-size if !mHasSize.
|
|
|
|
return nsIntRect(nsIntPoint(0,0), mSize);
|
|
|
|
}
|
|
|
|
|
2013-02-04 14:22:30 -08:00
|
|
|
NS_IMETHODIMP_(bool)
|
2014-11-24 23:42:43 -08:00
|
|
|
RasterImage::IsOpaque()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2014-11-24 23:42:43 -08:00
|
|
|
if (mError) {
|
2013-02-04 14:22:30 -08:00
|
|
|
return false;
|
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2014-11-24 23:42:43 -08:00
|
|
|
Progress progress = mProgressTracker->GetProgress();
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2014-11-24 23:42:43 -08:00
|
|
|
// If we haven't yet finished decoding, the safe answer is "not opaque".
|
|
|
|
if (!(progress & FLAG_DECODE_COMPLETE)) {
|
2013-02-04 14:22:30 -08:00
|
|
|
return false;
|
2014-11-24 23:42:43 -08:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2014-11-24 23:42:43 -08:00
|
|
|
// Other, we're opaque if FLAG_HAS_TRANSPARENCY is not set.
|
|
|
|
return !(progress & FLAG_HAS_TRANSPARENCY);
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
}
|
|
|
|
|
2014-11-27 19:55:57 -08:00
|
|
|
void
|
|
|
|
RasterImage::OnSurfaceDiscarded()
|
|
|
|
{
|
2015-01-08 00:04:31 -08:00
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
nsCOMPtr<nsIRunnable> runnable =
|
|
|
|
NS_NewRunnableMethod(this, &RasterImage::OnSurfaceDiscarded);
|
|
|
|
NS_DispatchToMainThread(runnable);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-11-27 19:55:57 -08:00
|
|
|
if (mProgressTracker) {
|
|
|
|
mProgressTracker->OnDiscard();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
//******************************************************************************
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
/* readonly attribute boolean animated; */
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
2011-09-28 23:19:26 -07:00
|
|
|
RasterImage::GetAnimated(bool *aAnimated)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aAnimated);
|
|
|
|
|
2009-10-06 21:39:30 -07:00
|
|
|
// If we have mAnim, we can know for sure
|
|
|
|
if (mAnim) {
|
2011-10-17 07:59:28 -07:00
|
|
|
*aAnimated = true;
|
2009-10-06 21:39:30 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we need to have been decoded to know for sure, since if we were
|
|
|
|
// decoded at least once mAnim would have been created for animated images
|
|
|
|
if (!mHasBeenDecoded)
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
|
|
|
// We know for sure
|
2011-10-17 07:59:28 -07:00
|
|
|
*aAnimated = false;
|
2009-10-06 21:39:30 -07:00
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-05-17 10:42:20 -07:00
|
|
|
//******************************************************************************
|
|
|
|
/* [notxpcom] int32_t getFirstFrameDelay (); */
|
|
|
|
NS_IMETHODIMP_(int32_t)
|
|
|
|
RasterImage::GetFirstFrameDelay()
|
|
|
|
{
|
|
|
|
if (mError)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
bool animated = false;
|
|
|
|
if (NS_FAILED(GetAnimated(&animated)) || !animated)
|
|
|
|
return -1;
|
|
|
|
|
2015-01-07 13:07:23 -08:00
|
|
|
MOZ_ASSERT(mAnim, "Animated images should have a FrameAnimator");
|
|
|
|
return mAnim->GetTimeoutForFrame(0);
|
2013-05-17 10:42:20 -07:00
|
|
|
}
|
|
|
|
|
2014-04-19 18:28:38 -07:00
|
|
|
TemporaryRef<SourceSurface>
|
2012-08-22 08:56:38 -07:00
|
|
|
RasterImage::CopyFrame(uint32_t aWhichFrame,
|
2014-09-26 18:50:24 -07:00
|
|
|
uint32_t aFlags,
|
|
|
|
bool aShouldSyncNotify /* = true */)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (aWhichFrame > FRAME_MAX_VALUE)
|
2014-04-19 18:28:38 -07:00
|
|
|
return nullptr;
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
if (mError)
|
2014-04-19 18:28:38 -07:00
|
|
|
return nullptr;
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
// Get the frame. If it's not there, it's probably the caller's fault for
|
|
|
|
// not waiting for the data to be loaded from the network or not passing
|
|
|
|
// FLAG_SYNC_DECODE
|
2014-09-26 18:50:24 -07:00
|
|
|
DrawableFrameRef frameRef = LookupFrame(GetRequestedFrameIndex(aWhichFrame),
|
2014-11-26 13:22:10 -08:00
|
|
|
mSize, aFlags, aShouldSyncNotify);
|
2014-09-12 18:29:27 -07:00
|
|
|
if (!frameRef) {
|
2014-09-26 18:50:24 -07:00
|
|
|
// The OS threw this frame away and we couldn't redecode it right now.
|
2014-04-19 18:28:38 -07:00
|
|
|
return nullptr;
|
2009-09-12 15:44:18 -07:00
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
|
|
|
// Create a 32-bit image surface of our size, but draw using the frame's
|
|
|
|
// rect, implicitly padding the frame out to the image's size.
|
2014-04-19 18:28:38 -07:00
|
|
|
|
|
|
|
IntSize size(mSize.width, mSize.height);
|
|
|
|
RefPtr<DataSourceSurface> surf =
|
2014-09-10 14:54:16 -07:00
|
|
|
Factory::CreateDataSourceSurface(size,
|
|
|
|
SurfaceFormat::B8G8R8A8,
|
|
|
|
/* aZero = */ true);
|
2014-08-27 08:57:43 -07:00
|
|
|
if (NS_WARN_IF(!surf)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2014-04-19 18:28:38 -07:00
|
|
|
|
|
|
|
DataSourceSurface::MappedSurface mapping;
|
|
|
|
DebugOnly<bool> success =
|
|
|
|
surf->Map(DataSourceSurface::MapType::WRITE, &mapping);
|
|
|
|
NS_ASSERTION(success, "Failed to map surface");
|
|
|
|
RefPtr<DrawTarget> target =
|
|
|
|
Factory::CreateDrawTargetForData(BackendType::CAIRO,
|
|
|
|
mapping.mData,
|
|
|
|
size,
|
|
|
|
mapping.mStride,
|
|
|
|
SurfaceFormat::B8G8R8A8);
|
|
|
|
|
2014-09-12 18:29:27 -07:00
|
|
|
nsIntRect intFrameRect = frameRef->GetRect();
|
|
|
|
Rect rect(intFrameRect.x, intFrameRect.y,
|
|
|
|
intFrameRect.width, intFrameRect.height);
|
|
|
|
if (frameRef->IsSinglePixel()) {
|
|
|
|
target->FillRect(rect, ColorPattern(frameRef->SinglePixelColor()),
|
2014-04-19 18:28:38 -07:00
|
|
|
DrawOptions(1.0f, CompositionOp::OP_SOURCE));
|
|
|
|
} else {
|
2014-09-12 18:29:27 -07:00
|
|
|
RefPtr<SourceSurface> srcSurf = frameRef->GetSurface();
|
|
|
|
Rect srcRect(0, 0, intFrameRect.width, intFrameRect.height);
|
|
|
|
target->DrawSurface(srcSurf, srcRect, rect);
|
2014-04-19 18:28:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
target->Flush();
|
|
|
|
surf->Unmap();
|
|
|
|
|
|
|
|
return surf;
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
//******************************************************************************
|
2014-04-15 11:02:23 -07:00
|
|
|
/* [noscript] SourceSurface getFrame(in uint32_t aWhichFrame,
|
|
|
|
* in uint32_t aFlags); */
|
|
|
|
NS_IMETHODIMP_(TemporaryRef<SourceSurface>)
|
2012-08-22 08:56:38 -07:00
|
|
|
RasterImage::GetFrame(uint32_t aWhichFrame,
|
2013-12-13 00:34:24 -08:00
|
|
|
uint32_t aFlags)
|
2014-09-26 18:50:24 -07:00
|
|
|
{
|
|
|
|
return GetFrameInternal(aWhichFrame, aFlags);
|
|
|
|
}
|
|
|
|
|
|
|
|
TemporaryRef<SourceSurface>
|
|
|
|
RasterImage::GetFrameInternal(uint32_t aWhichFrame,
|
|
|
|
uint32_t aFlags,
|
|
|
|
bool aShouldSyncNotify /* = true */)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2013-12-13 00:34:24 -08:00
|
|
|
MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE);
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
if (aWhichFrame > FRAME_MAX_VALUE)
|
2013-12-13 00:34:24 -08:00
|
|
|
return nullptr;
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
if (mError)
|
2013-12-13 00:34:24 -08:00
|
|
|
return nullptr;
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Get the frame. If it's not there, it's probably the caller's fault for
|
|
|
|
// not waiting for the data to be loaded from the network or not passing
|
|
|
|
// FLAG_SYNC_DECODE
|
2014-09-26 18:50:24 -07:00
|
|
|
DrawableFrameRef frameRef = LookupFrame(GetRequestedFrameIndex(aWhichFrame),
|
2014-11-26 13:22:10 -08:00
|
|
|
mSize, aFlags, aShouldSyncNotify);
|
2014-09-12 18:29:27 -07:00
|
|
|
if (!frameRef) {
|
2014-09-26 18:50:24 -07:00
|
|
|
// The OS threw this frame away and we couldn't redecode it.
|
2013-12-13 00:34:24 -08:00
|
|
|
return nullptr;
|
2009-09-12 15:44:18 -07:00
|
|
|
}
|
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
// If this frame covers the entire image, we can just reuse its existing
|
|
|
|
// surface.
|
2014-09-12 18:29:27 -07:00
|
|
|
RefPtr<SourceSurface> frameSurf;
|
|
|
|
nsIntRect frameRect = frameRef->GetRect();
|
|
|
|
if (frameRect.x == 0 && frameRect.y == 0 &&
|
|
|
|
frameRect.width == mSize.width &&
|
|
|
|
frameRect.height == mSize.height) {
|
|
|
|
frameSurf = frameRef->GetSurface();
|
2014-02-24 19:37:51 -08:00
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2014-09-12 18:29:27 -07:00
|
|
|
// The image doesn't have a usable surface because it's been optimized away or
|
|
|
|
// because it's a partial update frame from an animation. Create one.
|
|
|
|
if (!frameSurf) {
|
2014-09-26 18:50:24 -07:00
|
|
|
frameSurf = CopyFrame(aWhichFrame, aFlags, aShouldSyncNotify);
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
}
|
|
|
|
|
2014-09-12 18:29:27 -07:00
|
|
|
return frameSurf;
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
}
|
|
|
|
|
2012-09-24 13:31:30 -07:00
|
|
|
already_AddRefed<layers::Image>
|
|
|
|
RasterImage::GetCurrentImage()
|
2011-11-08 19:14:41 -08:00
|
|
|
{
|
2014-09-26 18:50:24 -07:00
|
|
|
RefPtr<SourceSurface> surface =
|
|
|
|
GetFrameInternal(FRAME_CURRENT, FLAG_NONE, /* aShouldSyncNotify = */ false);
|
2014-04-15 11:02:23 -07:00
|
|
|
if (!surface) {
|
2014-09-26 18:50:24 -07:00
|
|
|
// The OS threw out some or all of our buffer. We'll need to wait for the
|
|
|
|
// redecode (which was automatically triggered by GetFrame) to complete.
|
2014-02-24 19:37:51 -08:00
|
|
|
return nullptr;
|
|
|
|
}
|
2012-11-16 10:04:29 -08:00
|
|
|
|
2012-10-01 21:01:25 -07:00
|
|
|
if (!mImageContainer) {
|
|
|
|
mImageContainer = LayerManager::CreateImageContainer();
|
|
|
|
}
|
|
|
|
|
2012-09-24 13:31:30 -07:00
|
|
|
CairoImage::Data cairoData;
|
2011-11-08 19:14:41 -08:00
|
|
|
GetWidth(&cairoData.mSize.width);
|
|
|
|
GetHeight(&cairoData.mSize.height);
|
2014-04-15 11:02:23 -07:00
|
|
|
cairoData.mSourceSurface = surface;
|
2011-11-08 19:14:41 -08:00
|
|
|
|
2014-01-30 14:58:51 -08:00
|
|
|
nsRefPtr<layers::Image> image = mImageContainer->CreateImage(ImageFormat::CAIRO_SURFACE);
|
2011-11-08 19:14:41 -08:00
|
|
|
NS_ASSERTION(image, "Failed to create Image");
|
2013-03-29 13:14:19 -07:00
|
|
|
|
2011-11-08 19:14:41 -08:00
|
|
|
static_cast<CairoImage*>(image.get())->SetData(cairoData);
|
2012-09-24 13:31:30 -07:00
|
|
|
|
|
|
|
return image.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-11-27 18:34:45 -08:00
|
|
|
RasterImage::GetImageContainer(LayerManager* aManager, ImageContainer **_retval)
|
2012-09-24 13:31:30 -07:00
|
|
|
{
|
2012-11-27 18:34:45 -08:00
|
|
|
int32_t maxTextureSize = aManager->GetMaxTextureSize();
|
|
|
|
if (mSize.width > maxTextureSize || mSize.height > maxTextureSize) {
|
|
|
|
*_retval = nullptr;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2014-11-14 20:10:47 -08:00
|
|
|
if (IsUnlocked() && mProgressTracker) {
|
|
|
|
mProgressTracker->OnUnlockedDraw();
|
2013-04-26 12:58:17 -07:00
|
|
|
}
|
|
|
|
|
2014-02-24 19:37:51 -08:00
|
|
|
if (!mImageContainer) {
|
|
|
|
mImageContainer = mImageContainerCache;
|
|
|
|
}
|
|
|
|
|
2012-09-24 13:31:30 -07:00
|
|
|
if (mImageContainer) {
|
|
|
|
*_retval = mImageContainer;
|
|
|
|
NS_ADDREF(*_retval);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2012-11-16 10:04:29 -08:00
|
|
|
|
2012-09-24 13:31:30 -07:00
|
|
|
nsRefPtr<layers::Image> image = GetCurrentImage();
|
|
|
|
if (!image) {
|
2012-11-16 10:04:29 -08:00
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2012-09-24 13:31:30 -07:00
|
|
|
}
|
2012-07-26 11:11:22 -07:00
|
|
|
mImageContainer->SetCurrentImageInTransaction(image);
|
2011-11-08 19:14:41 -08:00
|
|
|
|
|
|
|
*_retval = mImageContainer;
|
2012-01-29 21:16:54 -08:00
|
|
|
NS_ADDREF(*_retval);
|
2014-02-24 19:37:51 -08:00
|
|
|
// We only need to be careful about holding on to the image when it is
|
|
|
|
// discardable by the OS.
|
2014-11-27 19:55:57 -08:00
|
|
|
if (CanDiscard()) {
|
2014-07-30 12:52:05 -07:00
|
|
|
mImageContainerCache = mImageContainer;
|
2014-02-24 19:37:51 -08:00
|
|
|
mImageContainer = nullptr;
|
|
|
|
}
|
|
|
|
|
2011-11-08 19:14:41 -08:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-09-24 13:31:30 -07:00
|
|
|
void
|
|
|
|
RasterImage::UpdateImageContainer()
|
|
|
|
{
|
2014-11-14 20:06:21 -08:00
|
|
|
if (!mImageContainer) {
|
2012-09-24 13:31:30 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRefPtr<layers::Image> image = GetCurrentImage();
|
|
|
|
if (!image) {
|
|
|
|
return;
|
|
|
|
}
|
2014-11-14 20:06:21 -08:00
|
|
|
|
2012-09-24 13:31:30 -07:00
|
|
|
mImageContainer->SetCurrentImage(image);
|
|
|
|
}
|
|
|
|
|
2012-02-19 19:51:48 -08:00
|
|
|
size_t
|
2014-11-26 18:00:15 -08:00
|
|
|
RasterImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
|
2012-02-19 19:51:48 -08:00
|
|
|
{
|
2015-01-12 01:20:23 -08:00
|
|
|
return mSourceBuffer->SizeOfIncludingThisWithComputedFallback(aMallocSizeOf);
|
2012-02-19 19:51:48 -08:00
|
|
|
}
|
2011-07-18 06:20:27 -07:00
|
|
|
|
2012-10-13 19:17:40 -07:00
|
|
|
size_t
|
2014-11-26 18:00:15 -08:00
|
|
|
RasterImage::SizeOfDecoded(gfxMemoryLocation aLocation,
|
|
|
|
MallocSizeOf aMallocSizeOf) const
|
2010-05-21 21:10:14 -07:00
|
|
|
{
|
2014-11-26 13:22:11 -08:00
|
|
|
size_t n = 0;
|
|
|
|
n += SurfaceCache::SizeOfSurfaces(ImageKey(this), aLocation, aMallocSizeOf);
|
2015-01-07 13:07:23 -08:00
|
|
|
if (mAnim) {
|
|
|
|
n += mAnim->SizeOfCompositingFrames(aLocation, aMallocSizeOf);
|
2014-11-26 13:22:11 -08:00
|
|
|
}
|
|
|
|
return n;
|
2011-07-18 06:20:27 -07:00
|
|
|
}
|
|
|
|
|
2015-01-08 00:04:31 -08:00
|
|
|
class OnAddedFrameRunnable : public nsRunnable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
OnAddedFrameRunnable(RasterImage* aImage,
|
|
|
|
uint32_t aNewFrameCount,
|
|
|
|
const nsIntRect& aNewRefreshArea)
|
|
|
|
: mImage(aImage)
|
|
|
|
, mNewFrameCount(aNewFrameCount)
|
|
|
|
, mNewRefreshArea(aNewRefreshArea)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aImage);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD Run()
|
|
|
|
{
|
|
|
|
mImage->OnAddedFrame(mNewFrameCount, mNewRefreshArea);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsRefPtr<RasterImage> mImage;
|
|
|
|
uint32_t mNewFrameCount;
|
|
|
|
nsIntRect mNewRefreshArea;
|
|
|
|
};
|
|
|
|
|
2015-01-08 00:01:25 -08:00
|
|
|
void
|
|
|
|
RasterImage::OnAddedFrame(uint32_t aNewFrameCount,
|
|
|
|
const nsIntRect& aNewRefreshArea)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2015-01-08 00:04:31 -08:00
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
nsCOMPtr<nsIRunnable> runnable =
|
|
|
|
new OnAddedFrameRunnable(this, aNewFrameCount, aNewRefreshArea);
|
|
|
|
NS_DispatchToMainThread(runnable);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-01-11 11:43:32 -08:00
|
|
|
MOZ_ASSERT((mFrameCount == 1 && aNewFrameCount == 1) ||
|
|
|
|
mFrameCount < aNewFrameCount,
|
|
|
|
"Frame count running backwards");
|
2015-01-11 05:34:20 -08:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
if (aNewFrameCount > mFrameCount) {
|
|
|
|
mFrameCount = aNewFrameCount;
|
|
|
|
|
|
|
|
if (aNewFrameCount == 2) {
|
|
|
|
// We're becoming animated, so initialize animation stuff.
|
|
|
|
MOZ_ASSERT(!mAnim, "Already have animation state?");
|
|
|
|
mAnim = MakeUnique<FrameAnimator>(this, mSize.ToIntSize(), mAnimationMode);
|
|
|
|
|
|
|
|
// We don't support discarding animated images (See bug 414259).
|
|
|
|
// Lock the image and throw away the key.
|
|
|
|
//
|
|
|
|
// Note that this is inefficient, since we could get rid of the source data
|
|
|
|
// too. However, doing this is actually hard, because we're probably
|
|
|
|
// mid-decode, and thus we're decoding out of the source buffer. Since we're
|
|
|
|
// going to fix this anyway later, and since we didn't kill the source data
|
|
|
|
// in the old world either, locking is acceptable for the moment.
|
|
|
|
LockImage();
|
|
|
|
|
|
|
|
if (mPendingAnimation && ShouldAnimate()) {
|
|
|
|
StartAnimation();
|
|
|
|
}
|
2015-01-11 11:43:32 -08:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
if (aNewFrameCount > 1) {
|
|
|
|
mAnim->UnionFirstFrameRefreshArea(aNewRefreshArea);
|
|
|
|
}
|
|
|
|
}
|
2015-01-11 11:43:32 -08:00
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2013-08-25 00:19:42 -07:00
|
|
|
RasterImage::SetSize(int32_t aWidth, int32_t aHeight, Orientation aOrientation)
|
2009-09-12 15:44:18 -07:00
|
|
|
{
|
2013-03-01 15:17:24 -08:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// Ensure that we have positive values
|
|
|
|
// XXX - Why isn't the size unsigned? Should this be changed?
|
|
|
|
if ((aWidth < 0) || (aHeight < 0))
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
// if we already have a size, check the new size against the old one
|
2015-01-07 01:37:20 -08:00
|
|
|
if (mHasSize &&
|
2013-08-25 00:19:42 -07:00
|
|
|
((aWidth != mSize.width) ||
|
|
|
|
(aHeight != mSize.height) ||
|
|
|
|
(aOrientation != mOrientation))) {
|
2012-05-19 12:32:37 -07:00
|
|
|
NS_WARNING("Image changed size on redecode! This should not happen!");
|
2009-09-12 15:44:18 -07:00
|
|
|
DoError();
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the size and flag that we have it
|
|
|
|
mSize.SizeTo(aWidth, aHeight);
|
2013-08-25 00:19:42 -07:00
|
|
|
mOrientation = aOrientation;
|
2011-10-17 07:59:28 -07:00
|
|
|
mHasSize = true;
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2014-11-26 13:22:10 -08:00
|
|
|
void
|
2015-01-12 01:20:23 -08:00
|
|
|
RasterImage::OnDecodingComplete()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2013-03-01 15:17:24 -08:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
2014-11-26 13:22:10 -08:00
|
|
|
if (mError) {
|
|
|
|
return;
|
|
|
|
}
|
2009-09-12 15:44:18 -07:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// Flag that we've been decoded before.
|
2011-10-17 07:59:28 -07:00
|
|
|
mHasBeenDecoded = true;
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// Let our FrameAnimator know not to expect any more frames.
|
2015-01-11 05:34:20 -08:00
|
|
|
if (mAnim) {
|
|
|
|
mAnim->SetDoneDecoding(true);
|
2015-01-10 18:47:44 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-15 11:38:59 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::SetAnimationMode(uint16_t aAnimationMode)
|
|
|
|
{
|
|
|
|
if (mAnim) {
|
|
|
|
mAnim->SetAnimationMode(aAnimationMode);
|
|
|
|
}
|
|
|
|
return SetAnimationModeInternal(aAnimationMode);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
//******************************************************************************
|
2010-09-07 17:33:02 -07:00
|
|
|
/* void StartAnimation () */
|
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::StartAnimation()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2010-09-07 17:33:02 -07:00
|
|
|
NS_ABORT_IF_FALSE(ShouldAnimate(), "Should not animate!");
|
|
|
|
|
2014-11-26 13:22:10 -08:00
|
|
|
// If we don't have mAnim yet, then we're not ready to animate. Setting
|
|
|
|
// mPendingAnimation will cause us to start animating as soon as we have a
|
|
|
|
// second frame, which causes mAnim to be constructed.
|
|
|
|
mPendingAnimation = !mAnim;
|
|
|
|
if (mPendingAnimation) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2010-09-07 17:33:02 -07:00
|
|
|
|
2013-09-20 05:12:10 -07:00
|
|
|
// A timeout of -1 means we should display this frame forever.
|
2015-01-07 13:07:23 -08:00
|
|
|
if (mAnim->GetTimeoutForFrame(GetCurrentFrameIndex()) < 0) {
|
2013-09-20 05:12:10 -07:00
|
|
|
mAnimationFinished = true;
|
|
|
|
return NS_ERROR_ABORT;
|
|
|
|
}
|
2011-11-09 13:39:16 -08:00
|
|
|
|
2015-01-07 13:07:23 -08:00
|
|
|
// We need to set the time that this initial frame was first displayed, as
|
|
|
|
// this is used in AdvanceFrame().
|
|
|
|
mAnim->InitAnimationFrameTimeIfNecessary();
|
2013-03-29 13:14:19 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
/* void stopAnimation (); */
|
2010-09-07 17:33:02 -07:00
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::StopAnimation()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2010-09-07 17:33:02 -07:00
|
|
|
NS_ABORT_IF_FALSE(mAnimating, "Should be animating!");
|
|
|
|
|
2013-09-20 05:12:10 -07:00
|
|
|
nsresult rv = NS_OK;
|
|
|
|
if (mError) {
|
|
|
|
rv = NS_ERROR_FAILURE;
|
|
|
|
} else {
|
|
|
|
mAnim->SetAnimationFrameTime(TimeStamp());
|
|
|
|
}
|
2013-09-03 13:20:15 -07:00
|
|
|
|
2013-09-20 05:12:10 -07:00
|
|
|
mAnimating = false;
|
|
|
|
return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
/* void resetAnimation (); */
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::ResetAnimation()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2014-11-26 13:22:10 -08:00
|
|
|
mPendingAnimation = false;
|
|
|
|
|
|
|
|
if (mAnimationMode == kDontAnimMode || !mAnim ||
|
|
|
|
mAnim->GetCurrentAnimationFrameIndex() == 0) {
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
2014-11-26 13:22:10 -08:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
mAnimationFinished = false;
|
2011-03-31 14:05:31 -07:00
|
|
|
|
2010-09-07 17:33:02 -07:00
|
|
|
if (mAnimating)
|
|
|
|
StopAnimation();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2015-01-07 13:07:23 -08:00
|
|
|
MOZ_ASSERT(mAnim, "Should have a FrameAnimator");
|
2013-09-20 05:12:10 -07:00
|
|
|
mAnim->ResetAnimation();
|
2013-06-17 13:49:04 -07:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
NotifyProgress(NoProgress, mAnim->GetFirstFrameRefreshArea());
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2013-09-20 05:12:10 -07:00
|
|
|
// Start the animation again. It may not have been running before, if
|
|
|
|
// mAnimationFinished was true before entering this function.
|
|
|
|
EvaluateAnimation();
|
2010-09-07 17:33:02 -07:00
|
|
|
|
2008-03-19 22:54:30 -07:00
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2013-05-17 13:57:20 -07:00
|
|
|
//******************************************************************************
|
2013-09-03 13:20:15 -07:00
|
|
|
// [notxpcom] void setAnimationStartTime ([const] in TimeStamp aTime);
|
2013-05-17 13:57:20 -07:00
|
|
|
NS_IMETHODIMP_(void)
|
2014-06-16 15:25:43 -07:00
|
|
|
RasterImage::SetAnimationStartTime(const TimeStamp& aTime)
|
2013-05-17 13:57:20 -07:00
|
|
|
{
|
2013-09-03 13:20:15 -07:00
|
|
|
if (mError || mAnimationMode == kDontAnimMode || mAnimating || !mAnim)
|
2013-05-17 13:57:20 -07:00
|
|
|
return;
|
|
|
|
|
2013-07-15 11:38:59 -07:00
|
|
|
mAnim->SetAnimationFrameTime(aTime);
|
2013-05-17 13:57:20 -07:00
|
|
|
}
|
|
|
|
|
2013-04-25 15:58:20 -07:00
|
|
|
NS_IMETHODIMP_(float)
|
|
|
|
RasterImage::GetFrameIndex(uint32_t aWhichFrame)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE, "Invalid argument");
|
|
|
|
return (aWhichFrame == FRAME_FIRST || !mAnim)
|
|
|
|
? 0.0f
|
2013-07-15 11:38:59 -07:00
|
|
|
: mAnim->GetCurrentAnimationFrameIndex();
|
2013-04-25 15:58:20 -07:00
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
void
|
2012-08-22 08:56:38 -07:00
|
|
|
RasterImage::SetLoopCount(int32_t aLoopCount)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
2010-08-13 21:09:49 -07:00
|
|
|
return;
|
2009-09-12 15:44:18 -07:00
|
|
|
|
2015-01-07 13:07:23 -08:00
|
|
|
// No need to set this if we're not an animation.
|
2013-07-15 11:38:59 -07:00
|
|
|
if (mAnim) {
|
2015-01-07 13:07:23 -08:00
|
|
|
mAnim->SetLoopCount(aLoopCount);
|
2013-07-15 11:38:59 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2014-06-26 16:02:04 -07:00
|
|
|
NS_IMETHODIMP_(nsIntRect)
|
|
|
|
RasterImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect)
|
|
|
|
{
|
|
|
|
return aRect;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2015-01-12 01:20:23 -08:00
|
|
|
RasterImage::OnImageDataComplete(nsIRequest*, nsISupports*, nsresult aStatus,
|
|
|
|
bool aLastPart)
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2013-03-01 15:17:24 -08:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// Record that we have all the data we're going to get now.
|
2015-01-11 11:43:32 -08:00
|
|
|
mHasSourceData = true;
|
2009-09-12 15:44:18 -07:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// Let decoders know that there won't be any more data coming.
|
|
|
|
mSourceBuffer->Complete(aStatus);
|
2013-02-13 18:41:10 -08:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
if (!mHasSize) {
|
|
|
|
// We need to guarantee that we've gotten the image's size, or at least
|
|
|
|
// determined that we won't be able to get it, before we deliver the load
|
|
|
|
// event. That means we have to do a synchronous size decode here.
|
|
|
|
Decode(DecodeStrategy::SYNC_IF_POSSIBLE, DECODE_FLAGS_DEFAULT,
|
|
|
|
/* aDoSizeDecode = */ true);
|
2013-03-01 15:17:24 -08:00
|
|
|
}
|
2013-02-01 17:06:34 -08:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// Determine our final status, giving precedence to Necko failure codes. We
|
|
|
|
// check after running the size decode above in case it triggered an error.
|
|
|
|
nsresult finalStatus = mError ? NS_ERROR_FAILURE : NS_OK;
|
|
|
|
if (NS_FAILED(aStatus)) {
|
2015-01-11 11:43:32 -08:00
|
|
|
finalStatus = aStatus;
|
2015-01-12 01:20:23 -08:00
|
|
|
}
|
2015-01-11 11:43:32 -08:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// If loading failed, report an error.
|
|
|
|
if (NS_FAILED(finalStatus)) {
|
|
|
|
DoError();
|
2015-01-11 11:43:32 -08:00
|
|
|
}
|
2015-01-11 05:34:20 -08:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// Notify our listeners, which will fire this image's load event.
|
|
|
|
MOZ_ASSERT(mHasSize || mError, "Need to know size before firing load event");
|
|
|
|
MOZ_ASSERT(!mHasSize ||
|
|
|
|
(mProgressTracker->GetProgress() & FLAG_SIZE_AVAILABLE),
|
|
|
|
"Should have notified that the size is available if we have it");
|
|
|
|
Progress loadProgress = LoadCompleteProgress(aLastPart, mError, finalStatus);
|
|
|
|
NotifyProgress(loadProgress);
|
|
|
|
|
2013-02-13 18:41:10 -08:00
|
|
|
return finalStatus;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2012-12-17 14:05:18 -08:00
|
|
|
RasterImage::OnImageDataAvailable(nsIRequest*,
|
|
|
|
nsISupports*,
|
|
|
|
nsIInputStream* aInStr,
|
|
|
|
uint64_t,
|
|
|
|
uint32_t aCount)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
2013-03-29 13:14:19 -07:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// WriteToSourceBuffer always consumes everything it gets if it doesn't run
|
|
|
|
// out of memory.
|
2012-12-17 14:05:18 -08:00
|
|
|
uint32_t bytesRead;
|
2015-01-12 01:20:23 -08:00
|
|
|
rv = aInStr->ReadSegments(WriteToSourceBuffer, this, aCount, &bytesRead);
|
2012-12-17 14:05:18 -08:00
|
|
|
|
2014-08-23 21:47:55 -07:00
|
|
|
NS_ABORT_IF_FALSE(bytesRead == aCount || HasError() || NS_FAILED(rv),
|
2015-01-12 01:20:23 -08:00
|
|
|
"WriteToSourceBuffer should consume everything if ReadSegments succeeds or "
|
2014-08-23 21:47:55 -07:00
|
|
|
"the image must be in error!");
|
2012-12-17 14:05:18 -08:00
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2015-01-12 01:20:23 -08:00
|
|
|
RasterImage::SetSourceSizeHint(uint32_t aSizeHint)
|
2010-06-25 11:21:40 -07:00
|
|
|
{
|
2015-01-12 01:20:23 -08:00
|
|
|
return mSourceBuffer->ExpectLength(aSizeHint);
|
2010-06-25 11:21:40 -07:00
|
|
|
}
|
|
|
|
|
2007-06-21 13:45:49 -07:00
|
|
|
/********* Methods to implement lazy allocation of nsIProperties object *************/
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::Get(const char *prop, const nsIID & iid, void * *result)
|
2007-06-21 13:45:49 -07:00
|
|
|
{
|
|
|
|
if (!mProperties)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
return mProperties->Get(prop, iid, result);
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::Set(const char *prop, nsISupports *value)
|
2007-06-21 13:45:49 -07:00
|
|
|
{
|
|
|
|
if (!mProperties)
|
|
|
|
mProperties = do_CreateInstance("@mozilla.org/properties;1");
|
|
|
|
if (!mProperties)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
return mProperties->Set(prop, value);
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
2011-09-28 23:19:26 -07:00
|
|
|
RasterImage::Has(const char *prop, bool *_retval)
|
2007-06-21 13:45:49 -07:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
|
|
if (!mProperties) {
|
2011-10-17 07:59:28 -07:00
|
|
|
*_retval = false;
|
2007-06-21 13:45:49 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
return mProperties->Has(prop, _retval);
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::Undefine(const char *prop)
|
2007-06-21 13:45:49 -07:00
|
|
|
{
|
|
|
|
if (!mProperties)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
return mProperties->Undefine(prop);
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
RasterImage::GetKeys(uint32_t *count, char ***keys)
|
2007-06-21 13:45:49 -07:00
|
|
|
{
|
|
|
|
if (!mProperties) {
|
|
|
|
*count = 0;
|
2012-07-30 07:20:58 -07:00
|
|
|
*keys = nullptr;
|
2007-06-21 13:45:49 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
return mProperties->GetKeys(count, keys);
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
|
|
|
void
|
2014-11-27 19:56:00 -08:00
|
|
|
RasterImage::Discard()
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2013-03-01 15:17:24 -08:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2014-11-27 19:55:57 -08:00
|
|
|
MOZ_ASSERT(CanDiscard(), "Asked to discard but can't");
|
2015-01-12 01:20:23 -08:00
|
|
|
MOZ_ASSERT(!mAnim, "Asked to discard for animated image");
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2015-01-07 13:07:23 -08:00
|
|
|
// Delete all the decoded frames.
|
2014-11-26 13:22:10 -08:00
|
|
|
SurfaceCache::RemoveImage(ImageKey(this));
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// Notify that we discarded.
|
2014-11-27 19:56:00 -08:00
|
|
|
if (mProgressTracker) {
|
2014-11-14 20:10:47 -08:00
|
|
|
mProgressTracker->OnDiscard();
|
2014-11-26 13:22:10 -08:00
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2011-08-05 06:57:16 -07:00
|
|
|
bool
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::CanDiscard() {
|
2014-11-26 13:22:10 -08:00
|
|
|
return mHasSourceData && // ...have the source data...
|
2014-01-21 15:19:22 -08:00
|
|
|
!mAnim; // Can never discard animated images
|
|
|
|
}
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// Sets up a decoder for this image.
|
|
|
|
already_AddRefed<Decoder>
|
|
|
|
RasterImage::CreateDecoder(bool aDoSizeDecode, uint32_t aFlags)
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2013-02-01 17:06:34 -08:00
|
|
|
// Make sure we actually get size before doing a full decode.
|
2015-01-12 01:20:23 -08:00
|
|
|
if (aDoSizeDecode) {
|
|
|
|
MOZ_ASSERT(!mHasSize, "Should not do unnecessary size decodes");
|
|
|
|
} else {
|
|
|
|
MOZ_ASSERT(mHasSize, "Must do a size decode before a full decode!");
|
2013-01-31 10:38:24 -08:00
|
|
|
}
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// Figure out which decoder we want.
|
2010-08-22 19:30:45 -07:00
|
|
|
eDecoderType type = GetDecoderType(mSourceDataMimeType.get());
|
2015-01-12 01:20:23 -08:00
|
|
|
if (type == eDecoderType_unknown) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2010-08-22 19:30:45 -07:00
|
|
|
|
2015-01-12 01:20:22 -08:00
|
|
|
// Instantiate the appropriate decoder.
|
2015-01-12 01:20:23 -08:00
|
|
|
nsRefPtr<Decoder> decoder;
|
2010-08-22 19:30:45 -07:00
|
|
|
switch (type) {
|
|
|
|
case eDecoderType_png:
|
2015-01-12 01:20:23 -08:00
|
|
|
decoder = new nsPNGDecoder(this);
|
2010-08-22 19:30:45 -07:00
|
|
|
break;
|
|
|
|
case eDecoderType_gif:
|
2015-01-12 01:20:23 -08:00
|
|
|
decoder = new nsGIFDecoder2(this);
|
2010-08-22 19:30:45 -07:00
|
|
|
break;
|
|
|
|
case eDecoderType_jpeg:
|
2012-11-18 17:18:52 -08:00
|
|
|
// If we have all the data we don't want to waste cpu time doing
|
2015-01-12 01:20:22 -08:00
|
|
|
// a progressive decode.
|
2015-01-12 01:20:23 -08:00
|
|
|
decoder = new nsJPEGDecoder(this,
|
|
|
|
mHasBeenDecoded ? Decoder::SEQUENTIAL :
|
|
|
|
Decoder::PROGRESSIVE);
|
2010-08-22 19:30:45 -07:00
|
|
|
break;
|
|
|
|
case eDecoderType_bmp:
|
2015-01-12 01:20:23 -08:00
|
|
|
decoder = new nsBMPDecoder(this);
|
2010-08-22 19:30:45 -07:00
|
|
|
break;
|
|
|
|
case eDecoderType_ico:
|
2015-01-12 01:20:23 -08:00
|
|
|
decoder = new nsICODecoder(this);
|
2010-08-22 19:30:45 -07:00
|
|
|
break;
|
|
|
|
case eDecoderType_icon:
|
2015-01-12 01:20:23 -08:00
|
|
|
decoder = new nsIconDecoder(this);
|
2010-08-22 19:30:45 -07:00
|
|
|
break;
|
|
|
|
default:
|
2015-01-12 01:20:22 -08:00
|
|
|
MOZ_ASSERT_UNREACHABLE("Unknown decoder type");
|
2010-08-22 19:30:45 -07:00
|
|
|
}
|
2010-08-11 17:49:50 -07:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
MOZ_ASSERT(decoder, "Should have a decoder now");
|
|
|
|
|
|
|
|
// Initialize the decoder.
|
|
|
|
decoder->SetSizeDecode(aDoSizeDecode);
|
|
|
|
decoder->SetSendPartialInvalidations(!mHasBeenDecoded);
|
|
|
|
decoder->SetImageIsTransient(mTransient);
|
|
|
|
decoder->SetDecodeFlags(DecodeFlags(aFlags));
|
2015-01-11 11:43:32 -08:00
|
|
|
if (!aDoSizeDecode) {
|
|
|
|
// We already have the size; tell the decoder so it can preallocate a
|
|
|
|
// frame. By default, we create an ARGB frame with no offset. If decoders
|
|
|
|
// need a different type, they need to ask for it themselves.
|
2015-01-12 01:20:23 -08:00
|
|
|
decoder->SetSize(mSize, mOrientation);
|
|
|
|
decoder->NeedNewFrame(0, 0, 0, mSize.width, mSize.height,
|
|
|
|
SurfaceFormat::B8G8R8A8);
|
|
|
|
decoder->AllocateFrame();
|
|
|
|
}
|
|
|
|
decoder->SetIterator(mSourceBuffer->Iterator());
|
|
|
|
decoder->Init();
|
|
|
|
|
|
|
|
if (NS_FAILED(decoder->GetDecoderError())) {
|
|
|
|
return nullptr;
|
2015-01-11 05:34:20 -08:00
|
|
|
}
|
2009-09-12 15:44:18 -07:00
|
|
|
|
2011-09-08 11:05:11 -07:00
|
|
|
if (!aDoSizeDecode) {
|
|
|
|
Telemetry::GetHistogramById(Telemetry::IMAGE_DECODE_COUNT)->Subtract(mDecodeCount);
|
|
|
|
mDecodeCount++;
|
|
|
|
Telemetry::GetHistogramById(Telemetry::IMAGE_DECODE_COUNT)->Add(mDecodeCount);
|
2013-01-03 13:06:08 -08:00
|
|
|
|
|
|
|
if (mDecodeCount > sMaxDecodeCount) {
|
|
|
|
// Don't subtract out 0 from the histogram, because that causes its count
|
|
|
|
// to go negative, which is not kosher.
|
|
|
|
if (sMaxDecodeCount > 0) {
|
|
|
|
Telemetry::GetHistogramById(Telemetry::IMAGE_MAX_DECODE_COUNT)->Subtract(sMaxDecodeCount);
|
2013-02-01 11:36:39 -08:00
|
|
|
}
|
2013-01-03 13:06:08 -08:00
|
|
|
sMaxDecodeCount = mDecodeCount;
|
|
|
|
Telemetry::GetHistogramById(Telemetry::IMAGE_MAX_DECODE_COUNT)->Add(sMaxDecodeCount);
|
|
|
|
}
|
2011-09-08 11:05:11 -07:00
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
return decoder.forget();
|
2015-01-11 11:43:32 -08:00
|
|
|
}
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
void
|
2014-09-26 18:50:24 -07:00
|
|
|
RasterImage::WantDecodedFrames(uint32_t aFlags, bool aShouldSyncNotify)
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2014-09-26 18:50:24 -07:00
|
|
|
if (aShouldSyncNotify) {
|
|
|
|
// We can sync notify, which means we can also sync decode.
|
|
|
|
if (aFlags & FLAG_SYNC_DECODE) {
|
2015-01-12 01:20:23 -08:00
|
|
|
Decode(DecodeStrategy::SYNC_IF_POSSIBLE, aFlags);
|
|
|
|
return;
|
2014-09-26 18:50:24 -07:00
|
|
|
}
|
2015-01-12 01:20:23 -08:00
|
|
|
|
|
|
|
// Here we are explicitly trading off flashing for responsiveness in the
|
|
|
|
// case that we're redecoding an image (see bug 845147).
|
|
|
|
Decode(mHasBeenDecoded ? DecodeStrategy::ASYNC
|
|
|
|
: DecodeStrategy::SYNC_FOR_SMALL_IMAGES,
|
|
|
|
aFlags);
|
|
|
|
return;
|
2014-09-26 18:50:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// We can't sync notify, so do an async decode.
|
2015-01-12 01:20:23 -08:00
|
|
|
Decode(DecodeStrategy::ASYNC, aFlags);
|
2009-09-12 15:44:18 -07:00
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
//******************************************************************************
|
|
|
|
/* void requestDecode() */
|
|
|
|
NS_IMETHODIMP
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::RequestDecode()
|
2012-10-04 13:02:15 -07:00
|
|
|
{
|
2015-01-12 01:20:23 -08:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
if (mError) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
if (!mHasSize) {
|
|
|
|
mWantFullDecode = true;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look up the first frame of the image, which will implicitly start decoding
|
|
|
|
// if it's not available right now.
|
|
|
|
// XXX(seth): Passing false for aShouldSyncNotify here has the effect of
|
|
|
|
// decoding asynchronously, but that's not obvious from the argument name.
|
|
|
|
// This API needs to be reworked.
|
|
|
|
LookupFrame(0, mSize, DECODE_FLAGS_DEFAULT, /* aShouldSyncNotify = */ false);
|
|
|
|
|
|
|
|
return NS_OK;
|
2012-10-04 13:02:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* void startDecode() */
|
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::StartDecoding()
|
|
|
|
{
|
2013-09-28 11:28:42 -07:00
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
return NS_DispatchToMainThread(
|
|
|
|
NS_NewRunnableMethod(this, &RasterImage::StartDecoding));
|
|
|
|
}
|
2013-07-26 11:57:41 -07:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
if (mError) {
|
2015-01-11 05:34:20 -08:00
|
|
|
return NS_ERROR_FAILURE;
|
2015-01-11 11:43:32 -08:00
|
|
|
}
|
2015-01-12 01:20:23 -08:00
|
|
|
if (!mHasSize) {
|
|
|
|
mWantFullDecode = true;
|
2015-01-11 11:43:32 -08:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// Look up the first frame of the image, which will implicitly start decoding
|
|
|
|
// if it's not available right now.
|
|
|
|
// XXX(seth): Passing true for aShouldSyncNotify here has the effect of
|
|
|
|
// synchronously decoding small images, but that's not obvious from the
|
|
|
|
// argument name. This API needs to be reworked.
|
|
|
|
LookupFrame(0, mSize, DECODE_FLAGS_DEFAULT, /* aShouldSyncNotify = */ true);
|
2015-01-11 11:43:32 -08:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
bool
|
|
|
|
RasterImage::IsDecoded()
|
2015-01-11 11:43:32 -08:00
|
|
|
{
|
2015-01-12 01:20:23 -08:00
|
|
|
// XXX(seth): We need to get rid of this; it's not reliable.
|
|
|
|
return mHasBeenDecoded || mError;
|
|
|
|
}
|
2009-09-12 15:44:18 -07:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::Decode(DecodeStrategy aStrategy,
|
|
|
|
uint32_t aFlags,
|
|
|
|
bool aDoSizeDecode /* = false */)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aDoSizeDecode || NS_IsMainThread());
|
2015-01-11 11:43:32 -08:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
if (mError) {
|
|
|
|
return NS_ERROR_FAILURE;
|
2015-01-11 11:43:32 -08:00
|
|
|
}
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// If we don't have a size yet, we can't do any other decoding.
|
|
|
|
if (!mHasSize && !aDoSizeDecode) {
|
|
|
|
mWantFullDecode = true;
|
2015-01-11 11:43:32 -08:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// Create a decoder.
|
|
|
|
nsRefPtr<Decoder> decoder = CreateDecoder(aDoSizeDecode, aFlags);
|
|
|
|
if (!decoder) {
|
|
|
|
return NS_ERROR_FAILURE;
|
2009-09-12 15:44:18 -07:00
|
|
|
}
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// Send out early notifications right away. (Unless this is a size decode,
|
|
|
|
// which doesn't send out any notifications until the end.)
|
|
|
|
if (!aDoSizeDecode) {
|
|
|
|
NotifyProgress(decoder->TakeProgress(),
|
|
|
|
decoder->TakeInvalidRect(),
|
|
|
|
decoder->GetDecodeFlags());
|
2015-01-11 11:43:32 -08:00
|
|
|
}
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
if (mHasSourceData) {
|
|
|
|
// If we have all the data, we can sync decode if requested.
|
|
|
|
if (aStrategy == DecodeStrategy::SYNC_FOR_SMALL_IMAGES) {
|
|
|
|
PROFILER_LABEL_PRINTF("DecodePool", "SyncDecodeIfSmall",
|
|
|
|
js::ProfileEntry::Category::GRAPHICS, "%s", GetURIString().get());
|
|
|
|
DecodePool::Singleton()->SyncDecodeIfSmall(decoder);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2015-01-11 11:43:32 -08:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
if (aStrategy == DecodeStrategy::SYNC_IF_POSSIBLE) {
|
|
|
|
PROFILER_LABEL_PRINTF("DecodePool", "SyncDecodeIfPossible",
|
|
|
|
js::ProfileEntry::Category::GRAPHICS, "%s", GetURIString().get());
|
|
|
|
DecodePool::Singleton()->SyncDecodeIfPossible(decoder);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2015-01-11 11:43:32 -08:00
|
|
|
}
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// Perform an async decode. We also take this path if we don't have all the
|
|
|
|
// source data yet, since sync decoding is impossible in that situation.
|
|
|
|
DecodePool::Singleton()->AsyncDecode(decoder);
|
|
|
|
return NS_OK;
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2013-03-24 09:37:21 -07:00
|
|
|
bool
|
2014-09-19 14:53:29 -07:00
|
|
|
RasterImage::CanScale(GraphicsFilter aFilter,
|
|
|
|
const nsIntSize& aSize,
|
|
|
|
uint32_t aFlags)
|
2012-10-03 11:29:42 -07:00
|
|
|
{
|
2014-09-19 14:53:29 -07:00
|
|
|
#ifndef MOZ_ENABLE_SKIA
|
|
|
|
// The high-quality scaler requires Skia.
|
|
|
|
return false;
|
|
|
|
#else
|
2015-01-12 01:20:23 -08:00
|
|
|
// Check basic requirements: HQ downscaling is enabled, we have all the source
|
|
|
|
// data and know our size, the flags allow us to do it, and a 'good' filter is
|
|
|
|
// being used. The flags may ask us not to scale because the caller isn't
|
|
|
|
// drawing to the window. If we're drawing to something else (e.g. a canvas)
|
|
|
|
// we usually have no way of updating what we've drawn, so HQ scaling is
|
|
|
|
// useless.
|
|
|
|
if (!gfxPrefs::ImageHQDownscalingEnabled() || !mHasSize || !mHasSourceData ||
|
2014-09-19 14:53:29 -07:00
|
|
|
!(aFlags & imgIContainer::FLAG_HIGH_QUALITY_SCALING) ||
|
|
|
|
aFilter != GraphicsFilter::FILTER_GOOD) {
|
2012-10-03 11:29:42 -07:00
|
|
|
return false;
|
2013-03-24 09:37:21 -07:00
|
|
|
}
|
|
|
|
|
2015-01-07 01:37:20 -08:00
|
|
|
// We don't use the scaler for animated or transient images to avoid doing a
|
2013-01-21 08:37:54 -08:00
|
|
|
// bunch of work on an image that just gets thrown away.
|
2015-01-07 01:37:20 -08:00
|
|
|
if (mAnim || mTransient) {
|
2014-09-19 14:53:29 -07:00
|
|
|
return false;
|
|
|
|
}
|
2012-10-10 08:35:23 -07:00
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
// If target size is 1:1 with original, don't scale.
|
|
|
|
if (aSize == mSize) {
|
|
|
|
return false;
|
2014-09-14 23:17:28 -07:00
|
|
|
}
|
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
// To save memory, don't quality upscale images bigger than the limit.
|
|
|
|
if (aSize.width > mSize.width || aSize.height > mSize.height) {
|
|
|
|
uint32_t scaledSize = static_cast<uint32_t>(aSize.width * aSize.height);
|
2014-09-22 14:30:20 -07:00
|
|
|
if (scaledSize > gfxPrefs::ImageHQUpscalingMaxSize()) {
|
2014-09-19 14:53:29 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2014-09-16 19:04:53 -07:00
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
// There's no point in scaling if we can't store the result.
|
|
|
|
if (!SurfaceCache::CanHold(aSize.ToIntSize())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-09-22 14:30:20 -07:00
|
|
|
// XXX(seth): It's not clear what this check buys us over
|
|
|
|
// gfxPrefs::ImageHQUpscalingMaxSize().
|
2014-09-19 14:53:29 -07:00
|
|
|
// The default value of this pref is 1000, which means that we never upscale.
|
|
|
|
// If that's all it's getting us, I'd rather we just forbid that explicitly.
|
|
|
|
gfx::Size scale(double(aSize.width) / mSize.width,
|
|
|
|
double(aSize.height) / mSize.height);
|
2014-09-22 14:30:20 -07:00
|
|
|
gfxFloat minFactor = gfxPrefs::ImageHQDownscalingMinFactor() / 1000.0;
|
2014-09-19 14:53:29 -07:00
|
|
|
return (scale.width < minFactor || scale.height < minFactor);
|
|
|
|
#endif
|
2014-09-14 21:51:20 -07:00
|
|
|
}
|
2014-07-28 14:27:39 -07:00
|
|
|
|
2014-09-14 21:51:20 -07:00
|
|
|
void
|
2014-09-19 14:53:29 -07:00
|
|
|
RasterImage::NotifyNewScaledFrame()
|
2014-09-14 21:51:20 -07:00
|
|
|
{
|
2015-01-12 01:20:23 -08:00
|
|
|
// Send an invalidation so observers will repaint and can take advantage of
|
|
|
|
// the new scaled frame if possible.
|
|
|
|
NotifyProgress(NoProgress, nsIntRect(0, 0, mSize.width, mSize.height));
|
2014-09-16 19:04:53 -07:00
|
|
|
}
|
2014-09-14 23:17:28 -07:00
|
|
|
|
2014-09-16 19:04:53 -07:00
|
|
|
void
|
2014-09-19 14:53:29 -07:00
|
|
|
RasterImage::RequestScale(imgFrame* aFrame,
|
|
|
|
uint32_t aFlags,
|
|
|
|
const nsIntSize& aSize)
|
2014-09-16 19:04:53 -07:00
|
|
|
{
|
2014-09-19 14:53:29 -07:00
|
|
|
// We don't scale frames which aren't fully decoded.
|
2015-01-11 19:28:02 -08:00
|
|
|
if (!aFrame->IsImageComplete()) {
|
2014-09-16 22:30:11 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
// We can't scale frames that need padding or are single pixel.
|
|
|
|
if (aFrame->NeedsPadding() || aFrame->IsSinglePixel()) {
|
2014-09-18 19:26:01 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-09-16 22:30:11 -07:00
|
|
|
// We also can't scale if we can't lock the image data for this frame.
|
2014-09-12 01:12:55 -07:00
|
|
|
RawAccessFrameRef frameRef = aFrame->RawAccessRef();
|
|
|
|
if (!frameRef) {
|
2014-07-28 14:27:39 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
nsRefPtr<ScaleRunner> runner =
|
|
|
|
new ScaleRunner(this, DecodeFlags(aFlags), aSize, Move(frameRef));
|
|
|
|
if (runner->Init()) {
|
2014-07-28 14:27:39 -07:00
|
|
|
if (!sScaleWorkerThread) {
|
|
|
|
NS_NewNamedThread("Image Scaler", getter_AddRefs(sScaleWorkerThread));
|
|
|
|
ClearOnShutdown(&sScaleWorkerThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
sScaleWorkerThread->Dispatch(runner, NS_DISPATCH_NORMAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-12 18:29:27 -07:00
|
|
|
void
|
|
|
|
RasterImage::DrawWithPreDownscaleIfNeeded(DrawableFrameRef&& aFrameRef,
|
2014-09-16 19:02:26 -07:00
|
|
|
gfxContext* aContext,
|
2014-08-22 13:12:38 -07:00
|
|
|
const nsIntSize& aSize,
|
|
|
|
const ImageRegion& aRegion,
|
2013-10-01 14:01:19 -07:00
|
|
|
GraphicsFilter aFilter,
|
2013-04-25 15:08:58 -07:00
|
|
|
uint32_t aFlags)
|
2012-04-03 14:57:22 -07:00
|
|
|
{
|
2014-09-12 18:29:27 -07:00
|
|
|
DrawableFrameRef frameRef;
|
2012-04-03 14:57:22 -07:00
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
if (CanScale(aFilter, aSize, aFlags)) {
|
|
|
|
frameRef =
|
|
|
|
SurfaceCache::Lookup(ImageKey(this),
|
|
|
|
RasterSurfaceKey(aSize.ToIntSize(),
|
2015-01-07 01:40:23 -08:00
|
|
|
DecodeFlags(aFlags),
|
|
|
|
0));
|
2014-09-19 14:53:29 -07:00
|
|
|
if (!frameRef) {
|
|
|
|
// We either didn't have a matching scaled frame or the OS threw it away.
|
|
|
|
// Request a new one so we'll be ready next time. For now, we'll fall back
|
|
|
|
// to aFrameRef below.
|
|
|
|
RequestScale(aFrameRef.get(), aFlags, aSize);
|
2012-10-10 08:35:23 -07:00
|
|
|
}
|
2015-01-11 19:28:02 -08:00
|
|
|
if (frameRef && !frameRef->IsImageComplete()) {
|
2014-09-19 14:53:29 -07:00
|
|
|
frameRef.reset(); // We're still scaling, so we can't use this yet.
|
2012-04-03 14:57:22 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-12 18:29:27 -07:00
|
|
|
gfxContextMatrixAutoSaveRestore saveMatrix(aContext);
|
2014-08-22 13:12:38 -07:00
|
|
|
ImageRegion region(aRegion);
|
2014-09-12 18:29:27 -07:00
|
|
|
if (!frameRef) {
|
|
|
|
frameRef = Move(aFrameRef);
|
|
|
|
}
|
2014-08-22 13:12:38 -07:00
|
|
|
|
|
|
|
// By now we may have a frame with the requested size. If not, we need to
|
|
|
|
// adjust the drawing parameters accordingly.
|
2014-11-26 13:22:10 -08:00
|
|
|
IntSize finalSize = frameRef->GetImageSize();
|
|
|
|
if (ThebesIntSize(finalSize) != aSize) {
|
|
|
|
gfx::Size scale(double(aSize.width) / finalSize.width,
|
|
|
|
double(aSize.height) / finalSize.height);
|
2014-08-22 13:12:38 -07:00
|
|
|
aContext->Multiply(gfxMatrix::Scaling(scale.width, scale.height));
|
|
|
|
region.Scale(1.0 / scale.width, 1.0 / scale.height);
|
|
|
|
}
|
|
|
|
|
2014-11-26 13:22:10 -08:00
|
|
|
frameRef->Draw(aContext, region, aFilter, aFlags);
|
2012-04-03 14:57:22 -07:00
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
//******************************************************************************
|
2010-07-05 13:49:05 -07:00
|
|
|
/* [noscript] void draw(in gfxContext aContext,
|
|
|
|
* in gfxGraphicsFilter aFilter,
|
|
|
|
* [const] in gfxMatrix aUserSpaceToImageSpace,
|
|
|
|
* [const] in gfxRect aFill,
|
|
|
|
* [const] in nsIntRect aSubimage,
|
2010-09-08 13:40:39 -07:00
|
|
|
* [const] in nsIntSize aViewportSize,
|
2013-02-28 12:22:43 -08:00
|
|
|
* [const] in SVGImageContext aSVGContext,
|
2013-03-10 18:43:37 -07:00
|
|
|
* in uint32_t aWhichFrame,
|
2012-08-22 08:56:38 -07:00
|
|
|
* in uint32_t aFlags); */
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
2014-08-22 13:12:38 -07:00
|
|
|
RasterImage::Draw(gfxContext* aContext,
|
|
|
|
const nsIntSize& aSize,
|
|
|
|
const ImageRegion& aRegion,
|
2013-03-10 18:43:37 -07:00
|
|
|
uint32_t aWhichFrame,
|
2014-08-22 13:12:38 -07:00
|
|
|
GraphicsFilter aFilter,
|
|
|
|
const Maybe<SVGImageContext>& /*aSVGContext - ignored*/,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aFlags)
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2013-03-10 18:43:37 -07:00
|
|
|
if (aWhichFrame > FRAME_MAX_VALUE)
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2011-01-12 17:45:13 -08:00
|
|
|
// Illegal -- you can't draw with non-default decode flags.
|
|
|
|
// (Disabling colorspace conversion might make sense to allow, but
|
|
|
|
// we don't currently.)
|
|
|
|
if ((aFlags & DECODE_FLAGS_MASK) != DECODE_FLAGS_DEFAULT)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aContext);
|
|
|
|
|
2014-11-14 20:10:47 -08:00
|
|
|
if (IsUnlocked() && mProgressTracker) {
|
|
|
|
mProgressTracker->OnUnlockedDraw();
|
2013-02-24 16:59:22 -08:00
|
|
|
}
|
|
|
|
|
2014-11-26 13:22:10 -08:00
|
|
|
// XXX(seth): For now, we deliberately don't look up a frame of size aSize
|
|
|
|
// (though DrawWithPreDownscaleIfNeeded will do so later). It doesn't make
|
|
|
|
// sense to do so until we support downscale-during-decode. Right now we need
|
|
|
|
// to make sure that we always touch an mSize-sized frame so that we have
|
|
|
|
// something to HQ scale.
|
2015-01-12 01:20:23 -08:00
|
|
|
DrawableFrameRef ref =
|
|
|
|
LookupFrame(GetRequestedFrameIndex(aWhichFrame), mSize, aFlags);
|
2014-09-12 18:29:27 -07:00
|
|
|
if (!ref) {
|
2014-11-26 13:22:10 -08:00
|
|
|
// Getting the frame (above) touches the image and kicks off decoding.
|
2015-01-12 01:20:23 -08:00
|
|
|
if (mDrawStartTime.IsNull()) {
|
|
|
|
mDrawStartTime = TimeStamp::Now();
|
|
|
|
}
|
2014-11-26 13:22:10 -08:00
|
|
|
return NS_OK;
|
2009-09-12 15:44:18 -07:00
|
|
|
}
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
bool shouldRecordTelemetry = !mDrawStartTime.IsNull() &&
|
|
|
|
ref->IsImageComplete();
|
|
|
|
|
2014-11-26 13:22:10 -08:00
|
|
|
DrawWithPreDownscaleIfNeeded(Move(ref), aContext, aSize,
|
|
|
|
aRegion, aFilter, aFlags);
|
2014-02-24 19:37:51 -08:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
if (shouldRecordTelemetry) {
|
2011-08-10 16:12:08 -07:00
|
|
|
TimeDuration drawLatency = TimeStamp::Now() - mDrawStartTime;
|
2015-01-12 01:20:23 -08:00
|
|
|
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_ON_DRAW_LATENCY,
|
|
|
|
int32_t(drawLatency.ToMicroseconds()));
|
2011-08-10 16:12:08 -07:00
|
|
|
mDrawStartTime = TimeStamp();
|
|
|
|
}
|
2012-04-03 14:57:22 -07:00
|
|
|
|
2007-10-18 17:36:34 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
//******************************************************************************
|
|
|
|
/* void lockImage() */
|
2007-10-18 17:36:34 -07:00
|
|
|
NS_IMETHODIMP
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::LockImage()
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2013-09-28 11:28:43 -07:00
|
|
|
MOZ_ASSERT(NS_IsMainThread(),
|
|
|
|
"Main thread to encourage serialization with UnlockImage");
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// Increment the lock count
|
|
|
|
mLockCount++;
|
|
|
|
|
2014-11-26 13:22:10 -08:00
|
|
|
// Lock this image's surfaces in the SurfaceCache.
|
|
|
|
if (mLockCount == 1) {
|
|
|
|
SurfaceCache::LockImage(ImageKey(this));
|
|
|
|
}
|
|
|
|
|
2007-10-18 17:36:34 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
//******************************************************************************
|
|
|
|
/* void unlockImage() */
|
2007-10-18 17:36:34 -07:00
|
|
|
NS_IMETHODIMP
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::UnlockImage()
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2013-09-28 11:28:43 -07:00
|
|
|
MOZ_ASSERT(NS_IsMainThread(),
|
|
|
|
"Main thread to encourage serialization with LockImage");
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// It's an error to call this function if the lock count is 0
|
|
|
|
NS_ABORT_IF_FALSE(mLockCount > 0,
|
|
|
|
"Calling UnlockImage with mLockCount == 0!");
|
|
|
|
if (mLockCount == 0)
|
|
|
|
return NS_ERROR_ABORT;
|
|
|
|
|
|
|
|
// Decrement our lock count
|
|
|
|
mLockCount--;
|
|
|
|
|
2014-11-26 13:22:10 -08:00
|
|
|
// Unlock this image's surfaces in the SurfaceCache.
|
2015-01-07 01:40:23 -08:00
|
|
|
if (mLockCount == 0 ) {
|
2014-11-26 13:22:10 -08:00
|
|
|
SurfaceCache::UnlockImage(ImageKey(this));
|
|
|
|
}
|
|
|
|
|
2007-10-18 17:36:34 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-03-09 22:29:28 -08:00
|
|
|
//******************************************************************************
|
|
|
|
/* void requestDiscard() */
|
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::RequestDiscard()
|
|
|
|
{
|
2014-11-27 19:55:57 -08:00
|
|
|
if (mDiscardable && // Enabled at creation time...
|
|
|
|
mLockCount == 0 && // ...not temporarily disabled...
|
2014-11-27 19:56:00 -08:00
|
|
|
CanDiscard()) {
|
2014-11-27 19:55:57 -08:00
|
|
|
Discard();
|
2012-03-09 22:29:28 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-09-12 08:22:30 -07:00
|
|
|
// Indempotent error flagging routine. If a decoder is open, shuts it down.
|
2010-08-13 21:09:49 -07:00
|
|
|
void
|
|
|
|
RasterImage::DoError()
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
// If we've flagged an error before, we have nothing to do
|
|
|
|
if (mError)
|
|
|
|
return;
|
|
|
|
|
2013-09-12 14:40:16 -07:00
|
|
|
// We can't safely handle errors off-main-thread, so dispatch a worker to do it.
|
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
HandleErrorWorker::DispatchIfNeeded(this);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Put the container in an error state.
|
2011-10-17 07:59:28 -07:00
|
|
|
mError = true;
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
// Log our error
|
|
|
|
LOG_CONTAINER_ERROR;
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2013-09-12 14:40:16 -07:00
|
|
|
/* static */ void
|
|
|
|
RasterImage::HandleErrorWorker::DispatchIfNeeded(RasterImage* aImage)
|
|
|
|
{
|
2015-01-12 01:20:23 -08:00
|
|
|
nsRefPtr<HandleErrorWorker> worker = new HandleErrorWorker(aImage);
|
|
|
|
NS_DispatchToMainThread(worker);
|
2013-09-12 14:40:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
RasterImage::HandleErrorWorker::HandleErrorWorker(RasterImage* aImage)
|
|
|
|
: mImage(aImage)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mImage, "Should have image");
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::HandleErrorWorker::Run()
|
|
|
|
{
|
|
|
|
mImage->DoError();
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-02-09 12:04:30 -08:00
|
|
|
// nsIInputStream callback to copy the incoming image data directly to the
|
2010-08-13 21:09:51 -07:00
|
|
|
// RasterImage without processing. The RasterImage is passed as the closure.
|
2009-09-12 15:44:18 -07:00
|
|
|
// Always reads everything it gets, even if the data is erroneous.
|
|
|
|
NS_METHOD
|
2015-01-12 01:20:23 -08:00
|
|
|
RasterImage::WriteToSourceBuffer(nsIInputStream* /* unused */,
|
|
|
|
void* aClosure,
|
|
|
|
const char* aFromRawSegment,
|
|
|
|
uint32_t /* unused */,
|
|
|
|
uint32_t aCount,
|
|
|
|
uint32_t* aWriteCount)
|
2009-09-12 15:44:18 -07:00
|
|
|
{
|
2010-08-13 21:09:49 -07:00
|
|
|
// Retrieve the RasterImage
|
2010-08-13 21:09:51 -07:00
|
|
|
RasterImage* image = static_cast<RasterImage*>(aClosure);
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2011-06-08 19:21:53 -07:00
|
|
|
// Copy the source data. Unless we hit OOM, we squelch the return value
|
|
|
|
// here, because returning an error means that ReadSegments stops
|
|
|
|
// reading data, violating our invariant that we read everything we get.
|
|
|
|
// If we hit OOM then we fail and the load is aborted.
|
2015-01-12 01:20:23 -08:00
|
|
|
nsresult rv = image->mSourceBuffer->Append(aFromRawSegment, aCount);
|
2011-06-08 19:21:53 -07:00
|
|
|
if (rv == NS_ERROR_OUT_OF_MEMORY) {
|
|
|
|
image->DoError();
|
|
|
|
return rv;
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// We wrote everything we got
|
2010-08-13 21:09:51 -07:00
|
|
|
*aWriteCount = aCount;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
return NS_OK;
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
2010-08-13 21:09:49 -07:00
|
|
|
|
2011-08-05 06:57:16 -07:00
|
|
|
bool
|
2010-09-07 17:33:02 -07:00
|
|
|
RasterImage::ShouldAnimate()
|
|
|
|
{
|
2013-06-17 13:49:04 -07:00
|
|
|
return ImageResource::ShouldAnimate() && GetNumFrames() >= 2 &&
|
2010-11-17 12:39:23 -08:00
|
|
|
!mAnimationFinished;
|
2010-09-07 17:33:02 -07:00
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
/* readonly attribute uint32_t framesNotified; */
|
2010-09-07 17:34:18 -07:00
|
|
|
#ifdef DEBUG
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
RasterImage::GetFramesNotified(uint32_t *aFramesNotified)
|
2010-09-07 17:34:18 -07:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aFramesNotified);
|
|
|
|
|
|
|
|
*aFramesNotified = mFramesNotified;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
void
|
|
|
|
RasterImage::NotifyProgress(Progress aProgress,
|
|
|
|
const nsIntRect& aInvalidRect /* = nsIntRect() */,
|
|
|
|
uint32_t aFlags /* = DECODE_FLAGS_DEFAULT */)
|
2015-01-11 11:43:32 -08:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
// Ensure that we stay alive long enough to finish notifying.
|
2013-01-28 09:26:36 -08:00
|
|
|
nsRefPtr<RasterImage> image(this);
|
2013-01-18 13:47:18 -08:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
bool wasDefaultFlags = aFlags == DECODE_FLAGS_DEFAULT;
|
2014-11-14 20:10:47 -08:00
|
|
|
Progress progress = aProgress;
|
2015-01-12 01:20:23 -08:00
|
|
|
nsIntRect invalidRect = aInvalidRect;
|
2015-01-11 11:43:32 -08:00
|
|
|
|
2014-12-10 19:35:15 -08:00
|
|
|
if (!invalidRect.IsEmpty() && wasDefaultFlags) {
|
|
|
|
// Update our image container since we're invalidating.
|
|
|
|
UpdateImageContainer();
|
|
|
|
}
|
2014-11-10 12:37:35 -08:00
|
|
|
|
2013-11-26 17:22:44 -08:00
|
|
|
if (mNotifying) {
|
2014-11-14 20:10:47 -08:00
|
|
|
// Accumulate the progress changes. We don't permit recursive notifications
|
2013-11-26 17:22:44 -08:00
|
|
|
// because they cause subtle concurrency bugs, so we'll delay sending out
|
|
|
|
// the notifications until we pop back to the lowest invocation of
|
2015-01-12 01:20:23 -08:00
|
|
|
// NotifyProgress on the stack.
|
2014-11-14 20:10:47 -08:00
|
|
|
mNotifyProgress |= progress;
|
|
|
|
mNotifyInvalidRect.Union(invalidRect);
|
2013-11-26 17:22:44 -08:00
|
|
|
} else {
|
2014-11-14 20:10:47 -08:00
|
|
|
MOZ_ASSERT(mNotifyProgress == NoProgress && mNotifyInvalidRect.IsEmpty(),
|
|
|
|
"Shouldn't have an accumulated change at this point");
|
2013-11-26 17:22:44 -08:00
|
|
|
|
2014-11-14 20:10:47 -08:00
|
|
|
progress = image->mProgressTracker->Difference(progress);
|
2014-11-14 20:10:47 -08:00
|
|
|
|
2014-11-14 20:10:47 -08:00
|
|
|
while (progress != NoProgress || !invalidRect.IsEmpty()) {
|
2013-11-26 17:22:44 -08:00
|
|
|
// Tell the observers what happened.
|
|
|
|
mNotifying = true;
|
2014-11-14 20:10:47 -08:00
|
|
|
image->mProgressTracker->SyncNotifyProgress(progress, invalidRect);
|
2013-11-26 17:22:44 -08:00
|
|
|
mNotifying = false;
|
|
|
|
|
2014-11-14 20:10:47 -08:00
|
|
|
// Gather any progress changes that may have occurred as a result of sending
|
2013-11-26 17:22:44 -08:00
|
|
|
// out the previous notifications. If there were any, we'll send out
|
|
|
|
// notifications for them next.
|
2014-11-14 20:10:47 -08:00
|
|
|
progress = image->mProgressTracker->Difference(mNotifyProgress);
|
|
|
|
mNotifyProgress = NoProgress;
|
|
|
|
|
|
|
|
invalidRect = mNotifyInvalidRect;
|
|
|
|
mNotifyInvalidRect = nsIntRect();
|
2013-11-26 17:22:44 -08:00
|
|
|
}
|
2013-01-31 10:38:24 -08:00
|
|
|
}
|
2015-01-12 01:20:23 -08:00
|
|
|
}
|
2013-02-01 17:06:34 -08:00
|
|
|
|
2015-01-12 01:20:23 -08:00
|
|
|
void
|
|
|
|
RasterImage::FinalizeDecoder(Decoder* aDecoder)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(aDecoder);
|
|
|
|
MOZ_ASSERT(mError || mHasSize || !aDecoder->HasSize(),
|
|
|
|
"Should have handed off size by now");
|
|
|
|
|
|
|
|
// Send out any final notifications.
|
|
|
|
NotifyProgress(aDecoder->TakeProgress(),
|
|
|
|
aDecoder->TakeInvalidRect(),
|
|
|
|
aDecoder->GetDecodeFlags());
|
|
|
|
|
|
|
|
bool wasSize = aDecoder->IsSizeDecode();
|
|
|
|
bool done = aDecoder->GetDecodeDone();
|
|
|
|
|
|
|
|
if (!wasSize && aDecoder->ChunkCount()) {
|
|
|
|
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_CHUNKS,
|
|
|
|
aDecoder->ChunkCount());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (done) {
|
|
|
|
// Do some telemetry if this isn't a size decode.
|
|
|
|
if (!wasSize) {
|
|
|
|
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_TIME,
|
|
|
|
int32_t(aDecoder->DecodeTime().ToMicroseconds()));
|
|
|
|
|
|
|
|
// We record the speed for only some decoders. The rest have
|
|
|
|
// SpeedHistogram return HistogramCount.
|
|
|
|
Telemetry::ID id = aDecoder->SpeedHistogram();
|
|
|
|
if (id < Telemetry::HistogramCount) {
|
|
|
|
int32_t KBps = int32_t(aDecoder->BytesDecoded() /
|
|
|
|
(1024 * aDecoder->DecodeTime().ToSeconds()));
|
|
|
|
Telemetry::Accumulate(id, KBps);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Detect errors.
|
|
|
|
if (aDecoder->HasError() && !aDecoder->WasAborted()) {
|
|
|
|
DoError();
|
|
|
|
} else if (wasSize && !mHasSize) {
|
|
|
|
DoError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we were a size decode and a full decode was requested, now's the time.
|
|
|
|
if (done && wasSize && mWantFullDecode) {
|
|
|
|
mWantFullDecode = false;
|
|
|
|
RequestDecode();
|
|
|
|
}
|
2013-01-18 13:47:18 -08:00
|
|
|
}
|
|
|
|
|
2014-06-27 20:50:26 -07:00
|
|
|
already_AddRefed<imgIContainer>
|
|
|
|
RasterImage::Unwrap()
|
|
|
|
{
|
|
|
|
nsCOMPtr<imgIContainer> self(this);
|
|
|
|
return self.forget();
|
|
|
|
}
|
|
|
|
|
2014-07-28 14:27:39 -07:00
|
|
|
nsIntSize
|
|
|
|
RasterImage::OptimalImageSizeForDest(const gfxSize& aDest, uint32_t aWhichFrame,
|
|
|
|
GraphicsFilter aFilter, uint32_t aFlags)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aDest.width >= 0 || ceil(aDest.width) <= INT32_MAX ||
|
|
|
|
aDest.height >= 0 || ceil(aDest.height) <= INT32_MAX,
|
|
|
|
"Unexpected destination size");
|
|
|
|
|
2014-09-16 16:18:49 -07:00
|
|
|
if (mSize.IsEmpty() || aDest.IsEmpty()) {
|
2014-07-28 14:27:39 -07:00
|
|
|
return nsIntSize(0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIntSize destSize(ceil(aDest.width), ceil(aDest.height));
|
|
|
|
|
2014-09-19 14:53:29 -07:00
|
|
|
if (CanScale(aFilter, destSize, aFlags)) {
|
|
|
|
DrawableFrameRef frameRef =
|
|
|
|
SurfaceCache::Lookup(ImageKey(this),
|
|
|
|
RasterSurfaceKey(destSize.ToIntSize(),
|
2015-01-07 01:40:23 -08:00
|
|
|
DecodeFlags(aFlags),
|
|
|
|
0));
|
2014-09-19 14:53:29 -07:00
|
|
|
|
2015-01-11 19:28:02 -08:00
|
|
|
if (frameRef && frameRef->IsImageComplete()) {
|
2014-07-28 14:27:39 -07:00
|
|
|
return destSize; // We have an existing HQ scale for this size.
|
2014-09-14 23:17:28 -07:00
|
|
|
}
|
2014-09-19 14:53:29 -07:00
|
|
|
if (!frameRef) {
|
|
|
|
// We could HQ scale to this size, but we haven't. Request a scale now.
|
2014-11-26 13:22:10 -08:00
|
|
|
frameRef = LookupFrame(GetRequestedFrameIndex(aWhichFrame),
|
|
|
|
mSize, aFlags);
|
2014-09-19 14:53:29 -07:00
|
|
|
if (frameRef) {
|
|
|
|
RequestScale(frameRef.get(), aFlags, destSize);
|
|
|
|
}
|
2014-09-16 22:30:11 -07:00
|
|
|
}
|
2014-07-28 14:27:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// We either can't HQ scale to this size or the scaled version isn't ready
|
|
|
|
// yet. Use our intrinsic size for now.
|
|
|
|
return mSize;
|
|
|
|
}
|
|
|
|
|
2012-01-06 08:02:27 -08:00
|
|
|
} // namespace image
|
2010-08-13 21:09:49 -07:00
|
|
|
} // namespace mozilla
|