Subject: v14i022: Device-independant graphics system, with drivers Newsgroups: comp.sources.unix Sender: sources Approved: rsalz@uunet.UU.NET Submitted-by: Joe Dellinger Posting-number: Volume 14, Issue 22 Archive-name: vplot/part17 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'Vplot_Kernel/Documentation/vplottext.mn' <<'END_OF_FILE' X.TH vplot_text 9 "7 April 1987" X.SH NAME vplot text \- A guide to using the new Hershey fonts in vplot X X.SH DESCRIPTION Vplot fonts are mixtures of vectors and filled areas which simulate typeset fonts on graphics devices. Since they are not raster, they can be arbitrarily scaled, stretched, skewed, and rotated, and can be plotted on any device. X There are 17 fonts. Font 0 is just the regular old PEN font we've been using all along. The default font is device and installation dependent, or can be set from the command line (see options below). Here is a complete list of fonts and their number: X X.br X0 pen X.br X1 roman simplex X.br X2 roman duplex X.br X3 roman complex X.br X4 roman triplex X.br X5 italic complex X.br X6 italic triplex X.br X7 script simplex X.br X8 script complex X.br X9 greek simplex X.br X10 greek complex X.br X11 Cyrillic complex X.br X12 German style gothic triplex X.br X13 Greek style gothic triplex X.br X14 Italian style gothic triplex X.br X15 mathematics X.br X16 miscellaneous X.br X Font 0 was designed by Rob Clayton at Stanford. Fonts 1 through 16 are debugged versions of the `Hershey' fonts available from mod.sources. In order to have permission to use these fonts, I must now display this message: X X.br X - The Hershey Fonts were originally created by Dr. X.br X A. V. Hershey while working at the U. S. X.br X National Bureau of Standards. X X.SH INTERFACE This section describes the control sequences which are accessible to any user of X.B vplot text, via whatever program. X Vplot text recognizes `\\' as a special character used to signal the start of an escape sequence. There are two sorts of escape sequences, those that take an argument and those that do not. X Here is a complete list of escape sequences that do not take an argument: X.br X\\> Advance one interletter space X.br X\\< Back up one interletter space X.br X\\^ Raise one half of a capital letter height X.br X\\_ Lower one half of a capital letter height X.br X\\g Continue processing text, but don't actually print it (`ghostify it'). This is useful if you want to leave space to go back and add something by hand. X.br X\\G Start printing text again X.br X\\n Newline X.br X\\h Backspace (control-h also works) back up over the last character X.br X\\- Does nothing; used to prevent a group of characters from being formed into a ligature. X.br X\\\\ Print a backslash X.br X The following take an integer argument immediately after, with a X.B required space after the integer to delineate the end. This space is not printed. X X.br X\\s Size change. Change to this percent of the size set in the text vplot call. \\s100 restores the default height. X.br X\\f Add this to current fatness. Goes out of effect when text printing is finished. X.br X\\F Switch to this font number. (-1 restores the default font). X.br X\\k Move by this many space widths to the right. X.br X\\r Move up this many character heights (the height of a standard capital letter, such as `A'). X.br X\\v Print this ASCII character number in the current font, stripping it of any special meaning. This and ligatures are the only way that glyphs numbered greater than 255 are available. X.br X\\c Switch to this color. -1 restores the current drawing color. Vplot's current drawing color is not changed by changing the color inside text. X.br X\\m Save current position in this number register. X.br X\\M Restore position saved in this number register. X.br X X.SH EXAMPLES Since programs such as `graph' do not interpret text themselves, but rely on vplot to do it, the above control sequences may simply be used wherever any graphics text is used. For example, instead of specifying as an option to graph label=`beta', you can specify label=`\\F9 b' and actually get the Greek letter beta from the Greek Simplex font. X X Here are some more examples: X X To get an integral sign: X.br X \\F15 \\v168 X.br X Translation: Switch to font 15 (math symbols), print character #168 (integral sign). X X To get `X squared plus Y squared': X.br X X\\^2\\_ + Y\\^2 X.br X Translation: Print X, go up half, print 2, go back down half, print +, print Y, go up half, print 2. X X As an advanced example, to get `A sub b sup beta': X.br X A\\m1 \\_b\\M1 \\^\\F9 b X.br X Translation: Do A, save this spot, go down half, do b, restore the saved spot, go up half, switch to font 9 (Greek Simplex) do beta. (Notice the use of marks to stack characters on top of each other.) X X Warning: \\ is a special character in C. To get a backslash, you have to use \\\\. X X.SH GENERIC PEN OPTIONS X X.TP X.B txfont=font_number Txfont specifies the default text font. The default is device and installation dependent. Generally, screen devices will default to the `pen' font since it is by far the fastest to draw, and hardcopy devices will default to either roman simplex or roman complex since these are the closest to looking like standard typeset text. Out-of-range font numbers (starting at 100) may be used in a device-dependent fashion to access hardware fonts on devices that have them. Devices that don't have hardware fonts will use the font number modulo 100. Fonts 0-99 are guaranteed device-independent. X X.TP X.B txprec=0 Txprec specifies the default text precision (a GKS term). Possible values are character (0), string (1), and stroke (2). For vector fonts, the text precision parameter is ignored except that ligatures are only enabled at precision 2. The precision parameter may be significant if device-dependent hardware fonts are used, however. The default precision is device and installation dependent. X X.TP X.B txovly=0 Txovly sets the default text overlay mode. This controls whether or not to clear out an area behind the text before writing it, and whether or not to put a box around it. Overlay modes 1 and 3 draw a box, and modes 2 and 3 shade the inside of the box with the background color. The default text overlay mode is 0 X(do nothing). All text overlay modes may not be supported on all devices. X(Some devices cannot shade to background color, for example.) X The default font, default precision, and default text overlay mode may all be reset by the appropriate vplot command. X X.TP X.B fontN=file_name The binary format vplot font file for font number N is located in file_name. If the font number is not one normally defined on the system, file_name defaults to fontN, where again N is the font number. If the device does not have hardware fonts, the font number modulo 100 will be used for all internal purposes (so fonts 201 and 101 must be the same, for example). The N in the above option will still be the original font number, however. Fonts that are included at compile time are hardwired and cannot be changed. X X.SH LIGATURES Fonts may specify that certain combinations of adjacent glyphs be combined into a single new glyph whenever they occur. For example, `ffi' in font 3 (it's a ligature in troff, too). This takes place automatically at precision 2. The only fonts which currently contain ligatures are the Roman Complex, Italic Complex, and Cyrillic Complex fonts. X(Ligatures may be used in fonts for foreign languages to good effect to automatically de-transliterate English approximations. For example, `sh' in the Cyrillic font automatically comes out as a single Shah character. X`KHrushchev', for example, contains only 6 glyphs: KH-r-u-shch-e-v. The K and H here are both capitalized since they are both part of the first character. The `Tests' directory contains the example TEST_Cyrillic which shows how to generate every letter in the Cyrillic alphabet.) X X.SH TEXT JUSTIFICATION Text justification is set by the appropriate command in vplot, and follows the GKS standard. Since this text routine allows character size and active font to be changed within a single text string, the GKS standard is extended so that X`TOP' and `BOTTOM' alignments align on the highest top and the lowest bottom of the characters used. (Note that this makes the alignment font and size dependent, but not dependent on the actual characters used.) The `CAP' and `HALF' alignments are determined by those for the default font. X All sizes of all fonts are aligned together by their baselines. X Horizontal alignment is based according to the beginning and ending horizontal positions. You can use marks to make the ending position be anywhere in the string you wish. X A `SYMBOL' justification mode has also been added to those defined by GKS. Each glyph has a `hot spot' defined, which is where the glyph is to be centered if it is used as a symbol. The last printable character in a string is the character centered on as the symbol. To center on a character in the middle of the string as a symbol, mark the spot with the \\m command immediately after that character and then restore that location at the end of the string with the X\\M command. That character is now the `last character' as far as all centering is concerned. Size changes and horizontal shifts are taken into account in the symbol justification mode, but shifts up and down are not. X Vplot polymarkers are drawn by setting the SYMBOL text justification mode, setting the correct font, creating a special single-character string, and then calling the text routine to draw the symbol. X X.SH DIAGNOSTICS Nonexistent glyphs are rendered as a special `error' glyph. Which glyph is used for this is installation dependent, and is set by defines in gentext.c. As distributed, it is glyph 30 in font 0, which is a `?' inside a diamond. (I stole this idea from the Imagen laser printer.) An error message will be produced the first time that a nonexistent glyph is referenced. X(Only the first time so that you don't get overwhelmed with error messages if you're trying to use a font that doesn't exist on that system.) Attempts to use nonexistent fonts produce an error message and font 0 (or whatever other font has been designated as the error font in gentext.c) is used instead. X Various other non-fatal errors can occur and all give self-explanatory error messages. X X.SH COPYRIGHT The Vplot source code is copyrighted. Please read the copyright notice you will find in the Vplot manual page. X X.SH FONT FILES Font files used by the vplot text subroutine `gentext' are kept in X.../vplot/filters/include/vplotfonts/*. There are two forms for each font, an `include' form and a `binary' form. The include form is compiled in as an #include file into gentext. This is more efficient, but makes the executable code considerably longer and slows down compilation. The binary form is loaded on the fly as needed at runtime. Which method is used for which font is system dependent and is determined by the file .../vplot/include/font_definitions.h. X X.SH ASSOCIATED PROGRAMS The subroutine X.B gentext.c is the device-independent generic subroutine that vplot uses to draw vector fonts. Gentext.c is constructed in such a way that it could easily be fit into a GKS package. While Vplot itself thinks in terms of `text orientation' and X`text size', gentext thinks in terms of `character up vectors' and X`character path vectors'. Squashed, slanted, etc, text can be produced by having these two vectors not be perpendicular or not the same length. X(This can only happen when using vplot when xscale does not equal yscale.) X The program X.B makefont.c takes a `vplot font' and encodes it into the forms required by gentext. The format of a `vplot font' is designed such that it can be read into the program `plas' and then piped into a vplot filter. IE, the command X.br plas < cyrilc.vplot_font | ?pen xcenter=0 ycenter=0 scale=50 pause=1 X.br will display each glyph in the cyrillic font, one per second. X The exact format of a `vplot font' file is given in comments at the beginning of makefont.c, and the file pen.vplot_font serves as an example. Since vplot_fonts are just open-format vplot files, it is very easy to create your own special purpose glyphs, markers, or fonts and add these to the system. X The program X.B hertovplot.c converts `Hershey' font data as distributed by mod.sources X(mod.sources is a UNIX network `news' group for distributing useful UNIX software.) into vplot fonts. Its use is described in comments at the beginning of the program. The program X.B hertogrid.c draws all the glyphs in a Hershey glyph file on a grid, labeling each glyph with its number. (The Hershey glyph files have to be organized into reasonable fonts by hand! The organization of my fonts mostly follows those provided by Mr. Hurt, but I have added in a few things he missed and reordered the non-English fonts to make more sense. I have stolen bits of Mr. Hurt's code to write hertovplot.c and hertogrid.c.) X X.SH FONT INSTALLATION To install all the fonts, you must first obtain the Hershey fonts for yourself as distributed by mod.sources (if you don't know how to get stuff from them, then how did you get this file that you're reading now?). Follow the instructions to create the four `.oc' files, and copy these into the .../vplot/Hershey directory. Do not copy the `.hmp' files. Follow the instructions you will find in the file .../vplot/Hershey/README to make all the required `vplot_font's. X(Note that pen.vplot_font is not part of the Hershey font distribution. This font was created by Rob Clayton around 1980, and slightly modified by Joe Dellinger in 1986.) Once you have done this, go into the .../vplot/filters/include/vplotfonts directory, and do `make'. This will create the required `.include' and `.bin' fonts. X X.SH SEE ALSO pen(9) vplot(9) libvplot(9) X X.SH AUTHOR Joe Dellinger X(joe@hanauma.stanford.edu, convex!convexw!hanauma!joe, decvax!hanauma!joe) You may ask me for advice if you wish to help do any of the things in the wish list below. X X.SH BUGS The letter `J' in the Roman Triplex font in the Hershey font distribution has mangled width information. The vplot font for this font has to be edited by hand to correct this mistake. X Gentext.c does not yet support all the required GKS features. However, as all the internal calculations are done in a way consistent with the GKS model modifying the code to support these is a very straightforward job which I leave to someone else. X Somebody should make sure that all the `hot spots' defined for characters are reasonable. (The `hot spot' is the point that is aligned on when symbol alignment mode is used.) X(The ones installed now are the defaults chosen by makefont.c.) Somebody should create a special `polymarker' font. Currently several of the more esoteric symbols called by the vplot polymarker command are not very well centered (notably triangles). X Somebody should write an interactive program to create new glyphs with. X Somebody should turn some of the better Hershey vector fonts into filled-area fonts. (Unfortunately, Mr. Hershey didn't see fit to order his vectors in such a way as to make this easy.) The only thing lacking is the font itself, because vplot itself already supports arbitrary mixtures of filled-areas and vectors in fonts. Currently there are just a few glyphs containing filled areas in font 0, as examples showing how to do it. X Dr. Geller (the first tenured American professor at a Japanese university, and a former Stanford Earth Sciences professor) should have his students create a katakana and a hirigana font. Ligatures can be used to pair the appropriate consonant-vowel pairs. There are also quite a few Kanji glyphs available as well, from which a Kanji font could be constructed. A ligature could be constructed to turn each English word into its Kanji equivalent! (The number of glyphs in a font is not limited to 256! That's why I did things that way.) X Somebody should extend the way ligatures are read from vplot font files, so that you can just give the ASCII character itself instead of the glyph number if one exists. Since I only had a few ligatures I didn't want to bother with this. END_OF_FILE if test 15800 -ne `wc -c <'Vplot_Kernel/Documentation/vplottext.mn'`; then echo shar: \"'Vplot_Kernel/Documentation/vplottext.mn'\" unpacked with wrong size! fi # end of 'Vplot_Kernel/Documentation/vplottext.mn' fi if test -f 'Vplot_Kernel/filters/genlib/polyfix.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Vplot_Kernel/filters/genlib/polyfix.c'\" else echo shar: Extracting \"'Vplot_Kernel/filters/genlib/polyfix.c'\" \(15037 characters\) sed "s/^X//" >'Vplot_Kernel/filters/genlib/polyfix.c' <<'END_OF_FILE' X/* X * Copyright 1987 the Board of Trustees of the Leland Stanford Junior X * University. Official permission to use this software is included in X * the documentation. It authorizes you to use this file for any X * non-commercial purpose, provided that this copyright notice is not X * removed and that any modifications made to this file are commented X * and dated in the style of my example below. X */ X X/* X * X * source file: ./filters/genlib/polyfix.c X * X * Joe Dellinger (SEP), June 11 1987 X * Inserted this sample edit history entry. X * Please log any further modifications made to this file: X * Joe Dellinger Feb 29, 1988 X * Changed POLYS to 5000 so it will compile on RT's. X * Somebody should change the whole thing into linked lists! X */ X X#include X#include "../include/err.h" X#include "../include/extern.h" X#include "../include/params.h" X#define EMPTY -100 X#define NOLINK -10 X#define ENDOFLIST -1 X#define UNCLAIMED 0 X#define CLAIMED 1 X#define INTERIOR 0 X#define POLYS 5000 /* Memory alloted for polygon */ X#define MAXPOL 500 /* Maximum number of polygons made */ X X/* X * This routine breaks up the clipped polygon generated by "polygon" into X * multiple polygons as needed, using the Thorson-Dellinger method! X * X * Note 1: X * The output of "polygon" is a clipped polygon with different parts X * joined by lines around the edge of the window. (This is unsightly.) X * This routine seems to do a reasonably efficient job of fixing this. X * (It's a pretty hard problem!) X * X * Note 2: X * This always (I hope) works for non-crossed polygons. Crossed polygons X * will sometimes be turned into two overlapping polygons, X * which can cause interior voids to be shaded. Some terminals, X * like the color tektronix, can be sent multiple polygons X * and told that they are to be shaded as one. If this is the X * case, the routine should always (I think) work, even for crossed X * polygons. To fix this problem, you would have to laboriously X * look for intersections of "disjoint" polygons. A new point would X * then be added at the intersection, and the two polygons joined X * into one through that point. The required routines are pretty much X * already in this program, but it seems that the large amount of X * time to check for this obscure case is not worth it. There seems X * to be no obvious way around this. X * X * --- Joe Dellinger, May 7, 1984. X * X * Looking back on this I realize that I still had a lot to learn X * about C coding when I wrote this; some kind soul should go back X * and update this to use pointers and allocated linked-lists. X * I don't feel like doing this myself; the thing works perfectly X * for us even if the code itself is a mess! X * X * --- Joe Dellinger, May 3, 1987. X */ X static int poly[POLYS][5]; X/* X * Doubly linked list that will contain the vertices of our polygons. 0-X 1-Y X * 2-forward link 3-backward link 4-which edge? 1-bottom 2-left 4-top 8-right X */ static int pols[MAXPOL]; /* Point to the start of each polygon */ static int polsc[MAXPOL]; /* Cycle length */ static int npols; /* How many polygons we have */ X static int pedge[POLYS]; /* Edge points of the polygon */ static int nedge, nedge2; /* number of edge points */ X static int point, endlist; X int bottom, left; X X int Allgone;/* Communicate to polygon whether we ever got X * anything */ X polyfix (x, y, first) /* Read in the data for polystart */ X int x, y, *first; X{ static int oldx, oldy; X X if (*first == 1) X { X *first = 0; X point = 1; X Allgone = 0; /* All the points aren't gone! */ X oldx = x + 1; X oldy = y + 1; /* Won't match */ X } X /* X * Put the point x,y into the list as number point, Unless it is * X * superfluous X */ X if ((x == oldx) && (y == oldy)) X return; /* ignore repeated points */ X poly[point][0] = x; /* X of vertex */ X poly[point][1] = y; /* Y of vertex */ X oldx = x; X oldy = y; X point++; X if (point >= POLYS) X ERR (FATAL, name, "Not enough memory for polygon!"); X} X polystart () /* Start working on the polygons */ X{ int i, j, k, l, ii; int firstpoint, flag, double_check; int temp1, temp2, temp; extern int smart_clip; X X endlist = point; /* Last element in use */ X /* initialize array */ X for (i = 0; i <= point; i++) X { X poly[i][4] = INTERIOR; X poly[i][2] = i + 1; X poly[i][3] = i - 1; X } X poly[0][0] = poly[0][1] = EMPTY; X poly[point][0] = poly[point][1] = EMPTY; X X /* fix links of free list and last point */ X poly[0][3] = NOLINK; X poly[0][2] = point; X poly[point][2] = ENDOFLIST; X poly[point][3] = 0; /* point to start of free list */ X X poly[point - 1][2] = 1; /* point to start of polygon */ X poly[1][3] = point - 1; X X /* Now we have our polygon stored as a circular double-linked list! */ X X if (smart_clip) X goto skip_it; /* smart device can handle it from here */ X X X /* Identify all edge points */ X X /* X * They are identified 2 ways; each point contains the information X * itself, and there is an array which points to all edge points. This is X * to avoid searching through the entire polygon. X */ X X nedge = 0; X i = firstpoint = 1; /* Since we are just starting, we know the X * polygon MUST start here */ X do X { X if (poly[i][4] = edge (poly[i][0], poly[i][1])) /* NOT an == */ X { X /* It's on an edge */ X nedge++; X pedge[nedge] = i; X } X i = poly[i][2]; X } X while (firstpoint != i); X X nedge2 = nedge; X X /* X * Look at each edge segment. See if any edge points occur inside X * segments joining two other edge points. (Got that?) X */ X X for (ii = 1; ii <= nedge2; ii++) X { X i = pedge[ii]; X if (k = (poly[i][4] & poly[poly[i][2]][4])) X { X /* We have an edge link. That is, it connects to edge vertices. */ X /* See if any other edge points lie inbetween these two. */ X for (j = 1; j <= nedge; j++) X { X if (k & poly[pedge[j]][4]) X { X /* This point is on the correct edge */ X X l = ((k & (8 + 2)) > 0); X X /* l = 0 if top or bottom, 1 if left or right */ X X if (poly[i][l] > poly[poly[i][2]][l]) X { X if ((poly[pedge[j]][l] > poly[poly[i][2]][l]) X && (poly[pedge[j]][l] < poly[i][l])) X /* Got one! */ X /* insert it into the list */ X { X nedge2++; X insert (i, poly[pedge[j]][0], X poly[pedge[j]][1], X poly[pedge[j]][4]); X pedge[nedge2] = poly[i][2]; X } X } X else X { X if ((poly[pedge[j]][l] < poly[poly[i][2]][l]) X && (poly[pedge[j]][l] > poly[i][l])) X /* Got one! */ X /* insert it into the list */ X { X nedge2++; X insert (i, poly[pedge[j]][0], X poly[pedge[j]][1], X poly[pedge[j]][4]); X pedge[nedge2] = poly[i][2]; X } X } X } X /* X * Whether you found one or not, continue on. If we did X * insert one, IT is now the next point and our interval has X * gotten shorter. Some sort of sorting would be more X * effecient, but it doesn't seem worth the extra complexity X * at this time of night. It would involve a lot of special X * cases, whereas doing it this way doesn't. X */ X } X } X } X X nedge = nedge2; /* Keep track of all the new edge points we X * just created */ X X /* X * We have now inserted all the required points. Look for links that X * connect the same two positions. (But different vertices... That is, X * vertices which are not consecutive but have the same location!) X */ X /* Be careful that the link is not of zero length! */ X /* X * Despite everything, it still seems to occasionally miss a spot. So as X * an easy fix make it go through the search until it doesn't find X * anything. In the overwhelming majority of cases, the first pass will X * have done the job. X */ X double_check = 1; X while (double_check == 1) X { X double_check = 0; X X for (j = 1; j <= nedge; j++) /* Loop through all edge points */ X { X flag = 1; X while (flag == 1) X { X flag = 0; X if ((poly[pedge[j]][4] & poly[poly[pedge[j]][2]][4]) X && ((poly[pedge[j]][0] != poly[poly[pedge[j]][2]][0]) X || (poly[pedge[j]][1] != poly[poly[pedge[j]][2]][1]))) X { X /* X * This edge point's succesor is a point on the same X * edge, And the link is not of zero length X */ X for (k = j; k <= nedge; k++) /* Loop through edge X * points */ X { X /* Look for a vertex that is at the same position */ X if ((poly[pedge[j]][0] == poly[pedge[k]][0]) X && (poly[pedge[j]][1] == poly[pedge[k]][1])) X { X /* X * OK, it is in the same position. See if either X * its succesor or predecessor is the same as the X * other end of the link. X */ X if ((poly[poly[pedge[j]][2]][0] == X poly[poly[pedge[k]][3]][0]) X && (poly[poly[pedge[j]][2]][1] == X poly[poly[pedge[k]][3]][1])) X { X /* X * links go in opposite directions. (The easy X * case) Break the links and instead link X * points at the same location. Delete X * duplicated point. X */ X /* X * pedge[j] and pedge[k] are at the same X * spot, as are pedge[j]'s succesor and X * pedge[k]'s predecessor. X */ X temp1 = poly[pedge[j]][2]; X /* remember pedge[j]'s succesor */ X poly[pedge[j]][2] = pedge[k]; X /* pedge[j]'s succesor is now pedge[k] */ X temp2 = poly[pedge[k]][3]; X /* remember pedge[k]'s predecessor */ X poly[pedge[k]][3] = pedge[j]; X /* X * pedge[j] and pedge[k] are now linked. Link X * temp1 and temp2 X */ X poly[temp1][3] = temp2; X poly[temp2][2] = temp1; X /* X * Done. We have just split one polygon into X * two! X */ X /* Clean up by removing the repeated vertices */ X delete (pedge[k]); X pedge[k] = 0; X /* X * Point this to a place we know is marked as X * an interior point. Always fails checks to X * see if it is on the edge we want. X */ X delete (temp2); X flag = 1; X double_check = 1; X } X else X { X if ((j != k) && X (poly[poly[pedge[j]][2]][0] == X poly[poly[pedge[k]][2]][0]) X && (poly[poly[pedge[j]][2]][1] == X poly[poly[pedge[k]][2]][1])) X { X /* X * the hard case. Both links go the same X * direction. Do as before, but Reverse X * the direction of one of the two X * pieces. X */ X temp1 = poly[pedge[j]][2]; X temp2 = poly[pedge[k]][2]; X i = temp1; X do X { /* Reverse one piece first */ X temp = poly[i][2]; X poly[i][2] = poly[i][3]; X poly[i][3] = temp; X i = temp; X } X while ((temp2 != i) && (temp1 != i)); X poly[temp1][2] = temp2; X poly[temp2][3] = temp1; X if (i == temp2) X { X poly[pedge[j]][2] = pedge[k]; X poly[pedge[k]][3] = pedge[j]; X /* X * We have not created a new polygon, X * merely re-ordered one! X */ X } X else X { X poly[pedge[j]][3] = pedge[k]; X poly[pedge[k]][2] = pedge[j]; X /* X * We have merged two polygons back X * into one! X */ X } X /* clean up */ X delete (pedge[k]); X pedge[k] = 0; X delete (temp2); X flag = 1; X double_check = 1; X } X } X } X if (flag == 1) X break; X /* X * We've just altered the point we're at! So better X * stop this loop. X */ X } /* End of search loop */ X } X } X } X } X X /* X * Our polygon has been fragmented into multiple smaller polygons as X * necessary! Output the resulting polygons X */ X skip_it: X scan (); X X for (i = 1; i <= npols; i++) X { X dev.startpoly (polsc[i]); X j = pols[i]; X do X { X dev.midpoly (poly[j][0], poly[j][1]); X j = poly[j][2]; X } X while (j != pols[i]); X dev.endpoly (i == npols); X } X} X insert (where, x, y, z) X int where, x, y, z; X{ int temp; X X /* insert the given vertex between the element where and its forward link */ X X /* remove an element from the free list */ X temp = poly[0][2]; /* free element */ X if (temp == endlist) X { X /* Need to make our list one longer. */ X endlist++; X if (endlist >= POLYS) X ERR (FATAL, name, "Ran out of memory on the polygon!"); X poly[endlist][3] = temp; X poly[endlist][2] = ENDOFLIST; X poly[temp][2] = endlist; X } X /* OK, Now you can remove it, it isn't at the end anymore. */ X poly[0][2] = poly[temp][2]; X poly[poly[temp][2]][3] = 0; X X poly[temp][0] = x; /* Put vertex in for element */ X poly[temp][1] = y; X poly[temp][4] = z; X X /* update links */ X X poly[temp][2] = poly[where][2]; X poly[where][2] = temp; X X poly[temp][3] = poly[poly[temp][2]][3]; X poly[poly[temp][2]][3] = temp; X} X delete (where) X int where; X{ int temp; X X /* Get rid of element number where; put it on the free list */ X /* This must work even if element where points to itself! */ X poly[where][0] = poly[where][1] = EMPTY; X poly[where][4] = INTERIOR; X temp = poly[where][3]; X poly[where][3] = 0; X poly[temp][2] = poly[where][2]; X poly[where][2] = poly[0][2]; X poly[0][2] = where; X poly[poly[where][2]][3] = where; X poly[poly[temp][2]][3] = temp; X} X X/* X * See how many polygons we have, and where they start. X * Put this information in pols. X */ scan () X{ int polyon[POLYS]; /* Array to remember whom this point belongs X * to */ int joe; int cycle; int firstpoint; int where; X X for (joe = 1; joe < endlist; joe++) X { X if (poly[joe][0] == EMPTY) X { X polyon[joe] = EMPTY; X } X else X { X polyon[joe] = UNCLAIMED; X } X } X X npols = 0; X for (joe = 1; joe < endlist; joe++) X { X if (polyon[joe] == UNCLAIMED) X { X /* Found the start of a polygon */ X firstpoint = joe; X polyon[firstpoint] = CLAIMED; X cycle = 1; X where = poly[firstpoint][2]; X while (firstpoint != where) X { X cycle++; X polyon[where] = CLAIMED; X where = poly[where][2]; X if (where == NOLINK) X ERR (FATAL, name, "Oh, No! Polygon list damaged! (This shouldn't be able to happen.)"); X } X if (cycle < 3) X { /* Not really a polygon, remove it */ X where = poly[firstpoint][2]; X while (firstpoint != where) X { X delete (where); X where = poly[firstpoint][2]; X } X delete (firstpoint); X } X else X { X /* We found another polygon */ X npols++; X if (npols > MAXPOL) X ERR (FATAL, name, "Too many polygons!"); X pols[npols] = firstpoint; X polsc[npols] = cycle; X } X } X } X} X /* X * Now pols is a list of indexes to the beginnings of each of the Polygons. X * npols gives how many there are. X */ X int edge (x, y) /* Find out which edges this point is on */ X int x, y; X{ X bottom = left = 0; X if (x == xwmin) X left = 2; X if (y == ywmin) X bottom = 1; X if (x == xwmax) X left = 8; X if (y == ywmax) X bottom = 4; X return (bottom + left); X} END_OF_FILE if test 15037 -ne `wc -c <'Vplot_Kernel/filters/genlib/polyfix.c'`; then echo shar: \"'Vplot_Kernel/filters/genlib/polyfix.c'\" unpacked with wrong size! fi # end of 'Vplot_Kernel/filters/genlib/polyfix.c' fi if test -f 'Vplot_Kernel/util/Ta2vplot.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Vplot_Kernel/util/Ta2vplot.c'\" else echo shar: Extracting \"'Vplot_Kernel/util/Ta2vplot.c'\" \(15559 characters\) sed "s/^X//" >'Vplot_Kernel/util/Ta2vplot.c' <<'END_OF_FILE' X/* X * Ta2vplot - reads in a Taplot/Movie format file and outputs a vplot raster X * file. X * X * vplotfile.H X * X * esize: X * X * If esize=1, then the input file is in "Taplot" format. Default is color=I. X * X * If esize=3, then the input file is assumed to contain RGB 3-byte triples. X * The color number that corresponds to the "closest available color" X * to that defined by the triple is used. Default is color=332. X * Using Movie color schemes is slow. (BEWARE "color" set to the wrong X * value by your history file!!!) X * X * Positioning the plot: X * X * xll,yll are the coordinates of the lower left corner of the plot. xur,yur are X * the coordinates of the upper right corner. orient=0,1,2,3 to start plot in X * upper left, upper right, lower right, or lower left. invert=y 'flips' output X * image to agree with movie display. X * X * Annotation: X * X * title,label1, and label2 are strings for axis labelling. titlefat and titlesz X * are the fatness and size of the title. labelfat and labelsz are the fatness X * and size of the axis labels. labelrot = 1 rotates label1 180 degrees o1num X * and d1num are the starting value and increment for labelling the n1 axis. X * o2num and d2num are the starting value and increment for labelling the n2 X * axis. grid=y places a grid line for each label. frame=y draws a frame around X * the plot. axiscol determines the frame, label and title colors d1num = 0 X * turns off the labelling. d1num and d2num MUST be specified. negative fatness X * turns off the title or labels. NOTE: labelling works properly only for X * invert=y orient=1 at this time! X * X * polarity=-1 flips the raster values black to white and white to black X * X * If coltab=n, no color table definition is prepended to the vplot file. nreserve X * is the number of colors for the plotting device that you want to be left X * "free", ie not used in the raster color table. This prevents Ta2vplot from X * overwriting vplot type colors with the grey scale used to display movie X * files. X * X * color= one of {I,i,F,R,W,G} just like in Movie, and also RGB, where X * each of R,G, and B is the number of bits to allot to that primary. X * X * backcol=red,green,blue sets the background color. Each of {red,green,blue} are X * between 0. and 1. X * X * movish=n (if y, halves the color table like movie does) X * X * The resulting vplot file can be displayed using any vplot pen filter. X * Various device-dependent corrections are automatically made by vplot X * to compensate for the peculiarities of each display device. Some of X * these corrections can be controlled by the user. See "man pen" for X * more details. X * X * Keywords: vplot plot movie raster hardcopy rgb color X */ X/* X * EDIT HISTORY: X * Author Steve Cole, March 1987 X * Joe Dellinger, Dec 1987 fixed "color value too large" bug. X * Steve Cole, Dec 1987, changed putch call for movish to avoid problem X * on suns. X * Joe Dellinger, Jan 1988, fixed some bugs involving color mapping, X * and added capability for RGB triples. X * Joe Dellinger Feb 25 1988, vp_style after vp_erase X */ X#ifndef SOURCE X#define SOURCE "/usr/src/sepsrc/Ta2vplot.c" X#endif X#include X#include X#include X#include X X#define SQUARE(A) ((A)*(A)) X int cintensityp[9] = X{ X 0, 128, 255, 0, 128, 255, 0, 128, 255 X}; int cintensityn[9] = X{ X 255, 128, 0, 255, 128, 0, 255, 128, 0 X}; int cflag[9] = X{ X 255, 255, 0, 0, 255, 0, 0, 255, 255 X}; int cbi[9] = X{ X 255, 0, 0, 0, 0, 0, 0, 0, 255 X}; int csurf[9] = X{ X 0, 0, 255, 0, 0, 255, 0, 200, 255 X}; int cgsi[9] = X{ X 0, 255, 255, 0, 255, 0, 0, 255, 0 X}; int *cola; X MAIN () X{ int n1, n2, n3, i3, i4, incr, ii, jj, kk, esize; int labelsz, titlesz, labelfat, titlefat; int labelrot, axiscol, sign; float d1, o1, d2, o2, d3, o3; float pos1, pos2; float xx, yy; char string[80]; float d1num, d2num; float o1num, o2num; int grid, frame; char label1[80], label2[80], title[160]; int offset, xpix, ypix, bit, blast, orient, invert; float xll, yll, xur, yur, ppi; int nreserve; int polarity, coltab; unsigned char *data; char color[10]; extern float rd_color (), gr_color (), bl_color (); float backcol[3]; float back = 0; int movish; int map[256]; int smap[256]; float red[256], green[256], blue[256]; float red_lev, green_lev, blue_lev, error, error_win; int ired_lev, igreen_lev, iblue_lev; int win, redbit, greenbit, bluebit; int redbit2, greenbit2, bluebit2; int redoff, greenoff, blueoff; X X if (!fetch ("n1", "d", &n1)) X err ("n1 not given\n"); X if (!fetch ("n2", "d", &n2)) X err ("n2 not given\n"); X if (!fetch ("n3", "d", &n3)) X n3 = 1; X if (!fetch ("esize", "d", &esize)) X err ("esize not given\n"); X X if (esize != 1 && esize != 3) X err ("esize must be 1 or 3\n"); X X coltab = 1; X fetch ("coltab", "1", &coltab); X if (!coltab && esize == 3) X err ("esize must be 1 if coltab=no\n"); X X if (esize == 1) X strcpy (color, "I"); X else X strcpy (color, "332"); X fetch ("color", "s", color); X X if (!getch ("xll", "f", &xll)) X xll = 1.; X if (!getch ("yll", "f", &yll)) X yll = 1.; X if (!getch ("xur", "f", &xur)) X xur = 5.; X if (!getch ("yur", "f", &yur)) X yur = 5.; X if (!getch ("orient", "d", &orient)) X orient = 1; X if (!getch ("nreserve", "d", &nreserve)) X nreserve = 8; X if (!getch ("invert", "1", &invert)) X invert = 1; X if (!getch ("movish", "1", &movish)) X movish = 0; X X putch_ ("movish", "d", &movish); X X puthead ("\tn1=-1\n"); X X /* Polarity stuff */ X polarity = 1; X fetch ("polarity", "d", &polarity); X putch ("polarity", "d", &polarity); X X /* Axis and labelling parameters */ X strcpy (label1, ""); X strcpy (label2, ""); X strcpy (title, ""); X fetch ("label1", "s", label1); X fetch ("label2", "s", label2); X fetch ("title", "s", title); X o1 = 0.; X o2 = 0.; X d1 = 1.; X d2 = 1.; X fetch ("o1", "f", &o1); X fetch ("o2", "f", &o2); X fetch ("d1", "f", &d1); X fetch ("d2", "f", &d2); X d1num = 0.; X d2num = 0.; X o1num = o1; X o2num = o2; X fetch ("d1num", "f", &d1num); X fetch ("d2num", "f", &d2num); X fetch ("o1num", "f", &o1num); X fetch ("o2num", "f", &o2num); X labelsz = 5; X titlesz = 5; X labelfat = 1; X titlefat = 1; X fetch ("labelsz", "d", &labelsz); X fetch ("titlesz", "d", &titlesz); X fetch ("labelfat", "d", &labelfat); X fetch ("titlefat", "d", &titlefat); X labelrot = 0; X axiscol = 7; X fetch ("labelrot", "1", &labelrot); X fetch ("axiscol", "d", &axiscol); X sign = -1; X if (labelrot) X sign = 1; X X frame = 1; X grid = 1; X fetch ("frame", "1", &frame); X fetch ("grid", "1", &grid); X X if (fetch ("backcol", "f", backcol)) X { X back = 1; X } X blast = 1; X fetch ("hurry", "1", &blast); X X hclose (); X X data = (unsigned char *) alloc (n1 * n2 * esize); X X vp_erase (); X vp_style (STANDARD); X vp_color (axiscol); X X if (coltab) X { X X if (color[0] >= '0' && color[0] <= '9') X { X redbit = color[0] - '0'; X greenbit = color[1] - '0'; X bluebit = color[2] - '0'; X if (redbit + greenbit + bluebit != 8) X err ("You must use exactly 8 bits!\n"); X X redoff = 0; X greenoff = redbit; X blueoff = redbit + greenbit; X X for (i3 = 0; i3 < 256; i3++) X { X ii = ~(~0 << redbit); X if (ii > 0) X red[i3] = (float) ((i3 >> redoff) & ii) / (float) (ii); X else X red[i3] = 0.; X X ii = ~(~0 << greenbit); X if (ii > 0) X green[i3] = (float) ((i3 >> greenoff) & ii) / (float) (ii); X else X green[i3] = 0.; X X ii = ~(~0 << bluebit); X if (ii > 0) X blue[i3] = (float) ((i3 >> blueoff) & ii) / (float) (ii); X else X blue[i3] = 0.; X } X X for (i3 = 256; i3 < 512; i3++) X { X jj = i3 - 256; X X if (movish) X jj = 2 * (int) (jj / 2); X vp_coltab (i3, red[jj], green[jj], blue[jj]); X } X X for (jj = 0; jj < 256; jj++) X { X ii = 0; X greenbit2 = greenbit; X bluebit2 = bluebit; X redbit2 = redbit; X kk = 0; X while (kk < 8) X { X greenbit2--; X if (greenbit2 >= 0) X { X if (jj & (1 << (greenbit2 + greenoff))) X ii |= 1 << kk; X kk++; X } X X redbit2--; X if (redbit2 >= 0) X { X if (jj & (1 << (redbit2 + redoff))) X ii |= 1 << kk; X kk++; X } X X bluebit2--; X if (bluebit2 >= 0) X { X if (jj & (1 << (bluebit2 + blueoff))) X ii |= 1 << kk; X kk++; X } X } X map[ii] = jj; X } X X for (i3 = nreserve; i3 < 256; i3++) X { X jj = i3 - nreserve; X X vp_coltab (i3, red[map[jj]], X green[map[jj]], X blue[map[jj]]); X } X } X else X { X switch (*color) X { X case 'i': X cola = cintensityn; X break; X case 'F': X cola = cflag; X break; X case 'R': X cola = cbi; X break; X case 'W': X cola = csurf; X break; X case 'G': X cola = cgsi; X break; X case 'I': X default: X cola = cintensityp; X break; X } X X /* X * set up a perfect grey scale in colors 256-511. the offset in X * vp_raster maps the pixels into that range. no device actually X * has such colors, so vplot looks at those colors the device X * does have (0 through some n) and picks out the one closest to X * the desired grey. thus by setting up black, white, 50% grey, X * 75% grey, 25% grey, ... in 0-255, we'll get the best grey X * scale for the device. X * X * note: we leave colors 0 through nreserve-1 alone, since they are X * already defined for the device. X * X */ X for (i3 = 0; i3 < 256; i3++) X { X red[i3] = rd_color ((float) i3); X green[i3] = gr_color ((float) i3); X blue[i3] = bl_color ((float) i3); X } X X for (i3 = 256; i3 < 512; i3++) X { X jj = i3 - 256; X X if (movish) X jj = 2 * (int) (jj / 2); X vp_coltab (i3, red[jj], green[jj], blue[jj]); X } X X /* X * set the lower grey scale, which will give us the best grey X * scale possible for the device. X * X * we assume that the device already has colors white and black set. X */ X X i3 = 0; X smap[i3] = 0; X i3++; X if (nreserve == 0) X { X smap[i3] = 255; X i3++; X } X for (incr = 2; incr < 512; incr *= 2) X { X for (i4 = 1; i4 < incr; i4 += 2) X { X jj = i4 * 256 / incr; X smap[i3] = jj; X i3++; X if (i3 == 256) X break; X } X } X X for (i3 = nreserve; i3 < 256; i3++) X { X jj = i3 - nreserve; X X vp_coltab (i3, red[smap[jj]], X green[smap[jj]], X blue[smap[jj]]); X } X X } X if (back) X vp_coltab (0, backcol[0], backcol[1], backcol[2]); X } X /* Set the coordinate transformation */ X vp_orig (xll, yur); X vp_uorig (o2, o1); X vp_scale ((xur - xll) / (d2 * n2), (yll - yur) / (d1 * n1)); X X X /* X * Do the plots X */ X X for (i3 = 0; i3 < n3; i3++) X { X if (i3 != 0) X { X vp_erase (); X vp_style (STANDARD); X vp_color (axiscol); X } X reed (infd, data, n1 * n2 * esize); X if (polarity < 0) X for (ii = 0; ii < n1 * n2 * esize; ii++) X { X data[ii] = (unsigned char) 255 - data[ii]; X } X/* X * If esize=3, then map the RGB triples onto the closest available X * color. X */ X if (esize == 3) X { X if (color[0] >= '0' && color[0] <= '9') X { X for (ii = 0; ii < n1 * n2; ii++) X { X ired_lev = data[esize * ii]; X igreen_lev = data[esize * ii + 1]; X iblue_lev = data[esize * ii + 2]; X X win = 0; X win |= ((ired_lev >> (8 - redbit)) & ~(~0 << redbit)) << redoff; X win |= ((igreen_lev >> (8 - greenbit)) & ~(~0 << greenbit)) << greenoff; X win |= ((iblue_lev >> (8 - bluebit)) & ~(~0 << bluebit)) << blueoff; X data[ii] = win; X } X } X else X { X for (ii = 0; ii < n1 * n2; ii++) X { X red_lev = data[esize * ii] / 255.; X green_lev = data[esize * ii + 1] / 255.; X blue_lev = data[esize * ii + 2] / 255.; X error_win = 8.; X for (jj = 0; jj < 256; jj++) X { X error = 2. * SQUARE (red_lev - red[jj]) + 4. * SQUARE (green_lev - green[jj]) + SQUARE (blue_lev - blue[jj]); X if (error < error_win) X { X error_win = error; X win = jj; X if (error == 0.) X break; X } X } X data[ii] = win; X } X } X } X X /* X * Only offset the colors if we have defined a color table. X * Otherwise, leave them alone. X */ X if (coltab) X offset = 256; X else X offset = 0; X X xpix = n1; X ypix = n2; X bit = 0; X ppi = 0; X vp_raster (data, blast, bit, offset, xpix, ypix, xll, yll, ppi, &xur, &yur, orient, invert); X X vp_fat (1); X if (frame) X { X vp_move (xll, yll); X vp_draw (xll, yur); X vp_draw (xur, yur); X vp_draw (xur, yll); X vp_draw (xll, yll); X } X if (grid) X { X if (d2num > 0) X { X for (pos2 = o2num; pos2 <= o2 + n2 * d2; pos2 += d2num) X { X vp_umove (pos2, o1); X vp_udraw (pos2, o1 + n1 * d1); X } X } X if (d1num > 0) X { X for (pos1 = o1num; pos1 <= o1 + n1 * d1; pos1 += d1num) X { X vp_umove (o2, pos1); X vp_udraw (o2 + n2 * d2, pos1); X } X } X } X if (d2num > 0) X { X vp_fat (labelfat); X vp_tjust (TH_CENTER, TV_BASE); X for (pos2 = o2num; pos2 <= o2 + n2 * d2; pos2 += d2num) X { X vp_umove (pos2, o1); X vp_where (&xx, &yy); X yy += .07; X vp_draw (xx, yy); X yy += .03; X sprintf (string, "%g", pos2); X vp_text (xx, yy, labelsz, 0, string); X } X } X if (d1num > 0) X { X vp_fat (labelfat); X vp_tjust (TH_CENTER, TV_TOP); X for (pos1 = o1num; pos1 <= o1 + n1 * d1; pos1 += d1num) X { X vp_umove (o2, pos1); X vp_where (&xx, &yy); X xx -= .07; X vp_draw (xx, yy); X xx -= .03; X sprintf (string, "%g", pos1); X vp_text (xx, yy, labelsz, -90, string); X } X } X vp_move ((xll + xur) / 2., yur); X vp_where (&xx, &yy); X yy += .07; X yy += .03; X yy += labelsz / TXPERIN; X yy += .15; X vp_fat (labelfat); X vp_tjust (TH_CENTER, TV_BASE); X vp_text (xx, yy, labelsz, 0, label2); X X yy += labelsz / TXPERIN; X yy += .15; X vp_fat (titlefat); X vp_tjust (TH_CENTER, TV_BOTTOM); X vp_text (xx, yy, titlesz, 0, title); X X vp_move (xll, (yll + yur) / 2.); X vp_where (&xx, &yy); X xx -= .07; X xx -= .03; X xx -= labelsz / TXPERIN; X xx -= .15; X vp_fat (labelfat); X if (labelrot) X vp_tjust (TH_CENTER, TV_BOTTOM); X else X vp_tjust (TH_CENTER, TV_TOP); X vp_text (xx, yy, labelsz, sign * 90, label1); X } X} X float rd_color (x) X float x; X{ X if (x < 128) X return (((128. - x) * (float) cola[0] / 128.) + (x * (float) cola[1] / 128.)) / 255.; X else X return (((255. - x) * (float) cola[1] / 127.) + ((x - 128.) * (float) cola[2] / 127.)) / 255.; X} X float gr_color (x) X float x; X{ X if (x < 128) X return (((128. - x) * (float) cola[3] / 128.) + (x * (float) cola[4] / 128.)) / 255.; X else X return (((255. - x) * (float) cola[4] / 127.) + ((x - 128.) * (float) cola[5] / 127.)) / 255.; X} X float bl_color (x) X float x; X{ X if (x < 128) X return (((128. - x) * (float) cola[6] / 128.) + (x * (float) cola[7] / 128.)) / 255.; X else X return (((255. - x) * (float) cola[7] / 127.) + ((x - 128.) * (float) cola[8] / 127.)) / 255.; X} END_OF_FILE if test 15559 -ne `wc -c <'Vplot_Kernel/util/Ta2vplot.c'`; then echo shar: \"'Vplot_Kernel/util/Ta2vplot.c'\" unpacked with wrong size! fi # end of 'Vplot_Kernel/util/Ta2vplot.c' fi echo shar: End of archive 17 \(of 24\). cp /dev/null ark17isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 24 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0