home *** CD-ROM | disk | FTP | other *** search
/ Creative Computers / CreativeComputers.iso / shareware / text / dvi_3.62 / source / dvisrc.lha / dvidraw.c < prev    next >
C/C++ Source or Header  |  1993-10-26  |  11KB  |  572 lines

  1. /*
  2. ** Datei: DVIDRAW.C
  3. ** Autor: Ingo Eichenseher
  4. */
  5.  
  6. #include <stdlib.h>
  7. #include <stdarg.h>
  8. #include <stdio.h>
  9. #include <math.h>
  10. #include <string.h>
  11. #include "dvi.h"
  12. #include "dvisplin.h"
  13. #include "dvidraw.h"
  14. #include "dviframe.h"
  15.  
  16. gstate_t gstate;
  17.  
  18. static int pic_bytewidth, pic_height;
  19. static int xmin=0, ymin=0, xmax=639, ymax=399;
  20.  
  21. void setframe(int width, int height)
  22. {
  23.     pic_bytewidth = width;
  24.     pic_height = height;
  25.     xmin = ymin = 0;
  26.     xmax = width*8 - 1;
  27.     ymax = height - 1;
  28. }
  29.  
  30. int iabs(int x)
  31. {
  32.     return x>=0 ? x : -x;
  33. }
  34.  
  35. int isgn(int x)
  36. {
  37.     return x==0 ? 0 : x<0 ? -1 : 1;
  38. }
  39.  
  40. static real dmax(real x, real y)
  41. {
  42.     return x>y ? x : y;
  43. }
  44.  
  45. static long address(int x, int y)
  46. {
  47.     long addr;
  48.     addr = ((long)y*(long)pic_bytewidth);
  49.     if (x>=0) addr += x/8;
  50.     else addr -= (7-x)/8;
  51.     return addr;
  52. }
  53.  
  54. static unsigned char bitpos(int x)
  55. {
  56.     if (x>=0) return( (unsigned char)( 128>>(x%8) ) );
  57.     return( (unsigned char)( 1<<((7-x)%8) ) );
  58. }
  59.  
  60. #if 0
  61. static void plot(int x1, int y1)
  62. {
  63.     register unsigned char huge *addr, bit;
  64.     if (x1<xmin || x1>xmax || y1<ymin || y1>ymax) return;
  65.     if (clip_active)
  66.     {
  67.     SW_Y(y1); SW_X(x1);
  68.     if (SW)
  69.     {
  70.         addr = address(x1,y1);
  71.         bit  = bitpos(x1);
  72.         frame_or(addr,bit);
  73.     }
  74.     }
  75.     else
  76.     {
  77.     addr = address(x1,y1);
  78.     bit  = bitpos(x1);
  79.     frame_or(addr,bit);
  80.     }
  81. }
  82. #endif
  83.  
  84. static void vline(int x1, int y1, int y2)
  85. {
  86.     register unsigned long addr;
  87.     register unsigned char bit;
  88.     if (y1>y2) { int h=y1; y1=y2; y2=h; }
  89.     if (x1<xmin || x1>xmax) return;
  90.     if (y1<ymin) y1=ymin;
  91.     if (y2>ymax) y2=ymax;
  92.     addr = address(x1,y1);
  93.     bit = bitpos(x1);
  94.     if (clip_active)
  95.     {
  96.     while(y1<=y2)
  97.     {
  98.         SW_Y(y1); SW_X(x1);
  99.         if (SW) frame_or(addr,bit);
  100.         addr += pic_bytewidth;
  101.         y1++;
  102.     }
  103.     }
  104.     else
  105.     {
  106.     while(y1<=y2)
  107.     {
  108.         frame_or(addr,bit);
  109.         addr += pic_bytewidth;
  110.         y1++;
  111.     }
  112.     }
  113. }
  114.  
  115. void hline(int x1, int y1, int x2, unsigned char pattern)
  116. {
  117.     register unsigned char bit;
  118.     register long addr;
  119.  
  120.     if (y1<ymin || y1>ymax) return;
  121.     if (x1>x2) { int h=x1; x1=x2; x2=h; }
  122.     if (x1<xmin) x1 = xmin;
  123.     if (x2>xmax) x2 = xmax;
  124.     if (x1>x2) return;
  125.  
  126.     addr = address(x1,y1);
  127.     bit  = bitpos(x1);
  128.  
  129.     if (clip_active)
  130.     {
  131.     SW_Y(y1);
  132.     while( x1<=x2 )
  133.     {
  134.         SW_X(x1);
  135.         if (SW)
  136.         if (pattern&bit) frame_or(addr,bit);
  137.         else frame_and(addr,~bit);
  138.         if ( (bit >>= 1)==0)
  139.         {
  140.         addr++;
  141.         bit = 128;
  142.         }
  143.         x1 ++;
  144.     }
  145.     }
  146.     else
  147.     {
  148.     if (bit!=128)
  149.     {
  150.         while( x1<=x2 && bit )
  151.         {
  152.         if (pattern&bit) frame_or(addr,bit);
  153.         else frame_and(addr,~bit);
  154.         bit >>= 1;
  155.         x1 ++;
  156.         }
  157.         addr++;
  158.         bit = 128;
  159.     }
  160.     while(x1 <= x2-8)
  161.     {
  162.         frame_poke(addr,pattern);
  163.         addr ++;
  164.         x1 += 8;
  165.     }
  166.     while(x1<=x2)
  167.     {
  168.         if (pattern&bit) frame_or(addr,bit);
  169.         else frame_and(addr,~bit);
  170.         bit >>= 1;
  171.         x1 ++;
  172.     }
  173.     }
  174. }
  175.  
  176. static void circle(int x0, int y0, int a, int b)
  177. {
  178.     if (a && b)
  179.     {
  180.     int x = 0, y = b;
  181.     long aq = (long)a*(long)a, aq2=aq+aq, bq=(long)b*(long)b, bq2=bq+bq;
  182.     long d = bq-aq*(long)b+aq/4l, dx=0, dy=aq2*(long)b;
  183.     while(dx<dy)
  184.     {
  185.         hline(x0-x,y0+y,x0+x,0xff);
  186.         hline(x0-x,y0-y,x0+x,0xff);
  187.         if (d>0l) --y, dy -= aq2, d -= dy;
  188.         ++x, dx += bq2, d += bq+dx;
  189.     }
  190.     d += (3l*(aq-bq)/2l-(dx+dy))/2l;
  191.     while(y>=0)
  192.     {
  193.         hline(x0-x,y0+y,x0+x,0xff);
  194.         hline(x0-x,y0-y,x0+x,0xff);
  195.         if (d<0l) ++x, dx += bq2, d+=dx;
  196.         --y, dy -= aq2, d += aq-dy;
  197.     }
  198.     }
  199.     else if (a) hline(x0-a,y0,x0+a,0xff);
  200.     else if (b) vline(x0,y0-b,y0+b);
  201. }
  202.  
  203. void g_circle(const coord *p, real r)
  204. {
  205.     int a, b;
  206.  
  207.     a = iround(r);
  208.     b = iround(r*aspect_ratio);
  209.     circle(iround(p->x),iround(p->y),a,b);
  210. }
  211.  
  212. static void thin_line(int x1, int y1, int x2, int y2)
  213. {
  214.     register int dx, dy, e, i, offset, sy, sx;
  215.     register long addr;
  216.     register unsigned char bit;
  217.     real diag, ylen;
  218.     ylen = 1.0/aspect_ratio;
  219.  
  220.     addr = address(x1,y1);
  221.     bit = bitpos(x1);
  222.     dx = iabs(x2-x1);
  223.     sx = isgn(x2-x1);
  224.     dy = iabs(y2-y1);
  225.     sy = isgn(y2-y1);
  226.     offset = sy*pic_bytewidth;
  227.  
  228.     if (clip_active)
  229.     {
  230.     if (dx==0 && dy==0)
  231.     {
  232.         SW_Y(y1);
  233.         SW_X(x1);
  234.         if (SW) frame_or(addr,bit);
  235.         return;
  236.     }
  237.  
  238.     if (dy>dx)
  239.     {
  240.         diag = sqrt(1.0+ylen*ylen)-1.0;
  241.         dx *= 2;
  242.         i = dy;
  243.         e = dx-dy;
  244.         dy *= 2;
  245.         while( i-- >= 0 )
  246.         {
  247.         SW_Y(y1);
  248.         SW_X(x1);
  249.         if (x1>=xmin && x1<=xmax && y1>=ymin && y1<=ymax)
  250.             if (SW & gstate.dash_color) frame_or(addr,bit);
  251.         if (gstate.dash_len>0)
  252.         {
  253.             if (gstate.dash_count <= 0)
  254.             {
  255.             if (++gstate.dash_index >= gstate.dash_len)
  256.                 gstate.dash_index=0;
  257.             gstate.dash_count +=
  258.                 gstate.dash_vector[gstate.dash_index];
  259.             gstate.dash_color = !gstate.dash_color;
  260.             }
  261.         }
  262.         if (e>=0)
  263.         {
  264.             if (dx)
  265.             {
  266.             if (sx>0)
  267.             {
  268.                 if ((bit >>= 1)==0) { bit=128; addr++;}
  269.                 x1++;
  270.             }
  271.             else
  272.             {
  273.                 if ((bit <<= 1)==0) { bit=1; addr--;}
  274.                 x1--;
  275.             }
  276.             }
  277.             e -= dy;
  278.             if (gstate.dash_len) gstate.dash_count -= diag;
  279.         }
  280.         if (gstate.dash_len) gstate.dash_count -= ylen;
  281.         addr += offset;
  282.         e += dx;
  283.         y1 += sy;
  284.         }
  285.     }
  286.     else
  287.     {
  288.         diag = sqrt(1.0+ylen*ylen)-1.0;
  289.         dy *= 2;
  290.         i = dx;
  291.         e = dy-dx;
  292.         dx *= 2;
  293.         while ( i-- >= 0)
  294.         {
  295.         SW_Y(y1);
  296.         SW_X(x1);
  297.         if (x1>=xmin && x1<=xmax && y1>=ymin && y1<=ymax)
  298.             if (SW && gstate.dash_color) frame_or(addr,bit);
  299.         if (gstate.dash_len>0)
  300.         {
  301.             if (gstate.dash_count <= 0)
  302.             {
  303.             if (++gstate.dash_index >= gstate.dash_len)
  304.                 gstate.dash_index=0;
  305.             gstate.dash_count +=
  306.                 gstate.dash_vector[gstate.dash_index];
  307.             gstate.dash_color = !gstate.dash_color;
  308.             }
  309.         }
  310.         if (e>=0)
  311.         {
  312.             addr += offset;
  313.             y1 += sy;
  314.             e -= dx;
  315.             if (gstate.dash_len) gstate.dash_count -= diag;
  316.         }
  317.         if (gstate.dash_len) gstate.dash_count -= 1.0;
  318.         if (dx)
  319.         {
  320.             if (sx>0)
  321.             {
  322.             if ((bit >>= 1)==0) { bit=128; addr++;}
  323.             x1++;
  324.             }
  325.             else
  326.             {
  327.             if ((bit <<= 1)==0) { bit=1; addr--;}
  328.             x1--;
  329.             }
  330.         }
  331.         e += dy;
  332.         }
  333.     }
  334.     }
  335.     else
  336.     {
  337.     if (dx==0 && dy==0)
  338.     {
  339.         frame_or(addr,bit);
  340.         return;
  341.     }
  342.  
  343.     if (dy>dx)
  344.     {
  345.         diag = sqrt(1.0+ylen*ylen)-1.0;
  346.         dx *= 2;
  347.         i = dy;
  348.         e = dx-dy;
  349.         dy *= 2;
  350.         while( i-- >= 0 )
  351.         {
  352.         if (x1>=xmin && x1<=xmax && y1>=ymin && y1<=ymax)
  353.             if (gstate.dash_color) frame_or(addr,bit);
  354.         if (gstate.dash_len>0)
  355.         {
  356.             if (gstate.dash_count <= 0)
  357.             {
  358.             if (++gstate.dash_index >= gstate.dash_len)
  359.                 gstate.dash_index=0;
  360.             gstate.dash_count +=
  361.                 gstate.dash_vector[gstate.dash_index];
  362.             gstate.dash_color = !gstate.dash_color;
  363.             }
  364.         }
  365.         if (e>=0)
  366.         {
  367.             if (dx)
  368.             {
  369.             if (sx>0)
  370.             {
  371.                 if ((bit >>= 1)==0) { bit=128; addr++;}
  372.                 x1++;
  373.             }
  374.             else
  375.             {
  376.                 if ((bit <<= 1)==0) { bit=1; addr--;}
  377.                 x1--;
  378.             }
  379.             }
  380.             e -= dy;
  381.             if (gstate.dash_len) gstate.dash_count -= diag;
  382.         }
  383.         if (gstate.dash_len) gstate.dash_count -= ylen;
  384.         addr += offset;
  385.         e += dx;
  386.         y1 += sy;
  387.         }
  388.     }
  389.     else
  390.     {
  391.         diag = sqrt(1.0+ylen*ylen)-1.0;
  392.         dy *= 2;
  393.         i = dx;
  394.         e = dy-dx;
  395.         dx *= 2;
  396.         while ( i-- >= 0)
  397.         {
  398.         if (x1>=xmin && x1<=xmax && y1>=ymin && y1<=ymax)
  399.             if (gstate.dash_color) frame_or(addr,bit);
  400.         if (gstate.dash_len>0)
  401.         {
  402.             if (gstate.dash_count <= 0)
  403.             {
  404.             if (++gstate.dash_index >= gstate.dash_len)
  405.                 gstate.dash_index=0;
  406.             gstate.dash_count +=
  407.                 gstate.dash_vector[gstate.dash_index];
  408.             gstate.dash_color = !gstate.dash_color;
  409.             }
  410.         }
  411.         if (e>=0)
  412.         {
  413.             addr += offset;
  414.             y1 += sy;
  415.             e -= dx;
  416.             if (gstate.dash_len) gstate.dash_count -= diag;
  417.         }
  418.         if (gstate.dash_len) gstate.dash_count -= 1.0;
  419.         if (dx)
  420.         {
  421.             if (sx>0)
  422.             {
  423.             if ((bit >>= 1)==0) { bit=128; addr++;}
  424.             x1++;
  425.             }
  426.             else
  427.             {
  428.             if ((bit <<= 1)==0) { bit=1; addr--;}
  429.             x1--;
  430.             }
  431.         }
  432.         e += dy;
  433.         }
  434.     }
  435.     }
  436. }
  437.  
  438. void g_line(const coord *p1, const coord *p2)
  439. {
  440.     int savepos, savecolor;
  441.     real savecount;
  442.     static real last_x2, last_y2;
  443.  
  444.     if (fill_mode)
  445.     {
  446.     clip_line(iround(p1->x),iround(p1->y),iround(p2->x),iround(p2->y));
  447.     return;
  448.     }
  449.     if (gstate.dash_len>0 &&
  450.     (fabs(p1->x-last_x2)>1.0 || fabs(p1->y-last_y2)>1.0) )
  451.     {
  452.     gstate.dash_index = 0;
  453.     gstate.dash_color = 1;
  454.     gstate.dash_count = gstate.dash_vector[gstate.dash_index];
  455.     }
  456.  
  457.     savepos = gstate.dash_index;
  458.     savecolor = gstate.dash_color;
  459.     savecount = gstate.dash_count;
  460.     last_x2 = p2->x;
  461.     last_y2 = p2->y;
  462.  
  463.     if (gstate.line_width<=1.0)
  464.     thin_line(iround(p1->x),iround(p1->y),iround(p2->x),iround(p2->y));
  465.     else
  466.     {
  467.     register int dx, dy, sx, sy, e, xe, ye, xa, ya, xb, yb;
  468.     real f, g, norm, delta_x, delta_y;
  469.  
  470.     delta_x = p2->x - p1->x;
  471.     delta_y = p2->y - p1->y;
  472.  
  473.     norm = sqrt(delta_x*delta_x+delta_y*delta_y
  474.             /aspect_ratio/aspect_ratio);
  475.     if (norm<0.01) return;
  476.     f = (gstate.line_width-1.0)/norm/2;
  477.     g = delta_x * aspect_ratio * f;
  478.     f = delta_y / aspect_ratio * f;
  479.  
  480.     xa = iround(p1->x + f);
  481.     ya = iround(p1->y - g);
  482.     xb = iround(p2->x + f);
  483.     yb = iround(p2->y - g);
  484.     xe = iround((real)xa - 2*f);
  485.     ye = iround((real)ya + 2*g);
  486.  
  487.     dx = iabs(xe-xa);
  488.     dy = iabs(ye-ya);
  489.     sx = isgn(xe-xa);
  490.     sy = isgn(ye-ya);
  491.     e  = dx - dy;
  492.  
  493.     thin_line(xa, ya, xb, yb);
  494.     while(xa!=xe || ya!=ye)
  495.     {
  496.         if (e<0) e += dx, ya += sy, yb += sy;
  497.         else e -= dy, xa += sx, xb += sx;
  498.         gstate.dash_index = savepos;
  499.         gstate.dash_color = savecolor;
  500.         gstate.dash_count = savecount;
  501.         thin_line(xa,ya,xb,yb);
  502.     }
  503.     }
  504. }
  505.  
  506. void g_join(const coord *p)
  507. {
  508.     if (gstate.dash_len==0 && !fill_mode && gstate.line_width>=3.0)
  509.     g_circle(p,floor((gstate.line_width-1)/2));
  510. }
  511.  
  512. void g_bezier(const coord *p1,const coord *p2,const coord *p3,const coord *p4, int ttl)
  513. {
  514.     real dx, dy, dm;
  515.     static int r,  t=0;
  516.  
  517.     if (ttl==0)
  518.     gr_error("Stack overflow in curve");
  519.  
  520.     dx = p4->x-p1->x;
  521.     dy = p4->y-p1->y;
  522.     dm = dmax(fabs(dx),fabs(dy));
  523.  
  524.     if (dx!=0 || dy!=0)
  525.     {
  526.     if ( fabs((p3->y-p1->y)*dx-(p3->x-p1->x)*dy) > dm ||
  527.          fabs((p2->y-p1->y)*dx-(p2->x-p1->x)*dy) > dm ) r=1;
  528.     else
  529.     {
  530.         g_line(p1,p4);
  531.         r = 0;
  532.     }
  533.     }
  534.     else
  535.     {
  536.     if ( (p2->x-p1->x)*(p2->x-p1->x)+(p2->y-p1->y)*(p2->y-p1->y) > 0.25 ||
  537.          (p3->x-p1->x)*(p3->x-p1->x)+(p3->y-p1->y)*(p3->y-p1->y) > 0.25   )
  538.         r = 1;
  539.     }
  540.  
  541.     if (r)
  542.     {
  543.     coord p12, p23, p34, p123, p234, p1234;
  544.  
  545.     p12.x   = (p1->x+p2->x)/2;   p12.y   = (p1->y+p2->y)/2;
  546.     p23.x   = (p2->x+p3->x)/2;   p23.y   = (p2->y+p3->y)/2;
  547.     p34.x   = (p3->x+p4->x)/2;   p34.y   = (p3->y+p4->y)/2;
  548.     p123.x  = (p12.x+p23.x)/2;   p123.y  = (p12.y+p23.y)/2;
  549.     p234.x  = (p23.x+p34.x)/2;   p234.y  = (p23.y+p34.y)/2;
  550.     p1234.x = (p123.x+p234.x)/2; p1234.y = (p123.y+p234.y)/2;
  551.  
  552.     g_bezier(p1,&p12,&p123,&p1234,ttl-1);
  553.     g_join(&p1234);
  554.     g_bezier(&p1234,&p234,&p34,p4,ttl-1);
  555.     }
  556.  
  557.     t--;
  558. }
  559.  
  560. void setdash(real *pat, int len)
  561. {
  562.     if ((gstate.dash_len=len)<=0) gstate.dash_color = 1;
  563.     else
  564.     {
  565.     gstate.dash_color = 1;
  566.     gstate.dash_vector = pat;
  567.     gstate.dash_index = 0;
  568.     gstate.dash_count = gstate.dash_vector[gstate.dash_index];
  569.     }
  570. }
  571.  
  572.