Use a different internal icon format ifdef MOZ_CAIRO_GFX that is easier to convert to the image frame format we use, and make the relevant icon channel implementations produce it. b=333253 r=pavlov

This commit is contained in:
dbaron%dbaron.org 2007-01-08 23:58:12 +00:00
Родитель 3ed1cd85e7
Коммит c0407d49ab
6 изменённых файлов: 117 добавлений и 31 удалений

Просмотреть файл

@ -314,7 +314,11 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBloc
return NS_ERROR_NOT_AVAILABLE;
// Got a bitmap and color space info - convert data to mozilla's icon format
#ifdef MOZ_CAIRO_GFX
PRUint32 iconLength = 2 + iconSize * iconSize * 4;
#else
PRUint32 iconLength = 3 + iconSize * (iconSize * 3 + alphaBytesPerRow);
#endif
uint8 *buffer = new uint8[iconLength];
if (!buffer)
return NS_ERROR_OUT_OF_MEMORY;
@ -322,7 +326,9 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBloc
uint8* destByte = buffer;
*(destByte++) = iconSize;
*(destByte++) = iconSize;
#ifndef MOZ_CAIRO_GFX
*(destByte++) = 1; // alpha bits per pixel
#endif
// RGB data
uint8* sourceByte = (uint8*)nativeIcon.Bits();
@ -334,15 +340,32 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBloc
if (*sourceByte != B_TRANSPARENT_MAGIC_CMAP8)
{
rgb_color colorVal = mainScreen.ColorForIndex(*sourceByte);
#ifdef MOZ_CAIRO_GFX
#ifdef IS_LITTLE_ENDIAN
*(destByte++) = colorVal.blue;
*(destByte++) = colorVal.green;
*(destByte++) = colorVal.red;
*(destByte++) = uint8(255);
#else
*(destByte++) = uint8(255);
*(destByte++) = colorVal.red;
*(destByte++) = colorVal.green;
*(destByte++) = colorVal.blue;
#endif
#else
*(destByte++) = colorVal.blue;
*(destByte++) = colorVal.green;
*(destByte++) = colorVal.red;
#endif
}
else
{
*destByte++ = 0;
*destByte++ = 0;
*destByte++ = 0;
#ifdef MOZ_CAIRO_GFX
*destByte++ = 0;
#endif
}
// original code had a conditional here:
// if (iconCol < iconSize - 1)
@ -350,6 +373,7 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBloc
sourceByte++;
}
}
#ifndef MOZ_CAIRO_GFX
// Alpha data - bitmask, with rows aligned on 32-bit boundaries
for(PRUint32 iconRow = 0; iconRow < iconSize; iconRow++)
{
@ -372,6 +396,9 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBloc
destByte++;
}
}
#endif
NS_ASSERTION(buffer + iconLength == destByte, "size miscalculation");
// Now, create a pipe and stuff our data into it
nsCOMPtr<nsIInputStream> inStream;

Просмотреть файл

@ -83,35 +83,67 @@ moz_gdk_pixbuf_to_channel(GdkPixbuf* aPixbuf, nsIURI *aURI,
NS_ERROR_UNEXPECTED);
const int n_channels = 4;
#ifdef MOZ_CAIRO_GFX
gsize buf_size = 2 + n_channels * height * width;
#else
gsize buf_size = 3 + n_channels * height * width;
#endif
PRUint8 * const buf = (PRUint8*)NS_Alloc(buf_size);
NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
PRUint8 *out = buf;
*(out++) = width;
*(out++) = height;
#ifndef MOZ_CAIRO_GFX
*(out++) = 8; // bits of alpha per pixel
#endif
const guchar * const pixels = gdk_pixbuf_get_pixels(aPixbuf);
int rowextra = gdk_pixbuf_get_rowstride(aPixbuf) - width * n_channels;
// encode the RGB data and the A data
const guchar * in = pixels;
#ifndef MOZ_CAIRO_GFX
PRUint8 *alpha_out = out + height * width * 3;
#ifdef DEBUG
PRUint8 * const alpha_start = alpha_out;
#endif
#endif
for (int y = 0; y < height; ++y, in += rowextra) {
for (int x = 0; x < width; ++x) {
#ifdef MOZ_CAIRO_GFX
PRUint8 r = *(in++);
PRUint8 g = *(in++);
PRUint8 b = *(in++);
PRUint8 a = *(in++);
#define DO_PREMULTIPLY(c_) PRUint8(PRUint16(c_) * PRUint16(a) / PRUint16(255))
#ifdef IS_LITTLE_ENDIAN
*(out++) = DO_PREMULTIPLY(b);
*(out++) = DO_PREMULTIPLY(g);
*(out++) = DO_PREMULTIPLY(r);
*(out++) = a;
#else
*(out++) = a;
*(out++) = DO_PREMULTIPLY(r);
*(out++) = DO_PREMULTIPLY(g);
*(out++) = DO_PREMULTIPLY(b);
#endif
#undef DO_PREMULTIPLY
#else
*(out++) = *(in++); // R
*(out++) = *(in++); // G
*(out++) = *(in++); // B
*(alpha_out++) = *(in++); // A
#endif
}
}
#ifdef MOZ_CAIRO_GFX
NS_ASSERTION(out == buf + buf_size, "size miscalculation");
#else
NS_ASSERTION(out == alpha_start && alpha_out == buf + buf_size,
"size miscalculation");
#endif
nsresult rv;
nsCOMPtr<nsIStringInputStream> stream =

