summaryrefslogtreecommitdiffstats
path: root/image
diff options
context:
space:
mode:
Diffstat (limited to 'image')
-rw-r--r--image/Downscaler.cpp14
-rw-r--r--image/DownscalingFilter.h14
-rw-r--r--image/VectorImage.cpp22
-rw-r--r--image/decoders/icon/nsIconURI.cpp26
4 files changed, 63 insertions, 13 deletions
diff --git a/image/Downscaler.cpp b/image/Downscaler.cpp
index 18f09c596..2ded487a5 100644
--- a/image/Downscaler.cpp
+++ b/image/Downscaler.cpp
@@ -231,6 +231,7 @@ Downscaler::CommitRow()
int32_t inLineToRead = filterOffset + mLinesInBuffer;
MOZ_ASSERT(mCurrentInLine <= inLineToRead, "Reading past end of input");
if (mCurrentInLine == inLineToRead) {
+ MOZ_RELEASE_ASSERT(mLinesInBuffer < mWindowCapacity, "Need more rows than capacity!");
skia::ConvolveHorizontally(mRowBuffer.get(), *mXFilter,
mWindow[mLinesInBuffer++], mHasAlpha,
supports_sse2() || supports_mmi());
@@ -239,7 +240,7 @@ Downscaler::CommitRow()
MOZ_ASSERT(mCurrentOutLine < mTargetSize.height,
"Writing past end of output");
- while (mLinesInBuffer == filterLength) {
+ while (mLinesInBuffer >= filterLength) {
DownscaleInputLine();
if (mCurrentOutLine == mTargetSize.height) {
@@ -340,9 +341,14 @@ Downscaler::DownscaleInputLine()
// Shift the buffer. We're just moving pointers here, so this is cheap.
mLinesInBuffer -= diff;
- mLinesInBuffer = max(mLinesInBuffer, 0);
- for (int32_t i = 0; i < mLinesInBuffer; ++i) {
- swap(mWindow[i], mWindow[filterLength - mLinesInBuffer + i]);
+ mLinesInBuffer = min(max(mLinesInBuffer, 0), mWindowCapacity);
+
+ // If we already have enough rows to satisfy the filter, there is no need
+ // to swap as we won't be writing more before the next convolution.
+ if (filterLength > mLinesInBuffer) {
+ for (int32_t i = 0; i < mLinesInBuffer; ++i) {
+ swap(mWindow[i], mWindow[filterLength - mLinesInBuffer + i]);
+ }
}
}
diff --git a/image/DownscalingFilter.h b/image/DownscalingFilter.h
index 6b0d3b26b..1485b85c2 100644
--- a/image/DownscalingFilter.h
+++ b/image/DownscalingFilter.h
@@ -246,6 +246,7 @@ protected:
int32_t inputRowToRead = filterOffset + mRowsInWindow;
MOZ_ASSERT(mInputRow <= inputRowToRead, "Reading past end of input");
if (mInputRow == inputRowToRead) {
+ MOZ_RELEASE_ASSERT(mRowsInWindow < mWindowCapacity, "Need more rows than capacity!");
skia::ConvolveHorizontally(mRowBuffer.get(), *mXFilter,
mWindow[mRowsInWindow++], mHasAlpha,
supports_sse2() || supports_mmi());
@@ -254,7 +255,7 @@ protected:
MOZ_ASSERT(mOutputRow < mNext.InputSize().height,
"Writing past end of output");
- while (mRowsInWindow == filterLength) {
+ while (mRowsInWindow >= filterLength) {
DownscaleInputRow();
if (mOutputRow == mNext.InputSize().height) {
@@ -330,9 +331,14 @@ private:
// Shift the buffer. We're just moving pointers here, so this is cheap.
mRowsInWindow -= diff;
- mRowsInWindow = std::max(mRowsInWindow, 0);
- for (int32_t i = 0; i < mRowsInWindow; ++i) {
- std::swap(mWindow[i], mWindow[filterLength - mRowsInWindow + i]);
+ mRowsInWindow = std::min(std::max(mRowsInWindow, 0), mWindowCapacity);
+
+ // If we already have enough rows to satisfy the filter, there is no need
+ // to swap as we won't be writing more before the next convolution.
+ if (filterLength > mRowsInWindow) {
+ for (int32_t i = 0; i < mRowsInWindow; ++i) {
+ std::swap(mWindow[i], mWindow[filterLength - mRowsInWindow + i]);
+ }
}
}
diff --git a/image/VectorImage.cpp b/image/VectorImage.cpp
index fd970e179..1e59b13fa 100644
--- a/image/VectorImage.cpp
+++ b/image/VectorImage.cpp
@@ -9,6 +9,7 @@
#include "gfxContext.h"
#include "gfxDrawable.h"
#include "gfxPlatform.h"
+#include "gfxPrefs.h" // for surface cache size
#include "gfxUtils.h"
#include "imgFrame.h"
#include "mozilla/AutoRestore.h"
@@ -931,11 +932,14 @@ VectorImage::CreateSurfaceAndShow(const SVGDrawingParameters& aParams, BackendTy
RefPtr<gfxDrawable> svgDrawable =
new gfxCallbackDrawable(cb, aParams.size);
- // We take an early exit without using the surface cache if
- // x or y > maxDimension, because for vector images this can cause bad perf
- // issues if large sizes are scaled repeatedly (a rather common scenario)
- // that can quickly exhaust the cache.
- int32_t maxDimension = 3000;
+ // We take an early exit without using the surface cache if too large,
+ // because for vector images this can cause bad perf issues if large sizes
+ // are scaled repeatedly (a rather common scenario) that can quickly exhaust
+ // the cache.
+ // Similar to max image size calculations, this has a max cap and size check.
+ // max cap = 8000 (pixels); size check = 5% of cache
+ int32_t maxDimension = 8000;
+ int32_t maxCacheElemSize = (gfxPrefs::ImageMemSurfaceCacheMaxSizeKB() * 1024) / 20;
bool bypassCache = bool(aParams.flags & FLAG_BYPASS_SURFACE_CACHE) ||
// Refuse to cache animated images:
@@ -946,6 +950,14 @@ VectorImage::CreateSurfaceAndShow(const SVGDrawingParameters& aParams, BackendTy
// Image x or y is larger than our cache cap:
aParams.size.width > maxDimension ||
aParams.size.height > maxDimension;
+ if (!bypassCache) {
+ // This is separated out to make sure width and height are sane at this point
+ // and the result can't overflow. Note: keep maxDimension low enough so that
+ // (maxDimension)^2 x 4 < INT32_MAX.
+ // Assuming surface size for any rendered vector image is RGBA, so 4Bpp.
+ bypassCache = (aParams.size.width * aParams.size.height * 4) > maxCacheElemSize;
+ }
+
if (bypassCache) {
return Show(svgDrawable, aParams);
}
diff --git a/image/decoders/icon/nsIconURI.cpp b/image/decoders/icon/nsIconURI.cpp
index 2c2788c8f..632a733fe 100644
--- a/image/decoders/icon/nsIconURI.cpp
+++ b/image/decoders/icon/nsIconURI.cpp
@@ -372,6 +372,32 @@ nsMozIconURI::SetPath(const nsACString& aPath)
}
NS_IMETHODIMP
+nsMozIconURI::GetFilePath(nsACString& aFilePath)
+{
+ aFilePath.Truncate();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMozIconURI::SetFilePath(const nsACString& aFilePath)
+{
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsMozIconURI::GetQuery(nsACString& aQuery)
+{
+ aQuery.Truncate();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMozIconURI::SetQuery(const nsACString& aQuery)
+{
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
nsMozIconURI::GetRef(nsACString& aRef)
{
aRef.Truncate();