diff --git a/gfx/src/mac/nsDeviceContextMac.cpp b/gfx/src/mac/nsDeviceContextMac.cpp index f66a6c3bdb85..43f1c0c717b3 100644 --- a/gfx/src/mac/nsDeviceContextMac.cpp +++ b/gfx/src/mac/nsDeviceContextMac.cpp @@ -437,7 +437,7 @@ nsresult nsDeviceContextMac :: CheckFontExistence(const nsString& aFontName) return NS_OK; } -nsresult nsDeviceContextMac :: CreateILColorSpace(IL_ColorSpace*& aColorSpace) +nsresult nsDeviceContextMac :: GetILColorSpace(IL_ColorSpace*& aColorSpace) { return nsnull; } diff --git a/gfx/src/nsDeviceContext.cpp b/gfx/src/nsDeviceContext.cpp index 686d40566335..44c599f62a8e 100644 --- a/gfx/src/nsDeviceContext.cpp +++ b/gfx/src/nsDeviceContext.cpp @@ -47,6 +47,7 @@ DeviceContextImpl :: DeviceContextImpl() mIcons[i] = nsnull; } mFontAliasTable = nsnull; + mColorSpace = nsnull; } static PRBool DeleteValue(nsHashKey* aKey, void* aValue) @@ -76,6 +77,10 @@ DeviceContextImpl :: ~DeviceContextImpl() mFontAliasTable->Enumerate(DeleteValue); delete mFontAliasTable; } + + if (nsnull != mColorSpace) { + IL_ReleaseColorSpace(mColorSpace); + } } nsresult DeviceContextImpl :: Init(nsNativeWidget aWidget) @@ -258,7 +263,7 @@ nsresult DeviceContextImpl::CreateIconILGroupContext() // Initialize the image group context. IL_ColorSpace* colorSpace; - result = CreateILColorSpace(colorSpace); + result = GetILColorSpace(colorSpace); if (NS_FAILED(result)) { NS_RELEASE(renderer); IL_DestroyGroupContext(mIconImageGroup); @@ -492,24 +497,29 @@ NS_IMETHODIMP DeviceContextImpl::GetLocalFontName(const nsString& aFaceName, nsS return result; } - -NS_IMETHODIMP DeviceContextImpl::CreateILColorSpace(IL_ColorSpace*& aColorSpace) +NS_IMETHODIMP DeviceContextImpl::GetILColorSpace(IL_ColorSpace*& aColorSpace) { - IL_RGBBits colorRGBBits; - - // Default is to create a 24-bit color space - colorRGBBits.red_shift = 16; - colorRGBBits.red_bits = 8; - colorRGBBits.green_shift = 8; - colorRGBBits.green_bits = 8; - colorRGBBits.blue_shift = 0; - colorRGBBits.blue_bits = 8; - - aColorSpace = IL_CreateTrueColorSpace(&colorRGBBits, 24); - if (nsnull == aColorSpace) { - return NS_ERROR_OUT_OF_MEMORY; + if (nsnull == mColorSpace) { + IL_RGBBits colorRGBBits; + + // Default is to create a 24-bit color space + colorRGBBits.red_shift = 16; + colorRGBBits.red_bits = 8; + colorRGBBits.green_shift = 8; + colorRGBBits.green_bits = 8; + colorRGBBits.blue_shift = 0; + colorRGBBits.blue_bits = 8; + + mColorSpace = IL_CreateTrueColorSpace(&colorRGBBits, 24); + if (nsnull == mColorSpace) { + aColorSpace = nsnull; + return NS_ERROR_OUT_OF_MEMORY; + } } + NS_POSTCONDITION(nsnull != mColorSpace, "null color space"); + aColorSpace = mColorSpace; + IL_AddRefToColorSpace(aColorSpace); return NS_OK; } diff --git a/gfx/src/nsDeviceContext.h b/gfx/src/nsDeviceContext.h index 7ad41452021f..15c4bec843b8 100644 --- a/gfx/src/nsDeviceContext.h +++ b/gfx/src/nsDeviceContext.h @@ -70,7 +70,7 @@ public: NS_IMETHOD GetDepth(PRUint32& aDepth); - NS_IMETHOD CreateILColorSpace(IL_ColorSpace*& aColorSpace); + NS_IMETHOD GetILColorSpace(IL_ColorSpace*& aColorSpace); protected: virtual ~DeviceContextImpl(); @@ -95,6 +95,7 @@ protected: IL_GroupContext* mIconImageGroup; nsIImageRequest* mIcons[NS_NUMBER_OF_ICONS]; nsHashtable* mFontAliasTable; + IL_ColorSpace* mColorSpace; }; #endif /* nsDeviceContext_h___ */ diff --git a/gfx/src/nsIDeviceContext.h b/gfx/src/nsIDeviceContext.h index c5153ecb8e7e..7b1f1c1959f9 100644 --- a/gfx/src/nsIDeviceContext.h +++ b/gfx/src/nsIDeviceContext.h @@ -129,10 +129,12 @@ public: NS_IMETHOD GetDepth(PRUint32& aDepth) = 0; /** - * Create an image lib color space that's appropriate for this rendering - * context + * Return the image lib color space that's appropriate for this rendering + * context. + * + * You must call IL_ReleaseColorSpace() when you're done using the color space. */ - NS_IMETHOD CreateILColorSpace(IL_ColorSpace*& aColorSpace) = 0; + NS_IMETHOD GetILColorSpace(IL_ColorSpace*& aColorSpace) = 0; }; #endif /* nsIDeviceContext_h___ */ diff --git a/gfx/src/nsImageGroup.cpp b/gfx/src/nsImageGroup.cpp index 7d31be52b8c1..29bc4e45758b 100644 --- a/gfx/src/nsImageGroup.cpp +++ b/gfx/src/nsImageGroup.cpp @@ -71,7 +71,6 @@ private: IL_GroupContext *mGroupContext; nsVoidArray *mObservers; nsIDeviceContext *mDeviceContext; - IL_ColorSpace *mColorSpace; ilINetContext* mNetContext; }; @@ -103,10 +102,6 @@ ImageGroupImpl::~ImageGroupImpl() IL_DestroyGroupContext(mGroupContext); } - if (mColorSpace != nsnull) { - IL_ReleaseColorSpace(mColorSpace); - } - NS_IF_RELEASE(mManager); NS_IF_RELEASE(mNetContext); } @@ -137,20 +132,22 @@ ImageGroupImpl::Init(nsIDeviceContext *aDeviceContext) mDeviceContext = aDeviceContext; NS_ADDREF(mDeviceContext); - // Ask the device context to create a color space. - // XXX We should ask the device context to get its color space - // rather than having it create a color space for us... - mDeviceContext->CreateILColorSpace(mColorSpace); + // Get color space to use for this device context. + IL_ColorSpace* colorSpace; + + mDeviceContext->GetILColorSpace(colorSpace); // Set the image group context display mode IL_DisplayData displayData; displayData.dither_mode = IL_Auto; - displayData.color_space = mColorSpace; + displayData.color_space = colorSpace; displayData.progressive_display = PR_TRUE; IL_SetDisplayMode(mGroupContext, IL_COLOR_SPACE | IL_PROGRESSIVE_DISPLAY | IL_DITHER_MODE, &displayData); + // Release the color space + IL_ReleaseColorSpace(colorSpace); return NS_OK; } diff --git a/gfx/src/nsImageRenderer.cpp b/gfx/src/nsImageRenderer.cpp index 35ca2fe6672e..9c79200ed45b 100644 --- a/gfx/src/nsImageRenderer.cpp +++ b/gfx/src/nsImageRenderer.cpp @@ -29,234 +29,172 @@ static NS_DEFINE_IID(kIImageRendererIID, IL_IIMAGERENDERER_IID); class ImageRendererImpl : public ilIImageRenderer { public: - static IL_ColorSpace *sPseudoColorSpace; - ImageRendererImpl(); - ~ImageRendererImpl(); NS_DECL_ISUPPORTS virtual void NewPixmap(void* aDisplayContext, - PRInt32 aWidth, PRInt32 aHeight, - IL_Pixmap* aImage, IL_Pixmap* aMask); + PRInt32 aWidth, PRInt32 aHeight, + IL_Pixmap* aImage, IL_Pixmap* aMask); virtual void UpdatePixmap(void* aDisplayContext, - IL_Pixmap* aImage, - PRInt32 aXOffset, PRInt32 aYOffset, - PRInt32 aWidth, PRInt32 aHeight); + IL_Pixmap* aImage, + PRInt32 aXOffset, PRInt32 aYOffset, + PRInt32 aWidth, PRInt32 aHeight); virtual void ControlPixmapBits(void* aDisplayContext, - IL_Pixmap* aImage, PRUint32 aControlMsg); + IL_Pixmap* aImage, PRUint32 aControlMsg); virtual void DestroyPixmap(void* aDisplayContext, IL_Pixmap* aImage); virtual void DisplayPixmap(void* aDisplayContext, - IL_Pixmap* aImage, IL_Pixmap* aMask, - PRInt32 aX, PRInt32 aY, - PRInt32 aXOffset, PRInt32 aYOffset, - PRInt32 aWidth, PRInt32 aHeight); + IL_Pixmap* aImage, IL_Pixmap* aMask, + PRInt32 aX, PRInt32 aY, + PRInt32 aXOffset, PRInt32 aYOffset, + PRInt32 aWidth, PRInt32 aHeight); virtual void DisplayIcon(void* aDisplayContext, - PRInt32 aX, PRInt32 aY, PRUint32 aIconNumber); + PRInt32 aX, PRInt32 aY, PRUint32 aIconNumber); virtual void GetIconDimensions(void* aDisplayContext, - PRInt32 *aWidthPtr, PRInt32 *aHeightPtr, - PRUint32 aIconNumber); + PRInt32 *aWidthPtr, PRInt32 *aHeightPtr, + PRUint32 aIconNumber); }; -IL_ColorSpace *ImageRendererImpl::sPseudoColorSpace = nsnull; - ImageRendererImpl::ImageRendererImpl() { NS_INIT_REFCNT(); } -ImageRendererImpl::~ImageRendererImpl() -{ -} - NS_IMPL_ISUPPORTS(ImageRendererImpl, kIImageRendererIID) - void ImageRendererImpl::NewPixmap(void* aDisplayContext, - PRInt32 aWidth, PRInt32 aHeight, - IL_Pixmap* aImage, IL_Pixmap* aMask) + PRInt32 aWidth, PRInt32 aHeight, + IL_Pixmap* aImage, IL_Pixmap* aMask) { - nsIDeviceContext *dc = (nsIDeviceContext *)aDisplayContext; - nsIImage *img; - nsresult rv; + nsIDeviceContext *dc = (nsIDeviceContext *)aDisplayContext; + nsIImage *img; + nsresult rv; - static NS_DEFINE_IID(kImageCID, NS_IMAGE_CID); - static NS_DEFINE_IID(kImageIID, NS_IIMAGE_IID); + static NS_DEFINE_IID(kImageCID, NS_IMAGE_CID); + static NS_DEFINE_IID(kImageIID, NS_IIMAGE_IID); - rv = NSRepository::CreateInstance(kImageCID, nsnull, kImageIID, (void **)&img); - - if (NS_OK != rv) - return; - - PRInt32 depth; - if (aImage->header.color_space->pixmap_depth == 8) { - depth = 8; - } - else { - depth = 24; - } - - // XXX When the other platforms implement GetDepth() then remove the - // XP_WIN ifdef -#ifdef XP_WIN - PRUint32 deviceDepth; - dc->GetDepth(deviceDepth); - - if ((8 == depth) && (deviceDepth > (PRUint32)depth)) { - // Don't force dithering to the color cube... - depth = 24; + // Create a new image object + rv = NSRepository::CreateInstance(kImageCID, nsnull, kImageIID, (void **)&img); + if (NS_OK != rv) { + // XXX What about error handling? + return; } -#endif - img->Init(aWidth, aHeight, depth, - (aMask == nsnull) ? nsMaskRequirements_kNoMask : - nsMaskRequirements_kNeeds1Bit); + // Have the image match the depth and color space associated with the + // device. + // XXX We probably don't want to do that for monomchrome images (e.g., XBM) + // or one-bit deep GIF images. + PRInt32 depth; + IL_ColorSpace *colorSpace; - aImage->bits = img->GetBits(); - aImage->client_data = img; - // We don't need to add a reference here, because we're already holding - // a reference, because of the call above to the repository to create the - // nsIImage* - aImage->header.width = aWidth; - aImage->header.height = aHeight; - aImage->header.widthBytes = img->GetLineStride(); + dc->GetILColorSpace(colorSpace); + depth = colorSpace->pixmap_depth; - if (aMask) { - aMask->bits = img->GetAlphaBits(); - aMask->client_data = img; - // Make sure you add another reference here, because when the mask's - // pixmap is destroyed the reference will be released - NS_ADDREF(img); - aMask->header.width = aWidth; - aMask->header.height = aHeight; + // Initialize the image object + img->Init(aWidth, aHeight, depth, (aMask == nsnull) ? nsMaskRequirements_kNoMask : + nsMaskRequirements_kNeeds1Bit); + + // Update the pixmap image and mask information + aImage->bits = img->GetBits(); + aImage->client_data = img; // we don't need to add a ref here, because there's + // already one from the call to create the image object + aImage->header.width = aWidth; + aImage->header.height = aHeight; + aImage->header.widthBytes = img->GetLineStride(); + + if (aMask) { + aMask->bits = img->GetAlphaBits(); + aMask->client_data = img; + // We must add another reference here, because when the mask's pixmap is + // destroyed it will release a reference + NS_ADDREF(img); + aMask->header.width = aWidth; + aMask->header.height = aHeight; + } + + // Replace the existing color space with the color space associated + // with the device. + IL_ReleaseColorSpace(aImage->header.color_space); + aImage->header.color_space = colorSpace; + + // XXX Why do we do this on a per-image basis? + if (8 == depth) { + IL_ColorMap *cmap = &colorSpace->cmap; + nsColorMap *nscmap = img->GetColorMap(); + PRUint8 *mapptr = nscmap->Index; + int i; + + for (i=0; i < cmap->num_colors; i++) { + *mapptr++ = cmap->map[i].red; + *mapptr++ = cmap->map[i].green; + *mapptr++ = cmap->map[i].blue; } - if (8 == depth) { - IL_ColorMap *cmap; - if (sPseudoColorSpace == nsnull) { -#ifdef XP_WIN - // This needs to match the logical palette - // XXX Clean this up to use the one and only color space - // the device manager should hold... - IL_RGB reserved[10]; - memset(reserved, 0, sizeof(reserved)); - cmap = IL_NewCubeColorMap(reserved, 10, 216 + 10); -#else - cmap = IL_NewCubeColorMap(nsnull, 0, 216); -#endif - - if (cmap != nsnull) { - sPseudoColorSpace = IL_CreatePseudoColorSpace(cmap, 8, 8); + img->ImageUpdated(dc, nsImageUpdateFlags_kColorMapChanged, nsnull); - if (sPseudoColorSpace == nsnull) { - IL_DestroyColorMap(cmap); - - // XXX We should do something here - return; - } - } - else { - // XXX We should do something here - return; - } - } - IL_AddRefToColorSpace(sPseudoColorSpace); - IL_ReleaseColorSpace(aImage->header.color_space); - aImage->header.color_space = sPseudoColorSpace; - - cmap = &sPseudoColorSpace->cmap; - nsColorMap *nscmap = img->GetColorMap(); - PRUint8 *mapptr = nscmap->Index; - int i; - - for (i=0; i < cmap->num_colors; i++) { - *mapptr++ = cmap->map[i].red; - *mapptr++ = cmap->map[i].green; - *mapptr++ = cmap->map[i].blue; - } - - img->ImageUpdated(dc, nsImageUpdateFlags_kColorMapChanged, nsnull); - - if (aImage->header.transparent_pixel) { - PRUint8 red, green, blue; - PRUint8 *lookup_table = (PRUint8 *)aImage->header.color_space->cmap.table; - red = aImage->header.transparent_pixel->red; - green = aImage->header.transparent_pixel->green; - blue = aImage->header.transparent_pixel->blue; - aImage->header.transparent_pixel->index = - lookup_table[((red >> 3) << 10) | - ((green >> 3) << 5) | - (blue >> 3)]; - } - } - else { - IL_RGBBits colorRGBBits; - IL_ColorSpace *colorSpace; - - // XXX We shouldn't be creating a new color space for pixmap. Change it - // to ask the device context for its color space - colorRGBBits.red_shift = 16; - colorRGBBits.red_bits = 8; - colorRGBBits.green_shift = 8; - colorRGBBits.green_bits = 8; - colorRGBBits.blue_shift = 0; - colorRGBBits.blue_bits = 8; - colorSpace = IL_CreateTrueColorSpace(&colorRGBBits, 24); - IL_ReleaseColorSpace(aImage->header.color_space); - aImage->header.color_space = colorSpace; + if (aImage->header.transparent_pixel) { + PRUint8 red, green, blue; + PRUint8 *lookup_table = (PRUint8 *)aImage->header.color_space->cmap.table; + red = aImage->header.transparent_pixel->red; + green = aImage->header.transparent_pixel->green; + blue = aImage->header.transparent_pixel->blue; + aImage->header.transparent_pixel->index = lookup_table[((red >> 3) << 10) | + ((green >> 3) << 5) | + (blue >> 3)]; } + } } void ImageRendererImpl::UpdatePixmap(void* aDisplayContext, - IL_Pixmap* aImage, - PRInt32 aXOffset, PRInt32 aYOffset, - PRInt32 aWidth, PRInt32 aHeight) + IL_Pixmap* aImage, + PRInt32 aXOffset, PRInt32 aYOffset, + PRInt32 aWidth, PRInt32 aHeight) { - nsIDeviceContext *dc = (nsIDeviceContext *)aDisplayContext; - nsIImage *img = (nsIImage *)aImage->client_data; - nsRect drect(aXOffset, aYOffset, aWidth, aHeight); + nsIDeviceContext *dc = (nsIDeviceContext *)aDisplayContext; + nsIImage *img = (nsIImage *)aImage->client_data; + nsRect drect(aXOffset, aYOffset, aWidth, aHeight); - img->ImageUpdated(dc, nsImageUpdateFlags_kBitsChanged, &drect); + img->ImageUpdated(dc, nsImageUpdateFlags_kBitsChanged, &drect); } void ImageRendererImpl::ControlPixmapBits(void* aDisplayContext, - IL_Pixmap* aImage, PRUint32 aControlMsg) + IL_Pixmap* aImage, PRUint32 aControlMsg) { - nsIDeviceContext *dc = (nsIDeviceContext *)aDisplayContext; - nsIImage *img = (nsIImage *)aImage->client_data; + nsIDeviceContext *dc = (nsIDeviceContext *)aDisplayContext; + nsIImage *img = (nsIImage *)aImage->client_data; - if (aControlMsg == IL_RELEASE_BITS) { - img->Optimize(dc); - } + if (aControlMsg == IL_RELEASE_BITS) { + img->Optimize(dc); + } } void ImageRendererImpl::DestroyPixmap(void* aDisplayContext, IL_Pixmap* aImage) { - nsIDeviceContext *dc = (nsIDeviceContext *)aDisplayContext; - nsIImage *img = (nsIImage *)aImage->client_data; + nsIDeviceContext *dc = (nsIDeviceContext *)aDisplayContext; + nsIImage *img = (nsIImage *)aImage->client_data; - aImage->client_data = nsnull; - if (img) { - NS_RELEASE(img); - } + aImage->client_data = nsnull; + if (img) { + NS_RELEASE(img); + } } void ImageRendererImpl::DisplayPixmap(void* aDisplayContext, - IL_Pixmap* aImage, IL_Pixmap* aMask, - PRInt32 aX, PRInt32 aY, - PRInt32 aXOffset, PRInt32 aYOffset, - PRInt32 aWidth, PRInt32 aHeight) + IL_Pixmap* aImage, IL_Pixmap* aMask, + PRInt32 aX, PRInt32 aY, + PRInt32 aXOffset, PRInt32 aYOffset, + PRInt32 aWidth, PRInt32 aHeight) { // Image library doesn't drive the display process. // XXX Why is this part of the API? @@ -264,15 +202,15 @@ ImageRendererImpl::DisplayPixmap(void* aDisplayContext, void ImageRendererImpl::DisplayIcon(void* aDisplayContext, - PRInt32 aX, PRInt32 aY, PRUint32 aIconNumber) + PRInt32 aX, PRInt32 aY, PRUint32 aIconNumber) { // XXX Why is this part of the API? } void ImageRendererImpl::GetIconDimensions(void* aDisplayContext, - PRInt32 *aWidthPtr, PRInt32 *aHeightPtr, - PRUint32 aIconNumber) + PRInt32 *aWidthPtr, PRInt32 *aHeightPtr, + PRUint32 aIconNumber) { // XXX Why is this part of the API? } @@ -287,9 +225,8 @@ NS_NewImageRenderer(ilIImageRenderer **aInstancePtrResult) ilIImageRenderer *renderer = new ImageRendererImpl(); if (renderer == nsnull) { - return NS_ERROR_OUT_OF_MEMORY; + return NS_ERROR_OUT_OF_MEMORY; } - return renderer->QueryInterface(kIImageRendererIID, - (void **) aInstancePtrResult); + return renderer->QueryInterface(kIImageRendererIID, (void **)aInstancePtrResult); } diff --git a/gfx/src/windows/nsDeviceContextWin.cpp b/gfx/src/windows/nsDeviceContextWin.cpp index daee0aa14bab..1c6166177d64 100644 --- a/gfx/src/windows/nsDeviceContextWin.cpp +++ b/gfx/src/windows/nsDeviceContextWin.cpp @@ -106,8 +106,14 @@ NS_IMETHODIMP nsDeviceContextWin::GetDepth(PRUint32& aDepth) return NS_OK; } -NS_IMETHODIMP nsDeviceContextWin::CreateILColorSpace(IL_ColorSpace*& aColorSpace) +NS_IMETHODIMP nsDeviceContextWin::GetILColorSpace(IL_ColorSpace*& aColorSpace) { + if (nsnull != mColorSpace) { + aColorSpace = mColorSpace; + IL_AddRefToColorSpace(aColorSpace); + return NS_OK; + } + HWND hwnd = (HWND)GetNativeWidget(); HDC hdc = ::GetDC(hwnd); nsresult result = NS_OK; @@ -168,14 +174,16 @@ NS_IMETHODIMP nsDeviceContextWin::CreateILColorSpace(IL_ColorSpace*& aColorSpace } // Create an IL pseudo color space - aColorSpace = IL_CreatePseudoColorSpace(colorMap, 8, 8); + mColorSpace = IL_CreatePseudoColorSpace(colorMap, 8, 8); if (nsnull == aColorSpace) { return NS_ERROR_OUT_OF_MEMORY; } + aColorSpace = mColorSpace; + IL_AddRefToColorSpace(aColorSpace); } else { - // Create a default color space. - result = DeviceContextImpl::CreateILColorSpace(aColorSpace); + // Get the default color space. + result = DeviceContextImpl::GetILColorSpace(aColorSpace); } return result; diff --git a/gfx/src/windows/nsDeviceContextWin.h b/gfx/src/windows/nsDeviceContextWin.h index ddb5751d8d45..f930113b60a5 100644 --- a/gfx/src/windows/nsDeviceContextWin.h +++ b/gfx/src/windows/nsDeviceContextWin.h @@ -42,7 +42,7 @@ public: NS_IMETHOD GetDepth(PRUint32& aDepth); - NS_IMETHOD CreateILColorSpace(IL_ColorSpace*& aColorSpace); + NS_IMETHOD GetILColorSpace(IL_ColorSpace*& aColorSpace); protected: virtual ~nsDeviceContextWin(); diff --git a/widget/src/mac/nsDeviceContextMac.cpp b/widget/src/mac/nsDeviceContextMac.cpp index f66a6c3bdb85..43f1c0c717b3 100644 --- a/widget/src/mac/nsDeviceContextMac.cpp +++ b/widget/src/mac/nsDeviceContextMac.cpp @@ -437,7 +437,7 @@ nsresult nsDeviceContextMac :: CheckFontExistence(const nsString& aFontName) return NS_OK; } -nsresult nsDeviceContextMac :: CreateILColorSpace(IL_ColorSpace*& aColorSpace) +nsresult nsDeviceContextMac :: GetILColorSpace(IL_ColorSpace*& aColorSpace) { return nsnull; }