2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation, either version 3 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "gameglobals.h"
22 #include "sincostab.c"
26 static FILE *fdump
= NULL
;
29 typedef struct PolyPoint
{
37 static int polyPointPoolSize
= 0;
38 static int polyPointPoolPos
= 0;
39 static PolyPoint
*polyPointPool
= NULL
;
40 static int polyScans
[200]; // index of the first point of each scan; -1: none
41 static int firstX
, firstY
;
42 static int lastX
, lastY
;
43 static int pofsx
, pofsy
;
50 void polymodInitialize (void) {
51 for (int f
= 0; f
< 200; ++f
) polyScans
[f
] = -1;
53 polyPointPoolSize
= 0;
59 void polymodDeinitialize (void) {
60 if (polyPointPool
!= NULL
) free(polyPointPool
);
62 polyPointPoolSize
= 0;
68 static inline int allocPolyPoint (int x
, int next
, int dy
) {
69 if (polyPointPoolPos
+1 > polyPointPoolSize
) {
70 int newsz
= polyPointPoolSize
+8192;
71 PolyPoint
*nn
= realloc(polyPointPool
, sizeof(PolyPoint
)*newsz
);
73 if (nn
== NULL
) fatal("out of memory in polymod");
75 polyPointPoolSize
= newsz
;
77 polyPointPool
[polyPointPoolPos
].x
= x
;
78 polyPointPool
[polyPointPoolPos
].next
= next
;
79 polyPointPool
[polyPointPoolPos
].dy
= dy
;
80 polyPointPool
[polyPointPoolPos
].vertexnum
= vertexnum
;
81 return polyPointPoolPos
++;
85 static inline void insertPoint (int x
, int y
, int dy
) {
86 if (y
>= 0 && y
< 200) {
89 if ((n
= polyScans
[y
]) != -1) {
92 for (p
= -1; n
!= -1 && x
> polyPointPool
[n
].x
; p
= n
, n
= polyPointPool
[n
].next
) ;
94 // this is new first point
95 polyScans
[y
] = allocPolyPoint(x
, n
, dy
);
97 // insert new point after p; n is the next point
98 polyPointPool
[p
].next
= allocPolyPoint(x
, n
, dy
);
102 polyScans
[y
] = allocPolyPoint(x
, -1, dy
);
109 static inline void rotate (int *x, int *y) {
110 int64_t tx = (int64_t)(*x)*pscale/POLYFIX_BASE;
111 int64_t ty = (int64_t)(*y)*pscale/POLYFIX_BASE;
112 *x = (tx*costab[pangle]-ty*sintab[pangle])/POLYFIX_BASE+pofsx;
113 *y = (tx*sintab[pangle]+ty*costab[pangle])/POLYFIX_BASE+pofsy;
117 #define rotate(x, y) do { \
118 int64_t tx = (int64_t)(x)*pscale/POLYFIX_BASE; \
119 int64_t ty = (int64_t)(y)*pscale/POLYFIX_BASE; \
120 (x) = (tx*costab[pangle]-ty*sintab[pangle])/POLYFIX_BASE+pofsx; \
121 (y) = (tx*sintab[pangle]+ty*costab[pangle])/POLYFIX_BASE+pofsy; \
124 #define rotate(x, y) do { \
125 int64_t tx = (int64_t)(x)*pscale/POLYFIX_BASE; \
126 int64_t ty = (int64_t)(y)*pscale/POLYFIX_BASE; \
127 (x) = (tx*sintab[panglec]-ty*sintab[pangles])/POLYFIX_BASE+pofsx; \
128 (y) = (tx*sintab[pangles]+ty*sintab[panglec])/POLYFIX_BASE+pofsy; \
132 static void lineDDA (int x0
, int y0
, int x1
, int y1
) {
142 if (fdump
) fprintf(fdump
, "%d: (%d,%d)-(%d,%d)\n", vertexnum
, x0
, y0
, x1
, y1
);
144 if (y0
== y1
) return; // horizontal line
146 //fprintf(stderr, "*(%d,%d)-(%d,%d)\n", x0, y0, x1, y1);
147 if ((y0
< 0 && y1
< 0) || (y0
> 199 && y1
> 199)) return; // out-of-screen lines aren't interesting
150 // straight vertical line
152 for (; y0
< y1
; ++y0
) insertPoint(x0
, y0
, 1);
154 for (--y0
; y0
>= y1
; --y0
) insertPoint(x0
, y0
, -1);
160 dx
= (double)(x1
-x0
)/(double)(y1
-y0
);
161 for (; y0
< y1
; ++y0
) { insertPoint(x
+0.5, y0
, 1); x
+= dx
; }
163 dx
= (double)(x1
-x0
)/(double)(y0
-y1
);
164 for (--y0
; y0
>= y1
; --y0
) { insertPoint(x
+0.5, y0
, -1); x
+= dx
; }
170 void polymodStart (int ofsx
, int ofsy
, int scale
, int angle
) {
171 for (int f
= 0; f
< 200; ++f
) polyScans
[f
] = -1;
172 polyPointPoolPos
= 0;
176 angle
%= 360; if (angle
< 0) angle
+= 360;
178 panglec
= (angle
+90)%360;
180 fdump
= fopen("zdump.txt", "w");
186 void polymodAddPoint (int x
, int y
) {
188 lineDDA(lastX
, lastY
, x
, y
);
199 void polymodEnd (void) {
200 if (vertexnum
>= 3) {
201 lineDDA(lastX
, lastY
, firstX
, firstY
);
203 for (int f
= 0; f
< 200; ++f
) polyScans
[f
] = -1;
208 static void drawLine (SDL_Surface
*frame
, int x0
, int y0
, int x1
, int y1
, Uint8 color
, Uint8 alpha
) {
209 int dx
= abs(x1
-x0
), sx
= x0
<x1
? 1 : -1;
210 int dy
= -abs(y1
-y0
), sy
= y0
<y1
? 1 : -1;
211 int err
= dx
+dy
, e2
; /* error value e_xy */
213 //if (x0 == x1 && y0 == y1) break; // break first, so last point is not drawn
214 putPixelA2x(frame
, x0
, y0
, color
, alpha
);
215 if (x0
== x1
&& y0
== y1
) break;
217 if (e2
>= dy
) { err
+= dy
; x0
+= sx
; } /* e_xy+e_x > 0 */
218 if (e2
<= dx
) { err
+= dx
; y0
+= sy
; } /* e_xy+e_y < 0 */
223 void polymodFill (SDL_Surface
*frame
, Uint8 color
, Uint8 alpha
) {
224 //fprintf(stderr, "vertexnum=%d\n", vertexnum);
225 if (vertexnum
< 1) return;
227 fprintf(fdump
, "=========================\n");
228 for (int y
= 0; y
< 200; ++y
) {
229 int p
= polyScans
[y
], cnt
= 0;
232 fprintf(fdump
, "y: %d\n", y
);
234 fprintf(fdump
, " x: %d (%d) [%d]\n", polyPointPool
[p
].x
, polyPointPool
[p
].dy
, polyPointPool
[p
].vertexnum
);
235 p
= polyPointPool
[p
].next
;
238 if (cnt
%2) fprintf(fdump
, " ***\n");
242 if (vertexnum
== 1) {
243 rotate(firstX
, firstY
);
244 putPixelA2x(frame
, firstX
, firstY
, color
, alpha
);
248 if (vertexnum
== 2) {
249 rotate(firstX
, firstY
);
250 rotate(lastX
, lastY
);
251 //fprintf(stderr, "(%d,%d)-(%d,%d)\n", firstX, firstY, lastX, lastY);
252 drawLine(frame
, firstX
, firstY
, lastX
, lastY
, color
, alpha
);
256 for (int y
= 0; y
< 200; ++y
) {
257 int p
= polyScans
[y
];
260 int wind
= polyPointPool
[p
].dy
, x
= polyPointPool
[p
].x
;
262 for (p
= polyPointPool
[p
].next
; p
!= -1; p
= polyPointPool
[p
].next
) {
263 int ex
= polyPointPool
[p
].x
;
266 while (x
++ < ex
) putPixelA2x(frame
, x
, y
, color
, alpha
);
270 if (polyPointPool
[p
].dy
< 0) putPixelA2x(frame
, x
, y
, color
, alpha
);
271 wind
+= polyPointPool
[p
].dy
;
276 if (fdump
!= NULL
) fclose(fdump
);
284 static int polymodStrokes (const signed char *data
, int len
, SDL_Surface
*frame
, int ofsx
, int ofsy
, int scale
, int angle
, Uint8 color
, Uint8 alpha
) {
288 //fprintf(stderr, "len=%d\n", len);
293 if (data
[0] == -128 && data
[1] == -128) {
296 polymodStart(ofsx, ofsy, scale, angle);
297 polymodAddPoint(data[-2], data[-1]);
299 polymodFill(frame, color, alpha);
305 //fprintf(stderr, " %d: (%d,%d)-(%d,%d)\n", len, data[-2], data[-1], data[0], data[1]);
306 polymodStart(ofsx
, ofsy
, scale
, angle
);
307 polymodAddPoint(data
[-2], data
[-1]);
308 polymodAddPoint(data
[0], data
[1]);
310 polymodFill(frame
, color
, alpha
);
319 polymodStart(ofsx, ofsy, scale, angle);
320 polymodAddPoint(data[-2], data[-1]);
322 polymodFill(frame, color, alpha);
331 int polymodChar (SDL_Surface
*frame
, int ch
, int ofsx
, int ofsy
, int scale
, int angle
, Uint8 color
, Uint8 alpha
) {
332 if (ch
< ' ' || ch
> 127) return 0;
333 return polymodStrokes(hfData
+hfInfo
[ch
-32], hfInfo
[ch
-31]-hfInfo
[ch
-32], frame
, ofsx
, ofsy
, scale
, angle
, color
, alpha
);
337 void polymodStr (SDL_Surface
*frame
, const char *str
, int ofsx
, int ofsy
, int scale
, int angle
, Uint8 color
, Uint8 alpha
) {
341 w
= polymodChar(frame
, *str
++, ofsx
, ofsy
, scale
, angle
, color
, alpha
);