home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / vplot / part23 < prev    next >
Encoding:
Internet Message Format  |  1988-03-31  |  39.3 KB

  1. Subject:  v14i028:  Device-independant graphics system, with drivers
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Joe Dellinger <joe@hanauma.STANFORD.EDU>
  7. Posting-number: Volume 14, Issue 28
  8. Archive-name: vplot/part23
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 23 (of 24)."
  17. # Contents:  Vplot_Kernel/filters/genlib/gentext.c
  18. # Wrapped by rsalz@fig.bbn.com on Fri Mar 25 11:47:35 1988
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'Vplot_Kernel/filters/genlib/gentext.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'Vplot_Kernel/filters/genlib/gentext.c'\"
  22. else
  23. echo shar: Extracting \"'Vplot_Kernel/filters/genlib/gentext.c'\" \(37130 characters\)
  24. sed "s/^X//" >'Vplot_Kernel/filters/genlib/gentext.c' <<'END_OF_FILE'
  25. X/*
  26. X * Copyright 1987 the Board of Trustees of the Leland Stanford Junior
  27. X * University. Official permission to use this software is included in
  28. X * the documentation. It authorizes you to use this file for any
  29. X * non-commercial purpose, provided that this copyright notice is not
  30. X * removed and that any modifications made to this file are commented
  31. X * and dated in the style of my example below.
  32. X */
  33. X
  34. X/*
  35. X *
  36. X *  source file:   ./filters/genlib/gentext.c
  37. X *
  38. X * Joe Dellinger (SEP), June 11 1987
  39. X *    Inserted this sample edit history entry.
  40. X *    Please log any further modifications made to this file:
  41. X */
  42. X/*
  43. X * Joe Dellinger Oct 18 1987
  44. X *     Keep track of fatness as a float, not an int. Round when needed.
  45. X * Joe Dellinger Jan 16 1988
  46. X *    Allow user-defined fonts. As a check, require that they have a
  47. X *    magic sequence on the front. If they ask for a font >= NUMGENFONT,
  48. X *    modulo back into range.
  49. X * Joe Dellinger Feb 16 1988
  50. X *    Make number of arguments to dev.attributes consistent.
  51. X */
  52. X
  53. X/*
  54. X * VPLOT soft text plotting
  55. X *
  56. X * Keywords: vplot text vector hershey font
  57. X */
  58. X#include    <stdio.h>
  59. X#include    <math.h>
  60. X#include    <strings.h>
  61. X#include    <sys/file.h>
  62. X#include    <vplot.h>
  63. X#include    "../include/extern.h"
  64. X#include    "../include/err.h"
  65. X#include    "../include/enum.h"
  66. X#include    "../include/params.h"
  67. X#include    "../include/font_definitions.h"
  68. X#include    "../include/attrcom.h"
  69. X#include    "../include/round.h"
  70. X
  71. X#define        NMARK   8    /* Maximum number of marks to use */
  72. X#define        MAXPOLY 100    /* Maximum number of points in polygon */
  73. X
  74. X/*
  75. X * The font to use for undefined fonts.
  76. X * It should NOT be a runtime-loaded font!
  77. X */
  78. X#define ERRFONT        0
  79. X/*
  80. X * The glyph to use for undefined glyphs.
  81. X * It must be a glyph in the font ERRFONT.
  82. X * Needless to say, this glyph at least had better exist or you're
  83. X * in real trouble.
  84. X */
  85. X/* We use Glyph 30 in font 0, which is a '?' with a square around it. */
  86. X#define ERRGLYPH     (30-font[0].dim[START])
  87. X
  88. X/* Fraction of height of capital letter to use as vertical padding for box */
  89. X#define VSPACE_FRAC  .20
  90. X/* Fraction of inter-letter space to use for horizontal padding of box */
  91. X#define HSPACE_FRAC  0.5
  92. X
  93. X#define EOC 0x8000    /* END OF CHARACTER BIT */
  94. X#define DRAWBIT 0x4000    /* DRAW BIT */
  95. X#define POLYBITS (EOC | DRAWBIT)    /* Polygon */
  96. X#define XBIT 0x0040
  97. X#define YBIT 0x2000
  98. X#define UNDEFINED    -1
  99. X
  100. X#define SIGN_X (glyph_stroke & XBIT)
  101. X#define SIGN_Y (glyph_stroke & YBIT)
  102. X#define DRAW (glyph_stroke & DRAWBIT)
  103. X#define INPOLY ((glyph_stroke & POLYBITS) == POLYBITS)
  104. X
  105. X#define COLOR_MAP(A) color_set[A][MAP];
  106. X
  107. X/*
  108. X * Correct for difference in size between what you want and what you've got
  109. X */
  110. X#define SIZE_FACTOR(A) (((double)tsize/100.)*(A)/(double)(font[ttxfont].dim[CAP]-font[ttxfont].dim[BASE]))
  111. X
  112. X/*
  113. X * When you change sizes or fonts in midstream, what level do you line up on?
  114. X */
  115. X#define ALIGN_HEIGHT    (font[ttxfont].dim[BASE])
  116. X
  117. X#define CONTROL 001
  118. X#define BS    010
  119. X#define CR    015
  120. X#define NL    012
  121. X
  122. static double   path_orient_dx, path_orient_dy;
  123. static double   up_orient_dx, up_orient_dy;
  124. static double   xorigin_f, yorigin_f, xold_f, yold_f;
  125. static int      ttxfont, cur_color_save, overlay_save;
  126. extern int      cur_color, ipat, need_devcolor, overlay;
  127. extern int      color_set[MAX_COL + 1][_NUM_PRIM];
  128. X
  129. extern char    *malloc ();
  130. extern char    *calloc ();
  131. X
  132. X/*
  133. X * interpret characters into vectors
  134. X */
  135. gentext (string, pathx, pathy, upx, upy)
  136. X    char           *string;
  137. X    float           pathx, pathy, upx, upy;
  138. X{
  139. double          fpathx, fpathy, fupx, fupy;
  140. double          up, path;
  141. double          xp, yp;
  142. float           tfat;
  143. int             add;
  144. int             ixp, iyp;
  145. int            *istring;
  146. unsigned short *glyphptr, glyph_stroke;
  147. double          xtxshift, ytxshift;
  148. int             a, b, ii, jj, kk;
  149. int             string_length;
  150. double          last_widthl, last_widthr;
  151. double          widthl_1st_char, char_width, total_width = 0.;
  152. int             tsize, first, ttxfont_save, txfont_checked;
  153. int             ghost = 0;
  154. double          th_symb, th_symb_s, tv_symb, tv_symb_s;
  155. double          char_width_s[NMARK];
  156. double          total_width_s[NMARK];
  157. int             mark_flag[NMARK];
  158. double          last_widthl_s[NMARK], last_widthr_s[NMARK];
  159. double          xold_f_s[NMARK];
  160. double          yold_f_s[NMARK];
  161. double          maxtop, minbot;
  162. double          vspace, hspace, vline;
  163. int             flag;
  164. char           *charp;
  165. int             polycount, xxx[MAXPOLY], yyy[MAXPOLY];
  166. int            *ligp;
  167. static int      one_error = YES;
  168. int             linecount;
  169. X
  170. X    if (*string == '\0')
  171. X    return;
  172. X
  173. X/*
  174. X * Set the initial parameters
  175. X */
  176. X
  177. X/*
  178. X * Convert the input float path vectors to doubles.
  179. X */
  180. X    fpathx = (double) pathx;
  181. X    fpathy = (double) pathy;
  182. X    fupx = (double) upx;
  183. X    fupy = (double) upy;
  184. X
  185. X    path = sqrt ((double) (fpathx * fpathx + fpathy * fpathy));
  186. X    up = sqrt ((double) (fupx * fupx + fupy * fupy));
  187. X
  188. X    if (path == 0. || up == 0.)
  189. X    {
  190. X/* Text got squashed away to nothing */
  191. X    return;
  192. X    }
  193. X
  194. X    path_orient_dx = fpathx / path;
  195. X    path_orient_dy = fpathy / path;
  196. X    up_orient_dx = fupx / up;
  197. X    up_orient_dy = fupy / up;
  198. X
  199. X/*
  200. X * We didn't bomb out right away, so save things we may change so
  201. X * they can be restored at exit
  202. X */
  203. X    cur_color_save = cur_color;
  204. X    overlay_save = overlay;
  205. X
  206. X    overlay = NO;
  207. X
  208. X    for (ii = 0; ii < NMARK; ii++)
  209. X    mark_flag[ii] = 0;
  210. X
  211. X/* Text starts out in the default font at 100% of the requested size */
  212. X    tsize = 100;
  213. X    txfont_checked = txfont;
  214. X
  215. X    if (txfont_checked >= 0)
  216. X    {
  217. X    ttxfont = txfont_checked % NUMGENFONT;
  218. X    if (font[ttxfont] .load == NO)
  219. X    {
  220. X        load_font (txfont_checked);
  221. X    }
  222. X    txfont_checked = ttxfont;
  223. X    }
  224. X    else
  225. X    {
  226. X    txfont_checked = ERRFONT;
  227. X    }
  228. X
  229. X    ttxfont = txfont_checked;
  230. X    total_width = 0.;
  231. X    char_width = font[ttxfont] .dim[SPACE] * SIZE_FACTOR (path);
  232. X    th_symb = char_width / 2.;
  233. X    last_widthl = font[ttxfont] .dim[SPACE] * .5 * SIZE_FACTOR (path);
  234. X    last_widthr = font[ttxfont] .dim[SPACE] * .5 * SIZE_FACTOR (path);
  235. X    widthl_1st_char = font[ttxfont] .dim[SPACE] * .5 * SIZE_FACTOR (path);
  236. X    tv_symb = (font[ttxfont] .dim[HALF] - ALIGN_HEIGHT) * SIZE_FACTOR (up);
  237. X    maxtop = (font[ttxfont] .dim[TOP] - ALIGN_HEIGHT) * SIZE_FACTOR (up);
  238. X    minbot = (font[ttxfont] .dim[BOTTOM] - ALIGN_HEIGHT) * SIZE_FACTOR (up);
  239. X
  240. X/* These used in making the bounding box */
  241. X    vline = (font[ttxfont] .dim[TOP] - font[ttxfont] .dim[BOTTOM] + font[ttxfont] .dim[LINE]) * SIZE_FACTOR (up);
  242. X    vspace = VSPACE_FRAC * (font[ttxfont] .dim[CAP] - font[ttxfont] .dim[BASE]) * SIZE_FACTOR (up);
  243. X    hspace = (HSPACE_FRAC * font[ttxfont] .dim[SPACE] + font[ttxfont] .dim[LETTER]) * SIZE_FACTOR (path);
  244. X
  245. X/*
  246. X * Parse ligatures, control sequences, etc.
  247. X * each object gets 2 ints;
  248. X * The first tells what sort of object it is.
  249. X * Positive == printing character
  250. X * Negative == command
  251. X * The second is there for any parameters that are associated.
  252. X * For normal characters, it gives the glyph number in this font.
  253. X * For commands it gives any parameter the command may have.
  254. X */
  255. X    string_length = strlen (string);
  256. X    istring = (int *) calloc ((unsigned) 2 * (string_length + 1), sizeof (int));
  257. X
  258. X    for (ii = 0, charp = string; (charp - string) < string_length; ii++, charp++)
  259. X    {
  260. X    switch ((int) (*charp))
  261. X    {
  262. X/* Check for special ASCII characters first */
  263. X    case ' ':
  264. X    case NL:
  265. X    case CR:
  266. X    case BS:
  267. X        istring[2 * ii] = -(int) (*charp);
  268. X        continue;
  269. X        break;
  270. X/* Check for \ commands */
  271. X    case '\\':
  272. X        charp++;
  273. X        switch (*charp)
  274. X        {
  275. X/* \\ just falls through and makes a \ with no special properties */
  276. X        case '\\':
  277. X        break;
  278. X/* \ commands with no arguments */
  279. X        case '-':
  280. X        case '>':
  281. X        case '<':
  282. X        case '^':
  283. X        case '_':
  284. X        case 'g':
  285. X        case 'G':
  286. X        case 'n':
  287. X        case 'h':
  288. X        istring[2 * ii] = -(int) (*charp);
  289. X        continue;
  290. X        break;
  291. X/* \ commands with arguments */
  292. X        case 's':
  293. X        case 'f':
  294. X        case 'F':
  295. X        case 'k':
  296. X        case 'r':
  297. X        case 'm':
  298. X        case 'M':
  299. X        case 'v':
  300. X        case 'c':
  301. X        istring[2 * ii] = -(int) (*charp);
  302. X        charp++;
  303. X/* default value of the argument is 0 if they just leave a space */
  304. X        istring[2 * ii + 1] = 0;
  305. X/* read the argument */
  306. X        sscanf (charp, "%d ", &istring[2 * ii + 1]);
  307. X/* skip past it and check for syntax */
  308. X        do
  309. X        {
  310. X            if ((*charp >= '0' && *charp <= '9') ||
  311. X            *charp == '-' || *charp == '+')
  312. X            {
  313. X            charp++;
  314. X            }
  315. X            else
  316. X            ERR (FATAL, name, "In text \\%c must be followed by an integer and then a space.", (char) (-istring[2 * ii]));
  317. X        } while (*charp != ' ');
  318. X
  319. X        if (istring[2 * ii] == -(int) ('v'))
  320. X        {
  321. X/*
  322. X * The \v command.
  323. X * Make an ordinary character with the proper value.
  324. X */
  325. X            istring[2 * ii] = istring[2 * ii + 1];
  326. X            istring[2 * ii + 1] = 0;
  327. X        }
  328. X        else
  329. X        if (istring[2 * ii] == -(int) ('F'))
  330. X        {
  331. X/* Font change command */
  332. X            if (istring[2 * ii + 1] >= 0)
  333. X            {
  334. X            ttxfont = istring[2 * ii + 1] % NUMGENFONT;
  335. X/* On this first pass through, load all the fonts we're going to need */
  336. X            if (font[ttxfont] .load == NO)
  337. X            {
  338. X                load_font (istring[2 * ii + 1]);
  339. X            }
  340. X            istring[2 * ii + 1] = ttxfont;
  341. X            }
  342. X            else
  343. X            {
  344. X/* \F-1  means the default font again. */
  345. X            if (istring[2 * ii + 1] == -1)
  346. X                istring[2 * ii + 1] = txfont_checked;
  347. X            else
  348. X                istring[2 * ii + 1] = ERRFONT;
  349. X            }
  350. X        }
  351. X        else
  352. X        if (istring[2 * ii] == -(int) ('c'))
  353. X        {
  354. X/* Color change command */
  355. X            if (istring[2 * ii + 1] == -1)
  356. X            {
  357. X/*
  358. X * They want to return to the original text color.
  359. X * This has already been checked to be within range and
  360. X * properly mapped, so just use it!
  361. X */
  362. X            istring[2 * ii + 1] = cur_color_save;
  363. X            }
  364. X            else
  365. X            {
  366. X/*
  367. X * Map from the color asked for to the colors that are available.
  368. X * Normally only dovplot is allowed to do this, but this is an
  369. X * unusual case where dovplot can't do it for us.
  370. X */
  371. X            if (istring[2 * ii + 1] > MAX_COL || istring[2 * ii + 1] < 0)
  372. X                ERR (FATAL, name, "(gentext) bad color number %d (max %d, min 0)",
  373. X                 istring[2 * ii + 1], MAX_COL);
  374. X            istring[2 * ii + 1] = COLOR_MAP (istring[2 * ii + 1]);
  375. X            }
  376. X        }
  377. X        continue;
  378. X        break;
  379. X        default:
  380. X        ERR (WARN, name, "(gentext) Unknown command \\%c.", *charp);
  381. X        charp--;
  382. X        break;
  383. X        }
  384. X    default:
  385. X        break;
  386. X    }
  387. X/* Normal character */
  388. X    istring[2 * ii] = (int) (*charp);
  389. X    }
  390. X    string_length = ii;
  391. X
  392. X/* Ligatures */
  393. X    if (txprec > 1)
  394. X    {
  395. X    ttxfont = txfont_checked;
  396. X/*
  397. X * Turning things into ligatures can only make the string shorter.
  398. X * ii keeps track of where we are without ligatures,
  399. X * kk keeps track of where we are with ligatures included.
  400. X * The string is copied back into itself. Since ii >= kk, there is
  401. X * no recursion problem.
  402. X */
  403. X    for (ii = 0, kk = 0; ii < string_length; ii++, kk++)
  404. X    {
  405. X        if (istring[2 * ii] < 0)
  406. X        {
  407. X/*
  408. X * The only special command we care about for constructing ligatures
  409. X * is the font change command, since ligatures are font dependent.
  410. X * The commands WILL break up a ligature, but other than that aren't
  411. X * interpreted at all here.
  412. X */
  413. X        if (-istring[2 * ii] == 'F')
  414. X            ttxfont = istring[2 * ii + 1];
  415. X        istring[2 * kk] = istring[2 * ii];
  416. X        istring[2 * kk + 1] = istring[2 * ii + 1];
  417. X        continue;
  418. X        }
  419. X
  420. X/*
  421. X * Take the first ligature that matches. This means that longer ligatures
  422. X * MUST be listed first in the font data!
  423. X */
  424. X/*
  425. X * Loop over ligatures.
  426. X * Each ligature has 1 number at the beginning giving the number of characters
  427. X * in this ligature. The next number gives the glyph that is drawn for this
  428. X * ligature. The next several numbers give the glyphs that are combined.
  429. X * ligp points to the ligature we are currently searching for.
  430. X * ligp += 2 + ligp[0] moves to the beginning of the next ligature:
  431. X * 2 places for the 2 numbers at the beginning plus the ligp[0] characters
  432. X * making up the ligature.
  433. X */
  434. X        for (ligp = font[ttxfont] .lig; ligp[0] > 0; ligp += 2 + ligp[0])
  435. X        {
  436. X/* Is there enough room before the end to possibly make this? */
  437. X        if (ii + ligp[0] - 1 < string_length)
  438. X        {
  439. X/* Loop over the characters in the ligature */
  440. X            for (jj = 0; jj < ligp[0]; jj++)
  441. X            {
  442. X/* Didn't match. Stop looking on this one. */
  443. X            if (ligp[jj + 2] != istring[2 * (ii + jj)])
  444. X                goto failed;
  445. X            }
  446. X/* Got to the end and so it worked. Put in the glyph for the ligature */
  447. X            istring[2 * kk] = ligp[1];
  448. X/* skip past the ligp[0] characters in the original string that went into it */
  449. X            ii += ligp[0] - 1;
  450. X            goto success;
  451. X        }
  452. X    failed:
  453. X        continue;
  454. X        }
  455. X/* No ligatures for this one. Copy it across unchanged */
  456. X        istring[2 * kk] = istring[2 * ii];
  457. X/*
  458. X * Don't need to look at any more ligatures for this character
  459. X * (Ligatures don't nest)
  460. X */
  461. X    success:
  462. X        continue;
  463. X    }
  464. X/* Update the length of the string */
  465. X    string_length = kk;
  466. X    }
  467. X
  468. X
  469. X/************************************************************************/
  470. X/************************************************************************/
  471. X
  472. X/*
  473. X * This section conducts a "dry run" through the text string to determine
  474. X * its length.
  475. X *
  476. X * Each character has a left half-width (widthl) and a right half-width (widthr).
  477. X * These give the left and right half-widths of the character's bounding box
  478. X * away from the character's origin.
  479. X * The vertical dimensions of each character's bounding box are a function of
  480. X * the font only; font[font_number].dim[TOP] and font[font_number].dim[BOTTOM]
  481. X * give the coordinates in font units of the top and bottom of the character's box.
  482. X *
  483. X * Each character is also separated from its neighbors by an inter-letter space
  484. X * (font[font_number].dim[LETTER]). This is effectively tacked onto the beginning
  485. X * of each new character, with the exception of the first.
  486. X *
  487. X * When we actually output vectors we will start with the center of the
  488. X * 1st character as our origin. (So we have to remember the left half-width
  489. X * in order to be able to compensate for the fact that we measure the length
  490. X * of the string starting from the left hand edge of the first character.)
  491. X * Variables like "char_width" keep track of the latest character's width
  492. X * in case we have to back up over it again.
  493. X *
  494. X * Multiplying by SIZE_FACTOR converts from the Font's units to Vplot's.
  495. X * (Horizontal scales with "path", vertical scales with "up". These simply
  496. X * give the length of the path and up vectors.)
  497. X * All variables except for those in the font structure itself are in Vplot units.
  498. X *
  499. X * Left and right the total width of everything (characters and inter-spaces
  500. X * between them) is summed into total_width. This is used to do the horizontal
  501. X * text justification.
  502. X *
  503. X * Up and down the highest top and lowest bottom to date are saved in "maxtop" and
  504. X * "minbot". These are used for vertical text justification. "ALIGN_HEIGHT"
  505. X * gives the effective origin for vertical glyph positioning.
  506. X *
  507. X * The "symb" variables keep track of the symbol position of the latest character.
  508. X */
  509. X    first = 1;
  510. X    flag = 1;
  511. X    linecount = 1;
  512. X    ttxfont = txfont_checked;
  513. X    for (ii = 0; ii < string_length; ii++)
  514. X    {
  515. X/* 
  516. X * Figure the lenth of the message string.
  517. X * Justification is based on the first line of text only
  518. X * (That's what "flag" is for)
  519. X */
  520. X
  521. X/*
  522. X * Check for special characters
  523. X */
  524. X    if (istring[2 * ii] < 0)
  525. X    {
  526. X        switch (-istring[2 * ii])
  527. X        {
  528. X        case 'n':
  529. X        case NL:
  530. X        linecount++;
  531. X        case CR:
  532. X        flag = 0;
  533. X        break;
  534. X        case 'h':
  535. X        case BS:
  536. X        total_width -= font[ttxfont] .dim[LETTER] *
  537. X         SIZE_FACTOR (path) + char_width;
  538. X        break;
  539. X        case 'F':
  540. X/* Change the font */
  541. X        ttxfont = istring[2 * ii + 1];
  542. X        break;
  543. X        case 's':
  544. X/* Change the size. This affects the SIZE_FACTOR. */
  545. X        tsize = istring[2 * ii + 1];
  546. X        break;
  547. X        case 'k':
  548. X        if (flag)
  549. X        {
  550. X/*
  551. X * Add in the blank space created by horizontal 'k'earning.
  552. X * This is measured in percent of the width of a space in this font.
  553. X *
  554. X * Similar vertical movements are ignored for the purposes of justification.
  555. X */
  556. X            total_width += font[ttxfont] .dim[SPACE]
  557. X             * SIZE_FACTOR (path) * (istring[2 * ii + 1] / 100.);
  558. X        }
  559. X        break;
  560. X        case 'm':
  561. X        if (istring[2 * ii + 1] < 0 || istring[2 * ii + 1] >= NMARK)
  562. X            ERR (FATAL, name,
  563. X             "(gentext) Too high a mark number %d", istring[2 * ii + 1]);
  564. X/* Save all relevant parameters as they are at this instant */
  565. X        if (flag)
  566. X        {
  567. X/* Vertical symbol alignment position */
  568. X            tv_symb_s = tv_symb;
  569. X/* Horizontal symbol alignment position */
  570. X            th_symb_s = th_symb;
  571. X/* Width of this character (in case the next thing is a backspace) */
  572. X            char_width_s[istring[2 * ii + 1]] = char_width;
  573. X/* The width so far up to this point */
  574. X            total_width_s[istring[2 * ii + 1]] = total_width;
  575. X        }
  576. X        mark_flag[istring[2 * ii + 1]] = 1;
  577. X        break;
  578. X        case 'M':
  579. X        if (istring[2 * ii + 1] < 0 || istring[2 * ii + 1] >= NMARK)
  580. X            ERR (FATAL, name,
  581. X             "(gentext) Too high a mark number %d", istring[2 * ii + 1]);
  582. X/* Make sure it isn't junk */
  583. X        if (!mark_flag[istring[2 * ii + 1]])
  584. X            ERR (FATAL, name,
  585. X             "(gentext) Attempt to use undefined mark number %d",
  586. X             istring[2 * ii + 1]);
  587. X/*
  588. X * Restore the parameters previously saved. All events after that point
  589. X * are now ignored for the purposes of justification.
  590. X */
  591. X        if (flag)
  592. X        {
  593. X            tv_symb = tv_symb_s;
  594. X            th_symb = th_symb_s;
  595. X            char_width = char_width_s[istring[2 * ii + 1]];
  596. X            total_width = total_width_s[istring[2 * ii + 1]];
  597. X        }
  598. X        break;
  599. X        case '-':        /* Nothing */
  600. X        break;
  601. X        case '>':        /* Forward one inter-letter space */
  602. X        if (flag)
  603. X            total_width += font[ttxfont] .dim[LETTER]
  604. X             * SIZE_FACTOR (path);
  605. X        break;
  606. X        case '<':        /* Remove one inter-letter space */
  607. X        if (flag)
  608. X            total_width -= font[ttxfont] .dim[LETTER]
  609. X             * SIZE_FACTOR (path);
  610. X        break;
  611. X        case '^':        /* Up a half letter */
  612. X        case '_':        /* Down a half letter */
  613. X        case 'g':        /* Make text invisible */
  614. X        case 'G':        /* Make text visible again */
  615. X        break;
  616. X        case ' ':        /* Space */
  617. X        if (flag)
  618. X        {
  619. X            char_width = font[ttxfont] .dim[SPACE]
  620. X             * SIZE_FACTOR (path);
  621. X            th_symb = char_width / 2.;
  622. X            tv_symb = (font[ttxfont] .dim[HALF] - ALIGN_HEIGHT)
  623. X             * SIZE_FACTOR (up);
  624. X            total_width += char_width;
  625. X            if (first)
  626. X            {
  627. X/* If it is the first character, remember the left half width */
  628. X            widthl_1st_char = font[ttxfont] .dim[SPACE] * .5
  629. X             * SIZE_FACTOR (path);
  630. X/* No longer at the first printable character */
  631. X            first = 0;
  632. X            }
  633. X            else
  634. X            {
  635. X/* else add inter-letter space between it and the previous character */
  636. X            total_width += font[ttxfont] .dim[LETTER]
  637. X             * SIZE_FACTOR (path);
  638. X            }
  639. X        }
  640. X        break;
  641. X        }
  642. X        continue;
  643. X    }
  644. X
  645. X    if (flag)
  646. X    {
  647. X/*
  648. X * There are 2 ways a glyph can be undefined: it can be outside the range of
  649. X * the font, OR it can have no data associated with it
  650. X */
  651. X        if (istring[2 * ii] >= font[ttxfont] .dim[START] && istring[2 * ii] <= font[ttxfont] .dim[END])
  652. X        {
  653. X/* Find the glyph number, and save it so we don't have to recalculate it */
  654. X        istring[2 * ii + 1] = istring[2 * ii] - font[ttxfont] .dim[START];
  655. X        if (font[ttxfont] .saddr[istring[2 * ii + 1]] != UNDEFINED)
  656. X        {
  657. X/* OK glyph */
  658. X/* In case it's the last one, save its vertical symbol position */
  659. X            tv_symb = (font[ttxfont] .symbol[istring[2 * ii + 1]] - ALIGN_HEIGHT)
  660. X             * SIZE_FACTOR (up);
  661. X/* And in case we back up later its width */
  662. X            char_width = (font[ttxfont] .swidthl[istring[2 * ii + 1]] +
  663. X                font[ttxfont] .swidthr[istring[2 * ii + 1]])
  664. X             * SIZE_FACTOR (path);
  665. X/* and horizontal symbol position */
  666. X            th_symb = font[ttxfont] .swidthr[istring[2 * ii + 1]]
  667. X             * SIZE_FACTOR (path);
  668. X/* See if it sets a new record high */
  669. X            if ((font[ttxfont] .dim[TOP] - ALIGN_HEIGHT) * SIZE_FACTOR (up) > maxtop)
  670. X            maxtop = (font[ttxfont] .dim[TOP] - ALIGN_HEIGHT) * SIZE_FACTOR (up);
  671. X/* Or a record low */
  672. X            if ((font[ttxfont] .dim[BOTTOM] - ALIGN_HEIGHT)
  673. X            * SIZE_FACTOR (up) < minbot)
  674. X            minbot = (font[ttxfont] .dim[BOTTOM] - ALIGN_HEIGHT)
  675. X             * SIZE_FACTOR (up);
  676. X/* Add it into the total width */
  677. X            total_width += char_width;
  678. X            if (first)
  679. X            {
  680. X/* If it's the first remember its left half width */
  681. X            widthl_1st_char = font[ttxfont] .swidthl[istring[2 * ii + 1]]
  682. X             * SIZE_FACTOR (path);
  683. X            }
  684. X            else
  685. X            {
  686. X/* or if not first add in the space between it and the previous glyph */
  687. X            total_width += font[ttxfont] .dim[LETTER]
  688. X             * SIZE_FACTOR (path);
  689. X            }
  690. X        }
  691. X        else
  692. X        {
  693. X/* Second way to be undefined. Turn it into a "special" character */
  694. X            istring[2 * ii] = UNDEFINED;
  695. X        }
  696. X        }
  697. X        else
  698. X        {
  699. X/* First way to be undefined. Turn it into a "special" character */
  700. X        istring[2 * ii] = UNDEFINED;
  701. X        }
  702. X
  703. X        if (istring[2 * ii] == UNDEFINED)
  704. X        {
  705. X/*
  706. X * If it is undefined, use the special "ERROR" glyph and then
  707. X * treat that just like we would treat a regular character.
  708. X */
  709. X        ttxfont_save = ttxfont;
  710. X        ttxfont = ERRFONT;
  711. X        istring[2 * ii + 1] = ERRGLYPH;
  712. X        char_width = (font[ttxfont] .swidthl[ERRGLYPH] +
  713. X                  font[ttxfont] .swidthr[ERRGLYPH])
  714. X         * SIZE_FACTOR (path);
  715. X        th_symb = font[ttxfont] .swidthr[ERRGLYPH] * SIZE_FACTOR (path);
  716. X        tv_symb = (font[ttxfont] .symbol[ERRGLYPH] - ALIGN_HEIGHT)
  717. X         * SIZE_FACTOR (up);
  718. X        if ((font[ttxfont] .dim[TOP] - ALIGN_HEIGHT) * SIZE_FACTOR (up) > maxtop)
  719. X            maxtop = (font[ttxfont] .dim[TOP] - ALIGN_HEIGHT) * SIZE_FACTOR (up);
  720. X        if ((font[ttxfont] .dim[BOTTOM] - ALIGN_HEIGHT) * SIZE_FACTOR (up) < minbot)
  721. X            minbot = (font[ttxfont] .dim[BOTTOM] - ALIGN_HEIGHT) * SIZE_FACTOR (up);
  722. X        total_width += char_width;
  723. X        if (first)
  724. X        {
  725. X            widthl_1st_char = font[ttxfont] .swidthl[ERRGLYPH] * SIZE_FACTOR (path);
  726. X        }
  727. X        else
  728. X            total_width += font[ttxfont] .dim[LETTER] * SIZE_FACTOR (path);
  729. X        ttxfont = ttxfont_save;
  730. X        }
  731. X
  732. X/* We printed something, so we aren't at the first character anymore */
  733. X        first = 0;
  734. X    }
  735. X    else
  736. X    {
  737. X/*
  738. X * If we're past the first line of text, do the few things that aren't related
  739. X * to justification (looking for undefined glyphs, finding the glyph numbers)
  740. X */
  741. X        if (istring[2 * ii] >= font[ttxfont] .dim[START] && istring[2 * ii] <= font[ttxfont] .dim[END])
  742. X        {
  743. X        istring[2 * ii + 1] = istring[2 * ii] - font[ttxfont] .dim[START];
  744. X        if (font[ttxfont] .saddr[istring[2 * ii + 1]] == UNDEFINED)
  745. X        {
  746. X            istring[2 * ii] = UNDEFINED;
  747. X        }
  748. X        }
  749. X        else
  750. X        {
  751. X        istring[2 * ii] = UNDEFINED;
  752. X        }
  753. X        if (istring[2 * ii] == UNDEFINED)
  754. X        {
  755. X        istring[2 * ii + 1] = ERRGLYPH;
  756. X        }
  757. X    }
  758. X    }
  759. X
  760. X/*
  761. X *  Set the proper alignment from the calculated length of the 
  762. X *  text string. Remember that when we plot zero will be in the center
  763. X *  of the first character and not the left hand edge of the first character,
  764. X *  so we have to use widthl_1st_char to compensate for that.
  765. X */
  766. X    switch (txalign.hor)
  767. X    {
  768. X    case TH_SYMBOL:
  769. X    xtxshift = total_width - widthl_1st_char - th_symb;
  770. X    break;
  771. X    case TH_CENTER:
  772. X    xtxshift = total_width / 2. - widthl_1st_char;
  773. X    break;
  774. X    case TH_RIGHT:
  775. X    xtxshift = total_width - widthl_1st_char;
  776. X    break;
  777. X    case TH_NORMAL:
  778. X    case TH_LEFT:
  779. X    default:
  780. X    xtxshift = -widthl_1st_char;
  781. X    break;
  782. X    }
  783. X
  784. X    tsize = 100;
  785. X    ttxfont = txfont_checked;
  786. X    tfat = fat;
  787. X
  788. X/*
  789. X * CAP, HALF, and BASE are calculated based on font and size of default
  790. X * TOP and BOTTOM are based on highest TOP and lowest BOTTOM of all
  791. X * glyphs in string.
  792. X */
  793. X    switch (txalign.ver)
  794. X    {
  795. X    case TV_SYMBOL:
  796. X    ytxshift = tv_symb;
  797. X    break;
  798. X    case TV_TOP:
  799. X    ytxshift = maxtop;
  800. X    break;
  801. X    case TV_CAP:
  802. X    ytxshift = (font[ttxfont] .dim[CAP] - ALIGN_HEIGHT) * SIZE_FACTOR (up);
  803. X    break;
  804. X    case TV_HALF:
  805. X    ytxshift = (font[ttxfont] .dim[HALF] - ALIGN_HEIGHT) * SIZE_FACTOR (up);
  806. X    break;
  807. X    case TV_BOTTOM:
  808. X    ytxshift = minbot;
  809. X    break;
  810. X    case TV_NORMAL:
  811. X    case TV_BASE:
  812. X    default:
  813. X    ytxshift = (font[ttxfont] .dim[BASE] - ALIGN_HEIGHT) * SIZE_FACTOR (up);
  814. X    break;
  815. X    }
  816. X
  817. X
  818. X/************************************************************************/
  819. X/************************************************************************/
  820. X
  821. X
  822. X/*
  823. X * This part of the code draws the characters.
  824. X *
  825. X * The complexity arises because when we do each character we have to
  826. X * be at its CENTER in the left-right direction and at its ALIGN_HEIGHT
  827. X * in the up-down direction.
  828. X * So to move from one character to the next we have to move over by
  829. X * the right half-width of the previous character, an inter-letter space,
  830. X * and then the left half-width of the character we're on!
  831. X * This helps to make the code confusing.
  832. X *
  833. X * We also have to always be ready to unexpectedly back up over the last
  834. X * character, so we also have to keep around the left half-width of the
  835. X * previous character as well.
  836. X */
  837. X    xold_f = xold;
  838. X    yold_f = yold;
  839. X
  840. X/*
  841. X * The "mov" routine moves us around in the cock-eyed coordinate system
  842. X * determined by the up and path vectors. There's no problem if these
  843. X * vectors aren't orthogonal!
  844. X */
  845. X    mov (-xtxshift, -ytxshift);
  846. X    xorigin_f = xold_f;
  847. X    yorigin_f = yold_f;
  848. X
  849. X    if (txovly)
  850. X    {
  851. X    mov (-widthl_1st_char - hspace, minbot - vline * (linecount - 1) - vspace);
  852. X    xxx[0] = ROUND (xold_f);
  853. X    yyy[0] = ROUND (yold_f);
  854. X    mov (0., maxtop - minbot + vline * (linecount - 1) + 2. * vspace);
  855. X    xxx[1] = ROUND (xold_f);
  856. X    yyy[1] = ROUND (yold_f);
  857. X    mov (total_width + 2. * hspace, 0.);
  858. X    xxx[2] = ROUND (xold_f);
  859. X    yyy[2] = ROUND (yold_f);
  860. X    mov (0., -(maxtop - minbot + vline * (linecount - 1) + 2. * vspace));
  861. X    xxx[3] = ROUND (xold_f);
  862. X    yyy[3] = ROUND (yold_f);
  863. X
  864. X    if (txovly == 2 || txovly == 3)
  865. X    {
  866. X        if (cur_color != 0 || need_devcolor)
  867. X        {
  868. X        cur_color = 0;
  869. X        dev.attributes (SET_COLOR, cur_color, 0, 0, 0);
  870. X        need_devcolor = NO;
  871. X        }
  872. X        drawpolygon (4, xxx, yyy);
  873. X        if (cur_color != cur_color_save || need_devcolor)
  874. X        {
  875. X        cur_color = cur_color_save;
  876. X        dev.attributes (SET_COLOR, cur_color, 0, 0, 0);
  877. X        need_devcolor = NO;
  878. X        }
  879. X    }
  880. X
  881. X    if (txovly == 1 || txovly == 3)
  882. X    {
  883. X        dev.vector (xxx[0], yyy[0], xxx[1], yyy[1], ROUND (tfat), 0);
  884. X        dev.vector (xxx[1], yyy[1], xxx[2], yyy[2], ROUND (tfat), 0);
  885. X        dev.vector (xxx[2], yyy[2], xxx[3], yyy[3], ROUND (tfat), 0);
  886. X        dev.vector (xxx[3], yyy[3], xxx[0], yyy[0], ROUND (tfat), 0);
  887. X    }
  888. X
  889. X    xold_f = xorigin_f;
  890. X    yold_f = yorigin_f;
  891. X    }
  892. X
  893. X    first = 1;
  894. X
  895. X/*
  896. X * This is where the actual drawing of the characters takes place.
  897. X * Loop over all the characters in the string
  898. X */
  899. X    for (ii = 0; ii < string_length; ii++)
  900. X    {
  901. X/*
  902. X * Check for special characters first
  903. X */
  904. X    if (istring[2 * ii] < 0)
  905. X    {
  906. X        switch (-istring[2 * ii])
  907. X        {            /* standard carriage controls */
  908. X        case 'h':
  909. X        case BS:
  910. X        mov (-font[ttxfont] .dim[LETTER] * SIZE_FACTOR (path) -
  911. X             (last_widthl + last_widthr), 0.);
  912. X        break;
  913. X        case NL:
  914. X        case 'n':
  915. X        xold_f = xorigin_f;
  916. X        yold_f = yorigin_f;
  917. X        mov (0., -(
  918. X               (font[ttxfont] .dim[TOP] - font[ttxfont] .dim[BOTTOM] + font[ttxfont] .dim[LINE])
  919. X               * SIZE_FACTOR (up)));
  920. X        xorigin_f = xold_f;
  921. X        yorigin_f = yold_f;
  922. X        first = 1;
  923. X        break;
  924. X        case CR:
  925. X        xold_f = xorigin_f;
  926. X        yold_f = yorigin_f;
  927. X        first = 1;
  928. X        break;
  929. X        case 'F':
  930. X        ttxfont = istring[2 * ii + 1];
  931. X        break;
  932. X        case 'c':
  933. X        if (cur_color != istring[2 * ii + 1] || need_devcolor)
  934. X        {
  935. X            cur_color = istring[2 * ii + 1];
  936. X            dev.attributes (SET_COLOR, cur_color, 0, 0, 0);
  937. X            need_devcolor = NO;
  938. X        }
  939. X        break;
  940. X        case 's':
  941. X        tsize = istring[2 * ii + 1];
  942. X        break;
  943. X        case 'f':
  944. X        tfat += istring[2 * ii + 1] * fatmult;
  945. X        break;
  946. X        case 'k':
  947. X/* Horizontal motion */
  948. X        mov (font[ttxfont] .dim[SPACE] * SIZE_FACTOR (path) *
  949. X             (istring[2 * ii + 1] / 100.), 0.);
  950. X        break;
  951. X        case 'r':
  952. X/* Vertical motion */
  953. X        mov (0., (font[ttxfont] .dim[CAP] - font[ttxfont] .dim[BASE])
  954. X             * SIZE_FACTOR (up) * (istring[2 * ii + 1] / 100.));
  955. X        break;
  956. X        case 'm':
  957. X/*
  958. X * Save the current position. No need to check mark number valid; this
  959. X * was checked when we did the justification
  960. X */
  961. X        last_widthl_s[istring[2 * ii + 1]] = last_widthl;
  962. X        last_widthr_s[istring[2 * ii + 1]] = last_widthr;
  963. X        xold_f_s[istring[2 * ii + 1]] = xold_f;
  964. X        yold_f_s[istring[2 * ii + 1]] = yold_f;
  965. X        break;
  966. X        case 'M':
  967. X/*
  968. X * Restore the current position
  969. X */
  970. X        last_widthl = last_widthl_s[istring[2 * ii + 1]];
  971. X        last_widthr = last_widthr_s[istring[2 * ii + 1]];
  972. X        xold_f = xold_f_s[istring[2 * ii + 1]];
  973. X        yold_f = yold_f_s[istring[2 * ii + 1]];
  974. X        break;
  975. X        case 'G':
  976. X        ghost = 0;
  977. X        break;
  978. X        case 'g':
  979. X        ghost = 1;
  980. X        break;
  981. X        case '^':
  982. X/* Up half a character */
  983. X        mov (0.,
  984. X             (font[ttxfont] .dim[CAP] - font[ttxfont] .dim[BASE])
  985. X             * (.5) * SIZE_FACTOR (up));
  986. X        break;
  987. X        case '_':
  988. X/* Down half a character */
  989. X        mov (0., -(
  990. X            (font[ttxfont] .dim[CAP] - font[ttxfont] .dim[BASE])
  991. X               * (.5) * SIZE_FACTOR (up)));
  992. X        break;
  993. X        case '-':
  994. X        break;
  995. X        case '>':
  996. X/* Right an inter-letter space */
  997. X        mov (font[ttxfont] .dim[LETTER] * SIZE_FACTOR (path), 0.);
  998. X        break;
  999. X        case '<':
  1000. X/* Left an inter-letter space */
  1001. X        mov (-(font[ttxfont] .dim[LETTER] * SIZE_FACTOR (path)), 0.);
  1002. X        break;
  1003. X        case -(UNDEFINED):
  1004. X        /* Don't overload them with error messages */
  1005. X        if (one_error)
  1006. X        {
  1007. X            ERR (WARN, name,
  1008. X             "(gentext) Attempt(s) to use undefined glyph(s) in font %d",
  1009. X             ttxfont);
  1010. X            one_error = NO;
  1011. X        }
  1012. X/* Switch to use the ERROR glyph, and the treat it as a regular glyph */
  1013. X        ttxfont_save = ttxfont;
  1014. X        ttxfont = ERRFONT;
  1015. X        goto not_special;
  1016. X        break;
  1017. X        case ' ':
  1018. X        default:
  1019. X        if (!first)
  1020. X        {
  1021. X            mov (
  1022. X             (font[ttxfont] .dim[SPACE] * .5 +
  1023. X              font[ttxfont] .dim[LETTER])
  1024. X             * SIZE_FACTOR (path)
  1025. X             + last_widthr
  1026. X             ,0.);
  1027. X        }
  1028. X        else
  1029. X        {
  1030. X            first = 0;
  1031. X        }
  1032. X        last_widthl = font[ttxfont] .dim[SPACE] * .5 * SIZE_FACTOR (path);
  1033. X        last_widthr = font[ttxfont] .dim[SPACE] * .5 * SIZE_FACTOR (path);
  1034. X        break;
  1035. X        }
  1036. X    }
  1037. X    else
  1038. X    {
  1039. X    not_special:
  1040. X/*
  1041. X *  Printable character.
  1042. X *  Pull out the actual strokes that make up each glyph.
  1043. X *  First get the address of the character from the address array
  1044. X *  Get the address by adding the offset (add) to the base array address
  1045. X *  (font[ttxfont].svec).
  1046. X */
  1047. X        add = font[ttxfont] .saddr[istring[2 * ii + 1]];
  1048. X        glyphptr = font[ttxfont] .svec + add;
  1049. X/*
  1050. X * Now that we have the address of the fonts,
  1051. X * we position the pen at the beginning of the next character
  1052. X * (Unless it's the first printable character in which case we are already
  1053. X *  there)
  1054. X */
  1055. X        if (!first)
  1056. X        {
  1057. X        mov (
  1058. X             (font[ttxfont] .swidthl[istring[2 * ii + 1]] +
  1059. X              font[ttxfont] .dim[LETTER])
  1060. X             * SIZE_FACTOR (path)
  1061. X             + last_widthr
  1062. X             ,0.);
  1063. X        }
  1064. X        else
  1065. X        first = 0;
  1066. X
  1067. X/* Save the left and right half-widths of this glyph */
  1068. X        last_widthl = font[ttxfont] .swidthl[istring[2 * ii + 1]]
  1069. X         * SIZE_FACTOR (path);
  1070. X        last_widthr = font[ttxfont] .swidthr[istring[2 * ii + 1]]
  1071. X         * SIZE_FACTOR (path);
  1072. X
  1073. X/*
  1074. X * Calculate where to position each character in high precision.
  1075. X */
  1076. X        xnew = ROUND (xold_f);
  1077. X        ynew = ROUND (yold_f);
  1078. X/*
  1079. X * This loop contains the structure for the actual drawing of the characters
  1080. X * We go through this block until an "END OF CHARACTER" is read
  1081. X *
  1082. X *  Strokes are kept in a packed format to save
  1083. X *  space. Each stroke is packed into an unsigned
  1084. X *  short int with the following format: 
  1085. X *
  1086. X *         edsyyyyyysxxxxxx
  1087. X *         ||||____|||____|--> The x-coordinate value
  1088. X *         |||   |  `--------> Set if X < 0            
  1089. X *         |||   `-----------> The y-coordinate value
  1090. X *         ||`---------------> Set if Y < 0
  1091. X *         |`----------------> Draw bit, set if
  1092. X *         |                    command is draw.
  1093. X *         |                    Clear, if move.
  1094. X *         `-----------------> End of Character Bit
  1095. X *
  1096. X *  This is enough bits per coordinate to accomodate all the "Hershey" fonts.
  1097. X *
  1098. X *  Polygons are also encoded into this scheme. If the EOC and DRAW bits
  1099. X *  are simultaneously on, then we are inside a polygon. The last point of
  1100. X *  the polygon will only have the draw flag on, and at that point the entire
  1101. X *  polygon will be outputted.
  1102. X */
  1103. X
  1104. X        polycount = 0;
  1105. X
  1106. X        while ((glyph_stroke = *glyphptr++) != EOC)
  1107. X        {
  1108. X        a = glyph_stroke & 077;
  1109. X        if (SIGN_X)
  1110. X            a = -a;
  1111. X        b = (glyph_stroke >> 7) & 077;
  1112. X        if (SIGN_Y)
  1113. X            b = -b;
  1114. X        b -= ALIGN_HEIGHT;
  1115. X
  1116. X/*
  1117. X * Here is the correct place to insert code to rotate a glyph.
  1118. X * You want to do that before it gets distorted by the global coordinate
  1119. X * transformation. The "ALIGN_HEIGHT" defines where the vertical origin
  1120. X * is for a glyph in a font. Note that we are in the font's coordinate
  1121. X * system units at this point.
  1122. X */
  1123. X        xp = xold_f;
  1124. X        yp = yold_f;
  1125. X/*
  1126. X * Cock-eyed coordinate system.
  1127. X * "up" is in the direction of the up vector,
  1128. X * "right" is in the direction of the path vector.
  1129. X * These can be screwy, and thus distort the glyph.
  1130. X *
  1131. X * "path" and "up" contain the magnitude, and the
  1132. X * "orient_dx"'s and "orient_dy"'s contain the direction cosines
  1133. X */
  1134. X        xp += SIZE_FACTOR (path) * a * path_orient_dx +
  1135. X         SIZE_FACTOR (up) * b * up_orient_dx;
  1136. X        yp += SIZE_FACTOR (path) * a * path_orient_dy +
  1137. X         SIZE_FACTOR (up) * b * up_orient_dy;
  1138. X        ixp = ROUND (xp);
  1139. X        iyp = ROUND (yp);
  1140. X
  1141. X        if (polycount > 0 && !INPOLY)
  1142. X        {
  1143. X/*
  1144. X * If we just WERE in a polygon, but are not now, then we must have just
  1145. X * finished one. Plot it out.
  1146. X */
  1147. X            xxx[polycount] = ixp;
  1148. X            yyy[polycount] = iyp;
  1149. X            polycount++;
  1150. X            if (!ghost)
  1151. X            {
  1152. X            drawpolygon (polycount, xxx, yyy);
  1153. X            }
  1154. X/*
  1155. X * Done with this one, reset the vertex counter
  1156. X */
  1157. X            polycount = 0;
  1158. X        }
  1159. X        else
  1160. X        if (INPOLY)
  1161. X        {
  1162. X/*
  1163. X * We're still saving up the polygon. Save this vertex.
  1164. X */
  1165. X            xxx[polycount] = ixp;
  1166. X            yyy[polycount] = iyp;
  1167. X            polycount++;
  1168. X            if (polycount > MAXPOLY - 1)
  1169. X            {
  1170. X            ERR (FATAL, name,
  1171. X                 "(gentext) Too many points in polygon.");
  1172. X            }
  1173. X        }
  1174. X        else
  1175. X        {
  1176. X/* No polygons, just output the vector */
  1177. X            if (DRAW && !ghost)
  1178. X            dev.vector (xnew, ynew, ixp, iyp, ROUND (tfat), 0);
  1179. X        }
  1180. X
  1181. X        xnew = ixp;
  1182. X        ynew = iyp;
  1183. X        }
  1184. X
  1185. X/*
  1186. X * If we switched to the error font just to plot the error glyph,
  1187. X * then switch back to the correct font
  1188. X */
  1189. X        if (istring[2 * ii] == UNDEFINED)
  1190. X        {
  1191. X        ttxfont = ttxfont_save;
  1192. X        }
  1193. X    }
  1194. X    }
  1195. X
  1196. X/* Restore the correct color, if necessary */
  1197. X    if (cur_color != cur_color_save)
  1198. X    {
  1199. X    cur_color = cur_color_save;
  1200. X    need_devcolor = YES;
  1201. X    }
  1202. X
  1203. X/* Restore overlay mode */
  1204. X    overlay = overlay_save;
  1205. X
  1206. X/*
  1207. X * If they jump back into text they can continue right where they left off
  1208. X * (As long as they do nothing to move the pen between now and then.)
  1209. X */
  1210. X    mov (last_widthr + font[ttxfont] .dim[LETTER] * SIZE_FACTOR (path),
  1211. X     ytxshift);
  1212. X    xold = ROUND (xold_f);
  1213. X    yold = ROUND (yold_f);
  1214. X    cfree ((char *) istring);
  1215. X}
  1216. X
  1217. mov (hadd, vadd)
  1218. X    double          hadd, vadd;
  1219. X{
  1220. X    xold_f += hadd * path_orient_dx + vadd * up_orient_dx;
  1221. X    yold_f += hadd * path_orient_dy + vadd * up_orient_dy;
  1222. X}
  1223. X
  1224. load_font (ifont)
  1225. X    int             ifont;
  1226. X{
  1227. int             fd, length;
  1228. char            filename[120];
  1229. char            string[80];
  1230. char           *newfont;
  1231. int             offs[7];
  1232. static int      done[NUMGENFONT];
  1233. X
  1234. X    if (done[ttxfont])
  1235. X    {
  1236. X    ttxfont = ERRFONT;
  1237. X    return;
  1238. X    }
  1239. X
  1240. X    done[ttxfont] = YES;
  1241. X
  1242. X    sprintf (string, "font%d", ifont);
  1243. X
  1244. X    if (ttxfont < NUM_FONTS)
  1245. X    sprintf (filename, "%s%s.bin", SYSTEM_FONT_DIRECTORY, font[ttxfont] .name);
  1246. X    else
  1247. X    strcpy (filename, string);
  1248. X
  1249. X    getpar (string, "s", filename);
  1250. X
  1251. X    if ((fd = open (filename, O_RDONLY)) == -1)
  1252. X    {
  1253. X    ERR (WARN, name,
  1254. X         "(gentext) Couldn't find font %d, file %s",
  1255. X         ttxfont, filename);
  1256. X    ttxfont = ERRFONT;
  1257. X    return;
  1258. X    }
  1259. X    else
  1260. X    {
  1261. X/*
  1262. X * First check to make sure it has the magic sequence "Vplot Binary fonT  \n"
  1263. X * followed by the binary integer FONTCHECK at the beginning.
  1264. X * If it doesn't, it's junk, so don't read it in.
  1265. X */
  1266. X    read (fd, string, 20);
  1267. X    read (fd, (char *) &length, sizeof (int));
  1268. X
  1269. X    if (strncmp ("Vplot Binary fonT  \n", string, 20) != 0 || length != FONTCHECK)
  1270. X    {
  1271. X        close (fd);
  1272. X        ERR (WARN, name,
  1273. X         "(gentext) Font %d file %s is garbled.",
  1274. X         ttxfont, filename);
  1275. X        ttxfont = ERRFONT;
  1276. X        return;
  1277. X    }
  1278. X
  1279. X/*
  1280. X *  Binary fonts are machine-specific. Just suck it into memory.
  1281. X *  The start of the file contains the length and then the
  1282. X *  offsets from the beginning to the 7 structures defining the font.
  1283. X */
  1284. X    read (fd, (char *) &length, sizeof (int));
  1285. X    newfont = (char *) malloc ((unsigned) (length * sizeof (char)));
  1286. X    if (newfont == NULL)
  1287. X    {
  1288. X        close (fd);
  1289. X        ERR (WARN, name,
  1290. X         "(gentext) Font %d file %s is too big.",
  1291. X         ttxfont, filename);
  1292. X        ttxfont = ERRFONT;
  1293. X        return;
  1294. X    }
  1295. X    read (fd, (char *) offs, 7 * sizeof (int));
  1296. X    read (fd, (char *) newfont, length);
  1297. X    close (fd);
  1298. X/* The 7 structures defining the font... */
  1299. X
  1300. X/* The vital parameters (dimensions, bounds, and lengths) */
  1301. X    font[ttxfont] .dim = (short *) (newfont + offs[0]);
  1302. X/* Pointers to the addresses of the glyphs themselves */
  1303. X    font[ttxfont] .saddr = (int *) (newfont + offs[1]);
  1304. X/* Left widths */
  1305. X    font[ttxfont] .swidthl = (short *) (newfont + offs[2]);
  1306. X/* Right widths */
  1307. X    font[ttxfont] .swidthr = (short *) (newfont + offs[3]);
  1308. X/* Vertical symbol hot-spot position */
  1309. X    font[ttxfont] .symbol = (short *) (newfont + offs[4]);
  1310. X/* The actual glyph strokes */
  1311. X    font[ttxfont] .svec = (unsigned short *) (newfont + offs[5]);
  1312. X/* Ligature data */
  1313. X    font[ttxfont] .lig = (int *) (newfont + offs[6]);
  1314. X
  1315. X/* Whether or not this font has been loaded into memory or not yet */
  1316. X    font[ttxfont] .load = YES;
  1317. X    }
  1318. X}
  1319. END_OF_FILE
  1320. if test 37130 -ne `wc -c <'Vplot_Kernel/filters/genlib/gentext.c'`; then
  1321.     echo shar: \"'Vplot_Kernel/filters/genlib/gentext.c'\" unpacked with wrong size!
  1322. fi
  1323. # end of 'Vplot_Kernel/filters/genlib/gentext.c'
  1324. fi
  1325. echo shar: End of archive 23 \(of 24\).
  1326. cp /dev/null ark23isdone
  1327. MISSING=""
  1328. 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
  1329.     if test ! -f ark${I}isdone ; then
  1330.     MISSING="${MISSING} ${I}"
  1331.     fi
  1332. done
  1333. if test "${MISSING}" = "" ; then
  1334.     echo You have unpacked all 24 archives.
  1335.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1336. else
  1337.     echo You still need to unpack the following archives:
  1338.     echo "        " ${MISSING}
  1339. fi
  1340. ##  End of shell archive.
  1341. exit 0
  1342.