diff --git a/modules/libimg/gifcom/Makefile.in b/modules/libimg/gifcom/Makefile.in new file mode 100644 index 000000000000..c084fa7afff8 --- /dev/null +++ b/modules/libimg/gifcom/Makefile.in @@ -0,0 +1,51 @@ +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +LIBRARY_NAME = nsgif +EXPORT_LIBRARY = 1 +IS_COMPONENT = 1 +REQUIRES = xpcom string img layout locale util unicharutil + +CPPSRCS = \ + gif.cpp \ + nsGIFModule.cpp \ + nsGIFDecoder.cpp \ + $(NULL) + +LOCAL_INCLUDES = -I$(srcdir) + +EXTRA_LIBS = $(NSPR_LIBS) + +EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS) + +ifndef MOZ_JAVA +LOCAL_JMC_SUBDIR = . +endif + +include $(topsrcdir)/config/rules.mk + diff --git a/modules/libimg/gifcom/gif.cpp b/modules/libimg/gifcom/gif.cpp new file mode 100644 index 000000000000..927b1bd380bc --- /dev/null +++ b/modules/libimg/gifcom/gif.cpp @@ -0,0 +1,1709 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +/* -*- Mode: C; tab-width: 4 -*- + * gif.c --- GIF87 & GIF89 Image decoder + */ + + + +/* +The Graphics Interchange Format(c) is the copyright property of CompuServe +Incorporated. Only CompuServe Incorporated is authorized to define, redefine, +enhance, alter, modify or change in any way the definition of the format. + +CompuServe Incorporated hereby grants a limited, non-exclusive, royalty-free +license for the use of the Graphics Interchange Format(sm) in computer +software; computer software utilizing GIF(sm) must acknowledge ownership of the +Graphics Interchange Format and its Service Mark by CompuServe Incorporated, in +User and Technical Documentation. Computer software utilizing GIF, which is +distributed or may be distributed without User or Technical Documentation must +display to the screen or printer a message acknowledging ownership of the +Graphics Interchange Format and the Service Mark by CompuServe Incorporated; in +this case, the acknowledgement may be displayed in an opening screen or leading +banner, or a closing screen or trailing banner. A message such as the following +may be used: + + "The Graphics Interchange Format(c) is the Copyright property of + CompuServe Incorporated. GIF(sm) is a Service Mark property of + CompuServe Incorporated." + +For further information, please contact : + + CompuServe Incorporated + Graphics Technology Department + 5000 Arlington Center Boulevard + Columbus, Ohio 43220 + U. S. A. + +CompuServe Incorporated maintains a mailing list with all those individuals and +organizations who wish to receive copies of this document when it is corrected +or revised. This service is offered free of charge; please provide us with your +mailing address. + +*/ + +#include "nsIImgDecoder.h" +#include "il.h" +#include "prmem.h" + +#include "ilErrors.h" +#include "nsCRT.h" + +#include "gif.h" +#include "nsIImgDCallbk.h" + +#include "ilISystemServices.h" + +#define HOWMANY(x, r) (((x) + ((r) - 1)) / (r)) +#define ROUNDUP(x, r) (HOWMANY(x, r) * (r)) + +#ifdef DEBUG +static int il_debug_gif = 0; +static PRLogModuleInfo *il_log_module_gif = NULL; +#define ILTRACE(l,t) { if(il_debug_gif>l) {PR_LOG(il_log_module_gif, 1, t);} } +#else +#define ILTRACE(l,t) {} +#endif + +#ifndef MAX +# define MAX(x, y) (((x) > (y)) ? (x) : (y)) +#endif + +/* List of possible parsing states */ +typedef enum { + gif_gather, + gif_init, /*1*/ + gif_type, + gif_version, + gif_global_header, + gif_global_colormap, + gif_image_start, /*6*/ + gif_image_header, + gif_image_colormap, + gif_image_body, + gif_lzw_start, + gif_lzw, /*11*/ + gif_sub_block, + gif_extension, + gif_control_extension, + gif_consume_block, + gif_skip_block, + gif_done, /*17*/ + gif_oom, + gif_error, + gif_comment_extension, + gif_application_extension, + gif_netscape_extension_block, + gif_consume_netscape_extension, + gif_consume_comment, + gif_delay, + gif_wait_for_buffer_full, + gif_stop_animating //added for animation stop +} gstate; + +/* "Disposal" method indicates how the image should be handled in the + framebuffer before the subsequent image is displayed. */ +typedef enum +{ + DISPOSE_NOT_SPECIFIED = 0, + DISPOSE_KEEP = 1, /* Leave it in the framebuffer */ + DISPOSE_OVERWRITE_BGCOLOR = 2, /* Overwrite with background color */ + DISPOSE_OVERWRITE_PREVIOUS = 4 /* Save-under */ +} gdispose; + +#define MAX_HOLD 768 /* for now must be big enough for a cmap */ + +#define MAX_LZW_BITS 12 +#define MAX_BITS 4097 /* 2^MAX_LZW_BITS+1 */ +#define MINIMUM_DELAY_TIME 10 + + +/* A GIF decoder */ + +typedef struct +gif_struct { + /* Parsing state machine */ + gstate state; /* Curent decoder master state */ + PRUint8 *hold; /* Accumulation buffer */ + int32 hold_size; /* Capacity, in bytes, of accumulation buffer */ + PRUint8 *gather_head; /* Next byte to read in accumulation buffer */ + int32 gather_request_size; /* Number of bytes to accumulate */ + int32 gathered; /* bytes accumulated so far*/ + gstate post_gather_state; /* State after requested bytes accumulated */ + int32 requested_buffer_fullness; /* For netscape application extension */ + + /* LZW decoder state machine */ + PRUint8 *stack; /* Base of decoder stack */ + PRUint8 *stackp; /* Current stack pointer */ + PRUint16 *prefix; + PRUint8 *suffix; + int datasize; + int codesize; + int codemask; + int clear_code; /* Codeword used to trigger dictionary reset */ + int avail; /* Index of next available slot in dictionary */ + int oldcode; + PRUint8 firstchar; + int count; /* Remaining # bytes in sub-block */ + int bits; /* Number of unread bits in "datum" */ + int32 datum; /* 32-bit input buffer */ + + /* Output state machine */ + int ipass; /* Interlace pass; Ranges 1-4 if interlaced. */ + PRUintn rows_remaining; /* Rows remaining to be output */ + PRUintn irow; /* Current output row, starting at zero */ + PRUint8 *rgbrow; /* Temporary storage for dithering/mapping */ + PRUint8 *rowbuf; /* Single scanline temporary buffer */ + PRUint8 *rowend; /* Pointer to end of rowbuf */ + PRUint8 *rowp; /* Current output pointer */ + + /* Image parameters */ + PRUintn x_offset, y_offset; /* With respect to "screen" origin */ + PRUintn height, width; + PRUintn last_x_offset, last_y_offset; /* With respect to "screen" origin */ + PRUintn last_height, last_width; + int interlaced; /* TRUE, if scanlines arrive interlaced order */ + int tpixel; /* Index of transparent pixel */ + int is_transparent; /* TRUE, if tpixel is valid */ + int control_extension; /* TRUE, if image control extension present */ + int is_local_colormap_defined; + gdispose disposal_method; /* Restore to background, leave in place, etc.*/ + gdispose last_disposal_method; + IL_RGB *local_colormap; /* Per-image colormap */ + int local_colormap_size; /* Size of local colormap array. */ + int progressive_display; /* If TRUE, do Haeberli interlace hack */ + PRUint32 delay_time; /* Display time, in milliseconds, + for this image in a multi-image GIF */ + + /* Global (multi-image) state */ + int screen_bgcolor; /* Logical screen background color */ + int version; /* Either 89 for GIF89 or 87 for GIF87 */ + PRUintn screen_width; /* Logical screen width & height */ + PRUintn screen_height; + IL_RGB *global_colormap; /* Default colormap if local not supplied */ + int global_colormap_size; /* Size of global colormap array. */ + int images_decoded; /* Counts images for multi-part GIFs */ + il_container *ic; /* Back pointer to requesting image_container */ + void *delay_timeout; /* Used to delay after displaying picture */ + int destroy_pending; /* Stream has ended */ +} gif_struct; + +/* Gather n characters from the input stream and then enter state s. */ +#define GETN(n,s) \ +do {gs->state=gif_gather; gs->gather_request_size = (n); \ + gs->post_gather_state = s;} while (0) + +/* Get a 16-bit value stored in little-endian format */ +#define GETINT16(p) ((p)[1]<<8|(p)[0]) + +/* Get a 32-bit value stored in little-endian format */ +#define GETINT32(p) (((p)[3]<<24) | ((p)[2]<<16) | ((p)[1]<<8) | ((p)[0])) + +/* binary block Allocate and Concatenate + * + * destination_length is the length of the existing block + * source_length is the length of the block being added to the + * destination block + */ +static char * +il_BACat (char **destination, + size_t destination_length, + const char *source, + size_t source_length) +{ + if (source) + { + if (*destination) + { + *destination = (char *) PR_REALLOC (*destination, destination_length + source_length); + if (*destination == NULL) + return(NULL); + + nsCRT::memmove(*destination + destination_length, source, source_length); + + } + else + { + *destination = (char *) PR_MALLOC (source_length); + if (*destination == NULL) + return(NULL); + + nsCRT::memcpy(*destination, source, source_length); + } + } + + return *destination; +} +#undef BlockAllocCat +#define BlockAllocCat(dest, dest_length, src, src_length) il_BACat(&(dest), dest_length, src, src_length) + +/* Send the data to the display front-end. */ +static void +output_row(gif_struct *gs) +{ + int width, drow_start, drow_end; + + drow_start = drow_end = gs->irow; + + /* + * Haeberli-inspired hack for interlaced GIFs: Replicate lines while + * displaying to diminish the "venetian-blind" effect as the image is + * loaded. Adjust pixel vertical positions to avoid the appearance of the + * image crawling up the screen as successive passes are drawn. + */ + if (gs->progressive_display && gs->interlaced && (gs->ipass < 4)) + { + PRUintn row_dup=0, row_shift=0; + + switch (gs->ipass) { + case 1: + row_dup = 7; + row_shift = 3; + break; + case 2: + row_dup = 3; + row_shift = 1; + break; + case 3: + row_dup = 1; + row_shift = 0; + break; + default: + ILTRACE(0,("Illegal interlace pass")); + break; + } + + drow_start -= row_shift; + drow_end = drow_start + row_dup; + + /* Extend if bottom edge isn't covered because of the shift upward. */ + if (((gs->height - 1) - drow_end) <= row_shift) + drow_end = gs->height - 1; + + /* Clamp first and last rows to upper and lower edge of image. */ + if (drow_start < 0) + drow_start = 0; + if ((PRUintn)drow_end >= gs->height) + drow_end = gs->height - 1; + } + + /* Check for scanline below edge of logical screen */ + if ((gs->y_offset + gs->irow) < gs->screen_height) { + il_draw_mode draw_mode; + + if (gs->images_decoded >= 1) + draw_mode = ilOverlay; + else + draw_mode = ilErase; + + /* Clip if right edge of image exceeds limits */ + if ((gs->x_offset + gs->width) > gs->screen_width) + width = gs->screen_width - gs->x_offset; + else + width = gs->width; + + if (width > 0) + if(gs->ic->imgdcb) + gs->ic->imgdcb->ImgDCBHaveRow(gs->rowbuf, gs->rgbrow, + gs->x_offset, width, gs->y_offset + drow_start, + drow_end - drow_start + 1, draw_mode, gs->ipass); + + } + + gs->rowp = gs->rowbuf; + + if(!gs->interlaced) + { + gs->irow++; + } + else + { + do{ + switch(gs->ipass) + { + case 1: + gs->irow += 8; + if(gs->irow >= gs->height) + { + gs->ipass++; + gs->irow = 4; + } + break; + + case 2: + gs->irow += 8; + if(gs->irow >= gs->height) + { + gs->ipass++; + gs->irow = 2; + } + break; + + case 3: + gs->irow += 4; + if(gs->irow >= gs->height) + { + gs->ipass++; + gs->irow = 1; + } + break; + + case 4: + gs->irow += 2; + if(gs->irow >= gs->height){ + gs->ipass++; + gs->irow = 0; + } + break; + + default: + PR_ASSERT(0); + } + }while(gs->irow > gs->height - 1); + } +} + +/* Perform Lempel-Ziv-Welch decoding */ +static int +do_lzw(gif_struct *gs, const PRUint8 *q) +{ + int code; + int incode; + const PRUint8 *ch; + + /* Copy all the decoder state variables into locals so the compiler + * won't worry about them being aliased. The locals will be homed + * back into the GIF decoder structure when we exit. + */ + int avail = gs->avail; + int bits = gs->bits; + int codesize = gs->codesize; + int codemask = gs->codemask; + int count = gs->count; + int oldcode = gs->oldcode; + int clear_code = gs->clear_code; + PRUint8 firstchar = gs->firstchar; + int32 datum = gs->datum; + PRUint16 *prefix = gs->prefix; + PRUint8 *stackp = gs->stackp; + PRUint8 *suffix = gs->suffix; + PRUint8 *stack = gs->stack; + PRUint8 *rowp = gs->rowp; + PRUint8 *rowend = gs->rowend; + PRUintn rows_remaining = gs->rows_remaining; + + +#define OUTPUT_ROW(gs) \ + { \ + output_row(gs); \ + rows_remaining--; \ + rowp = gs->rowp; \ + if (!rows_remaining) \ + goto END; \ + } + + for (ch=q; count-- > 0; ch++) + { + /* Feed the next byte into the decoder's 32-bit input buffer. */ + datum += ((int32) *ch) << bits; + bits += 8; + + /* Check for underflow of decoder's 32-bit input buffer. */ + while (bits >= codesize) + { + /* Get the leading variable-length symbol from the data stream */ + code = datum & codemask; + datum >>= codesize; + bits -= codesize; + + /* Reset the dictionary to its original state, if requested */ + if (code == clear_code) + { + codesize = gs->datasize + 1; + codemask = (1 << codesize) - 1; + avail = clear_code + 2; + oldcode = -1; + continue; + } + + /* Check for explicit end-of-stream code */ + if (code == (clear_code + 1)) + return 0; + + if (oldcode == -1) + { + *rowp++ = suffix[code]; + if (rowp == rowend) { + OUTPUT_ROW(gs); + } + + firstchar = oldcode = code; + continue; + } + + /* Check for a code not defined in the dictionary yet. */ + if (code > avail) + { + ILTRACE(3,("il:gif: code too large %d %d", code, avail)); + return -1; + } + + incode = code; + if (code == avail) + { + /* the first code is always < avail */ + *stackp++ = firstchar; + code = oldcode; + } + + int code2=0; + while(code > clear_code) + { + code2 = code; + if(code == prefix[code]) + return -1; + + *stackp++ = suffix[code]; + code = prefix[code]; + + if(code2 == prefix[code]) + return -1; + } + + /* Define a new codeword in the dictionary. */ + *stackp++ = firstchar = suffix[code]; + prefix[avail] = oldcode; + suffix[avail] = firstchar; + avail++; + if(avail >= MAX_BITS) + return -1; + + /* If we've used up all the codewords of a given length + * increase the length of codewords by one bit, but don't + * exceed the specified maximum codeword size of 12 bits. + */ + if (((avail & codemask) == 0) && (avail < 4096)) + { + codesize++; + codemask += avail; + } + oldcode = incode; + + /* Copy the decoded data out to the scanline buffer. */ + do { + *rowp++ = *--stackp; + if (rowp == rowend) { + OUTPUT_ROW(gs); + } + } while (stackp > stack); + } + } + + END: + + /* Home the local copies of the GIF decoder state variables */ + gs->avail = avail; + gs->bits = bits; + gs->codesize = codesize; + gs->codemask = codemask; + gs->count = count; + gs->oldcode = oldcode; + gs->firstchar = firstchar; + gs->datum = datum; + gs->stackp = stackp; + gs->rowp = rowp; + gs->rows_remaining = rows_remaining; + + return 0; +} + +/* + * setup an ic for gif decoding + */ +PRBool +il_gif_init(il_container *ic) +{ + gif_struct *gs; + NI_ColorSpace *src_color_space = ic->src_header->color_space; + + gs = PR_NEWZAP(gif_struct); + if (gs) + { + ic->ds = gs; + gs->state = gif_init; + gs->post_gather_state = gif_error; + gs->gathered = 0; + gs->ic = ic; + } + + /* Initialize the container's source image header. */ + src_color_space->type = NI_PseudoColor; + src_color_space->pixmap_depth = 8; + src_color_space->bit_alloc.index_depth = 8; + + return (gs != 0); +} + +static int +il_gif_init_transparency(il_container *ic, int index) +{ + IL_IRGB *src_trans_pixel = ic->src_header->transparent_pixel; + IL_IRGB *img_trans_pixel; + + if (!src_trans_pixel) { + src_trans_pixel = PR_NEWZAP(IL_IRGB); + if (!src_trans_pixel) + return PR_FALSE; + ic->src_header->transparent_pixel = src_trans_pixel; + + /* Initialize the destination image's transparent pixel. */ + if(ic->imgdcb) + ic->imgdcb->ImgDCBInitTransparentPixel(); + + /* Set the source image's transparent pixel color to be the preferred + transparency color of the destination image. */ + img_trans_pixel = ic->image->header.transparent_pixel; + src_trans_pixel->red = img_trans_pixel->red; + src_trans_pixel->green = img_trans_pixel->green; + src_trans_pixel->blue = img_trans_pixel->blue; + } + + /* Set the source image's transparent pixel index. Do this even if the source + image's transparent pixel has previously been set, since the index can vary + from frame to frame in an animated gif. */ + src_trans_pixel->index = index; + + return PR_TRUE; +} + + +static void +il_gif_destroy_transparency(il_container *ic) +{ + NI_PixmapHeader *src_header = ic->src_header; + + if (src_header->transparent_pixel) { + /* Destroy the source image's transparent pixel. */ + PR_FREEIF(src_header->transparent_pixel); + src_header->transparent_pixel = NULL; + + /* Destroy the destination image's transparent pixel. */ + if(ic->imgdcb) + ic->imgdcb->ImgDCBDestroyTransparentPixel(); + } +} + + +int +il_gif_compute_percentage_complete(int row, il_container *ic) +{ + PRUintn percent_height; + int percent_done = 0; + + percent_height = (PRUintn)(row * (PRUint32)100 / ic->image->header.height); + switch(ic->pass) { + case 0: percent_done = percent_height; /* non-interlaced GIF */ + break; + case 1: percent_done = percent_height / 8; + break; + case 2: percent_done = 12 + percent_height / 8; + break; + case 3: percent_done = 25 + percent_height / 4; + break; + case 4: percent_done = 50 + percent_height / 2; + break; + default: + ILTRACE(0,("Illegal interlace pass")); + break; + } + + return percent_done; +} + +/* Maximum # of bytes to read ahead while waiting for delay_time to expire. + We no longer limit this number to remain within WIN16 malloc limitations + of 0xffff */ + +#define MAX_READ_AHEAD (0xFFFFFFL) + +PRUint8 +il_gif_write_ready(il_container *ic) +{ + gif_struct *gs = (gif_struct *)ic->ds; + int32 max; + + if (!gs) + return 1; /* Let imglib generic code decide */ + + max = MAX(MAX_READ_AHEAD, gs->requested_buffer_fullness); + if (gs->gathered < max) + return 1; /* Let imglib generic code decide */ + else + return 0; /* No more data until timeout expires */ +} + + +static void +process_buffered_gif_input_data(gif_struct* gs) +{ + gstate state; + il_container *ic = gs->ic; + PRUint8 err = 0; + + /* Force any data we've buffered up to be processed. */ + err = il_gif_write(ic, (PRUint8 *) "", 0); + + /* The stream has already finished delivering data and the stream + completion routine has been called sometime in the past. Now that + we're actually done handling all of that data, call the stream + completion routine again, but this time for real. */ + state = gs->state; + + if(ic->state==IC_ABORT_PENDING) + state = gif_error; + + /* test, stop loopers if error */ + if( state == gif_error){ + ic->loop_count = 0; + gs->destroy_pending = PR_TRUE; + ic->state = IC_ABORT_PENDING; + } + if (gs->destroy_pending && + ((state == gif_done) || (state == gif_error) || (state == gif_oom))) { + + il_gif_abort(ic); + + if(ic->imgdcb) + ic->imgdcb->ImgDCBHaveImageAll(); + } +} + +void +gif_delay_time_callback(void *closure) +{ + il_container *ic = (il_container*)closure; + gif_struct *gs = NULL; + + if((ic)&&(ic->ds)) + gs = (gif_struct *)ic->ds; + else + return; //error + + + PR_ASSERT(gs->state == gif_delay); + gs->delay_timeout = NULL; + + if(gs->ic){ + if(gs->ic->type == NULL) + gs->ic->type = nsCRT::strdup("image/gif"); //mime string + } + else + return; //error + + if (gs->ic->state == IC_ABORT_PENDING) + return; + + gs->delay_time = 0; /* Reset for next image */ + + if (gs->state == gif_delay) { + GETN(1, gif_image_start); + process_buffered_gif_input_data(gs); + } + return; +} + +/* + * For the first images in the sequence clear the logical + * screen to the background color, unless the first image + * completely covers the logical screen, in which case + * it's unnecessary. XXX - This can be optimized. + */ + +static int +gif_clear_screen(gif_struct *gs) +{ + PRUintn erase_width=0, erase_height=0, erase_x_offset=0, erase_y_offset=0; + PRBool erase; + il_container *ic = gs->ic; + + erase = PR_FALSE; + if (gs->images_decoded == 0) + { + if ((gs->width != gs->screen_width) || + (gs->height != gs->screen_height) || + gs->is_transparent) + { + erase = PR_TRUE; + erase_width = gs->screen_width; + erase_height = gs->screen_height; + erase_x_offset = erase_y_offset = 0; + } + } + else + { + if (gs->last_disposal_method == DISPOSE_OVERWRITE_BGCOLOR) + { + erase = PR_TRUE; + erase_width = gs->last_width; + erase_height = gs->last_height; + erase_x_offset = gs->last_x_offset; + erase_y_offset = gs->last_y_offset; + } + } + + gs->last_disposal_method = gs->disposal_method; + gs->last_width = gs->width; + gs->last_height = gs->height; + gs->last_x_offset = gs->x_offset; + gs->last_y_offset = gs->y_offset; + + if (erase) + { + PRUintn i; + int src_trans_pixel_index; + PRUint8 *rowbuf = gs->rowbuf; + NI_PixmapHeader *src_header = ic->src_header; + IL_IRGB *saved_src_trans_pixel, *saved_img_trans_pixel; + + /* Catch images that fall outside the logical screen. */ + if ((erase_x_offset + erase_width) > gs->screen_width) + erase_width = gs->screen_width - erase_x_offset; + + /* We have to temporarily pretend the image is transparent + so we can clear using the context's background color. */ + saved_img_trans_pixel = ic->image->header.transparent_pixel; + saved_src_trans_pixel = src_header->transparent_pixel; + src_header->transparent_pixel = NULL; + ic->image->header.transparent_pixel = NULL; + + /* Pick an index for the source image's temporary transparent pixel. + The actual choice is immaterial since it will only be used for + the clear screen operation. */ + + src_trans_pixel_index = 0; + if (!il_gif_init_transparency(ic, src_trans_pixel_index)) + return MK_OUT_OF_MEMORY; + + /* Now fill in the row buffer. */ + for (i = 0; i < erase_width; i++) + rowbuf[i] = src_trans_pixel_index; + + /* Note: We deliberately lie about the interlace + pass number so that calls to il_flush_image_data() + are done using a timer. */ + if (erase_width > 0) + if(gs->ic->imgdcb) + gs->ic->imgdcb->ImgDCBHaveRow(gs->rowbuf, gs->rgbrow, + erase_x_offset, erase_width, + erase_y_offset,erase_height, ilErase, 2); + + /* Reset the source image's transparent pixel to its former state. */ + il_gif_destroy_transparency(ic); + src_header->transparent_pixel = saved_src_trans_pixel; + ic->image->header.transparent_pixel = saved_img_trans_pixel; + } + return 0; +} + + +/* + * process data arriving from the stream for the gif decoder + */ + +int +il_gif_write(il_container *ic, const PRUint8 *buf, int32 len) +{ + int status; + gif_struct *gs = (gif_struct *)ic->ds; + NI_PixmapHeader *src_header = ic->src_header; + NI_ColorMap *cmap = &src_header->color_space->cmap; + const PRUint8 *q, *p=buf,*ep=buf+len; + + + /* If this assert fires, chances are the netlib flubbed and + continued to send data after the image stream was closed. */ + PR_ASSERT(gs); + if (!gs) { +#ifdef DEBUG + ILTRACE(1,("Netlib Error - imagelib image stream is closed\n")); +#endif + return MK_IMAGE_LOSSAGE; + } + + /* If this assert fires, some upstream data provider ignored the + zero return value from il_gif_write_ready() which says not to + send any more data to this stream until the delay timeout fires. */ + // PR_ASSERT ((len == 0) || (gs->gathered < MAX_READ_AHEAD)); + if (!((len == 0) || (gs->gathered < MAX_READ_AHEAD))) + return MK_INTERRUPTED; + + q = NULL; /* Initialize to shut up gcc warnings */ + + while (p <= ep) + { + ILTRACE(9,("il:gif: state %d len %d buf %u p %u q %u ep %u", + gs->state,len,buf,p,q,ep)); + switch(gs->state) + { + case gif_lzw: + if (do_lzw(gs, q) < 0) + { + gs->state=gif_error; + break; + } + GETN(1,gif_sub_block); + break; + + case gif_lzw_start: + { + int i; + + cmap->map = gs->is_local_colormap_defined ? + gs->local_colormap : gs->global_colormap; + + PR_ASSERT(cmap->map); + if (!cmap->map) + return MK_IMAGE_LOSSAGE; + + /* Now we know how many colors are in our colormap. */ + if (gs->is_local_colormap_defined || (gs->images_decoded == 0)){ + if(ic->imgdcb){ + nsresult rv = ic->imgdcb->ImgDCBSetupColorspaceConverter(); + if(NS_FAILED(rv)) + return MK_IMAGE_LOSSAGE; + } + } + + status = gif_clear_screen(gs); + if (status < 0) + return status; + + /* Initialize LZW parser/decoder */ + gs->datasize = *q; + if(gs->datasize > MAX_LZW_BITS) + { + gs->state=gif_error; + break; + } + + gs->clear_code = 1 << gs->datasize; + gs->avail = gs->clear_code + 2; + gs->oldcode = -1; + gs->codesize = gs->datasize + 1; + gs->codemask = (1 << gs->codesize) - 1; + + gs->datum = gs->bits = 0; + + if (!gs->prefix) + gs->prefix = (PRUint16 *)PR_Calloc(sizeof(PRUint16), MAX_BITS); + if (!gs->suffix) + gs->suffix = ( PRUint8 *)PR_Calloc(sizeof(PRUint8), MAX_BITS); + if (!gs->stack) + gs->stack = ( PRUint8 *)PR_Calloc(sizeof(PRUint8), MAX_BITS); + + if( !gs->prefix || !gs->suffix || !gs->stack) + { + /* complete from abort will free prefix & suffix */ + ILTRACE(0,("il:gif: MEM stack")); + gs->state=gif_oom; + break; + } + + if(gs->clear_code >= MAX_BITS) + { + gs->state=gif_error; + break; + } + + /* init the tables */ + for (i=0; i < gs->clear_code; i++) + gs->suffix[i] = i; + + gs->stackp = gs->stack; + + GETN(1,gif_sub_block); + } + break; + + /* We're positioned at the very start of the file. */ + case gif_init: + { + GETN(3,gif_type); + break; + } + + /* All GIF files begin with "GIF87a" or "GIF89a" */ + case gif_type: + { + if (strncmp((char*)q,"GIF",3)) + { + ILTRACE(2,("il:gif: not a GIF file")); + gs->state=gif_error; + break; + } + GETN(3,gif_version); + } + break; + + case gif_version: + { + if(!strncmp((char*)q,"89a",3)) + { + gs->version=89; + } + else + { + if(!strncmp((char*)q,"87a",3)) + { + gs->version=87; + } + else + { + ILTRACE(2,("il:gif: unrecognized GIF version number")); + gs->state=gif_error; + break; + } + } + ILTRACE(2,("il:gif: %d gif", gs->version)); + GETN(7,gif_global_header); + } + break; + + case gif_global_header: + { + /* This is the height and width of the "screen" or + * frame into which images are rendered. The + * individual images can be smaller than the + * screen size and located with an origin anywhere + * within the screen. + */ + + gs->screen_width = GETINT16(q); + gs->screen_height = GETINT16(q+2); + + gs->screen_bgcolor = q[5]; + + gs->global_colormap_size = 2<<(q[4]&0x07); + + /* A -ve value for cmap->num_colors indicates that the colors may + be non-unique.*/ + cmap->num_colors = -gs->global_colormap_size; + cmap->map = NULL; + + if(q[6]) + { + /* should assert gif89 */ + if(q[6] != 49) + { +#ifdef DEBUG + float aspect = (float)((q[6] + 15) / 64.0); + ILTRACE(2, ("il:gif: %f aspect ratio", aspect)); +#endif + } + } + + if( q[4] & 0x80 ) /* global map */ + { + GETN(gs->global_colormap_size*3, gif_global_colormap); + } + else + { + GETN(1, gif_image_start); + } + } + break; + + case gif_global_colormap: + { + IL_RGB* map; + int i; + + if(!(map = (IL_RGB*)PR_Calloc(gs->global_colormap_size, + sizeof(IL_RGB)))) + { + ILTRACE(0,("il:gif: MEM map")); + gs->state=gif_oom; + break; + } + + if(ic->imgdcb) + ic->imgdcb->ImgDCBResetPalette(); + gs->global_colormap = map; + +#ifndef M12N /* Fix me. */ +#ifdef XP_MAC + im->hasUniqueColormap = 1; +#endif +#endif /* M12N */ + for (i=0; i < gs->global_colormap_size; i++, map++) + { + map->red = *q++; + map->green = *q++; + map->blue = *q++; + } + + GETN(1,gif_image_start); + } + break; + + case gif_image_start: + { + if(*q==';') /* terminator */ + { + gs->state = gif_done; + break; + } + + if(*q=='!') /* extension */ + { + GETN(2,gif_extension); + break; + } + + if(*q!=',') /* invalid start character */ + { + ILTRACE(2,("il:gif: bogus start character 0x%02x", + (int)*q)); + gs->state=gif_error; + break; + } + else + { + /* If this is a multi-part GIF, flush the last image */ + if (gs->images_decoded) { + ic->multi++; /* Avoid progressive display */ + } + + GETN(9, gif_image_header); + } + } + break; + + case gif_extension: + { + int len = gs->count = q[1]; + gstate es = gif_skip_block; + + ILTRACE(2,("il:gif: %d byte extension %x", len, (int)*q)); + switch(*q) + { + case 0xf9: + es = gif_control_extension; + break; + + case 0x01: + ILTRACE(2,("il:gif: ignoring plain text extension")); + break; + + case 0xff: + es = gif_application_extension; + break; + + case 0xfe: + es = gif_consume_comment; + break; + } + + if (len) + GETN(len, es); + else + GETN(1, gif_image_start); + } + break; + + case gif_consume_block: + { + if(!*q) + { + GETN(1, gif_image_start); + } + else + { + GETN(*q, gif_skip_block); + } + } + break; + + case gif_skip_block: + GETN(1, gif_consume_block); + break; + + case gif_control_extension: + { + if(*q & 0x1) + { + gs->tpixel = *(q+3); + ILTRACE(2,("il:gif: transparent pixel %d", gs->tpixel)); + if (!il_gif_init_transparency(ic, gs->tpixel)) + return MK_OUT_OF_MEMORY; + gs->is_transparent = PR_TRUE; + } + else + { + ILTRACE(2,("il:gif: ignoring gfx control extension")); + } + gs->control_extension = PR_TRUE; + gs->disposal_method = (gdispose)(((*q) >> 2) & 0x7); + gs->delay_time = GETINT16(q + 1) * 10; + GETN(1,gif_consume_block); + } + break; + + case gif_comment_extension: + { + gs->count = *q; + if (gs->count) + GETN(gs->count, gif_consume_comment); + else + GETN(1, gif_image_start); + } + break; + + case gif_consume_comment: + { + BlockAllocCat(ic->comment, ic->comment_length, (char*)q, gs->count); + ic->comment_length += gs->count; + BlockAllocCat(ic->comment, ic->comment_length, "", 1); + ic->comment_length++; + GETN(1, gif_comment_extension); + } + break; + + case gif_application_extension: + /* Check for netscape application extension */ + if (!strncmp((char*)q, "NETSCAPE2.0", 11) || + !strncmp((char*)q, "ANIMEXTS1.0", 11)) + GETN(1, gif_netscape_extension_block); + else + GETN(1, gif_consume_block); + break; + + /* Netscape-specific GIF extension: animation looping */ + case gif_netscape_extension_block: + if (*q) + GETN(*q, gif_consume_netscape_extension); + else + GETN(1, gif_image_start); + break; + + /* Parse netscape-specific application extensions */ + case gif_consume_netscape_extension: + { + int netscape_extension = q[0] & 7; + + /* Loop entire animation specified # of times. Only read the + loop count during the first iteration. */ + if (netscape_extension == 1) { + if (!ic->is_looping) { + ic->loop_count = GETINT16(q + 1); + + /* Zero loop count is infinite animation loop request */ + if (ic->loop_count == 0) + ic->loop_count = -1; + + /* Tell the front end that the stop state might have changed */ + /* because of the looping GIF. */ +#ifndef M12N /* XXXM12N Fix me. */ + if (ic->net_cx) + FE_UpdateStopState(ic->net_cx); +#endif /* M12N */ + } + + GETN(1, gif_netscape_extension_block); + } + + /* Wait for specified # of bytes to enter buffer */ + else if (netscape_extension == 2) + { + gs->requested_buffer_fullness = GETINT32(q + 1); + GETN(gs->requested_buffer_fullness, gif_wait_for_buffer_full); + } + + break; + } + + case gif_wait_for_buffer_full: + gs->gathered = gs->requested_buffer_fullness; + GETN(1, gif_netscape_extension_block); + break; + + case gif_image_header: + { + PRUintn height, width; + + /* Get image offsets, with respect to the screen origin */ + gs->x_offset = GETINT16(q); + gs->y_offset = GETINT16(q + 2); + + /* Get image width and height. */ + width = GETINT16(q + 4); + height = GETINT16(q + 6); + + ILTRACE(2,("il:gif: screen %dx%d, image %dx%d", + gs->screen_width, gs->screen_height, width, height)); + + /* Work around broken GIF files where the logical screen + * size has weird width or height. We assume that GIF87a + * files don't contain animations. + */ + if ((gs->images_decoded == 0) && + ((gs->screen_height < height) || (gs->screen_width < width) || + (gs->version == 87))){ + gs->screen_height = height; + gs->screen_width = width; + gs->x_offset = 0; + gs->y_offset = 0; + } + /* Work around more broken GIF files that have zero image + width or height */ + if (!height || !width) + { + height = gs->screen_height; + width = gs->screen_width; + } + + gs->height = height; + gs->width = width; + + /* This case will never be taken if this is the first image */ + /* being decoded. If any of the later images are larger */ + /* than the screen size, we need to reallocate buffers. */ + if (gs->screen_width < width) { + + gs->rgbrow = (PRUint8*)PR_REALLOC(gs->rgbrow, 3 * width); + gs->rowbuf = (PRUint8*)PR_REALLOC(gs->rowbuf, width); + + if((!gs->rgbrow)||(!gs->rowbuf)){ + gs->state = gif_oom; + break; + } + + gs->screen_width = width; + if(gs->screen_height < gs->height ) + gs->screen_height = gs->height; + + ic->src_header->width = gs->width; + ic->src_header->height = gs->height; + ic->image->header.width = gs->width; + ic->image->header.height = gs->height; + ic->image->header.widthBytes = (ic->image->header.width * ic->image->header.color_space->pixmap_depth + 7)/8; + + ic->image->header.widthBytes = ROUNDUP(ic->image->header.widthBytes, 4); + + if(ic->imgdcb){ + nsresult rv = ic->imgdcb->ImgDCBImageSize(); + + if(NS_FAILED(rv)){ + gs->state = gif_error; + break; + } + } + else{ //no callback is an error too. + gs->state = gif_error; + break; + } + + ic->img_cx->img_cb->NewPixmap(ic->img_cx->dpy_cx, ic->dest_width, + ic->dest_height, ic->image, ic->mask); + + if((!ic->scalerow)||(!ic->image->bits)||(ic->mask && !ic->mask->bits)){ + gs->state=gif_oom; + break; + } + } + else{ + if (!gs->rgbrow) + gs->rgbrow = (PRUint8*)PR_MALLOC(3 * gs->screen_width); + + if (!gs->rowbuf) + gs->rowbuf = (PRUint8*)PR_MALLOC(gs->screen_width); + } + + if (!gs->rowbuf || !gs->rgbrow) + { + ILTRACE(0,("il:gif: MEM row")); + gs->state=gif_oom; + break; + } + + /* Free transparency from earlier image in multi-image sequence. */ + if (!gs->is_transparent && src_header->transparent_pixel) { + il_gif_destroy_transparency(ic); + } + + if (gs->images_decoded == 0) { + src_header->width = gs->screen_width; + src_header->height = gs->screen_height; + + if(ic->imgdcb){ + nsresult rv = ic->imgdcb->ImgDCBImageSize(); + + if(NS_FAILED(rv)){ + gs->state = gif_error; + break; + } + } + else{ //no callback is an error too. + gs->state = gif_error; + break; + } + } + + if ( *(q+8) & 0x40 ) + { + ILTRACE(2,("il:gif: interlaced")); + gs->interlaced = PR_TRUE; + gs->ipass = 1; + } else { + gs->interlaced = PR_FALSE; + gs->ipass = 0; + } + + if (gs->images_decoded == 0) + { + gs->progressive_display = ic->img_cx->progressive_display; + } else { + + /* Overlaying interlaced, transparent GIFs over + existing image data using the Haeberli display hack + requires saving the underlying image in order to + avoid jaggies at the transparency edges. We are + unprepared to deal with that, so don't display such + images progressively */ + gs->progressive_display = ic->img_cx->progressive_display && + !(gs->interlaced && gs->is_transparent); + } + + /* Clear state from last image */ + gs->requested_buffer_fullness = 0; + gs->irow = 0; + gs->rows_remaining = gs->height; + gs->rowend = gs->rowbuf + gs->width; + gs->rowp = gs->rowbuf; + + /* bits per pixel is 1<<((q[8]&0x07)+1); */ + + if ( *(q+8) & 0x80 ) + { + int num_colors = 2 << (*(q + 8) & 0x7); + + if ((num_colors > gs->local_colormap_size) && + gs->local_colormap) + { + PR_FREEIF(gs->local_colormap); + gs->local_colormap = NULL; + } + gs->local_colormap_size = num_colors; + /* A -ve value for cmap->num_colors indicates that the colors + may be non-unique. */ + cmap->num_colors = -num_colors; + + /* Switch to the new local palette after it loads */ + if(ic->imgdcb) + ic->imgdcb->ImgDCBResetPalette(); + + gs->is_local_colormap_defined = PR_TRUE; + GETN(gs->local_colormap_size * 3, gif_image_colormap); + } + else + { + /* Switch back to the global palette */ + if (gs->is_local_colormap_defined) + if(ic->imgdcb) + ic->imgdcb->ImgDCBResetPalette(); + + gs->is_local_colormap_defined = PR_FALSE; + GETN(1, gif_lzw_start); + } + } + break; + + case gif_image_colormap: + { + IL_RGB* map; + int i; + + ILTRACE(2,("il:gif: local colormap")); + + map = gs->local_colormap; + if (!map) + { + map = gs->local_colormap = (IL_RGB*)PR_Calloc( + gs->local_colormap_size, sizeof(IL_RGB)); + + if(!map) + { + ILTRACE(0,("il:gif: MEM map")); + gs->state=gif_oom; + break; + } + } + +#ifndef M12N /* Fix me */ +#ifdef XP_MAC + im->hasUniqueColormap = 1; +#endif +#endif /* M12N */ + + for (i=0; i < gs->local_colormap_size; i++, map++) + { + map->red = *q++; + map->green = *q++; + map->blue = *q++; + } + + GETN(1,gif_lzw_start); + } + break; + + case gif_sub_block: + { + if ((gs->count = *q) != 0) + /* Still working on the same image: Process next LZW data block */ + { + /* Make sure there are still rows left. If the GIF data */ + /* is corrupt, we may not get an explicit terminator. */ + if (gs->rows_remaining == 0) { + ILTRACE(3,("il:gif: missing image terminator, continuing")); + /* This is an illegal GIF, but we remain tolerant. */ +#ifdef DONT_TOLERATE_BROKEN_GIFS + gs->state=gif_error; + break; +#else + GETN(1,gif_sub_block); +#endif + } + GETN(gs->count, gif_lzw); + } + else + /* See if there are any more images in this sequence. */ + { + /* Flush the image data unconditionally, so that we can + notify observers that the current frame has completed. */ + if(ic->imgdcb){ + ic->imgdcb->ImgDCBFlushImage(); + ic->imgdcb->ImgDCBHaveImageFrame(); + } + + gs->images_decoded++; + + /* Clear state from this image */ + gs->control_extension = PR_FALSE; + gs->is_transparent = PR_FALSE; + + if(ic->animate_request == eImageAnimation_None){ + /* This is not really an error, but a mechanism + to stop decoding of subsequent frames. Only the + first frame is displayed for eImageAnimation_None. + */ + gs->state = gif_stop_animating; + break; + } + + /* An image can specify a delay time before which to display + subsequent images. Block until the appointed time. */ + if(gs->delay_time < MINIMUM_DELAY_TIME ) + gs->delay_time = MINIMUM_DELAY_TIME; + + if (gs->delay_time){ + if(ic->imgdcb){ + gs->delay_timeout = (void *) + ic->imgdcb->ImgDCBSetTimeout(gif_delay_time_callback, gs->ic, gs->delay_time); + } + /* Essentially, tell the decoder state machine to wait + forever. The timeout callback routine will wake up the + state machine and force it to decode the next image. */ + GETN(1L<<30, gif_image_start); + gs->state = gif_delay; + } else { + GETN(1, gif_image_start); + } + + } + } + break; + + case gif_done: + return 0; + break; + + case gif_delay: + case gif_gather: + { + int32 gather_remaining; + int32 request_size = gs->gather_request_size; + + { + gather_remaining = request_size - gs->gathered; + + /* Do we already have enough data in the accumulation + buffer to satisfy the request ? (This can happen + after we transition from the gif_delay state.) */ + if (gather_remaining <= 0) + { + gs->gathered -= request_size; + q = gs->gather_head; + gs->gather_head += request_size; + gs->state = gs->post_gather_state; + break; + } + + /* Shift remaining data to the head of the buffer */ + if (gs->gathered && (gs->gather_head != gs->hold)) { + nsCRT::memmove(gs->hold, gs->gather_head, gs->gathered); + gs->gather_head = gs->hold; + } + + /* If we add the data just handed to us by the netlib + to what we've already gathered, is there enough to satisfy + the current request ? */ + if ((ep - p) >= gather_remaining) + { + if(gs->gathered) + { /* finish a prior gather */ + char *hold = (char*)gs->hold; + BlockAllocCat(hold, gs->gathered, (char*)p, gather_remaining); + gs->hold = (PRUint8*)hold; + q = gs->gather_head = gs->hold; + gs->gathered = 0; + } + else + { + q = p; + } + p += gather_remaining; + gs->state = gs->post_gather_state; + } + else + { + char *hold = (char*)gs->hold; + BlockAllocCat(hold, gs->gathered, (char*)p, ep - p); + gs->hold = (PRUint8*)hold; + gs->gather_head = gs->hold; + gs->gathered += ep-p; + return 0; + } + } + } + break; + + case gif_oom: + ILTRACE(1,("il:gif: reached oom state")); + return MK_OUT_OF_MEMORY; + break; + + case gif_error: + ILTRACE(2,("il:gif: reached error state")); + return MK_IMAGE_LOSSAGE; + break; + + case gif_stop_animating: + return 0; + break; + + default: + ILTRACE(0,("il:gif: unknown state")); + PR_ASSERT(0); + break; + } + } + + return 0; +} + +void +il_gif_complete(il_container *ic) +{ + if (ic->ds) + { + gif_struct *gs = (gif_struct*) ic->ds; + + /* No more data in the stream, but we may still have work to do, + so don't actually free any of the data structures. */ + if (gs->delay_timeout) { + /* We will free the data structures when image display completes. */ + gs->destroy_pending = PR_TRUE; + return; + } else if (gs->requested_buffer_fullness) { + /* We will free the data structures when image display completes. */ + gs->destroy_pending = PR_TRUE; + process_buffered_gif_input_data(gs); + return; + } + if(!(ic->is_multipart)) + il_gif_abort(ic); + } + + if (ic->imgdcb) + ic->imgdcb->ImgDCBHaveImageAll(); + else + il_gif_abort(ic); + +} + +/* Free up all the data structures associated with decoding a GIF */ +void +il_gif_abort(il_container *ic) +{ + if (ic->ds) + { + gif_struct *gs = (gif_struct*) ic->ds; + + /* Clear any pending timeouts */ + if (gs->delay_timeout) { + ic->imgdcb->ImgDCBClearTimeout(gs->delay_timeout); + gs->delay_timeout = NULL; + } + + PR_FREEIF(gs->rowbuf); + PR_FREEIF(gs->rgbrow); + PR_FREEIF(gs->prefix); + PR_FREEIF(gs->suffix); + PR_FREEIF(gs->stack); + + PR_FREEIF(gs->hold); + + /* Free the colormap that is not in use. The other one, if + * present, will be freed when the image container is + * destroyed. + */ + + if (gs->is_local_colormap_defined) { + if (gs->local_colormap) { + PR_FREEIF(gs->local_colormap); + gs->local_colormap = NULL; + ic->src_header->color_space->cmap.map = NULL; + } + } + if (gs->global_colormap) { + PR_FREEIF(gs->global_colormap); + gs->global_colormap = NULL; + ic->src_header->color_space->cmap.map = NULL; + } + + + PR_FREEIF(gs); + ic->ds = 0; + } +} + diff --git a/modules/libimg/gifcom/gif.h b/modules/libimg/gifcom/gif.h new file mode 100644 index 000000000000..1735e3c154ab --- /dev/null +++ b/modules/libimg/gifcom/gif.h @@ -0,0 +1,31 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + + +/* gif.h */ + +extern PRBool il_gif_init(il_container *ic); +extern int il_gif_write(il_container *, const PRUint8 *, int32); +extern void il_gif_complete(il_container *ic); +extern PRUint8 il_gif_write_ready(il_container *ic); +extern void il_gif_abort(il_container *ic); +extern void gif_delay_time_callback(void *closure); diff --git a/modules/libimg/gifcom/makefile.win b/modules/libimg/gifcom/makefile.win new file mode 100644 index 000000000000..c46e6afa16e8 --- /dev/null +++ b/modules/libimg/gifcom/makefile.win @@ -0,0 +1,98 @@ +#!gmake +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): + + +# + +#------------------------------------------------------------------------ +# +# Makefile to build the IMGLIB LIB +# +#------------------------------------------------------------------------ + +!ifdef MOZ_JAVA +LOCAL_JMC_SUBDIR = . +!endif + + +LIBRARY_NAME = nsgif + +# +# Make sure we have MOZILLA_CLIENT defined so we get the +# proper JS includes +# +LCFLAGS = $(LCFLAGS) -DMOZILLA_CLIENT + +!ifdef BUILD_DEBUG_GC +LCFLAGS = $(LCFLAGS) -DDEBUG_GC +!endif + +LCFLAGS = $(LCFLAGS) /TP + +LLIBS= $(LIBNSPR) \ + $(DIST)\lib\util.lib \ + $(DIST)\lib\xpcom.lib \ +!ifdef NU_CACHE + $(DIST)\lib\cache.lib \ +!endif + $(NULL) + +LIBRARY= .\$(OBJDIR)\$(LIBNAME).lib +LIBRARY_SUFFIX = $(MOZ_BITS)$(VERSION_NUMBER) + +MAKE_OBJ_TYPE=DLL +#//------------------------------------------------------------------------ +#// +#// Define any Public Make Variables here: (ie. PDFFILE, MAPFILE, ...) +#// +#//------------------------------------------------------------------------ +DLLNAME=nsgif +DLL1NAME=nsgif +PDBFILE=$(DLLNAME).pdb +MAPFILE=$(DLLNAME).map +DEFFILE=nsgif.def + + +#//------------------------------------------------------------------------ +#// +#// Define any Public Targets here (ie. PROGRAM, LIBRARY, DLL, ...) +#// (these must be defined before the common makefiles are included) +#// +#//------------------------------------------------------------------------ +DLL=.\$(OBJDIR)\$(DLLNAME).dll +MAPFILE= $(DLLNAME).map + + + +MODULE=img +DEPTH=..\..\.. + +LINCS=-I$(DEPTH)/dist/public/xpcom -I. -I$(DEPTH)/dist/public/raptor +CPPSRCS= nsGIFModule.cpp nsGIFDecoder.cpp gif.cpp +CPP_OBJS= .\$(OBJDIR)\nsGIFModule.obj .\$(OBJDIR)\nsGIFDecoder.obj \ + .\$(OBJDIR)\gif.obj + +include <$(DEPTH)\config\rules.mak> + +install:: $(DLL) + $(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin\components + $(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib + diff --git a/modules/libimg/gifcom/nsGIFDecoder.cpp b/modules/libimg/gifcom/nsGIFDecoder.cpp new file mode 100644 index 000000000000..bf527e4d5f83 --- /dev/null +++ b/modules/libimg/gifcom/nsGIFDecoder.cpp @@ -0,0 +1,128 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +/* + * nsGIFDecoder.cpp --- interface to gif decoder + */ + +#include "nsGIFDecoder.h" +#include "nsCOMPtr.h" + +////////////////////////////////////////////////////////////////////// +// GIF Decoder Implementation + +NS_IMPL_ISUPPORTS1(GIFDecoder, nsIImgDecoder); + +GIFDecoder::GIFDecoder(il_container* aContainer) +{ + NS_INIT_REFCNT(); + ilContainer = aContainer; +} + +GIFDecoder::~GIFDecoder(void) +{ +} + + +NS_METHOD +GIFDecoder::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) +{ + nsresult rv; + if (aOuter) return NS_ERROR_NO_AGGREGATION; + + il_container *ic = new il_container(); + if (!ic) return NS_ERROR_OUT_OF_MEMORY; + + GIFDecoder *decoder = new GIFDecoder(ic); + if (!decoder) { + delete ic; + return NS_ERROR_OUT_OF_MEMORY; + } + + NS_ADDREF(decoder); + rv = decoder->QueryInterface(aIID, aResult); + NS_RELEASE(decoder); + + /* why are we creating and destroying this object for no reason? */ + delete ic; /* is a place holder */ + + return rv; +} + + +NS_IMETHODIMP +GIFDecoder::ImgDInit() +{ + PRBool ret=PR_FALSE; + + if(ilContainer != NULL) { + ret=il_gif_init(ilContainer); + } + if(ret) + return NS_OK; + else + return NS_ERROR_FAILURE; +} + + +NS_IMETHODIMP +GIFDecoder::ImgDWriteReady(PRUint32 *max_read) +{ + + if(ilContainer != NULL) { + *max_read = il_gif_write_ready(ilContainer); + } + return NS_OK; +} + +NS_IMETHODIMP +GIFDecoder::ImgDWrite(const unsigned char *buf, int32 len) +{ + int ret = 0; + + if( ilContainer != NULL ) { + ret = il_gif_write(ilContainer, buf,len); + if(ret != 0) + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +NS_IMETHODIMP +GIFDecoder::ImgDComplete() +{ + if( ilContainer != NULL ) { + il_gif_complete(ilContainer); + } + return NS_OK; +} + +NS_IMETHODIMP +GIFDecoder::ImgDAbort() +{ + if( ilContainer != NULL ) { + il_gif_abort(ilContainer); + } + return NS_OK; +} + + diff --git a/modules/libimg/gifcom/nsGIFDecoder.h b/modules/libimg/gifcom/nsGIFDecoder.h new file mode 100644 index 000000000000..64269bc4fd9c --- /dev/null +++ b/modules/libimg/gifcom/nsGIFDecoder.h @@ -0,0 +1,66 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +/* -*- Mode: C; tab-width: 4 -*- + * nsGIFDecoder.cpp --- interface to gif decoder + */ +#ifndef _nsGIFDec_h +#define _nsGIFDec_h + +#include "nsISupports.h" +#include "nsIImgDecoder.h" +#include "gif.h" + +#define NS_GIFDECODER_CID \ +{ 0x0d471b70, 0xbaf5, 0x11d2, \ +{ 0x80, 0x2c, 0x00, 0x60, 0x08, 0x8f, 0x91, 0xa3 } } + +////////////////////////////////////////////////////////////////////// +// GIF Decoder Definition + +class GIFDecoder : public nsIImgDecoder +{ +public: + GIFDecoder(il_container* aContainer); + virtual ~GIFDecoder(); + + NS_DECL_ISUPPORTS + + static NS_METHOD Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); + + /* stream */ + NS_IMETHOD ImgDInit(); + + NS_IMETHOD ImgDWriteReady(PRUint32 *max_read); + NS_IMETHOD ImgDWrite(const unsigned char *buf, int32 len); + NS_IMETHOD ImgDComplete(); + NS_IMETHOD ImgDAbort(); + + NS_IMETHOD_(il_container *) SetContainer(il_container *ic){ilContainer = ic; return ic;} + NS_IMETHOD_(il_container *) GetContainer() {return ilContainer;} + + +private: + il_container* ilContainer; +}; + +#endif diff --git a/modules/libimg/gifcom/nsGIFModule.cpp b/modules/libimg/gifcom/nsGIFModule.cpp new file mode 100644 index 000000000000..a8beceb9c21a --- /dev/null +++ b/modules/libimg/gifcom/nsGIFModule.cpp @@ -0,0 +1,40 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +#include "nsGIFDecoder.h" +#include "nsIComponentManager.h" +#include "nsIGenericFactory.h" +#include "nsISupports.h" +#include "nsCOMPtr.h" + +static NS_DEFINE_CID(kGIFDecoderCID, NS_GIFDECODER_CID); + +static nsModuleComponentInfo components[] = +{ + { "GIF Decoder", + NS_GIFDECODER_CID, + "@mozilla.org/image/decoder;1?type=image/gif", + GIFDecoder::Create } +}; + +NS_IMPL_NSGETMODULE(nsGIFModule, components) + diff --git a/modules/libimg/gifcom/nsgif.def b/modules/libimg/gifcom/nsgif.def new file mode 100644 index 000000000000..e041893d24c6 --- /dev/null +++ b/modules/libimg/gifcom/nsgif.def @@ -0,0 +1,14 @@ +; +; temp def file for nsgif dll +; + +LIBRARY nsgif.dll +DESCRIPTION 'test dll' + +EXPORTS + ImgDInit @1002 PRIVATE + ImgDWrite @1003 PRIVATE + ImgDWriteReady @1004 PRIVATE + ImgDComplete @1005 PRIVATE + ImgDAbort @1006 PRIVATE + diff --git a/modules/libimg/gifcom/win32.order b/modules/libimg/gifcom/win32.order new file mode 100644 index 000000000000..3c5b907b4a27 --- /dev/null +++ b/modules/libimg/gifcom/win32.order @@ -0,0 +1,21 @@ +?il_gif_write@@YAHPAUil_container_struct@@PBEJ@Z ; 43937 +?il_BACat@@YAPADPAPADIPBDI@Z ; 42718 +?gif_delay_time_callback@@YAXPAX@Z ; 41012 +?ImgDWrite@GIFDecoder@@UAGIPBEJ@Z ; 2925 +?il_gif_write_ready@@YAEPAUil_container_struct@@@Z ; 2820 +?ImgDWriteReady@GIFDecoder@@UAGIPAI@Z ; 2820 +?AddRef@GIFDecoder@@UAGKXZ ; 2814 +?Release@GIFDecoder@@UAGKXZ ; 2776 +?il_gif_abort@@YAXPAUil_container_struct@@@Z ; 1486 +?SetContainer@GIFDecoder@@UAGPAUil_container_struct@@PAU2@@Z ; 1474 +?QueryInterface@GIFDecoder@@UAGIABUnsID@@PAPAX@Z ; 1407 +??0GIFDecoder@@QAE@PAUil_container_struct@@@Z ; 1407 +?ImgDComplete@GIFDecoder@@UAGIXZ ; 1407 +?ImgDInit@GIFDecoder@@UAGIXZ ; 1407 +?il_gif_init@@YAHPAUil_container_struct@@@Z ; 1407 +?Create@GIFDecoder@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 1407 +?il_gif_complete@@YAXPAUil_container_struct@@@Z ; 1407 +??1GIFDecoder@@UAE@XZ ; 1369 +??_GGIFDecoder@@UAEPAXI@Z ; 1369 +?ImgDAbort@GIFDecoder@@UAGIXZ ; 136 +_NSGetModule ; 1 diff --git a/modules/libimg/jpgcom/.cvsignore b/modules/libimg/jpgcom/.cvsignore new file mode 100644 index 000000000000..f3c7a7c5da68 --- /dev/null +++ b/modules/libimg/jpgcom/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/modules/libimg/jpgcom/Makefile.in b/modules/libimg/jpgcom/Makefile.in new file mode 100644 index 000000000000..fb1cfa0fc534 --- /dev/null +++ b/modules/libimg/jpgcom/Makefile.in @@ -0,0 +1,61 @@ +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +LIBRARY_NAME = nsjpg +EXPORT_LIBRARY = 1 +IS_COMPONENT = 1 +REQUIRES = xpcom string img util layout locale jpeg unicharutil + +CPPSRCS = \ + jpeg.cpp \ + nsJPGDecoder.cpp \ + nsJPGModule.cpp \ + $(NULL) + +LOCAL_INCLUDES = -I$(srcdir) + +EXTRA_DSO_LDOPTS = $(JPEG_LIBS) \ + $(MOZ_COMPONENT_LIBS) \ + $(NULL) + +EXTRA_LIBS = $(NSPR_LIBS) + +ifndef MOZ_JAVA +LOCAL_JMC_SUBDIR = . +endif + +include $(topsrcdir)/config/rules.mk + +ifeq ($(OS_ARCH)$(OS_RELEASE),SunOS5) +ifeq ($(shell uname -r),5.3) +# In this special case (jpeg.cpp), the compiler has to know +# the OS version to a finer granularity than normal. +DEFINES += -DOSMINOR=3 +endif +endif + diff --git a/modules/libimg/jpgcom/jpeg.cpp b/modules/libimg/jpgcom/jpeg.cpp new file mode 100644 index 000000000000..6d2c6b7cbfac --- /dev/null +++ b/modules/libimg/jpgcom/jpeg.cpp @@ -0,0 +1,1012 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +/* + * jpeg.c --- Glue code to Independent JPEG Group decoder library + * $Id: jpeg.cpp,v 1.30 2001/06/19 11:11:40 pavlov%netscape.com Exp $ + */ + + + +#include "nsIImgDecoder.h" // include if_struct.h Needs to be first +#include "nsIImgDCallbk.h" +#include "nsCRT.h" +#include "nsJPGDecoder.h" +#include "jpeg.h" +#include "ilErrors.h" +#include "il.h" + +#include /* to declare isprint() */ +#ifndef XP_MAC +# include +#endif + +/* This is a lame hack to get around a problem with boolean on Solaris 2.3 */ +#if defined(__sun) && defined(__sparc) && defined(__svr4__) && (OSMINOR == 3) +#define HAVE_BOOLEAN +#undef MUST_UNDEF_HAVE_BOOLEAN_AFTER_INCLUDES +#endif + +PR_BEGIN_EXTERN_C +#include "jpeglib.h" +#include "jerror.h" +PR_END_EXTERN_C + +#ifdef XP_OS2 +/* IBM-MAS: We removed setjmp.h from XP_core.h, now we need it here. */ +/* We need to see if we can fix hwthreads/XP_CORE correctly.. */ +#include +#endif + +#ifdef PROFILE +# pragma profile on +#endif + +/* Normal JFIF markers can't have more bytes than this. */ +#define MAX_JPEG_MARKER_LENGTH (((PRUint32)1 << 16) - 1) + +#ifdef DEBUG +static int il_debug_jpg = 0; +static PRLogModuleInfo *il_log_module_jpg = NULL; +#define ILTRACE(l,t) { if(il_debug_jpg>l) {PR_LOG(il_log_module_jpg, 1, t);} } +#else +#define ILTRACE(l,t) {} +#endif + +/* + * States that the jpeg decoder might be in + */ +typedef enum { + JPEG_HEADER, /* Reading JFIF headers */ + JPEG_START_DECOMPRESS, + JPEG_DECOMPRESS_PROGRESSIVE, /* Output progressive pixels */ + JPEG_DECOMPRESS_SEQUENTIAL, /* Output sequential pixels */ + JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT, + JPEG_DONE, + JPEG_SINK_NON_JPEG_TRAILER, /* Some image files have a */ + /* non-JPEG trailer */ + JPEG_ERROR +} jstate; + +typedef struct { + struct jpeg_error_mgr pub; /* "public" fields for IJG library*/ + jmp_buf setjmp_buffer; /* For handling catastropic errors */ +} il_error_mgr; + +/* + * Structure used to manage the JPEG decoder stream. + */ +typedef struct jpeg_struct { + jstate state; /* Decoder FSM state */ + int pass_num; + int completed_output_passes; + + int rows_per_chunk; + void *timeout; + + /* One scanline's worth of post-processed sample data */ + JSAMPARRAY samples; + JSAMPARRAY samples3; + /* IJG JPEG library decompressor state */ + struct jpeg_decompress_struct jd; + il_error_mgr jerr; + il_container *ic; +} jpeg_struct; + + + + +/* 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 + */ +typedef struct { + /* public fields; must be first in this struct! */ + struct jpeg_source_mgr pub; + + jpeg_struct *js; /* pointer to netlib stream object */ + + int bytes_to_skip; /* remaining bytes to skip */ + + enum data_source_state state; + + JOCTET *netlib_buffer; /* next buffer for fill_input_buffer */ + PRUint32 netlib_buflen; + + /* + * 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 */ +} il_source_mgr; + + +/* Override the standard error method in the IJG JPEG decoder code. */ +void PR_CALLBACK +il_error_exit (j_common_ptr cinfo) +{ + int error_code; + il_error_mgr *err = (il_error_mgr *) cinfo->err; + +#ifdef DEBUG +#if 0 + /*ptn fix later */ + if (il_debug >= 1) { + char buffer[JMSG_LENGTH_MAX]; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + + ILTRACE(1,("%s\n", buffer)); + } +#endif +#endif + + /* Convert error to a browser error code */ + if (cinfo->err->msg_code == JERR_OUT_OF_MEMORY) + error_code = MK_OUT_OF_MEMORY; + else + error_code = MK_IMAGE_LOSSAGE; + + /* Return control to the setjmp point. */ + longjmp(err->setjmp_buffer, error_code); +} + + +static void PR_CALLBACK +init_source (j_decompress_ptr jd) +{ +} + +/*----------------------------------------------------------------------------- + * 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 + * multiple buffers in an attempt to avoid unnecessary copying of input data. + * + * (A simpler scheme is possible: It's much easier to use only a single + * buffer; when fill_input_buffer() is called, move any unconsumed data + * (beyond the current pointer/count) down to the beginning of this buffer and + * then load new data into the remaining buffer space. This approach requires + * a little more data copying but is far easier to get right.) + * + * At any one time, the JPEG decompressor is either reading from the netlib + * input buffer, which is volatile across top-level calls to the IJG library, + * or the "backtrack" buffer. The backtrack buffer contains the remaining + * unconsumed data from the netlib buffer after parsing was suspended due + * to insufficient data in some previous call to the IJG library. + * + * When suspending, the decompressor will back up to a convenient restart + * point (typically the start of the current MCU). The variables + * next_input_byte & bytes_in_buffer indicate where the restart point will be + * if the current call returns FALSE. Data beyond this point must be + * rescanned after resumption, so it must be preserved in case the decompressor + * decides to backtrack. + * + * Returns: + * TRUE if additional data is available, FALSE if no data present and + * the JPEG library should therefore suspend processing of input stream + *---------------------------------------------------------------------------*/ +static boolean PR_CALLBACK +fill_input_buffer (j_decompress_ptr jd) +{ + il_source_mgr *src = (il_source_mgr *)jd->src; + enum data_source_state src_state = src->state; + PRUint32 bytesToSkip, new_backtrack_buflen, new_buflen, roundup_buflen; + unsigned char *new_buffer; + + ILTRACE(5,("il:jpeg: fill, state=%d, nib=0x%x, bib=%d", src_state, + src->pub.next_input_byte, src->pub.bytes_in_buffer)); + + 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) { + j_common_ptr cinfo = (j_common_ptr)(&src->js->jd); + cinfo->err->msg_code = JERR_OUT_OF_MEMORY; + il_error_exit(cinfo); + } + + src->backtrack_buffer_size = (size_t)roundup_buflen; + + /* Check for malformed MARKER segment lengths. */ + if (new_backtrack_buflen > MAX_JPEG_MARKER_LENGTH) + il_error_exit((j_common_ptr)(&src->js->jd)); + } + + /* Copy remainder of netlib buffer into backtrack buffer. */ + nsCRT::memmove(src->backtrack_buffer + src->backtrack_buflen, + src->pub.next_input_byte, + src->pub.bytes_in_buffer); + + /* Point to start of data to be rescanned. */ + src->pub.next_input_byte = src->backtrack_buffer + + src->backtrack_buflen - src->backtrack_num_unread_bytes; + src->pub.bytes_in_buffer += src->backtrack_num_unread_bytes; + src->backtrack_buflen = (size_t)new_backtrack_buflen; + + src->state = dss_consuming_backtrack_buffer; + goto suspend; + + default: + PR_ASSERT(0); + return FALSE; + } + + suspend: + ILTRACE(5,(" Suspending, bib=%d", src->pub.bytes_in_buffer)); + return FALSE; +} + +static void PR_CALLBACK +skip_input_data (j_decompress_ptr jd, long num_bytes) +{ + il_source_mgr *src = (il_source_mgr *)jd->src; + +#ifdef DEBUG + 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->bytes_to_skip = (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; + } +} + + +/* + * Terminate source --- called by jpeg_finish_decompress() after all + * data has been read to clean up JPEG source manager. + */ +static void PR_CALLBACK +term_source (j_decompress_ptr jd) +{ + /* No work necessary here */ +} + + +/*----------------------------------------------------------------------------- + * Setup a JPEG source object for streaming data in a demand-driven + * fashion into the IJG JPEG decompression library. A JPEG source + * object consists of a set of callback functions which the + * decompressor library calls when it needs more data or to seek ahead + * in the input stream. + * + * Returns: + * TRUE if setup succeeds, FALSE otherwise. + *---------------------------------------------------------------------------*/ +PRBool +setup_jpeg_src (j_decompress_ptr jd, jpeg_struct *js) +{ + il_source_mgr *src; + + if (jd->src == NULL) { + src = PR_NEWZAP(il_source_mgr); + if (!src) { + ILTRACE(1,("il:jpeg: src manager memory lossage")); + return PR_FALSE; + } + jd->src = (struct jpeg_source_mgr *) src; + } + + src = (il_source_mgr *)jd->src; + src->js = js; + + /* Setup callback functions. */ + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; + src->pub.term_source = term_source; + + return PR_TRUE; +} + + + +/* + * Macros for fetching data from the data source module. + * + * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect + * the current restart point; we update them only when we have reached a + * suitable place to restart if a suspension occurs. + */ + +/* Declare and initialize local copies of input pointer/count */ +#define INPUT_VARS(cinfo) \ + struct jpeg_source_mgr * datasrc = (cinfo)->src; \ + const JOCTET * next_input_byte = datasrc->next_input_byte; \ + size_t bytes_in_buffer = datasrc->bytes_in_buffer + +/* Unload the local copies --- do this only at a restart boundary */ +#define INPUT_SYNC(cinfo) \ + ( datasrc->next_input_byte = next_input_byte, \ + datasrc->bytes_in_buffer = bytes_in_buffer ) + +/* Reload the local copies --- seldom used except in MAKE_BYTE_AVAIL */ +#define INPUT_RELOAD(cinfo) \ + ( next_input_byte = datasrc->next_input_byte, \ + bytes_in_buffer = datasrc->bytes_in_buffer ) + +/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. + * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + * but we must reload the local copies after a successful fill. + */ +#define MAKE_BYTE_AVAIL(cinfo,action) \ + if (bytes_in_buffer == 0) { \ + if (! (*datasrc->fill_input_buffer) (cinfo)) \ + { action; } \ + INPUT_RELOAD(cinfo); \ + } \ + bytes_in_buffer-- + +/* Read a byte into variable V. + * If must suspend, take the specified action (typically "return FALSE"). + */ +#define INPUT_BYTE(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + V = GETJOCTET(*next_input_byte++); ) + +/* As above, but read two bytes interpreted as an unsigned 16-bit integer. + * V should be declared unsigned int or perhaps INT32. + */ +#define INPUT_2BYTES(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ + MAKE_BYTE_AVAIL(cinfo,action); \ + V += GETJOCTET(*next_input_byte++); ) + + +/* Process the COM marker segment, which contains human-readable comments. */ +boolean PR_CALLBACK +il_jpeg_COM_handler (j_decompress_ptr cinfo) +{ + PRUintn length; + char *comment; + unsigned int ch; + + il_source_mgr *src = (il_source_mgr*) cinfo->src; + il_container *ic = src->js->ic; + static unsigned int lastch = 0; + + INPUT_VARS(cinfo); + + /* Get 16-bit comment length word. */ + INPUT_2BYTES(cinfo, length, return FALSE); + if (length < 2) { + cinfo->err->msg_code = JERR_BAD_LENGTH; + il_error_exit((j_common_ptr)cinfo); + } + length -= 2; /* discount the length word itself */ + + PR_FREEIF(ic->comment); + comment = ic->comment = (char *)PR_MALLOC(length + 1); + ic->comment_length = length; + + if (!ic->comment) { + skip_input_data(cinfo, length + 2); + return TRUE; + } + + /* Emit the character in a readable form. + * Newlines in CR, CR/LF, or LF form will be printed as one newline. + */ + while (length-- > 0) { + INPUT_BYTE(cinfo, ch, return FALSE); + + if (ch == '\r') { + *comment++ = '\n'; + } else if (ch == '\n') { + if (lastch != '\r') + *comment++ = '\n'; + } else if (isprint(ch) || !ch) { + *comment++ = ch; + } + lastch = ch; + } + + *comment = 0; + + INPUT_SYNC(cinfo); + + return TRUE; +} + +PRBool +il_jpeg_init(il_container *ic) +{ + jpeg_struct *js; + j_decompress_ptr jd; + NI_ColorSpace *src_color_space = ic->src_header->color_space; + NI_RGBBits *rgb = &src_color_space->bit_alloc.rgb; + + js = PR_NEWZAP(jpeg_struct); + if (!js) { + ILTRACE(1,("il:jpeg: jpeg_struct memory lossage")); + return PR_FALSE; + } + + /* Init jpeg_struct */ + ic->ds = js; + js->state = JPEG_HEADER; + js->samples = NULL; + js->samples3 = NULL; + js->ic = ic; + + jd = &js->jd; + + /* Install our error handler because the default is to exit(). */ + jd->err = jpeg_std_error(&js->jerr.pub); + js->jerr.pub.error_exit = il_error_exit; + + /* Control returns here if an error occurs before setup completes. */ + if(setjmp(js->jerr.setjmp_buffer)) { + /* Free up all the data structures */ + il_jpeg_abort(ic); + return PR_FALSE; + } + +#ifdef DEBUG +#if 0 + if (il_debug > 20) { + jd->err->trace_level = 99; + } +#endif +#endif + jpeg_create_decompress(jd); + + /* Setup jpeg data source object */ + if (!setup_jpeg_src(jd, js)) { + ILTRACE(1,("il:jpeg: jpeg source memory lossage")); + /* Free up all the data structures */ + il_jpeg_abort(ic); + return PR_FALSE; + } + + /* Insert custom COM comment marker processor. */ + jpeg_set_marker_processor(jd, JPEG_COM, il_jpeg_COM_handler); + + + /* Initialize the container's source image header. */ + src_color_space->type = NI_TrueColor; + src_color_space->pixmap_depth = 24; + rgb->red_bits = 8; + rgb->red_shift = 16; + rgb->green_bits = 8; + rgb->green_shift = 8; + rgb->blue_bits = 8; + rgb->blue_shift = 0; + + return PR_TRUE; +} + + +/*----------------------------------------------------------------------------- + * Calling this routine sends scanlines to the front-end for display. + * Scanlines will be emitted until the entire scan has been displayed or + * until insufficient input data is available to continue output. + * + * The maximum number of scanlines to be output is controlled by the + * `num_scanlines' parameter. Set num_scanlines to -1 to output scanlines + * until input data is exhausted. + * + * Returns: + * TRUE if output was discontinued due to lack of input data + * FALSE, otherwise + *---------------------------------------------------------------------------*/ +int +output_jpeg_scanlines(il_container *ic, int num_scanlines) +{ + jpeg_struct *js = (jpeg_struct *)ic->ds; + j_decompress_ptr jd = &js->jd; + int input_exhausted; + int pass; + +#ifdef DEBUG + PRUintn start_scanline = jd->output_scanline; +#endif + + if (js->state == JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT) + pass = IL_FINAL_PASS; + else + pass = js->completed_output_passes + 1; + + while ((jd->output_scanline < jd->output_height) && num_scanlines--) { + JSAMPROW samples; + + /* Request one scanline. Returns 0 or 1 scanlines. */ + int ns = jpeg_read_scanlines(jd, js->samples, 1); + ILTRACE(15,("il:jpeg: scanline %d, ns = %d", + jd->output_scanline, ns)); + if (ns != 1) { + ILTRACE(5,("il:jpeg: suspending scanline")); + input_exhausted = TRUE; + goto done; + } + + /* If grayscale image ... */ + if (jd->output_components == 1) { + JSAMPLE j, *j1, *j1end, *j3; + + /* Convert from grayscale to RGB. */ + j1 = js->samples[0]; + j1end = j1 + jd->output_width; + j3 = js->samples3[0]; + while (j1 < j1end) { + j = *j1++; + j3[0] = j; + j3[1] = j; + j3[2] = j; + j3 += 3; + } + samples = js->samples3[0]; + } else { /* 24-bit color image */ + samples = js->samples[0]; + } + + ic->imgdcb->ImgDCBHaveRow( 0, samples, 0, jd->output_width, jd->output_scanline-1, + 1, ilErase, pass); + } + + input_exhausted = FALSE; + + done: + +#ifdef DEBUG + if (start_scanline != jd->output_scanline) + ILTRACE(4, ("il: jpeg: Input pass=%2d, next input scanline=%3d," + " emitted %3d - %3d\n", + jd->input_scan_number, jd->input_iMCU_row * 16, + start_scanline, jd->output_scanline - 1)); + +#endif + + return input_exhausted; +} + +#define JPEG_OUTPUT_CHUNK_SIZE 150000 + +/* Timeout durations, in milliseconds */ + +/* Delay between displaying chunks of pixels for the first scan. */ +#define JPEG_TIMEOUT_INITIAL_DELAY 32 + +/* Delay between displaying chunks of pixels for subsequent scans */ +#define JPEG_TIMEOUT_DELAY 250 + +static void +jpeg_timeout_callback(void *closure) +{ + PRUint32 delay; + jpeg_struct *js = (jpeg_struct *)closure; + j_decompress_ptr jd = &js->jd; + + if (jd->input_scan_number == 1) + delay = JPEG_TIMEOUT_INITIAL_DELAY; + else + delay = JPEG_TIMEOUT_DELAY; + + /* + * Perform incremental display of progressive scans, + * except don't display unless enough time has elapsed + * since the previous scan was displayed. + */ + + if (js->pass_num != js->completed_output_passes + 1) { + if (! jpeg_start_output(jd, jd->input_scan_number)) { + ILTRACE(1, ("il: jpeg: jpeg_start_output returned" + "FALSE!\n")); + goto done; + } + js->pass_num = js->completed_output_passes + 1; + } + + js->timeout = NULL; + + /* If there's no more data to process for this scan, + wait until jpeg_write() wakes us up by scheduling a + new timeout */ + if (output_jpeg_scanlines(js->ic, js->rows_per_chunk)) + return; + + /* If we're at the end of this progressive scan ... */ + if (jd->output_scanline == jd->output_height) { + if (jpeg_finish_output(jd)) + js->completed_output_passes++; + } + + done: + js->timeout = js->ic->imgdcb->ImgDCBSetTimeout(jpeg_timeout_callback, js, delay); +} + +/* + * Force the display of scans, even if no data has entered the netlib + * buffer since jpeg_timeout_callback() was run. This will flush + * pixels to the screen during a long pause in a bursty data source. + */ +#if 0 +static void +jpeg_idle_callback(void *closure) +{ + il_container *ic = (il_container *)closure; + il_jpeg_write(ic, NULL, 0); +} +#endif + +int +il_jpeg_write(il_container *ic, const unsigned char *buf, int32 len) +{ + int row_stride, status; + int input_exhausted; + int error_code; + + jpeg_struct *js = (jpeg_struct *)ic->ds; + + + + /* If this js == NULL, chances are the netlib + continued to send data after the image stream was closed. */ + if (!js) { +#ifdef DEBUG + ILTRACE(1,("Netlib sent data after the image stream was closed\n")); +#endif + return MK_IMAGE_LOSSAGE; + } + + j_decompress_ptr jd = &js->jd; + il_source_mgr *src = (il_source_mgr*) js->jd.src; + NI_PixmapHeader *img_header = &ic->image->header; +#ifndef M12N /* XXXM12N Get rid of this */ + NI_PixmapHeader *src_header = ic->src_header; + NI_ColorMap *cmap = &src_header->color_space->cmap; +#endif /* M12N */ + + /* Return here if there is a fatal error. */ + if ((error_code = setjmp(js->jerr.setjmp_buffer)) != 0) { + /* Free up all the data structures */ + il_jpeg_abort(ic); + return error_code; + } + + /* Register new buffer contents with data source manager. */ + src->netlib_buffer = (JOCTET*)buf; + src->netlib_buflen = (PRUint32)len; + + input_exhausted = 0; + while (! input_exhausted) { + ILTRACE(5,("il:jpeg: write, state=%d, buf=0x%x, len=%d", + js->state, buf, len)); + + switch (js->state) { + case JPEG_HEADER: + if (jpeg_read_header(jd, TRUE) != JPEG_SUSPENDED) { +#ifndef M12N /* XXXM12N Get rid of this */ + cmap->map = 0; + cmap->num_colors = ic->cs->default_map_size; +#endif /* M12N */ + ic->src_header->width = jd->image_width; + ic->src_header->height = jd->image_height; + if ((status = ic->imgdcb->ImgDCBImageSize()) != 0) { + ILTRACE(1,("il:jpeg: MEM il_size")); + return status; + } + + ic->imgdcb->ImgDCBSetupColorspaceConverter(); /* XXXM12N Should check + return code. */ + if(!img_header->widthBytes) + return JPEG_ERROR; + else + js->rows_per_chunk = + JPEG_OUTPUT_CHUNK_SIZE / img_header->widthBytes; + + /* FIXME -- Should reset dct_method and dither mode + * for final pass of progressive JPEG + */ + jd->dct_method = JDCT_FASTEST; + jd->dither_mode = JDITHER_ORDERED; + jd->do_fancy_upsampling = FALSE; + jd->enable_2pass_quant = FALSE; + jd->do_block_smoothing = TRUE; + + /* + * Don't allocate a giant and superfluous memory buffer + * when the image is a sequential JPEG. + */ + jd->buffered_image = jpeg_has_multiple_scans(jd); + + /* Used to set up image size so arrays can be allocated */ + jpeg_calc_output_dimensions(jd); + + /* + * Make a one-row-high sample array that will go away + * when done with image. Always make it big enough to + * hold an RGB row. Since this uses the IJG memory + * manager, it must be allocated before the call to + * jpeg_start_compress(). + */ + row_stride = jd->output_width * jd->output_components; + js->samples = (*jd->mem->alloc_sarray)((j_common_ptr) jd, + JPOOL_IMAGE, + row_stride, 1); + + /* Allocate RGB buffer for conversion from greyscale. */ + if (jd->output_components != 3) { + row_stride = jd->output_width * 3; + js->samples3 = (*jd->mem->alloc_sarray)((j_common_ptr) jd, + JPOOL_IMAGE, + row_stride, 1); + } + js->state = JPEG_START_DECOMPRESS; + + } else { + ILTRACE(5,("il:jpeg: suspending header")); + input_exhausted = TRUE; + } + break; + + case JPEG_START_DECOMPRESS: + if (jpeg_start_decompress(jd)) { + + /* If this is a progressive JPEG ... */ + if (jd->buffered_image) { + js->state = JPEG_DECOMPRESS_PROGRESSIVE; + } else { + js->state = JPEG_DECOMPRESS_SEQUENTIAL; + } + } + + break; + + case JPEG_DECOMPRESS_SEQUENTIAL: + input_exhausted = output_jpeg_scanlines(ic, -1); + + /* If we've completed image output ... */ + if (jd->output_scanline == jd->output_height) + js->state = JPEG_DONE; + + break; + + case JPEG_DECOMPRESS_PROGRESSIVE: + + /* + * Set a timeout to trigger display of the next progressive scan. + * Any scans which arrive in the intervening time will be displayed + * instead. Thus, the decoder adapts to the data arrival rate. + */ + if (js->timeout == NULL) { + PRUint32 delay; + + /* + * First time around, display the scan a little + * quicker than in subsequent scans. + */ + if (jd->input_scan_number == 1) + delay = JPEG_TIMEOUT_INITIAL_DELAY; + else { + delay = JPEG_TIMEOUT_DELAY; + } + + js->timeout = ic->imgdcb->ImgDCBSetTimeout(jpeg_timeout_callback, js, delay); + + } + + /* Eat all the available input data in the netlib buffer. */ + do { + status = jpeg_consume_input(jd); + } while (!((status == JPEG_SUSPENDED) || + (status == JPEG_REACHED_EOI))); + + /* If we've parsed the whole input, do final display immediately. */ + if (status == JPEG_REACHED_EOI) { + js->state = JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT; + break; + } + + input_exhausted = TRUE; + + break; + + case JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT: + + if ((jd->input_scan_number == jd->output_scan_number) && + (js->pass_num == js->completed_output_passes + 1)) { + output_jpeg_scanlines(ic, -1); + jpeg_finish_output(jd); + } else { + + /* Abort the last output scan. + * We need to redraw the whole image. + */ + if (js->pass_num == js->completed_output_passes + 1) + jpeg_finish_output(jd); + + jpeg_start_output(jd, jd->input_scan_number); + output_jpeg_scanlines(ic, -1); + jpeg_finish_output(jd); + } + + js->state = JPEG_DONE; + + /* Fall through ... */ + + case JPEG_DONE: + status = jpeg_finish_decompress(jd); + + /* Clear any pending timeouts */ + if (js->timeout) { + ic->imgdcb->ImgDCBClearTimeout(js->timeout); + js->timeout = NULL; + } + + input_exhausted = TRUE; + js->state = JPEG_SINK_NON_JPEG_TRAILER; /* Be prepared for */ + /* non-JPEG data after */ + /* EOI marker. */ + break; + + case JPEG_SINK_NON_JPEG_TRAILER: /* Ignore non-JPEG trailer, if any */ + input_exhausted = TRUE; + break; + + default: + PR_ASSERT(0); + break; + } + } + + return 0; +} + +void +il_jpeg_abort(il_container *ic) +{ + jpeg_struct *js = (jpeg_struct *)ic->ds; + + if (js) { + il_source_mgr *src = (il_source_mgr*) js->jd.src; + + /* + * Free up the memory that we allocated ourselves (not memory we + * allocated using the IJG memory manager - it will be freed in + * a moment.) + */ + if (src) { + if (src->backtrack_buffer) { + PR_FREEIF(src->backtrack_buffer); + src->backtrack_buffer = NULL; + } + PR_FREEIF(src); + js->jd.src = NULL; + } + + /* Clear any pending timeouts */ + if (js->timeout) { + ic->imgdcb->ImgDCBClearTimeout(js->timeout); + js->timeout = NULL; + } + + /* + * Free all the ancillary memory used during JPEG decoding by the + * IJG JPEG library. This has the side effect of freeing up js->samples + * and js->samples3 which were allocated using the IJG memory manager. + */ + jpeg_destroy_decompress(&js->jd); + js->samples = NULL; + js->samples3 = NULL; + + /* Finally, free up our private decoder structure. */ + PR_FREEIF(js); + ic->ds = NULL; + } +} + +void +il_jpeg_complete(il_container *ic) +{ + il_jpeg_abort(ic); + ic->imgdcb->ImgDCBHaveImageAll(); +} + +#ifdef PROFILE +# pragma profile off +#endif + diff --git a/modules/libimg/jpgcom/jpeg.h b/modules/libimg/jpgcom/jpeg.h new file mode 100644 index 000000000000..3829206af253 --- /dev/null +++ b/modules/libimg/jpgcom/jpeg.h @@ -0,0 +1,34 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + + + +/* jpeg.h */ + + +extern int il_jpeg_init(il_container *ic); +extern int il_jpeg_write(il_container *, const PRUint8 *, int32); +extern void il_jpeg_complete(il_container *ic); +//extern unsigned int il_jpeg_write_ready(il_container *ic); +extern void il_jpeg_abort(il_container *ic); + + diff --git a/modules/libimg/jpgcom/makefile.win b/modules/libimg/jpgcom/makefile.win new file mode 100644 index 000000000000..36a5278a208b --- /dev/null +++ b/modules/libimg/jpgcom/makefile.win @@ -0,0 +1,102 @@ +#!gmake +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): + + +# + +#------------------------------------------------------------------------ +# +# Makefile to build the IMGLIB LIB +# +#------------------------------------------------------------------------ + +!ifdef MOZ_JAVA +LOCAL_JMC_SUBDIR = . +!endif + + +LIBRARY_NAME = nsjpg + +# +# Make sure we have MOZILLA_CLIENT defined so we get the +# proper JS includes +# +LCFLAGS = $(LCFLAGS) -DMOZILLA_CLIENT + +!ifdef BUILD_DEBUG_GC +LCFLAGS = $(LCFLAGS) -DDEBUG_GC +!endif + +LCFLAGS = $(LCFLAGS) /TP + +LLIBS= $(LIBNSPR) \ + $(DIST)\lib\util.lib \ + $(DIST)\lib\jpeg3250.lib \ + $(DIST)\lib\xpcom.lib \ +!ifdef NU_CACHE + $(DIST)\lib\cache.lib \ +!endif + $(NULL) + +LIBRARY= .\$(OBJDIR)\$(LIBNAME).lib +LIBRARY_SUFFIX = $(MOZ_BITS)$(VERSION_NUMBER) + +MAKE_OBJ_TYPE=DLL +#//------------------------------------------------------------------------ +#// +#// Define any Public Make Variables here: (ie. PDFFILE, MAPFILE, ...) +#// +#//------------------------------------------------------------------------ +DLLNAME=nsjpg +DLL1NAME=nsjpg +PDBFILE=$(DLLNAME).pdb +MAPFILE=$(DLLNAME).map +DEFFILE=nsjpg.def + + +#//------------------------------------------------------------------------ +#// +#// Define any Public Targets here (ie. PROGRAM, LIBRARY, DLL, ...) +#// (these must be defined before the common makefiles are included) +#// +#//------------------------------------------------------------------------ +DLL=.\$(OBJDIR)\$(DLLNAME).dll +MAPFILE= $(DLLNAME).map + + + +MODULE=img +DEPTH=..\..\.. + +LINCS=-I$(DEPTH)/dist/public/xpcom -I. -I$(DEPTH)/dist/public/raptor -I$(DEPTH)/dist/public/jpeg +CPPSRCS= nsJPGDecoder.cpp nsJPGModule.cpp jpeg.cpp +CPP_OBJS= \ + .\$(OBJDIR)\nsJPGDecoder.obj \ + .\$(OBJDIR)\nsJPGModule.obj \ + .\$(OBJDIR)\jpeg.obj \ + $(NULL) + +include <$(DEPTH)\config\rules.mak> + +install:: $(DLL) + $(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin\components + $(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib + diff --git a/modules/libimg/jpgcom/nsJPGDecoder.cpp b/modules/libimg/jpgcom/nsJPGDecoder.cpp new file mode 100644 index 000000000000..52d978acc76c --- /dev/null +++ b/modules/libimg/jpgcom/nsJPGDecoder.cpp @@ -0,0 +1,131 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +/* -*- Mode: C; tab-width: 4 -*- + * nsJPGDecoder.cpp --- interface to JPG decoder + */ + + +#include "nsCOMPtr.h" +#include "nsJPGDecoder.h" +#include "jpeg.h" + + +////////////////////////////////////////////////////////////////////// +// JPG Decoder Implementation + +NS_IMPL_ISUPPORTS1(JPGDecoder, nsIImgDecoder); + +JPGDecoder::JPGDecoder(il_container* aContainer) +{ + NS_INIT_REFCNT(); + ilContainer = aContainer; +} + +JPGDecoder::~JPGDecoder(void) +{ +} + + +NS_METHOD +JPGDecoder::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) +{ + nsresult rv; + if (aOuter) return NS_ERROR_NO_AGGREGATION; + + il_container *ic = new il_container(); + if (!ic) return NS_ERROR_OUT_OF_MEMORY; + + JPGDecoder *decoder = new JPGDecoder(ic); + if (!decoder) { + delete ic; + return NS_ERROR_OUT_OF_MEMORY; + } + + NS_ADDREF(decoder); + rv = decoder->QueryInterface(aIID, aResult); + NS_RELEASE(decoder); + + /* why are we creating and destroying this object for no reason? */ + delete ic; /* is a place holder */ + + return rv; +} + +/*------------------------------------------------------*/ +/* api functions + */ +/*------------------------------------------------------*/ +NS_IMETHODIMP +JPGDecoder::ImgDInit() +{ + int ret; + + if( ilContainer != NULL ) { + ret = il_jpeg_init(ilContainer); + if(ret != 1) + return NS_ERROR_FAILURE; + } + return NS_OK; +} + + +NS_IMETHODIMP +JPGDecoder::ImgDWriteReady(PRUint32 *max_read) +{ + /* dummy return needed */ + *max_read = 2048; + return NS_OK; +} + +NS_IMETHODIMP +JPGDecoder::ImgDWrite(const unsigned char *buf, int32 len) +{ + int ret; + + if( ilContainer != NULL ) { + ret = il_jpeg_write(ilContainer, buf,len); + if(ret != 0) + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +NS_IMETHODIMP +JPGDecoder::ImgDComplete() +{ + if( ilContainer != NULL ) { + il_jpeg_complete(ilContainer); + } + return NS_OK; +} + +NS_IMETHODIMP +JPGDecoder::ImgDAbort() +{ + if( ilContainer != NULL ) { + il_jpeg_abort(ilContainer); + } + return NS_OK; + +} + diff --git a/modules/libimg/jpgcom/nsJPGDecoder.h b/modules/libimg/jpgcom/nsJPGDecoder.h new file mode 100644 index 000000000000..da8a0ced0181 --- /dev/null +++ b/modules/libimg/jpgcom/nsJPGDecoder.h @@ -0,0 +1,58 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ +#ifndef nsJPGDecoder_h___ +#define nsJPGDecoder_h___ + +#include "nsIImgDecoder.h" + +/* 1b0e6b90-d68a-11d2-802e-0060088f91a3 */ +#define NS_JPGDECODER_CID \ +{ 0x1b0e6b90, 0xd68a, 0x11d2, \ +{ 0x80, 0x2c, 0x00, 0x60, 0x08, 0x8f, 0x91, 0xa3 } } + +class JPGDecoder : public nsIImgDecoder +{ +public: + JPGDecoder(il_container* aContainer); + virtual ~JPGDecoder(); + + NS_DECL_ISUPPORTS + + static NS_METHOD Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); + + /* stream */ + NS_IMETHOD ImgDInit(); + + NS_IMETHOD ImgDWriteReady(PRUint32 *max_read); + NS_IMETHOD ImgDWrite(const unsigned char *buf, int32 len); + NS_IMETHOD ImgDComplete(); + NS_IMETHOD ImgDAbort(); + + NS_IMETHOD_(il_container *) SetContainer(il_container *ic){ilContainer = ic; return ic;} + NS_IMETHOD_(il_container *) GetContainer() {return ilContainer;} + + +private: + il_container* ilContainer; +}; + +#endif /* nsJPGDecoder_h___ */ diff --git a/modules/libimg/jpgcom/nsJPGModule.cpp b/modules/libimg/jpgcom/nsJPGModule.cpp new file mode 100644 index 000000000000..db9c86047f0c --- /dev/null +++ b/modules/libimg/jpgcom/nsJPGModule.cpp @@ -0,0 +1,40 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Pierre Phaneuf + */ + +#include "nsJPGDecoder.h" +#include "nsIComponentManager.h" +#include "nsIGenericFactory.h" +#include "nsISupports.h" +#include "nsCOMPtr.h" + +static NS_DEFINE_CID(kJPGDecoderCID, NS_JPGDECODER_CID); + +static nsModuleComponentInfo components[] = +{ + { "JPEG Decoder", + NS_JPGDECODER_CID, + "@mozilla.org/image/decoder;1?type=image/jpeg", + JPGDecoder::Create } +}; + +NS_IMPL_NSGETMODULE(nsJPGModule, components) diff --git a/modules/libimg/jpgcom/nsJPGModule.h b/modules/libimg/jpgcom/nsJPGModule.h new file mode 100644 index 000000000000..2b14d4cf82c1 --- /dev/null +++ b/modules/libimg/jpgcom/nsJPGModule.h @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ +#ifndef nsJPGModule_h___ +#define nsJPGModule_h___ + +#include "nsIModule.h" + +class nsJPGModule : public nsIModule +{ +public: + NS_DECL_ISUPPORTS + + // Construction, Init and desstruction + nsJPGModule(); + virtual ~nsJPGModule(); + + // nsIModule Interfaces + NS_DECL_NSIMODULE + + // Facility for counting object instances + int IncrementObjCount() { if (mObjCount == -1) mObjCount = 0; return ++mObjCount; } + int DecrementObjCount() { if (mObjCount == -1) mObjCount = 0; return --mObjCount; } + int GetObjCount() { return mObjCount; } + +private: + int mObjCount; + nsISupports* mClassObject; +}; + +#endif /* nsJPGModule_h___ */ diff --git a/modules/libimg/jpgcom/nsjpg.def b/modules/libimg/jpgcom/nsjpg.def new file mode 100644 index 000000000000..ef91c571177b --- /dev/null +++ b/modules/libimg/jpgcom/nsjpg.def @@ -0,0 +1,14 @@ +; +; temp def file for nsjpg dll +; + +LIBRARY nsjpg.dll +DESCRIPTION 'test dll' + +EXPORTS + ImgDInit @1002 PRIVATE + ImgDWrite @1003 PRIVATE + ImgDWriteReady @1004 PRIVATE + ImgDComplete @1005 PRIVATE + ImgDAbort @1006 PRIVATE + diff --git a/modules/libimg/jpgcom/win32.order b/modules/libimg/jpgcom/win32.order new file mode 100644 index 000000000000..9361a07086a2 --- /dev/null +++ b/modules/libimg/jpgcom/win32.order @@ -0,0 +1,24 @@ +?fill_input_buffer@@YAEPAUjpeg_decompress_struct@@@Z ; 53 +?ImgDWrite@JPGDecoder@@UAGIPBEJ@Z ; 45 +?il_jpeg_write@@YAHPAUil_container_struct@@PBEJ@Z ; 45 +?ImgDWriteReady@JPGDecoder@@UAGIPAI@Z ; 44 +?output_jpeg_scanlines@@YAHPAUil_container_struct@@H@Z ; 4 +?init_source@@YAXPAUjpeg_decompress_struct@@@Z ; 2 +?AddRef@JPGDecoder@@UAGKXZ ; 2 +?Release@JPGDecoder@@UAGKXZ ; 2 +?skip_input_data@@YAXPAUjpeg_decompress_struct@@J@Z ; 2 +?SetContainer@JPGDecoder@@UAGPAUil_container_struct@@PAU2@@Z ; 2 +?il_jpeg_abort@@YAXPAUil_container_struct@@@Z ; 2 +_NSGetModule ; 1 +?il_jpeg_COM_handler@@YAEPAUjpeg_decompress_struct@@@Z ; 1 +?il_jpeg_init@@YAHPAUil_container_struct@@@Z ; 1 +?setup_jpeg_src@@YAHPAUjpeg_decompress_struct@@PAUjpeg_struct@@@Z ; 1 +?ImgDInit@JPGDecoder@@UAGIXZ ; 1 +?QueryInterface@JPGDecoder@@UAGIABUnsID@@PAPAX@Z ; 1 +??_GJPGDecoder@@UAEPAXI@Z ; 1 +??0JPGDecoder@@QAE@PAUil_container_struct@@@Z ; 1 +?Create@JPGDecoder@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 1 +??1JPGDecoder@@UAE@XZ ; 1 +?ImgDAbort@JPGDecoder@@UAGIXZ ; 1 +?ImgDComplete@JPGDecoder@@UAGIXZ ; 1 +?il_jpeg_complete@@YAXPAUil_container_struct@@@Z ; 1 diff --git a/modules/libimg/public/.cvsignore b/modules/libimg/public/.cvsignore new file mode 100644 index 000000000000..f3c7a7c5da68 --- /dev/null +++ b/modules/libimg/public/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/modules/libimg/public/MANIFEST b/modules/libimg/public/MANIFEST new file mode 100644 index 000000000000..26680984d116 --- /dev/null +++ b/modules/libimg/public/MANIFEST @@ -0,0 +1,18 @@ +# +# This is a list of local files which get copied to the mozilla:dist:libimg directory +# + +dummy_nc.h +ilErrors.h +ilIImageRenderer.h +ilINetContext.h +ilINetReader.h +ilISystemServices.h +ilIURL.h +il_icons.h +il_strm.h +il_types.h +il_util.h +libimg.h +ni_pixmp.h +xpcompat.h diff --git a/modules/libimg/public/Makefile.in b/modules/libimg/public/Makefile.in new file mode 100644 index 000000000000..2dcc6ba0ba36 --- /dev/null +++ b/modules/libimg/public/Makefile.in @@ -0,0 +1,55 @@ +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = img + +EXPORTS = \ + il_types.h \ + ni_pixmp.h \ + libimg.h \ + il_icons.h \ + il_strm.h \ + il_util.h \ + ilINetContext.h \ + ilIURL.h \ + ilINetReader.h \ + ilIImageRenderer.h \ + ilISystemServices.h \ + dummy_nc.h \ + xpcompat.h \ + ilErrors.h \ + $(NULL) + +EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS)) + +ifndef MOZ_JAVA +LOCAL_JMC_SUBDIR = . +endif + +include $(topsrcdir)/config/rules.mk + diff --git a/modules/libimg/public/xpcompat.h b/modules/libimg/public/xpcompat.h new file mode 100644 index 000000000000..2a14d879c57f --- /dev/null +++ b/modules/libimg/public/xpcompat.h @@ -0,0 +1,103 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +/* + * The purpose of this file is to help phase out XP_ library + * from the image library. In general, XP_ data structures and + * functions will be replaced with the PR_ or PL_ equivalents. + * In cases where the PR_ or PL_ equivalents don't yet exist, + * this file (and its source equivalent) will play the role + * of the XP_ library. + */ + +#ifndef xpcompat_h___ +#define xpcompat_h___ + +#include "xp_core.h" +#include "prtypes.h" +#include "nsCom.h" + + +#define XP_HUGE +#define XP_HUGE_ALLOC(SIZE) malloc(SIZE) +#define XP_HUGE_FREE(SIZE) free(SIZE) +#define XP_HUGE_MEMCPY(DEST, SOURCE, LEN) memcpy(DEST, SOURCE, LEN) + + +#define XP_HUGE_CHAR_PTR char XP_HUGE * + + +typedef void +(*TimeoutCallbackFunction) (void * closure); + + +PR_BEGIN_EXTERN_C + +/* + * XP_GetString is a mechanism for getting localized strings from a + * resource file. It needs to be replaced with a PR_ equivalent. + */ +extern char *XP_GetString(int i); + +/* + * I don't know if qsort will ever be in NSPR, so this might have + * to stay here indefinitely. Mac is completely broken and should use + * mozilla/include/xp_qsort.h, mozilla/lib/xp/xp_qsort.c. + */ +#if defined(XP_MAC_NEVER) +extern void XP_QSORT(void *, size_t, size_t, + int (*)(const void *, const void *)); +#endif /* XP_MAC */ + + +NS_EXPORT void* IL_SetTimeout(TimeoutCallbackFunction func, void * closure, PRUint32 msecs); + +NS_EXPORT void IL_ClearTimeout(void *timer_id); + +#define MK_UNABLE_TO_LOCATE_FILE -1 +#define MK_OUT_OF_MEMORY -2 + +#define XP_MSG_IMAGE_PIXELS -7 +#define XP_MSG_IMAGE_NOT_FOUND -8 +#define XP_MSG_XBIT_COLOR -9 +#define XP_MSG_1BIT_MONO -10 +#define XP_MSG_XBIT_GREYSCALE -11 +#define XP_MSG_XBIT_RGB -12 +#define XP_MSG_DECODED_SIZE -13 +#define XP_MSG_WIDTH_HEIGHT -14 +#define XP_MSG_SCALED_FROM -15 +#define XP_MSG_IMAGE_DIM -16 +#define XP_MSG_COLOR -17 +#define XP_MSG_NB_COLORS -18 +#define XP_MSG_NONE -19 +#define XP_MSG_COLORMAP -20 +#define XP_MSG_BCKDRP_VISIBLE -21 +#define XP_MSG_SOLID_BKGND -22 +#define XP_MSG_JUST_NO -23 +#define XP_MSG_TRANSPARENCY -24 +#define XP_MSG_COMMENT -25 +#define XP_MSG_UNKNOWN -26 +#define XP_MSG_COMPRESS_REMOVE -27 + +PR_END_EXTERN_C + +#endif diff --git a/modules/libimg/public_com/.cvsignore b/modules/libimg/public_com/.cvsignore new file mode 100644 index 000000000000..f3c7a7c5da68 --- /dev/null +++ b/modules/libimg/public_com/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/modules/libimg/public_com/MANIFEST b/modules/libimg/public_com/MANIFEST new file mode 100644 index 000000000000..937d93f92221 --- /dev/null +++ b/modules/libimg/public_com/MANIFEST @@ -0,0 +1,10 @@ +# +# This is a list of local files which get copied to the mozilla:dist:libimg directory +# + +if_struct.h +il.h +il_utilp.h +nsIImgDecoder.h +nsImgDCallbk.h +nsIImgDCallbk.h diff --git a/modules/libimg/public_com/Makefile.in b/modules/libimg/public_com/Makefile.in new file mode 100644 index 000000000000..8790c7ed0090 --- /dev/null +++ b/modules/libimg/public_com/Makefile.in @@ -0,0 +1,48 @@ +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = img + +# XXX nsImgDCallbk.h should go into libimg/src instead of being here +EXPORTS = \ + il.h \ + if_struct.h \ + il_utilp.h \ + nsIImgDecoder.h \ + nsIImgDCallbk.h \ + nsImgDCallbk.h \ + $(NULL) + +EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS)) + +ifndef MOZ_JAVA +LOCAL_JMC_SUBDIR = . +endif + +include $(topsrcdir)/config/rules.mk + diff --git a/modules/libimg/public_com/if_struct.h b/modules/libimg/public_com/if_struct.h new file mode 100644 index 000000000000..e3f7159c681b --- /dev/null +++ b/modules/libimg/public_com/if_struct.h @@ -0,0 +1,344 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +/* if.h --- Top-level image library internal routines + * + * $Id: if_struct.h,v 1.19 2001/06/19 11:15:45 pavlov%netscape.com Exp $ + */ + +#ifndef _if_h +#ifndef _ifstruct_h +#define _ifstruct_h + +#define M12N + +#define IL_INTERNAL + +#include "prtypes.h" +#include "prlog.h" +#include "prmem.h" +#include "plstr.h" +#include "prtime.h" +#include "prlong.h" +#include "nsIPresContext.h" + +#include "nsIImgDecoder.h" + +typedef struct _IL_GroupContext IL_GroupContext; +typedef struct _IL_ImageReq IL_ImageReq; +typedef struct il_context_list il_context_list; +typedef struct il_container_list il_container_list; +typedef struct il_container_struct il_container; + +#include "il_icons.h" /* Image icons. */ +#include "libimg.h" /* Public API to Image Library. */ +#include "il_utilp.h" /* Private header for colormap/colorspaces. */ +#include "il_util.h" /* Public API for colormaps/colorspaces. */ +#include "ilINetContext.h" +#include "ilIURL.h" +#include "ilINetReader.h" +#include "ilIImageRenderer.h" + +#include "il.h" + +#ifdef XP_WIN +#define _USD 1 /* scanlines upside-down */ +#endif + +/* For debugging counts of loading, looping and aborted images, needed for + group observer notification. */ +/* #define DEBUG_GROUP_OBSERVER */ + +#define FREE_IF_NOT_NULL(x) do {if (x) {PR_FREEIF(x); (x) = NULL;}} while (0) + +#include "prtypes.h" /* for IS_LITTLE_ENDIAN / IS_BIG_ENDIAN */ + +/* The imagelib labels bits in a 32-bit word from 31 on the left to 0 on the right. + This macro performs the necessary conversion to make that definition work on + little-endian platforms */ +#if defined(IS_LITTLE_ENDIAN) +# define M32(bit) ((bit) ^ 0x18) +#elif defined(IS_BIG_ENDIAN) +# define M32(bit) (bit) +#else + ENDIANNESS UNKNOWN! +#endif + +/* Don't change these unless you know what you're doing or you will + break 16-bit binaries. */ +#define MAX_IMAGE_WIDTH 8000 +#define MAX_IMAGE_HEIGHT 8000 + +/* MAX and MIN are almost universal, but be paranoid and use our + definitions. */ +#ifdef MAX +#undef MAX +#endif +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +#ifdef MIN +#undef MIN +#endif +#define MIN(x, y) ((x) < (y) ? (x) : (y)) + +/* Last output pass of an image */ +#define IL_FINAL_PASS -1 + +/* Nature of the conversion from source image colorspace to target image + colorspace. */ +typedef enum _IL_ConversionType { + IL_TrueToTrue = 0x09, + IL_TrueToPseudo = 0x0a, + IL_TrueToGrey = 0x0c, + IL_PseudoToTrue = 0x11, + IL_PseudoToPseudo = 0x12, + IL_PseudoToGrey = 0x14, + IL_GreyToTrue = 0x21, + IL_GreyToPseudo = 0x22, + IL_GreyToGrey = 0x24 +} IL_ConversionType; + +typedef void (*il_converter)(il_container *ic, const PRUint8 *mask, + const PRUint8 *sp, int x_offset, + int num, void XP_HUGE *out); + +enum icstate { + IC_VIRGIN = 0x00, /* Newly-created container */ + IC_START = 0x01, /* Requested stream from netlib, but no data yet */ + IC_STREAM = 0x02, /* Stream opened, but insufficient data + received to determine image size */ + IC_SIZED = 0x04, /* Image size determined - still loading */ + IC_MULTI = 0x06, /* Same as IC_SIZED, but for second or + subsequent images in multipart MIME */ + IC_NOCACHE = 0x11, /* Image deferred for loading later */ + IC_COMPLETE = 0x20, /* Image loaded - no errors */ + IC_BAD = 0x21, /* Corrupt or illegal image data */ + IC_INCOMPLETE = 0x22, /* Partially loaded image data */ + IC_MISSING = 0x23, /* No such file on server */ + IC_ABORT_PENDING= 0x24 /* Image download abort in progress */ +}; + +/* Still receiving data from the netlib ? */ +#define IMAGE_CONTAINER_ACTIVE(ic) ((ic)->state <= IC_MULTI) + +/* Force memory cache to be flushed ? */ +#define FORCE_RELOAD(reload_method) \ + (reload_method = DONT_USE_IMG_CACHE) + +/* Simple list of image contexts. */ +struct il_context_list { + IL_GroupContext *img_cx; + struct il_context_list *next; +}; + +/* Simple list of image containers. */ +struct il_container_list { + il_container *ic; + struct il_container_list *next; +}; + + +/* There is one il_container per real image */ +struct il_container_struct { + il_container *next; /* Cache bidirectional linked list */ + il_container *prev; + + ilIURL *url; + char *url_address; /* Same as url->address if there is no redirection*/ + + PRUint32 hash; + PRUint32 urlhash; + + enum icstate state; + int sized; + + int moz_type; /* TYPE_CHROME, etc. */ + + int is_alone; /* only image on a page */ + int is_in_use; /* Used by some context */ + int32 loop_count; /* Remaining number of times to repeat image, + -1 means loop infinitely */ + int is_looping; /* TRUE if this is the second or subsequent + pass of an animation. */ + nsImageAnimation animate_request; /* Set in nsPresContext. + normal = 0; one frame = 1; one loop = 2 */ + int is_aborted; /* True if aborted by NetLib. */ + PRPackedBool is_url_loading;/* TRUE if NetLib is currently loading the URL. */ + int is_multipart; /* TRUE if stream is known to be multipart. */ + int multi; /* Known to be either multipart-MIME + or multi-image format */ + int new_data_for_fe; /* Any Scanlines that FE doesn't know about ? */ + int update_start_row; /* Scanline range to send to FE */ + int update_end_row; + + PRUint32 bytes_consumed; /* Bytes read from the stream so far */ + + NI_PixmapHeader *src_header; /* Source image header information. */ + IL_Pixmap *image; /* Destination image pixmap structure. */ + IL_Pixmap *mask; /* Destination mask pixmap structure. */ + + char* type; + void *ds; /* decoder's private data */ + + il_converter converter; + void *quantize; /* quantizer's private data */ + + class nsIImgDecoder *imgdec; + class nsIImgDCallbk *imgdcb; + + void *row_output_timeout; + PRUint8 *scalerow; + int pass; /* pass (scan #) of a multi-pass image. + Used for interlaced GIFs & p-JPEGs */ + + int forced; + PRUint32 content_length; + + int dest_width, dest_height; /* Target dimensions of the image */ + PRPackedBool natural_size; /* True if the image is decoded to its natural + size. */ + PRPackedBool aspect_distorted; /* True if the image undergoes aspect ratio + distortion during decoding. */ + + IL_IRGB *background_color; /* The requested background color for this + image (only applies if the image is + determined to be transparent.) A mask will + be created for a transparent image only if + no background color was requested. */ + + char *comment; /* Human-readable text stored in image */ + int comment_length; + + int colormap_serial_num; /* serial number of last installed colormap */ + + int dont_use_custom_palette; + int rendered_with_custom_palette; + IL_DitherMode dither_mode; /* ilDither or ilClosestColor */ + + IL_GroupContext *img_cx; /* The context in which this image was created. + Used during image decoding only. */ + IL_DisplayType display_type; /* Type of display for which the container + is created. */ + ilIImageRenderer *img_cb; + ilINetContext *net_cx; /* Context which initiated this transfer. */ + + IL_ImageReq *clients; /* List of clients of this container. */ + IL_ImageReq *lclient; /* Last client in the client list. */ + il_context_list *img_cx_list; /* List of contexts which have clients of + this container. */ + + IL_Rect displayable_rect; /* The area of the image pixmap which is in a + displayable state. Used as a filter + between client calls to IL_DisplaySubImage + and Image Library calls to DisplayPixmap, in + the event that the client requests us to + draw a part of the pixmap that has yet to + be decoded. */ + + time_t expires; /* Expiration date for the corresponding URL */ + +#ifdef DEBUG + PRTime start_time; +#endif + char *fetch_url; /* actual url address used */ +}; + + +typedef enum { ilUndefined, ilCI, ilGrey, ilRGB } il_mode; + +typedef enum il_draw_mode +{ + ilErase, /* Transparent areas are reset to background */ + ilOverlay /* Transparent areas overlay existing data */ +} il_draw_mode; + + +/* A context for a group of images. */ +struct _IL_GroupContext { + ilIImageRenderer *img_cb; + void *dpy_cx; /* An opaque pointer passed back to all + callbacks in the interface vtable. */ + + IL_DisplayType display_type; /* IL_Console, IL_Printer or IL_PostScript. */ + IL_ColorSpace *color_space; /* Display colorspace. */ + + /* Preferences */ + PRPackedBool progressive_display; /* If TRUE, images are displayed while + loading */ + IL_DitherMode dither_mode; /* IL_ClosestColor, IL_Dither or IL_Auto. */ + int dontscale; /* Used for Macs, which do their own scaling */ + int nolowsrc; /* If TRUE, never display LOSRC images */ + + /* Per-context state */ + il_container_list *container_list;/* List of containers in this context. */ + int32 num_containers; /* Number of containers in this context. */ + int32 num_loading; /* Number of containers which are currently + loading. */ + int32 num_looping; /* Number of containers which are currently + looping i.e. on second or subsequent + iteration of an animation. */ + int32 num_aborted; /* Number of containers which have aborted + so far. */ + + XP_ObserverList obs_list; /* List of observers for this image group. */ + + struct _IL_GroupContext *next; /* Next entry in a list of image group + contexts. */ +}; + + +/* Tag to indicate whether a request represents an image or an icon. */ +typedef enum +{ + IL_IMAGE, + IL_ICON +} IL_ImageType; + + +/* This is Image Library's internal representation of a client's image request. + It represents a handle on a specific instance of an image container. */ +struct _IL_ImageReq { + il_container *ic; /* The image container for this request (may + be shared with other requests.) */ + IL_ImageType image_type; /* Image or icon. */ + + IL_GroupContext *img_cx; /* The group context to which this request + belongs. */ + ilINetContext *net_cx; /* A clone of the net context which the image + library was given when this image handle was + created. This serves as a backup in case + the image container's net_cx becomes invalid, + (for example, when the client for which the + container was initially created is destroyed.) */ + PRPackedBool stopped; /* TRUE - if user hit "Stop" button */ + int is_view_image; /* non-zero if client is + internal-external-reconnect */ + + XP_ObserverList obs_list; /* List of observers for this request. */ + + struct _IL_ImageReq *next; /* Next entry in a list of image requests. */ +}; + + + +#endif +#endif diff --git a/modules/libimg/public_com/il.h b/modules/libimg/public_com/il.h new file mode 100644 index 000000000000..f2fa08c5157b --- /dev/null +++ b/modules/libimg/public_com/il.h @@ -0,0 +1,58 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +/* -*- Mode: C; tab-width: 4 -*- + * il.h --- Exported image library interface + * + * $Id: il.h,v 1.6 2001/06/19 11:15:46 pavlov%netscape.com Exp $ + */ + + +/* + * global defines for image lib users + */ + +#ifndef _IL_H +#define _IL_H + + +/* attr values */ +#define IL_ATTR_RDONLY 0 +#define IL_ATTR_RW 1 +#define IL_ATTR_TRANSPARENT 2 +#define IL_ATTR_HONOR_INDEX 4 + +#undef ABS +#define ABS(x) (((x) < 0) ? -(x) : (x)) + +/* A fast but limited, perceptually-weighted color distance function */ +#define IL_COLOR_DISTANCE(r1, r2, g1, g2, b1, b2) \ + ((ABS((g1) - (g2)) << 2) + (ABS((r1) - (r2)) << 1) + (ABS((b1) - (b2)))) + +/* We don't distinguish between colors that are "closer" together + than this. The appropriate setting is a subjective matter. */ +#define IL_CLOSE_COLOR_THRESHOLD 6 + + +#endif /* _IL_H */ + + diff --git a/modules/libimg/public_com/il_utilp.h b/modules/libimg/public_com/il_utilp.h new file mode 100644 index 000000000000..951940e35bdf --- /dev/null +++ b/modules/libimg/public_com/il_utilp.h @@ -0,0 +1,82 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +/* -*- Mode: C; tab-width: 4 -*- + * il_utilp.h Colormap and colorspace utilities - types and definitions + * private to Image Library. + * + * $Id: il_utilp.h,v 1.6 2001/06/19 11:15:49 pavlov%netscape.com Exp $ + */ + + +/************************* Colormap utilities ********************************/ + +/* Parameters for building a color cube and its associated lookup table. */ +#define LOOKUP_TABLE_SIZE 32768 +#define LOOKUP_TABLE_RED 32 +#define LOOKUP_TABLE_GREEN 32 +#define LOOKUP_TABLE_BLUE 32 +#define CUBE_MAX_SIZE 256 + +/* Macro to convert 8-bit/channel RGB data into an 8-bit colormap index. */ +#define COLORMAP_INDEX(lookup_table, red, green, blue) \ + lookup_table[LOOKUP_TABLE_INDEX(red, green, blue)] + +/* Macro to convert 8-bit/channel RGB data into a 16-bit lookup table index. + The lookup table value is the index to the colormap. */ +#define LOOKUP_TABLE_INDEX(red, green, blue) \ + ((USE_5_BITS(red) << 10) | \ + (USE_5_BITS(green) << 5) | \ + USE_5_BITS(blue)) + +/* Take the 5 most significant bits of an 8-bit value. */ +#define USE_5_BITS(x) ((x) >> 3) + +/* Scaling macro for creating color cubes. */ +#define CUBE_SCALE(val, double_new_size_minus1, old_size_minus1, \ + double_old_size_minus1) \ + ((val) * (double_new_size_minus1) + (old_size_minus1)) / \ + (double_old_size_minus1) + + +/************************** Colorspace utilities *****************************/ + +/* Image Library private part of an IL_ColorSpace structure. */ +typedef struct il_ColorSpaceData { + /* RGB24 to RGBN depth conversion maps. Each of these maps take an + 8-bit input for a color channel and converts it into that channel's + contribution to a depth N pixmap e.g. for a 24 to 16-bit color + conversion, the output pixel is given by + + PRUint8 red, green, blue; + PRUint16 output_pixel; + output_pixel = r8torgbn[red] + g8torgbn[green] + b8torgbn[blue]; + + Depth conversion maps are created for the following destination image + pixmap depths: N = 8, 16 and 32. The type of the array elements is a + PRUintn. */ + void *r8torgbn; + void *g8torgbn; + void *b8torgbn; +} il_ColorSpaceData; + + diff --git a/modules/libimg/public_com/makefile.win b/modules/libimg/public_com/makefile.win new file mode 100644 index 000000000000..a9d1833cc8ac --- /dev/null +++ b/modules/libimg/public_com/makefile.win @@ -0,0 +1,52 @@ +#!gmake +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): + + +# + +DEPTH = ..\..\.. + + +#//------------------------------------------------------------------------ +#// +#// Specify any "command" targets. (ie. DIRS, INSTALL_FILES, ...) +#// (these must come before the common makefiles are included) +#// +#// DIRS - There is a subdirectory to process +#// INSTALL_FILES - Files to be installed in the distribution area +#// +#//------------------------------------------------------------------------ + +INSTALL_FILE_LIST=*.h +INSTALL_DIR=$(XPDIST)\include + +LCFLAGS = $(LCFLAGS) /TP + + +MODULE=img +DEPTH=..\..\.. +EXPORTS= if_struct.h il.h il_utilp.h \ + nsIImgDecoder.h nsIImgDCallbk.h nsImgDCallbk.h + +include <$(DEPTH)/config/rules.mak> + + +export:: INSTALL_FILES diff --git a/modules/libimg/public_com/nsIImgDCallbk.h b/modules/libimg/public_com/nsIImgDCallbk.h new file mode 100644 index 000000000000..80543b382c1c --- /dev/null +++ b/modules/libimg/public_com/nsIImgDCallbk.h @@ -0,0 +1,61 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ +#ifndef nsIImgDCallbk_h___ +#define nsIImgDCallbk_h___ + +#include "xpcompat.h" // for TimeoutCallbackFunction +#include "nsISupports.h" + +/* d34a2f20-cd9f-11d2-802c-0060088f91a3 */ +#define NS_IIMGDCALLBK_IID \ +{ 0xd34a2f20, 0xcd9f, 0x11d2, \ +{ 0x80, 0x2c, 0x00, 0x60, 0x08, 0x8f, 0x91, 0xa3 } } + +class nsIImgDCallbk : public nsISupports +{ +public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IIMGDCALLBK_IID) + + NS_IMETHOD ImgDCBFlushImage()=0; + NS_IMETHOD ImgDCBImageSize()=0; + NS_IMETHOD ImgDCBResetPalette()=0; + NS_IMETHOD ImgDCBInitTransparentPixel()=0; + NS_IMETHOD ImgDCBDestroyTransparentPixel()=0; + NS_IMETHOD ImgDCBSetupColorspaceConverter()=0; + NS_IMETHOD ImgDCBCreateGreyScaleColorSpace()=0; + + NS_IMETHOD_(void*) ImgDCBSetTimeout(TimeoutCallbackFunction func, void* closure, PRUint32 msecs)=0; + NS_IMETHOD ImgDCBClearTimeout(void *timer_id)=0; + + NS_IMETHOD ImgDCBHaveHdr(int destwidth, int destheight )=0; + + NS_IMETHOD ImgDCBHaveRow(PRUint8 *rowbuf, PRUint8* rgbrow, int x_offset, int len, + int row, int dup_rowcnt, PRUint8 draw_mode, + int pass )=0; + + + NS_IMETHOD ImgDCBHaveImageFrame()=0; + NS_IMETHOD ImgDCBHaveImageAll()=0; + NS_IMETHOD ImgDCBError()=0; +}; + +#endif /* nsIImgDCallbk_h___ */ diff --git a/modules/libimg/public_com/nsIImgDecoder.h b/modules/libimg/public_com/nsIImgDecoder.h new file mode 100644 index 000000000000..662a6db30f01 --- /dev/null +++ b/modules/libimg/public_com/nsIImgDecoder.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +#ifndef _nsIImgDecoder_h +#define _nsIImgDecoder_h + +#include "if_struct.h" // for il_container +#include "ni_pixmp.h" +#include "nsISupports.h" + +/* f00c22b0-bbd2-11d2-802c-0060088f91a3 */ +#define NS_IIMGDECODER_IID \ +{ 0xf00c22b0, 0xbbd2, 0x11d2, \ +{ 0x80, 0x2c, 0x00, 0x60, 0x08, 0x8f, 0x91, 0xa3 } } + +#define NS_IIMGDECODER_BASE_CONTRACTID "@mozilla.org/image/decoder;1?type=" + +class nsIImgDecoder : public nsISupports +{ +public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IIMGDECODER_IID) + + NS_IMETHOD ImgDInit()=0; + + NS_IMETHOD ImgDWriteReady(PRUint32 *max_read)=0; + NS_IMETHOD ImgDWrite(const unsigned char *buf, int32 len)=0; + NS_IMETHOD ImgDComplete()=0; + NS_IMETHOD ImgDAbort()=0; + + // XXX Need to fix this to make sure return type is nsresult + NS_IMETHOD_(il_container *) SetContainer(il_container *ic) = 0; + NS_IMETHOD_(il_container *) GetContainer() = 0; +}; + + + +#endif diff --git a/modules/libimg/public_com/nsImgDCallbk.h b/modules/libimg/public_com/nsImgDCallbk.h new file mode 100644 index 000000000000..dd642f1a0e82 --- /dev/null +++ b/modules/libimg/public_com/nsImgDCallbk.h @@ -0,0 +1,85 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ +#ifndef nsImgDCallbk_h___ +#define nsImgDCallbk_h___ + +// XXX This file needs to move to libimg/src - dp + +#include "nsIImgDCallbk.h" + +/*---------------------------------------------*/ +/*-----------------class-----------------------*/ + +class ImgDCallbk : public nsIImgDCallbk +{ +public: + ImgDCallbk(il_container *aContainer) { + NS_INIT_ISUPPORTS(); + ilContainer = aContainer; + }; + + virtual ~ImgDCallbk(); + + NS_DECL_ISUPPORTS + + NS_IMETHOD ImgDCBFlushImage(); + NS_IMETHOD ImgDCBImageSize(); + NS_IMETHOD ImgDCBResetPalette(); + NS_IMETHOD ImgDCBInitTransparentPixel(); + NS_IMETHOD ImgDCBDestroyTransparentPixel(); + NS_IMETHOD ImgDCBSetupColorspaceConverter(); + NS_IMETHOD ImgDCBCreateGreyScaleColorSpace(); + + NS_IMETHOD_(void*) ImgDCBSetTimeout(TimeoutCallbackFunction func, + void* closure, PRUint32 msecs); + NS_IMETHOD ImgDCBClearTimeout(void *timer_id); + + + /* callbacks from the decoder */ + NS_IMETHOD ImgDCBHaveHdr(int destwidth, int destheight); + NS_IMETHOD ImgDCBHaveRow(PRUint8*, PRUint8*, + int, int, int, int, + PRUint8 , int); + + NS_IMETHOD ImgDCBHaveImageFrame(); + NS_IMETHOD ImgDCBHaveImageAll(); + NS_IMETHOD ImgDCBError(); + + NS_IMETHODIMP CreateInstance(const nsCID &aClass, + il_container* ic, + const nsIID &aIID, + void **ppv) ; + + il_container *GetContainer() { + return ilContainer; + }; + + il_container *SetContainer(il_container *ic) { + ilContainer=ic; + return ic; + }; + +private: + il_container* ilContainer; +}; + +#endif /* nsImgDCallbk_h___ */ diff --git a/modules/libimg/public_com/nsImgDecCID.h b/modules/libimg/public_com/nsImgDecCID.h new file mode 100644 index 000000000000..adb90c260c4b --- /dev/null +++ b/modules/libimg/public_com/nsImgDecCID.h @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +#if 0 // OBSOLETE + +#ifndef nsImgDecCIID_h__ +#define nsImgDecCIID_h__ + +#include "nsRepository.h" + + +/* f00c22b0-bbd2-11d2-802c-0060088f91a3 */ +#define NS_IIMGDECODER_IID \ +{ 0xf00c22b0, 0xbbd2, 0x11d2, \ +{ 0x80, 0x2c, 0x00, 0x60, 0x08, 0x8f, 0x91, 0xa3 } } + + +/***************************************************/ + +#define NS_IMGDECODER_CID \ +{ 0xc9089cc0, 0xbaf4, 0x11d2, \ +{ 0x80, 0x2c, 0x00, 0x60, 0x08, 0x8f, 0x91, 0xa3 } } + +/* bc60b730-bbcf-11d2-802c-0060088f91a3 */ +#define NS_IMGDECODER_IID \ +{ 0xbc60730, 0xbbcf, 0x11d2, \ +{ 0x80, 0x2c, 0x00, 0x60, 0x08, 0x8f, 0x91, 0xa3 } } + +NS_DEFINE_IID(kImgDecoderIID, NS_IMGDECODER_IID); +NS_DEFINE_IID(kImgDecoderCID, NS_IMGDECODER_CID); + +/***************************************************/ + +/* e41ac650-cd9f-11d2-802c-0060088f91a3 */ +#define NS_IMGDCALLBK_CID \ +{ 0xe41ac650, 0xcd9f, 0x11d2, \ +{ 0x80, 0x2c, 0x00, 0x60, 0x08, 0x8f, 0x91, 0xa3 } } + +/* d34a2f20-cd9f-11d2-802c-0060088f91a3 */ +#define NS_IMGDCALLBK_IID \ +{ 0xd34a2f20, 0xcd9f, 0x11d2, \ +{ 0x80, 0x2c, 0x00, 0x60, 0x08, 0x8f, 0x91, 0xa3 } } + +#endif +#endif /* 0 */ diff --git a/modules/libimg/public_com/nsImgDecoder.h b/modules/libimg/public_com/nsImgDecoder.h new file mode 100644 index 000000000000..77555018d70b --- /dev/null +++ b/modules/libimg/public_com/nsImgDecoder.h @@ -0,0 +1,32 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +#if 0 // OBSOLETE +#ifndef nsImgDec_h___ +#define nsImgDec_h___ + + + +#include "nsIFactory.h" + +#endif +#endif /* 0 */ diff --git a/modules/libimg/src/.cvsignore b/modules/libimg/src/.cvsignore new file mode 100644 index 000000000000..f3c7a7c5da68 --- /dev/null +++ b/modules/libimg/src/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/modules/libimg/src/MANIFEST b/modules/libimg/src/MANIFEST new file mode 100644 index 000000000000..51fc96dd9c13 --- /dev/null +++ b/modules/libimg/src/MANIFEST @@ -0,0 +1,4 @@ +# +# This is a list of local files which get copied to the mozilla:dist directory +# + diff --git a/modules/libimg/src/Makefile.in b/modules/libimg/src/Makefile.in new file mode 100644 index 000000000000..3c243a72bd09 --- /dev/null +++ b/modules/libimg/src/Makefile.in @@ -0,0 +1,64 @@ +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = img +LIBRARY_NAME = img_s +REQUIRES = xpcom string layout util locale cookie necko timer jpeg unicharutil + +CPPSRCS = \ + ilNetReader.cpp \ + color.cpp \ + colormap.cpp \ + dither.cpp \ + if.cpp \ + ilclient.cpp \ + il_util.cpp \ + scale.cpp \ + xpcompat.cpp \ + $(NULL) + +LOCAL_INCLUDES = -I$(srcdir) + +ifndef MOZ_JAVA +LOCAL_JMC_SUBDIR = . +endif + +FORCE_STATIC_LIB = 1 + +include $(topsrcdir)/config/rules.mk + +ifeq ($(OS_ARCH),Linux) +DEFINES += -D_BSD_SOURCE -D_XOPEN_SOURCE=500 +endif +ifeq ($(OS_ARCH)$(OS_RELEASE),SunOS5) +ifeq ($(shell uname -r),5.3) +# In this special case (dither.cpp), the compiler has to know +# the OS version to a finer granularity than normal. +DEFINES += -DOSMINOR=3 +endif +endif diff --git a/modules/libimg/src/nsIImgDecoder.cpp b/modules/libimg/src/nsIImgDecoder.cpp new file mode 100644 index 000000000000..1efee70c7e0e --- /dev/null +++ b/modules/libimg/src/nsIImgDecoder.cpp @@ -0,0 +1,166 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + + + +#include "nsISupports.h" +#include "nsImgDecCID.h" + + +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); + + +NS_DEFINE_CID(kGIFDecoderCID, NS_IMGDECODER_CID); +NS_DEFINE_CID(kJPGDecoderCID, NS_IMGDECODER_CID); + +class ImgFactoryImpl : public nsIFactory +{ +public: + ImgFactoryImpl(const nsCID &aClass, const char* className, const char* contractID); + + NS_DECL_ISUPPORTS + + NS_IMETHOD CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult); + + NS_IMETHOD LockFactory(PRBool aLock); + +protected: + virtual ~ImgFactoryImpl(); + +protected: + nsCID mClassID; + const char* mClassName; + const char* mContractID; +}; + +/*---------------------*/ + +ImgFactoryImpl::ImgFactoryImpl(const nsCID &aClass, + const char* className, + const char* contractID) + : mClassID(aClass), mClassName(className), mContractID(contractID) +{ + NS_INIT_REFCNT(); +} + +ImgFactoryImpl::~ImgFactoryImpl() +{ +} + +NS_IMETHODIMP +ImgFactoryImpl::QueryInterface(const nsIID &aIID, void **aResult) +{ + if (! aResult) + return NS_ERROR_NULL_POINTER; + + // Always NULL result, in case of failure + *aResult = nsnull; + + if (aIID.Equals(kISupportsIID)) { + *aResult = NS_STATIC_CAST(nsISupports*, this); + AddRef(); + return NS_OK; + } else if (aIID.Equals(kIFactoryIID)) { + *aResult = NS_STATIC_CAST(nsIFactory*, this); + AddRef(); + return NS_OK; + } + return NS_NOINTERFACE; +} + +NS_IMPL_ADDREF(ImgFactoryImpl); +NS_IMPL_RELEASE(ImgFactoryImpl); + +extern nsresult +NS_NewDefaultResource(nsIRDFResource** aResult); + +NS_IMETHODIMP +ImgFactoryImpl::CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult) +{ + if (! aResult) + return NS_ERROR_NULL_POINTER; + + if (aOuter) + return NS_ERROR_NO_AGGREGATION; + + *aResult = nsnull; + + nsresult rv; + PRBool wasRefCounted = PR_TRUE; + nsISupports *inst = nsnull; + + if (mClassID.Equals(kGIFDecoderCID)) { + if (NS_FAILED(rv = NS_NewGIFDecoder((nsIGIFDecoder**) &inst))) + return rv; + } + if (mClassID.Equals(kJPEGDecoderCID)) { + if (NS_FAILED(rv = NS_NewJPGDecoder((nsIJPGDecoder**) &inst))) + return rv; + } + else { + return NS_ERROR_NO_INTERFACE; + } + + if (! inst) + return NS_ERROR_OUT_OF_MEMORY; + + if (NS_FAILED(rv = inst->QueryInterface(aIID, aResult))) + delete inst; + + if (wasRefCounted) + NS_IF_RELEASE(inst); + + return rv; +} + +nsresult ImgFactoryImpl::LockFactory(PRBool aLock) +{ + return NS_OK; +} + +/*---------------------*/ + + +/* return the proper factory to the caller */ +extern "C" PR_IMPLEMENT(nsresult) +NSGetFactory(nsISupports* serviceMgr, + const nsCID &aClass, + const char *aClassName, + const char *aContractID, + nsIFactory **aFactory) +{ + if (! aFactory) + return NS_ERROR_NULL_POINTER; + + ImgFactoryImpl* factory = new ImgFactoryImpl(aClass, aClassName, aContractID); + if (factory == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(factory); + *aFactory = factory; + return NS_OK; +} diff --git a/modules/libimg/src/win32.order b/modules/libimg/src/win32.order new file mode 100644 index 000000000000..2c80bee72e53 --- /dev/null +++ b/modules/libimg/src/win32.order @@ -0,0 +1,95 @@ +?il_partial@@YAXPAUil_container_struct@@HHH@Z ; 1357286 +?il_emit_row@@YAHPAUil_container_struct@@PAE1HHHHW4il_draw_mode@@H@Z ; 1357286 +?ImgDCBHaveRow@ImgDCallbk@@UAGIPAE0HHHHEH@Z ; 1357286 +IL_AddRefToColorSpace ; 138105 +IL_ReleaseColorSpace ; 138094 +XP_NotifyObservers ; 97013 +IL_GetImagePixmap ; 96561 +?il_progress_notify@@YAXPAUil_container_struct@@@Z ; 44047 +?il_flush_image_data@@YAXPAUil_container_struct@@@Z ; 43843 +?ImgDCBInitTransparentPixel@ImgDCallbk@@UAGIXZ ; 42416 +?il_init_image_transparent_pixel@@YAHPAUil_container_struct@@@Z ; 42416 +?il_destroy_image_transparent_pixel@@YAXPAUil_container_struct@@@Z ; 42341 +IL_SetTimeout ; 41179 +?il_pixmap_update_notify@@YAXPAUil_container_struct@@@Z ; 41074 +?ImgDCBFlushImage@ImgDCallbk@@UAGIXZ ; 41070 +?il_frame_complete_notify@@YAXPAUil_container_struct@@@Z ; 41069 +?ImgDCBHaveImageFrame@ImgDCallbk@@UAGIXZ ; 41069 +?ImgDCBSetTimeout@ImgDCallbk@@UAGPAXP6AXPAX@Z0I@Z ; 41069 +?ImgDCBDestroyTransparentPixel@ImgDCallbk@@UAGIXZ ; 41039 +?compare_PRUint32@@YAHPBX0PAX@Z ; 13734 +?AddRef@NetReaderImpl@@UAGKXZ ; 7119 +?Release@NetReaderImpl@@UAGKXZ ; 7119 +?il_image_stopped@@YAHPAUil_container_struct@@@Z ; 4275 +?IL_StreamWrite@@YAHPAUil_container_struct@@PBEJ@Z ; 2973 +?IL_StreamWriteReady@@YAHPAUil_container_struct@@@Z ; 2973 +?Write@NetReaderImpl@@UAGIPBEJ@Z ; 2973 +?WriteReady@NetReaderImpl@@UAGIPAI@Z ; 2973 +?il_reset_palette@@YAHPAUil_container_struct@@@Z ; 2709 +?il_compute_percentage_complete@@YAHHPAUil_container_struct@@@Z ; 1455 +??0NetReaderImpl@@QAE@PAUil_container_struct@@@Z ; 1418 +?StreamCreated@NetReaderImpl@@UAEHPAVilIURL@@PAD@Z ; 1418 +?IL_NewNetReader@@YAPAVilINetReader@@PAUil_container_struct@@@Z ; 1418 +?FlushImgBuffer@NetReaderImpl@@UAGIXZ ; 1418 +??1NetReaderImpl@@UAE@XZ ; 1418 +?NetRequestDone@NetReaderImpl@@UAGIPAVilIURL@@H@Z ; 1418 +?IL_StreamCreated@@YAHPAUil_container_struct@@PAVilIURL@@PAD@Z ; 1418 +?IL_NetRequestDone@@YAXPAUil_container_struct@@PAVilIURL@@H@Z ; 1418 +??_GNetReaderImpl@@UAEPAXI@Z ; 1418 +?StreamComplete@NetReaderImpl@@UAGIH@Z ; 1409 +?sniffout_mimetype@@YAHPBDJPAD@Z ; 1409 +?il_setup_color_space_converter@@YAHPAUil_container_struct@@@Z ; 1409 +?IL_StreamComplete@@YAXPAUil_container_struct@@H@Z ; 1409 +?il_size@@YAHPAUil_container_struct@@@Z ; 1409 +?FirstWrite@NetReaderImpl@@UAGIPBEJPAD@Z ; 1409 +?ImgDCBSetupColorspaceConverter@ImgDCallbk@@UAGIXZ ; 1409 +?ImgDCBImageSize@ImgDCallbk@@UAGIXZ ; 1409 +?IL_StreamFirstWrite@@YAHPAUil_container_struct@@PBEJ@Z ; 1409 +?ImgDCBResetPalette@ImgDCallbk@@UAGIXZ ; 1407 +?il_image_complete_notify@@YAXPAUil_container_struct@@@Z ; 1352 +?il_image_complete@@YAXPAUil_container_struct@@@Z ; 1352 +?ImgDCBHaveImageAll@ImgDCallbk@@UAGIXZ ; 1352 +XP_DisposeObserverList ; 271 +?il_group_notify@@YAXPAU_IL_GroupContext@@J@Z ; 232 +?il_image_destroyed_notify@@YAXPAU_IL_ImageReq@@@Z ; 220 +?il_add_client@@YAHPAU_IL_GroupContext@@PAUil_container_struct@@PAU_IL_ImageReq@@H@Z ; 220 +IL_GetImage ; 220 +?il_hash@@YAIPBD@Z ; 220 +IL_DestroyImage ; 220 +?il_PermitLoad@@YAHPBDPAVnsIImageRequestObserver@@@Z ; 220 +?il_get_container@@YAPAUil_container_struct@@PAU_IL_GroupContext@@W4ImgCachePolicy@@PBDPAU_NI_IRGB@@W4IL_DitherMode@@HHH@Z ; 220 +?il_delete_client@@YAHPAUil_container_struct@@PAU_IL_ImageReq@@@Z ; 220 +?il_check_requested_animation@@YA?AW4nsImageAnimation@@PAVnsIImageRequestObserver@@@Z ; 220 +XP_SetObserverListObservable ; 220 +XP_GetString ; 211 +?il_removefromcache@@YAPAUil_container_struct@@PAU1@@Z ; 182 +?il_image_abort@@YAXPAUil_container_struct@@@Z ; 174 +?il_destroy_pixmap@@YAXPAVilIImageRenderer@@PAU_NI_Pixmap@@@Z ; 127 +?QueryInterface@ImgDCallbk@@UAGIABUnsID@@PAPAX@Z ; 116 +?AddRef@ImgDCallbk@@UAGKXZ ; 116 +IL_ClearTimeout ; 114 +?il_reduce_image_cache_size_to@@YAXI@Z ; 108 +?il_dimensions_notify@@YAXPAUil_container_struct@@HH@Z ; 107 +?il_adjust_cache_fullness@@YAXJ@Z ; 107 +?ImgDCBHaveHdr@ImgDCallbk@@UAGIHH@Z ; 107 +?il_cache_return_notify@@YAXPAU_IL_ImageReq@@@Z ; 104 +IL_DestroyGroupContext ; 90 +?il_delete_container@@YAXPAUil_container_struct@@@Z ; 87 +IL_CreateGreyScaleColorSpace ; 70 +?il_scour_container@@YAXPAUil_container_struct@@@Z ; 69 +??1ImgDCallbk@@UAE@XZ ; 69 +?Release@ImgDCallbk@@UAGKXZ ; 69 +??_GImgDCallbk@@UAEPAXI@Z ; 69 +?assign_assuming_AddRef@nsCOMPtr_base@@IAEXPAVnsISupports@@@Z ; 68 +IL_SetDisplayMode ; 64 +XP_NewObserverList ; 64 +IL_NewGroupContext ; 64 +?ImgDCBClearTimeout@ImgDCallbk@@UAGIPAX@Z ; 57 +IL_InterruptContext ; 51 +IL_CreateTrueColorSpace ; 50 +?IL_StreamAbort@@YAXPAUil_container_struct@@H@Z ; 27 +?StreamAbort@NetReaderImpl@@UAGIH@Z ; 27 +IL_ShrinkCache ; 11 +IL_SetCacheSize ; 1 +IL_FlushCache ; 1 +IL_Init ; 1