diff options
Diffstat (limited to 'src/uqm/planets/oval.c')
-rw-r--r-- | src/uqm/planets/oval.c | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/src/uqm/planets/oval.c b/src/uqm/planets/oval.c new file mode 100644 index 0000000..4112997 --- /dev/null +++ b/src/uqm/planets/oval.c @@ -0,0 +1,329 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "../units.h" +#include "libs/gfxlib.h" +#include "libs/graphics/context.h" +#include "libs/graphics/drawable.h" + +#include "planets.h" + +#define NUM_QUADS 4 + +void +DrawOval (RECT *pRect, BYTE num_off_pixels) +{ +#define FIRST_QUAD (1 << 0) +#define SECOND_QUAD (1 << 1) +#define THIRD_QUAD (1 << 2) +#define FOURTH_QUAD (1 << 3) + COUNT off; + COORD x, y; + SIZE A, B; + long Asquared, TwoAsquared, + Bsquared, TwoBsquared; + long d, dx, dy; + BYTE quad_visible; + LINE corners; + POINT mp; + PRIMITIVE prim[NUM_QUADS]; + COUNT StartPrim; + RECT ClipRect; + BRESENHAM_LINE ClipLine; + + ClipRect.corner.x = ClipRect.corner.y = 0; + + corners.first.x = pRect->corner.x - ClipRect.corner.x; + corners.first.y = pRect->corner.y - ClipRect.corner.y; + corners.second.x = corners.first.x + pRect->extent.width - 1; + corners.second.y = corners.first.y + pRect->extent.height - 1; + if (corners.second.x <= corners.first.x + || corners.second.y <= corners.first.y) + { + if (corners.second.x < corners.first.x) + corners.second.x = corners.first.x; + if (corners.second.y < corners.first.y) + corners.second.y = corners.first.y; + + DrawLine (&corners); + return; + } + + ClipRect.extent.width = SIS_SCREEN_WIDTH; + ClipRect.extent.height = SIS_SCREEN_HEIGHT; + + quad_visible = 0; + mp.x = (corners.first.x + corners.second.x) >> 1; + mp.y = (corners.first.y + corners.second.y) >> 1; + ClipRect.corner.x = ClipRect.corner.y = 0; + + if (corners.first.y >= 0 && corners.first.y < ClipRect.extent.height + && corners.second.x >= 0 && corners.second.x < ClipRect.extent.width) + quad_visible |= FIRST_QUAD; + else + { + ClipLine.first.x = mp.x; + ClipLine.first.y = corners.first.y; + ClipLine.second.x = corners.second.x; + ClipLine.second.y = mp.y; + if (_clip_line (&ClipRect, &ClipLine)) + quad_visible |= FIRST_QUAD; + } + + if (corners.first.y >= 0 && corners.first.y < ClipRect.extent.height + && corners.first.x >= 0 && corners.first.x < ClipRect.extent.width) + quad_visible |= SECOND_QUAD; + else + { + ClipLine.first.x = mp.x; + ClipLine.first.y = corners.first.y; + ClipLine.second.x = corners.first.x; + ClipLine.second.y = mp.y; + if (_clip_line (&ClipRect, &ClipLine)) + quad_visible |= SECOND_QUAD; + } + + if (corners.second.y >= 0 && corners.second.y < ClipRect.extent.height + && corners.first.x >= 0 && corners.first.x < ClipRect.extent.width) + quad_visible |= THIRD_QUAD; + else + { + ClipLine.first.x = mp.x; + ClipLine.first.y = corners.second.y; + ClipLine.second.x = corners.first.x; + ClipLine.second.y = mp.y; + if (_clip_line (&ClipRect, &ClipLine)) + quad_visible |= THIRD_QUAD; + } + + if (corners.second.y >= 0 && corners.second.y < ClipRect.extent.height + && corners.second.x >= 0 && corners.second.x < ClipRect.extent.width) + quad_visible |= FOURTH_QUAD; + else + { + ClipLine.first.x = mp.x; + ClipLine.first.y = corners.second.y; + ClipLine.second.x = corners.second.x; + ClipLine.second.y = mp.y; + if (_clip_line (&ClipRect, &ClipLine)) + quad_visible |= FOURTH_QUAD; + } + + if (!quad_visible) + return; + + StartPrim = END_OF_LIST; + for (x = 0; x < NUM_QUADS; ++x) + { + if (quad_visible & (1 << x)) + { + SetPrimNextLink (&prim[x], StartPrim); + SetPrimType (&prim[x], POINT_PRIM); + SetPrimColor (&prim[x], _get_context_fg_color ()); + + StartPrim = x; + } + } + + A = pRect->extent.width >> 1; + B = pRect->extent.height >> 1; + + x = 0; + y = B; + + Asquared = ((long)A * A) << 1; + Bsquared = ((long)B * B) << 1; + do + { + Asquared >>= 1; + Bsquared >>= 1; + TwoAsquared = Asquared << 1; + dy = TwoAsquared * B; + } while (dy / B != TwoAsquared); + TwoBsquared = Bsquared << 1; + + dx = 0; + d = Bsquared - (dy >> 1) + (Asquared >> 2); + + off = 0; + A += pRect->corner.x; + B += pRect->corner.y; + while (dx < dy) + { + if (off-- == 0) + { + prim[0].Object.Point.x = prim[3].Object.Point.x = A + x; + prim[0].Object.Point.y = prim[1].Object.Point.y = B - y; + prim[1].Object.Point.x = prim[2].Object.Point.x = A - x; + prim[2].Object.Point.y = prim[3].Object.Point.y = B + y; + + DrawBatch (prim, StartPrim, 0); + off = num_off_pixels; + } + + if (d > 0) + { + --y; + dy -= TwoAsquared; + d -= dy; + } + + ++x; + dx += TwoBsquared; + d += Bsquared + dx; + } + + d += ((((Asquared - Bsquared) * 3) >> 1) - (dx + dy)) >> 1; + + while (y >= 0) + { + if (off-- == 0) + { + prim[0].Object.Point.x = prim[3].Object.Point.x = A + x; + prim[0].Object.Point.y = prim[1].Object.Point.y = B - y; + prim[1].Object.Point.x = prim[2].Object.Point.x = A - x; + prim[2].Object.Point.y = prim[3].Object.Point.y = B + y; + + DrawBatch (prim, StartPrim, 0); + off = num_off_pixels; + } + + if (d < 0) + { + ++x; + dx += TwoBsquared; + d += dx; + } + + --y; + dy -= TwoAsquared; + d += Asquared - dy; + } +} + +void +DrawFilledOval (RECT *pRect) +{ + COORD x, y; + SIZE A, B; + long Asquared, TwoAsquared, + Bsquared, TwoBsquared; + long d, dx, dy; + LINE corners; + PRIMITIVE prim[NUM_QUADS >> 1]; + COUNT StartPrim; + + corners.first.x = pRect->corner.x; + corners.first.y = pRect->corner.y; + corners.second.x = corners.first.x + pRect->extent.width - 1; + corners.second.y = corners.first.y + pRect->extent.height - 1; + if (corners.second.x <= corners.first.x + || corners.second.y <= corners.first.y) + { + if (corners.second.x < corners.first.x) + corners.second.x = corners.first.x; + if (corners.second.y < corners.first.y) + corners.second.y = corners.first.y; + + DrawLine (&corners); + return; + } + + StartPrim = END_OF_LIST; + for (x = 0; x < (NUM_QUADS >> 1); ++x) + { + SetPrimNextLink (&prim[x], StartPrim); + SetPrimType (&prim[x], RECTFILL_PRIM); + SetPrimColor (&prim[x], _get_context_fg_color ()); + prim[x].Object.Rect.extent.height = 1; + + StartPrim = x; + } + + A = pRect->extent.width >> 1; + B = pRect->extent.height >> 1; + + x = 0; + y = B; + + Asquared = ((long)A * A) << 1; + Bsquared = ((long)B * B) << 1; + do + { + Asquared >>= 1; + Bsquared >>= 1; + TwoAsquared = Asquared << 1; + dy = TwoAsquared * B; + } while (dy / B != TwoAsquared); + TwoBsquared = Bsquared << 1; + + dx = 0; + d = Bsquared - (dy >> 1) + (Asquared >> 2); + + A += pRect->corner.x; + B += pRect->corner.y; + while (dx < dy) + { + if (d > 0) + { + prim[0].Object.Rect.corner.x = + prim[1].Object.Rect.corner.x = A - x; + prim[0].Object.Rect.extent.width = + prim[1].Object.Rect.extent.width = (x << 1) + 1; + prim[0].Object.Rect.corner.y = B - y; + prim[1].Object.Rect.corner.y = B + y; + + DrawBatch (prim, StartPrim, 0); + + --y; + dy -= TwoAsquared; + d -= dy; + } + + ++x; + dx += TwoBsquared; + d += Bsquared + dx; + } + + d += ((((Asquared - Bsquared) * 3) >> 1) - (dx + dy)) >> 1; + + while (y >= 0) + { + prim[0].Object.Rect.corner.x = + prim[1].Object.Rect.corner.x = A - x; + prim[0].Object.Rect.extent.width = + prim[1].Object.Rect.extent.width = (x << 1) + 1; + prim[0].Object.Rect.corner.y = B - y; + prim[1].Object.Rect.corner.y = B + y; + + DrawBatch (prim, StartPrim, 0); + + if (d < 0) + { + ++x; + dx += TwoBsquared; + d += dx; + } + + --y; + dy -= TwoAsquared; + d += Asquared - dy; + } +} + + |