diff -x .svn -x CVS -x testing -b -B -r mozilla/gfx/public/nsIImage.h dev/mozilla/gfx/public/nsIImage.h 72a73 > #define nsImageUpdateFlags_ImageIncomplete 0x4 diff -x .svn -x CVS -x testing -b -B -r mozilla/gfx/src/thebes/nsThebesImage.cpp dev/mozilla/gfx/src/thebes/nsThebesImage.cpp 23a24 > * Francis Robichaud 50a52,56 > #ifdef XP_UNIX > static gfxFloat gImageThreshold = 0.5; > #include "nsIPrefBranch.h" > #include "nsIPrefService.h" > #endif 67c73 < mImageComplete(PR_FALSE), --- > mImageIncomplete(PR_FALSE), 72,73c78,79 < static PRBool hasCheckedOptimize = PR_FALSE; < if (!hasCheckedOptimize) { --- > static PRBool hasLoadedStatic = PR_FALSE; > if (!hasLoadedStatic) { 77c83,95 < hasCheckedOptimize = PR_TRUE; --- > #ifdef XP_UNIX > nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); > if (prefs) { > PRInt32 threshold; > nsresult rv = prefs->GetIntPref("browser.gdk_image_interpolation_threshold", &threshold); > if (NS_SUCCEEDED(rv)) { > // Store a value between 1 and 100 > threshold = (threshold > 0 || threshold <= 100) ? threshold: NS_lroundf(gImageThreshold*100); > gImageThreshold = gfxFloat(threshold) / 100; > } > } > #endif > hasLoadedStatic = PR_TRUE; 82a101,103 > /*#ifdef XP_UNIX > mTinySurf = nsnull; > #endif*/ 213a235 > mImageIncomplete = aFlags & nsImageUpdateFlags_ImageIncomplete; 224,226c246 < if (!mImageComplete) < mImageComplete = (mDecoded == nsRect(0, 0, mWidth, mHeight)); < return mImageComplete; --- > return (mDecoded == nsRect(0, 0, mWidth, mHeight)) && !mImageIncomplete; 333a354 > #ifndef XP_UNIX 335a357,358 > #endif > 337a361 > #ifndef XP_UNIX 338a363 > #endif 489a515,597 > #ifdef XP_UNIX > // We optimize the image surface to it's visible size and use scaling algorithms > // to reduce X memory consumption, bug 395260. We bypass 1x1 rectangles to avoid useless operations. > if (destRect.size != gfxSize(1.0, 1.0) && > (mWidth > (destRect.size.width / gImageThreshold) || > mHeight > (destRect.size.height / gImageThreshold) || > xscale < (1.0 * gImageThreshold) || yscale < (1.0 * gImageThreshold) || > xscale > (1.0 / gImageThreshold) || yscale > (1.0 / gImageThreshold))) { > > gfxIntSize tinySize(NS_lroundf(destRect.size.width), NS_lroundf(destRect.size.height)); > GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(mImageSurface->Data(), GDK_COLORSPACE_RGB, > PR_TRUE, 8, mWidth, mHeight, > mStride, nsnull, nsnull); > if (!pixbuf) > return NS_ERROR_FAILURE; > > GdkPixbuf* tinyPix = pixbuf; > // XXX Cairo should have it's own scaling algorithm for image surfaces and use Sun's mediaLib > if (xscale != 1.0 || yscale != 1.0) { > // Scales the pixbuf, R and B channels are inverted but this should not cause any issue. > tinyPix = gdk_pixbuf_scale_simple(pixbuf, PRInt32(NS_ceilf(mWidth*xscale)), PRInt32(NS_ceilf(mHeight*yscale)), GDK_INTERP_BILINEAR); > if (!tinyPix) > return NS_ERROR_FAILURE; > g_object_unref(pixbuf); > } > > if (subimageRect.size.width >= srcRect.size.width || subimageRect.size.height >= srcRect.size.height) { > // We need to round the visible portion of the image for GDK > GdkPixbuf* tmpPix = gdk_pixbuf_new_subpixbuf(tinyPix, > PRInt32(NS_ceilf(srcRect.pos.x*xscale)), > PRInt32(NS_ceilf(srcRect.pos.y*yscale)), > srcRect.size.width*xscale > 0.0 ? PRInt32(NS_floorf(srcRect.size.width*xscale)) : 1, > srcRect.size.height*yscale > 0.0 ? PRInt32(NS_floorf(srcRect.size.height*yscale)): 1); > if (!tmpPix) > return NS_ERROR_FAILURE; > g_object_unref(tinyPix); > tinyPix = tmpPix; > } > > unsigned char* pixels = gdk_pixbuf_get_pixels(tinyPix); > PRInt32 stride = gdk_pixbuf_get_rowstride(tinyPix); > > // We generate a new tiny surface > nsRefPtr tinySurf = new gfxImageSurface(tinySize, mFormat); > > for (int i=0; i < tinySize.height; i++) { > unsigned char* src = pixels + stride*i; > memcpy(tinySurf->Data() + tinySurf->Stride()*i, src, tinySurf->Stride()); > } > > nsRefPtr tmpSurf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(tinySize, mFormat); > if (!tmpSurf || tmpSurf->CairoStatus() != 0) > return NS_ERROR_FAILURE; > > gfxContext tmpCtx(tmpSurf); > tmpCtx.SetOperator(gfxContext::OPERATOR_SOURCE); > tmpCtx.SetSource(tinySurf); > tmpCtx.Paint(); > > // Use this tiny surface for further rendering > pat = new gfxPattern(tmpSurf); > // Release the gdk objects without affecting the actual image data > g_object_unref(tinyPix); > > // Disables further scaling operation to avoid bug 364968 explained below. > xscale = yscale = 1.0; > > // Origin could be different than (0,0) > subimageRect.pos.x -= srcRect.pos.x; > srcRect.pos.x -= srcRect.pos.x; > subimageRect.pos.y -= srcRect.pos.y; > srcRect.pos.y -= srcRect.pos.y; > > } else if (!mOptSurface) { > // Sends pixmaps to X > if (GetIsImageComplete()) { > mOptSurface = gfxPlatform::GetPlatform()->OptimizeImage(mImageSurface, mFormat); > } else { > gfxPlatform::GetPlatform()->OptimizeImage(mImageSurface, mFormat); > } > } > #endif > 497a606 > if (!pat) diff -x .svn -x CVS -x testing -b -B -r mozilla/gfx/src/thebes/nsThebesImage.h dev/mozilla/gfx/src/thebes/nsThebesImage.h 43c43,47 < --- > #if defined(XP_UNIX) > #include > #include > #include "nsIServiceManager.h" > #endif 163c167 < PRPackedBool mImageComplete; --- > PRPackedBool mImageIncomplete; diff -x .svn -x CVS -x testing -b -B -r mozilla/modules/libpr0n/decoders/png/nsPNGDecoder.cpp dev/mozilla/modules/libpr0n/decoders/png/nsPNGDecoder.cpp 184d183 < if (numFrames > 1) { 192a192 > if (numFrames > 1) { 799c799 < img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r); --- > img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged | nsImageUpdateFlags_ImageIncomplete, &r); diff -x .svn -x CVS -x testing -b -B -r mozilla/modules/libpref/src/init/all.js dev/mozilla/modules/libpref/src/init/all.js 104a105,107 > #ifdef XP_UNIX > pref("browser.gdk_image_interpolation_threshold", 50); > #endif