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

  1. /*
  2. ** Datei: DVICLIP.C
  3. ** Autor: Ingo Eichenseher
  4. */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <stdarg.h>
  9. #include <math.h>
  10. #include <string.h>
  11. #include "dvi.h"
  12. #include "dvisplin.h"
  13. #include "dvidraw.h"
  14.  
  15. #define QSORT
  16.  
  17. int clip_active = 0;
  18. int fill_mode;
  19.  
  20. int clip_nx, clip_ymin, clip_ymax;
  21. int *clip_x, **clip_y;
  22. int cmaxx = MAX_X;
  23. int sw, *swp;
  24.  
  25. static struct clip_xy *path_coord = NULL;
  26. static struct clip_xy *clip_coord = NULL;
  27. static long clip_size, path_size, clip_x_size, clip_y_size;
  28. static int path_points = 0, path_max_points=0, clip_max_points=0;
  29. static int clip_xmax;
  30. static int fill_s0, fill_sn, fill_start;
  31. static int fill_error, fill_x1, fill_x2, fill_y1, fill_y2, path_start;
  32.  
  33. #ifdef QSORT
  34. static int clip_compare(struct clip_xy const *a, struct clip_xy const *b)
  35. {
  36.     if (a->y==b->y) return a->x - b->x;
  37.     return a->y - b->y;
  38. }
  39.  
  40. typedef int (*cmpf)(const void *, const void*);
  41.  
  42. static struct clip_xy *path_ptr;
  43.  
  44. static void clip_newcoord(int x, int y)
  45. {
  46.     if (path_points<path_max_points)
  47.     {
  48.     path_ptr->x = x;
  49.     path_ptr->y = y;
  50.     path_ptr++;
  51.     path_points++;
  52.     }
  53.     else fill_error = 2;
  54. }
  55.  
  56. #define clip_rmcoord() path_points--, path_ptr--
  57. #else
  58. static int lp;
  59.  
  60. static void clip_newcoord(int x, int y)
  61. {
  62.     if (path_points>=path_max_points)
  63.     {
  64.     fill_error = 2;
  65.     return;
  66.     }
  67.     if (path_points>0)
  68.     {
  69.     int c = y==path_coord[lp].y ? x-path_coord[lp].x : y-path_coord[lp].y;
  70.     while(c>0 && lp<path_points)
  71.         if (++lp<path_points)
  72.         c = y==path_coord[lp].y ? x-path_coord[lp].x : y-path_coord[lp].y;
  73.     while(lp>0)
  74.     {
  75.         c = y==path_coord[lp-1].y ? x-path_coord[lp-1].x : y-path_coord[lp-1].y;
  76.         if (c>=0) break;
  77.         lp--;
  78.     }
  79.     if (lp<path_points)
  80.         memmove(path_coord+lp+1,path_coord+lp,(path_points-lp)*sizeof(struct coord));
  81.     }
  82.     else lp = 0;
  83.     path_coord[lp].x = x;
  84.     path_coord[lp].y = y;
  85.     path_points++;
  86. }
  87.  
  88. static void clip_rmcoord(void)
  89. {
  90.     if (path_points>0 && lp<path_points-1)
  91.     memmove(path_coord+lp,path_coord+lp+1,(path_points-lp-1)*sizeof(struct coord));
  92.     if (path_points>0) path_points--;
  93. }
  94. #endif
  95.  
  96. static void clip_newpoint(int x, int y)
  97. {
  98.     clip_newcoord(x,y);
  99.     clip_newcoord(x,y);
  100. }
  101.  
  102. void clip_line(int x1, int y1, int x2, int y2)
  103. {
  104.     register int dx, dy, e, i, sy, sx;
  105.     static int last_sy = 0;
  106.     int last_y = y1;
  107.  
  108.     dx = iabs(x2-x1);
  109.     sx = isgn(x2-x1);
  110.     dy = iabs(y2-y1);
  111.     sy = isgn(y2-y1);
  112.  
  113.     if (path_start)
  114.     {
  115.     fill_x1 = x1;
  116.     fill_y1 = y1;
  117.     path_start = 0;
  118.     }
  119.     else
  120.     {
  121.     if (fill_x2!=x1 || fill_y2!=y1)
  122.     {
  123.         fill_error = 1;
  124.         /* print("(%d!=%d,%d!=%d)",fill_x2,x1,fill_y2,y1); */
  125.     }
  126.     }
  127.     if (fill_error) return;
  128.  
  129.     fill_x2 = x2;
  130.     fill_y2 = y2;
  131.  
  132.     if (sy!=0)
  133.     {
  134.     if (fill_start)
  135.     {
  136.         clip_newcoord(x1,y1);
  137.         fill_s0 = sy;
  138.         fill_start=0;
  139.     }
  140.     else if (sy!=last_sy) clip_newcoord(x1,y1);
  141.     last_sy = sy;
  142.     fill_sn = sy;
  143.     }
  144.  
  145.     if (dx==0 && dy==0)
  146.     {
  147.     clip_newpoint(x1,y1);
  148.     return;
  149.     }
  150.  
  151.     if (dy>dx)
  152.     {
  153.     dx += dx;
  154.     i = dy;
  155.     e = dx-dy;
  156.     dy += dy;
  157.     while( i-- >= 0 )
  158.     {
  159.         if (y1!=last_y)
  160.         {
  161.         clip_newcoord(x1,y1);
  162.         last_y = y1;
  163.         }
  164.         else clip_newpoint(x1,y1);
  165.         while(e>=0)
  166.         {
  167.         x1 += sx;
  168.         e -= dy;
  169.         }
  170.         e += dx;
  171.         y1 += sy;
  172.     }
  173.     }
  174.     else
  175.     {
  176.     dy += dy;
  177.     i = dx;
  178.     e = dy-dx;
  179.     dx += dx;
  180.     while ( i-- >= 0)
  181.     {
  182.         if (y1!=last_y)
  183.         {
  184.         clip_newcoord(x1,y1);
  185.         last_y = y1;
  186.         }
  187.         else clip_newpoint(x1,y1);
  188.         while(e>=0)
  189.         {
  190.         y1 += sy;
  191.         e -= dx;
  192.         }
  193.         x1 += sx;
  194.         e += dy;
  195.     }
  196.     }
  197. }
  198.  
  199. static void psize_init(long *size, int *points)
  200. {
  201.     if (op.pathmem>0l)
  202.     {
  203.     long p;
  204.     *size = op.pathmem;
  205.     p = *size/sizeof(struct clip_xy);
  206.     if (p!=(int)p) 
  207.     {
  208.         p = 32767;
  209.         *size = p*sizeof(struct clip_xy);
  210.     }
  211.     *points = (int)p;
  212.     }
  213.     else
  214.     {
  215.     *points = 2*(dvi_info.width+dvi_info.height);
  216.     *size = *points*sizeof(struct clip_xy);
  217.     }
  218. }
  219.  
  220. void clip_init(void)
  221. {
  222.     psize_init(&path_size,&path_max_points);
  223.     if (op.tracemem) xprint(0,"{DefClip:%ld",path_size);
  224.     path_coord = (struct clip_xy*)mem_alloc(path_size,"DefClip");
  225.  
  226.     path_points = 0;
  227.     path_ptr = path_coord;
  228.  
  229.     fill_start = 1;
  230.     fill_mode = 1;
  231.     path_start = 1;
  232.     fill_error = 0;
  233. }
  234.  
  235. static int clip_cut(struct clip_xy *clip_coord, int clip_max_points)
  236. {
  237.     int f, n = clip_max_points;
  238.     struct clip_xy *cp = clip_coord, *pp;
  239.  
  240.     for (f=0, pp=path_coord; f<path_points-1; f+=2, pp+=2)
  241.     {
  242.     int y = pp->y;
  243.     if (y>=clip_ymin && y<=clip_ymax)
  244.     {
  245.         int *p;
  246.         for (p=clip_y[y-clip_ymin]; *p<MAX_X; p+=2)
  247.         {
  248.         int min_x = pp->x > *p ? pp->x : *p;
  249.         int max_x = pp[1].x < p[1] ? pp[1].x : p[1];
  250.         if (min_x<=max_x)
  251.         {
  252.             if ( 0==n-- ) return -1;
  253.             cp->x = min_x;
  254.             cp->y = y;
  255.             cp++;
  256.             if ( 0==n-- ) return -1;
  257.             cp->x = max_x;
  258.             cp->y = y;
  259.             cp++;
  260.         }
  261.         }
  262.     }
  263.     }
  264.     return clip_max_points-n;
  265. }
  266.  
  267. static int clip1(unsigned char *clip_mask)
  268. {
  269.     int i, clip_points, *cpx;
  270.     static struct clip_xy *cp;
  271.  
  272.     if (!fill_mode) return fill_error = 1;
  273.     fill_mode = 0;
  274.     if (fill_start) return 0;
  275.     if (fill_x1!=fill_x2 || fill_y1!=fill_y2) return fill_error = 1;
  276.     if (fill_error) return fill_error;
  277.     if (fill_sn==fill_s0) clip_rmcoord();
  278. #ifdef QSORT
  279.     qsort(path_coord,path_points,sizeof(*path_coord),(cmpf)clip_compare);
  280. #endif
  281.     if (clip_active)
  282.     {
  283.     psize_init(&clip_size,&clip_max_points);
  284.     if (op.tracemem) xprint(0,"{ClipCut:%ld",clip_size);
  285.     clip_coord = (struct clip_xy*)mem_alloc(clip_size,"ClipCut");
  286.     clip_active = 0;
  287.     clip_points = clip_cut(clip_coord,clip_max_points);
  288.     mem_free(path_coord,path_size);
  289.     path_coord = NULL;
  290.     if (op.tracemem) xprint(-1,"}");
  291.     if (clip_points<0) return 2;
  292.     }
  293.     else
  294.     {
  295.     clip_points = path_points;
  296.     clip_coord = path_coord;
  297.     clip_size = path_size;
  298.     clip_max_points = path_max_points;
  299.     path_coord = NULL;
  300.     }
  301.  
  302.     if (clip_x==NULL)
  303.     {
  304.     clip_xmax = clip_max_points;
  305.     clip_x_size = clip_xmax*sizeof(*clip_x);
  306.     clip_y_size = clip_max_points*sizeof(*clip_y);
  307.     if (op.tracemem) xprint(0,"{Clip:%ld",clip_x_size+clip_y_size);
  308.     clip_x = (int*)mem_alloc(clip_x_size,"ClipX");
  309.     clip_y = (int**)mem_alloc(clip_y_size,"ClipY");
  310.     }
  311.  
  312.     if (clip_points>0)
  313.     {
  314.     clip_ymin = clip_coord[0].y;
  315.     clip_ymax = clip_coord[clip_points-1].y;
  316.     }
  317.     else
  318.     {
  319.     clip_ymin = 0;
  320.     clip_ymax = -1;
  321.     }
  322.  
  323.     if (clip_ymax-clip_ymin>=clip_max_points) return 2;
  324.     for (i=0; i<=clip_ymax-clip_ymin; i++) clip_y[i] = &cmaxx;
  325.  
  326.     clip_nx = clip_xmax;
  327.     cpx = clip_x;
  328.     for (i=0, cp=clip_coord; i<clip_points;)
  329.     {
  330.     int y = cp->y;
  331.     clip_y[y-clip_ymin] = cpx;
  332.     while(cp->y==y)
  333.     {
  334.         if (0==clip_nx--) return 2;
  335.         *cpx++ = (cp++)->x; i++;
  336.         if (cp->y!=y) return 3;
  337.         while(i<clip_points-2 && cp[1].y==y && cp->x>cp[1].x)
  338.         {
  339.         i += 2; cp += 2;
  340.         if (cp->y!=y) return 3;
  341.         }
  342.         if ( 0==clip_nx-- ) return 2;
  343.         *cpx++ = (cp++)->x; i++;
  344.     }
  345.     if ( 0==clip_nx-- ) return 2;
  346.     *cpx++ = MAX_X;
  347.     }
  348.     clip_nx = clip_xmax - clip_nx;
  349.     if (clip_mask)
  350.     {
  351.     for (i=0, cp=clip_coord; i<clip_points; i+=2, cp+=2)
  352.         hline(cp->x,cp->y,cp[1].x,clip_mask[cp->y&7]);
  353.     }
  354.     clip_active = 1;
  355.     return 0;
  356. }
  357.  
  358. void clip_clean(int phase)
  359. {
  360.     if (path_coord!=NULL)
  361.     {
  362.     mem_free(path_coord,path_size);
  363.     path_coord = NULL;
  364.     if (op.tracemem) xprint(-1,"}");
  365.     }
  366.     if (clip_coord!=NULL)
  367.     {
  368.     mem_free(clip_coord,clip_size);
  369.     clip_coord = NULL;
  370.     if (op.tracemem) xprint(-1,"}");
  371.     }
  372.     if (phase>0 && clip_x!=NULL)
  373.     {
  374.     mem_free(clip_x,clip_x_size);
  375.     mem_free(clip_y,clip_y_size);
  376.     clip_x = NULL;
  377.     clip_y = NULL;
  378.     if (op.tracemem) xprint(-1,"}");
  379.     }
  380. }
  381.  
  382. int clip_exec(unsigned char *clip_mask)
  383. {
  384.     int ret = clip1(clip_mask);
  385.     clip_clean(0);
  386.  
  387.     return ret;
  388. }
  389.  
  390. void clip_end(void)
  391. {
  392.     clip_clean(1);
  393.     clip_active = 0;
  394. }
  395.  
  396. int fill_with_pattern(int pattern)
  397. {
  398.     int i;
  399.  
  400.     if (!fill_mode) return fill_error = 1;
  401.     fill_mode = 0;
  402.     if (fill_start) return 0;
  403.     if (fill_x1!=fill_x2 || fill_y1!=fill_y2) return fill_error = 1;
  404.     if (fill_error) return fill_error;
  405.     if (fill_sn==fill_s0) clip_rmcoord();
  406. #ifdef QSORT
  407.     qsort(path_coord,path_points,sizeof(*path_coord),(cmpf)clip_compare);
  408. #endif
  409.     for (i=0; i<path_points-1; i+=2)
  410.     {
  411.     if (path_coord[i].y!=path_coord[i+1].y) return 3;
  412.     hline(path_coord[i].x,path_coord[i].y,path_coord[i+1].x,
  413.         pattern);
  414.     }
  415.     mem_free(path_coord,path_size);
  416.     path_coord = 0;
  417.     if (op.tracemem) xprint(-1,"}");
  418.     return 0;
  419. }
  420.