Bug 1034345 (Part 2) - Implement OptimalImageSizeForDest for RasterImage. r=tn

--HG--
extra : rebase_source : 63c58e8df2c992f9550b481530e41938e8672ad1
This commit is contained in:
Seth Fowler 2014-07-28 14:27:39 -07:00
Родитель c03739fc30
Коммит 5f4250d96a
2 изменённых файлов: 79 добавлений и 21 удалений

Просмотреть файл

@ -59,6 +59,7 @@ using namespace gfx;
using namespace layers;
namespace image {
using std::ceil;
// 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)
@ -2586,6 +2587,39 @@ RasterImage::ScalingDone(ScaleRequest* request, ScaleStatus status)
}
}
void
RasterImage::RequestScale(imgFrame* aFrame, gfxSize aScale)
{
// We can't store more than one scaled version of an image right now, so if
// there's more than one instance of this image, bail.
if (mLockCount != 1) {
return;
}
// We also can't scale if we can't lock the image data for this frame.
if (NS_FAILED(aFrame->LockImageData())) {
aFrame->UnlockImageData();
return;
}
// If we have an outstanding request, signal it to stop (if it can).
if (mScaleRequest) {
mScaleRequest->stopped = true;
}
nsRefPtr<ScaleRunner> runner = new ScaleRunner(this, aScale, aFrame);
if (runner->IsOK()) {
if (!sScaleWorkerThread) {
NS_NewNamedThread("Image Scaler", getter_AddRefs(sScaleWorkerThread));
ClearOnShutdown(&sScaleWorkerThread);
}
sScaleWorkerThread->Dispatch(runner, NS_DISPATCH_NORMAL);
}
aFrame->UnlockImageData();
}
bool
RasterImage::DrawWithPreDownscaleIfNeeded(imgFrame *aFrame,
gfxContext *aContext,
@ -2636,27 +2670,8 @@ RasterImage::DrawWithPreDownscaleIfNeeded(imgFrame *aFrame,
// If we're not waiting for exactly this result, and there's only one
// instance of this image on this page, ask for a scale.
if (needScaleReq && mLockCount == 1) {
if (NS_FAILED(frame->LockImageData())) {
frame->UnlockImageData();
return false;
}
// If we have an outstanding request, signal it to stop (if it can).
if (mScaleRequest) {
mScaleRequest->stopped = true;
}
nsRefPtr<ScaleRunner> runner = new ScaleRunner(this, scale, frame);
if (runner->IsOK()) {
if (!sScaleWorkerThread) {
NS_NewNamedThread("Image Scaler", getter_AddRefs(sScaleWorkerThread));
ClearOnShutdown(&sScaleWorkerThread);
}
sScaleWorkerThread->Dispatch(runner, NS_DISPATCH_NORMAL);
}
frame->UnlockImageData();
if (needScaleReq) {
RequestScale(frame, scale);
}
}
@ -3656,5 +3671,45 @@ RasterImage::FrameNeededWorker::Run()
return NS_OK;
}
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");
if (mSize.IsEmpty()) {
return nsIntSize(0, 0);
}
nsIntSize destSize(ceil(aDest.width), ceil(aDest.height));
gfxSize scale(double(destSize.width) / mSize.width,
double(destSize.height) / mSize.height);
if (CanScale(aFilter, scale, aFlags)) {
if (mScaleResult.scale == scale) {
if (mScaleResult.status == SCALE_DONE) {
return destSize; // We have an existing HQ scale for this size.
} else if (mScaleResult.status == SCALE_PENDING) {
return mSize; // We're waiting for exactly this result.
}
}
// If there's only one instance of this image on this page, ask for a scale.
uint32_t frameIndex = aWhichFrame == FRAME_FIRST ? 0
: GetCurrentImgFrameIndex();
imgFrame* frame = GetDrawableImgFrame(frameIndex);
if (frame) {
RequestScale(frame, scale);
}
}
// 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;
}
} // namespace image
} // namespace mozilla

Просмотреть файл

@ -329,6 +329,9 @@ public:
// Decode strategy
private:
// Initiates an HQ scale for the given frame, if possible.
void RequestScale(imgFrame* aFrame, gfxSize aScale);
already_AddRefed<imgStatusTracker> CurrentStatusTracker()
{
mDecodingMonitor.AssertCurrentThreadIn();