00001 
00002 
00003 
00004 
00005 
00006 
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <math.h>
00010 #include <string.h>
00011 
00012 #include "render.h"
00013 #include "greymap.h"
00014 #include "auxiliary.h"
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 render_t *render_new(greymap_t *gm) {
00048   render_t *rm;
00049 
00050   rm = (render_t *) malloc(sizeof(render_t));
00051   if (!rm) {
00052     return NULL;
00053   }
00054   memset(rm, 0, sizeof(render_t));
00055   rm->gm = gm;
00056   rm->incrow_buf = (int *) malloc(gm->h * sizeof(int));
00057   if (!rm->incrow_buf) {
00058     free(rm);
00059     return NULL;
00060   }
00061   memset(rm->incrow_buf, 0, gm->h * sizeof(int));
00062   return rm;
00063 }
00064 
00065 
00066 
00067 void render_free(render_t *rm) {
00068   free(rm->incrow_buf);
00069   free(rm);
00070 }
00071 
00072 
00073 void render_close(render_t *rm) {
00074   if (rm->x0 != rm->x1 || rm->y0 != rm->y1) {
00075     render_lineto(rm, rm->x0, rm->y0);
00076   }
00077   GM_INC(rm->gm, rm->x0i, rm->y0i, (rm->a0+rm->a1)*255);
00078 
00079   
00080   
00081   
00082 }
00083 
00084 
00085 void render_moveto(render_t *rm, double x, double y) {
00086   
00087   render_close(rm);
00088 
00089   rm->x0 = rm->x1 = x;
00090   rm->y0 = rm->y1 = y;
00091   rm->x0i = (int)floor(rm->x0);
00092   rm->x1i = (int)floor(rm->x1);
00093   rm->y0i = (int)floor(rm->y0);
00094   rm->y1i = (int)floor(rm->y1);
00095   rm->a0 = rm->a1 = 0;
00096 }
00097 
00098 
00099 
00100 static void incrow(render_t *rm, int x, int y, int b) {
00101   int i, x0;
00102 
00103   if (y < 0 || y >= rm->gm->h) {
00104     return;
00105   }
00106 
00107   if (x < 0) {
00108     x = 0;
00109   } else if (x > rm->gm->w) {
00110     x = rm->gm->w;
00111   }
00112   if (rm->incrow_buf[y] == 0) {
00113     rm->incrow_buf[y] = x+1; 
00114     return;
00115   }
00116   x0 = rm->incrow_buf[y]-1;
00117   rm->incrow_buf[y] = 0;
00118   if (x0 < x) {
00119     for (i=x0; i<x; i++) {
00120       GM_INC(rm->gm, i, y, -b);
00121     }
00122   } else {
00123     for (i=x; i<x0; i++) {
00124       GM_INC(rm->gm, i, y, b);
00125     }
00126   }    
00127 }
00128 
00129 
00130 void render_lineto(render_t *rm, double x2, double y2) {
00131   int x2i, y2i;
00132   double t0=2, s0=2;
00133   int sn, tn;
00134   double ss=2, ts=2;
00135   double r0, r1;
00136   int i, j;
00137   int rxi, ryi;
00138   int s;
00139 
00140   x2i = (int)floor(x2);
00141   y2i = (int)floor(y2);
00142 
00143   sn = abs(x2i - rm->x1i);
00144   tn = abs(y2i - rm->y1i);
00145 
00146   if (sn) {
00147     s0 = ((x2>rm->x1 ? rm->x1i+1 : rm->x1i) - rm->x1)/(x2-rm->x1);
00148     ss = fabs(1.0/(x2-rm->x1));
00149   }
00150   if (tn) {
00151     t0 = ((y2>rm->y1 ? rm->y1i+1 : rm->y1i) - rm->y1)/(y2-rm->y1);
00152     ts = fabs(1.0/(y2-rm->y1));
00153   }
00154 
00155   r0 = 0;
00156 
00157   i = 0;
00158   j = 0;
00159 
00160   rxi = rm->x1i;
00161   ryi = rm->y1i;
00162 
00163   while (i<sn || j<tn) {
00164     if (j>=tn || (i<sn && s0+i*ss < t0+j*ts)) {
00165       r1 = s0+i*ss;
00166       i++;
00167       s = 1;
00168     } else {
00169       r1 = t0+j*ts;
00170       j++;
00171       s = 0;
00172     }
00173     
00174     
00175     
00176     rm->a1 += (r1-r0)*(y2-rm->y1)*(rxi+1-((r0+r1)/2.0*(x2-rm->x1)+rm->x1));
00177 
00178     
00179     if (s && x2>rm->x1) {
00180       GM_INC(rm->gm, rxi, ryi, rm->a1*255);
00181       rm->a1 = 0;
00182       rxi++;
00183       rm->a1 += rm->y1+r1*(y2-rm->y1)-ryi;
00184     } else if (!s && y2>rm->y1) {
00185       GM_INC(rm->gm, rxi, ryi, rm->a1*255);
00186       rm->a1 = 0;
00187       incrow(rm, rxi+1, ryi, 255);
00188       ryi++;
00189     } else if (s && x2<=rm->x1) {
00190       rm->a1 -= rm->y1+r1*(y2-rm->y1)-ryi;
00191       GM_INC(rm->gm, rxi, ryi, rm->a1*255);
00192       rm->a1 = 0;
00193       rxi--;
00194     } else if (!s && y2<=rm->y1) {
00195       GM_INC(rm->gm, rxi, ryi, rm->a1*255);
00196       rm->a1 = 0;
00197       ryi--;
00198       incrow(rm, rxi+1, ryi, -255);
00199     }
00200 
00201     r0 = r1;
00202   }
00203   
00204   
00205   
00206   r1 = 1;
00207   rm->a1 += (r1-r0)*(y2-rm->y1)*(rxi+1-((r0+r1)/2.0*(x2-rm->x1)+rm->x1));
00208 
00209   rm->x1i = x2i;
00210   rm->y1i = y2i;
00211   rm->x1 = x2;
00212   rm->y1 = y2;
00213 
00214   
00215 }
00216 
00217 
00218 void render_curveto(render_t *rm, double x2, double y2, double x3, double y3, double x4, double y4) {
00219   double x1, y1, dd0, dd1, dd, delta, e2, epsilon, t;
00220 
00221   x1 = rm->x1;  
00222   y1 = rm->y1;
00223 
00224   
00225 
00226 
00227 
00228 
00229   delta = .1;  
00230 
00231   
00232 
00233   dd0 = sq(x1-2*x2+x3) + sq(y1-2*y2+y3);
00234   dd1 = sq(x2-2*x3+x4) + sq(y2-2*y3+y4);
00235   dd = 6*sqrt(max(dd0, dd1));
00236   e2 = 8*delta <= dd ? 8*delta/dd : 1;
00237   epsilon = sqrt(e2);  
00238 
00239   for (t=epsilon; t<1; t+=epsilon) {
00240     render_lineto(rm, x1*cu(1-t)+3*x2*sq(1-t)*t+3*x3*(1-t)*sq(t)+x4*cu(t),
00241                   y1*cu(1-t)+3*y2*sq(1-t)*t+3*y3*(1-t)*sq(t)+y4*cu(t));
00242   }
00243   render_lineto(rm, x4, y4);
00244 }