home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume19 / xfig / part12 / u_redraw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-27  |  13.9 KB  |  567 lines

  1. /*
  2.  * FIG : Facility for Interactive Generation of figures
  3.  * Copyright (c) 1985 by Supoj Sutanthavibul
  4.  *
  5.  * "Permission to use, copy, modify, distribute, and sell this software and its
  6.  * documentation for any purpose is hereby granted without fee, provided that
  7.  * the above copyright notice appear in all copies and that both the copyright
  8.  * notice and this permission notice appear in supporting documentation. 
  9.  * No representations are made about the suitability of this software for 
  10.  * any purpose.  It is provided "as is" without express or implied warranty."
  11.  */
  12.  
  13. #include "fig.h"
  14. #include "resources.h"
  15. #include "object.h"
  16. #include "paintop.h"
  17. #include "w_setup.h"
  18. #include "w_util.h"
  19. #include "w_zoom.h"
  20.  
  21. /*
  22.  * Support for rendering based on correct object depth.     A simple depth based
  23.  * caching scheme; anything more will require major surgery on the object
  24.  * data structures that will percolate throughout program.
  25.  *
  26.  * One ``counts'' structure for each object type at each nesting depth from 0
  27.  * to MAXDEPTH - 1.  We track both the number of objects per type per depth,
  28.  * as well as the number of objects drawn so far per type per depth to cut
  29.  * down on search loop overhead.
  30.  */
  31.  
  32. struct counts {
  33.     unsigned        num_arcs;    /* # arcs at this depth */
  34.     unsigned        num_lines;    /* # lines at this depth */
  35.     unsigned        num_ellipses;    /* # ellipses at this depth */
  36.     unsigned        num_splines;/* # splines at this depth */
  37.     unsigned        num_texts;    /* # texts at this depth */
  38.     unsigned        cnt_arcs;    /* count of arcs drawn at this depth */
  39.     unsigned        cnt_lines;    /* count of lines drawn at this depth */
  40.     unsigned        cnt_ellipses;    /* count of ellipses drawn at this
  41.                      * depth */
  42.     unsigned        cnt_splines;/* count of splines drawn at this depth */
  43.     unsigned        cnt_texts;    /* count of texts drawn at this depth */
  44. };
  45.  
  46. /*
  47.  * The array of ``counts'' structures.    All objects at depth >= MAXDEPTH are
  48.  * accounted for in the counts[MAXDEPTH] entry.
  49.  */
  50.  
  51. struct counts    counts[MAXDEPTH + 1];
  52.  
  53. /*
  54.  * Function to clear the array of object counts prior to each redraw.
  55.  */
  56.  
  57. static void
  58. clearcounts()
  59. {
  60.     register struct counts *cp;
  61.  
  62.     for (cp = &counts[0]; cp <= &counts[MAXDEPTH]; ++cp) {
  63.     cp->num_arcs = 0;
  64.     cp->num_lines = 0;
  65.     cp->num_ellipses = 0;
  66.     cp->num_splines = 0;
  67.     cp->num_texts = 0;
  68.     cp->cnt_arcs = 0;
  69.     cp->cnt_lines = 0;
  70.     cp->cnt_ellipses = 0;
  71.     cp->cnt_splines = 0;
  72.     cp->cnt_texts = 0;
  73.     }
  74. }
  75.  
  76. unsigned int    max_depth;
  77.  
  78. redisplay_objects(objects)
  79.     F_compound       *objects;
  80. {
  81.     int            depth;
  82.  
  83.     if (objects == NULL)
  84.     return;
  85.  
  86.     /*
  87.      * Clear object counts, and then get the max. depth of any object from
  88.      * the max. depths of each object type in the top level compound.
  89.      */
  90.  
  91.     clearcounts();
  92.     max_depth = max2(compound_depths(objects->compounds),
  93.           max2(text_depths(objects->texts),
  94.                spline_depths(objects->splines)));
  95.     max_depth = max2(arc_depths(objects->arcs),
  96.              max2(line_depths(objects->lines),
  97.               max2(ellipse_depths(objects->ellipses),
  98.                    max_depth)));
  99.  
  100.     /*
  101.      * A new outer loop, executing once per depth level from max_depth down
  102.      * to 0 (negative depths are not supported).  The code inside the loop is
  103.      * the original code for redisplay_objects.
  104.      */
  105.  
  106.     for (depth = max_depth; depth >= 0; --depth) {
  107.     redisplay_arcobject(objects->arcs, depth);
  108.     redisplay_compoundobject(objects->compounds, depth);
  109.     redisplay_ellipseobject(objects->ellipses, depth);
  110.     redisplay_lineobject(objects->lines, depth);
  111.     redisplay_splineobject(objects->splines, depth);
  112.     redisplay_textobject(objects->texts, depth);
  113.     }
  114.  
  115.     /*
  116.      * Point markers and compounds, not being ``real objects'', are handled
  117.      * outside the depth loop.
  118.      */
  119.  
  120.     /* show the markers if they are on */
  121.     toggle_markers_in_compound(objects);
  122. }
  123.  
  124. /*
  125.  * Find the maximum depth of any arc, recording the number of arcs per each
  126.  * level along the way.
  127.  */
  128.  
  129. int
  130. arc_depths(arcs)
  131.     F_arc       *arcs;
  132. {
  133.     int            maxdepth = 0;
  134.     F_arc       *fp;
  135.  
  136.     for (fp = arcs; fp != NULL; fp = fp->next) {
  137.     if (maxdepth < fp->depth)
  138.         maxdepth = fp->depth;
  139.  
  140.     ++counts[min2(fp->depth, MAXDEPTH)].num_arcs;
  141.     }
  142.     return maxdepth;
  143. }
  144.  
  145. /*
  146.  * Find the maximum depth of any line, recording the number of lines per each
  147.  * level along the way.
  148.  */
  149.  
  150. int
  151. line_depths(lines)
  152.     F_line       *lines;
  153. {
  154.     int            maxdepth = 0;
  155.     F_line       *fp;
  156.  
  157.     for (fp = lines; fp != NULL; fp = fp->next) {
  158.     if (maxdepth < fp->depth)
  159.         maxdepth = fp->depth;
  160.  
  161.     ++counts[min2(fp->depth, MAXDEPTH)].num_lines;
  162.     }
  163.     return maxdepth;
  164. }
  165.  
  166. /*
  167.  * Find the maximum depth of any ellipse, recording the number of ellipses
  168.  * per each level along the way.
  169.  */
  170.  
  171. int
  172. ellipse_depths(ellipses)
  173.     F_ellipse       *ellipses;
  174. {
  175.     int            maxdepth = 0;
  176.     F_ellipse       *fp;
  177.  
  178.     for (fp = ellipses; fp != NULL; fp = fp->next) {
  179.     if (maxdepth < fp->depth)
  180.         maxdepth = fp->depth;
  181.  
  182.     ++counts[min2(fp->depth, MAXDEPTH)].num_ellipses;
  183.     }
  184.     return maxdepth;
  185. }
  186.  
  187. /*
  188.  * Find the maximum depth of any spline, recording the number of splines per
  189.  * each level along the way.
  190.  */
  191.  
  192. int
  193. spline_depths(splines)
  194.     F_spline       *splines;
  195. {
  196.     int            maxdepth = 0;
  197.     F_spline       *fp;
  198.  
  199.     for (fp = splines; fp != NULL; fp = fp->next) {
  200.     if (maxdepth < fp->depth)
  201.         maxdepth = fp->depth;
  202.  
  203.     ++counts[min2(fp->depth, MAXDEPTH)].num_splines;
  204.     }
  205.     return maxdepth;
  206. }
  207.  
  208. /*
  209.  * Find the maximum depth of any text, recording the number of texts per each
  210.  * level along the way.
  211.  */
  212.  
  213. int
  214. text_depths(texts)
  215.     F_text       *texts;
  216. {
  217.     int            maxdepth = 0;
  218.     F_text       *fp;
  219.  
  220.     for (fp = texts; fp != NULL; fp = fp->next) {
  221.     if (maxdepth < fp->depth)
  222.         maxdepth = fp->depth;
  223.  
  224.     ++counts[min2(fp->depth, MAXDEPTH)].num_texts;
  225.     }
  226.     return maxdepth;
  227. }
  228.  
  229. /*
  230.  * Find the maximum depth of any of the objects contained in the compound.
  231.  */
  232.  
  233. int
  234. compound_depths(compounds)
  235.     F_compound       *compounds;
  236. {
  237.     int            maxdepth = 0;
  238.     F_compound       *fp;
  239.  
  240.     for (fp = compounds; fp != NULL; fp = fp->next) {
  241.     maxdepth = max2(compound_depths(fp->compounds),
  242.               max2(text_depths(fp->texts),
  243.                max2(spline_depths(fp->splines),
  244.                 maxdepth)));
  245.     maxdepth = max2(arc_depths(fp->arcs),
  246.             max2(line_depths(fp->lines),
  247.                  max2(ellipse_depths(fp->ellipses),
  248.                   maxdepth)));
  249.     }
  250.     return maxdepth;
  251. }
  252.  
  253. /*
  254.  * Redisplay a list of arcs.  Only display arcs of the correct depth.
  255.  * For each arc drawn, update the count for the appropriate depth in
  256.  * the counts array.
  257.  */
  258.  
  259. redisplay_arcobject(arcs, depth)
  260.     F_arc       *arcs;
  261.     int            depth;
  262. {
  263.     F_arc       *arc;
  264.     struct counts  *cp = &counts[min2(depth, MAXDEPTH)];
  265.  
  266.     arc = arcs;
  267.     while (arc != NULL && cp->cnt_arcs < cp->num_arcs) {
  268.     if (depth == arc->depth) {
  269.         draw_arc(arc, PAINT);
  270.         ++cp->cnt_arcs;
  271.         }
  272.     arc = arc->next;
  273.     }
  274. }
  275.  
  276. /*
  277.  * Redisplay a list of ellipses.  Only display ellipses of the correct depth
  278.  * For each ellipse drawn, update the count for the
  279.  * appropriate depth in the counts array.
  280.  */
  281.  
  282. redisplay_ellipseobject(ellipses, depth)
  283.     F_ellipse       *ellipses;
  284.     int            depth;
  285. {
  286.     F_ellipse       *ep;
  287.     struct counts  *cp = &counts[min2(depth, MAXDEPTH)];
  288.  
  289.  
  290.     ep = ellipses;
  291.     while (ep != NULL && cp->cnt_ellipses < cp->num_ellipses) {
  292.     if (depth == ep->depth) {
  293.         draw_ellipse(ep, PAINT);
  294.         ++cp->cnt_ellipses;
  295.         }
  296.     ep = ep->next;
  297.     }
  298. }
  299.  
  300. /*
  301.  * Redisplay a list of lines.  Only display lines of the correct depth.
  302.  * For each line drawn, update the count for the appropriate
  303.  * depth in the counts array.
  304.  */
  305.  
  306. redisplay_lineobject(lines, depth)
  307.     F_line       *lines;
  308.     int            depth;
  309. {
  310.     F_line       *lp;
  311.     struct counts  *cp = &counts[min2(depth, MAXDEPTH)];
  312.  
  313.  
  314.     lp = lines;
  315.     while (lp != NULL && cp->cnt_lines < cp->num_lines) {
  316.     if (depth == lp->depth) {
  317.         draw_line(lp, PAINT);
  318.         ++cp->cnt_lines;
  319.         }
  320.     lp = lp->next;
  321.     }
  322. }
  323.  
  324. /*
  325.  * Redisplay a list of splines.     Only display splines of the correct depth
  326.  * For each spline drawn, update the count for the
  327.  * appropriate depth in the counts array.
  328.  */
  329.  
  330. redisplay_splineobject(splines, depth)
  331.     F_spline       *splines;
  332.     int            depth;
  333. {
  334.     F_spline       *spline;
  335.     struct counts  *cp = &counts[min2(depth, MAXDEPTH)];
  336.  
  337.     spline = splines;
  338.     while (spline != NULL && cp->cnt_splines < cp->num_splines) {
  339.     if (depth == spline->depth) {
  340.         draw_spline(spline, PAINT);
  341.         ++cp->cnt_splines;
  342.         }
  343.     spline = spline->next;
  344.     }
  345. }
  346.  
  347. /*
  348.  * Redisplay a list of texts.  Only display texts of the correct depth.     For
  349.  * each text drawn, update the count for the appropriate depth in the counts
  350.  * array.
  351.  */
  352.  
  353. redisplay_textobject(texts, depth)
  354.     F_text       *texts;
  355.     int            depth;
  356. {
  357.     F_text       *text;
  358.     struct counts  *cp = &counts[min2(depth, MAXDEPTH)];
  359.  
  360.     text = texts;
  361.     while (text != NULL && cp->cnt_texts < cp->num_texts) {
  362.     if (depth == text->depth) {
  363.         draw_text(text, PAINT);
  364.         ++cp->cnt_texts;
  365.     }
  366.     text = text->next;
  367.     }
  368. }
  369.  
  370. /*
  371.  * Redisplay a list of compounds at a current depth.  Basically just farm the
  372.  * work out to the objects contained in the compound.
  373.  */
  374.  
  375. redisplay_compoundobject(compounds, depth)
  376.     F_compound       *compounds;
  377.     int            depth;
  378. {
  379.     F_compound       *c;
  380.  
  381.     for (c = compounds; c != NULL; c = c->next) {
  382.     redisplay_arcobject(c->arcs, depth);
  383.     redisplay_compoundobject(c->compounds, depth);
  384.     redisplay_ellipseobject(c->ellipses, depth);
  385.     redisplay_lineobject(c->lines, depth);
  386.     redisplay_splineobject(c->splines, depth);
  387.     redisplay_textobject(c->texts, depth);
  388.     }
  389. }
  390.  
  391. /*
  392.  * Redisplay the entire drawing.
  393.  */
  394. redisplay_canvas()
  395. {
  396.     redisplay_region(0, 0, CANVAS_WD, CANVAS_HT);
  397. }
  398.  
  399. redisplay_region(xmin, ymin, xmax, ymax)
  400.     int            xmin, ymin, xmax, ymax;
  401. {
  402.     set_temp_cursor(wait_cursor);
  403.     /* kludge so that markers are redrawn */
  404.     xmin -= 8;
  405.     ymin -= 8;
  406.     xmax += 8;
  407.     ymax += 8;
  408.     set_clip_window(xmin, ymin, xmax, ymax);
  409.     clear_canvas();
  410.     redisplay_objects(&objects);
  411.     reset_clip_window();
  412.     reset_cursor();
  413. }
  414.  
  415. redisplay_zoomed_region(xmin, ymin, xmax, ymax)
  416.     int            xmin, ymin, xmax, ymax;
  417. {
  418.     redisplay_region(ZOOMX(xmin), ZOOMY(ymin), ZOOMX(xmax), ZOOMY(ymax));
  419. }
  420.  
  421. redisplay_ellipse(e)
  422.     F_ellipse       *e;
  423. {
  424.     int            xmin, ymin, xmax, ymax;
  425.  
  426.     ellipse_bound(e, &xmin, &ymin, &xmax, &ymax);
  427.     redisplay_zoomed_region(xmin, ymin, xmax, ymax);
  428. }
  429.  
  430. redisplay_ellipses(e1, e2)
  431.     F_ellipse       *e1, *e2;
  432. {
  433.     int            xmin1, ymin1, xmax1, ymax1;
  434.     int            xmin2, ymin2, xmax2, ymax2;
  435.  
  436.     ellipse_bound(e1, &xmin1, &ymin1, &xmax1, &ymax1);
  437.     ellipse_bound(e2, &xmin2, &ymin2, &xmax2, &ymax2);
  438.     redisplay_regions(xmin1, ymin1, xmax1, ymax1, xmin2, ymin2, xmax2, ymax2);
  439. }
  440.  
  441. redisplay_arc(a)
  442.     F_arc       *a;
  443. {
  444.     int            xmin, ymin, xmax, ymax;
  445.  
  446.     arc_bound(a, &xmin, &ymin, &xmax, &ymax);
  447.     redisplay_zoomed_region(xmin, ymin, xmax, ymax);
  448. }
  449.  
  450. redisplay_arcs(a1, a2)
  451.     F_arc       *a1, *a2;
  452. {
  453.     int            xmin1, ymin1, xmax1, ymax1;
  454.     int            xmin2, ymin2, xmax2, ymax2;
  455.  
  456.     arc_bound(a1, &xmin1, &ymin1, &xmax1, &ymax1);
  457.     arc_bound(a2, &xmin2, &ymin2, &xmax2, &ymax2);
  458.     redisplay_regions(xmin1, ymin1, xmax1, ymax1, xmin2, ymin2, xmax2, ymax2);
  459. }
  460.  
  461. redisplay_spline(s)
  462.     F_spline       *s;
  463. {
  464.     int            xmin, ymin, xmax, ymax;
  465.  
  466.     spline_bound(s, &xmin, &ymin, &xmax, &ymax);
  467.     redisplay_zoomed_region(xmin, ymin, xmax, ymax);
  468. }
  469.  
  470. redisplay_splines(s1, s2)
  471.     F_spline       *s1, *s2;
  472. {
  473.     int            xmin1, ymin1, xmax1, ymax1;
  474.     int            xmin2, ymin2, xmax2, ymax2;
  475.  
  476.     spline_bound(s1, &xmin1, &ymin1, &xmax1, &ymax1);
  477.     spline_bound(s2, &xmin2, &ymin2, &xmax2, &ymax2);
  478.     redisplay_regions(xmin1, ymin1, xmax1, ymax1, xmin2, ymin2, xmax2, ymax2);
  479. }
  480.  
  481. redisplay_line(l)
  482.     F_line       *l;
  483. {
  484.     int            xmin, ymin, xmax, ymax;
  485.  
  486.     line_bound(l, &xmin, &ymin, &xmax, &ymax);
  487.     redisplay_zoomed_region(xmin, ymin, xmax, ymax);
  488. }
  489.  
  490. redisplay_lines(l1, l2)
  491.     F_line       *l1, *l2;
  492. {
  493.     int            xmin1, ymin1, xmax1, ymax1;
  494.     int            xmin2, ymin2, xmax2, ymax2;
  495.  
  496.     line_bound(l1, &xmin1, &ymin1, &xmax1, &ymax1);
  497.     line_bound(l2, &xmin2, &ymin2, &xmax2, &ymax2);
  498.     redisplay_regions(xmin1, ymin1, xmax1, ymax1, xmin2, ymin2, xmax2, ymax2);
  499. }
  500.  
  501. redisplay_compound(c)
  502.     F_compound       *c;
  503. {
  504.     redisplay_zoomed_region(c->nwcorner.x, c->nwcorner.y,
  505.                 c->secorner.x, c->secorner.y);
  506. }
  507.  
  508. redisplay_compounds(c1, c2)
  509.     F_compound       *c1, *c2;
  510. {
  511.     redisplay_regions(c1->nwcorner.x, c1->nwcorner.y,
  512.               c1->secorner.x, c1->secorner.y,
  513.               c2->nwcorner.x, c2->nwcorner.y,
  514.               c2->secorner.x, c2->secorner.y);
  515. }
  516.  
  517. redisplay_text(t)
  518.     F_text       *t;
  519. {
  520.     int            xmin, ymin, xmax, ymax;
  521.     int            dum;
  522.  
  523.     if (appres.textoutline) {
  524.     text_bound_both(t, &xmin, &ymin, &xmax, &ymax,
  525.             &dum,&dum,&dum,&dum,&dum,&dum,&dum,&dum);
  526.     } else {
  527.     text_bound(t, &xmin, &ymin, &xmax, &ymax);
  528.     }
  529.     redisplay_zoomed_region(xmin, ymin, xmax, ymax);
  530. }
  531.  
  532. redisplay_texts(t1, t2)
  533.     F_text       *t1, *t2;
  534. {
  535.     int            xmin1, ymin1, xmax1, ymax1;
  536.     int            xmin2, ymin2, xmax2, ymax2;
  537.     int            dum;
  538.  
  539.     if (appres.textoutline) {
  540.     text_bound_both(t1, &xmin1, &ymin1, &xmax1, &ymax1,
  541.             &dum,&dum,&dum,&dum,&dum,&dum,&dum,&dum);
  542.     text_bound_both(t2, &xmin2, &ymin2, &xmax2, &ymax2,
  543.             &dum,&dum,&dum,&dum,&dum,&dum,&dum,&dum);
  544.     } else {
  545.     text_bound(t1, &xmin1, &ymin1, &xmax1, &ymax1);
  546.     text_bound(t2, &xmin2, &ymin2, &xmax2, &ymax2);
  547.     }
  548.     redisplay_regions(xmin1, ymin1, xmax1, ymax1, xmin2, ymin2, xmax2, ymax2);
  549. }
  550.  
  551. redisplay_regions(xmin1, ymin1, xmax1, ymax1, xmin2, ymin2, xmax2, ymax2)
  552.     int            xmin1, ymin1, xmax1, ymax1, xmin2, ymin2, xmax2, ymax2;
  553. {
  554.     if (xmin1 == xmin2 && ymin1 == ymin2 && xmax1 == xmax2 && ymax1 == ymax2) {
  555.     redisplay_zoomed_region(xmin1, ymin1, xmax1, ymax1);
  556.     return;
  557.     }
  558.     /* below is easier than sending clip rectangle array to X */
  559.     if (overlapping(xmin1, ymin1, xmax1, ymax1, xmin2, ymin2, xmax2, ymax2)) {
  560.     redisplay_zoomed_region(min2(xmin1, xmin2), min2(ymin1, ymin2),
  561.                 max2(xmax1, xmax2), max2(ymax1, ymax2));
  562.     } else {
  563.     redisplay_zoomed_region(xmin1, ymin1, xmax1, ymax1);
  564.     redisplay_zoomed_region(xmin2, ymin2, xmax2, ymax2);
  565.     }
  566. }
  567.