949 lines
26 KiB
C
949 lines
26 KiB
C
/****************************************************************************
|
|
* NCSA Mosaic for the X Window System *
|
|
* Software Development Group *
|
|
* National Center for Supercomputing Applications *
|
|
* University of Illinois at Urbana-Champaign *
|
|
* 605 E. Springfield, Champaign IL 61820 *
|
|
* mosaic@ncsa.uiuc.edu *
|
|
* *
|
|
* Copyright (C) 1993, Board of Trustees of the University of Illinois *
|
|
* *
|
|
* NCSA Mosaic software, both binary and source (hereafter, Software) is *
|
|
* copyrighted by The Board of Trustees of the University of Illinois *
|
|
* (UI), and ownership remains with the UI. *
|
|
* *
|
|
* The UI grants you (hereafter, Licensee) a license to use the Software *
|
|
* for academic, research and internal business purposes only, without a *
|
|
* fee. Licensee may distribute the binary and source code (if released) *
|
|
* to third parties provided that the copyright notice and this statement *
|
|
* appears on all copies and that no charge is associated with such *
|
|
* copies. *
|
|
* *
|
|
* Licensee may make derivative works. However, if Licensee distributes *
|
|
* any derivative work based on or derived from the Software, then *
|
|
* Licensee will (1) notify NCSA regarding its distribution of the *
|
|
* derivative work, and (2) clearly notify users that such derivative *
|
|
* work is a modified version and not the original NCSA Mosaic *
|
|
* distributed by the UI. *
|
|
* *
|
|
* Any Licensee wishing to make commercial use of the Software should *
|
|
* contact the UI, c/o NCSA, to negotiate an appropriate license for such *
|
|
* commercial use. Commercial use includes (1) integration of all or *
|
|
* part of the source code into a product for sale or license by or on *
|
|
* behalf of Licensee to third parties, or (2) distribution of the binary *
|
|
* code or source code to third parties that need it to utilize a *
|
|
* commercial product sold or licensed by or on behalf of Licensee. *
|
|
* *
|
|
* UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR *
|
|
* ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED *
|
|
* WARRANTY. THE UI SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE *
|
|
* USERS OF THIS SOFTWARE. *
|
|
* *
|
|
* By using or copying this Software, Licensee agrees to abide by the *
|
|
* copyright law and all other applicable laws of the U.S. including, but *
|
|
* not limited to, export control laws, and the terms of this license. *
|
|
* UI shall have the right to terminate this license immediately by *
|
|
* written notice upon Licensee's breach of, or non-compliance with, any *
|
|
* of its terms. Licensee may be held legally responsible for any *
|
|
* copyright infringement that is caused or encouraged by Licensee's *
|
|
* failure to abide by the terms of this license. *
|
|
* *
|
|
* Comments and questions are welcome and can be sent to *
|
|
* mosaic-x@ncsa.uiuc.edu. *
|
|
****************************************************************************/
|
|
#include "../config.h"
|
|
#include "mosaic.h"
|
|
#include "gui.h"
|
|
#include "img.h"
|
|
#include "mo-www.h"
|
|
#include "globalhist.h"
|
|
#include "picread.h"
|
|
#include "libhtmlw/HTML.h"
|
|
#include "cci.h"
|
|
extern int cci_event;
|
|
|
|
#ifndef DISABLE_TRACE
|
|
extern int srcTrace;
|
|
#endif
|
|
|
|
#include "bitmaps/gopher_image.xbm"
|
|
#include "bitmaps/gopher_movie.xbm"
|
|
#include "bitmaps/gopher_menu.xbm"
|
|
#include "bitmaps/gopher_text.xbm"
|
|
#include "bitmaps/gopher_sound.xbm"
|
|
#include "bitmaps/gopher_index.xbm"
|
|
#include "bitmaps/gopher_telnet.xbm"
|
|
#include "bitmaps/gopher_binary.xbm"
|
|
#include "bitmaps/gopher_unknown.xbm"
|
|
|
|
ImageInfo *scaleImage(ImageInfo *img_data,char *width,char *height);
|
|
|
|
static ImageInfo *gopher_image = NULL;
|
|
static ImageInfo *gopher_movie = NULL;
|
|
static ImageInfo *gopher_menu = NULL;
|
|
static ImageInfo *gopher_text = NULL;
|
|
static ImageInfo *gopher_sound = NULL;
|
|
static ImageInfo *gopher_index = NULL;
|
|
static ImageInfo *gopher_telnet = NULL;
|
|
static ImageInfo *gopher_binary = NULL;
|
|
static ImageInfo *gopher_unknown = NULL;
|
|
|
|
|
|
/* for selective image loading */
|
|
#define blank_width 8
|
|
#define blank_height 8
|
|
static unsigned char blank_bits[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
|
|
static ImageInfo *blank = NULL;
|
|
|
|
extern char **imagekill_sites;
|
|
|
|
/*******************************/
|
|
|
|
|
|
/* Defined in gui.c */
|
|
extern char *cached_url;
|
|
extern mo_window *current_win;
|
|
/* Defined in gui-documents.c */
|
|
extern int interrupted;
|
|
extern int loading_inlined_images;
|
|
extern int installed_colormap;
|
|
extern Colormap installed_cmap;
|
|
|
|
/*
|
|
(dsp, DefaultRootWindow (dsp), \
|
|
*/
|
|
|
|
#if defined(__STDC__) || defined(__sgi)
|
|
#define MAKE_IMGINFO_FROM_BITMAP(name) \
|
|
if (!name) \
|
|
{ \
|
|
name = (ImageInfo *)malloc (sizeof (ImageInfo)); \
|
|
name->ismap = 0; \
|
|
name->width = name##_width; \
|
|
name->height = name##_height; \
|
|
name->image_data = NULL; \
|
|
/* Bandaid for bug in Eric's code. */ \
|
|
name->internal = 1; \
|
|
name->transparent = 0; \
|
|
name->image = \
|
|
XCreatePixmapFromBitmapData \
|
|
(XtDisplay(swin), XtWindow(view), \
|
|
name##_bits, \
|
|
name##_width, name##_height, \
|
|
fg_pixel, bg_pixel, DefaultDepth(dsp, DefaultScreen(dsp))); \
|
|
} \
|
|
if (!name->image) \
|
|
{ \
|
|
name->image = \
|
|
XCreatePixmapFromBitmapData \
|
|
(XtDisplay(swin), XtWindow(view), \
|
|
name##_bits, \
|
|
name##_width, name##_height, \
|
|
fg_pixel, bg_pixel, DefaultDepth(dsp, DefaultScreen(dsp))); \
|
|
}
|
|
#else
|
|
#define MAKE_IMGINFO_FROM_BITMAP(name) \
|
|
if (!name) \
|
|
{ \
|
|
name = (ImageInfo *)malloc (sizeof (ImageInfo)); \
|
|
name->ismap = 0; \
|
|
name->width = name/**/_width; \
|
|
name->height = name/**/_height; \
|
|
name->image_data = NULL; \
|
|
/* Bandaid for bug in Eric's code. */ \
|
|
name->internal = 1; \
|
|
name->transparent = 0; \
|
|
name->image = \
|
|
XCreatePixmapFromBitmapData \
|
|
(XtDisplay(swin), XtWindow(view), \
|
|
name/**/_bits, \
|
|
name/**/_width, name/**/_height, \
|
|
fg_pixel, bg_pixel, DefaultDepth(dsp, DefaultScreen(dsp))); \
|
|
} \
|
|
if (!name->image) \
|
|
{ \
|
|
name->image = \
|
|
XCreatePixmapFromBitmapData \
|
|
(XtDisplay(swin), XtWindow(view), \
|
|
name/**/_bits, \
|
|
name/**/_width, name/**/_height, \
|
|
fg_pixel, bg_pixel, DefaultDepth(dsp, DefaultScreen(dsp))); \
|
|
}
|
|
#endif /* __STDC__ */
|
|
|
|
#define RETURN_IMGINFO_FROM_BITMAP(x) \
|
|
{ \
|
|
MAKE_IMGINFO_FROM_BITMAP(x); \
|
|
if (cci_event) MoCCISendEventOutput(IMAGE_LOADED); \
|
|
return x; \
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
|
|
ImageInfo *scaleImage(ImageInfo *img_data,char *width,char *height) {
|
|
/*
|
|
int widthInt,heightInt;
|
|
|
|
if (!width) {
|
|
widthInt=img_data->width;
|
|
}
|
|
else {
|
|
if (strchr(width,'%')) {
|
|
widthInt=(atoi(width)/100)*img_data->width;
|
|
}
|
|
else {
|
|
widthInt=atoi(width);
|
|
}
|
|
}
|
|
|
|
if (!height) {
|
|
heightInt=img_data->height;
|
|
}
|
|
else {
|
|
heightInt=atoi(height);
|
|
}
|
|
|
|
for (i=0; i<256; i++) {
|
|
convertRed[i]=(byte)img_data->reds[i];
|
|
convertGreen[i]=(byte)img_data->greens[i];
|
|
convertBlue[i]=(byte)img_data->blues[i];
|
|
}
|
|
|
|
img_data->image_data=SmoothResize(img_data->image_data,0,
|
|
img_data->width,img_data->height,
|
|
widthInt,heightInt,
|
|
convertRed,convertGreen,convertBlue,
|
|
newRed,newGreen,newBlue,256);
|
|
*/
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
unsigned char nums[]={
|
|
1,
|
|
2,
|
|
4,
|
|
8,
|
|
16,
|
|
32,
|
|
64,
|
|
128
|
|
};
|
|
|
|
/* Cache Load Hack: (BJS)
|
|
char *ir_hack_string, *diskfile, *url;
|
|
sprintf(ir_hack_string,"%s\0%s",diskfile,url);
|
|
ImageResolve(NULL,ir_hack_string,0,NULL,NULL);
|
|
*/
|
|
|
|
/* Width and Height Hack: (SWP)
|
|
Added "width" and "height" to the parameter list. These are used to
|
|
resize the image when we are done decoding. This'll be fun when we
|
|
start processing on a line-by-line basis.
|
|
If NULLs are passed, the width and height are not used.
|
|
*/
|
|
|
|
/* Image resolution function. */
|
|
/*static*/
|
|
ImageInfo *ImageResolve (Widget w, char *src, int noload, char *wid, char *hei)
|
|
{
|
|
extern Widget view; /*hw->html.view*/
|
|
Widget swin = current_win->scrolled_win;
|
|
int i, cnt;
|
|
unsigned char *data;
|
|
unsigned char *bg_map;
|
|
unsigned char *bgptr;
|
|
unsigned char *cptr;
|
|
unsigned char *ptr;
|
|
int width, height;
|
|
int Used[256];
|
|
XColor colrs[256];
|
|
ImageInfo *img_data;
|
|
/* char *txt;*/
|
|
int widthbyheight = 0;
|
|
char *fnam;
|
|
int rc;
|
|
int bg, bg_red, bg_green, bg_blue;
|
|
#ifdef HAVE_HDF
|
|
int ishdf = 0;
|
|
char *hdfref = NULL;
|
|
#endif
|
|
mo_window *win = NULL;
|
|
extern int Vclass;
|
|
static Pixel fg_pixel, bg_pixel;
|
|
static int done_fetch_colors = 0;
|
|
int j,bcnt;
|
|
|
|
/* Cache Load Hack - BJS 1/18/96 */ /* Fixed - SWP 02/01/96 */
|
|
if(!w) {
|
|
fnam = src;
|
|
while(*src != '\n') src++;
|
|
*src='\0';
|
|
src++;
|
|
|
|
goto stuffcache;
|
|
}
|
|
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr,
|
|
"[ImageResolve] I'm entering, src '%s', noload %d!\n",
|
|
src, noload);
|
|
#endif
|
|
|
|
if (!src)
|
|
return NULL;
|
|
|
|
if (current_win && current_win->scrolled_win == w)
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr, "[ImageResolve] already have current_win\n");
|
|
#endif
|
|
|
|
goto foundit;
|
|
}
|
|
|
|
while (win = mo_next_window (win))
|
|
{
|
|
if (win->scrolled_win == w)
|
|
{
|
|
mo_set_current_cached_win (win);
|
|
|
|
cached_url = win->current_node ? win->current_node->url : "lose";
|
|
win->cached_url = cached_url;
|
|
|
|
goto foundit;
|
|
}
|
|
}
|
|
|
|
/* Shit outta luck. */
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr, "[ImageResolve] aaaaaaaaaaaaaaaaaaaaagh\n");
|
|
#endif
|
|
|
|
return NULL;
|
|
|
|
foundit:
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr, "[ImageResolve] hello! win 0x%08x\n",
|
|
win);
|
|
#endif
|
|
|
|
|
|
/* Here is one place we do image_kill */
|
|
if(src){
|
|
if(imagekill_sites != NULL) {
|
|
for(i = 0; imagekill_sites[i]; i++) {
|
|
if(strstr(cached_url, imagekill_sites[i])) {
|
|
extern Widget view; /*hw->html.view*/
|
|
Widget swin = current_win->scrolled_win;
|
|
|
|
if (!done_fetch_colors){
|
|
if (!view)
|
|
return NULL;
|
|
/* First, go fetch the pixels. */
|
|
XtVaGetValues(view,
|
|
XtNforeground, &fg_pixel,
|
|
XtNbackground, &bg_pixel,
|
|
NULL);
|
|
done_fetch_colors = 1;
|
|
}
|
|
RETURN_IMGINFO_FROM_BITMAP(blank);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Internal images. */
|
|
if (strncmp (src, "internal-", 9) == 0)
|
|
{
|
|
|
|
if (!done_fetch_colors)
|
|
{
|
|
|
|
if (!view)
|
|
return NULL;
|
|
|
|
/* First, go fetch the pixels. */
|
|
XtVaGetValues(view,
|
|
XtNforeground, &fg_pixel,
|
|
XtNbackground, &bg_pixel,
|
|
NULL);
|
|
|
|
done_fetch_colors = 1;
|
|
}
|
|
|
|
if (strcmp (src, "internal-gopher-image") == 0)
|
|
RETURN_IMGINFO_FROM_BITMAP(gopher_image);
|
|
if (strcmp (src, "internal-gopher-movie") == 0)
|
|
RETURN_IMGINFO_FROM_BITMAP(gopher_movie);
|
|
if (strcmp (src, "internal-gopher-menu") == 0)
|
|
RETURN_IMGINFO_FROM_BITMAP(gopher_menu);
|
|
if (strcmp (src, "internal-gopher-text") == 0)
|
|
RETURN_IMGINFO_FROM_BITMAP(gopher_text);
|
|
if (strcmp (src, "internal-gopher-sound") == 0)
|
|
RETURN_IMGINFO_FROM_BITMAP(gopher_sound);
|
|
if (strcmp (src, "internal-gopher-index") == 0)
|
|
RETURN_IMGINFO_FROM_BITMAP(gopher_index);
|
|
if (strcmp (src, "internal-gopher-telnet") == 0)
|
|
RETURN_IMGINFO_FROM_BITMAP(gopher_telnet);
|
|
if (strcmp (src, "internal-gopher-binary") == 0)
|
|
RETURN_IMGINFO_FROM_BITMAP(gopher_binary);
|
|
if (strcmp (src, "internal-gopher-unknown") == 0)
|
|
RETURN_IMGINFO_FROM_BITMAP(gopher_unknown);
|
|
}
|
|
|
|
#ifdef HAVE_HDF
|
|
/* Incoming HDF image references will only be anchors,
|
|
so we can determine that they are in fact HDF image references
|
|
by doing strncmp here. */
|
|
if (strncmp (src, "#hdfref;", 8) == 0)
|
|
ishdf = 1;
|
|
|
|
/* OK, src is the URL we have to go hunt down.
|
|
First, we go get it. */
|
|
/* We can use cached_url here, since we set it in do_window_text. */
|
|
if (ishdf)
|
|
{
|
|
hdfref = &(src[8]);
|
|
src = mo_url_canonicalize_keep_anchor (src, cached_url);
|
|
}
|
|
else
|
|
#endif
|
|
|
|
stuffcache:
|
|
src = mo_url_canonicalize (src, cached_url);
|
|
|
|
/* Go see if we already have the image info hanging around. */
|
|
img_data = mo_fetch_cached_image_data (src);
|
|
if (img_data && img_data->image_data)
|
|
{
|
|
unsigned long bg_pixel;
|
|
XColor tmpcolr;
|
|
|
|
if (img_data->bg_index>=0) {
|
|
/* This code copied from xpmread.c. I could almost
|
|
* delete the code from there, but I suppose an XPM
|
|
* file could pathalogially have multiple transparent
|
|
* colour indicies. -- GWP
|
|
*/
|
|
XtVaGetValues(view, XtNbackground, &bg_pixel, NULL);
|
|
tmpcolr.pixel = bg_pixel;
|
|
XQueryColor(XtDisplay(view),
|
|
(installed_colormap ?
|
|
installed_cmap :
|
|
DefaultColormap(XtDisplay(view), DefaultScreen(XtDisplay(view)))),
|
|
&tmpcolr);
|
|
img_data->reds[img_data->bg_index]=tmpcolr.red;
|
|
img_data->greens[img_data->bg_index]=tmpcolr.green;
|
|
img_data->blues[img_data->bg_index]=tmpcolr.blue;
|
|
}
|
|
|
|
img_data->src = strdup(src);
|
|
free (src);
|
|
if (cci_event) MoCCISendEventOutput(IMAGE_LOADED);
|
|
|
|
return (ImageInfo *)img_data;
|
|
/*
|
|
if (!wid && !hei) {
|
|
return (ImageInfo *)img_data;
|
|
}
|
|
|
|
return(scaleImage(img_data,wid,hei));
|
|
*/
|
|
}
|
|
|
|
/* If we don't have the image cached and noload is high,
|
|
then just return NULL to avoid doing a network load. */
|
|
/* Also return if interrupted is high. */
|
|
if (noload || interrupted)
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr, "RETURNING Null noload %d interrupted %d\n",
|
|
noload, interrupted);
|
|
#endif
|
|
free (src);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr, "GOING ON THROUGH...\n");
|
|
#endif
|
|
|
|
/*
|
|
* No transparent background by default
|
|
*/
|
|
bg = -1;
|
|
bg_map = NULL;
|
|
#ifdef HAVE_HDF
|
|
if (ishdf)
|
|
{
|
|
img_data =
|
|
(ImageInfo *)hdfGrokImage
|
|
(mo_hdf_fetch_local_filename (src),
|
|
hdfref,
|
|
&bg);
|
|
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr, "[ImageResolve] Did hdfGrokImage, got back 0x%08x\n",
|
|
img_data);
|
|
#endif
|
|
|
|
if (!img_data)
|
|
return NULL;
|
|
|
|
/* Yet another bandaid... */
|
|
img_data->internal = 0;
|
|
|
|
/* Fill out colrs array. */
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
colrs[i].red = img_data->reds[i];
|
|
colrs[i].green = img_data->greens[i];
|
|
colrs[i].blue = img_data->blues[i];
|
|
colrs[i].pixel = i;
|
|
colrs[i].flags = DoRed|DoGreen|DoBlue;
|
|
}
|
|
|
|
if (bg >= 0)
|
|
{
|
|
bg_red = colrs[bg].red;
|
|
bg_green = colrs[bg].green;
|
|
bg_blue = colrs[bg].blue;
|
|
bg_map = (unsigned char *)malloc(img_data->width * img_data->height);
|
|
}
|
|
}
|
|
else
|
|
#endif /* HAVE_HDF */
|
|
{
|
|
|
|
/* if w is NULL we're stuffing the cache with our own info...
|
|
BJS */
|
|
if(w) {
|
|
|
|
/* We have to load the image. */
|
|
fnam = mo_tmpnam(src);
|
|
|
|
interrupted = 0;
|
|
rc = mo_pull_er_over_virgin (src, fnam);
|
|
if (!rc)
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr, "mo_pull_er_over_virgin returned %d; bonging\n",
|
|
rc);
|
|
#endif
|
|
free (fnam);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr,
|
|
"[ImageResolve] Got through mo_pull_er_over_virgin, rc %d\n",
|
|
rc);
|
|
#endif
|
|
|
|
#if 0
|
|
/* This causes problems. */
|
|
{
|
|
/* Check use_this_url_instead from HTAccess.c. */
|
|
extern char *use_this_url_instead;
|
|
if (use_this_url_instead)
|
|
{
|
|
free (src);
|
|
src = use_this_url_instead;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*********************************************/
|
|
/* Send it through CCI if need be */
|
|
MoCCISendBrowserViewFile(src, "unknown", fnam);
|
|
}
|
|
|
|
data = ReadBitmap(fnam, &width, &height, colrs, &bg);
|
|
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr,
|
|
"[ImageResolve] Did ReadBitmap, got 0x%08x\n", data);
|
|
#endif
|
|
|
|
/* if we have a transparent background, prepare for it */
|
|
if ((bg >= 0)&&(data != NULL))
|
|
{
|
|
unsigned long bg_pixel;
|
|
XColor tmpcolr;
|
|
|
|
/* This code copied from xpmread.c. I could almost
|
|
* delete the code from there, but I suppose an XPM
|
|
* file could pathalogially have multiple transparent
|
|
* colour indicies. -- GWP
|
|
*/
|
|
XtVaGetValues(view, XtNbackground, &bg_pixel, NULL);
|
|
tmpcolr.pixel = bg_pixel;
|
|
XQueryColor(XtDisplay(view),
|
|
(installed_colormap ?
|
|
installed_cmap :
|
|
DefaultColormap(XtDisplay(view), DefaultScreen(XtDisplay(view)))),
|
|
&tmpcolr);
|
|
|
|
bg_red = colrs[bg].red = tmpcolr.red;
|
|
bg_green = colrs[bg].green = tmpcolr.green;
|
|
bg_blue = colrs[bg].blue = tmpcolr.blue;
|
|
colrs[bg].flags = DoRed|DoGreen|DoBlue;
|
|
|
|
bg_map = (unsigned char *)malloc(width * height);
|
|
}
|
|
|
|
/* Now delete the file. */
|
|
unlink(fnam);
|
|
{
|
|
char *hfnam = (char *)malloc ((strlen (fnam) + strlen(".html") + 5) * sizeof (char));
|
|
sprintf (hfnam, "%s.html", fnam);
|
|
unlink(hfnam);
|
|
free(hfnam);
|
|
}
|
|
|
|
if (w) {
|
|
free (fnam);
|
|
}
|
|
|
|
if (data == NULL)
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr, "[ImageResolve] data == NULL; punting...\n");
|
|
#endif
|
|
|
|
return NULL;
|
|
}
|
|
|
|
{
|
|
int found_bg=0;
|
|
|
|
if (data!=NULL) {
|
|
for (i=0; i<width*height; i++) {
|
|
if ((int)(data[i])==bg) {
|
|
found_bg=1;
|
|
break;
|
|
}
|
|
}
|
|
if (!found_bg) {
|
|
bg=(-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
img_data = (ImageInfo *)malloc(sizeof(ImageInfo));
|
|
if ((bg >= 0)&&(data != NULL) &&
|
|
get_pref_boolean(eCLIPPING) &&
|
|
(get_pref_int(eMAX_CLIPPING_SIZE_X)==(-1) ||
|
|
get_pref_int(eMAX_CLIPPING_SIZE_X)>=width) &&
|
|
(get_pref_int(eMAX_CLIPPING_SIZE_Y)==(-1) ||
|
|
get_pref_int(eMAX_CLIPPING_SIZE_Y)>=height)) {
|
|
img_data->transparent=1;
|
|
img_data->clip_data=(unsigned char *)malloc(width * height);
|
|
memset(img_data->clip_data,0,(width*height));
|
|
img_data->bg_index=bg;
|
|
}
|
|
else {
|
|
img_data->transparent=0;
|
|
img_data->clip_data=NULL;
|
|
img_data->bg_index=(-1);
|
|
}
|
|
|
|
img_data->width = width;
|
|
img_data->height = height;
|
|
img_data->image_data = data;
|
|
img_data->image = 0;
|
|
img_data->clip = 0;
|
|
img_data->src = strdup(src);
|
|
/* Bandaid for bug afflicting Eric's code, apparently. */
|
|
img_data->internal = 0;
|
|
}
|
|
|
|
widthbyheight = img_data->width * img_data->height;
|
|
|
|
/* Fill out used array. */
|
|
for (i=0; i < 256; i++) {
|
|
Used[i] = 0;
|
|
}
|
|
|
|
cnt = 1;
|
|
bgptr = bg_map;
|
|
cptr = img_data->clip_data;
|
|
ptr = img_data->image_data;
|
|
|
|
/*This sets the bg map and also creates bitmap data for the
|
|
clip mask when there is a bg image */
|
|
for (i=0; i<img_data->height; i++) {
|
|
for (j=0,bcnt=0; j<img_data->width; j++) {
|
|
if (Used[(int)*ptr] == 0) {
|
|
Used[(int)*ptr] = cnt;
|
|
cnt++;
|
|
}
|
|
if (bg>=0) {
|
|
if (*ptr == bg) {
|
|
*bgptr = 1;
|
|
}
|
|
else {
|
|
*bgptr = 0;
|
|
if (img_data->transparent) {
|
|
*cptr += nums[(bcnt % 8)];
|
|
}
|
|
}
|
|
if (img_data->transparent &&
|
|
((bcnt % 8)==7 ||
|
|
j==(img_data->width-1))) {
|
|
cptr++;
|
|
}
|
|
bgptr++;
|
|
bcnt++;
|
|
}
|
|
ptr++;
|
|
}
|
|
}
|
|
cnt--;
|
|
|
|
/*
|
|
* If the image has too many colors, apply a median cut algorithm to
|
|
* reduce the color usage, and then reprocess it.
|
|
* Don't cut colors for direct mapped visuals like TrueColor.
|
|
*/
|
|
if ((cnt > get_pref_int(eCOLORS_PER_INLINED_IMAGE))&&(Vclass != TrueColor))
|
|
{
|
|
MedianCut(img_data->image_data, &img_data->width,
|
|
&img_data->height, colrs, 256,
|
|
get_pref_int(eCOLORS_PER_INLINED_IMAGE));
|
|
|
|
for (i=0; i < 256; i++)
|
|
Used[i] = 0;
|
|
cnt = 1;
|
|
ptr = img_data->image_data;
|
|
for (i=0; i < widthbyheight; i++)
|
|
{
|
|
if (Used[(int)*ptr] == 0)
|
|
{
|
|
Used[(int)*ptr] = cnt;
|
|
cnt++;
|
|
}
|
|
ptr++;
|
|
}
|
|
cnt--;
|
|
|
|
/* if we had a transparent bg, MedianCut used it. Get a new one */
|
|
if (bg >= 0)
|
|
{
|
|
cnt++;
|
|
bg = 256;
|
|
}
|
|
}
|
|
|
|
img_data->num_colors = cnt;
|
|
|
|
#ifdef HAVE_HDF
|
|
if (!ishdf)
|
|
#endif
|
|
{
|
|
img_data->reds = (int *)malloc(sizeof(int) * cnt);
|
|
img_data->greens = (int *)malloc(sizeof(int) * cnt);
|
|
img_data->blues = (int *)malloc(sizeof(int) * cnt);
|
|
}
|
|
|
|
/* bg is not set in here if it gets munged by MedCut */
|
|
for (i=0; i < 256; i++)
|
|
{
|
|
int indx;
|
|
|
|
if (Used[i] != 0)
|
|
{
|
|
indx = Used[i] - 1;
|
|
img_data->reds[indx] = colrs[i].red;
|
|
img_data->greens[indx] = colrs[i].green;
|
|
img_data->blues[indx] = colrs[i].blue;
|
|
/* squeegee in the background color */
|
|
if ((bg >= 0)&&(i == bg))
|
|
{
|
|
img_data->reds[indx] = bg_red;
|
|
img_data->greens[indx] = bg_green;
|
|
img_data->blues[indx] = bg_blue;
|
|
img_data->bg_index=indx;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* if MedianCut ate our background, add the new one now. */
|
|
if (bg == 256)
|
|
{
|
|
img_data->reds[cnt - 1] = bg_red;
|
|
img_data->greens[cnt - 1] = bg_green;
|
|
img_data->blues[cnt - 1] = bg_blue;
|
|
img_data->bg_index=(cnt-1);
|
|
}
|
|
|
|
bgptr = bg_map;
|
|
cptr = img_data->clip_data;
|
|
ptr = img_data->image_data;
|
|
for (i=0; i < widthbyheight; i++)
|
|
{
|
|
*ptr = (unsigned char)(Used[(int)*ptr] - 1);
|
|
/* if MedianCut ate the background, enforce it here */
|
|
if (bg == 256)
|
|
{
|
|
if (*bgptr)
|
|
{
|
|
*ptr = (unsigned char)(cnt - 1);
|
|
}
|
|
bgptr++;
|
|
}
|
|
ptr++;
|
|
}
|
|
|
|
/* free the background map if we have one */
|
|
if (bg_map != NULL)
|
|
{
|
|
free (bg_map);
|
|
}
|
|
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr, "[ImageResolve] Doing mo_cache_data on '%s', 0x%08x\n",
|
|
src, img_data);
|
|
#endif
|
|
|
|
mo_cache_data (src, (void *)img_data, 0);
|
|
|
|
free (src);
|
|
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr, "[ImageResolve] Leaving...\n");
|
|
#endif
|
|
|
|
if (cci_event) MoCCISendEventOutput(IMAGE_LOADED);
|
|
|
|
return img_data;
|
|
/*
|
|
if (!wid && !hei) {
|
|
return img_data;
|
|
}
|
|
|
|
return(scaleImage(img_data,wid,hei));
|
|
*/
|
|
}
|
|
|
|
static ImageInfo *DelayedImageResolve (Widget w, char *src)
|
|
{
|
|
ImageInfo *img;
|
|
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr, "[DelayedImageResolve] I'm entering, src '%s'\n", src);
|
|
#endif
|
|
|
|
interrupted = 0;
|
|
|
|
loading_inlined_images = 1;
|
|
img = ImageResolve (w, src, 0, NULL, NULL);
|
|
loading_inlined_images = 0;
|
|
|
|
if (interrupted == 1)
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr, "[DelayedImageResolve] Interrupted...\n");
|
|
#endif
|
|
|
|
interrupted = 0;
|
|
}
|
|
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr, "[DelayedImageResolve] Returning 0x%08x\n", img);
|
|
#endif
|
|
|
|
/* need this here now...but may make other stuff look cheeeezy -- SWP */
|
|
mo_gui_done_with_icon ();
|
|
mo_gui_check_icon(-1);
|
|
|
|
return img;
|
|
}
|
|
|
|
mo_status mo_free_image_data (void *ptr)
|
|
{
|
|
ImageInfo *img = (ImageInfo *)ptr;
|
|
Widget swin=current_win->scrolled_win;
|
|
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace)
|
|
fprintf (stderr, "[mo_free_image_info] Freeing 0x%08x\n", img);
|
|
#endif
|
|
|
|
if (!img)
|
|
return mo_fail;
|
|
|
|
if (img->reds)
|
|
{
|
|
free (img->reds);
|
|
img->reds = NULL;
|
|
}
|
|
if (img->greens)
|
|
{
|
|
free (img->greens);
|
|
img->greens = NULL;
|
|
}
|
|
if (img->blues)
|
|
{
|
|
free (img->blues);
|
|
img->blues = NULL;
|
|
}
|
|
if (img->image_data)
|
|
{
|
|
free (img->image_data);
|
|
img->image_data = NULL;
|
|
}
|
|
if (img->clip_data) {
|
|
free (img->clip_data);
|
|
img->clip_data = NULL;
|
|
}
|
|
if (img->src) {
|
|
free(img->src);
|
|
img->src=NULL;
|
|
}
|
|
if (img->image!=None) {
|
|
XFreePixmap(XtDisplay(swin),img->image);
|
|
img->image=None;
|
|
}
|
|
if (img->clip!=None) {
|
|
XFreePixmap(XtDisplay(swin),img->clip);
|
|
img->clip=None;
|
|
}
|
|
|
|
return mo_succeed;
|
|
}
|
|
|
|
mo_status mo_register_image_resolution_function (mo_window *win)
|
|
{
|
|
XmxSetArg (WbNresolveImageFunction, (long)ImageResolve);
|
|
XmxSetArg (WbNresolveDelayedImage, (long)DelayedImageResolve);
|
|
XmxSetValues (win->scrolled_win);
|
|
return mo_succeed;
|
|
}
|
|
|