home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / groff / libXdvi / draw.c next >
Encoding:
C/C++ Source or Header  |  1991-04-30  |  7.2 KB  |  369 lines

  1. /*
  2.  * draw.c
  3.  *
  4.  * accept dvi function calls and translate to X
  5.  */
  6.  
  7. #include <X11/Xos.h>
  8. #include <X11/IntrinsicP.h>
  9. #include <X11/StringDefs.h>
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include <math.h>
  13.  
  14. /* math.h on a Sequent doesn't define M_PI, apparently */
  15. #ifndef M_PI
  16. #define M_PI    3.14159265358979323846
  17. #endif
  18.  
  19. #include "DviP.h"
  20.  
  21. HorizontalMove(dw, delta)
  22.     DviWidget    dw;
  23.     int        delta;
  24. {
  25.     dw->dvi.state->x += delta;
  26. }
  27.  
  28. HorizontalGoto(dw, NewPosition)
  29.     DviWidget    dw;
  30.     int        NewPosition;
  31. {
  32.     dw->dvi.state->x = NewPosition;
  33. }
  34.  
  35. VerticalMove(dw, delta)
  36.     DviWidget    dw;
  37.     int        delta;
  38. {
  39.     dw->dvi.state->y += delta;
  40. }
  41.  
  42. VerticalGoto(dw, NewPosition)
  43.     DviWidget    dw;
  44.     int        NewPosition;
  45. {
  46.     dw->dvi.state->y = NewPosition;
  47. }
  48.  
  49. FlushCharCache (dw)
  50.     DviWidget    dw;
  51. {
  52.     if (dw->dvi.cache.char_index != 0)
  53.         XDrawText (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
  54.             dw->dvi.cache.start_x, dw->dvi.cache.start_y,
  55.              dw->dvi.cache.cache, dw->dvi.cache.index + 1);
  56.     dw->dvi.cache.index = 0;
  57.     dw->dvi.cache.max = DVI_TEXT_CACHE_SIZE;
  58.     if (dw->dvi.noPolyText)
  59.         dw->dvi.cache.max = 1;
  60.     dw->dvi.cache.char_index = 0;
  61.     dw->dvi.cache.cache[0].nchars = 0;
  62.     dw->dvi.cache.start_x = dw->dvi.cache.x = dw->dvi.state->x;
  63.     dw->dvi.cache.start_y = dw->dvi.cache.y = dw->dvi.state->y;
  64. }
  65.  
  66. ClearPage (dw)
  67.     DviWidget    dw;
  68. {
  69.     XClearWindow (XtDisplay (dw), XtWindow (dw));
  70. }
  71.  
  72. static
  73. setGC (dw)
  74.     DviWidget    dw;
  75. {
  76.     int desired_line_width;
  77.     
  78.     if (dw->dvi.line_thickness < 0) {
  79.         desired_line_width = (((dw->dvi.device_resolution
  80.                     * dw->dvi.state->font_size) + 5*72)
  81.                       / (10*72));
  82.         if (desired_line_width == 0)
  83.             desired_line_width = 1;
  84.     }
  85.     else
  86.         desired_line_width = dw->dvi.line_thickness;
  87.     
  88.     if (desired_line_width != dw->dvi.line_width) {
  89.         XGCValues values;
  90.         values.line_width = desired_line_width;
  91.         XChangeGC(XtDisplay (dw), dw->dvi.normal_GC,
  92.               GCLineWidth, &values);
  93.         dw->dvi.line_width = desired_line_width;
  94.     }
  95. }
  96.  
  97. static
  98. setFillGC (dw)
  99.     DviWidget    dw;
  100. {
  101.     int fill_type;
  102.     
  103.     if (dw->dvi.fill == DVI_FILL_MAX)
  104.         fill_type = DVI_FILL_BLACK;
  105.     else if (dw->dvi.fill == 0)
  106.         fill_type = DVI_FILL_WHITE;
  107.     else
  108.         fill_type = DVI_FILL_GRAY;
  109.     if (dw->dvi.fill_type != fill_type) {
  110.         XGCValues values;
  111.         switch (fill_type) {
  112.         case DVI_FILL_WHITE:
  113.             values.foreground = dw->dvi.background;
  114.             values.fill_style = FillSolid;
  115.             break;
  116.         case DVI_FILL_BLACK:
  117.             values.foreground = dw->dvi.foreground;
  118.             values.fill_style = FillSolid;
  119.             break;
  120.         case DVI_FILL_GRAY:
  121.             values.foreground = dw->dvi.foreground;
  122.             values.fill_style = FillOpaqueStippled;
  123.             break;
  124.         }
  125.         XChangeGC(XtDisplay (dw), dw->dvi.fill_GC,
  126.               GCFillStyle|GCForeground,
  127.               &values);
  128.         dw->dvi.fill_type = fill_type;
  129.     }
  130. }
  131.  
  132. DrawLine (dw, x, y)
  133.     DviWidget    dw;
  134.     int        x, y;
  135. {
  136.     setGC (dw);
  137.     XDrawLine (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
  138.            dw->dvi.state->x, dw->dvi.state->y,
  139.            dw->dvi.state->x + x, dw->dvi.state->y + y);
  140. }
  141.  
  142. DrawCircle (dw, diam)
  143.     DviWidget    dw;
  144.     int        diam;
  145. {
  146.     setGC (dw);
  147.     XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
  148.           dw->dvi.state->x, dw->dvi.state->y - diam/2,
  149.           diam, diam, 0, 64*360);
  150. }
  151.  
  152. DrawFilledCircle (dw, diam)
  153.     DviWidget    dw;
  154.     int        diam;
  155. {
  156.     setFillGC (dw);
  157.     XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
  158.           dw->dvi.state->x, dw->dvi.state->y - diam/2,
  159.           diam, diam, 0, 64*360);
  160. }
  161.  
  162. DrawEllipse (dw, a, b)
  163.     DviWidget    dw;
  164.     int        a, b;
  165. {
  166.     setGC (dw);
  167.     XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
  168.           dw->dvi.state->x, dw->dvi.state->y - b/2,
  169.           a, b, 0, 64*360);
  170. }
  171.  
  172. DrawFilledEllipse (dw, a, b)
  173.     DviWidget    dw;
  174.     int        a, b;
  175. {
  176.     setFillGC (dw);
  177.     XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
  178.           dw->dvi.state->x, dw->dvi.state->y - b/2,
  179.           a, b, 0, 64*360);
  180. }
  181.  
  182. DrawArc (dw, x0, y0, x1, y1)
  183.     DviWidget    dw;
  184.     int        x0, y0, x1, y1;
  185. {
  186.     int x, y;
  187.     int angle1, angle2;
  188.     int rad = (int)((sqrt ((double)x0*x0 + (double)y0*y0)
  189.             + sqrt ((double)x1*x1 + (double)y1*y1) + 1.0)/2.0);
  190.     if ((x0 == 0 && y0 == 0) || (x1 == 0 && y1 == 0))
  191.         return;
  192.     angle1 = (int)(atan2 ((double)y0, (double)-x0)*180.0*64.0/M_PI);
  193.     angle2 = (int)(atan2 ((double)-y1, (double)x1)*180.0*64.0/M_PI);
  194.     
  195.     angle2 -= angle1;
  196.     if (angle2 < 0)
  197.         angle2 += 64*360;
  198.     
  199.     setGC (dw);
  200.     XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
  201.           dw->dvi.state->x + x0 - rad, dw->dvi.state->y + y0 - rad,
  202.           rad*2, rad*2, angle1, angle2);
  203. }
  204.  
  205. DrawPolygon (dw, v, n)
  206.     DviWidget    dw;
  207.     int        *v;
  208.     int        n;
  209. {
  210.     extern char *malloc();
  211.     XPoint *p;
  212.     int i;
  213.     
  214.     n /= 2;
  215.     
  216.     setGC (dw);
  217.     p = (XPoint *)malloc((n + 2)*sizeof(XPoint));
  218.     if (p == NULL)
  219.         return;
  220.     p[0].x = dw->dvi.state->x;
  221.     p[0].y = dw->dvi.state->y;
  222.     for (i = 0; i < n; i++) {
  223.         p[i + 1].x = v[2*i] + p[i].x;
  224.         p[i + 1].y = v[2*i + 1] + p[i].y;
  225.     }
  226.     p[n+1].x = dw->dvi.state->x;
  227.     p[n+1].y = dw->dvi.state->y;
  228.     XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
  229.            p, n + 2, CoordModeOrigin);
  230.     free(p);
  231. }
  232.  
  233.  
  234. DrawFilledPolygon (dw, v, n)
  235.     DviWidget    dw;
  236.     int        *v;
  237.     int        n;
  238. {
  239.     extern char *malloc();
  240.     XPoint *p;
  241.     int i;
  242.     
  243.     n /= 2;
  244.     if (n < 2)
  245.         return;
  246.     
  247.     setFillGC (dw);
  248.     p = (XPoint *)malloc((n + 1)*sizeof(XPoint));
  249.     if (p == NULL)
  250.         return;
  251.     p[0].x = dw->dvi.state->x;
  252.     p[0].y = dw->dvi.state->y;
  253.     for (i = 0; i < n; i++) {
  254.         p[i + 1].x = v[2*i];
  255.         p[i + 1].y = v[2*i + 1];
  256.     }
  257.     XFillPolygon (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
  258.               p, n + 1, Complex, CoordModePrevious);
  259.     free(p);
  260. }
  261.  
  262. #define POINTS_MAX 10000
  263.  
  264. static
  265. appendPoint(points, pointi, x, y)
  266.     XPoint    *points;
  267.     int    *pointi;
  268.     int    x, y;
  269. {
  270.     if (*pointi < POINTS_MAX) {
  271.         points[*pointi].x = x;
  272.         points[*pointi].y = y;
  273.         *pointi += 1;
  274.     }
  275. }
  276.  
  277. #define FLATNESS 1
  278.  
  279. static
  280. flattenCurve(points, pointi, x2, y2, x3, y3, x4, y4)
  281.     XPoint    *points;
  282.     int    *pointi;
  283.     int    x2, y2, x3, y3, x4, y4;
  284. {
  285.     int x1, y1, dx, dy, n1, n2, n;
  286.  
  287.     x1 = points[*pointi - 1].x;
  288.     y1 = points[*pointi - 1].y;
  289.     
  290.     dx = x4 - x1;
  291.     dy = y4 - y1;
  292.     
  293.     n1 = dy*(x2 - x1) - dx*(y2 - y1);
  294.     n2 = dy*(x3 - x1) - dx*(y3 - y1);
  295.     if (n1 < 0)
  296.         n1 = -n1;
  297.     if (n2 < 0)
  298.         n2 = -n2;
  299.     n = n1 > n2 ? n1 : n2;
  300.  
  301.     if (n*n / (dy*dy + dx*dx) <= FLATNESS*FLATNESS)
  302.         appendPoint (points, pointi, x4, y4);
  303.     else {
  304.         flattenCurve (points, pointi,
  305.                   (x1 + x2)/2, (y1 + y2)/2,
  306.                   (x1 + x2*2 + x3)/4, (y1 + y2*2 + y3)/4,
  307.                   (x1 +3*x2 + 3*x3 + x4)/8, (y1 +3*y2 + 3*y3 + y4)/8);
  308.         flattenCurve (points, pointi,
  309.                   (x2 + x3*2 + x4)/4, (y2 + y3*2 + y4)/4,
  310.                   (x3 + x4)/2, (y3 + y4)/2,
  311.                   x4, y4);
  312.     }
  313. }
  314.  
  315.  
  316. DrawSpline (dw, v, n)
  317.     DviWidget    dw;
  318.     int        *v;
  319.     int        n;
  320. {
  321.     int sx, sy, tx, ty, ux, uy;
  322.     int i;
  323.     int pointi;
  324.     XPoint points[POINTS_MAX];
  325.     
  326.     if (n == 0 || (n & 1) != 0)
  327.         return;
  328.     setGC (dw);
  329.     sx = dw->dvi.state->x;
  330.     sy = dw->dvi.state->y;
  331.     tx = sx + v[0];
  332.     ty = sy + v[1];
  333.     
  334.     pointi = 0;
  335.     
  336.     appendPoint (points, &pointi, sx, sy);
  337.     appendPoint (points, &pointi, (sx + tx)/2, (sy + ty)/2);
  338.     
  339.     for (i = 2; i < n; i += 2) {
  340.         int ux = tx + v[i];
  341.         int uy = ty + v[i+1];
  342.         flattenCurve (points, &pointi,
  343.                    (sx + tx*5)/6, (sy + ty*5)/6,
  344.                    (tx*5 + ux)/6, (ty*5 + uy)/6,
  345.                    (tx + ux)/2, (ty + uy)/2);
  346.         sx = tx;
  347.         sy = ty;
  348.         tx = ux;
  349.         ty = uy;
  350.     }
  351.     
  352.     appendPoint (points, &pointi, tx, ty);
  353.     
  354.     XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
  355.            points, pointi, CoordModeOrigin);
  356. }
  357.  
  358.  
  359. /*
  360. Local Variables:
  361. c-indent-level: 8
  362. c-continued-statement-offset: 8
  363. c-brace-offset: -8
  364. c-argdecl-indent: 8
  365. c-label-offset: -8
  366. c-tab-always-indent: nil
  367. End:
  368. */
  369.