maug
Quick and dirty C mini-augmentation library.
retrosft.h
Go to the documentation of this file.
1
2#ifndef RETROSFT_H
3#define RETROSFT_H
4
5#ifndef RETROSOFT_PRESENT
6# error "RETROSOFT_PRESENT must be defined in order to use retrosoft!"
7#endif /* !RETROSOFT_PRESENT */
8
24#define RETROFLAT_LINE_X 0
25#define RETROFLAT_LINE_Y 1
26
27#ifndef RETROSOFT_TRACE_LVL
28# define RETROSOFT_TRACE_LVL 0
29#endif /* RETROSOFT_TRACE_LVL */
30
37 retroflat_blit_t* target, RETROFLAT_COLOR color,
38 int x1, int y1, int x2, int y2, uint8_t flags );
39
46 retroflat_blit_t* target, const RETROFLAT_COLOR color_idx,
47 int x, int y, int w, int h, uint8_t flags );
48
57 retroflat_blit_t* target, RETROFLAT_COLOR color,
58 int x, int y, int w, int h, uint8_t flags );
59 /* maug_retrosft */
61
62#ifdef RETROSFT_C
63
64/* === */
65
66void retrosoft_line_strategy(
67 int x1, int y1, int x2, int y2,
68 uint8_t* p_for_axis, uint8_t* p_off_axis, int16_t dist[2],
69 int16_t start[2], int16_t end[2], int16_t iter[2],
70 int16_t* p_inc, int16_t* p_delta
71) {
72
73 /* Figure out strategy based on line slope. */
74 if( abs( y2 - y1 ) < abs( x2 - x1 ) ) {
75 if( x1 > x2 ) {
76 start[RETROFLAT_LINE_X] = x2;
77 start[RETROFLAT_LINE_Y] = y2;
78 end[RETROFLAT_LINE_X] = x1;
79 end[RETROFLAT_LINE_Y] = y1;
80 *p_for_axis = RETROFLAT_LINE_X;
81 } else {
82 start[RETROFLAT_LINE_X] = x1;
83 start[RETROFLAT_LINE_Y] = y1;
84 end[RETROFLAT_LINE_X] = x2;
85 end[RETROFLAT_LINE_Y] = y2;
86 *p_for_axis = RETROFLAT_LINE_X;
87 }
88 } else {
89 if( y2 < y1 ) {
90 start[RETROFLAT_LINE_X] = x2;
91 start[RETROFLAT_LINE_Y] = y2;
92 end[RETROFLAT_LINE_X] = x1;
93 end[RETROFLAT_LINE_Y] = y1;
94 *p_for_axis = RETROFLAT_LINE_Y;
95 } else {
96 start[RETROFLAT_LINE_X] = x1;
97 start[RETROFLAT_LINE_Y] = y1;
98 end[RETROFLAT_LINE_X] = x2;
99 end[RETROFLAT_LINE_Y] = y2;
100 *p_for_axis = RETROFLAT_LINE_Y;
101 }
102 }
103
104 /* C89 requires const initializers, so do math down here. */
105 *p_off_axis = 1 - *p_for_axis;
106 iter[RETROFLAT_LINE_X] = start[RETROFLAT_LINE_X];
107 iter[RETROFLAT_LINE_Y] = start[RETROFLAT_LINE_Y];
108 dist[RETROFLAT_LINE_X] = end[RETROFLAT_LINE_X] - start[RETROFLAT_LINE_X];
109 dist[RETROFLAT_LINE_Y] = end[RETROFLAT_LINE_Y] - start[RETROFLAT_LINE_Y];
110
111 /* Adjust delta/slope for off-axis. */
112 *p_delta = (2 * dist[*p_off_axis]) - dist[*p_for_axis];
113 if( 0 > dist[*p_off_axis] ) {
114 *p_inc = -1;
115 dist[*p_off_axis] *= -1;
116 } else {
117 *p_inc = 1;
118 }
119
120
121}
122
123#if defined( RETROFLAT_OPENGL ) || \
124 defined( RETROFLAT_API_PC_BIOS ) || \
125 defined( RETROFLAT_SOFT_LINES )
126
127void retrosoft_line(
128 retroflat_blit_t* target, RETROFLAT_COLOR color,
129 int x1, int y1, int x2, int y2, uint8_t flags
130) {
131
132 uint8_t for_axis = 0,
133 off_axis = 0;
134 int16_t dist[2],
135 start[2],
136 end[2],
137 iter[2],
138 inc = 1,
139 delta = 0;
140
141 /* TODO: Handle thickness. */
142
143#ifndef RETROFLAT_3D
144 /* Under 3D mode, we should never be drawing directly to the screen! */
145 if( NULL == target ) {
146 target = retroflat_screen_buffer();
147 }
148#endif /* !RETROFLAT_3D */
149
150 retroflat_px_lock( target );
151
152 retrosoft_line_strategy(
153 x1, y1, x2, y2,
154 &for_axis, &off_axis, dist, start, end, iter, &inc, &delta );
155
156 for(
157 iter[for_axis] = start[for_axis] ;
158 end[for_axis] > iter[for_axis] ;
159 iter[for_axis]++
160 ) {
161
162 /*
163 if(
164 (size_t)iter[RETROFLAT_LINE_X] < (size_t)retroflat_screen_w() &&
165 (size_t)iter[RETROFLAT_LINE_Y] < (size_t)retroflat_screen_h()
166 ) {
167 */
168 retroflat_2d_px(
169 target, color,
170 iter[RETROFLAT_LINE_X], iter[RETROFLAT_LINE_Y], flags );
171 /* } */
172
173 /* Increment off-axis based on for-axis. */
174 if( 0 < delta ) {
175 iter[off_axis] += inc;
176 delta += (2 * (dist[off_axis] - dist[for_axis]));
177 } else {
178 delta += (2 * dist[off_axis]);
179 }
180 }
181
182 retroflat_px_release( target );
183}
184
185#endif /* RETROFLAT_OPENGL || RETROFLAT_SOFT_LINES */
186
187/* === */
188
189void retrosoft_rect(
190 retroflat_blit_t* target, const RETROFLAT_COLOR color_idx,
191 int x, int y, int w, int h, uint8_t flags
192) {
193 int x_iter = 0,
194 y_iter = 0;
195
196 /* Don't trim or constrain, as those should be left to the platform-specific
197 * px routine.
198 */
199
200#ifndef RETROFLAT_3D
201 /* Under 3D mode, we should never be drawing directly to the screen! */
202 if( NULL == target ) {
203 target = retroflat_screen_buffer();
204 }
205#endif /* !RETROFLAT_3D */
206
207 retroflat_px_lock( target );
208
210
211 for( y_iter = y ; y_iter < y + h ; y_iter++ ) {
212 for( x_iter = x ; x_iter < x + w ; x_iter++ ) {
213 /* TODO: Optimize filling 4-byte sequences! */
214 retroflat_2d_px( target, color_idx, x_iter, y_iter, flags );
215 }
216 }
217
218 } else {
219
220#if defined( RETROFLAT_SOFT_LINES ) || defined( RETROFLAT_3D )
221 retrosoft_line( target, color_idx, x, y, x + w, y, flags );
222 retrosoft_line( target, color_idx, x + w, y, x + w, y + h, flags );
223 retrosoft_line( target, color_idx, x + w, y + h, x, y + h, flags );
224 retrosoft_line( target, color_idx, x, y + h, x, y, flags );
225#else
226 retroflat_line( target, color_idx, x, y, x + w, y, flags );
227 retroflat_line( target, color_idx, x + w, y, x + w, y + h, flags );
228 retroflat_line( target, color_idx, x + w, y + h, x, y + h, flags );
229 retroflat_line( target, color_idx, x, y + h, x, y, flags );
230#endif
231
232 }
233
234 retroflat_px_release( target );
235}
236
237/* === */
238
240 retroflat_blit_t* target, RETROFLAT_COLOR color,
241 int x, int y, int w, int h, uint8_t flags
242) {
243 int32_t i = 0,
244 i_prev = 0;
245 uint16_t px_x1 = 0,
246 px_y1 = 0,
247 px_x2 = 0,
248 px_y2 = 0;
249
250 /* TODO: Switch to Bresenham algorithm. */
251
252 /* TODO: Filled ellipse. */
253
254#ifndef RETROFLAT_3D
255 /* Under 3D mode, we should never be drawing directly to the screen! */
256 if( NULL == target ) {
257 target = retroflat_screen_buffer();
258 }
259#endif /* !RETROFLAT_3D */
260
261 retroflat_px_lock( target );
262
263 do {
264 /* For the soft_lut, input numbers are * 1000... so 0.1 becomes 100. */
265 for( i = 100 ; 2 * MFIX_PI + 100 > i ; i += 100 ) {
266 i_prev = i - 100;
267
268 px_x1 =
269 /* Offset circle center by X. */
270 x + (w / 2) +
271 /* Get Cartesian coord by multiplying polar coord by radius. */
272 /* (Note that we convert to i *after* multiplication so the number
273 * is big enough that the precision no longer matters! */
274 mfix_to_i( mfix_cos( i_prev ) * w / 2 );
275
276 px_y1 = y + (h / 2) + mfix_to_i( mfix_sin( i_prev ) * (h / 2) );
277 px_x2 = x + (w / 2) + mfix_to_i( mfix_cos( i ) * (w / 2) );
278 px_y2 = y + (h / 2) + mfix_to_i( mfix_sin( i ) * (h / 2) );
279
280 /* We don't do bounds checks since the low-level API should handle
281 * those! Performance!
282 */
283
284#ifdef RETROSOFT_HARD_LINES
285 retroflat_line( target, color, px_x1, px_y1, px_x2, px_y2, flags );
286#else
287 retrosoft_line( target, color, px_x1, px_y1, px_x2, px_y2, flags );
288#endif /* RETROSOFT_HARD_LINES */
289 }
290
291 /* Keep shrinking and filling if required. */
292 if( w > h ) {
293 x++;
294 w--;
295 if( 0 < h ) {
296 y++;
297 h--;
298 }
299 } else if( h > w ) {
300 y++;
301 h--;
302 if( 0 < w ) {
303 x++;
304 w--;
305 }
306 } else {
307 x++;
308 w--;
309 y++;
310 h--;
311 }
312 assert( 0 <= w );
313 assert( 0 <= h );
314 /* debug_printf( 1, "ELLIPSE %d, %d", w, h ); */
315 } while(
317 (0 < w || 0 < h)
318 );
319
320 retroflat_px_release( target );
321}
322
323#endif /* RETROSFT_C */
324
325#endif /* !RETROSFT_H */
326
int8_t RETROFLAT_COLOR
Defines an index in the platform-specific color-table.
Definition: retroflt.h:328
#define RETROFLAT_DRAW_FLAG_FILL
Flag for retroflat_rect() or retroflat_ellipse(), indicating drawn shape should be filled.
Definition: retroflt.h:376
void retroflat_line(struct RETROFLAT_BITMAP *target, const RETROFLAT_COLOR color, retroflat_pxxy_t x1, retroflat_pxxy_t y1, retroflat_pxxy_t x2, retroflat_pxxy_t y2, uint8_t flags)
Draw a straight line onto the target ::RETROFLAT_BITMAP.
void retrosoft_rect(retroflat_blit_t *target, const RETROFLAT_COLOR color_idx, int x, int y, int w, int h, uint8_t flags)
Draw a rectangle at the given coordinates, with the given dimensions.
void retrosoft_ellipse(retroflat_blit_t *target, RETROFLAT_COLOR color, int x, int y, int w, int h, uint8_t flags)
Draw an ellipsoid at the given coordinates, with the given dimensions.
void retrosoft_line(retroflat_blit_t *target, RETROFLAT_COLOR color, int x1, int y1, int x2, int y2, uint8_t flags)
Draw a line from x1, y1 to x2, y2.