home *** CD-ROM | disk | FTP | other *** search
- /*
- * canvas.c - This module implements all the I/O to the palette canvas.
- * This includes the color swatches, highlighting the current
- * color(s), and determining the location of a mouse click.
- *
- * Exported routines:
- * MakePalette
- * SetPaletteSize
- * SavePalette
- * DrawPalette
- * WhichSwatch
- * HighlightSwatch
- * BoxSwatches
- */
-
- /**************************************************************************
- * palette - a colormap editor
- * Copyright (c) 1988 Wayne Mesard *
- * *
- * This is free software. It may be reproduced, retransmitted, *
- * redistributed and otherwise propogated at will, provided that *
- * no monetary profit is realized and that this notice remains *
- * intact and in place. *
- * *
- * Please direct bug reports, code enhancements and comments *
- * to mesard@BBN.COM. *
- * *
- **************************************************************************/
-
- #include <suntool/sunview.h>
- #include <suntool/canvas.h>
- #include <stdio.h>
-
- #define Y_LOC(ENTRY) (y_edge + ((ENTRY)/powx)*edge)
- #define X_LOC(ENTRY) (x_edge + ((ENTRY)%powx)*edge)
-
- static Canvas palette_canvas;
- static Pixwin *palette_pw;
-
- static int palette_width, palette_height, x_edge, y_edge, edge;
- static unsigned int powx, powy;
-
-
- /* MakePalette - Sets module variables and returns the pixwin of the
- * canvas. Must be called once before any other routines
- * in this module.
- */
-
- Pixwin *MakePalette(canvas)
- Canvas canvas;
- {
- return(palette_pw = canvas_pixwin(palette_canvas=canvas));
- }
-
-
-
- /*
- * SetPaletteSize - Updates module variables. Must be called when
- * canvas is resized.
- */
-
- void SetPaletteSize()
- {
- palette_width = (int) window_get(palette_canvas, CANVAS_WIDTH);
- palette_height = (int) window_get(palette_canvas, CANVAS_HEIGHT);
- }
-
-
-
- /*
- * SavePalette - Given an open file pointer, creates a rasterfile image
- * of the palette.
- */
-
- int SavePalette(fp, colormap)
- FILE *fp;
- colormap_t *colormap;
- {
- return(pr_dump(palette_pw->pw_prretained, fp, colormap, RT_STANDARD, 0));
- }
-
-
- /*
- * DrawPalette - Given a number of colors, draw a recangle containing a
- * square for each color. The size of the rectangle
- * should be maximal w.r.t. the size of the palette.
- * (This procedure is greatly simplified by the fact that
- * the width:height ratio is always a power of 2 (since
- * the number of colors is always a power of 2.
- */
-
- void DrawPalette(n_colors)
- int n_colors;
- {
- void DrawRect();
- register int x, y;
- int temp;
- int x_max = palette_width;
- int y_max = palette_height;
-
- edge = 0;
- for (x = n_colors, y = 1; x; x >>= 1, y <<= 1) {
- temp = ((x_max-8)/x < (y_max-8)/y ?
- (x_max-8)/x : (y_max-8)/y);
- if (temp > edge) {
- powx = x;
- powy = y;
- edge = temp;
- }
- }
- /* Note: a non-iterative algorithm for the above procedure exists,
- * but it requires floating point arithmetic and mathlib routines.
- * This is computationally more efficient, although less elegant.
- */
-
- x_edge = (x_max - (powx*edge))/2;
- y_edge = (y_max - (powy*edge))/2;
-
- pw_batch_on(palette_pw);
- pw_writebackground(palette_pw, 0, 0, x_max, y_max, PIX_SRC | PIX_COLOR(0));
-
- x_max = x_edge + powx*edge;
- y_max = y_edge + powy*edge;
-
- n_colors--; /* So we don't have to compare n-1 */
-
- DrawRect(x_edge-2, y_edge-2, x_max, y_max, PIX_SRC, n_colors);
-
- for (temp = -1, y=y_edge; y < y_max; y += edge)
- for (x=x_edge; x < x_max; x += edge) {
- pw_writebackground(palette_pw, x, y, edge-1, edge-1,
- PIX_SRC | PIX_COLOR(++temp));
- }
- pw_batch_off(palette_pw);
- }
-
-
-
- /*
- * WhichSwatch - Find out which color is at specified position. Return
- * -1 if it's outside the rectangle.
- *
- * Can't simply look at the pixel value, since it might be
- * on the border, or adjacent to the currently selected
- * square (and therefore with that color's enlarge square
- */
-
- int WhichSwatch(x, y)
- int x, y;
- {
- x = x-x_edge;
- y = y-y_edge;
- if (x < 0 || y < 0 || (x=x/edge) >= powx || (y=y/edge) >= powy)
- return (-1);
- else
- return((y*powx)+x);
- }
-
-
-
- /*
- * HighlightSwatch - Draw a big old square for the specified color.
- */
-
- void HighlightSwatch(num, border_color)
- int num, border_color;
- {
- void DrawRect();
- int x, y;
-
- if (border_color > 2) {
- y = Y_LOC(num);
- x = X_LOC(num);
-
- pw_batch_on(palette_pw);
- pw_writebackground(palette_pw, x-edge/2, y-edge/2, 2*edge, 2*edge,
- PIX_SRC | PIX_COLOR(num));
- DrawRect(x, y, x+edge, y+edge, PIX_SRC,
- (num == border_color ? 0 : border_color));
- pw_batch_off(palette_pw);
-
- }
- }
-
-
-
- /*
- * BoxSwatches - Draw a border around the specified range of color squares.
- */
-
- void BoxSwatches(e1, e2)
- int e1, e2;
- {
- void BoxRegion();
- int temp;
-
- pw_batch_on(palette_pw);
- /* Box the first row iff region doesn't start at col 0. */
- if (e1 % powx && ((e2-e1 > powx) || (e2%powx < e1%powx))) {
- temp = e1-(e1%powx)+powx-1;
- BoxRegion(e1, temp);
- e1 = temp+1;
- }
- /* Box the rows between the first and the last, if there are any. */
- if (e2-e1 >= powx) {
- temp = e2-(e2%powx)-1;
- BoxRegion(e1, temp);
- e1 = temp+1;
- }
- /* Box the partial row at the end, if there is one. */
- if (e1 <= e2)
- BoxRegion(e1, e2);
-
- pw_batch_off(palette_pw);
- }
-
-
-
- /*
- * BoxRegion - Draw a rectangle whose upper left corner is at square e1
- * and whose lower right is at e2.
- */
-
- static void BoxRegion(e1, e2)
- int e1, e2;
- {
- void DrawRect();
-
- DrawRect(X_LOC(e1)-1, Y_LOC(e1)-1, X_LOC(e2)+edge-1, Y_LOC(e2)+edge-1,
- PIX_NOT(PIX_DST), 0);
- }
-
-
- static void DrawRect(x1, y1, x2, y2, op, color)
- int x1, y1, x2, y2, color;
- {
- pw_vector(palette_pw, x1, y1, x2, y1, op, color);
- pw_vector(palette_pw, x2, y1, x2, y2, op, color);
- pw_vector(palette_pw, x2, y2, x1, y2, op, color);
- pw_vector(palette_pw, x1, y2, x1, y1, op, color);
- }
-
-