/* Copyright 1989 GROUPE BULL -- See license conditions in file COPYRIGHT * Copyright 1989 Massachusetts Institute of Technology */ /***********************\ * * * WOOL_OBJECT: Pixmap * * BODY * * * \***********************/ #define INCLUDE_PIXMAP_H #include #include "EXTERN.h" #include #include #include "wool.h" #include "wl_string.h" #include "wl_atom.h" #include "wl_pointer.h" #include "wl_active.h" #include "wl_number.h" #include "wl_label.h" #include "wl_list.h" #include "gwm.h" #include #include #include "INTERN.h" #undef INCLUDE_PIXMAP_H #include "wl_pixmap.h" #include "def_bitmap.h" /* local prototyping */ WOOL_OBJECT wool_default_bitmap_make(); WOOL_OBJECT wool_default_pixmap_make(); /* when debugging, maintain the screen to which belongs the pixmap */ #ifdef DEBUG #define StorePixmapScreen(pixmap, root) \ pixmap -> screen = ScreenOfRoot(root) #else #define StorePixmapScreen(pixmap, root) #endif /* DEBUG */ /* * makes a WOOL pixmap out of a X11 bitmap (or appropriate depth pixmap) */ WOOL_Pixmap WLPixmap_make(pixmap) Pixmap pixmap; { WOOL_Pixmap object = (WOOL_Pixmap) Malloc(sizeof(struct _WOOL_Pixmap)); unsigned int bw, depth; Window root; zrt_put(object); object -> type = WLPixmap; object->mask = 0; XGetGeometry(dpy, pixmap, &root, &object -> x_hot, &object -> y_hot, &object -> width, &object -> height, &bw, &depth); if (!object -> width || !object -> height || !depth) { /* ERROR */ wool_default_pixmap_make(object, "invalid pixmap %s", "size"); } else if (depth == 1) { /* BITMAP */ Trace('p', ("WLPixmap_make: create pixmap %d %d %d\n", object -> width, object -> height, Context->depth)); object -> pixmap = XCreatePixmap(dpy, Context->root, object -> width, object -> height, Context->depth); XSetForeground(dpy, Context->gc.Work, Context -> pixel.Back); XFillRectangle(dpy, object -> pixmap, Context->gc.Work, 0, 0, object -> width, object -> height); XSetForeground(dpy, Context->gc.Set, Context -> pixel.Fore); XSetStipple(dpy, Context->gc.Set, pixmap); XFillRectangle(dpy, object -> pixmap, Context->gc.Set, 0, 0, object -> width, object -> height); } else if (depth == Context->depth) { /* PIXMAP */ Trace('p', ("WLPixmap_make: create pixmap %d %d %d\n", object -> width, object -> height, Context->depth)); object -> pixmap = XCreatePixmap(dpy, Context->root, object -> width, object -> height, Context->depth); XCopyArea(dpy, pixmap, object->pixmap, Context->gc.Work, 0, 0, object->width, object->height, 0, 0); } else { /* ERROR */ wool_default_pixmap_make(object, "Pixmap is of depth %d", depth); } StorePixmapScreen(object, root); return object; } /* * the physical reading of a bitmap. Used for bitmaps & cursors * if parameter is a label returns it! */ WOOL_OBJECT wool_raw_bitmap_make(filename) WOOL_String filename; { char *name; WOOL_Pixmap object; char temp_filename[MAX_TEMP_STRING_SIZE]; must_be_string(filename, 0); object = (WOOL_Pixmap) Malloc(sizeof(struct _WOOL_Pixmap)); zrt_put(object); object -> type = WLPixmap; object->mask = 0; name = (char *) file_in_path(filename -> string, BITMAP_EXTENSION, wool_path, temp_filename); if (!name) { return wool_default_bitmap_make(object, "GWM: Cannot find Bitmap %s", filename -> string); } switch (XReadBitmapFile(dpy, Context->root, name, &object -> width, &object -> height, &object -> pixmap, &object -> x_hot, &object -> y_hot)) { case BitmapOpenFailed: return wool_default_bitmap_make(object, "Cannot open file %s", name); case BitmapFileInvalid: return wool_default_bitmap_make(object, "File %s is not a bitmap", name); case BitmapNoMemory: wool_error("No memory to load file %s", name); break; } return (WOOL_OBJECT) object; } /* Given a pre-allocated WOOL_Pixmap, fill it with the default * bitmap or pixmap, rexpectively */ WOOL_OBJECT wool_default_bitmap_make(object, reason_format, reason) WOOL_Pixmap object; /* empty wool structure */ char *reason_format; /* text of the error message or 0 */ char *reason; /* data for %s in reason format */ { if (reason_format) { wool_printf(reason_format, reason); wool_puts(", using default instead\n"); } object -> width = def_bitmap_width; object -> height = def_bitmap_height; object -> x_hot = def_bitmap_x_hot; object -> y_hot = def_bitmap_y_hot; object -> pixmap = Context -> DefaultBitmap; return (WOOL_OBJECT) object; } WOOL_OBJECT wool_default_pixmap_make(object, reason_format, reason) WOOL_Pixmap object; /* empty wool structure */ char *reason_format; /* text of the error message or 0 */ char *reason; /* data for %s in reason format */ { if (reason_format) { wool_printf(reason_format, reason); wool_puts(", using default instead\n"); } object -> width = def_bitmap_width; object -> height = def_bitmap_height; XSetForeground(dpy, Context->gc.Work, Context -> pixel.Back); Trace('p', ("wool_default_pixmap_make: create pixmap %d %d %d\n", object -> width, object -> height, Context->depth)); object -> pixmap = XCreatePixmap(dpy, Context->root, object -> width, object -> height, Context->depth); XFillRectangle(dpy, object -> pixmap, Context->gc.Work, 0, 0, object -> width, object -> height); XSetForeground(dpy, Context->gc.Set, Context -> pixel.Fore); XSetStipple(dpy, Context->gc.Set, Context -> DefaultBitmap); XFillRectangle(dpy, object -> pixmap, Context->gc.Set, 0, 0, object -> width, object -> height); StorePixmapScreen(object, Context -> root); return (WOOL_OBJECT) object; } /* * to overlay bitmaps: * (layered-bitmap-make back "file1" color1 "file2" color2 ...) * filenames can be active-labels */ WOOL_Pixmap wool_layered_bitmap_make(argc, argv) int argc; WOOL_Pixmap argv[]; { Pixmap pix; int i; unsigned int width = 0, height = 0; WOOL_Pixmap object; struct _Box box; WOOL_Label label; Graphic_desc *graphics; if ((argc == 0) || (argc > 2 && (argc % 2 == 0))) wool_error(BAD_NUMBER_OF_ARGS, argc); if (argc == 1) { /* one args re-calls with default colors */ WOOL_Number new_argv[3]; new_argv[0] = WLNumber_make(Context -> pixel.Back); new_argv[2] = WLNumber_make(Context -> pixel.Fore); new_argv[1] = (WOOL_Number) argv[0]; return (WOOL_Pixmap) wool_layered_bitmap_make(3, new_argv); } if (argc == 2) { /* two args make a blank bitmaps */ return wool_make_blank_bitmap(argv[0], argv[1]); } /* multi-args form */ must_be_number(argv[0], 0); must_be_number(argv[2], 2); graphics = (Graphic_desc *) Malloc(sizeof(Graphic_desc) * argc); /* first determine the size of the final pixmap and load the bitmaps */ for (i = 1; i < argc; i += 2) { if (is_a_string(argv[i])) { graphics[i].is_bitmap = 1; argv[i] = (WOOL_Pixmap) wool_raw_bitmap_make(argv[i]); } else { graphics[i].is_bitmap = 0; } WOOL_send(WOOL_get_dimensions, argv[i], (argv[i], &box)); graphics[i].width = box.width; graphics[i].height = box.height; width = Max(width, box.width); height = Max(height, box.height); } /* then lay the graphics one on top of another */ XSetForeground(dpy, Context->gc.Work, ((WOOL_Number) argv[0]) -> number); Trace('p', ("wool_layered_bitmap_make: create pixmap %d %d %d\n", width, height, Context->depth)); pix = XCreatePixmap(dpy, Context->root, width, height, Context->depth); XFillRectangle(dpy, pix, Context->gc.Work, 0, 0, width, height); for (i = 1; i < argc; i += 2) { must_be_number(argv[i + 1], i + 1); if (graphics[i].is_bitmap) { XSetForeground(dpy, Context->gc.Set, ((WOOL_Number) argv[i + 1]) -> number); XSetStipple(dpy, Context->gc.Set, argv[i] -> pixmap); XSetTSOrigin(dpy, Context->gc.Set, (width - argv[i] -> width) / 2, (height - argv[i] -> height) / 2); XFillRectangle(dpy, pix, Context->gc.Set, (width - argv[i] -> width) / 2, (height - argv[i] -> height) / 2, argv[i] -> width, argv[i] -> height); XSetTSOrigin(dpy, Context->gc.Set, 0, 0); } else if (argv[i] -> type == WLPixmap) { XCopyArea(dpy, argv[i] -> pixmap, pix, Context->gc.Work, 0, 0, argv[i] -> width, argv[i] -> height, (width - argv[i] -> width) / 2, (height - argv[i] -> height) / 2); } else if (argv[i] -> type == WLLabel) { /* label */ label = (WOOL_Label) argv[i]; XSetFont(dpy, Context->gc.Work, label -> font); XSetForeground(dpy, Context->gc.Work, ((WOOL_Number) argv[i + 1]) -> number); XDrawString(dpy, pix, Context->gc.Work, label -> x, label -> y, label -> label -> string, strlen(label -> label -> string)); } } /* then creates the WOOL_Pixmap */ object = (WOOL_Pixmap) Malloc(sizeof(struct _WOOL_Pixmap)); zrt_put(object); object -> type = WLPixmap; object->mask = 0; object -> pixmap = pix; object -> x_hot = object -> y_hot = 0; object -> width = width; object -> height = height; Free(graphics); StorePixmapScreen(object, Context -> root); return object; } /* * makes a pixmap of "foreground" color of a given size */ WOOL_Pixmap wool_make_blank_bitmap(width, height) WOOL_Number width; WOOL_Number height; { WOOL_Pixmap object; Pixmap pix; WOOL_Pixmap tile; get_val_from_context(tile, WA_tile); Trace('p', ("wool_make_blank_bitmap: create pixmap %d %d %d\n", width -> number, height -> number, Context->depth)); pix = XCreatePixmap(dpy, Context->root, width -> number, height -> number, Context->depth); if (tile->type != WLPixmap) { /* no tile = use solid color */ XSetForeground(dpy, Context->gc.Work, Context -> pixel.Fore); XFillRectangle(dpy, pix, Context->gc.Work, 0, 0, width -> number, height -> number); } else { /* tile overrides color */ XSetTile(dpy, Context->gc.Tile, tile->pixmap); XFillRectangle(dpy, pix, Context->gc.Tile, 0, 0, width -> number, height -> number); } object = (WOOL_Pixmap) Malloc(sizeof(struct _WOOL_Pixmap)); zrt_put(object); object -> type = WLPixmap; object->mask = 0; object -> pixmap = pix; object -> x_hot = object -> y_hot = 0; object -> width = width -> number; object -> height = height -> number; StorePixmapScreen(object, Context -> root); return object; } /* * A stamp is a string "stamped" on the background to yield a bitmap */ WOOL_OBJECT wool_stamp_make(argc, argv) int argc; WOOL_String argv[]; { int up, down, dir, x, y, width, height, font; XCharStruct extent; WOOL_Pixmap object; if (argc == 0 || argc > 2) return wool_error(BAD_NUMBER_OF_ARGS, argc); must_be_string(argv[0], 0); if (argc == 2) { must_be_number(argv[1], 1); font = ((WOOL_Number) argv[1]) -> number; } else font = DefaultFont; object = (WOOL_Pixmap) Malloc(sizeof(struct _WOOL_Pixmap)); XQueryTextExtents(dpy, font, argv[0] -> string, strlen(argv[0] -> string), &dir, &up, &down, &extent); x = DefaultLabelHorizontalMargin - extent.lbearing; y = DefaultLabelVerticalMargin + up; width = Max(1, extent.width + 2 * DefaultLabelHorizontalMargin); height = Max(1, up + down + 2 * DefaultLabelVerticalMargin); zrt_put(object); object -> type = WLPixmap; object->mask = 0; Trace('p', ("wool_make_blank_bitmap: create pixmap %d %d %d\n", width, height, Context->depth)); object -> pixmap = XCreatePixmap(dpy, Context->root, width, height, Context->depth); object -> x_hot = object -> y_hot = 0; object -> width = width; object -> height = height; XSetForeground(dpy, Context->gc.Work, Context -> pixel.Back); XFillRectangle(dpy, object -> pixmap, Context->gc.Work, 0, 0, width, height); XSetFont(dpy, Context->gc.Work, font); XSetForeground(dpy, Context->gc.Work, Context -> pixel.Fore); XDrawString(dpy, object -> pixmap, Context->gc.Work, x, y, argv[0] -> string, strlen(argv[0] -> string)); StorePixmapScreen(object, Context -> root); return (WOOL_OBJECT) object; } /* * WLPixmap_print: * a / bitmap prints as [PIXMAP widthxheight id] */ WOOL_OBJECT WLPixmap_print(obj) WOOL_Pixmap obj; { wool_printf("{PIXMAP %dx", obj -> width); wool_printf("%d", obj -> height); wool_printf(" 0x%x", obj -> pixmap); #ifdef DEBUG wool_printf(", on screen %d", obj -> screen); #endif /* DEBUG */ wool_puts("}"); return (WOOL_OBJECT) obj; } /* * WLPixmap_free: * The structure is just freed, and string released. */ WOOL_OBJECT WLPixmap_free(obj) WOOL_Pixmap obj; { if (obj->pixmap != Context -> DefaultBitmap) XFreePixmap(dpy, obj->pixmap); if (obj->mask) XFreePixmap(dpy, obj->mask); Free(obj); return NULL; } /* * returns the dimensions of the strings in the font + margins * x,y is the start of the string (baseline) in the box. */ WOOL_OBJECT WLPixmap_get_dimensions(bitmap, box) WOOL_Pixmap bitmap; Box box; /* RETURN the dimensions */ { box -> x = 0; box -> y = 0; box -> width = bitmap -> width; box -> height = bitmap -> height; box -> shape = bitmap -> mask; return NULL; } /* * opening a bitmap is putting it in backgroud */ WOOL_OBJECT WLPixmap_open(bitmap, wob) WOOL_Pixmap bitmap; Wob wob; { XSetWindowBackgroundPixmap(dpy, wob -> hook, bitmap -> pixmap); XClearWindow(dpy, wob -> hook); return NULL; /* 0 means no exposure necessary */ } /* * drawing a bitmap (not needed ?) */ WOOL_OBJECT WLPixmap_draw(bitmap, wob) WOOL_Pixmap bitmap; Wob wob; { XClearWindow(dpy, wob -> hook); return NULL; } /* * Reading of a Pixmap file (xpm v3 format) */ WOOL_OBJECT wool_xpm_pixmap_make(argc, argv) int argc; WOOL_String argv[]; { char *name; WOOL_Pixmap object; char temp_filename[MAX_TEMP_STRING_SIZE]; unsigned int npixels_return; unsigned long *pixels_return; WOOL_String filename; XpmAttributes xpmatt; XpmColorSymbol *colorsymbols = 0; int ncolorsymbols = 0; Pixmap pixmapshape; int i; int res; if ((argc == 0) || (argc > 2 && (argc % 2 == 0))) wool_error(BAD_NUMBER_OF_ARGS, argc); filename = argv[0]; must_be_string(filename, 0); if (argc > 1) { ncolorsymbols = (argc-1)/2; colorsymbols = (XpmColorSymbol *) Malloc(sizeof(XpmColorSymbol) * ncolorsymbols); for (i=0; i string; if (argv[i*2+2]->type == WLNumber) { colorsymbols[i].value = 0; colorsymbols[i].pixel = ((WOOL_Number) argv[i*2+2])->number; } else { must_be_string(argv[i*2+2], i*2+2); colorsymbols[i].value = argv[i*2+2] -> string; } } } object = (WOOL_Pixmap) Malloc(sizeof(struct _WOOL_Pixmap)); zrt_put(object); object -> type = WLPixmap; object -> x_hot = 0; object -> y_hot = 0; object -> mask = 0; name = (char *) file_in_path(filename -> string, PIXMAP_EXTENSION, wool_path, temp_filename); if (!name) { return wool_default_pixmap_make(object, "GWM: Cannot find Pixmap %s", filename -> string); } xpmatt.valuemask = XpmVisual|XpmColormap|XpmDepth|XpmColorSymbols; xpmatt.visual = DefaultVisual(dpy, Context->screen); xpmatt.colormap = DefaultColormap(dpy, Context->screen); xpmatt.depth = Context->depth; xpmatt.colorsymbols = colorsymbols; xpmatt.numsymbols = ncolorsymbols; if (GWM_xpm_closeness) { xpmatt.closeness = GWM_xpm_closeness; xpmatt.valuemask |= XpmCloseness; } Trace('p', ("Reading pixmap file: %s\n", name)); switch ( res = XpmReadFileToPixmap(dpy, Context->root, name, &object -> pixmap, &pixmapshape, &xpmatt), (colorsymbols ? (Free(colorsymbols), 0) : 0), res ) { case PixmapSuccess: break; case PixmapOpenFailed: return wool_default_pixmap_make(object, "Cannot open file %s", name); case PixmapFileInvalid: return wool_default_pixmap_make(object, "File %s is not a XPM pixmap", name); case PixmapNoMemory: wool_error("No memory to load file %s", name); break; default: wool_error("Error while reading pixmap %s", name); break; } if (pixmapshape) object->mask = pixmapshape; object->width = xpmatt.width; object->height = xpmatt.height; return (WOOL_OBJECT) object; } MakeDefaultBitmap() { if (!(Context -> DefaultBitmap = XCreateBitmapFromData(dpy, Context->root, def_bitmap_bits, def_bitmap_width, def_bitmap_height))) wool_error(NO_MEMORY, ""); } /* Graphical primitives */ /* draws a line in a pixmap: * syntax (draw-line pixmap x1 y1 x2 y2) * uses "foreground" color */ WOOL_OBJECT wool_draw_line(argc, argv) int argc; WOOL_Number argv[]; { int i; if (argc != 5) wool_error(BAD_NUMBER_OF_ARGS, argc); must_be(WLPixmap, argv[0], 0); for (i = 1; i < 5; i++) must_be(WLNumber, argv[i], i); XSetForeground(dpy, Context->gc.Work, Context -> pixel.Fore); XDrawLine(dpy, ((WOOL_Pixmap) argv[0]) -> pixmap, Context->gc.Work, argv[1] -> number, argv[2] -> number, argv[3] -> number, argv[4] -> number); return (WOOL_OBJECT) argv[0]; } /* draws a filled rectangle in a pixmap: * syntax (draw-rectangle pixmap x1 y1 width height border style) * uses "foreground" color for border * uses "background" color for rectangle * style: 0 = nothing, 1 = outline, 2 = filled, 3 = outline+filled */ WOOL_OBJECT wool_draw_rectangle(argc, argv) int argc; WOOL_Number argv[]; { int i; if (argc != 7) wool_error(BAD_NUMBER_OF_ARGS, argc); must_be(WLPixmap, argv[0], 0); for (i = 1; i < 7; i++) must_be(WLNumber, argv[i], i); if (argv[6] -> number & 2) { /* inside rectangle */ XSetForeground(dpy, Context->gc.Work, Context -> pixel.Back); XFillRectangle(dpy, ((WOOL_Pixmap) argv[0]) -> pixmap, Context->gc.Work, argv[1] -> number, argv[2] -> number, argv[3] -> number, argv[4] -> number); } if (argv[6] -> number & 1) { /* ouline rectangle */ int linewidth = argv[5] -> number ? argv[5] -> number : 1; XPoint points[5]; points[0].x = argv[1] -> number - 1; points[0].y = argv[2] -> number - 1; points[1].x = points[0].x + argv[3] -> number + 1; points[1].y = points[0].y; points[2].x = points[1].x; points[2].y = points[0].y + argv[4] -> number + 1; points[3].x = points[0].x; points[3].y = points[2].y; points[4].x = points[0].x; points[4].y = points[0].y; XSetForeground(dpy, Context->gc.Work, Context -> pixel.Fore); XDrawLines(dpy, ((WOOL_Pixmap) argv[0]) -> pixmap, Context->gc.Work, points, 5, CoordModeOrigin); for (i = 1; i < linewidth; i++) { points[0].x -= 1; points[0].y -= 1; points[1].x += 1; points[1].y -= 1; points[2].x += 1; points[2].y += 1; points[3].x -= 1; points[3].y += 1; points[4].x -= 1; points[4].y -= 1; XDrawLines(dpy, ((WOOL_Pixmap) argv[0]) -> pixmap, Context->gc.Work, points, 5, CoordModeOrigin); } } return (WOOL_OBJECT) argv[0]; } /* prints a text in a pixmap: * syntax (draw-text pixmap x1 y1 font text) * uses "foreground" color for text color */ WOOL_OBJECT wool_draw_text(argc, argv) int argc; WOOL_Number argv[]; { int i; if (argc != 5) wool_error(BAD_NUMBER_OF_ARGS, argc); must_be(WLPixmap, argv[0], 0); for (i = 1; i < 4; i++) must_be(WLNumber, argv[i], i); must_be_string(argv[4], 4); XSetForeground(dpy, Context->gc.Work, Context -> pixel.Fore); XSetFont(dpy, Context->gc.Work, argv[3]->number); XDrawString(dpy, ((WOOL_Pixmap) argv[0]) -> pixmap, Context->gc.Work, argv[1] -> number, argv[2] -> number, ((WOOL_String) argv[4]) -> string, strlen(((WOOL_String) argv[4]) -> string)); return (WOOL_OBJECT) argv[0]; }