Просмотреть файл

@ -312,7 +312,11 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBloc
PRUint8* bitmapRepData = (PRUint8*)[bitmapRep bitmapData];
// create our buffer
#ifdef MOZ_CAIRO_GFX
PRInt32 bufferCapacity = 2 + desiredImageSize * desiredImageSize * 4;
#else
PRInt32 bufferCapacity = 3 + desiredImageSize * desiredImageSize * 5;
#endif
nsAutoBuffer<PRUint8, 3 + 16 * 16 * 5> iconBuffer; // initial size is for 16x16
if (!iconBuffer.EnsureElemCapacity(bufferCapacity))
return NS_ERROR_OUT_OF_MEMORY;
@ -322,7 +326,9 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBloc
// write header data into buffer
*iconBufferPtr++ = desiredImageSize;
*iconBufferPtr++ = desiredImageSize;
#ifndef MOZ_CAIRO_GFX
*iconBufferPtr++ = 8; // alpha bits per pixel
#endif
PRUint32 dataCount = (desiredImageSize * desiredImageSize) * 4;
PRUint32 index = 0;
@ -333,6 +339,7 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBloc
PRUint8 b = bitmapRepData[index++];
PRUint8 a = bitmapRepData[index++];
#ifndef MOZ_CAIRO_GFX
// reverse premultiplication
if (a == 0) {
r = g = b = 0;
@ -342,21 +349,35 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBloc
g = ((PRUint32) g) * 255 / a;
b = ((PRUint32) b) * 255 / a;
}
#endif
// write data out to our buffer - the real alpha data is appended to the
// end of the stream, the alpha here is just an unused extra channel
// write data out to our buffer
// non-cairo uses native image format, but the A channel is ignored.
// cairo uses ARGB (highest to lowest bits)
#if defined(MOZ_CAIRO_GFX) && defined(IS_LITTLE_ENDIAN)
*iconBufferPtr++ = b;
*iconBufferPtr++ = g;
*iconBufferPtr++ = r;
*iconBufferPtr++ = a;
#else
*iconBufferPtr++ = a;
*iconBufferPtr++ = r;
*iconBufferPtr++ = g;
*iconBufferPtr++ = b;
#endif
}
#ifndef MOZ_CAIRO_GFX
// add the alpha to the buffer
index = 3;
while (index < dataCount) {
*iconBufferPtr++ = bitmapRepData[index];
index += 4;
}
#endif
NS_ASSERTION(iconBufferPtr == iconBuffer.get() + bufferCapacity,
"buffer size miscalculation");
// Now, create a pipe and stuff our data into it
nsCOMPtr<nsIInputStream> inStream;

Просмотреть файл

