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 }