diff options
Diffstat (limited to 'image')
-rw-r--r-- | image/Downscaler.cpp | 14 | ||||
-rw-r--r-- | image/DownscalingFilter.h | 14 | ||||
-rw-r--r-- | image/VectorImage.cpp | 22 | ||||
-rw-r--r-- | image/decoders/icon/nsIconURI.cpp | 26 |
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(); |