-- $Date: 2004/01/10 02:31:02 $
-- $Revision: 1.8 $
-- $Author: jcrocholl $

with Real_Vectors; use Real_Vectors;
with Messages; use Messages;
with Outlines; use Outlines;
with Lines; use Lines;
with Straights; use Straights;

package body Stairs is

   -- Remove pixel stairs. This is done by removing all lines with a
   -- length of less than Min_Length, and using their middle point
   -- instead.
   procedure Remove_Stairs
     (This       : in out Outline-- Remove stairs from this Outline.
      Min_Length : in Real := 1.5) -- Collapse lines shorter than this.
   is
      use Outlines.Line_Lists;
      Valid_1   : Boolean := False;
      Item_0    : Line_Lists.Item;
      Item_1    : Line_Lists.Item;
      Item_2    : Line_Lists.Item;
      Vector_1  : Vector;
      Vector_2  : Vector;
      Vector_L  : Vector;
      Redundant : Boolean := False;
      Red_First : Boolean := False;

      procedure Debug is
      begin
         Reset(This);
         while Next(This) loop
            Debug2(To_String(Current(This).To) & " ");
         end loop;
         if Redundant
         then Debug("Redundant");
         else Debug("");
         end if;
      end Debug;

      procedure Collapse is
         L : Line := Create(Vector_1);
      begin
         if Valid_1 then
            Update_Item(Item_1, L);
         else
            Red_First := True;
            Vector_L := Vector_1;
         end if;
         Update_Item(Item_2, L);
         Redundant := True;
      end Collapse;

      procedure Step is
      begin
         Item_0 := Item_1;
         Item_1 := Item_2;
         Valid_1 := True;
         Vector_1 := Vector_2;
         Line_Lists.Next_Item(Item_2);
      end Step;

   begin
      -- Debug("new border");
      Item_1 := Last_Item(This);
      Vector_1 := Item_Content(Item_1).To;
      Vector_L := Vector_1;
      Item_2 := First_Item(This);
      loop
         -- Debug;
         exit when Item_Invalid(Item_2);
         Vector_2 := Item_Content(Item_2).To;
         -- Debug2(To_String(Vector_1) & " " & To_String(Vector_2) & ": ");
         if Vector_2.X = Vector_1.X
           and abs(Vector_2.Y - Vector_1.Y) <= Min_Length
         then
            Vector_1.Y := (Vector_1.Y + Vector_2.Y) / 2.0;
            Collapse;
         elsif Vector_2.Y = Vector_1.Y
           and abs(Vector_2.X - Vector_1.X) <= Min_Length
         then
            Vector_1.X := (Vector_1.X + Vector_2.X) / 2.0;
            Collapse;
         elsif Redundant then
            Remove_Item(Item_0, Item_1, This);
            Redundant := False;
         end if;
         Step;
      end loop;
      if Redundant and not Red_First then
         -- Debug2("remove last item: ");
         Remove_Item(Item_0, Item_1, This);
      else
         -- Debug2("update last item: ");
         Update_Item(Item_1, Create(Vector_L));
      end if;
      -- Debug;
   end Remove_Stairs;

   -- Remove pixel stairs. This is done by collapsing all lines with a
   -- length of less than Min_Length, and using their middle point
   -- instead.
   procedure Remove_Stairs
     (This       : in Glyph;       -- Depixel this glyph.
      Min_Length : in Real := 1.5) -- Collapse lines shorter than this.
   is
      use Glyphs.Outline_Lists;
      Outlines        : Outline_List;
      Current_Outline : Outline;
   begin
      -- Debug("remove stairs...");
      Outlines := Get_Outlines(This);
      Reset(Outlines);
      while Next(Outlines) loop
         Current_Outline := Current(Outlines);
         Remove_Stairs(Current_Outline, Min_Length);
         if Line_Lists.Empty(Current_Outline) then
            Remove_Current(Outlines);
         end if;
      end loop;
      -- Debug("remove stairs done.");
   end Remove_Stairs;

end Stairs;