From caab8220a0ed2d953ca68a50f46207fc579b4d1a Mon Sep 17 00:00:00 2001 From: "pnunn%netscape.com" Date: Tue, 19 Oct 1999 21:49:20 +0000 Subject: [PATCH] bug# 16785. r: dp, valeski, neeti. Send mimetype info from channel to imglib. If no decoder, sniff data stream for mime info. --- gfx/src/nsImageNetContextAsync.cpp | 34 ++++-- gfx/src/nsImageNetContextSync.cpp | 32 +++++- modules/libimg/public/ilINetReader.h | 2 +- modules/libimg/src/if.cpp | 157 +++++++++++++++------------ modules/libimg/src/if.h | 23 +--- modules/libimg/src/ilNetReader.cpp | 4 +- modules/libimg/src/scale.cpp | 18 +-- 7 files changed, 164 insertions(+), 106 deletions(-) diff --git a/gfx/src/nsImageNetContextAsync.cpp b/gfx/src/nsImageNetContextAsync.cpp index ae3410abb166..25c46e3b8dc2 100644 --- a/gfx/src/nsImageNetContextAsync.cpp +++ b/gfx/src/nsImageNetContextAsync.cpp @@ -28,12 +28,14 @@ #include "nsIChannel.h" #include "nsCOMPtr.h" #include "nsWeakPtr.h" +#include "prprf.h" + #include "nsITimer.h" #include "nsVoidArray.h" #include "nsString.h" #include "prmem.h" #include "plstr.h" -#include "il_strm.h" +//#include "il_strm.h" #include "merrors.h" #include "nsNeckoUtil.h" @@ -163,13 +165,32 @@ ImageConsumer::OnStartRequest(nsIChannel* channel, nsISupports* aContext) return NS_ERROR_ABORT; } - ilINetReader *reader = mURL->GetReader(); - if (reader->StreamCreated(mURL, IL_UNKNOWN) != PR_TRUE) { + ilINetReader *reader = mURL->GetReader(); //ptn test: nsCOMPtr?? + + nsresult rv = NS_OK; + char* aContentType = NULL; + rv = channel->GetContentType(&aContentType); //nsCRT alloc's str + if (NS_FAILED(rv)) { + if(aContentType){ + nsCRT::free(aContentType); + } + aContentType = nsCRT::strdup("unknown"); + } + if(nsCRT::strlen(aContentType) > 50){ + //somethings wrong. mimetype string shouldn't be this big. + //protect us from the user. + nsCRT::free(aContentType); + aContentType = nsCRT::strdup("unknown"); + } + + if (reader->StreamCreated(mURL, aContentType) != PR_TRUE) { mStatus = MK_IMAGE_LOSSAGE; reader->StreamAbort(mStatus); NS_RELEASE(reader); + nsCRT::free(aContentType); return NS_ERROR_ABORT; } + nsCRT::free(aContentType); NS_RELEASE(reader); return NS_OK; @@ -192,7 +213,7 @@ ImageConsumer::OnDataAvailable(nsIChannel* channel, nsISupports* aContext, nsIIn NS_RELEASE(reader); return NS_ERROR_ABORT; } - + nsresult err = 0; PRUint32 nb; @@ -234,7 +255,7 @@ ImageConsumer::OnDataAvailable(nsIChannel* channel, nsISupports* aContext, nsIIn bytes_read += nb; if (mFirstRead == PR_TRUE) { - err = reader->FirstWrite((const unsigned char *)mBuffer, nb); + err = reader->FirstWrite((const unsigned char *)mBuffer, nb ); mFirstRead = PR_FALSE; //? move after err chk? /* * If FirstWrite(...) fails then the image type @@ -253,7 +274,7 @@ ImageConsumer::OnDataAvailable(nsIChannel* channel, nsISupports* aContext, nsIIn if(NS_FAILED(err)){ mStatus = MK_IMAGE_LOSSAGE; mInterrupted = PR_TRUE; - NS_RELEASE(reader); + NS_RELEASE(reader); return NS_ERROR_ABORT; } } while(bytes_read < length); @@ -276,7 +297,6 @@ ImageConsumer::OnDataAvailable(nsIChannel* channel, nsISupports* aContext, nsIIn } else { NS_IF_RELEASE(mStream); } - NS_RELEASE(reader); return NS_OK; } diff --git a/gfx/src/nsImageNetContextSync.cpp b/gfx/src/nsImageNetContextSync.cpp index 5a6b2dc84deb..d064735646cb 100644 --- a/gfx/src/nsImageNetContextSync.cpp +++ b/gfx/src/nsImageNetContextSync.cpp @@ -25,7 +25,7 @@ #include "nsIURL.h" #include "prmem.h" #include "plstr.h" -#include "il_strm.h" +//#include "il_strm.h" #ifndef NECKO #include "nsINetService.h" @@ -199,8 +199,10 @@ ImageNetContextSyncImpl::GetURL(ilIURL* aURL, #ifndef NECKO // Initiate a synchronous URL load + + if (NS_SUCCEEDED(service->OpenBlockingStream(url, nsnull, &stream)) && - (aReader->StreamCreated(aURL, IL_UNKNOWN) == PR_TRUE)) { + (aReader->StreamCreated(aURL, "unknown") == PR_TRUE)) { #else nsIURI *uri = nsnull; @@ -212,13 +214,30 @@ ImageNetContextSyncImpl::GetURL(ilIURL* aURL, nsIChannel *channel = nsnull; rv = service->NewChannelFromURI("load", uri, nsnull, nsnull, &channel); NS_RELEASE(uri); - if (NS_FAILED(rv)) return -1; + if (NS_FAILED(rv)) + return -1; + + char* aContentType = NULL; + rv = channel->GetContentType(&aContentType); //nsCRT alloc's str + if (NS_FAILED(rv)) { + if(aContentType){ + nsCRT::free(aContentType); + } + aContentType = nsCRT::strdup("unknown"); + } + if(nsCRT::strlen(aContentType) > 50){ + //somethings wrong. mimetype string shouldn't be this big. + //protect us from the user. + nsCRT::free(aContentType); + aContentType = nsCRT::strdup("unknown"); + } rv = channel->OpenInputStream(0, -1, &stream); NS_RELEASE(channel); - if (NS_FAILED(rv)) return -1; + if (NS_FAILED(rv)) + return -1; - if (aReader->StreamCreated(aURL, IL_UNKNOWN) == PR_TRUE) { + if (aReader->StreamCreated(aURL, aContentType) == PR_TRUE) { #endif // NECKO @@ -263,12 +282,15 @@ ImageNetContextSyncImpl::GetURL(ilIURL* aURL, } NS_IF_RELEASE(stream); + nsCRT::free(aContentType); + } else { aReader->StreamAbort(-1); status = -1; } aReader->NetRequestDone(aURL, status); + NS_IF_RELEASE(url); return 0; diff --git a/modules/libimg/public/ilINetReader.h b/modules/libimg/public/ilINetReader.h index ff229d0a648f..1ee821f2cb03 100644 --- a/modules/libimg/public/ilINetReader.h +++ b/modules/libimg/public/ilINetReader.h @@ -46,7 +46,7 @@ public: NS_IMETHOD NetRequestDone(ilIURL *urls, int status)=0; - virtual PRBool StreamCreated(ilIURL *urls, int type)=0; + virtual PRBool StreamCreated(ilIURL *urls, char* type)=0; virtual PRBool IsMulti()=0; }; diff --git a/modules/libimg/src/if.cpp b/modules/libimg/src/if.cpp index c7b2cd55a0ef..ec3c45dd9b2d 100644 --- a/modules/libimg/src/if.cpp +++ b/modules/libimg/src/if.cpp @@ -30,8 +30,9 @@ #include "xpcompat.h" #include "prtypes.h" +#include "prprf.h" -#include "il_strm.h" +//#include "il_strm.h" PR_BEGIN_EXTERN_C @@ -75,7 +76,7 @@ NS_IMETHODIMP ImgDCallbk::ImgDCBResetPalette() if( ilContainer != NULL ) { il_reset_palette(ilContainer); } - return NS_OK; + return 0; } @@ -197,24 +198,14 @@ ImgDCallbk :: ImgDCBClearTimeout(void *timer_id) static void il_description_notify(il_container *ic) { - char buf[36], buf2[12]; + char buf[36]; IL_MessageData message_data; IL_ImageReq *image_req; NI_PixmapHeader *img_header = &ic->image->header; XP_BZERO(&message_data, sizeof(IL_MessageData)); - switch (ic->type) { - /* XXX - This needs to be fixed for Image Plugins. */ - case IL_GIF : PL_strcpy(buf2, "GIF"); break; - case IL_XBM : PL_strcpy(buf2, "XBM"); break; - case IL_JPEG : PL_strcpy(buf2, "JPEG"); break; - case IL_PNG : PL_strcpy(buf2, "PNG"); break; - case IL_ART : PL_strcpy(buf2, "ART"); break; - - default : PL_strcpy(buf2, ""); - } - XP_SPRINTF(buf, XP_GetString(XP_MSG_IMAGE_PIXELS), buf2, + XP_SPRINTF(buf, XP_GetString(XP_MSG_IMAGE_PIXELS), ic->type, img_header->width, img_header->height); PR_ASSERT(ic->clients); @@ -379,9 +370,9 @@ il_progress_notify(il_container *ic) /* Could be zero if before il_size() is called. */ if (img_header->height == 0) return; - + int ret; /* Interlaced GIFs are weird */ - if (ic->type == IL_GIF) { + if (ret= nsCRT::strncasecmp(ic->type, "image/gif", 9) == 0) { percent_done = il_compute_percentage_complete(row, ic); } else @@ -427,8 +418,8 @@ il_cache_return_notify(IL_ImageReq *image_req) PR_ASSERT(ic->state >= IC_SIZED); /* First notify observers of the image dimensions. */ - message_data.width = ic->dest_width; /* Note: these are stored as */ - message_data.height = ic->dest_height; /* uint16s. */ + message_data.width = (unsigned short) ic->dest_width; /* Note: these are stored as */ + message_data.height = (unsigned short) ic->dest_height; /* uint16s. */ XP_NotifyObservers(image_req->obs_list, IL_DIMENSIONS, &message_data); message_data.width = message_data.height = 0; @@ -864,14 +855,15 @@ IL_StreamWriteReady(il_container *ic) } /* Given the first few bytes of a stream, identify the image format */ -static int -il_type(int suspected_type, const char *buf, int32 len) +bool +sniffout_mimetype(const char *buf, int32 len, char* aContentType) { int i; - if (len >= 4 && !strncmp(buf, "GIF8", 4)) + if (len >= 4 && !nsCRT::strncmp(buf, "GIF8", 4)) { - return IL_GIF; + PR_snprintf(aContentType, 10,"%s", "image/gif"); + return TRUE; } /* for PNG */ @@ -880,7 +872,8 @@ il_type(int suspected_type, const char *buf, int32 len) (unsigned char)buf[2]==0x4E && (unsigned char)buf[3]==0x47)) { - return IL_PNG; + PR_snprintf(aContentType, 10,"%s","image/png"); + return TRUE; } @@ -895,8 +888,9 @@ il_type(int suspected_type, const char *buf, int32 len) ((unsigned char)buf[1])==0xD8 && ((unsigned char)buf[2])==0xFF) { - return IL_JPEG; - } + PR_snprintf(aContentType, 11,"%s", "image/jpeg"); + return TRUE; + } /* ART begins with JG (4A 47). Major version offset 2. Minor version offset 3. Offset 4 must be NULL. @@ -906,7 +900,8 @@ il_type(int suspected_type, const char *buf, int32 len) ((unsigned char) buf[1])==0x47 && ((unsigned char) buf[4])==0x00 ) { - return IL_ART; + PR_snprintf(aContentType, 10,"%s", "image/art"); + return TRUE; } @@ -914,35 +909,44 @@ il_type(int suspected_type, const char *buf, int32 len) if (len >= 8 && !strncmp(buf, "#define ", 8) ) { /* Don't contradict the given type, since this ID isn't definitive */ - if ((suspected_type == IL_UNKNOWN) || (suspected_type == IL_XBM)) - return IL_XBM; + PR_snprintf(aContentType, 8,"%s", "unknown"); + return TRUE; } - if (len < 35) + if (len < 12) { ILTRACE(1,("il: too few bytes to determine type")); - return suspected_type; + PR_snprintf(aContentType, 8,"%s", "unknown"); + return FALSE; } /* all the servers return different formats so root around */ for (i=0; i<28; i++) { - if (!strncmp(&buf[i], "Not Fou", 7)) - return IL_NOTFOUND; + if (!strncmp(&buf[i], "Not Fou", 7)){ + PR_snprintf(aContentType, 8,"%s", "unknown"); + return FALSE; + } } - - return suspected_type; + + //just in case + PR_snprintf(aContentType, 8,"%s", "unknown"); + return FALSE; } /* * determine what kind of image data we are dealing with */ + + IL_IMPLEMENT(int) IL_Type(const char *buf, int32 len) { - return il_type(IL_UNKNOWN, buf, len); + char aContent[200]; + return sniffout_mimetype(buf, len, aContent); } + int IL_StreamWrite(il_container *ic, const unsigned char *str, int32 len) { @@ -984,7 +988,7 @@ IL_StreamFirstWrite(il_container *ic, const unsigned char *str, int32 len) PR_ASSERT(ic); PR_ASSERT(ic->image); - + /* If URL redirection occurs, the url stored in the image container is the redirect url not the image file url. If the image is animated, the imglib will never match the @@ -992,6 +996,7 @@ IL_StreamFirstWrite(il_container *ic, const unsigned char *str, int32 len) ic->fetch_url keeps the actual url for you. */ + FREE_IF_NOT_NULL(ic->fetch_url); #ifdef NECKO @@ -1010,47 +1015,55 @@ IL_StreamFirstWrite(il_container *ic, const unsigned char *str, int32 len) ic->fetch_url = NULL; } - /* Figure out the image type, possibly overriding the given MIME type */ - ic->type = il_type(ic->type, (const char*) str, len); - - /* Grab the URL's expiration date */ if (ic->url) ic->expires = ic->url->GetExpires(); - nsIImgDecoder *imgdec; - - char imgtype[150]; + nsIImgDecoder *imgdec ; char imgtypestr[200]; - switch (ic->type) { - case IL_GIF : PL_strcpy(imgtype, "gif"); break; - case IL_XBM : PL_strcpy(imgtype, "xbm"); break; - case IL_JPEG : PL_strcpy(imgtype, "jpeg"); break; - case IL_PNG : PL_strcpy(imgtype, "png"); break; - case IL_ART : PL_strcpy(imgtype, "art"); break; - default : PL_strcpy(imgtype, ""); - } - - sprintf(imgtypestr, "component://netscape/image/decoder&type=image/%s" - , imgtype ); - + PR_snprintf(imgtypestr, sizeof(imgtypestr), "component://netscape/image/decoder&type=%s" + , ic->type ); + static NS_DEFINE_IID(kIImgDecoderIID, NS_IIMGDECODER_IID); rv = nsComponentManager::CreateInstance(imgtypestr, NULL, - kIImgDecoderIID, // XXX was previously kImgDecoderIID - (void **)&imgdec); + kIImgDecoderIID, + (void **)&imgdec); - if (NS_FAILED(rv)) - return MK_IMAGE_LOSSAGE; + /* If no mimetype to decoder mapping, try to sniff out + the mime-type */ + if (NS_FAILED(rv)){ + char contenttype[50]; + if(sniffout_mimetype((const char*) str, len, contenttype)){ + + /* try again with the guessed mimetype */ + PR_snprintf(imgtypestr, sizeof(imgtypestr), "component://netscape/image/decoder&type=%s" + , contenttype ); + + rv = nsComponentManager::CreateInstance(imgtypestr, NULL, + kIImgDecoderIID, (void **)&imgdec); + } + if (NS_FAILED(rv)) + /* we did our best. Gotta give up. */ + return MK_IMAGE_LOSSAGE; + + /*we found it*/ + nsCRT::free(ic->type); + ic->type = NULL; + ic->type = nsCRT::strdup(contenttype); + + } imgdec->SetContainer(ic); ic->imgdec = imgdec; rv = imgdec->ImgDInit(); - if(NS_FAILED(rv)) - { + + if(NS_FAILED(rv)){ + NS_RELEASE(ic->imgdec); + ic->imgdec = nsnull; ILTRACE(0,("il: image init failed")); return MK_OUT_OF_MEMORY; } @@ -1103,7 +1116,9 @@ il_bad_container(il_container *ic) IL_ImageReq *image_req; ILTRACE(4,("il: bad container, sending icon")); - if (ic->type == IL_NOTFOUND) { + if((ic->type)&& + ((nsCRT::strlen(ic->type) < 8) || + (nsCRT::strncmp(ic->type, "unknown", 7)==0))) { ic->state = IC_MISSING; for (image_req = ic->clients; image_req; image_req = image_req->next) il_icon_notify(image_req, IL_IMAGE_NOT_FOUND, IL_ERROR_NO_DATA); @@ -1235,7 +1250,10 @@ IL_StreamComplete(il_container *ic, PRBool is_multipart) #endif /* DEBUG */ PR_ASSERT(ic); - + if(ic->type){ + nsCRT::free(ic->type); + ic->type = NULL; + } #ifdef DEBUG cur_time = PR_Now(); LL_SUB(cur_time, cur_time, ic->start_time); @@ -1549,6 +1567,11 @@ IL_StreamAbort(il_container *ic, int status) /* Abort the image. */ il_image_abort(ic); + if(ic->type){ + nsCRT::free(ic->type); + ic->type = NULL; + } + if(ic->state >= IC_SIZED || (ic->state == IC_ABORT_PENDING)){ if (status == MK_INTERRUPTED){ @@ -1581,7 +1604,7 @@ IL_StreamAbort(il_container *ic, int status) PRBool IL_StreamCreated(il_container *ic, ilIURL *url, - int type) + char* type) { PR_ASSERT(ic); @@ -1592,14 +1615,14 @@ IL_StreamCreated(il_container *ic, if (ic->state == IC_ABORT_PENDING) return PR_FALSE; - ic->type = (int)type; + ic->type = nsCRT::strdup(type); //mime string ic->content_length = url->GetContentLength(); #ifdef NECKO char* addr = url->GetAddress(); - ILTRACE(4,("il: new stream, type %d, %s", ic->type, addr)); + ILTRACE(4,("il: new stream, type %s, %s", ic->type, addr)); nsCRT::free(addr); #else - ILTRACE(4,("il: new stream, type %d, %s", ic->type, + ILTRACE(4,("il: new stream, type %s, %s", ic->type, url->GetAddress())); #endif ic->state = IC_STREAM; diff --git a/modules/libimg/src/if.h b/modules/libimg/src/if.h index d85d50191e7d..244253841486 100644 --- a/modules/libimg/src/if.h +++ b/modules/libimg/src/if.h @@ -18,7 +18,7 @@ /* if.h --- Top-level image library internal routines * - * $Id: if.h,v 3.10 1999/09/25 19:59:42 kipp%netscape.com Exp $ + * $Id: if.h,v 3.11 1999/10/19 21:48:03 pnunn%netscape.com Exp $ */ #ifndef _if_h @@ -207,7 +207,7 @@ struct il_container_struct { IL_Pixmap *image; /* Destination image pixmap structure. */ IL_Pixmap *mask; /* Destination mask pixmap structure. */ - intn type; + char* type; /* mimetype string ptn 10.13.99*/ void *ds; /* decoder's private data */ il_converter converter; @@ -364,32 +364,21 @@ extern PRBool il_image_stopped(il_container *ic); extern ilINetReader *IL_NewNetReader(il_container *ic); extern il_container *IL_GetNetReaderContainer(ilINetReader *reader); -#ifndef M12N_NEW_DEPENDENCIES /* XXXM12N */ + extern int IL_StreamWriteReady(il_container *ic); extern int IL_StreamFirstWrite(il_container *ic, const unsigned char *str, int32 len); extern int IL_StreamWrite(il_container *ic, const unsigned char *str, int32 len); extern void IL_StreamAbort(il_container *ic, int status); extern void IL_StreamComplete(il_container *ic, PRBool is_multipart); extern void IL_NetRequestDone(il_container *ic, ilIURL *urls, int status); -extern PRBool IL_StreamCreated(il_container *ic, ilIURL *urls, int type); -#else -extern jint -il_write_ready(NET_StreamClass *stream, jint op, struct JMCException* *exceptionThrown); -extern jint -il_first_write(NET_StreamClass *stream, jint op, jbyte* str, jsize len, - struct JMCException* *exceptionThrown); -extern void -il_abort(NET_StreamClass *stream, jint op, jint status, - struct JMCException* *exceptionThrown); -extern void -il_stream_complete(NET_StreamClass *stream, jint op, - struct JMCException* *exceptionThrown); -#endif /* M12N_NEW_DEPENDENCIES */ +extern PRBool IL_StreamCreated(il_container *ic, ilIURL *urls, char* type); +#if 0 extern int il_xbm_init(il_container *ic); extern int il_xbm_write(il_container *, const uint8 *, int32); extern void il_xbm_complete(il_container *ic); extern void il_xbm_abort(il_container *ic); +#endif /* Allocate and initialize the destination image's transparent_pixel with the Image Library's preferred transparency color i.e. the background color diff --git a/modules/libimg/src/ilNetReader.cpp b/modules/libimg/src/ilNetReader.cpp index 8f9cfea3ca00..298c53c67582 100644 --- a/modules/libimg/src/ilNetReader.cpp +++ b/modules/libimg/src/ilNetReader.cpp @@ -41,7 +41,7 @@ public: NS_IMETHOD NetRequestDone(ilIURL *urls, int status); - virtual PRBool StreamCreated(ilIURL *urls, int type); + virtual PRBool StreamCreated(ilIURL *urls, char* type); virtual PRBool IsMulti(); @@ -133,7 +133,7 @@ NetReaderImpl::NetRequestDone(ilIURL *urls, int status) } PRBool -NetReaderImpl::StreamCreated(ilIURL *urls, int type) +NetReaderImpl::StreamCreated(ilIURL *urls, char* type) { if (ilContainer != NULL) { return IL_StreamCreated(ilContainer, urls, type); diff --git a/modules/libimg/src/scale.cpp b/modules/libimg/src/scale.cpp index 4951f3c01a3d..79df6c5f3ff9 100644 --- a/modules/libimg/src/scale.cpp +++ b/modules/libimg/src/scale.cpp @@ -24,8 +24,8 @@ #include "if.h" /* Image library internal declarations */ #include "il.h" /* Image library external API */ -#include "il_strm.h" /* For image types. */ -#include "prmem.h" + +#include "nsCRT.h" #include "nsVoidArray.h" #include "nsITimer.h" @@ -971,8 +971,8 @@ il_emit_row( drow_start * mask_header->widthBytes; #endif - /* We know this mask is prescaled: */ - if (ic->type == IL_ART){ + /* We know this mask is prescaled: */ + if (nsCRT::strncasecmp(ic->type, "image/art",9)==0){ /* No scaling needed*/ if (len == column_count) XP_MEMCPY(maskp, cbuf, mask_header->widthBytes); @@ -1178,16 +1178,20 @@ il_emit_row( dup = row_count - 1; offset = dcolumn_start * (img_color_space->pixmap_depth / 8); + #ifndef M12N /* Clean this up */ if (ic->image->pixmap_depth == 1) do_dither = TRUE; else do_dither = ic->converter && (row_count <= 4) && - ((ic->dither_mode == IL_Dither) || (ic->type == IL_JPEG)); + ((ic->dither_mode == IL_Dither) || + (nsCRT::strncasecmp(ic->type, "image/jpeg",10)==0); #else do_dither = (ic->dither_mode == IL_Dither); - if ((ic->type == IL_GIF)||(ic->type == IL_PNG) && (!ic->converter || (row_count > 4))) - do_dither = FALSE; + if ((nsCRT::strncasecmp(ic->type, "image/gif",9)==0)|| + (nsCRT::strncasecmp(ic->type, "image/png",9)==0) && + (!ic->converter || (row_count > 4))) + do_dither = FALSE; #endif /* M12N */