--
--	rastergraphics: raster graphics primitives
--	Copyright (C) 2008 David Wood <dcw@kent.ac.uk>
--      Modified for clipping by Fred Barnes
--
--	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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
--

--** @module rastergraphics

--* Draws a solid ellipse.
--  Clips as necessary.
--
--  @param x, y Coordinates of centre
--  @param a, b X and Y radii
--  @param colour Colour
--  @param raster Raster

PROC fill.ellipse.radii (VAL INT x, y, a, b, VAL INT colour, [][]INT raster)

  INT INLINE FUNCTION IABS (VAL INT X)
    INT Y:
    VALOF
      IF
        X < 0
          Y := -X
        TRUE
          Y :=  X
      RESULT Y
  :

  VAL INT W IS SIZE raster[0]:
  VAL INT D IS SIZE raster:

  VAL INT a IS IABS (a):
  VAL INT b IS IABS (b):
  VAL INT ab IS a * b:

  SEQ
    IF
      ((x + a) < 0) OR ((x - a) >= W) OR ((y + b) < 0) OR ((y - b) >= D)
        SKIP                    -- wholly outside raster
      ab > 46000                -- on the safe side
        SKIP                    -- (ab)^2 would overflow
      TRUE
        BOOL inside:
        SEQ
          inside := ((x - a) > 0) AND ((x + a) < W) AND ((y - b) > 0) AND ((y + b) < D)

          VAL INT aa IS a * a:
          VAL INT bb IS b * b:
          VAL INT aabb IS aa * bb:
          INITIAL INT c IS 0:
          INITIAL INT d IS 0:
          SEQ i = 0 FOR b
            SEQ
              IF
                inside
                  -- straight-forward, all points inside
                  INITIAL INT e IS 0:
                  INITIAL INT f IS d:
                  INITIAL INT j IS 0:
                  WHILE f < aabb
                    SEQ
                      raster[y - i][x - j] := colour
                      raster[y - i][x + j] := colour
                      raster[y + i][x - j] := colour
                      raster[y + i][x + j] := colour
                      j := j + 1
                      e := e + (bb << 1)
                      f := (f + e) + bb
                TRUE
                  SEQ
                    -- top half
                    IF
                      ((y - i) < 0) OR ((y - i) > D)
                        SKIP            -- whole line outside raster
                      TRUE
                        INITIAL INT e IS 0:
                        INITIAL INT f IS d:
                        INITIAL INT j IS 0:
                        WHILE f < aabb
                          SEQ
                            IF
                              ((x - j) < 0) OR ((x - j) > W)
                                SKIP          -- left-point outside raster
                              TRUE
                                raster[y - i][x - j] := colour
                            IF
                              ((x + j) < 0) OR ((x + j) > W)
                                SKIP          -- right-point outside raster
                              TRUE
                                raster[y - i][x + j] := colour
                            j := j + 1
                            e := e + (bb << 1)
                            f := (f + e) + bb
                    -- bottom half
                    IF
                      ((y + i) < 0) OR ((y + i) > D)
                        SKIP            -- whole line outside raster
                      TRUE
                        INITIAL INT e IS 0:
                        INITIAL INT f IS d:
                        INITIAL INT j IS 0:
                        WHILE f < aabb
                          SEQ
                            IF
                              ((x - j) < 0) OR ((x - j) > W)
                                SKIP          -- left-point outside raster
                              TRUE
                                raster[y + i][x - j] := colour
                            IF
                              ((x + j) < 0) OR ((x + j) > W)
                                SKIP          -- right-point outside raster
                              TRUE
                                raster[y + i][x + j] := colour
                            j := j + 1
                            e := e + (bb << 1)
                            f := (f + e) + bb

              c := c + (aa << 1)
              d := (d + c) + aa

:

