mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-05-13 08:57:27 +00:00
merge from IMGLIB_20010126_BRANCH
This commit is contained in:
parent
eea8eb56d8
commit
e3fbe3ae72
2
modules/libpr0n/.cvsignore
Normal file
2
modules/libpr0n/.cvsignore
Normal file
@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
.deps
|
@ -26,7 +26,7 @@ VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = ppm png
|
||||
DIRS = ppm png gif jpeg
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
2
modules/libpr0n/decoders/jpeg/.cvsignore
Normal file
2
modules/libpr0n/decoders/jpeg/.cvsignore
Normal file
@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
.deps
|
40
modules/libpr0n/decoders/jpeg/Makefile.in
Normal file
40
modules/libpr0n/decoders/jpeg/Makefile.in
Normal file
@ -0,0 +1,40 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 2001 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = imgjpeg
|
||||
LIBRARY_NAME = imgjpeg
|
||||
IS_COMPONENT = 1
|
||||
|
||||
CPPSRCS = nsJPEGDecoder.cpp nsJPEGFactory.cpp
|
||||
|
||||
EXTRA_DSO_LDOPTS = $(JPEG_LIBS) $(ZLIB_LIBS) \
|
||||
$(MOZ_COMPONENT_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -28,10 +28,12 @@
|
||||
|
||||
#include "nspr.h"
|
||||
|
||||
#include "nsUnitConverters.h"
|
||||
|
||||
#include "nsCRT.h"
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
|
||||
#include "nsIImageContainerObserver.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsJPEGDecoder, nsIImageDecoder, nsIOutputStream)
|
||||
|
||||
|
||||
@ -44,14 +46,6 @@ void PR_CALLBACK il_error_exit (j_common_ptr cinfo);
|
||||
/* Normal JFIF markers can't have more bytes than this. */
|
||||
#define MAX_JPEG_MARKER_LENGTH (((PRUint32)1 << 16) - 1)
|
||||
|
||||
|
||||
/* Possible states for JPEG source manager */
|
||||
enum data_source_state {
|
||||
dss_consuming_backtrack_buffer = 0, /* Must be zero for init purposes */
|
||||
dss_consuming_netlib_buffer
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Implementation of a JPEG src object that understands our state machine
|
||||
*/
|
||||
@ -59,26 +53,8 @@ typedef struct {
|
||||
/* public fields; must be first in this struct! */
|
||||
struct jpeg_source_mgr pub;
|
||||
|
||||
|
||||
nsJPEGDecoder *decoder;
|
||||
|
||||
|
||||
int bytes_to_skip; /* remaining bytes to skip */
|
||||
|
||||
JOCTET *netlib_buffer; /* next buffer for fill_input_buffer */
|
||||
PRUint32 netlib_buflen;
|
||||
|
||||
enum data_source_state state;
|
||||
|
||||
|
||||
/*
|
||||
* Buffer of "remaining" characters left over after a call to
|
||||
* fill_input_buffer(), when no additional data is available.
|
||||
*/
|
||||
JOCTET *backtrack_buffer;
|
||||
size_t backtrack_buffer_size; /* Allocated size of backtrack_buffer */
|
||||
size_t backtrack_buflen; /* Offset of end of active backtrack data */
|
||||
size_t backtrack_num_unread_bytes; /* Length of active backtrack data */
|
||||
} decoder_source_mgr;
|
||||
|
||||
|
||||
@ -88,10 +64,8 @@ nsJPEGDecoder::nsJPEGDecoder()
|
||||
|
||||
mState = JPEG_HEADER;
|
||||
|
||||
mBuf = nsnull;
|
||||
mBufLen = 0;
|
||||
mDataLen = 0;
|
||||
|
||||
mCurDataLen = 0;
|
||||
mSamples = nsnull;
|
||||
mSamples3 = nsnull;
|
||||
|
||||
@ -110,15 +84,22 @@ nsJPEGDecoder::~nsJPEGDecoder()
|
||||
NS_IMETHODIMP nsJPEGDecoder::Init(nsIImageRequest *aRequest)
|
||||
{
|
||||
mRequest = aRequest;
|
||||
mObserver = do_QueryInterface(mRequest);
|
||||
|
||||
aRequest->GetImage(getter_AddRefs(mImage));
|
||||
|
||||
|
||||
NS_NewPipe(getter_AddRefs(mInStream),
|
||||
getter_AddRefs(mOutStream),
|
||||
10240); // this could be a lot smaller (like 3-6k?)
|
||||
|
||||
/* Step 1: allocate and initialize JPEG decompression object */
|
||||
|
||||
/* Now we can initialize the JPEG decompression object. */
|
||||
jpeg_create_decompress(&mInfo);
|
||||
|
||||
|
||||
/* Step 2: specify data source (eg, a file) */
|
||||
decoder_source_mgr *src;
|
||||
|
||||
if (mInfo.src == NULL) {
|
||||
@ -181,15 +162,12 @@ NS_IMETHODIMP nsJPEGDecoder::GetRequest(nsIImageRequest * *aRequest)
|
||||
/* void close (); */
|
||||
NS_IMETHODIMP nsJPEGDecoder::Close()
|
||||
{
|
||||
|
||||
// XXX this should flush the data out
|
||||
|
||||
|
||||
// XXX progressive? ;)
|
||||
OutputScanlines(mInfo.output_height);
|
||||
|
||||
/* Step 7: Finish decompression */
|
||||
|
||||
(void) jpeg_finish_decompress(&mInfo);
|
||||
/* We can ignore the return value since suspension is not possible
|
||||
* with the stdio data source.
|
||||
*/
|
||||
// OutputScanlines(mInfo.output_height);
|
||||
|
||||
|
||||
/* Step 8: Release JPEG decompression object */
|
||||
@ -197,15 +175,6 @@ NS_IMETHODIMP nsJPEGDecoder::Close()
|
||||
/* This is an important step since it will release a good deal of memory. */
|
||||
jpeg_destroy_decompress(&mInfo);
|
||||
|
||||
|
||||
|
||||
|
||||
printf("nsJPEGDecoder::Close()\n");
|
||||
|
||||
|
||||
PR_FREEIF(mBuf);
|
||||
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -230,26 +199,11 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR
|
||||
*/
|
||||
// XXX above what is this?
|
||||
|
||||
PRUint32 readLen;
|
||||
|
||||
if (!mBuf) {
|
||||
mBuf = (char*)PR_Malloc(count);
|
||||
mBufLen = count;
|
||||
if (inStr) {
|
||||
mOutStream->WriteFrom(inStr, count, _retval);
|
||||
mDataLen += *_retval;
|
||||
}
|
||||
|
||||
if (mBuf && count > mBufLen)
|
||||
{
|
||||
mBuf = (char *)PR_Realloc(mBuf, count);
|
||||
mBufLen = count;
|
||||
}
|
||||
|
||||
nsresult rv = inStr->Read(mBuf, count, &readLen);
|
||||
mCurDataLen = readLen;
|
||||
|
||||
/* Step 2: specify data source (eg, a file) */
|
||||
|
||||
// i think this magically happens
|
||||
// jpeg_stdio_src(&cinfo, infile);
|
||||
|
||||
|
||||
|
||||
@ -257,17 +211,13 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR
|
||||
|
||||
decoder_source_mgr *src = NS_REINTERPRET_CAST(decoder_source_mgr *, mInfo.src);
|
||||
|
||||
if (!mSamples && jpeg_read_header(&mInfo, TRUE) != JPEG_SUSPENDED) {
|
||||
|
||||
|
||||
/* FIXME -- Should reset dct_method and dither mode
|
||||
* for final pass of progressive JPEG
|
||||
*/
|
||||
mInfo.dct_method = JDCT_FASTEST;
|
||||
mInfo.dither_mode = JDITHER_ORDERED;
|
||||
mInfo.do_fancy_upsampling = FALSE;
|
||||
mInfo.enable_2pass_quant = FALSE;
|
||||
mInfo.do_block_smoothing = TRUE;
|
||||
int status;
|
||||
switch (mState) {
|
||||
case JPEG_HEADER:
|
||||
{
|
||||
/* Step 3: read file parameters with jpeg_read_header() */
|
||||
if (jpeg_read_header(&mInfo, TRUE) == JPEG_SUSPENDED)
|
||||
return NS_OK;
|
||||
|
||||
/*
|
||||
* Don't allocate a giant and superfluous memory buffer
|
||||
@ -278,7 +228,15 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR
|
||||
/* Used to set up image size so arrays can be allocated */
|
||||
jpeg_calc_output_dimensions(&mInfo);
|
||||
|
||||
mImage->Init(mInfo.image_width, mInfo.image_height, nsIGFXFormat::RGB);
|
||||
mObserver->OnStartDecode(nsnull, nsnull);
|
||||
|
||||
mImage->Init(mInfo.image_width, mInfo.image_height, mObserver);
|
||||
mObserver->OnStartContainer(nsnull, nsnull, mImage);
|
||||
|
||||
mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
|
||||
mFrame->Init(0, 0, mInfo.image_width, mInfo.image_height, nsIGFXFormat::RGB);
|
||||
mImage->AppendFrame(mFrame);
|
||||
mObserver->OnStartFrame(nsnull, nsnull, mFrame);
|
||||
|
||||
|
||||
/*
|
||||
@ -302,38 +260,64 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR
|
||||
row_stride, 1);
|
||||
}
|
||||
|
||||
} else {
|
||||
return NS_OK;
|
||||
mState = JPEG_START_DECOMPRESS;
|
||||
}
|
||||
|
||||
|
||||
/* Step 3: read file parameters with jpeg_read_header() */
|
||||
// (void) jpeg_read_header(&mInfo, TRUE);
|
||||
/* We can ignore the return value from jpeg_read_header since
|
||||
* (a) suspension is not possible with the stdio data source, and
|
||||
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
|
||||
* See libjpeg.doc for more info.
|
||||
*/
|
||||
case JPEG_START_DECOMPRESS:
|
||||
|
||||
/* Step 4: set parameters for decompression */
|
||||
|
||||
/* FIXME -- Should reset dct_method and dither mode
|
||||
* for final pass of progressive JPEG
|
||||
*/
|
||||
mInfo.dct_method = JDCT_FASTEST;
|
||||
mInfo.dither_mode = JDITHER_ORDERED;
|
||||
mInfo.do_fancy_upsampling = FALSE;
|
||||
mInfo.enable_2pass_quant = FALSE;
|
||||
mInfo.do_block_smoothing = TRUE;
|
||||
|
||||
/* In this example, we don't need to change any of the defaults set by
|
||||
* jpeg_read_header(), so we do nothing here.
|
||||
*/
|
||||
|
||||
/* Step 5: Start decompressor */
|
||||
if (jpeg_start_decompress(&mInfo) == FALSE)
|
||||
return NS_OK;
|
||||
|
||||
(void) jpeg_start_decompress(&mInfo);
|
||||
/* We can ignore the return value since suspension is not possible
|
||||
* with the stdio data source.
|
||||
*/
|
||||
mState = JPEG_DECOMPRESS_PROGRESSIVE;
|
||||
|
||||
int status;
|
||||
case JPEG_DECOMPRESS_PROGRESSIVE:
|
||||
do {
|
||||
status = jpeg_consume_input(&mInfo);
|
||||
} while (!((status == JPEG_SUSPENDED) ||
|
||||
(status == JPEG_REACHED_EOI)));
|
||||
|
||||
if (status == JPEG_REACHED_EOI) {
|
||||
mState = JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT;
|
||||
} else {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT:
|
||||
jpeg_start_output(&mInfo, mInfo.input_scan_number);
|
||||
OutputScanlines(-1);
|
||||
jpeg_finish_output(&mInfo);
|
||||
mState = JPEG_DONE;
|
||||
|
||||
case JPEG_DONE:
|
||||
/* Step 7: Finish decompression */
|
||||
|
||||
if (jpeg_finish_decompress(&mInfo) == FALSE)
|
||||
return NS_OK;
|
||||
|
||||
mState = JPEG_SINK_NON_JPEG_TRAILER;
|
||||
|
||||
/* we're done dude */
|
||||
break;
|
||||
|
||||
case JPEG_SINK_NON_JPEG_TRAILER:
|
||||
break;
|
||||
}
|
||||
|
||||
/* We may need to do some setup of our own at this point before reading
|
||||
* the data. After jpeg_start_decompress() we have the correct scaled
|
||||
* output image dimensions available, as well as the output colormap
|
||||
@ -361,7 +345,12 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR
|
||||
*/
|
||||
(void) jpeg_read_scanlines(&mInfo, buffer, 1);
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
mImage->SetBits(buffer[0], row_stride, row_stride*mInfo.output_scanline /* XXX ??? */);
|
||||
mFrame->SetImageData(buffer[0], row_stride, row_stride*mInfo.output_scanline /* XXX ??? */);
|
||||
|
||||
|
||||
nsRect r(0, mInfo.output_scanline, mInfo.output_width, 1);
|
||||
mObserver->OnDataAvailable(nsnull, nsnull, mFrame, &r);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -420,7 +409,7 @@ nsJPEGDecoder::OutputScanlines(int num_scanlines)
|
||||
}
|
||||
|
||||
|
||||
mImage->SetBits(samples, strlen((const char *)samples), strlen((const char *)samples)*mInfo.output_scanline /* XXX ??? */);
|
||||
mFrame->SetImageData(samples, strlen((const char *)samples), strlen((const char *)samples)*mInfo.output_scanline /* XXX ??? */);
|
||||
#if 0
|
||||
ic->imgdcb->ImgDCBHaveRow( 0, samples, 0, mInfo.output_width, mInfo.output_scanline-1,
|
||||
1, ilErase, pass);
|
||||
@ -506,6 +495,60 @@ init_source (j_decompress_ptr jd)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
static NS_METHOD DiscardData(nsIInputStream* in,
|
||||
void* closure,
|
||||
const char* fromRawSegment,
|
||||
PRUint32 toOffset,
|
||||
PRUint32 count,
|
||||
PRUint32 *writeCount)
|
||||
{
|
||||
j_decompress_ptr jd = NS_STATIC_CAST(j_decompress_ptr, closure);
|
||||
decoder_source_mgr *src = NS_REINTERPRET_CAST(decoder_source_mgr *, jd->src);
|
||||
|
||||
*writeCount = count;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void PR_CALLBACK
|
||||
skip_input_data (j_decompress_ptr jd, long num_bytes)
|
||||
{
|
||||
decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
|
||||
|
||||
if (num_bytes > (long)src->pub.bytes_in_buffer) {
|
||||
/*
|
||||
* Can't skip it all right now until we get more data from
|
||||
* network stream. Set things up so that fill_input_buffer
|
||||
* will skip remaining amount.
|
||||
*/
|
||||
|
||||
PRUint32 _retval;
|
||||
src->decoder->mInStream->ReadSegments(DiscardData, NS_STATIC_CAST(void*, jd),
|
||||
src->pub.bytes_in_buffer, &_retval);
|
||||
src->decoder->mDataLen -= _retval;
|
||||
|
||||
src->decoder->mBytesToSkip = (size_t)num_bytes - src->pub.bytes_in_buffer;
|
||||
src->pub.next_input_byte += src->pub.bytes_in_buffer;
|
||||
src->pub.bytes_in_buffer = 0;
|
||||
|
||||
} else {
|
||||
/* Simple case. Just advance buffer pointer */
|
||||
|
||||
PRUint32 _retval;
|
||||
src->decoder->mInStream->ReadSegments(DiscardData, NS_STATIC_CAST(void*, jd),
|
||||
num_bytes, &_retval);
|
||||
src->decoder->mDataLen -= _retval;
|
||||
|
||||
src->decoder->mBytesToSkip = 0;
|
||||
src->pub.bytes_in_buffer -= (size_t)num_bytes;
|
||||
src->pub.next_input_byte += num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* This is the callback routine from the IJG JPEG library used to supply new
|
||||
* data to the decompressor when its input buffer is exhausted. It juggles
|
||||
@ -534,181 +577,54 @@ init_source (j_decompress_ptr jd)
|
||||
* TRUE if additional data is available, FALSE if no data present and
|
||||
* the JPEG library should therefore suspend processing of input stream
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
static NS_METHOD ReadDataOut(nsIInputStream* in,
|
||||
void* closure,
|
||||
const char* fromRawSegment,
|
||||
PRUint32 toOffset,
|
||||
PRUint32 count,
|
||||
PRUint32 *writeCount)
|
||||
{
|
||||
j_decompress_ptr jd = NS_STATIC_CAST(j_decompress_ptr, closure);
|
||||
decoder_source_mgr *src = NS_REINTERPRET_CAST(decoder_source_mgr *, jd->src);
|
||||
|
||||
src->pub.next_input_byte = NS_REINTERPRET_CAST(const unsigned char *, fromRawSegment);
|
||||
src->pub.bytes_in_buffer = count;
|
||||
|
||||
*writeCount = 0; // pretend we didn't really read anything
|
||||
|
||||
return NS_ERROR_FAILURE; // return error so that we can point to this buffer and exit the ReadSegments loop
|
||||
}
|
||||
|
||||
|
||||
boolean PR_CALLBACK
|
||||
fill_input_buffer (j_decompress_ptr jd)
|
||||
{
|
||||
decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
|
||||
|
||||
return src->decoder->FillInput(jd);
|
||||
}
|
||||
PRUint32 _retval;
|
||||
|
||||
PRBool nsJPEGDecoder::FillInput(j_decompress_ptr jd)
|
||||
{
|
||||
// read the data from the input stram...
|
||||
|
||||
decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
|
||||
|
||||
if (mCurDataLen == 0)
|
||||
return FALSE;
|
||||
|
||||
unsigned char *newBuffer = (unsigned char *)mBuf;
|
||||
size_t newBufLen = mCurDataLen;
|
||||
|
||||
if (mBytesToSkip < mCurDataLen) {
|
||||
newBuffer += mBytesToSkip;
|
||||
newBufLen -= mBytesToSkip;
|
||||
mBytesToSkip = 0;
|
||||
if (src->decoder->mBytesToSkip != 0) {
|
||||
if (src->decoder->mBytesToSkip > src->decoder->mDataLen){
|
||||
src->decoder->mInStream->ReadSegments(DiscardData, NS_STATIC_CAST(void*, jd),
|
||||
src->decoder->mDataLen, &_retval);
|
||||
} else {
|
||||
mBytesToSkip -= newBufLen;
|
||||
return FALSE; // suspend
|
||||
src->decoder->mInStream->ReadSegments(DiscardData, NS_STATIC_CAST(void*, jd),
|
||||
src->decoder->mBytesToSkip, &_retval);
|
||||
}
|
||||
src->decoder->mBytesToSkip -= _retval;
|
||||
src->decoder->mDataLen -= _retval;
|
||||
}
|
||||
|
||||
src->pub.next_input_byte = newBuffer;
|
||||
src->pub.bytes_in_buffer = newBufLen;
|
||||
|
||||
return TRUE;
|
||||
|
||||
#if 0
|
||||
enum data_source_state src_state = src->state;
|
||||
PRUint32 bytesToSkip, new_backtrack_buflen, new_buflen, roundup_buflen;
|
||||
unsigned char *new_buffer;
|
||||
|
||||
#if 0
|
||||
ILTRACE(5,("il:jpeg: fill, state=%d, nib=0x%x, bib=%d", src_state,
|
||||
src->pub.next_input_byte, src->pub.bytes_in_buffer));
|
||||
#endif
|
||||
|
||||
switch (src_state) {
|
||||
|
||||
/* Decompressor reached end of backtrack buffer. Return netlib buffer.*/
|
||||
case dss_consuming_backtrack_buffer:
|
||||
new_buffer = (unsigned char *)src->netlib_buffer;
|
||||
new_buflen = src->netlib_buflen;
|
||||
if ((new_buffer == NULL) || (new_buflen == 0))
|
||||
goto suspend;
|
||||
|
||||
/*
|
||||
* Clear, so that repeated calls to fill_input_buffer() do not
|
||||
* deliver the same netlib buffer more than once.
|
||||
*/
|
||||
src->netlib_buflen = 0;
|
||||
|
||||
/* Discard data if asked by skip_input_data(). */
|
||||
bytesToSkip = src->bytes_to_skip;
|
||||
if (bytesToSkip) {
|
||||
if (bytesToSkip < new_buflen) {
|
||||
/* All done skipping bytes; Return what's left. */
|
||||
new_buffer += bytesToSkip;
|
||||
new_buflen -= bytesToSkip;
|
||||
src->bytes_to_skip = 0;
|
||||
if (src->decoder->mDataLen != 0) {
|
||||
src->decoder->mInStream->ReadSegments(ReadDataOut, NS_STATIC_CAST(void*, jd),
|
||||
src->decoder->mDataLen, &_retval);
|
||||
src->decoder->mDataLen -= src->pub.bytes_in_buffer;
|
||||
return PR_TRUE;
|
||||
} else {
|
||||
/* Still need to skip some more data in the future */
|
||||
src->bytes_to_skip -= (size_t)new_buflen;
|
||||
goto suspend;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/* Save old backtrack buffer parameters, in case the decompressor
|
||||
* backtracks and we're forced to restore its contents.
|
||||
*/
|
||||
src->backtrack_num_unread_bytes = src->pub.bytes_in_buffer;
|
||||
|
||||
src->pub.next_input_byte = new_buffer;
|
||||
src->pub.bytes_in_buffer = (size_t)new_buflen;
|
||||
src->state = dss_consuming_netlib_buffer;
|
||||
return TRUE;
|
||||
|
||||
/* Reached end of netlib buffer. Suspend */
|
||||
case dss_consuming_netlib_buffer:
|
||||
if (src->pub.next_input_byte != src->netlib_buffer) {
|
||||
/* Backtrack data has been permanently consumed. */
|
||||
src->backtrack_num_unread_bytes = 0;
|
||||
src->backtrack_buflen = 0;
|
||||
}
|
||||
|
||||
/* Save remainder of netlib buffer in backtrack buffer */
|
||||
new_backtrack_buflen = src->pub.bytes_in_buffer + src->backtrack_buflen;
|
||||
|
||||
/* Make sure backtrack buffer is big enough to hold new data. */
|
||||
if (src->backtrack_buffer_size < new_backtrack_buflen) {
|
||||
|
||||
/* Round up to multiple of 16 bytes. */
|
||||
roundup_buflen = ((new_backtrack_buflen + 15) >> 4) << 4;
|
||||
if (src->backtrack_buffer_size) {
|
||||
src->backtrack_buffer =
|
||||
(JOCTET *)PR_REALLOC(src->backtrack_buffer, roundup_buflen);
|
||||
} else {
|
||||
src->backtrack_buffer = (JOCTET*)PR_MALLOC(roundup_buflen);
|
||||
}
|
||||
|
||||
/* Check for OOM */
|
||||
if (! src->backtrack_buffer) {
|
||||
#if 0
|
||||
j_common_ptr cinfo = (j_common_ptr)(&src->js->jd);
|
||||
cinfo->err->msg_code = JERR_OUT_OF_MEMORY;
|
||||
il_error_exit(cinfo);
|
||||
#endif
|
||||
}
|
||||
|
||||
src->backtrack_buffer_size = (size_t)roundup_buflen;
|
||||
|
||||
/* Check for malformed MARKER segment lengths. */
|
||||
if (new_backtrack_buflen > MAX_JPEG_MARKER_LENGTH) {
|
||||
// il_error_exit((j_common_ptr)(&src->js->jd));
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy remainder of netlib buffer into backtrack buffer. */
|
||||
nsCRT::memmove(src->backtrack_buffer + src->backtrack_buflen,
|
||||
src->pub.next_input_byte,
|
||||
src->pub.bytes_in_buffer);
|
||||
|
||||
/* Point to start of data to be rescanned. */
|
||||
src->pub.next_input_byte = src->backtrack_buffer +
|
||||
src->backtrack_buflen - src->backtrack_num_unread_bytes;
|
||||
src->pub.bytes_in_buffer += src->backtrack_num_unread_bytes;
|
||||
src->backtrack_buflen = (size_t)new_backtrack_buflen;
|
||||
|
||||
src->state = dss_consuming_backtrack_buffer;
|
||||
goto suspend;
|
||||
|
||||
default:
|
||||
PR_ASSERT(0);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
suspend:
|
||||
// ILTRACE(5,(" Suspending, bib=%d", src->pub.bytes_in_buffer));
|
||||
return FALSE;
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void PR_CALLBACK
|
||||
skip_input_data (j_decompress_ptr jd, long num_bytes)
|
||||
{
|
||||
decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
|
||||
|
||||
#if 0
|
||||
ILTRACE(5, ("il:jpeg: skip_input_data js->buf=0x%x js->buflen=%d skip=%d",
|
||||
src->netlib_buffer, src->netlib_buflen,
|
||||
num_bytes));
|
||||
#endif
|
||||
|
||||
if (num_bytes > (long)src->pub.bytes_in_buffer) {
|
||||
/*
|
||||
* Can't skip it all right now until we get more data from
|
||||
* network stream. Set things up so that fill_input_buffer
|
||||
* will skip remaining amount.
|
||||
*/
|
||||
src->decoder->mBytesToSkip = (size_t)num_bytes - src->pub.bytes_in_buffer;
|
||||
src->pub.next_input_byte += src->pub.bytes_in_buffer;
|
||||
src->pub.bytes_in_buffer = 0;
|
||||
} else {
|
||||
/* Simple case. Just advance buffer pointer */
|
||||
src->pub.bytes_in_buffer -= (size_t)num_bytes;
|
||||
src->pub.next_input_byte += num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -719,5 +635,13 @@ skip_input_data (j_decompress_ptr jd, long num_bytes)
|
||||
void PR_CALLBACK
|
||||
term_source (j_decompress_ptr jd)
|
||||
{
|
||||
decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
|
||||
|
||||
if (src->decoder->mObserver) {
|
||||
src->decoder->mObserver->OnStopFrame(nsnull, nsnull, src->decoder->mFrame);
|
||||
src->decoder->mObserver->OnStopContainer(nsnull, nsnull, src->decoder->mImage);
|
||||
src->decoder->mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
|
||||
}
|
||||
|
||||
/* No work necessary here */
|
||||
}
|
@ -28,12 +28,17 @@
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include "nsIImage2.h"
|
||||
#include "nsIImageRequest.h"
|
||||
#include "nsIImageContainer.h"
|
||||
#include "nsIImageFrame.h"
|
||||
#include "nsIImageDecoderObserver.h"
|
||||
#include "nsIImageRequest2.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIPipe.h"
|
||||
|
||||
#include "jpeglib.h"
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
#define NS_JPEGDECODER_CID \
|
||||
{ /* 5871a422-1dd2-11b2-ab3f-e2e56be5da9c */ \
|
||||
0x5871a422, \
|
||||
@ -77,18 +82,21 @@ public:
|
||||
protected:
|
||||
int OutputScanlines(int num_scanlines);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIImage2> mImage;
|
||||
public:
|
||||
nsCOMPtr<nsIImageContainer> mImage;
|
||||
nsCOMPtr<nsIImageFrame> mFrame;
|
||||
nsCOMPtr<nsIImageRequest> mRequest;
|
||||
nsCOMPtr<nsIInputStream> mStream;
|
||||
|
||||
nsCOMPtr<nsIImageDecoderObserver> mObserver;
|
||||
|
||||
struct jpeg_decompress_struct mInfo;
|
||||
decoder_error_mgr mErr;
|
||||
jstate mState;
|
||||
|
||||
char *mBuf;
|
||||
PRUint32 mBufLen;
|
||||
PRUint32 mCurDataLen;
|
||||
nsCOMPtr<nsIInputStream> mInStream;
|
||||
nsCOMPtr<nsIOutputStream> mOutStream;
|
||||
|
||||
PRUint32 mDataLen;
|
||||
|
||||
JSAMPARRAY mSamples;
|
||||
JSAMPARRAY mSamples3;
|
||||
|
@ -34,7 +34,7 @@ static nsModuleComponentInfo components[] =
|
||||
{
|
||||
{ "ppm decoder",
|
||||
NS_JPEGDECODER_CID,
|
||||
"@mozilla.org/image/decoder?image/jpeg;1",
|
||||
"@mozilla.org/image/decoder;2?type=image/jpeg",
|
||||
nsJPEGDecoderConstructor, },
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,6 @@
|
||||
|
||||
DEPTH=..\..\..
|
||||
|
||||
DIRS = ppm png
|
||||
DIRS = ppm gif png jpeg
|
||||
|
||||
!include $(DEPTH)\config\rules.mak
|
||||
|
@ -39,6 +39,7 @@ LLIBS=\
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(DIST)\lib\png.lib \
|
||||
$(DIST)\lib\zlib.lib \
|
||||
$(DIST)\lib\gkgfxwin.lib \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
@ -34,6 +34,11 @@
|
||||
|
||||
#include "nsIStreamObserver.h"
|
||||
|
||||
#include "nsRect.h"
|
||||
|
||||
#include "nsMemory.h"
|
||||
|
||||
#include "nsIImageContainerObserver.h"
|
||||
|
||||
// XXX we need to be sure to fire onStopDecode messages to mObserver in error cases.
|
||||
|
||||
@ -47,11 +52,19 @@ nsPNGDecoder::nsPNGDecoder()
|
||||
|
||||
mPNG = nsnull;
|
||||
mInfo = nsnull;
|
||||
colorLine = 0;
|
||||
alphaLine = 0;
|
||||
interlacebuf = 0;
|
||||
}
|
||||
|
||||
nsPNGDecoder::~nsPNGDecoder()
|
||||
{
|
||||
|
||||
if (colorLine)
|
||||
nsMemory::Free(colorLine);
|
||||
if (alphaLine)
|
||||
nsMemory::Free(alphaLine);
|
||||
if (interlacebuf)
|
||||
nsMemory::Free(interlacebuf);
|
||||
}
|
||||
|
||||
|
||||
@ -85,7 +98,7 @@ NS_IMETHODIMP nsPNGDecoder::Init(nsIImageRequest *aRequest)
|
||||
}
|
||||
|
||||
/* use ic as libpng "progressive pointer" (retrieve in callbacks) */
|
||||
png_set_progressive_read_fn(mPNG, this, nsPNGDecoder::info_callback, nsPNGDecoder::row_callback, nsPNGDecoder::end_callback);
|
||||
png_set_progressive_read_fn(mPNG, NS_STATIC_CAST(png_voidp, this), nsPNGDecoder::info_callback, nsPNGDecoder::row_callback, nsPNGDecoder::end_callback);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -136,6 +149,17 @@ static NS_METHOD ReadDataOut(nsIInputStream* in,
|
||||
PRUint32 *writeCount)
|
||||
{
|
||||
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, closure);
|
||||
|
||||
// we need to do the setjmp here otherwise bad things will happen
|
||||
if (setjmp(decoder->mPNG->jmpbuf)) {
|
||||
png_destroy_read_struct(&decoder->mPNG, &decoder->mInfo, NULL);
|
||||
// is this NS_ERROR_FAILURE enough?
|
||||
|
||||
decoder->mRequest->Cancel(NS_BINDING_ABORTED); // XXX is this the correct error ?
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*writeCount = decoder->ProcessData((unsigned char*)fromRawSegment, count);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -150,16 +174,7 @@ PRUint32 nsPNGDecoder::ProcessData(unsigned char *data, PRUint32 count)
|
||||
/* unsigned long writeFrom (in nsIInputStream inStr, in unsigned long count); */
|
||||
NS_IMETHODIMP nsPNGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
|
||||
{
|
||||
PRUint32 sourceOffset = *_retval;
|
||||
|
||||
if (setjmp(mPNG->jmpbuf)) {
|
||||
png_destroy_read_struct(&mPNG, &mInfo, NULL);
|
||||
// is this NS_ERROR_FAILURE enough?
|
||||
|
||||
mRequest->Cancel(NS_BINDING_ABORTED); // XXX is this the correct error ?
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// PRUint32 sourceOffset = *_retval;
|
||||
|
||||
inStr->ReadSegments(ReadDataOut, this, count, _retval);
|
||||
|
||||
@ -313,13 +328,13 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr)
|
||||
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, png_get_progressive_ptr(png_ptr));
|
||||
|
||||
if (decoder->mObserver)
|
||||
decoder->mObserver->OnStartDecode(nsnull);
|
||||
decoder->mObserver->OnStartDecode(nsnull, nsnull);
|
||||
|
||||
// since the png is only 1 frame, initalize the container to the width and height of the frame
|
||||
decoder->mImage->Init(width, height);
|
||||
decoder->mImage->Init(width, height, decoder->mObserver);
|
||||
|
||||
if (decoder->mObserver)
|
||||
decoder->mObserver->OnStartContainer(nsnull, decoder->mImage);
|
||||
decoder->mObserver->OnStartContainer(nsnull, nsnull, decoder->mImage);
|
||||
|
||||
decoder->mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
|
||||
#if 0
|
||||
@ -328,20 +343,43 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr)
|
||||
return NS_ERROR_FAILURE;
|
||||
#endif
|
||||
|
||||
gfx_format format;
|
||||
|
||||
if (channels == 3) {
|
||||
format = nsIGFXFormat::RGB;
|
||||
} else if (channels > 3) {
|
||||
if (alpha_bits == 8) {
|
||||
decoder->mImage->GetPreferredAlphaChannelFormat(&format);
|
||||
} else if (alpha_bits == 1) {
|
||||
format = nsIGFXFormat::RGB_A1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef XP_PC
|
||||
// XXX this works...
|
||||
format += 1; // RGB to BGR
|
||||
#endif
|
||||
|
||||
// then initalize the frame and append it to the container
|
||||
decoder->mFrame->Init(0, 0, width, height, format);
|
||||
|
||||
decoder->mImage->AppendFrame(decoder->mFrame);
|
||||
|
||||
if (decoder->mObserver)
|
||||
decoder->mObserver->OnStartFrame(nsnull, decoder->mFrame);
|
||||
decoder->mObserver->OnStartFrame(nsnull, nsnull, decoder->mFrame);
|
||||
|
||||
PRUint32 bpr, abpr;
|
||||
decoder->mFrame->GetImageBytesPerRow(&bpr);
|
||||
decoder->mFrame->GetAlphaBytesPerRow(&abpr);
|
||||
decoder->colorLine = (PRUint8 *)nsMemory::Alloc(bpr);
|
||||
if (channels > 3)
|
||||
decoder->alphaLine = (PRUint8 *)nsMemory::Alloc(abpr);
|
||||
|
||||
// then initalize the frame (which was appended above in nsPNGDecoder::Init())
|
||||
if (channels == 3) {
|
||||
decoder->mFrame->Init(0, 0, width, height, nsIGFXFormat::RGB);
|
||||
} else if (channels > 3) {
|
||||
if (alpha_bits == 8) {
|
||||
decoder->mFrame->Init(0, 0, width, height, nsIGFXFormat::RGBA);
|
||||
} else if (alpha_bits == 1) {
|
||||
decoder->mFrame->Init(0, 0, width, height, nsIGFXFormat::RGB_A1);
|
||||
if (interlace_type == PNG_INTERLACE_ADAM7) {
|
||||
decoder->interlacebuf = (PRUint8 *)nsMemory::Alloc(channels*width*height);
|
||||
decoder->ibpr = channels*width;
|
||||
if (!decoder->interlacebuf) {
|
||||
// return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -385,23 +423,77 @@ nsPNGDecoder::row_callback(png_structp png_ptr, png_bytep new_row,
|
||||
*/
|
||||
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, png_get_progressive_ptr(png_ptr));
|
||||
|
||||
PRUint32 bpr;
|
||||
decoder->mFrame->GetBytesPerRow(&bpr);
|
||||
PRUint32 bpr, abpr;
|
||||
decoder->mFrame->GetImageBytesPerRow(&bpr);
|
||||
decoder->mFrame->GetAlphaBytesPerRow(&abpr);
|
||||
|
||||
PRUint32 length;
|
||||
PRUint8 *bits;
|
||||
decoder->mFrame->GetBits(&bits, &length);
|
||||
decoder->mFrame->GetImageData(&bits, &length);
|
||||
|
||||
png_bytep line;
|
||||
if (bits) {
|
||||
line = bits+(row_num*bpr);
|
||||
if (decoder->interlacebuf) {
|
||||
line = decoder->interlacebuf+(row_num*decoder->ibpr);
|
||||
png_progressive_combine_row(png_ptr, line, new_row);
|
||||
}
|
||||
else
|
||||
line = new_row;
|
||||
|
||||
if (new_row) {
|
||||
decoder->mFrame->SetBits((PRUint8*)line, bpr, row_num*bpr);
|
||||
nscoord width;
|
||||
decoder->mFrame->GetWidth(&width);
|
||||
PRUint32 iwidth = width;
|
||||
|
||||
gfx_format format;
|
||||
decoder->mFrame->GetFormat(&format);
|
||||
PRUint8 *aptr, *cptr;
|
||||
|
||||
switch (format) {
|
||||
case nsIGFXFormat::RGB:
|
||||
case nsIGFXFormat::BGR:
|
||||
decoder->mFrame->SetImageData((PRUint8*)line, bpr, row_num*bpr);
|
||||
break;
|
||||
case nsIGFXFormat::RGB_A1:
|
||||
case nsIGFXFormat::BGR_A1:
|
||||
{
|
||||
cptr = decoder->colorLine;
|
||||
aptr = decoder->alphaLine;
|
||||
memset(aptr, 0, abpr);
|
||||
for (PRUint32 x=0; x<iwidth; x++) {
|
||||
*cptr++ = *line++;
|
||||
*cptr++ = *line++;
|
||||
*cptr++ = *line++;
|
||||
if (*line++) {
|
||||
aptr[x>>3] |= 1<<(7-x&0x7);
|
||||
}
|
||||
}
|
||||
decoder->mFrame->SetImageData(decoder->colorLine, bpr, row_num*bpr);
|
||||
decoder->mFrame->SetAlphaData(decoder->alphaLine, abpr, row_num*abpr);
|
||||
}
|
||||
break;
|
||||
case nsIGFXFormat::RGB_A8:
|
||||
case nsIGFXFormat::BGR_A8:
|
||||
{
|
||||
cptr = decoder->colorLine;
|
||||
aptr = decoder->alphaLine;
|
||||
for (PRUint32 x=0; x<iwidth; x++) {
|
||||
*cptr++ = *line++;
|
||||
*cptr++ = *line++;
|
||||
*cptr++ = *line++;
|
||||
*aptr++ = *line++;
|
||||
}
|
||||
decoder->mFrame->SetImageData(decoder->colorLine, bpr, row_num*bpr);
|
||||
decoder->mFrame->SetAlphaData(decoder->alphaLine, abpr, row_num*abpr);
|
||||
}
|
||||
break;
|
||||
case nsIGFXFormat::RGBA:
|
||||
case nsIGFXFormat::BGRA:
|
||||
decoder->mFrame->SetImageData(line, bpr, row_num*bpr);
|
||||
break;
|
||||
}
|
||||
|
||||
nsRect r(0, row_num, width, 1);
|
||||
decoder->mObserver->OnDataAvailable(nsnull, nsnull, decoder->mFrame, &r);
|
||||
}
|
||||
}
|
||||
|
||||
@ -425,9 +517,9 @@ nsPNGDecoder::end_callback(png_structp png_ptr, png_infop info_ptr)
|
||||
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, png_get_progressive_ptr(png_ptr));
|
||||
|
||||
if (decoder->mObserver) {
|
||||
decoder->mObserver->OnStopFrame(nsnull, decoder->mFrame);
|
||||
decoder->mObserver->OnStopContainer(nsnull, decoder->mImage);
|
||||
decoder->mObserver->OnStopDecode(nsnull, NS_OK, nsnull);
|
||||
decoder->mObserver->OnStopFrame(nsnull, nsnull, decoder->mFrame);
|
||||
decoder->mObserver->OnStopContainer(nsnull, nsnull, decoder->mImage);
|
||||
decoder->mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "nsIImageContainer.h"
|
||||
#include "nsIImageDecoderObserver.h"
|
||||
#include "nsIImageFrame.h"
|
||||
#include "nsIImageRequest.h"
|
||||
#include "nsIImageRequest2.h"
|
||||
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
@ -66,7 +66,7 @@ end_callback(png_structp png_ptr, png_infop info_ptr);
|
||||
inline PRUint32 ProcessData(unsigned char *data, PRUint32 count);
|
||||
|
||||
|
||||
private:
|
||||
public:
|
||||
nsCOMPtr<nsIImageContainer> mImage;
|
||||
nsCOMPtr<nsIImageFrame> mFrame;
|
||||
nsCOMPtr<nsIImageRequest> mRequest;
|
||||
@ -74,6 +74,9 @@ private:
|
||||
|
||||
png_structp mPNG;
|
||||
png_infop mInfo;
|
||||
PRUint8 *colorLine, *alphaLine;
|
||||
PRUint8 *interlacebuf;
|
||||
PRUint32 ibpr;
|
||||
};
|
||||
|
||||
#endif // nsPNGDecoder_h__
|
||||
|
@ -34,7 +34,11 @@ static nsModuleComponentInfo components[] =
|
||||
{
|
||||
{ "PNG decoder",
|
||||
NS_PNGDECODER_CID,
|
||||
"@mozilla.org/image/decoder?image/png;1",
|
||||
"@mozilla.org/image/decoder;2?type=image/png",
|
||||
nsPNGDecoderConstructor, },
|
||||
{ "PNG decoder",
|
||||
NS_PNGDECODER_CID,
|
||||
"@mozilla.org/image/decoder;2?type=image/x-png",
|
||||
nsPNGDecoderConstructor, },
|
||||
};
|
||||
|
||||
|
@ -37,6 +37,7 @@ OBJS = \
|
||||
LLIBS=\
|
||||
$(LIBNSPR) \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(DIST)\lib\gkgfxwin.lib \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
@ -20,23 +20,20 @@
|
||||
* Contributor(s):
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
*
|
||||
*
|
||||
* the ppm decoding function is from Tim Rowley <tor@cs.brown.edu>
|
||||
* i dunno its license
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nsPPMDecoder.h"
|
||||
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIImageContainer.h"
|
||||
#include "nsIImageContainerObserver.h"
|
||||
|
||||
#include "nspr.h"
|
||||
|
||||
#include "nsUnitConverters.h"
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
|
||||
#include "nsRect.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsPPMDecoder, nsIImageDecoder, nsIOutputStream)
|
||||
|
||||
|
||||
@ -63,15 +60,14 @@ NS_IMETHODIMP nsPPMDecoder::Init(nsIImageRequest *aRequest)
|
||||
{
|
||||
mRequest = aRequest;
|
||||
|
||||
nsCOMPtr<nsIImageContainer> container;
|
||||
aRequest->GetImage(getter_AddRefs(container));
|
||||
mObserver = do_QueryInterface(aRequest); // we're holding 2 strong refs to the request.
|
||||
|
||||
mImage = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
|
||||
if (!mImage)
|
||||
aRequest->GetImage(getter_AddRefs(mImage));
|
||||
|
||||
mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
|
||||
if (!mFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
container->AppendFrame(mImage);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -93,11 +89,11 @@ NS_IMETHODIMP nsPPMDecoder::GetRequest(nsIImageRequest * *aRequest)
|
||||
/* void close (); */
|
||||
NS_IMETHODIMP nsPPMDecoder::Close()
|
||||
{
|
||||
printf("nsPPMDecoder::Close()\n");
|
||||
|
||||
// XXX hack
|
||||
gfx_format format;
|
||||
mImage->GetFormat(&format);
|
||||
if (mObserver) {
|
||||
mObserver->OnStopFrame(nsnull, nsnull, mFrame);
|
||||
mObserver->OnStopContainer(nsnull, nsnull, mImage);
|
||||
mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -185,6 +181,8 @@ NS_IMETHODIMP nsPPMDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRU
|
||||
|
||||
if (mDataReceived == 0) {
|
||||
|
||||
mObserver->OnStartDecode(nsnull, nsnull);
|
||||
|
||||
// Check the magic number
|
||||
char type;
|
||||
if ((sscanf(data, "P%c\n", &type) !=1) || (type != '6')) {
|
||||
@ -217,17 +215,23 @@ NS_IMETHODIMP nsPPMDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRU
|
||||
readLen -= i + j;
|
||||
dataLen = readLen; // since this is the first pass, we don't have any data waiting that we need to keep track of
|
||||
|
||||
// XXX this isn't the width/height that was actually requested.. get that from mRequest.
|
||||
mImage->Init(0, 0, w, h, nsIGFXFormat::RGB);
|
||||
mImage->Init(w, h, mObserver);
|
||||
if (mObserver)
|
||||
mObserver->OnStartContainer(nsnull, nsnull, mImage);
|
||||
|
||||
mFrame->Init(0, 0, w, h, nsIGFXFormat::RGB);
|
||||
mImage->AppendFrame(mFrame);
|
||||
if (mObserver)
|
||||
mObserver->OnStartFrame(nsnull, nsnull, mFrame);
|
||||
}
|
||||
|
||||
PRUint32 bpr;
|
||||
gfx_dimension width;
|
||||
mImage->GetBytesPerRow(&bpr);
|
||||
mImage->GetWidth(&width);
|
||||
nscoord width;
|
||||
mFrame->GetImageBytesPerRow(&bpr);
|
||||
mFrame->GetWidth(&width);
|
||||
|
||||
PRUint32 real_bpr = GFXCoordToIntCeil(width) * 3;
|
||||
// XXX ceil?
|
||||
PRUint32 real_bpr = width * 3;
|
||||
|
||||
PRUint32 i = 0;
|
||||
PRUint32 rownum = mDataWritten / real_bpr; // XXX this better not have a decimal
|
||||
@ -238,7 +242,12 @@ NS_IMETHODIMP nsPPMDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRU
|
||||
|
||||
do {
|
||||
PRUint8 *line = (PRUint8*)data + i*real_bpr;
|
||||
mImage->SetBits(line, real_bpr, (rownum++)*bpr);
|
||||
mFrame->SetImageData(line, real_bpr, (rownum++)*bpr);
|
||||
|
||||
nsRect r(0, rownum, width, 1);
|
||||
mObserver->OnDataAvailable(nsnull, nsnull, mFrame, &r);
|
||||
|
||||
|
||||
wroteLen += real_bpr ;
|
||||
i++;
|
||||
} while(dataLen >= real_bpr * (i+1));
|
||||
|
@ -28,8 +28,10 @@
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include "nsIImageContainer.h"
|
||||
#include "nsIImageDecoderObserver.h"
|
||||
#include "nsIImageFrame.h"
|
||||
#include "nsIImageRequest.h"
|
||||
#include "nsIImageRequest2.h"
|
||||
|
||||
#define NS_PPMDECODER_CID \
|
||||
{ /* e90bfa06-1dd1-11b2-8217-f38fe5d431a2 */ \
|
||||
@ -50,8 +52,11 @@ public:
|
||||
virtual ~nsPPMDecoder();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIImageFrame> mImage;
|
||||
nsCOMPtr<nsIImageContainer> mImage;
|
||||
nsCOMPtr<nsIImageFrame> mFrame;
|
||||
nsCOMPtr<nsIImageRequest> mRequest;
|
||||
nsCOMPtr<nsIImageDecoderObserver> mObserver; // this is just qi'd from mRequest for speed
|
||||
|
||||
PRUint32 mDataReceived;
|
||||
PRUint32 mDataWritten;
|
||||
|
||||
|
@ -34,7 +34,7 @@ static nsModuleComponentInfo components[] =
|
||||
{
|
||||
{ "ppm decoder",
|
||||
NS_PPMDECODER_CID,
|
||||
"@mozilla.org/image/decoder?image/x-portable-pixmap;1",
|
||||
"@mozilla.org/image/decoder;2?type=image/x-portable-pixmap",
|
||||
nsPPMDecoderConstructor, },
|
||||
};
|
||||
|
||||
|
Binary file not shown.
3
modules/libpr0n/public/.cvsignore
Normal file
3
modules/libpr0n/public/.cvsignore
Normal file
@ -0,0 +1,3 @@
|
||||
Makefile
|
||||
.deps
|
||||
_xpidlgen
|
4
modules/libpr0n/public/MANIFEST_IDL
Normal file
4
modules/libpr0n/public/MANIFEST_IDL
Normal file
@ -0,0 +1,4 @@
|
||||
nsIImageDecoder.idl
|
||||
nsIImageDecoderObserver.idl
|
||||
nsIImageLoader.idl
|
||||
nsIImageRequest2.idl
|
@ -31,7 +31,7 @@ MODULE = imglib2
|
||||
XPIDLSRCS = nsIImageDecoder.idl \
|
||||
nsIImageDecoderObserver.idl \
|
||||
nsIImageLoader.idl \
|
||||
nsIImageRequest.idl
|
||||
nsIImageRequest2.idl
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
@ -31,7 +31,7 @@ XPIDLSRCS = \
|
||||
.\nsIImageDecoder.idl \
|
||||
.\nsIImageDecoderObserver.idl \
|
||||
.\nsIImageLoader.idl \
|
||||
.\nsIImageRequest.idl \
|
||||
.\nsIImageRequest2.idl \
|
||||
$(NULL)
|
||||
|
||||
|
||||
|
@ -27,9 +27,25 @@
|
||||
|
||||
interface nsIImageRequest;
|
||||
|
||||
/**
|
||||
* nsIImageDecoder interface
|
||||
*
|
||||
* @author Stuart Parmenter <pavlov@netscape.com>
|
||||
* @version 0.1
|
||||
* @see imagelib2
|
||||
*/
|
||||
[scriptable, uuid(9eebf43a-1dd1-11b2-953e-f1782f4cbad3)]
|
||||
interface nsIImageDecoder : nsIOutputStream
|
||||
{
|
||||
/**
|
||||
* Initalize an image decoder.
|
||||
* @param aRequest the request that owns the decoder.
|
||||
*
|
||||
* @note The decode should QI \a aRequest to an nsIImageDecoderObserver
|
||||
* and should send decoder notifications to the request.
|
||||
* The decoder should always pass NULL as the first two parameters to
|
||||
* all of the nsIImageDecoderObserver APIs.
|
||||
*/
|
||||
void init(in nsIImageRequest aRequest);
|
||||
|
||||
/// allows access to the nsIImage we have to put bits in to.
|
||||
|
@ -21,13 +21,17 @@
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIImageContainerObserver.idl"
|
||||
#include "gfxtypes.idl"
|
||||
|
||||
interface nsIImageRequest;
|
||||
interface nsIImageContainer;
|
||||
interface nsIImageFrame;
|
||||
|
||||
%{C++
|
||||
#include "nsRect.h"
|
||||
%}
|
||||
|
||||
/**
|
||||
* nsIImageDecoderObserver interface
|
||||
*
|
||||
@ -36,42 +40,42 @@ interface nsIImageFrame;
|
||||
* @see imagelib2
|
||||
*/
|
||||
[scriptable, uuid(350163d2-1dd2-11b2-9e69-89959ecec1f3)]
|
||||
interface nsIImageDecoderObserver : nsISupports
|
||||
interface nsIImageDecoderObserver : nsIImageContainerObserver
|
||||
{
|
||||
/**
|
||||
* called as soon as the image begins getting decoded
|
||||
*/
|
||||
void onStartDecode(in nsIImageRequest request);
|
||||
void onStartDecode(in nsIImageRequest request, in nsISupports cx);
|
||||
|
||||
/**
|
||||
* called once the image has been inited and therefore has a width and height
|
||||
*/
|
||||
void onStartContainer(in nsIImageRequest request, in nsIImageContainer image);
|
||||
void onStartContainer(in nsIImageRequest request, in nsISupports cx, in nsIImageContainer image);
|
||||
|
||||
/**
|
||||
* called when each frame is created
|
||||
*/
|
||||
void onStartFrame(in nsIImageRequest request, in nsIImageFrame frame);
|
||||
void onStartFrame(in nsIImageRequest request, in nsISupports cx, in nsIImageFrame frame);
|
||||
|
||||
/**
|
||||
* called when some part of the frame has new data in it
|
||||
*/
|
||||
[noscript] void onDataAvailable(in nsIImageRequest request, in nsIImageFrame frame, [const] in nsRect2 rect);
|
||||
[noscript] void onDataAvailable(in nsIImageRequest request, in nsISupports cx, in nsIImageFrame frame, [const] in nsRect rect);
|
||||
|
||||
/**
|
||||
* called when a frame is finished decoding
|
||||
*/
|
||||
void onStopFrame(in nsIImageRequest request, in nsIImageFrame frame);
|
||||
void onStopFrame(in nsIImageRequest request, in nsISupports cx, in nsIImageFrame frame);
|
||||
|
||||
/**
|
||||
* probably not needed. called right before onStopDecode
|
||||
*/
|
||||
void onStopContainer(in nsIImageRequest request, in nsIImageContainer image);
|
||||
void onStopContainer(in nsIImageRequest request, in nsISupports cx, in nsIImageContainer image);
|
||||
|
||||
/**
|
||||
* called when the decoder is dying off
|
||||
*/
|
||||
void onStopDecode(in nsIImageRequest request, in nsresult status,
|
||||
in wstring statusArg);
|
||||
void onStopDecode(in nsIImageRequest request, in nsISupports cx,
|
||||
in nsresult status, in wstring statusArg);
|
||||
|
||||
};
|
||||
|
@ -24,19 +24,42 @@
|
||||
#include "nsISupports.idl"
|
||||
#include "gfxtypes.idl"
|
||||
|
||||
interface nsIImage;
|
||||
interface nsIImageDecoderObserver;
|
||||
interface nsIImageRequest;
|
||||
interface nsISimpleEnumerator;
|
||||
interface nsIStreamListener;
|
||||
interface nsIURI;
|
||||
interface nsIChannel;
|
||||
|
||||
/**
|
||||
* nsIImageLoader interface
|
||||
*
|
||||
* @author Stuart Parmenter <pavlov@netscape.com>
|
||||
* @version 0.1
|
||||
* @see imagelib2
|
||||
*/
|
||||
[scriptable, uuid(4c8cf1e0-1dd2-11b2-aff9-c51cdbfcb6da)]
|
||||
interface nsIImageLoader : nsISupports
|
||||
{
|
||||
nsIImageRequest loadImage(in nsIURI uri);
|
||||
/**
|
||||
* Start the load and decode of an image.
|
||||
* @param uri the URI to load
|
||||
* @param aObserver the observer
|
||||
* @param cx some random data
|
||||
*/
|
||||
nsIImageRequest loadImage(in nsIURI uri, in nsIImageDecoderObserver aObserver, in nsISupports cx);
|
||||
|
||||
/**
|
||||
* Start the load and decode of an image.
|
||||
* @param uri the URI to load
|
||||
* @param aObserver the observer
|
||||
* @param cx some random data
|
||||
*/
|
||||
nsIImageRequest loadImageWithChannel(in nsIChannel aChannel, in nsIImageDecoderObserver aObserver, in nsISupports cx, out nsIStreamListener aListener);
|
||||
|
||||
/**
|
||||
* Returns the channels contained directly in this group.
|
||||
* Enumerator element type: nsIImageRequest.
|
||||
* @note Enumerator element type: nsIImageRequest.
|
||||
*/
|
||||
readonly attribute nsISimpleEnumerator requests;
|
||||
};
|
||||
|
@ -22,23 +22,42 @@
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIRequest.idl"
|
||||
#include "gfxtypes.idl"
|
||||
|
||||
interface nsIChannel;
|
||||
interface nsIImageContainer;
|
||||
|
||||
/**
|
||||
* nsIImageRequest interface
|
||||
*
|
||||
* @author Stuart Parmenter <pavlov@netscape.com>
|
||||
* @version 0.1
|
||||
* @see imagelib2
|
||||
*/
|
||||
[scriptable, uuid(ccf705f6-1dd1-11b2-82ef-e18eccf7f7ec)]
|
||||
interface nsIImageRequest : nsIRequest
|
||||
interface nsIImageRequest : nsISupports
|
||||
{
|
||||
// const values for GetStatus() to be used someday...
|
||||
// const long STATUS_NONE = 0x0;
|
||||
// const long STATUS_SIZE_AVAILABLE = 0x1;
|
||||
// const long STATUS_IMAGE_READY = 0x2;
|
||||
// const long STATUS_ERROR = 0x4;
|
||||
void cancel(in nsresult status);
|
||||
|
||||
void init(in nsIChannel aChannel);
|
||||
|
||||
/// @return the image object associated with the request.
|
||||
/**
|
||||
* the image container...
|
||||
* @return the image object associated with the request.
|
||||
* @attention NEED DOCS
|
||||
*/
|
||||
readonly attribute nsIImageContainer image;
|
||||
|
||||
/**
|
||||
* Bits set in the return value from imageStatus
|
||||
* @name statusflags
|
||||
*/
|
||||
//@{
|
||||
const long STATUS_NONE = 0x0;
|
||||
const long STATUS_SIZE_AVAILABLE = 0x1;
|
||||
const long STATUS_LOAD_COMPLETE = 0x2;
|
||||
const long STATUS_ERROR = 0x4;
|
||||
//@}
|
||||
|
||||
/**
|
||||
* something
|
||||
* @attention NEED DOCS
|
||||
*/
|
||||
readonly attribute unsigned long imageStatus;
|
||||
};
|
2
modules/libpr0n/src/.cvsignore
Normal file
2
modules/libpr0n/src/.cvsignore
Normal file
@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
.deps
|
93
modules/libpr0n/src/ImageCache.cpp
Normal file
93
modules/libpr0n/src/ImageCache.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2001 Netscape Communications Corporation.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
*/
|
||||
|
||||
#include "ImageCache.h"
|
||||
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include "nsHashtable.h"
|
||||
|
||||
class nsIURIKey : public nsHashKey {
|
||||
protected:
|
||||
nsCOMPtr<nsIURI> mKey;
|
||||
|
||||
public:
|
||||
nsIURIKey(nsIURI* key) : mKey(key) {}
|
||||
~nsIURIKey(void) {}
|
||||
|
||||
PRUint32 HashCode(void) const {
|
||||
nsXPIDLCString spec;
|
||||
mKey->GetSpec(getter_Copies(spec));
|
||||
return (PRUint32) PL_HashString(spec);
|
||||
}
|
||||
|
||||
PRBool Equals(const nsHashKey *aKey) const {
|
||||
PRBool eq;
|
||||
mKey->Equals( ((nsIURIKey*) aKey)->mKey, &eq );
|
||||
return eq;
|
||||
}
|
||||
|
||||
nsHashKey *Clone(void) const {
|
||||
return new nsIURIKey(mKey);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ImageCache::ImageCache()
|
||||
{
|
||||
/* member initializers and constructor code */
|
||||
}
|
||||
|
||||
nsSupportsHashtable mCache;
|
||||
|
||||
|
||||
ImageCache::~ImageCache()
|
||||
{
|
||||
/* destructor code */
|
||||
}
|
||||
|
||||
PRBool ImageCache::Put(nsIURI *aKey, nsImageRequest *request)
|
||||
{
|
||||
nsIURIKey key(aKey);
|
||||
return mCache.Put(&key, NS_STATIC_CAST(nsIImageRequest*, request));
|
||||
}
|
||||
|
||||
PRBool ImageCache::Get(nsIURI *aKey, nsImageRequest **request)
|
||||
{
|
||||
nsIURIKey key(aKey);
|
||||
nsImageRequest *sup = NS_REINTERPRET_CAST(nsImageRequest*, NS_STATIC_CAST(nsIImageRequest*, mCache.Get(&key))); // this addrefs
|
||||
|
||||
if (sup) {
|
||||
*request = sup;
|
||||
return PR_TRUE;
|
||||
} else {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool ImageCache::Remove(nsIURI *aKey)
|
||||
{
|
||||
nsIURIKey key(aKey);
|
||||
return mCache.Remove(&key);
|
||||
}
|
53
modules/libpr0n/src/ImageCache.h
Normal file
53
modules/libpr0n/src/ImageCache.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2001 Netscape Communications Corporation.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
*/
|
||||
|
||||
#ifndef ImageCache_h__
|
||||
#define ImageCache_h__
|
||||
|
||||
#include "nsIURI.h"
|
||||
#include "nsImageRequest.h"
|
||||
|
||||
|
||||
#define IMAGE_CACHE_CID \
|
||||
{ /* 70058a20-1dd2-11b2-9d22-db0a9d82e8bd */ \
|
||||
0x70058a20, \
|
||||
0x1dd2, \
|
||||
0x11b2, \
|
||||
{0x9d, 0x22, 0xdb, 0x0a, 0x9d, 0x82, 0xe8, 0xbd} \
|
||||
}
|
||||
|
||||
class ImageCache
|
||||
{
|
||||
public:
|
||||
ImageCache();
|
||||
~ImageCache();
|
||||
|
||||
/* additional members */
|
||||
static PRBool Put(nsIURI *aKey, nsImageRequest *request);
|
||||
static PRBool Get(nsIURI *aKey, nsImageRequest **request);
|
||||
static PRBool Remove(nsIURI *aKey);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
@ -30,9 +30,11 @@ MODULE = imglib2
|
||||
LIBRARY_NAME = imglib2
|
||||
IS_COMPONENT = 1
|
||||
|
||||
CPPSRCS = nsImageFactory.cpp \
|
||||
CPPSRCS = ImageCache.cpp \
|
||||
nsImageFactory.cpp \
|
||||
nsImageLoader.cpp \
|
||||
nsImageRequest.cpp
|
||||
nsImageRequest.cpp \
|
||||
nsImageRequestProxy.cpp
|
||||
|
||||
EXTRA_DSO_LDOPTS = \
|
||||
$(MOZ_COMPONENT_LIBS) \
|
||||
|
@ -30,8 +30,10 @@ DLL = $(OBJDIR)\$(LIBRARY_NAME).dll
|
||||
MAKE_OBJ_TYPE = DLL
|
||||
|
||||
OBJS = \
|
||||
.\$(OBJDIR)\ImageCache.obj \
|
||||
.\$(OBJDIR)\nsImageLoader.obj \
|
||||
.\$(OBJDIR)\nsImageRequest.obj \
|
||||
.\$(OBJDIR)\nsImageRequestProxy.obj \
|
||||
.\$(OBJDIR)\nsImageFactory.obj \
|
||||
$(NULL)
|
||||
|
||||
|
@ -26,11 +26,13 @@
|
||||
|
||||
#include "nsImageLoader.h"
|
||||
#include "nsImageRequest.h"
|
||||
#include "nsImageRequestProxy.h"
|
||||
|
||||
// objects that just require generic constructors
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageLoader)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageRequest)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageRequestProxy)
|
||||
|
||||
static nsModuleComponentInfo components[] =
|
||||
{
|
||||
@ -40,9 +42,12 @@ static nsModuleComponentInfo components[] =
|
||||
nsImageLoaderConstructor, },
|
||||
{ "image request",
|
||||
NS_IMAGEREQUEST_CID,
|
||||
"@mozilla.org/image/request;1",
|
||||
"@mozilla.org/image/request/real;1",
|
||||
nsImageRequestConstructor, },
|
||||
|
||||
{ "image request proxy",
|
||||
NS_IMAGEREQUESTPROXY_CID,
|
||||
"@mozilla.org/image/request/proxy;1",
|
||||
nsImageRequestProxyConstructor, },
|
||||
};
|
||||
|
||||
NS_IMPL_NSGETMODULE("nsImageLib2Module", components)
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#include "nsImageLoader.h"
|
||||
|
||||
#include "nsIImageRequest.h"
|
||||
#include "nsIImageRequest2.h"
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
@ -33,35 +33,57 @@
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
#include "nsImageRequest.h"
|
||||
#include "nsImageRequestProxy.h"
|
||||
|
||||
#include "ImageCache.h"
|
||||
|
||||
#include "nsXPIDLString.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#ifdef LOADER_THREADSAFE
|
||||
#include "nsAutoLock.h"
|
||||
#endif
|
||||
|
||||
static NS_DEFINE_CID(kImageRequestCID, NS_IMAGEREQUEST_CID);
|
||||
static NS_DEFINE_CID(kImageRequestProxyCID, NS_IMAGEREQUESTPROXY_CID);
|
||||
|
||||
#ifdef LOADER_THREADSAFE
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsImageLoader, nsIImageLoader)
|
||||
#else
|
||||
NS_IMPL_ISUPPORTS1(nsImageLoader, nsIImageLoader)
|
||||
#endif
|
||||
|
||||
nsImageLoader::nsImageLoader()
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
/* member initializers and constructor code */
|
||||
#ifdef LOADER_THREADSAFE
|
||||
mLock = PR_NewLock();
|
||||
#endif
|
||||
}
|
||||
|
||||
nsImageLoader::~nsImageLoader()
|
||||
{
|
||||
/* destructor code */
|
||||
#ifdef LOADER_THREADSAFE
|
||||
PR_DestroyLock(mLock);
|
||||
#endif
|
||||
}
|
||||
|
||||
//#define IMAGE_THREADPOOL 1
|
||||
|
||||
/* nsIImageRequest loadImage (in nsIURI uri, in gfx_dimension width, in gfx_dimension height); */
|
||||
NS_IMETHODIMP nsImageLoader::LoadImage(nsIURI *aURI, nsIImageRequest **_retval)
|
||||
/* nsIImageRequest loadImage (in nsIURI uri, in nsIImageDecoderObserver aObserver, in nsISupports cx); */
|
||||
NS_IMETHODIMP nsImageLoader::LoadImage(nsIURI *aURI, nsIImageDecoderObserver *aObserver, nsISupports *cx, nsIImageRequest **_retval)
|
||||
{
|
||||
NS_ASSERTION(aURI, "nsImageLoader::LoadImage -- NULL URI pointer");
|
||||
|
||||
#ifdef IMAGE_THREADPOOL
|
||||
if (!mThreadPool) {
|
||||
NS_NewThreadPool(getter_AddRefs(mThreadPool),
|
||||
1, 4,
|
||||
512,
|
||||
PR_PRIORITY_NORMAL,
|
||||
PR_GLOBAL_THREAD);
|
||||
}
|
||||
nsImageRequest *imgRequest = nsnull;
|
||||
|
||||
ImageCache::Get(aURI, &imgRequest); // addrefs
|
||||
if (!imgRequest) {
|
||||
#ifdef LOADER_THREADSAFE
|
||||
nsAutoLock lock(mLock); // lock when we are adding things to the cache
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIIOService> ioserv(do_GetService("@mozilla.org/network/io-service;1"));
|
||||
if (!ioserv) return NS_ERROR_FAILURE;
|
||||
|
||||
@ -69,21 +91,78 @@ NS_IMETHODIMP nsImageLoader::LoadImage(nsIURI *aURI, nsIImageRequest **_retval)
|
||||
ioserv->NewChannelFromURI(aURI, getter_AddRefs(newChannel));
|
||||
if (!newChannel) return NS_ERROR_FAILURE;
|
||||
|
||||
// XXX do we need to SetOwner here?
|
||||
newChannel->SetOwner(this); // the channel is now holding a strong ref to 'this'
|
||||
|
||||
// XXX look at the progid
|
||||
nsCOMPtr<nsIImageRequest> imgRequest(do_CreateInstance("@mozilla.org/image/request;1"));
|
||||
nsCOMPtr<nsIImageRequest> req(do_CreateInstance(kImageRequestCID));
|
||||
imgRequest = NS_REINTERPRET_CAST(nsImageRequest*, req.get());
|
||||
NS_ADDREF(imgRequest);
|
||||
|
||||
imgRequest->Init(newChannel);
|
||||
|
||||
#ifdef IMAGE_THREADPOOL
|
||||
nsCOMPtr<nsIRunnable> run(do_QueryInterface(imgRequest));
|
||||
mThreadPool->DispatchRequest(run);
|
||||
#else
|
||||
nsCOMPtr<nsIStreamListener> streamList(do_QueryInterface(imgRequest));
|
||||
newChannel->AsyncRead(streamList, nsnull);
|
||||
ImageCache::Put(aURI, imgRequest);
|
||||
|
||||
newChannel->AsyncRead(NS_STATIC_CAST(nsIStreamListener *, imgRequest), cx); // XXX are we calling this too early?
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIImageRequest> proxyRequest(do_CreateInstance(kImageRequestProxyCID));
|
||||
// init adds itself to imgRequest's list of observers
|
||||
NS_REINTERPRET_CAST(nsImageRequestProxy*, proxyRequest.get())->Init(imgRequest, aObserver, cx);
|
||||
|
||||
NS_RELEASE(imgRequest);
|
||||
|
||||
*_retval = proxyRequest;
|
||||
NS_ADDREF(*_retval);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* nsIImageRequest loadImageWithChannel(in nsIChannel, in nsIImageDecoderObserver aObserver, in nsISupports cx, out nsIStreamListener); */
|
||||
NS_IMETHODIMP nsImageLoader::LoadImageWithChannel(nsIChannel *channel, nsIImageDecoderObserver *aObserver, nsISupports *cx, nsIStreamListener **listener, nsIImageRequest **_retval)
|
||||
{
|
||||
NS_ASSERTION(channel, "nsImageLoader::LoadImageWithChannel -- NULL channel pointer");
|
||||
|
||||
nsImageRequest *imgRequest = nsnull;
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
channel->GetURI(getter_AddRefs(uri));
|
||||
|
||||
ImageCache::Get(uri, &imgRequest);
|
||||
if (imgRequest) {
|
||||
// we have this in our cache already.. cancel the current (document) load
|
||||
|
||||
// XXX
|
||||
// if *listener is null when we return here, the caller should probably cancel
|
||||
// the channel instead of us doing it here.
|
||||
channel->Cancel(NS_BINDING_ABORTED); // this should fire an OnStopRequest
|
||||
|
||||
*listener = nsnull; // give them back a null nsIStreamListener
|
||||
} else {
|
||||
#ifdef LOADER_THREADSAFE
|
||||
nsAutoLock lock(mLock); // lock when we are adding things to the cache
|
||||
#endif
|
||||
|
||||
*_retval = imgRequest;
|
||||
nsCOMPtr<nsIImageRequest> req(do_CreateInstance(kImageRequestCID));
|
||||
|
||||
imgRequest = NS_REINTERPRET_CAST(nsImageRequest*, req.get());
|
||||
NS_ADDREF(imgRequest);
|
||||
|
||||
imgRequest->Init(channel);
|
||||
|
||||
ImageCache::Put(uri, imgRequest);
|
||||
|
||||
*listener = NS_STATIC_CAST(nsIStreamListener*, imgRequest);
|
||||
NS_IF_ADDREF(*listener);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIImageRequest> proxyRequest(do_CreateInstance(kImageRequestProxyCID));
|
||||
|
||||
// init adds itself to imgRequest's list of observers
|
||||
NS_REINTERPRET_CAST(nsImageRequestProxy*, proxyRequest.get())->Init(imgRequest, aObserver, cx);
|
||||
|
||||
NS_RELEASE(imgRequest);
|
||||
|
||||
*_retval = proxyRequest;
|
||||
NS_ADDREF(*_retval);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -21,9 +21,13 @@
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
*/
|
||||
|
||||
//#define LOADER_THREADSAFE 1
|
||||
|
||||
#include "nsIImageLoader.h"
|
||||
#include "nsIThreadPool.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#ifdef LOADER_THREADSAFE
|
||||
#include "prlock.h"
|
||||
#endif
|
||||
|
||||
#define NS_IMAGELOADER_CID \
|
||||
{ /* 9f6a0d2e-1dd1-11b2-a5b8-951f13c846f7 */ \
|
||||
@ -43,5 +47,7 @@ public:
|
||||
virtual ~nsImageLoader();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIThreadPool> mThreadPool;
|
||||
#ifdef LOADER_THREADSAFE
|
||||
PRLock *mLock;
|
||||
#endif
|
||||
};
|
||||
|
@ -35,18 +35,18 @@
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "ImageCache.h"
|
||||
|
||||
#include "nspr.h"
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS5(nsImageRequest, nsIImageRequest, nsIRequest, nsIStreamListener, nsIStreamObserver, nsIRunnable)
|
||||
NS_IMPL_ISUPPORTS5(nsImageRequest, nsIImageRequest,
|
||||
nsIImageDecoderObserver, nsIImageContainerObserver,
|
||||
nsIStreamListener, nsIStreamObserver)
|
||||
|
||||
nsImageRequest::nsImageRequest()
|
||||
nsImageRequest::nsImageRequest() :
|
||||
mObservers(0), mProcessing(PR_TRUE), mStatus(nsIImageRequest::STATUS_NONE), mState(0)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
/* member initializers and constructor code */
|
||||
mProcessing = PR_TRUE;
|
||||
}
|
||||
|
||||
nsImageRequest::~nsImageRequest()
|
||||
@ -55,12 +55,12 @@ nsImageRequest::~nsImageRequest()
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* void init (in nsIChannel aChannel, in gfx_dimension width, in gfx_dimension height); */
|
||||
NS_IMETHODIMP nsImageRequest::Init(nsIChannel *aChannel)
|
||||
nsresult nsImageRequest::Init(nsIChannel *aChannel)
|
||||
{
|
||||
if (mImage)
|
||||
return NS_ERROR_FAILURE; // XXX
|
||||
// XXX we should save off the thread we are getting called on here so that we can proxy all calls to mDecoder to it.
|
||||
|
||||
NS_ASSERTION(!mImage, "nsImageRequest::Init -- Multiple calls to init");
|
||||
NS_ASSERTION(aChannel, "nsImageRequest::Init -- No channel");
|
||||
|
||||
mChannel = aChannel;
|
||||
|
||||
@ -70,6 +70,52 @@ NS_IMETHODIMP nsImageRequest::Init(nsIChannel *aChannel)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsImageRequest::AddObserver(nsIImageDecoderObserver *observer)
|
||||
{
|
||||
mObservers.AppendElement(NS_STATIC_CAST(void*, observer));
|
||||
|
||||
if (mState & onStartDecode)
|
||||
observer->OnStartDecode(nsnull, nsnull);
|
||||
if (mState & onStartContainer)
|
||||
observer->OnStartContainer(nsnull, nsnull, mImage);
|
||||
|
||||
// XXX send the decoded rect in here
|
||||
|
||||
if (mState & onStopContainer)
|
||||
observer->OnStopContainer(nsnull, nsnull, mImage);
|
||||
if (mState & onStopDecode)
|
||||
observer->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsImageRequest::RemoveObserver(nsIImageDecoderObserver *observer, nsresult status)
|
||||
{
|
||||
mObservers.RemoveElement(NS_STATIC_CAST(void*, observer));
|
||||
|
||||
if ((mObservers.Count() == 0) && mChannel && mProcessing) {
|
||||
mChannel->Cancel(status);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** nsIImageRequest methods **/
|
||||
|
||||
|
||||
/* void cancel (in nsresult status); */
|
||||
NS_IMETHODIMP nsImageRequest::Cancel(nsresult status)
|
||||
{
|
||||
// XXX this method should not ever get called
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (mChannel && mProcessing) {
|
||||
rv = mChannel->Cancel(status);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIImage image; */
|
||||
NS_IMETHODIMP nsImageRequest::GetImage(nsIImageContainer * *aImage)
|
||||
{
|
||||
@ -78,113 +124,142 @@ NS_IMETHODIMP nsImageRequest::GetImage(nsIImageContainer * *aImage)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** nsIRequest methods **/
|
||||
|
||||
/* readonly attribute wstring name; */
|
||||
NS_IMETHODIMP nsImageRequest::GetName(PRUnichar * *aName)
|
||||
/* readonly attribute unsigned long imageStatus; */
|
||||
NS_IMETHODIMP nsImageRequest::GetImageStatus(PRUint32 *aStatus)
|
||||
{
|
||||
return mChannel->GetName(aName);
|
||||
}
|
||||
|
||||
/* boolean isPending (); */
|
||||
NS_IMETHODIMP nsImageRequest::IsPending(PRBool *_retval)
|
||||
{
|
||||
return mChannel->IsPending(_retval);
|
||||
}
|
||||
|
||||
/* readonly attribute nsresult status; */
|
||||
NS_IMETHODIMP nsImageRequest::GetStatus(nsresult *aStatus)
|
||||
{
|
||||
return mChannel->GetStatus(aStatus);
|
||||
}
|
||||
|
||||
/* void cancel (in nsresult status); */
|
||||
NS_IMETHODIMP nsImageRequest::Cancel(nsresult status)
|
||||
{
|
||||
return mChannel->Cancel(status);
|
||||
}
|
||||
|
||||
/* void suspend (); */
|
||||
NS_IMETHODIMP nsImageRequest::Suspend()
|
||||
{
|
||||
return mChannel->Suspend();
|
||||
}
|
||||
|
||||
/* void resume (); */
|
||||
NS_IMETHODIMP nsImageRequest::Resume()
|
||||
{
|
||||
return mChannel->Resume();
|
||||
*aStatus = mStatus;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** nsIImageContainerObserver methods **/
|
||||
|
||||
/* [noscript] void frameChanged (in nsIImageContainer container, in nsISupports cx, in nsIImageFrame newframe, in nsRect dirtyRect); */
|
||||
NS_IMETHODIMP nsImageRequest::FrameChanged(nsIImageContainer *container, nsISupports *cx, nsIImageFrame *newframe, nsRect * dirtyRect)
|
||||
{
|
||||
PRInt32 i = -1;
|
||||
PRInt32 count = mObservers.Count();
|
||||
|
||||
while (++i < count) {
|
||||
nsIImageDecoderObserver *ob = NS_STATIC_CAST(nsIImageDecoderObserver*, mObservers[i]);
|
||||
if (ob) ob->FrameChanged(container, cx, newframe, dirtyRect);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** nsIImageDecoderObserver methods **/
|
||||
|
||||
/* void onStartDecode (in nsIImageRequest request); */
|
||||
NS_IMETHODIMP nsImageRequest::OnStartDecode(nsIImageRequest *request)
|
||||
/* void onStartDecode (in nsIImageRequest request, in nsISupports cx); */
|
||||
NS_IMETHODIMP nsImageRequest::OnStartDecode(nsIImageRequest *request, nsISupports *cx)
|
||||
{
|
||||
if (mObserver)
|
||||
mObserver->OnStartDecode(this);
|
||||
mState |= onStartDecode;
|
||||
|
||||
PRInt32 i = -1;
|
||||
PRInt32 count = mObservers.Count();
|
||||
|
||||
while (++i < count) {
|
||||
nsIImageDecoderObserver *ob = NS_STATIC_CAST(nsIImageDecoderObserver*, mObservers[i]);
|
||||
if (ob) ob->OnStartDecode(request, cx);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onStartContainer (in nsIImageRequest request, in nsIImageContainer image); */
|
||||
NS_IMETHODIMP nsImageRequest::OnStartContainer(nsIImageRequest *request, nsIImageContainer *image)
|
||||
/* void onStartContainer (in nsIImageRequest request, in nsISupports cx, in nsIImageContainer image); */
|
||||
NS_IMETHODIMP nsImageRequest::OnStartContainer(nsIImageRequest *request, nsISupports *cx, nsIImageContainer *image)
|
||||
{
|
||||
if (mObserver)
|
||||
mObserver->OnStartContainer(this, image);
|
||||
mState |= onStartContainer;
|
||||
|
||||
mStatus |= nsIImageRequest::STATUS_SIZE_AVAILABLE;
|
||||
|
||||
PRInt32 i = -1;
|
||||
PRInt32 count = mObservers.Count();
|
||||
|
||||
while (++i < count) {
|
||||
nsIImageDecoderObserver *ob = NS_STATIC_CAST(nsIImageDecoderObserver*, mObservers[i]);
|
||||
if (ob) ob->OnStartContainer(request, cx, image);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onStartFrame (in nsIImageRequest request, in nsIImageFrame frame); */
|
||||
NS_IMETHODIMP nsImageRequest::OnStartFrame(nsIImageRequest *request, nsIImageFrame *frame)
|
||||
/* void onStartFrame (in nsIImageRequest request, in nsISupports cx, in nsIImageFrame frame); */
|
||||
NS_IMETHODIMP nsImageRequest::OnStartFrame(nsIImageRequest *request, nsISupports *cx, nsIImageFrame *frame)
|
||||
{
|
||||
if (mObserver)
|
||||
mObserver->OnStartFrame(this, frame);
|
||||
PRInt32 i = -1;
|
||||
PRInt32 count = mObservers.Count();
|
||||
|
||||
while (++i < count) {
|
||||
nsIImageDecoderObserver *ob = NS_STATIC_CAST(nsIImageDecoderObserver*, mObservers[i]);
|
||||
if (ob) ob->OnStartFrame(request, cx, frame);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [noscript] void onDataAvailable (in nsIImageRequest request, in nsIImageFrame frame, [const] in nsRect2 rect); */
|
||||
NS_IMETHODIMP nsImageRequest::OnDataAvailable(nsIImageRequest *request, nsIImageFrame *frame, const nsRect2 * rect)
|
||||
/* [noscript] void onDataAvailable (in nsIImageRequest request, in nsISupports cx, in nsIImageFrame frame, [const] in nsRect rect); */
|
||||
NS_IMETHODIMP nsImageRequest::OnDataAvailable(nsIImageRequest *request, nsISupports *cx, nsIImageFrame *frame, const nsRect * rect)
|
||||
{
|
||||
if (mObserver)
|
||||
mObserver->OnDataAvailable(this, frame, rect);
|
||||
PRInt32 i = -1;
|
||||
PRInt32 count = mObservers.Count();
|
||||
|
||||
while (++i < count) {
|
||||
nsIImageDecoderObserver *ob = NS_STATIC_CAST(nsIImageDecoderObserver*, mObservers[i]);
|
||||
if (ob) ob->OnDataAvailable(request, cx, frame, rect);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onStopFrame (in nsIImageRequest request, in nsIImageFrame frame); */
|
||||
NS_IMETHODIMP nsImageRequest::OnStopFrame(nsIImageRequest *request, nsIImageFrame *frame)
|
||||
/* void onStopFrame (in nsIImageRequest request, in nsISupports cx, in nsIImageFrame frame); */
|
||||
NS_IMETHODIMP nsImageRequest::OnStopFrame(nsIImageRequest *request, nsISupports *cx, nsIImageFrame *frame)
|
||||
{
|
||||
if (mObserver)
|
||||
mObserver->OnStopFrame(this, frame);
|
||||
PRInt32 i = -1;
|
||||
PRInt32 count = mObservers.Count();
|
||||
|
||||
while (++i < count) {
|
||||
nsIImageDecoderObserver *ob = NS_STATIC_CAST(nsIImageDecoderObserver*, mObservers[i]);
|
||||
if (ob) ob->OnStopFrame(request, cx, frame);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onStopContainer (in nsIImageRequest request, in nsIImageContainer image); */
|
||||
NS_IMETHODIMP nsImageRequest::OnStopContainer(nsIImageRequest *request, nsIImageContainer *image)
|
||||
/* void onStopContainer (in nsIImageRequest request, in nsISupports cx, in nsIImageContainer image); */
|
||||
NS_IMETHODIMP nsImageRequest::OnStopContainer(nsIImageRequest *request, nsISupports *cx, nsIImageContainer *image)
|
||||
{
|
||||
if (mObserver)
|
||||
mObserver->OnStopContainer(this, image);
|
||||
mState |= onStopContainer;
|
||||
|
||||
|
||||
PRInt32 i = -1;
|
||||
PRInt32 count = mObservers.Count();
|
||||
|
||||
while (++i < count) {
|
||||
nsIImageDecoderObserver *ob = NS_STATIC_CAST(nsIImageDecoderObserver*, mObservers[i]);
|
||||
if (ob) ob->OnStopContainer(request, cx, image);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onStopDecode (in nsIImageRequest request, in nsresult status, in wstring statusArg); */
|
||||
NS_IMETHODIMP nsImageRequest::OnStopDecode(nsIImageRequest *request, nsresult status, const PRUnichar *statusArg)
|
||||
/* void onStopDecode (in nsIImageRequest request, in nsISupports cx, in nsresult status, in wstring statusArg); */
|
||||
NS_IMETHODIMP nsImageRequest::OnStopDecode(nsIImageRequest *request, nsISupports *cx, nsresult status, const PRUnichar *statusArg)
|
||||
{
|
||||
if (mObserver)
|
||||
mObserver->OnStopDecode(this, status, statusArg);
|
||||
mState |= onStopDecode;
|
||||
|
||||
if (NS_FAILED(status))
|
||||
mStatus = nsIImageRequest::STATUS_ERROR;
|
||||
|
||||
PRInt32 i = -1;
|
||||
PRInt32 count = mObservers.Count();
|
||||
|
||||
while (++i < count) {
|
||||
nsIImageDecoderObserver *ob = NS_STATIC_CAST(nsIImageDecoderObserver*, mObservers[i]);
|
||||
if (ob) ob->OnStopDecode(request, cx, status, statusArg);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -199,13 +274,14 @@ NS_IMETHODIMP nsImageRequest::OnStopDecode(nsIImageRequest *request, nsresult st
|
||||
/* void onStartRequest (in nsIChannel channel, in nsISupports ctxt); */
|
||||
NS_IMETHODIMP nsImageRequest::OnStartRequest(nsIChannel *channel, nsISupports *ctxt)
|
||||
{
|
||||
NS_ASSERTION(!mDecoder, "nsImageRequest::OnStartRequest -- we already have a decoder");
|
||||
|
||||
nsXPIDLCString contentType;
|
||||
channel->GetContentType(getter_Copies(contentType));
|
||||
printf("content type is %s\n", contentType.get());
|
||||
|
||||
nsCAutoString conid("@mozilla.org/image/decoder?");
|
||||
nsCAutoString conid("@mozilla.org/image/decoder;2?type=");
|
||||
conid += contentType.get();
|
||||
conid += ";1";
|
||||
|
||||
mDecoder = do_CreateInstance(conid);
|
||||
|
||||
@ -225,11 +301,26 @@ NS_IMETHODIMP nsImageRequest::OnStartRequest(nsIChannel *channel, nsISupports *c
|
||||
/* void onStopRequest (in nsIChannel channel, in nsISupports ctxt, in nsresult status, in wstring statusArg); */
|
||||
NS_IMETHODIMP nsImageRequest::OnStopRequest(nsIChannel *channel, nsISupports *ctxt, nsresult status, const PRUnichar *statusArg)
|
||||
{
|
||||
NS_ASSERTION(mChannel || mProcessing, "nsImageRequest::OnStopRequest -- received multiple OnStopRequest");
|
||||
|
||||
mProcessing = PR_FALSE;
|
||||
|
||||
// if we failed, we should remove ourself from the cache
|
||||
if (NS_FAILED(status)) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
channel->GetURI(getter_AddRefs(uri));
|
||||
ImageCache::Remove(uri);
|
||||
}
|
||||
|
||||
mChannel = nsnull; // we no longer need the channel
|
||||
|
||||
if (!mDecoder) return NS_ERROR_FAILURE;
|
||||
|
||||
return mDecoder->Close();
|
||||
mDecoder->Close();
|
||||
|
||||
mDecoder = nsnull; // release the decoder so that it can rest peacefully ;)
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -240,57 +331,11 @@ NS_IMETHODIMP nsImageRequest::OnStopRequest(nsIChannel *channel, nsISupports *ct
|
||||
/* void onDataAvailable (in nsIChannel channel, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long sourceOffset, in unsigned long count); */
|
||||
NS_IMETHODIMP nsImageRequest::OnDataAvailable(nsIChannel *channel, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count)
|
||||
{
|
||||
if (!mDecoder) return NS_ERROR_FAILURE;
|
||||
if (!mDecoder) {
|
||||
NS_ASSERTION(mDecoder, "nsImageRequest::OnDataAvailable -- no decoder");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PRUint32 wrote;
|
||||
return mDecoder->WriteFrom(inStr, count, &wrote);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** nsIRunnable methods **/
|
||||
|
||||
NS_IMETHODIMP nsImageRequest::Run()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (!mChannel) return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
// create an event queue for this thread.
|
||||
nsCOMPtr<nsIEventQueueService> service = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = service->CreateThreadEventQueue();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIEventQueue> currentThreadQ;
|
||||
rv = service->GetThreadEventQueue(NS_CURRENT_THREAD,
|
||||
getter_AddRefs(currentThreadQ));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// initiate the AsyncRead from this thread so events are
|
||||
// sent here for processing.
|
||||
rv = mChannel->AsyncRead(NS_STATIC_CAST(nsIStreamListener*, this), nsnull);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// process events until we're finished.
|
||||
PLEvent *event;
|
||||
while (mProcessing) {
|
||||
rv = currentThreadQ->WaitForEvent(&event);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = currentThreadQ->HandleEvent(event);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
rv = service->DestroyThreadEventQueue();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX make sure cleanup happens on the calling thread.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -21,7 +21,10 @@
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
*/
|
||||
|
||||
#include "nsIImageRequest.h"
|
||||
#ifndef nsImageRequest_h__
|
||||
#define nsImageRequest_h__
|
||||
|
||||
#include "nsIImageRequest2.h"
|
||||
|
||||
#include "nsIRunnable.h"
|
||||
|
||||
@ -32,6 +35,8 @@
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
#define NS_IMAGEREQUEST_CID \
|
||||
{ /* 9f733dd6-1dd1-11b2-8cdf-effb70d1ea71 */ \
|
||||
0x9f733dd6, \
|
||||
@ -40,28 +45,44 @@
|
||||
{0x8c, 0xdf, 0xef, 0xfb, 0x70, 0xd1, 0xea, 0x71} \
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
onStartDecode = 0x1,
|
||||
onStartContainer = 0x2,
|
||||
onStopContainer = 0x4,
|
||||
onStopDecode = 0x8
|
||||
};
|
||||
|
||||
class nsImageRequest : public nsIImageRequest,
|
||||
public nsIImageDecoderObserver,
|
||||
public nsIStreamListener, public nsIRunnable
|
||||
public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIIMAGEREQUEST
|
||||
NS_DECL_NSIIMAGEDECODEROBSERVER
|
||||
NS_DECL_NSIREQUEST
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSISTREAMOBSERVER
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
nsImageRequest();
|
||||
virtual ~nsImageRequest();
|
||||
|
||||
/* additional members */
|
||||
nsresult Init(nsIChannel *aChannel);
|
||||
nsresult AddObserver(nsIImageDecoderObserver *observer);
|
||||
nsresult RemoveObserver(nsIImageDecoderObserver *observer, nsresult status);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIIMAGEREQUEST
|
||||
NS_DECL_NSIIMAGECONTAINEROBSERVER
|
||||
NS_DECL_NSIIMAGEDECODEROBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSISTREAMOBSERVER
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
nsCOMPtr<nsIImageContainer> mImage;
|
||||
nsCOMPtr<nsIImageDecoder> mDecoder;
|
||||
nsCOMPtr<nsIImageDecoderObserver> mObserver;
|
||||
|
||||
nsVoidArray mObservers;
|
||||
|
||||
PRBool mProcessing;
|
||||
PRUint32 mStatus;
|
||||
PRUint32 mState;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
171
modules/libpr0n/src/nsImageRequestProxy.cpp
Normal file
171
modules/libpr0n/src/nsImageRequestProxy.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2001 Netscape Communications Corporation.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
*/
|
||||
|
||||
#include "nsImageRequestProxy.h"
|
||||
|
||||
#include "nsXPIDLString.h"
|
||||
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIImageLoader.h"
|
||||
#include "nsIComponentManager.h"
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
#include "nsImageRequest.h"
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
#include "nsIChannel.h"
|
||||
|
||||
#include "nspr.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsImageRequestProxy, nsIImageRequest, nsIImageDecoderObserver, nsIImageContainerObserver)
|
||||
|
||||
nsImageRequestProxy::nsImageRequestProxy()
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
/* member initializers and constructor code */
|
||||
}
|
||||
|
||||
nsImageRequestProxy::~nsImageRequestProxy()
|
||||
{
|
||||
/* destructor code */
|
||||
NS_REINTERPRET_CAST(nsImageRequest*, mOwner.get())->RemoveObserver(this, NS_ERROR_FAILURE); // XXX bogus result value
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsresult nsImageRequestProxy::Init(nsImageRequest *request, nsIImageDecoderObserver *aObserver, nsISupports *cx)
|
||||
{
|
||||
PR_ASSERT(request);
|
||||
|
||||
mOwner = NS_STATIC_CAST(nsIImageRequest*, request);
|
||||
|
||||
mObserver = aObserver;
|
||||
// XXX we should save off the thread we are getting called on here so that we can proxy all calls to mDecoder to it.
|
||||
|
||||
mContext = cx;
|
||||
|
||||
request->AddObserver(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* void cancel (in nsresult status); */
|
||||
NS_IMETHODIMP nsImageRequestProxy::Cancel(nsresult status)
|
||||
{
|
||||
return NS_REINTERPRET_CAST(nsImageRequest*, mOwner.get())->RemoveObserver(this, status);
|
||||
}
|
||||
|
||||
/* readonly attribute nsIImage image; */
|
||||
NS_IMETHODIMP nsImageRequestProxy::GetImage(nsIImageContainer * *aImage)
|
||||
{
|
||||
return mOwner->GetImage(aImage);
|
||||
}
|
||||
|
||||
/* readonly attribute unsigned long imageStatus; */
|
||||
NS_IMETHODIMP nsImageRequestProxy::GetImageStatus(PRUint32 *aStatus)
|
||||
{
|
||||
return mOwner->GetImageStatus(aStatus);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** nsIImageContainerObserver methods **/
|
||||
|
||||
/* [noscript] void frameChanged (in nsIImageContainer container, in nsISupports cx, in nsIImageFrame newframe, in nsRect dirtyRect); */
|
||||
NS_IMETHODIMP nsImageRequestProxy::FrameChanged(nsIImageContainer *container, nsISupports *cx, nsIImageFrame *newframe, nsRect * dirtyRect)
|
||||
{
|
||||
if (mObserver)
|
||||
mObserver->FrameChanged(container, mContext, newframe, dirtyRect);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** nsIImageDecoderObserver methods **/
|
||||
|
||||
/* void onStartDecode (in nsIImageRequest request, in nsISupports cx); */
|
||||
NS_IMETHODIMP nsImageRequestProxy::OnStartDecode(nsIImageRequest *request, nsISupports *cx)
|
||||
{
|
||||
if (mObserver)
|
||||
mObserver->OnStartDecode(this, mContext);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onStartContainer (in nsIImageRequest request, in nsISupports cx, in nsIImageContainer image); */
|
||||
NS_IMETHODIMP nsImageRequestProxy::OnStartContainer(nsIImageRequest *request, nsISupports *cx, nsIImageContainer *image)
|
||||
{
|
||||
if (mObserver)
|
||||
mObserver->OnStartContainer(this, mContext, image);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onStartFrame (in nsIImageRequest request, in nsISupports cx, in nsIImageFrame frame); */
|
||||
NS_IMETHODIMP nsImageRequestProxy::OnStartFrame(nsIImageRequest *request, nsISupports *cx, nsIImageFrame *frame)
|
||||
{
|
||||
if (mObserver)
|
||||
mObserver->OnStartFrame(this, mContext, frame);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [noscript] void onDataAvailable (in nsIImageRequest request, in nsISupports cx, in nsIImageFrame frame, [const] in nsRect rect); */
|
||||
NS_IMETHODIMP nsImageRequestProxy::OnDataAvailable(nsIImageRequest *request, nsISupports *cx, nsIImageFrame *frame, const nsRect * rect)
|
||||
{
|
||||
if (mObserver)
|
||||
mObserver->OnDataAvailable(this, mContext, frame, rect);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onStopFrame (in nsIImageRequest request, in nsISupports cx, in nsIImageFrame frame); */
|
||||
NS_IMETHODIMP nsImageRequestProxy::OnStopFrame(nsIImageRequest *request, nsISupports *cx, nsIImageFrame *frame)
|
||||
{
|
||||
if (mObserver)
|
||||
mObserver->OnStopFrame(this, mContext, frame);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onStopContainer (in nsIImageRequest request, in nsISupports cx, in nsIImageContainer image); */
|
||||
NS_IMETHODIMP nsImageRequestProxy::OnStopContainer(nsIImageRequest *request, nsISupports *cx, nsIImageContainer *image)
|
||||
{
|
||||
if (mObserver)
|
||||
mObserver->OnStopContainer(this, mContext, image);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onStopDecode (in nsIImageRequest request, in nsISupports cx, in nsresult status, in wstring statusArg); */
|
||||
NS_IMETHODIMP nsImageRequestProxy::OnStopDecode(nsIImageRequest *request, nsISupports *cx, nsresult status, const PRUnichar *statusArg)
|
||||
{
|
||||
if (mObserver)
|
||||
mObserver->OnStopDecode(this, mContext, status, statusArg);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
60
modules/libpr0n/src/nsImageRequestProxy.h
Normal file
60
modules/libpr0n/src/nsImageRequestProxy.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2001 Netscape Communications Corporation.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
*/
|
||||
|
||||
#include "nsImageRequest.h"
|
||||
#include "nsIImageDecoderObserver.h"
|
||||
|
||||
#include "nsIImageContainer.h"
|
||||
#include "nsIImageDecoder.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#define NS_IMAGEREQUESTPROXY_CID \
|
||||
{ /* 20557898-1dd2-11b2-8f65-9c462ee2bc95 */ \
|
||||
0x20557898, \
|
||||
0x1dd2, \
|
||||
0x11b2, \
|
||||
{0x8f, 0x65, 0x9c, 0x46, 0x2e, 0xe2, 0xbc, 0x95} \
|
||||
}
|
||||
|
||||
class nsImageRequestProxy : public nsIImageRequest,
|
||||
public nsIImageDecoderObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIIMAGEREQUEST
|
||||
NS_DECL_NSIIMAGEDECODEROBSERVER
|
||||
NS_DECL_NSIIMAGECONTAINEROBSERVER
|
||||
|
||||
nsImageRequestProxy();
|
||||
virtual ~nsImageRequestProxy();
|
||||
|
||||
/* additional members */
|
||||
nsresult Init(nsImageRequest *request, nsIImageDecoderObserver *aObserver, nsISupports *cx);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIImageDecoderObserver> mObserver;
|
||||
|
||||
nsCOMPtr<nsISupports> mContext;
|
||||
|
||||
nsCOMPtr<nsIImageRequest> mOwner;
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user