/***** * readBitmap.c : XmHTML X11 bitmap image loading routines * * This file Version $Revision: 1.6 $ * * Creation date: Wed Feb 19 03:32:58 GMT+0100 1997 * Last modification: $Date: 1999/07/29 01:26:29 $ * By: $Author: sopwith $ * Current State: $State: Exp $ * * Author: newt * * Copyright (C) 1994-1997 by Ripley Software Development * All Rights Reserved * * This file is part of the XmHTML Widget Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *****/ /***** * ChangeLog * $Log: readBitmap.c,v $ * Revision 1.6 1999/07/29 01:26:29 sopwith * * * Fix all warnings. * * Revision 1.5 1998/02/12 03:09:44 unammx * Merge to Koen's XmHTML 1.1.2 + following fixes: * * Wed Feb 11 20:27:19 1998 Miguel de Icaza * * * gtk-forms.c (freeForm): gtk_destroy_widget is no longer needed * with the refcounting changes. * * * gtk-xmhtml.c (gtk_xmhtml_remove): Only god knows why I was * adding the just removed widget. * * Revision 1.4 1998/01/14 04:12:10 unammx * Tue Jan 13 22:04:43 1998 Federico Mena * * * Lots of changes all over the place to fix colors. Things are * *almost* working right now. I think I'm only missing setting the * window backgrounds appropriately. Several things were done: * * - Motif's color and gc fields from Core and XmManager were * replicated inside the GtkXmHTML widget structure. * * - Macros were created in toolkit.h to use these fields. * * - Instead of the old kludgy set_{fore,back}ground_internal * functions, we now set the window background directly. * This does not work perfectly; I'll look into it. * * - I created a shade_color() function in colors.c (ok, ok, * I stole it from gtkstyle.c) which mimics XmGetColors() * -- it calculates shaded colors for the 3D look. * * I hope to fix the remaining problems with window backgrounds real * soon now. * * Revision 1.3 1998/01/07 01:45:40 unammx * Gtk/XmHTML is ready to be used by the Gnome hackers now! * Weeeeeee! * * This afternoon: * * - Changes to integrate gtk-xmhtml into an autoconf setup. * * - Changes to make gtk-xmhtml a library to be used by Gnome * (simply include #endif #include #include /* prevent Byte re-declaration */ #if defined(HAVE_LIBPNG) || defined(HAVE_LIBZ) #include #endif #include "XmHTMLP.h" #include "XmHTMLfuncs.h" #include "plc.h" /*** External Function Prototype Declarations ***/ /*** Public Variable Declarations ***/ Byte bitmap_bits[8] = { 1, 2, 4, 8, 16, 32, 64, 128 }; /*** Private Datatype Declarations ****/ /*** Private Function Prototype Declarations ****/ /*** Private Variable Declarations ***/ #define MAX_LINE 81 /***** * Name: bgets * Return Type: String * Description: memory buffer version of fgets * In: * buf: character buffer * max_len: max chars to read * ib: memory buffer * Returns: * buf filled with at most max_len - 1 characters or NULL on end-of-buffer. *****/ static String bgets(String buf, int max_len, ImageBuffer *ib) { Byte *chPtr; int len = 0; if(ib->size > ib->next) { chPtr = ib->buffer + ib->next; while(True) { if(len < max_len-1 && *chPtr != '\0' && *chPtr != '\n' && ib->next + len < ib->size) { len++; chPtr++; } else break; } /* must include terminating character as well */ if(*chPtr == '\n' || *chPtr == '\0') len++; (void)memcpy(buf, ib->buffer + ib->next, len); buf[len] = '\0'; /* NULL terminate */ ib->next += len; return(buf); } return(NULL); } /***** * Name: _XmHTMLReadBitmap * Return Type: XmHTMLRawImageData* * Description: X11 Bitmap reading routine * In: * * Returns: * loaded image data * Note: * Can't use any of the X[]Bitmap[] functions since we require the image data * to be in ZPixmap format. *****/ XmHTMLRawImageData* _XmHTMLReadBitmap(TWidget html, ImageBuffer *ib) { char line[MAX_LINE], name_and_type[MAX_LINE], *t; Byte *ptr; int cnt = 0, lim, bytes_per_line, raster_length; int i, bytes, value, blackbit, whitebit, width = 0, height = 0; unsigned long fg_pixel, bg_pixel; TColor fg_color, bg_color; TWidget area; TColormap cmap; static XmHTMLRawImageData *img_data; area = (XmHTML (html))->html.work_area; _XmHTMLDebug(15, ("_XmHTMLReadBitmap: start, file is %s\n", ib->file)); /* Initialize image data */ ib->depth = 2; /* check bitmap header */ for( ; ; ) { if(!(bgets(line, MAX_LINE, ib))) break; /* see if we have successfully read a line */ if(strlen(line) == (MAX_LINE - 1)) { /* probably not an xbm image, just return. */ _XmHTMLDebug(15, ("_XmHTMLReadBitmap: end, not a xbm image\n")); return((XmHTMLRawImageData*)NULL); } /* check for xpm */ if(!(strcmp(line, "//* XPM *//"))) { /* an xpm pixmap, return */ return((XmHTMLRawImageData*)NULL); } /* get width and height for this bitmap */ if(sscanf(line, "#define %s %d", name_and_type, &value) == 2) { if (!(t = strrchr(name_and_type, '_'))) t = name_and_type; else t++; if (!strcmp("width", t)) width = value; if (!strcmp("height", t)) height = value; continue; } if(((sscanf(line, "static short %s = {", name_and_type)) == 1) || ((sscanf(line,"static char * %s = {", name_and_type)) == 1)) { /* not a bitmap, return */ return((XmHTMLRawImageData*)NULL); } /* last line of the bitmap header */ if(sscanf(line,"static char %s = [",name_and_type) == 1) break; } /* bitmap has invalid dimension(s) */ if(width == 0 || height == 0) return((XmHTMLRawImageData*)NULL); _XmHTMLDebug(15, ("readXbmBitmap: %s is plain X11 bitmap.\n", ib->file)); /* allocate image */ AllocRawImageWithCmap(img_data, width, height, 2); img_data->color_class = XmIMAGE_COLORSPACE_GRAYSCALE; img_data->bg = -1; #ifdef WITH_MOTIF /* Get the fore- and background pixels. */ XtVaGetValues(area, XtNforeground, &fg_pixel, XtNbackground, &bg_pixel, NULL); /* Get corresponding XColor values */ fg_color.pixel = fg_pixel; bg_color.pixel = bg_pixel; /* get display colormap */ if(XmIsHTML(html)) cmap = (XmHTML (html))->core.colormap; else /* every TWidget is derived from core */ XtVaGetValues(html, XmNcolormap, &cmap, NULL); /* fill image colormap */ XQueryColor(XtDisplay(area), cmap, &fg_color); XQueryColor(XtDisplay(area), cmap, &bg_color); #else /* FIXME: I don't know if getting the colors from the macros * will be quite the same as getting them from the Xt * resources as above. */ fg_pixel = Toolkit_StyleColor_Foreground (html); bg_pixel = Toolkit_StyleColor_Background (html); fg_color.pixel = fg_pixel; bg_color.pixel = bg_pixel; cmap = gtk_widget_get_colormap (html); my_x_query_colors (cmap, &fg_color, 1); my_x_query_colors (cmap, &bg_color, 1); #endif blackbit = 0; /* fg_color.pixel; */ whitebit = 1; /* bg_color.pixel; */ img_data->cmap[0].red = fg_color.red >> 8; img_data->cmap[0].green = fg_color.green >> 8; img_data->cmap[0].blue = fg_color.blue >> 8; img_data->cmap[0].pixel = fg_color.pixel; img_data->cmap[1].red = bg_color.red >> 8; img_data->cmap[1].green = bg_color.green >> 8; img_data->cmap[1].blue = bg_color.blue >> 8; img_data->cmap[1].pixel = bg_color.pixel; bytes_per_line = ((img_data->width + 7) / 8); /* size of a scan line */ raster_length = bytes_per_line * img_data->height; /* read bitmap data */ ptr = img_data->data; lim = bytes_per_line * 8; for(bytes = 0; bytes < raster_length; bytes++) { String chPtr, elePtr; if(!(bgets(line, MAX_LINE, ib))) break; elePtr = line; while((chPtr = strstr(elePtr, ",")) != NULL) { if(sscanf(elePtr, " 0x%x%*[,}]%*[ \r\n]", &value) != 1) { _XmHTMLDebug(15, ("readXbmBitmap: end, unexpected end of " "data.\n")); FreeRawImage(img_data); return((XmHTMLRawImageData*)NULL); } for(i = 0; i < 8; i++) { if(cnt < (img_data->width)) { if(value & bitmap_bits[i]) *ptr++ = blackbit; else *ptr++ = whitebit; } if(++cnt >= lim) cnt = 0; } elePtr = chPtr + 1; } } _XmHTMLDebug(15, ("_XmHTMLReadBitmap: end, %s loaded\n", ib->file)); return(img_data); } /***** * Progressive Bitmap loading routines *****/ static int _PLC_XBM_bgets(String buf, int max_len, PLC *plc) { Byte *chPtr; int len = 0; PLCImageXBM *xbm = &(plc->object->plc_xbm_image); if(xbm->buf_pos < xbm->byte_count) { chPtr = xbm->buffer + xbm->buf_pos; while(True) { if(len < max_len-1 && *chPtr != '\0' && *chPtr != '\n' && *chPtr != '}' && xbm->buf_pos + len < xbm->byte_count) { len++; chPtr++; } else break; } /* must include terminating character as well */ if(*chPtr == '\n' || *chPtr == '}' || *chPtr == '\0') len++; (void)memcpy(buf, xbm->buffer + xbm->buf_pos, len); buf[len] = '\0'; /* NULL terminate */ xbm->buf_pos += len; return(len); } /* not enough data, make a new request */ plc->min_in = 0; plc->max_in = plc->input_size; (void)_PLCDataRequest(plc); return(0); } void _PLC_XBM_Init(PLC *plc) { char line[MAX_LINE], name_and_type[MAX_LINE], *t; int value, width = 0, height = 0, len; unsigned long fg_pixel, bg_pixel; TColor fg_color, bg_color; TWidget area; TColormap cmap; PLCImageXBM *xbm; _XmHTMLDebug(15, ("plc.c: _PLC_XBM_Init for %s\n", plc->url)); /* this plc is active */ plc->plc_status = PLC_ACTIVE; xbm = &(plc->object->plc_xbm_image); area = xbm->owner->html.work_area; /* rewind input buffers, it may not be the first time we are doing this */ _PLCRewindInputBuffer(plc); /***** * We don't know how large the raw data will be at this point, allocate * a default buffer so we can get at least the initial image data *****/ if(xbm->buf_size == 0) { xbm->buf_size = PLC_MAX_BUFFER_SIZE; xbm->buffer = (Byte*)calloc(xbm->buf_size, sizeof(Byte)); } /* read some more data, appending at data we have already read */ if(xbm->buf_pos >= xbm->byte_count) { /* read data from input but not more than we can take */ if((value = plc->left) > (xbm->buf_size - xbm->byte_count)) value = xbm->buf_size - xbm->byte_count; if((len = _PLCReadOK(plc, xbm->buffer + xbm->byte_count, value)) == 0) return; /* end of data, suspended or aborted */ xbm->byte_count += len; } /* rewind input buffer */ xbm->buf_pos = 0; /* check bitmap header */ for( ; ; ) { if((len = _PLC_XBM_bgets(line, MAX_LINE, plc)) == 0) return; /* see if we have successfully read a line */ if(len == (MAX_LINE - 1)) { /* probably not an xbm image, just return. */ _XmHTMLDebug(15, ("_XmHTMLReadBitmap: end, not a xbm image\n")); plc->plc_status = PLC_ABORT; return; } /* check for xpm */ if(!(strcmp(line, "//* XPM *//"))) { /* an xpm pixmap, return */ plc->plc_status = PLC_ABORT; return; } /* get width and height for this bitmap */ if(sscanf(line, "#define %s %d", name_and_type, &value) == 2) { if (!(t = strrchr(name_and_type, '_'))) t = name_and_type; else t++; if (!strcmp("width", t)) width = value; if (!strcmp("height", t)) height = value; continue; } if(((sscanf(line, "static short %s = {", name_and_type)) == 1) || ((sscanf(line,"static char * %s = {", name_and_type)) == 1)) { /* not a bitmap, return */ plc->plc_status = PLC_ABORT; return; } /* last line of the bitmap header */ if(sscanf(line,"static char %s = [",name_and_type) == 1) break; } /* start of real image data */ xbm->data_start = xbm->buf_pos; /* bitmap has invalid dimension(s) */ if(width == 0 || height == 0) { plc->plc_status = PLC_ABORT; return; } xbm->width = width; xbm->height = height; /* two-color grayscale image */ xbm->colorclass = XmIMAGE_COLORSPACE_GRAYSCALE; xbm->cmapsize = 2; xbm->cmap = (TColor*)calloc(xbm->cmapsize, sizeof(TColor)); /* image is initially fully opaque */ xbm->transparency = XmHTML_NONE; xbm->bg_pixel = -1; /***** * Resize incoming data buffer but don't touch buf_pos and byte_count * as the buffer already contains data *****/ xbm->buf_size = xbm->width * xbm->height; xbm->buffer = (Byte*)realloc(xbm->buffer, xbm->buf_size * sizeof(Byte)); /* image data buffer. */ xbm->data_size = xbm->width*xbm->height; xbm->data_pos = 0; xbm->prev_pos = 0; xbm->data = (Byte*)calloc(xbm->data_size + 1, sizeof(Byte)); #ifdef WITH_MOTIF /* Get the fore- and background pixels. */ XtVaGetValues(area, XtNforeground, &fg_pixel, XtNbackground, &bg_pixel, NULL); /* Get corresponding XColor values */ fg_color.pixel = fg_pixel; bg_color.pixel = bg_pixel; /* get display colormap */ cmap = xbm->owner->core.colormap; /* fill image colormap */ XQueryColor(XtDisplay(area), cmap, &fg_color); XQueryColor(XtDisplay(area), cmap, &bg_color); #else /* FIXME: I don't know if getting the colors from the macros * will be quite the same as getting them from the Xt * resources as above. */ fg_pixel = Toolkit_StyleColor_Foreground (xbm->owner); bg_pixel = Toolkit_StyleColor_Background (xbm->owner); fg_color.pixel = fg_pixel; bg_color.pixel = bg_pixel; cmap = gtk_widget_get_colormap (GTK_WIDGET (xbm->owner)); my_x_query_colors (cmap, &fg_color, 1); my_x_query_colors (cmap, &bg_color, 1); #endif xbm->cmap[0].red = fg_color.red; xbm->cmap[0].green = fg_color.green; xbm->cmap[0].blue = fg_color.blue; xbm->cmap[0].pixel = fg_color.pixel; xbm->cmap[1].red = bg_color.red; xbm->cmap[1].green = bg_color.green; xbm->cmap[1].blue = bg_color.blue; xbm->cmap[1].pixel = bg_color.pixel; /* no of bytes per line for this bitmap */ xbm->stride = ((xbm->width + 7) / 8); /* full raw data size */ xbm->raster_length = xbm->stride * xbm->height; /* object has been initialized */ plc->initialized = True; plc->curr_obj_func = 0; /* move to XBM scanline reader */ } void _PLC_XBM_ScanlineProc(PLC *plc) { char line[MAX_LINE]; Byte *ptr; int lim, i, value, bytes, len = 0, cnt = 0; PLCImageXBM *xbm; _XmHTMLDebug(15, ("plc.c: _PLC_XBM_ScanlineProc for %s\n", plc->url)); xbm = &(plc->object->plc_xbm_image); /* all data in buffer has been consumed, get some more */ if(xbm->buf_pos >= xbm->byte_count) { if((value = plc->left) > (xbm->buf_size - xbm->byte_count)) value = xbm->buf_size - xbm->byte_count; /* append at current position */ if((len = _PLCReadOK(plc, xbm->buffer + xbm->byte_count, value)) == 0) return; /* end of data, suspended or aborted */ /* new data length */ xbm->byte_count += len; } /* raw image data start */ xbm->buf_pos = xbm->data_start; /* decoded image data start */ ptr = xbm->data; xbm->data_pos = 0; lim = xbm->stride * 8; for(bytes = 0; bytes < xbm->raster_length && xbm->data_pos < xbm->data_size; bytes++) { String chPtr, elePtr; /* read a new line of data */ if((len = _PLC_XBM_bgets(line, MAX_LINE, plc)) == 0) { /* last known full scanline */ xbm->data_pos = (xbm->data_pos > xbm->data_size ? xbm->data_size : xbm->data_pos); /* all data processed */ if(plc->plc_data_status == STREAM_END) break; return; /* suspended or aborted */ } elePtr = line; while((chPtr = strstr(elePtr, ",")) != NULL) { if(sscanf(elePtr, " 0x%x%*[,}]%*[ \r\n]", &value) != 1) { _XmHTMLDebug(15, ("_PLC_XBM_ScanlineProc: unexpected end of " "data.\n")); plc->plc_status = PLC_ABORT; return; } for(i = 0; i < 8; i++) { if(cnt < xbm->width) { if(value & bitmap_bits[i]) *ptr++ = 0; /* blackbit */ else *ptr++ = 1; /* whitebit */ xbm->data_pos++; } /* processed a full scanline */ if(++cnt >= lim) cnt = 0; } elePtr = chPtr + 1; } } /* done with this image */ plc->obj_funcs_complete = True; } void _PLC_XBM_Destructor(PLC *plc) { /* nothing special for XBM */ }