@ -107,7 +107,11 @@ NS_IMETHODIMP nsIconDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR
PRUint32 readLen;
rv = inStr->Read((char*)buf, count, &readLen);
NS_ENSURE_SUCCESS(rv, rv);
#ifdef MOZ_CAIRO_GFX
NS_ENSURE_TRUE(readLen >= 2, NS_ERROR_UNEXPECTED); // w, h
#else
NS_ENSURE_TRUE(readLen >= 3, NS_ERROR_UNEXPECTED); // w, h, alphaBits
#endif
PRUint8 * const buf_end = buf + readLen;
PRUint8 *data = buf;
@ -118,16 +122,24 @@ NS_IMETHODIMP nsIconDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR
// Read size
PRInt32 w = *(data++);
PRInt32 h = *(data++);
#ifdef MOZ_CAIRO_GFX
NS_ENSURE_TRUE(w > 0 && h > 0, NS_ERROR_UNEXPECTED);
#else
PRUint8 alphaBits = *(data++);
NS_ENSURE_TRUE(w > 0 && h > 0 && (alphaBits == 1 || alphaBits == 8),
NS_ERROR_UNEXPECTED);
#endif
mImage->Init(w, h, mObserver);
if (mObserver)
mObserver->OnStartContainer(nsnull, mImage);
#ifdef MOZ_CAIRO_GFX
gfx_format format = gfxIFormats::BGRA; // XXX not really
#else
gfx_format format = alphaBits == 1 ? gfx_format(gfxIFormats::RGB_A1)
: gfx_format(gfxIFormats::RGB_A8);
#endif
rv = mFrame->Init(0, 0, w, h, format, 24);
if (NS_FAILED(rv))
return rv;
@ -145,34 +157,11 @@ NS_IMETHODIMP nsIconDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR
PRInt32 rownum;
#if defined(MOZ_CAIRO_GFX)
return NS_ERROR_FAILURE; // this code is totally busted.. fixing shortly.
PRUint8 *row = (PRUint8*)malloc(bpr);
PRUint8 *adata = data + (bpr * height);
for (rownum = 0; rownum < height; ++rownum, data += bpr) {
PRUint8 *rowdata = data;
for (int i = 0; i < bpr; i++) {
const PRUint8 r = *rowdata++;
const PRUint8 g = *rowdata++;
const PRUint8 b = *rowdata++;
const PRUint8 a = (format == gfxIFormats::RGB_A1) ? adata[i>>3] : adata[i];
#ifdef IS_LITTLE_ENDIAN
// BGRX
*row++ = b;
*row++ = g;
*row++ = r;
*row++ = a;
#else
// XRGB
*row++ = a;
*row++ = r;
*row++ = g;
*row++ = b;
#endif
}
mFrame->SetImageData(row, bpr, rownum * bpr);
}
free(row);
NS_ENSURE_TRUE(buf_end - data >= PRInt32(bpr) * height,
NS_ERROR_UNEXPECTED);
for (rownum = 0; rownum < height; ++rownum, data += bpr)
mFrame->SetImageData(data, bpr, rownum * bpr);
#else
NS_ENSURE_TRUE(buf_end - data >= PRInt32(bpr + abpr) * height,
NS_ERROR_UNEXPECTED);

Просмотреть файл

@ -68,13 +68,23 @@
// support multiple ODA calls yet.
// (2) the format of the incoming data is as follows:
// The first two bytes contain the width and the height of the icon.
#ifdef MOZ_CAIRO_GFX
// The remaining bytes contain the icon data, 4 bytes per pixel, in
// ARGB order (platform endianness, A in highest bits, B in lowest
// bits), row-primary, top-to-bottom, left-to-right, with
// premultiplied alpha.
#else
// The third byte contains the number of bits per pixel in the alpha
// channel (either 1 or 8).
// Followed by 3 bytes per pixel for the color bitmap row after row,
// from top to bottom, with pixels left to right within rows, and
// RGB order within pixels, in platform endianness.
// RGB order within pixels, in platform endianness. Alpha is
// *not* premultiplied.
// XXXldb This isn't quite right -- we're just using
// platform-native format.
// Followed by alpha data (1 or 8 bits per pixel, see above) in the
// same order as the RGB data, and also in platform endianness.
#endif
//
//
//////////////////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -244,6 +244,13 @@ nsresult nsIconChannel::ExtractIconInfoFromUrl(nsIFile ** aLocalFile, PRUint32 *
nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBlocking)
{
#ifdef MOZ_CAIRO_GFX
// This needs to be changed to match the format changes described in
// nsIconDecoder.h. For cairo, the icon format is ARGB (A in highest
// bits, B in lowest bits, based on platform endianness).
return NS_ERROR_NOT_IMPLEMENTED;
#endif
// get some details about this icon
nsCOMPtr<nsIFile> localFile;
PRUint32 desiredImageSize;