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
|
include $(DEPTH)/config/autoconf.mk
|
||||||
|
|
||||||
DIRS = ppm png
|
DIRS = ppm png gif jpeg
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
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 "nspr.h"
|
||||||
|
|
||||||
#include "nsUnitConverters.h"
|
|
||||||
|
|
||||||
#include "nsCRT.h"
|
#include "nsCRT.h"
|
||||||
|
|
||||||
|
#include "nsIComponentManager.h"
|
||||||
|
|
||||||
|
#include "nsIImageContainerObserver.h"
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS2(nsJPEGDecoder, nsIImageDecoder, nsIOutputStream)
|
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. */
|
/* Normal JFIF markers can't have more bytes than this. */
|
||||||
#define MAX_JPEG_MARKER_LENGTH (((PRUint32)1 << 16) - 1)
|
#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
|
* 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! */
|
/* public fields; must be first in this struct! */
|
||||||
struct jpeg_source_mgr pub;
|
struct jpeg_source_mgr pub;
|
||||||
|
|
||||||
|
|
||||||
nsJPEGDecoder *decoder;
|
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;
|
} decoder_source_mgr;
|
||||||
|
|
||||||
|
|
||||||
@ -88,10 +64,8 @@ nsJPEGDecoder::nsJPEGDecoder()
|
|||||||
|
|
||||||
mState = JPEG_HEADER;
|
mState = JPEG_HEADER;
|
||||||
|
|
||||||
mBuf = nsnull;
|
mDataLen = 0;
|
||||||
mBufLen = 0;
|
|
||||||
|
|
||||||
mCurDataLen = 0;
|
|
||||||
mSamples = nsnull;
|
mSamples = nsnull;
|
||||||
mSamples3 = nsnull;
|
mSamples3 = nsnull;
|
||||||
|
|
||||||
@ -110,15 +84,22 @@ nsJPEGDecoder::~nsJPEGDecoder()
|
|||||||
NS_IMETHODIMP nsJPEGDecoder::Init(nsIImageRequest *aRequest)
|
NS_IMETHODIMP nsJPEGDecoder::Init(nsIImageRequest *aRequest)
|
||||||
{
|
{
|
||||||
mRequest = aRequest;
|
mRequest = aRequest;
|
||||||
|
mObserver = do_QueryInterface(mRequest);
|
||||||
|
|
||||||
aRequest->GetImage(getter_AddRefs(mImage));
|
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 */
|
/* Step 1: allocate and initialize JPEG decompression object */
|
||||||
|
|
||||||
/* Now we can initialize the JPEG decompression object. */
|
/* Now we can initialize the JPEG decompression object. */
|
||||||
jpeg_create_decompress(&mInfo);
|
jpeg_create_decompress(&mInfo);
|
||||||
|
|
||||||
|
|
||||||
|
/* Step 2: specify data source (eg, a file) */
|
||||||
decoder_source_mgr *src;
|
decoder_source_mgr *src;
|
||||||
|
|
||||||
if (mInfo.src == NULL) {
|
if (mInfo.src == NULL) {
|
||||||
@ -181,15 +162,12 @@ NS_IMETHODIMP nsJPEGDecoder::GetRequest(nsIImageRequest * *aRequest)
|
|||||||
/* void close (); */
|
/* void close (); */
|
||||||
NS_IMETHODIMP nsJPEGDecoder::Close()
|
NS_IMETHODIMP nsJPEGDecoder::Close()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// XXX this should flush the data out
|
||||||
|
|
||||||
|
|
||||||
// XXX progressive? ;)
|
// XXX progressive? ;)
|
||||||
OutputScanlines(mInfo.output_height);
|
// 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Step 8: Release JPEG decompression object */
|
/* 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. */
|
/* This is an important step since it will release a good deal of memory. */
|
||||||
jpeg_destroy_decompress(&mInfo);
|
jpeg_destroy_decompress(&mInfo);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
printf("nsJPEGDecoder::Close()\n");
|
|
||||||
|
|
||||||
|
|
||||||
PR_FREEIF(mBuf);
|
|
||||||
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,44 +199,25 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR
|
|||||||
*/
|
*/
|
||||||
// XXX above what is this?
|
// XXX above what is this?
|
||||||
|
|
||||||
PRUint32 readLen;
|
if (inStr) {
|
||||||
|
mOutStream->WriteFrom(inStr, count, _retval);
|
||||||
if (!mBuf) {
|
mDataLen += *_retval;
|
||||||
mBuf = (char*)PR_Malloc(count);
|
|
||||||
mBufLen = count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Register new buffer contents with data source manager. */
|
||||||
/* Register new buffer contents with data source manager. */
|
|
||||||
|
|
||||||
decoder_source_mgr *src = NS_REINTERPRET_CAST(decoder_source_mgr *, mInfo.src);
|
decoder_source_mgr *src = NS_REINTERPRET_CAST(decoder_source_mgr *, mInfo.src);
|
||||||
|
|
||||||
if (!mSamples && jpeg_read_header(&mInfo, TRUE) != JPEG_SUSPENDED) {
|
int status;
|
||||||
|
switch (mState) {
|
||||||
|
case JPEG_HEADER:
|
||||||
/* FIXME -- Should reset dct_method and dither mode
|
{
|
||||||
* for final pass of progressive JPEG
|
/* Step 3: read file parameters with jpeg_read_header() */
|
||||||
*/
|
if (jpeg_read_header(&mInfo, TRUE) == JPEG_SUSPENDED)
|
||||||
mInfo.dct_method = JDCT_FASTEST;
|
return NS_OK;
|
||||||
mInfo.dither_mode = JDITHER_ORDERED;
|
|
||||||
mInfo.do_fancy_upsampling = FALSE;
|
|
||||||
mInfo.enable_2pass_quant = FALSE;
|
|
||||||
mInfo.do_block_smoothing = TRUE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't allocate a giant and superfluous memory buffer
|
* 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 */
|
/* Used to set up image size so arrays can be allocated */
|
||||||
jpeg_calc_output_dimensions(&mInfo);
|
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,37 +260,63 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR
|
|||||||
row_stride, 1);
|
row_stride, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
mState = JPEG_START_DECOMPRESS;
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
case JPEG_START_DECOMPRESS:
|
||||||
|
|
||||||
|
/* Step 4: set parameters for decompression */
|
||||||
|
|
||||||
/* Step 3: read file parameters with jpeg_read_header() */
|
/* FIXME -- Should reset dct_method and dither mode
|
||||||
// (void) jpeg_read_header(&mInfo, TRUE);
|
* for final pass of progressive JPEG
|
||||||
/* We can ignore the return value from jpeg_read_header since
|
*/
|
||||||
* (a) suspension is not possible with the stdio data source, and
|
mInfo.dct_method = JDCT_FASTEST;
|
||||||
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
|
mInfo.dither_mode = JDITHER_ORDERED;
|
||||||
* See libjpeg.doc for more info.
|
mInfo.do_fancy_upsampling = FALSE;
|
||||||
*/
|
mInfo.enable_2pass_quant = FALSE;
|
||||||
|
mInfo.do_block_smoothing = TRUE;
|
||||||
|
|
||||||
/* Step 4: set parameters for decompression */
|
/* In this example, we don't need to change any of the defaults set by
|
||||||
|
* jpeg_read_header(), so we do nothing here.
|
||||||
|
*/
|
||||||
|
|
||||||
/* In this example, we don't need to change any of the defaults set by
|
/* Step 5: Start decompressor */
|
||||||
* jpeg_read_header(), so we do nothing here.
|
if (jpeg_start_decompress(&mInfo) == FALSE)
|
||||||
*/
|
return NS_OK;
|
||||||
|
|
||||||
/* Step 5: Start decompressor */
|
mState = JPEG_DECOMPRESS_PROGRESSIVE;
|
||||||
|
|
||||||
(void) jpeg_start_decompress(&mInfo);
|
case JPEG_DECOMPRESS_PROGRESSIVE:
|
||||||
/* We can ignore the return value since suspension is not possible
|
do {
|
||||||
* with the stdio data source.
|
status = jpeg_consume_input(&mInfo);
|
||||||
*/
|
} while (!((status == JPEG_SUSPENDED) ||
|
||||||
|
(status == JPEG_REACHED_EOI)));
|
||||||
|
|
||||||
int status;
|
if (status == JPEG_REACHED_EOI) {
|
||||||
do {
|
mState = JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT;
|
||||||
status = jpeg_consume_input(&mInfo);
|
} else {
|
||||||
} while (!((status == JPEG_SUSPENDED) ||
|
return NS_OK;
|
||||||
(status == JPEG_REACHED_EOI)));
|
}
|
||||||
|
|
||||||
|
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
|
/* 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
|
* the data. After jpeg_start_decompress() we have the correct scaled
|
||||||
@ -361,7 +345,12 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR
|
|||||||
*/
|
*/
|
||||||
(void) jpeg_read_scanlines(&mInfo, buffer, 1);
|
(void) jpeg_read_scanlines(&mInfo, buffer, 1);
|
||||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
/* 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
|
#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
|
#if 0
|
||||||
ic->imgdcb->ImgDCBHaveRow( 0, samples, 0, mInfo.output_width, mInfo.output_scanline-1,
|
ic->imgdcb->ImgDCBHaveRow( 0, samples, 0, mInfo.output_width, mInfo.output_scanline-1,
|
||||||
1, ilErase, pass);
|
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
|
* 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
|
* 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
|
* TRUE if additional data is available, FALSE if no data present and
|
||||||
* the JPEG library should therefore suspend processing of input stream
|
* 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
|
boolean PR_CALLBACK
|
||||||
fill_input_buffer (j_decompress_ptr jd)
|
fill_input_buffer (j_decompress_ptr jd)
|
||||||
{
|
{
|
||||||
decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
|
decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
|
||||||
|
|
||||||
return src->decoder->FillInput(jd);
|
PRUint32 _retval;
|
||||||
}
|
|
||||||
|
|
||||||
PRBool nsJPEGDecoder::FillInput(j_decompress_ptr jd)
|
if (src->decoder->mBytesToSkip != 0) {
|
||||||
{
|
if (src->decoder->mBytesToSkip > src->decoder->mDataLen){
|
||||||
// read the data from the input stram...
|
src->decoder->mInStream->ReadSegments(DiscardData, NS_STATIC_CAST(void*, jd),
|
||||||
|
src->decoder->mDataLen, &_retval);
|
||||||
decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
|
} else {
|
||||||
|
src->decoder->mInStream->ReadSegments(DiscardData, NS_STATIC_CAST(void*, jd),
|
||||||
if (mCurDataLen == 0)
|
src->decoder->mBytesToSkip, &_retval);
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
unsigned char *newBuffer = (unsigned char *)mBuf;
|
|
||||||
size_t newBufLen = mCurDataLen;
|
|
||||||
|
|
||||||
if (mBytesToSkip < mCurDataLen) {
|
|
||||||
newBuffer += mBytesToSkip;
|
|
||||||
newBufLen -= mBytesToSkip;
|
|
||||||
mBytesToSkip = 0;
|
|
||||||
} else {
|
|
||||||
mBytesToSkip -= newBufLen;
|
|
||||||
return FALSE; // suspend
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
} else {
|
|
||||||
/* Still need to skip some more data in the future */
|
|
||||||
src->bytes_to_skip -= (size_t)new_buflen;
|
|
||||||
goto suspend;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
|
src->decoder->mBytesToSkip -= _retval;
|
||||||
suspend:
|
src->decoder->mDataLen -= _retval;
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -719,5 +635,13 @@ skip_input_data (j_decompress_ptr jd, long num_bytes)
|
|||||||
void PR_CALLBACK
|
void PR_CALLBACK
|
||||||
term_source (j_decompress_ptr jd)
|
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 */
|
/* No work necessary here */
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,17 @@
|
|||||||
|
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
#include "nsIImage2.h"
|
#include "nsIImageContainer.h"
|
||||||
#include "nsIImageRequest.h"
|
#include "nsIImageFrame.h"
|
||||||
|
#include "nsIImageDecoderObserver.h"
|
||||||
|
#include "nsIImageRequest2.h"
|
||||||
#include "nsIInputStream.h"
|
#include "nsIInputStream.h"
|
||||||
|
#include "nsIPipe.h"
|
||||||
|
|
||||||
#include "jpeglib.h"
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
#define NS_JPEGDECODER_CID \
|
#define NS_JPEGDECODER_CID \
|
||||||
{ /* 5871a422-1dd2-11b2-ab3f-e2e56be5da9c */ \
|
{ /* 5871a422-1dd2-11b2-ab3f-e2e56be5da9c */ \
|
||||||
0x5871a422, \
|
0x5871a422, \
|
||||||
@ -77,18 +82,21 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
int OutputScanlines(int num_scanlines);
|
int OutputScanlines(int num_scanlines);
|
||||||
|
|
||||||
private:
|
public:
|
||||||
nsCOMPtr<nsIImage2> mImage;
|
nsCOMPtr<nsIImageContainer> mImage;
|
||||||
|
nsCOMPtr<nsIImageFrame> mFrame;
|
||||||
nsCOMPtr<nsIImageRequest> mRequest;
|
nsCOMPtr<nsIImageRequest> mRequest;
|
||||||
nsCOMPtr<nsIInputStream> mStream;
|
|
||||||
|
nsCOMPtr<nsIImageDecoderObserver> mObserver;
|
||||||
|
|
||||||
struct jpeg_decompress_struct mInfo;
|
struct jpeg_decompress_struct mInfo;
|
||||||
decoder_error_mgr mErr;
|
decoder_error_mgr mErr;
|
||||||
jstate mState;
|
jstate mState;
|
||||||
|
|
||||||
char *mBuf;
|
nsCOMPtr<nsIInputStream> mInStream;
|
||||||
PRUint32 mBufLen;
|
nsCOMPtr<nsIOutputStream> mOutStream;
|
||||||
PRUint32 mCurDataLen;
|
|
||||||
|
PRUint32 mDataLen;
|
||||||
|
|
||||||
JSAMPARRAY mSamples;
|
JSAMPARRAY mSamples;
|
||||||
JSAMPARRAY mSamples3;
|
JSAMPARRAY mSamples3;
|
||||||
|
@ -34,7 +34,7 @@ static nsModuleComponentInfo components[] =
|
|||||||
{
|
{
|
||||||
{ "ppm decoder",
|
{ "ppm decoder",
|
||||||
NS_JPEGDECODER_CID,
|
NS_JPEGDECODER_CID,
|
||||||
"@mozilla.org/image/decoder?image/jpeg;1",
|
"@mozilla.org/image/decoder;2?type=image/jpeg",
|
||||||
nsJPEGDecoderConstructor, },
|
nsJPEGDecoderConstructor, },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -21,6 +21,6 @@
|
|||||||
|
|
||||||
DEPTH=..\..\..
|
DEPTH=..\..\..
|
||||||
|
|
||||||
DIRS = ppm png
|
DIRS = ppm gif png jpeg
|
||||||
|
|
||||||
!include $(DEPTH)\config\rules.mak
|
!include $(DEPTH)\config\rules.mak
|
||||||
|
@ -39,6 +39,7 @@ LLIBS=\
|
|||||||
$(DIST)\lib\xpcom.lib \
|
$(DIST)\lib\xpcom.lib \
|
||||||
$(DIST)\lib\png.lib \
|
$(DIST)\lib\png.lib \
|
||||||
$(DIST)\lib\zlib.lib \
|
$(DIST)\lib\zlib.lib \
|
||||||
|
$(DIST)\lib\gkgfxwin.lib \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
include <$(DEPTH)\config\rules.mak>
|
include <$(DEPTH)\config\rules.mak>
|
||||||
|
@ -34,6 +34,11 @@
|
|||||||
|
|
||||||
#include "nsIStreamObserver.h"
|
#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.
|
// XXX we need to be sure to fire onStopDecode messages to mObserver in error cases.
|
||||||
|
|
||||||
@ -47,11 +52,19 @@ nsPNGDecoder::nsPNGDecoder()
|
|||||||
|
|
||||||
mPNG = nsnull;
|
mPNG = nsnull;
|
||||||
mInfo = nsnull;
|
mInfo = nsnull;
|
||||||
|
colorLine = 0;
|
||||||
|
alphaLine = 0;
|
||||||
|
interlacebuf = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsPNGDecoder::~nsPNGDecoder()
|
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) */
|
/* 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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -136,6 +149,17 @@ static NS_METHOD ReadDataOut(nsIInputStream* in,
|
|||||||
PRUint32 *writeCount)
|
PRUint32 *writeCount)
|
||||||
{
|
{
|
||||||
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, closure);
|
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);
|
*writeCount = decoder->ProcessData((unsigned char*)fromRawSegment, count);
|
||||||
return NS_OK;
|
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); */
|
/* unsigned long writeFrom (in nsIInputStream inStr, in unsigned long count); */
|
||||||
NS_IMETHODIMP nsPNGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
|
NS_IMETHODIMP nsPNGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
|
||||||
{
|
{
|
||||||
PRUint32 sourceOffset = *_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
inStr->ReadSegments(ReadDataOut, this, count, _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));
|
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, png_get_progressive_ptr(png_ptr));
|
||||||
|
|
||||||
if (decoder->mObserver)
|
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
|
// 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)
|
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");
|
decoder->mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
|
||||||
#if 0
|
#if 0
|
||||||
@ -328,21 +343,44 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr)
|
|||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
#endif
|
#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);
|
decoder->mImage->AppendFrame(decoder->mFrame);
|
||||||
|
|
||||||
if (decoder->mObserver)
|
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 (interlace_type == PNG_INTERLACE_ADAM7) {
|
||||||
if (channels == 3) {
|
decoder->interlacebuf = (PRUint8 *)nsMemory::Alloc(channels*width*height);
|
||||||
decoder->mFrame->Init(0, 0, width, height, nsIGFXFormat::RGB);
|
decoder->ibpr = channels*width;
|
||||||
} else if (channels > 3) {
|
if (!decoder->interlacebuf) {
|
||||||
if (alpha_bits == 8) {
|
// return NS_ERROR_FAILURE;
|
||||||
decoder->mFrame->Init(0, 0, width, height, nsIGFXFormat::RGBA);
|
}
|
||||||
} else if (alpha_bits == 1) {
|
|
||||||
decoder->mFrame->Init(0, 0, width, height, nsIGFXFormat::RGB_A1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -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));
|
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, png_get_progressive_ptr(png_ptr));
|
||||||
|
|
||||||
PRUint32 bpr;
|
PRUint32 bpr, abpr;
|
||||||
decoder->mFrame->GetBytesPerRow(&bpr);
|
decoder->mFrame->GetImageBytesPerRow(&bpr);
|
||||||
|
decoder->mFrame->GetAlphaBytesPerRow(&abpr);
|
||||||
|
|
||||||
PRUint32 length;
|
PRUint32 length;
|
||||||
PRUint8 *bits;
|
PRUint8 *bits;
|
||||||
decoder->mFrame->GetBits(&bits, &length);
|
decoder->mFrame->GetImageData(&bits, &length);
|
||||||
|
|
||||||
png_bytep line;
|
png_bytep line;
|
||||||
if (bits) {
|
if (decoder->interlacebuf) {
|
||||||
line = bits+(row_num*bpr);
|
line = decoder->interlacebuf+(row_num*decoder->ibpr);
|
||||||
png_progressive_combine_row(png_ptr, line, new_row);
|
png_progressive_combine_row(png_ptr, line, new_row);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
line = new_row;
|
line = new_row;
|
||||||
|
|
||||||
if (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));
|
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, png_get_progressive_ptr(png_ptr));
|
||||||
|
|
||||||
if (decoder->mObserver) {
|
if (decoder->mObserver) {
|
||||||
decoder->mObserver->OnStopFrame(nsnull, decoder->mFrame);
|
decoder->mObserver->OnStopFrame(nsnull, nsnull, decoder->mFrame);
|
||||||
decoder->mObserver->OnStopContainer(nsnull, decoder->mImage);
|
decoder->mObserver->OnStopContainer(nsnull, nsnull, decoder->mImage);
|
||||||
decoder->mObserver->OnStopDecode(nsnull, NS_OK, nsnull);
|
decoder->mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include "nsIImageContainer.h"
|
#include "nsIImageContainer.h"
|
||||||
#include "nsIImageDecoderObserver.h"
|
#include "nsIImageDecoderObserver.h"
|
||||||
#include "nsIImageFrame.h"
|
#include "nsIImageFrame.h"
|
||||||
#include "nsIImageRequest.h"
|
#include "nsIImageRequest2.h"
|
||||||
|
|
||||||
|
|
||||||
#include "nsCOMPtr.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);
|
inline PRUint32 ProcessData(unsigned char *data, PRUint32 count);
|
||||||
|
|
||||||
|
|
||||||
private:
|
public:
|
||||||
nsCOMPtr<nsIImageContainer> mImage;
|
nsCOMPtr<nsIImageContainer> mImage;
|
||||||
nsCOMPtr<nsIImageFrame> mFrame;
|
nsCOMPtr<nsIImageFrame> mFrame;
|
||||||
nsCOMPtr<nsIImageRequest> mRequest;
|
nsCOMPtr<nsIImageRequest> mRequest;
|
||||||
@ -74,6 +74,9 @@ private:
|
|||||||
|
|
||||||
png_structp mPNG;
|
png_structp mPNG;
|
||||||
png_infop mInfo;
|
png_infop mInfo;
|
||||||
|
PRUint8 *colorLine, *alphaLine;
|
||||||
|
PRUint8 *interlacebuf;
|
||||||
|
PRUint32 ibpr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // nsPNGDecoder_h__
|
#endif // nsPNGDecoder_h__
|
||||||
|
@ -34,7 +34,11 @@ static nsModuleComponentInfo components[] =
|
|||||||
{
|
{
|
||||||
{ "PNG decoder",
|
{ "PNG decoder",
|
||||||
NS_PNGDECODER_CID,
|
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, },
|
nsPNGDecoderConstructor, },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ OBJS = \
|
|||||||
LLIBS=\
|
LLIBS=\
|
||||||
$(LIBNSPR) \
|
$(LIBNSPR) \
|
||||||
$(DIST)\lib\xpcom.lib \
|
$(DIST)\lib\xpcom.lib \
|
||||||
|
$(DIST)\lib\gkgfxwin.lib \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
include <$(DEPTH)\config\rules.mak>
|
include <$(DEPTH)\config\rules.mak>
|
||||||
|
@ -20,23 +20,20 @@
|
|||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Stuart Parmenter <pavlov@netscape.com>
|
* 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 "nsPPMDecoder.h"
|
||||||
|
|
||||||
#include "nsIInputStream.h"
|
#include "nsIInputStream.h"
|
||||||
#include "nsIImageContainer.h"
|
#include "nsIImageContainer.h"
|
||||||
|
#include "nsIImageContainerObserver.h"
|
||||||
|
|
||||||
#include "nspr.h"
|
#include "nspr.h"
|
||||||
|
|
||||||
#include "nsUnitConverters.h"
|
|
||||||
|
|
||||||
#include "nsIComponentManager.h"
|
#include "nsIComponentManager.h"
|
||||||
|
|
||||||
|
#include "nsRect.h"
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS2(nsPPMDecoder, nsIImageDecoder, nsIOutputStream)
|
NS_IMPL_ISUPPORTS2(nsPPMDecoder, nsIImageDecoder, nsIOutputStream)
|
||||||
|
|
||||||
|
|
||||||
@ -63,15 +60,14 @@ NS_IMETHODIMP nsPPMDecoder::Init(nsIImageRequest *aRequest)
|
|||||||
{
|
{
|
||||||
mRequest = aRequest;
|
mRequest = aRequest;
|
||||||
|
|
||||||
nsCOMPtr<nsIImageContainer> container;
|
mObserver = do_QueryInterface(aRequest); // we're holding 2 strong refs to the request.
|
||||||
aRequest->GetImage(getter_AddRefs(container));
|
|
||||||
|
|
||||||
mImage = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
|
aRequest->GetImage(getter_AddRefs(mImage));
|
||||||
if (!mImage)
|
|
||||||
|
mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
|
||||||
|
if (!mFrame)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
container->AppendFrame(mImage);
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,11 +89,11 @@ NS_IMETHODIMP nsPPMDecoder::GetRequest(nsIImageRequest * *aRequest)
|
|||||||
/* void close (); */
|
/* void close (); */
|
||||||
NS_IMETHODIMP nsPPMDecoder::Close()
|
NS_IMETHODIMP nsPPMDecoder::Close()
|
||||||
{
|
{
|
||||||
printf("nsPPMDecoder::Close()\n");
|
if (mObserver) {
|
||||||
|
mObserver->OnStopFrame(nsnull, nsnull, mFrame);
|
||||||
// XXX hack
|
mObserver->OnStopContainer(nsnull, nsnull, mImage);
|
||||||
gfx_format format;
|
mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
|
||||||
mImage->GetFormat(&format);
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -185,6 +181,8 @@ NS_IMETHODIMP nsPPMDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRU
|
|||||||
|
|
||||||
if (mDataReceived == 0) {
|
if (mDataReceived == 0) {
|
||||||
|
|
||||||
|
mObserver->OnStartDecode(nsnull, nsnull);
|
||||||
|
|
||||||
// Check the magic number
|
// Check the magic number
|
||||||
char type;
|
char type;
|
||||||
if ((sscanf(data, "P%c\n", &type) !=1) || (type != '6')) {
|
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;
|
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
|
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(w, h, mObserver);
|
||||||
mImage->Init(0, 0, w, h, nsIGFXFormat::RGB);
|
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;
|
PRUint32 bpr;
|
||||||
gfx_dimension width;
|
nscoord width;
|
||||||
mImage->GetBytesPerRow(&bpr);
|
mFrame->GetImageBytesPerRow(&bpr);
|
||||||
mImage->GetWidth(&width);
|
mFrame->GetWidth(&width);
|
||||||
|
|
||||||
PRUint32 real_bpr = GFXCoordToIntCeil(width) * 3;
|
// XXX ceil?
|
||||||
|
PRUint32 real_bpr = width * 3;
|
||||||
|
|
||||||
PRUint32 i = 0;
|
PRUint32 i = 0;
|
||||||
PRUint32 rownum = mDataWritten / real_bpr; // XXX this better not have a decimal
|
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 {
|
do {
|
||||||
PRUint8 *line = (PRUint8*)data + i*real_bpr;
|
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 ;
|
wroteLen += real_bpr ;
|
||||||
i++;
|
i++;
|
||||||
} while(dataLen >= real_bpr * (i+1));
|
} while(dataLen >= real_bpr * (i+1));
|
||||||
|
@ -28,8 +28,10 @@
|
|||||||
|
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
|
#include "nsIImageContainer.h"
|
||||||
|
#include "nsIImageDecoderObserver.h"
|
||||||
#include "nsIImageFrame.h"
|
#include "nsIImageFrame.h"
|
||||||
#include "nsIImageRequest.h"
|
#include "nsIImageRequest2.h"
|
||||||
|
|
||||||
#define NS_PPMDECODER_CID \
|
#define NS_PPMDECODER_CID \
|
||||||
{ /* e90bfa06-1dd1-11b2-8217-f38fe5d431a2 */ \
|
{ /* e90bfa06-1dd1-11b2-8217-f38fe5d431a2 */ \
|
||||||
@ -50,8 +52,11 @@ public:
|
|||||||
virtual ~nsPPMDecoder();
|
virtual ~nsPPMDecoder();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsCOMPtr<nsIImageFrame> mImage;
|
nsCOMPtr<nsIImageContainer> mImage;
|
||||||
|
nsCOMPtr<nsIImageFrame> mFrame;
|
||||||
nsCOMPtr<nsIImageRequest> mRequest;
|
nsCOMPtr<nsIImageRequest> mRequest;
|
||||||
|
nsCOMPtr<nsIImageDecoderObserver> mObserver; // this is just qi'd from mRequest for speed
|
||||||
|
|
||||||
PRUint32 mDataReceived;
|
PRUint32 mDataReceived;
|
||||||
PRUint32 mDataWritten;
|
PRUint32 mDataWritten;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ static nsModuleComponentInfo components[] =
|
|||||||
{
|
{
|
||||||
{ "ppm decoder",
|
{ "ppm decoder",
|
||||||
NS_PPMDECODER_CID,
|
NS_PPMDECODER_CID,
|
||||||
"@mozilla.org/image/decoder?image/x-portable-pixmap;1",
|
"@mozilla.org/image/decoder;2?type=image/x-portable-pixmap",
|
||||||
nsPPMDecoderConstructor, },
|
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 \
|
XPIDLSRCS = nsIImageDecoder.idl \
|
||||||
nsIImageDecoderObserver.idl \
|
nsIImageDecoderObserver.idl \
|
||||||
nsIImageLoader.idl \
|
nsIImageLoader.idl \
|
||||||
nsIImageRequest.idl
|
nsIImageRequest2.idl
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ XPIDLSRCS = \
|
|||||||
.\nsIImageDecoder.idl \
|
.\nsIImageDecoder.idl \
|
||||||
.\nsIImageDecoderObserver.idl \
|
.\nsIImageDecoderObserver.idl \
|
||||||
.\nsIImageLoader.idl \
|
.\nsIImageLoader.idl \
|
||||||
.\nsIImageRequest.idl \
|
.\nsIImageRequest2.idl \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,9 +27,25 @@
|
|||||||
|
|
||||||
interface nsIImageRequest;
|
interface nsIImageRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nsIImageDecoder interface
|
||||||
|
*
|
||||||
|
* @author Stuart Parmenter <pavlov@netscape.com>
|
||||||
|
* @version 0.1
|
||||||
|
* @see imagelib2
|
||||||
|
*/
|
||||||
[scriptable, uuid(9eebf43a-1dd1-11b2-953e-f1782f4cbad3)]
|
[scriptable, uuid(9eebf43a-1dd1-11b2-953e-f1782f4cbad3)]
|
||||||
interface nsIImageDecoder : nsIOutputStream
|
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);
|
void init(in nsIImageRequest aRequest);
|
||||||
|
|
||||||
/// allows access to the nsIImage we have to put bits in to.
|
/// allows access to the nsIImage we have to put bits in to.
|
||||||
|
@ -21,13 +21,17 @@
|
|||||||
* Stuart Parmenter <pavlov@netscape.com>
|
* Stuart Parmenter <pavlov@netscape.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nsISupports.idl"
|
#include "nsIImageContainerObserver.idl"
|
||||||
#include "gfxtypes.idl"
|
#include "gfxtypes.idl"
|
||||||
|
|
||||||
interface nsIImageRequest;
|
interface nsIImageRequest;
|
||||||
interface nsIImageContainer;
|
interface nsIImageContainer;
|
||||||
interface nsIImageFrame;
|
interface nsIImageFrame;
|
||||||
|
|
||||||
|
%{C++
|
||||||
|
#include "nsRect.h"
|
||||||
|
%}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nsIImageDecoderObserver interface
|
* nsIImageDecoderObserver interface
|
||||||
*
|
*
|
||||||
@ -36,42 +40,42 @@ interface nsIImageFrame;
|
|||||||
* @see imagelib2
|
* @see imagelib2
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(350163d2-1dd2-11b2-9e69-89959ecec1f3)]
|
[scriptable, uuid(350163d2-1dd2-11b2-9e69-89959ecec1f3)]
|
||||||
interface nsIImageDecoderObserver : nsISupports
|
interface nsIImageDecoderObserver : nsIImageContainerObserver
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* called as soon as the image begins getting decoded
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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
|
* called when the decoder is dying off
|
||||||
*/
|
*/
|
||||||
void onStopDecode(in nsIImageRequest request, in nsresult status,
|
void onStopDecode(in nsIImageRequest request, in nsISupports cx,
|
||||||
in wstring statusArg);
|
in nsresult status, in wstring statusArg);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -24,19 +24,42 @@
|
|||||||
#include "nsISupports.idl"
|
#include "nsISupports.idl"
|
||||||
#include "gfxtypes.idl"
|
#include "gfxtypes.idl"
|
||||||
|
|
||||||
interface nsIImage;
|
interface nsIImageDecoderObserver;
|
||||||
interface nsIImageRequest;
|
interface nsIImageRequest;
|
||||||
interface nsISimpleEnumerator;
|
interface nsISimpleEnumerator;
|
||||||
|
interface nsIStreamListener;
|
||||||
interface nsIURI;
|
interface nsIURI;
|
||||||
|
interface nsIChannel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nsIImageLoader interface
|
||||||
|
*
|
||||||
|
* @author Stuart Parmenter <pavlov@netscape.com>
|
||||||
|
* @version 0.1
|
||||||
|
* @see imagelib2
|
||||||
|
*/
|
||||||
[scriptable, uuid(4c8cf1e0-1dd2-11b2-aff9-c51cdbfcb6da)]
|
[scriptable, uuid(4c8cf1e0-1dd2-11b2-aff9-c51cdbfcb6da)]
|
||||||
interface nsIImageLoader : nsISupports
|
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.
|
* Returns the channels contained directly in this group.
|
||||||
* Enumerator element type: nsIImageRequest.
|
* @note Enumerator element type: nsIImageRequest.
|
||||||
*/
|
*/
|
||||||
readonly attribute nsISimpleEnumerator requests;
|
readonly attribute nsISimpleEnumerator requests;
|
||||||
};
|
};
|
||||||
|
@ -22,23 +22,42 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nsISupports.idl"
|
#include "nsISupports.idl"
|
||||||
#include "nsIRequest.idl"
|
|
||||||
#include "gfxtypes.idl"
|
|
||||||
|
|
||||||
interface nsIChannel;
|
|
||||||
interface nsIImageContainer;
|
interface nsIImageContainer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nsIImageRequest interface
|
||||||
|
*
|
||||||
|
* @author Stuart Parmenter <pavlov@netscape.com>
|
||||||
|
* @version 0.1
|
||||||
|
* @see imagelib2
|
||||||
|
*/
|
||||||
[scriptable, uuid(ccf705f6-1dd1-11b2-82ef-e18eccf7f7ec)]
|
[scriptable, uuid(ccf705f6-1dd1-11b2-82ef-e18eccf7f7ec)]
|
||||||
interface nsIImageRequest : nsIRequest
|
interface nsIImageRequest : nsISupports
|
||||||
{
|
{
|
||||||
// const values for GetStatus() to be used someday...
|
void cancel(in nsresult status);
|
||||||
// const long STATUS_NONE = 0x0;
|
|
||||||
// const long STATUS_SIZE_AVAILABLE = 0x1;
|
|
||||||
// const long STATUS_IMAGE_READY = 0x2;
|
|
||||||
// const long STATUS_ERROR = 0x4;
|
|
||||||
|
|
||||||
void init(in nsIChannel aChannel);
|
/**
|
||||||
|
* the image container...
|
||||||
/// @return the image object associated with the request.
|
* @return the image object associated with the request.
|
||||||
|
* @attention NEED DOCS
|
||||||
|
*/
|
||||||
readonly attribute nsIImageContainer image;
|
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
|
LIBRARY_NAME = imglib2
|
||||||
IS_COMPONENT = 1
|
IS_COMPONENT = 1
|
||||||
|
|
||||||
CPPSRCS = nsImageFactory.cpp \
|
CPPSRCS = ImageCache.cpp \
|
||||||
nsImageLoader.cpp \
|
nsImageFactory.cpp \
|
||||||
nsImageRequest.cpp
|
nsImageLoader.cpp \
|
||||||
|
nsImageRequest.cpp \
|
||||||
|
nsImageRequestProxy.cpp
|
||||||
|
|
||||||
EXTRA_DSO_LDOPTS = \
|
EXTRA_DSO_LDOPTS = \
|
||||||
$(MOZ_COMPONENT_LIBS) \
|
$(MOZ_COMPONENT_LIBS) \
|
||||||
|
@ -30,8 +30,10 @@ DLL = $(OBJDIR)\$(LIBRARY_NAME).dll
|
|||||||
MAKE_OBJ_TYPE = DLL
|
MAKE_OBJ_TYPE = DLL
|
||||||
|
|
||||||
OBJS = \
|
OBJS = \
|
||||||
|
.\$(OBJDIR)\ImageCache.obj \
|
||||||
.\$(OBJDIR)\nsImageLoader.obj \
|
.\$(OBJDIR)\nsImageLoader.obj \
|
||||||
.\$(OBJDIR)\nsImageRequest.obj \
|
.\$(OBJDIR)\nsImageRequest.obj \
|
||||||
|
.\$(OBJDIR)\nsImageRequestProxy.obj \
|
||||||
.\$(OBJDIR)\nsImageFactory.obj \
|
.\$(OBJDIR)\nsImageFactory.obj \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
@ -26,11 +26,13 @@
|
|||||||
|
|
||||||
#include "nsImageLoader.h"
|
#include "nsImageLoader.h"
|
||||||
#include "nsImageRequest.h"
|
#include "nsImageRequest.h"
|
||||||
|
#include "nsImageRequestProxy.h"
|
||||||
|
|
||||||
// objects that just require generic constructors
|
// objects that just require generic constructors
|
||||||
|
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageLoader)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageLoader)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageRequest)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageRequest)
|
||||||
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageRequestProxy)
|
||||||
|
|
||||||
static nsModuleComponentInfo components[] =
|
static nsModuleComponentInfo components[] =
|
||||||
{
|
{
|
||||||
@ -40,9 +42,12 @@ static nsModuleComponentInfo components[] =
|
|||||||
nsImageLoaderConstructor, },
|
nsImageLoaderConstructor, },
|
||||||
{ "image request",
|
{ "image request",
|
||||||
NS_IMAGEREQUEST_CID,
|
NS_IMAGEREQUEST_CID,
|
||||||
"@mozilla.org/image/request;1",
|
"@mozilla.org/image/request/real;1",
|
||||||
nsImageRequestConstructor, },
|
nsImageRequestConstructor, },
|
||||||
|
{ "image request proxy",
|
||||||
|
NS_IMAGEREQUESTPROXY_CID,
|
||||||
|
"@mozilla.org/image/request/proxy;1",
|
||||||
|
nsImageRequestProxyConstructor, },
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_IMPL_NSGETMODULE("nsImageLib2Module", components)
|
NS_IMPL_NSGETMODULE("nsImageLib2Module", components)
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "nsImageLoader.h"
|
#include "nsImageLoader.h"
|
||||||
|
|
||||||
#include "nsIImageRequest.h"
|
#include "nsIImageRequest2.h"
|
||||||
|
|
||||||
#include "nsIServiceManager.h"
|
#include "nsIServiceManager.h"
|
||||||
|
|
||||||
@ -33,57 +33,136 @@
|
|||||||
#include "nsIStreamListener.h"
|
#include "nsIStreamListener.h"
|
||||||
#include "nsIURI.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)
|
NS_IMPL_ISUPPORTS1(nsImageLoader, nsIImageLoader)
|
||||||
|
#endif
|
||||||
|
|
||||||
nsImageLoader::nsImageLoader()
|
nsImageLoader::nsImageLoader()
|
||||||
{
|
{
|
||||||
NS_INIT_ISUPPORTS();
|
NS_INIT_ISUPPORTS();
|
||||||
/* member initializers and constructor code */
|
/* member initializers and constructor code */
|
||||||
|
#ifdef LOADER_THREADSAFE
|
||||||
|
mLock = PR_NewLock();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
nsImageLoader::~nsImageLoader()
|
nsImageLoader::~nsImageLoader()
|
||||||
{
|
{
|
||||||
/* destructor code */
|
/* destructor code */
|
||||||
|
#ifdef LOADER_THREADSAFE
|
||||||
|
PR_DestroyLock(mLock);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//#define IMAGE_THREADPOOL 1
|
/* nsIImageRequest loadImage (in nsIURI uri, in nsIImageDecoderObserver aObserver, in nsISupports cx); */
|
||||||
|
NS_IMETHODIMP nsImageLoader::LoadImage(nsIURI *aURI, nsIImageDecoderObserver *aObserver, nsISupports *cx, nsIImageRequest **_retval)
|
||||||
/* nsIImageRequest loadImage (in nsIURI uri, in gfx_dimension width, in gfx_dimension height); */
|
|
||||||
NS_IMETHODIMP nsImageLoader::LoadImage(nsIURI *aURI, nsIImageRequest **_retval)
|
|
||||||
{
|
{
|
||||||
|
NS_ASSERTION(aURI, "nsImageLoader::LoadImage -- NULL URI pointer");
|
||||||
|
|
||||||
#ifdef IMAGE_THREADPOOL
|
nsImageRequest *imgRequest = nsnull;
|
||||||
if (!mThreadPool) {
|
|
||||||
NS_NewThreadPool(getter_AddRefs(mThreadPool),
|
ImageCache::Get(aURI, &imgRequest); // addrefs
|
||||||
1, 4,
|
if (!imgRequest) {
|
||||||
512,
|
#ifdef LOADER_THREADSAFE
|
||||||
PR_PRIORITY_NORMAL,
|
nsAutoLock lock(mLock); // lock when we are adding things to the cache
|
||||||
PR_GLOBAL_THREAD);
|
#endif
|
||||||
|
nsCOMPtr<nsIIOService> ioserv(do_GetService("@mozilla.org/network/io-service;1"));
|
||||||
|
if (!ioserv) return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIChannel> newChannel;
|
||||||
|
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'
|
||||||
|
|
||||||
|
nsCOMPtr<nsIImageRequest> req(do_CreateInstance(kImageRequestCID));
|
||||||
|
imgRequest = NS_REINTERPRET_CAST(nsImageRequest*, req.get());
|
||||||
|
NS_ADDREF(imgRequest);
|
||||||
|
|
||||||
|
imgRequest->Init(newChannel);
|
||||||
|
|
||||||
|
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
|
#endif
|
||||||
|
|
||||||
nsCOMPtr<nsIIOService> ioserv(do_GetService("@mozilla.org/network/io-service;1"));
|
nsCOMPtr<nsIImageRequest> req(do_CreateInstance(kImageRequestCID));
|
||||||
if (!ioserv) return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIChannel> newChannel;
|
imgRequest = NS_REINTERPRET_CAST(nsImageRequest*, req.get());
|
||||||
ioserv->NewChannelFromURI(aURI, getter_AddRefs(newChannel));
|
NS_ADDREF(imgRequest);
|
||||||
if (!newChannel) return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
newChannel->SetOwner(this); // the channel is now holding a strong ref to 'this'
|
imgRequest->Init(channel);
|
||||||
|
|
||||||
// XXX look at the progid
|
ImageCache::Put(uri, imgRequest);
|
||||||
nsCOMPtr<nsIImageRequest> imgRequest(do_CreateInstance("@mozilla.org/image/request;1"));
|
|
||||||
imgRequest->Init(newChannel);
|
|
||||||
|
|
||||||
#ifdef IMAGE_THREADPOOL
|
*listener = NS_STATIC_CAST(nsIStreamListener*, imgRequest);
|
||||||
nsCOMPtr<nsIRunnable> run(do_QueryInterface(imgRequest));
|
NS_IF_ADDREF(*listener);
|
||||||
mThreadPool->DispatchRequest(run);
|
}
|
||||||
#else
|
|
||||||
nsCOMPtr<nsIStreamListener> streamList(do_QueryInterface(imgRequest));
|
|
||||||
newChannel->AsyncRead(streamList, nsnull);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*_retval = imgRequest;
|
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);
|
NS_ADDREF(*_retval);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -21,9 +21,13 @@
|
|||||||
* Stuart Parmenter <pavlov@netscape.com>
|
* Stuart Parmenter <pavlov@netscape.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//#define LOADER_THREADSAFE 1
|
||||||
|
|
||||||
#include "nsIImageLoader.h"
|
#include "nsIImageLoader.h"
|
||||||
#include "nsIThreadPool.h"
|
|
||||||
#include "nsCOMPtr.h"
|
#ifdef LOADER_THREADSAFE
|
||||||
|
#include "prlock.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define NS_IMAGELOADER_CID \
|
#define NS_IMAGELOADER_CID \
|
||||||
{ /* 9f6a0d2e-1dd1-11b2-a5b8-951f13c846f7 */ \
|
{ /* 9f6a0d2e-1dd1-11b2-a5b8-951f13c846f7 */ \
|
||||||
@ -43,5 +47,7 @@ public:
|
|||||||
virtual ~nsImageLoader();
|
virtual ~nsImageLoader();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsCOMPtr<nsIThreadPool> mThreadPool;
|
#ifdef LOADER_THREADSAFE
|
||||||
|
PRLock *mLock;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
@ -35,18 +35,18 @@
|
|||||||
|
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
|
|
||||||
#include "nsIEventQueueService.h"
|
#include "ImageCache.h"
|
||||||
#include "nsIEventQueue.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();
|
NS_INIT_ISUPPORTS();
|
||||||
/* member initializers and constructor code */
|
/* member initializers and constructor code */
|
||||||
mProcessing = PR_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsImageRequest::~nsImageRequest()
|
nsImageRequest::~nsImageRequest()
|
||||||
@ -55,12 +55,12 @@ nsImageRequest::~nsImageRequest()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nsresult nsImageRequest::Init(nsIChannel *aChannel)
|
||||||
/* void init (in nsIChannel aChannel, in gfx_dimension width, in gfx_dimension height); */
|
|
||||||
NS_IMETHODIMP nsImageRequest::Init(nsIChannel *aChannel)
|
|
||||||
{
|
{
|
||||||
if (mImage)
|
// XXX we should save off the thread we are getting called on here so that we can proxy all calls to mDecoder to it.
|
||||||
return NS_ERROR_FAILURE; // XXX
|
|
||||||
|
NS_ASSERTION(!mImage, "nsImageRequest::Init -- Multiple calls to init");
|
||||||
|
NS_ASSERTION(aChannel, "nsImageRequest::Init -- No channel");
|
||||||
|
|
||||||
mChannel = aChannel;
|
mChannel = aChannel;
|
||||||
|
|
||||||
@ -70,6 +70,52 @@ NS_IMETHODIMP nsImageRequest::Init(nsIChannel *aChannel)
|
|||||||
return NS_OK;
|
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; */
|
/* readonly attribute nsIImage image; */
|
||||||
NS_IMETHODIMP nsImageRequest::GetImage(nsIImageContainer * *aImage)
|
NS_IMETHODIMP nsImageRequest::GetImage(nsIImageContainer * *aImage)
|
||||||
{
|
{
|
||||||
@ -78,113 +124,142 @@ NS_IMETHODIMP nsImageRequest::GetImage(nsIImageContainer * *aImage)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* readonly attribute unsigned long imageStatus; */
|
||||||
|
NS_IMETHODIMP nsImageRequest::GetImageStatus(PRUint32 *aStatus)
|
||||||
|
|
||||||
/** nsIRequest methods **/
|
|
||||||
|
|
||||||
/* readonly attribute wstring name; */
|
|
||||||
NS_IMETHODIMP nsImageRequest::GetName(PRUnichar * *aName)
|
|
||||||
{
|
{
|
||||||
return mChannel->GetName(aName);
|
*aStatus = mStatus;
|
||||||
}
|
return NS_OK;
|
||||||
|
|
||||||
/* 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** 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 **/
|
/** nsIImageDecoderObserver methods **/
|
||||||
|
|
||||||
/* void onStartDecode (in nsIImageRequest request); */
|
/* void onStartDecode (in nsIImageRequest request, in nsISupports cx); */
|
||||||
NS_IMETHODIMP nsImageRequest::OnStartDecode(nsIImageRequest *request)
|
NS_IMETHODIMP nsImageRequest::OnStartDecode(nsIImageRequest *request, nsISupports *cx)
|
||||||
{
|
{
|
||||||
if (mObserver)
|
mState |= onStartDecode;
|
||||||
mObserver->OnStartDecode(this);
|
|
||||||
|
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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void onStartContainer (in nsIImageRequest request, in nsIImageContainer image); */
|
/* void onStartContainer (in nsIImageRequest request, in nsISupports cx, in nsIImageContainer image); */
|
||||||
NS_IMETHODIMP nsImageRequest::OnStartContainer(nsIImageRequest *request, nsIImageContainer *image)
|
NS_IMETHODIMP nsImageRequest::OnStartContainer(nsIImageRequest *request, nsISupports *cx, nsIImageContainer *image)
|
||||||
{
|
{
|
||||||
if (mObserver)
|
mState |= onStartContainer;
|
||||||
mObserver->OnStartContainer(this, image);
|
|
||||||
|
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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void onStartFrame (in nsIImageRequest request, in nsIImageFrame frame); */
|
/* void onStartFrame (in nsIImageRequest request, in nsISupports cx, in nsIImageFrame frame); */
|
||||||
NS_IMETHODIMP nsImageRequest::OnStartFrame(nsIImageRequest *request, nsIImageFrame *frame)
|
NS_IMETHODIMP nsImageRequest::OnStartFrame(nsIImageRequest *request, nsISupports *cx, nsIImageFrame *frame)
|
||||||
{
|
{
|
||||||
if (mObserver)
|
PRInt32 i = -1;
|
||||||
mObserver->OnStartFrame(this, frame);
|
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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [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); */
|
||||||
NS_IMETHODIMP nsImageRequest::OnDataAvailable(nsIImageRequest *request, nsIImageFrame *frame, const nsRect2 * rect)
|
NS_IMETHODIMP nsImageRequest::OnDataAvailable(nsIImageRequest *request, nsISupports *cx, nsIImageFrame *frame, const nsRect * rect)
|
||||||
{
|
{
|
||||||
if (mObserver)
|
PRInt32 i = -1;
|
||||||
mObserver->OnDataAvailable(this, frame, rect);
|
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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void onStopFrame (in nsIImageRequest request, in nsIImageFrame frame); */
|
/* void onStopFrame (in nsIImageRequest request, in nsISupports cx, in nsIImageFrame frame); */
|
||||||
NS_IMETHODIMP nsImageRequest::OnStopFrame(nsIImageRequest *request, nsIImageFrame *frame)
|
NS_IMETHODIMP nsImageRequest::OnStopFrame(nsIImageRequest *request, nsISupports *cx, nsIImageFrame *frame)
|
||||||
{
|
{
|
||||||
if (mObserver)
|
PRInt32 i = -1;
|
||||||
mObserver->OnStopFrame(this, frame);
|
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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void onStopContainer (in nsIImageRequest request, in nsIImageContainer image); */
|
/* void onStopContainer (in nsIImageRequest request, in nsISupports cx, in nsIImageContainer image); */
|
||||||
NS_IMETHODIMP nsImageRequest::OnStopContainer(nsIImageRequest *request, nsIImageContainer *image)
|
NS_IMETHODIMP nsImageRequest::OnStopContainer(nsIImageRequest *request, nsISupports *cx, nsIImageContainer *image)
|
||||||
{
|
{
|
||||||
if (mObserver)
|
mState |= onStopContainer;
|
||||||
mObserver->OnStopContainer(this, image);
|
|
||||||
|
|
||||||
|
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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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); */
|
||||||
NS_IMETHODIMP nsImageRequest::OnStopDecode(nsIImageRequest *request, nsresult status, const PRUnichar *statusArg)
|
NS_IMETHODIMP nsImageRequest::OnStopDecode(nsIImageRequest *request, nsISupports *cx, nsresult status, const PRUnichar *statusArg)
|
||||||
{
|
{
|
||||||
if (mObserver)
|
mState |= onStopDecode;
|
||||||
mObserver->OnStopDecode(this, status, statusArg);
|
|
||||||
|
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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -199,13 +274,14 @@ NS_IMETHODIMP nsImageRequest::OnStopDecode(nsIImageRequest *request, nsresult st
|
|||||||
/* void onStartRequest (in nsIChannel channel, in nsISupports ctxt); */
|
/* void onStartRequest (in nsIChannel channel, in nsISupports ctxt); */
|
||||||
NS_IMETHODIMP nsImageRequest::OnStartRequest(nsIChannel *channel, nsISupports *ctxt)
|
NS_IMETHODIMP nsImageRequest::OnStartRequest(nsIChannel *channel, nsISupports *ctxt)
|
||||||
{
|
{
|
||||||
|
NS_ASSERTION(!mDecoder, "nsImageRequest::OnStartRequest -- we already have a decoder");
|
||||||
|
|
||||||
nsXPIDLCString contentType;
|
nsXPIDLCString contentType;
|
||||||
channel->GetContentType(getter_Copies(contentType));
|
channel->GetContentType(getter_Copies(contentType));
|
||||||
printf("content type is %s\n", contentType.get());
|
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 += contentType.get();
|
||||||
conid += ";1";
|
|
||||||
|
|
||||||
mDecoder = do_CreateInstance(conid);
|
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); */
|
/* 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_IMETHODIMP nsImageRequest::OnStopRequest(nsIChannel *channel, nsISupports *ctxt, nsresult status, const PRUnichar *statusArg)
|
||||||
{
|
{
|
||||||
|
NS_ASSERTION(mChannel || mProcessing, "nsImageRequest::OnStopRequest -- received multiple OnStopRequest");
|
||||||
|
|
||||||
mProcessing = PR_FALSE;
|
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;
|
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); */
|
/* 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)
|
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;
|
PRUint32 wrote;
|
||||||
return mDecoder->WriteFrom(inStr, count, &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>
|
* Stuart Parmenter <pavlov@netscape.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nsIImageRequest.h"
|
#ifndef nsImageRequest_h__
|
||||||
|
#define nsImageRequest_h__
|
||||||
|
|
||||||
|
#include "nsIImageRequest2.h"
|
||||||
|
|
||||||
#include "nsIRunnable.h"
|
#include "nsIRunnable.h"
|
||||||
|
|
||||||
@ -32,6 +35,8 @@
|
|||||||
#include "nsIStreamListener.h"
|
#include "nsIStreamListener.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
|
#include "nsVoidArray.h"
|
||||||
|
|
||||||
#define NS_IMAGEREQUEST_CID \
|
#define NS_IMAGEREQUEST_CID \
|
||||||
{ /* 9f733dd6-1dd1-11b2-8cdf-effb70d1ea71 */ \
|
{ /* 9f733dd6-1dd1-11b2-8cdf-effb70d1ea71 */ \
|
||||||
0x9f733dd6, \
|
0x9f733dd6, \
|
||||||
@ -40,28 +45,44 @@
|
|||||||
{0x8c, 0xdf, 0xef, 0xfb, 0x70, 0xd1, 0xea, 0x71} \
|
{0x8c, 0xdf, 0xef, 0xfb, 0x70, 0xd1, 0xea, 0x71} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
onStartDecode = 0x1,
|
||||||
|
onStartContainer = 0x2,
|
||||||
|
onStopContainer = 0x4,
|
||||||
|
onStopDecode = 0x8
|
||||||
|
};
|
||||||
|
|
||||||
class nsImageRequest : public nsIImageRequest,
|
class nsImageRequest : public nsIImageRequest,
|
||||||
public nsIImageDecoderObserver,
|
public nsIImageDecoderObserver,
|
||||||
public nsIStreamListener, public nsIRunnable
|
public nsIStreamListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIIMAGEREQUEST
|
|
||||||
NS_DECL_NSIIMAGEDECODEROBSERVER
|
|
||||||
NS_DECL_NSIREQUEST
|
|
||||||
NS_DECL_NSISTREAMLISTENER
|
|
||||||
NS_DECL_NSISTREAMOBSERVER
|
|
||||||
NS_DECL_NSIRUNNABLE
|
|
||||||
|
|
||||||
nsImageRequest();
|
nsImageRequest();
|
||||||
virtual ~nsImageRequest();
|
virtual ~nsImageRequest();
|
||||||
|
|
||||||
/* additional members */
|
/* 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:
|
private:
|
||||||
nsCOMPtr<nsIChannel> mChannel;
|
nsCOMPtr<nsIChannel> mChannel;
|
||||||
nsCOMPtr<nsIImageContainer> mImage;
|
nsCOMPtr<nsIImageContainer> mImage;
|
||||||
nsCOMPtr<nsIImageDecoder> mDecoder;
|
nsCOMPtr<nsIImageDecoder> mDecoder;
|
||||||
nsCOMPtr<nsIImageDecoderObserver> mObserver;
|
|
||||||
|
nsVoidArray mObservers;
|
||||||
|
|
||||||
PRBool mProcessing;
|
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