-- $Date: 2004/02/23 08:36:42 $
-- $Revision: 1.3 $
-- $Author: jcrocholl $

with Readers; use Readers;
with Token_Readers; use Token_Readers;
with XML_Readers; use XML_Readers;

with Writers; use Writers;
with Indent_Writers; use Indent_Writers;
with XML_Writers; use XML_Writers;

with Real_Vectors; use Real_Vectors;
with Real_Strings; use Real_Strings;
with Integer_Strings; use Integer_Strings;
with Messages; use Messages;

with Glyphs; use Glyphs;
with Glyphs.SVG; use Glyphs.SVG;

package body Choices.SVG is

   procedure Read_SVG_Header
     (XML : access XML_Reader) is
   begin
      Assert_Tag_Name(XML, "?xml");
      Assert_Attribute_Name(XML, "version");
      Assert_Attribute_Value(XML, "1.0");
      Assert_Attribute_Name(XML, "standalone");
      Assert_Attribute_Value(XML, "no");
      Exit_Tag(XML);

      Assert_Tag_Name(XML, "!DOCTYPE");
      Assert_Attribute_Name(XML, "svg");
      Assert_Attribute_Name(XML, "PUBLIC");
      Assert_Attribute_Name(XML, "-//W3C//DTD SVG 1.1//EN");
      Assert_Attribute_Name(XML, "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd");
      Exit_Tag(XML);
   end Read_SVG_Header;

   procedure Write_SVG_Header
     (XML : access XML_Writer)
   is
   begin
      Start_Tag(XML, "?xml");
      Write_Attribute(XML, "version", "1.0");
      Write_Attribute(XML, "standalone", "no");
      Close_Tag(XML, "?");
      New_Line(XML);

      Start_Tag(XML, "!DOCTYPE");
      Put(XML, ' '); Write_Word(XML, "svg");
      Put(XML, ' '); Write_Word(XML, "PUBLIC");
      Put(XML, ' '); Write_String(XML, "-//W3C//DTD SVG 1.1//EN");
      Put(XML, ' '); Write_String(XML, "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd");
      Close_Tag(XML);
      New_Line(XML);
   end Write_SVG_Header;

   procedure Read_SVG_Start_Tag
     (XML  : access XML_Reader;
      This : access Choice)
   is
      Width, Height : Real;
   begin
      Assert_Tag_name(XML, "svg");
      while not End_Of_Tag(XML) loop
         Read_Attribute_Name(XML);
         if Found(XML, "width") then
            Read_Attribute_Value(XML);
            Width := To_Number(Get_Token(XML));
         elsif Found(XML, "height") then
            Read_Attribute_Value(XML);
            Height := To_Number(Get_Token(XML));
         elsif Found(XML, "version") then
            Assert_Attribute_Value(XML, "1.1");
         elsif Found(XML, "xmlns") then
            Assert_Attribute_Value(XML, "http://www.w3.org/2000/svg");
         elsif Found(XML, "xmlns:roemer") then
            Assert_Attribute_Value(XML, "http://roemer.sourceforge.net/xmlns");
         else
            XML_Expect_Error(XML, "", "width" / "height");
         end if;
      end loop;
      Exit_Tag(XML);
   end Read_SVG_Start_Tag;

   procedure Write_SVG_Start_Tag
     (XML       : access XML_Writer;
      This      : access Choice;
      Tolerance : in Real;
      Width     : in Real;
      Height    : in Real) is
   begin
      Start_Tag(XML, "svg");
      -- Write_Attribute(XML, "x", To_String(Get_Bounds(This).Left));
      -- Write_Attribute(XML, "y", To_String(Get_Bounds(This).Top));

      -- Messages.Debug(
      --   "width " & To_String(Get_Width(This)) &
      --   " height " & To_String(Get_Height(This)));
      Write_Attribute(XML, "width", To_String(Width, Tolerance));
      Write_Attribute(XML, "height", To_String(Height, Tolerance));

      -- To_String(Smaller_Or_Equal(Bounds.Left)) & " " &
      -- To_String(Smaller_Or_Equal(Bounds.Bottom)) & " " &
      -- To_String(Greater_Or_Equal(Bounds.Right)) & " " &
      -- To_String(Greater_Or_Equal(Bounds.Top)));
      Write_Attribute(XML, "version", "1.1");
      Write_Attribute(XML, "xmlns", "http://www.w3.org/2000/svg");
      Write_Attribute(XML, "xmlns:roemer", "http://roemer.sourceforge.net/xmlns");
      Close_Tag(XML);
      New_Line(XML);
      Indent(XML);
   end Write_SVG_Start_Tag;

   -- Read a choice from an XML reader.
   function Read
     (XML : access XML_Reader-- Read from this line reader.
     return Choice_Access      -- The newly created choice.
   is
      Result : Choice_Access := Create;
   begin
      -- Debug("reading choices");

      Read_SVG_Header(XML);
      Read_SVG_Start_Tag(XML, Result);

      -- if not Next_Line(XML) then Error(XML, "expect at least one outline"); end if;
      while Descend(XML) loop
         -- Debug(Get_Token(XML));
         if not Context_Is(XML, "path") then
            XML_Expect_Error(XML, "/svg", "path");
         end if;
         -- Debug("reading path");
         Add_Regular(Result, Read(XML));
         -- Debug("done path");
      end loop;
      -- Debug("done choices");

      return Result;
   end Read;

   procedure Layout
     (This           : access Choice;
      Glyphs_Per_Row : out Positive;
      Rows           : out Positive;
      Glyph_Width    : out Real;
      Glyph_Height   : out Real)
   is
      Layout_Space  : constant := 8;
      Layout_Factor : constant := 4;
      Count         : Natural := This.Regular_Count + This.Special_Count;
   begin
      Glyph_Width := 0.0;
      Glyph_Height := 0.0;

      for Index in 1 .. This.Regular_Count loop
         if Get_Height(Get_Regular(This, Index)) > Glyph_Height then
            Glyph_Height := Get_Height(Get_Regular(This, Index));
         end if;
         if Get_Width(Get_Regular(This, Index)) > Glyph_Width then
            Glyph_Width := Get_Width(Get_Regular(This, Index));
         end if;
      end loop;

      for Index in 1 .. This.Special_Count loop
         if Get_Height(Get_Special(This, Index)) > Glyph_Height then
            Glyph_Height := Get_Height(Get_Special(This, Index));
         end if;
         if Get_Width(Get_Special(This, Index)) > Glyph_Width then
            Glyph_Width := Get_Width(Get_Special(This, Index));
         end if;
      end loop;

      Glyph_Width := Glyph_Width + Real(Layout_Space * Layout_Factor);
      Glyph_Height := Glyph_Height + Real(Layout_Space * Layout_Factor);

      Glyphs_Per_Row := 480 * Layout_Factor / Positive(Glyph_Width);
      Rows := (Count + Glyphs_Per_Row - 1) / Glyphs_Per_Row;

      if Rows = 1 then
         Glyphs_Per_Row := Count;
      end if;
   end Layout;

   -- Write a choice to an XML writer.
   procedure Write
     (XML       : access XML_Writer-- Use this XML writer.
      This      : access Choice;     -- Write this choice.
      Tolerance : in Real)           -- Tolerance level.
   is
      Glyph_Width    : Real;
      Glyph_Height   : Real;
      Glyphs_Per_Row : Positive;
      Rows           : Positive;
      X, Y           : Natural := 0;