зеркало из https://github.com/mozilla/gecko-dev.git
Bug 846852 - Preallocate the RasterImage source data array when loading from file://. r=seth
--HG-- extra : rebase_source : 9bf2cc014d97f245ae063f65ab4aa6743c3194f2
This commit is contained in:
Родитель
63ad0ad95e
Коммит
09702bcf62
|
@ -10,6 +10,8 @@
|
|||
#include "mozilla/Likely.h"
|
||||
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIFileChannel.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsSimpleURI.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsIURI.h"
|
||||
|
@ -128,6 +130,49 @@ ImageFactory::CreateAnonymousImage(const nsCString& aMimeType)
|
|||
return newImage.forget();
|
||||
}
|
||||
|
||||
int32_t
|
||||
SaturateToInt32(int64_t val)
|
||||
{
|
||||
if (val > INT_MAX)
|
||||
return INT_MAX;
|
||||
if (val < INT_MIN)
|
||||
return INT_MIN;
|
||||
|
||||
return static_cast<int32_t>(val);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetContentSize(nsIRequest* aRequest)
|
||||
{
|
||||
// Use content-length as a size hint for http channels.
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest));
|
||||
if (httpChannel) {
|
||||
nsAutoCString contentLength;
|
||||
nsresult rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-length"),
|
||||
contentLength);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return std::max(contentLength.ToInteger(&rv), 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the file size as a size hint for file channels.
|
||||
nsCOMPtr<nsIFileChannel> fileChannel(do_QueryInterface(aRequest));
|
||||
if (fileChannel) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
nsresult rv = fileChannel->GetFile(getter_AddRefs(file));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
int64_t filesize;
|
||||
rv = file->GetFileSize(&filesize);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return std::max(SaturateToInt32(filesize), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback - neither http nor file. We'll use dynamic allocation.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Image>
|
||||
ImageFactory::CreateRasterImage(nsIRequest* aRequest,
|
||||
imgStatusTracker* aStatusTracker,
|
||||
|
@ -145,20 +190,12 @@ ImageFactory::CreateRasterImage(nsIRequest* aRequest,
|
|||
|
||||
newImage->SetInnerWindowID(aInnerWindowId);
|
||||
|
||||
// Use content-length as a size hint for http channels.
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest));
|
||||
if (httpChannel) {
|
||||
nsAutoCString contentLength;
|
||||
rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-length"),
|
||||
contentLength);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
int32_t len = contentLength.ToInteger(&rv);
|
||||
uint32_t len = GetContentSize(aRequest);
|
||||
|
||||
// Pass anything usable on so that the RasterImage can preallocate
|
||||
// its source buffer.
|
||||
if (len > 0) {
|
||||
uint32_t sizeHint = (uint32_t) len;
|
||||
sizeHint = std::min<uint32_t>(sizeHint, 20000000); // Bound by something reasonable
|
||||
uint32_t sizeHint = std::min<uint32_t>(len, 20000000); // Bound by something reasonable
|
||||
rv = newImage->SetSourceSizeHint(sizeHint);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Flush memory, try to get some back, and try again.
|
||||
|
@ -170,8 +207,6 @@ ImageFactory::CreateRasterImage(nsIRequest* aRequest,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newImage.forget();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче