summaryrefslogtreecommitdiff
path: root/src/uqm/planets/oval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/uqm/planets/oval.c')
-rw-r--r--src/uqm/planets/oval.c329
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;
+ }
+}
+
+