-- $Date: 2004/03/08 10:52:57 $
-- $Revision: 1.36 $
-- $Author: jcrocholl $
-- $Hash: 823f4df8c4900ca3137d3c14fed6ecbe $

-- This file was automatically created with ado.php.
-- Manual changes will be lost when it is updated.

with Render_Glyphs; use Render_Glyphs;
with Nocurves; use Nocurves;
with Integer_Vectors;
with Gray_Images; use Gray_Images;

package body Glyphs is

   -- Constructor for instances.
   function Create
     return Glyph_Access -- The newly created glyph.
   is
      Result : Glyph_Access := new Glyph;
   begin
      Result.Outlines := Outline_Lists.Create;
      return Result;
   end Create;

   -- Accessor to read the bounds of a glyph.
   function Get_Bounds
     (This : access Glyph-- The glyph to read from.
     return Rectangle is   -- The bounds of that glyph.
   begin
      return This.Bounds;
   end Get_Bounds;

   -- Accessor to read the outlines of a glyph.
   function Get_Outlines
     (This : access Glyph)         -- The glyph to read from.
     return Outline_List_Access is -- The outlines of that glyph.
   begin
      return This.Outlines;
   end Get_Outlines;

   -- Add an outline to a glyph.
   procedure Add_Outline
     (This : access Glyph;         -- The glyph object instance.
      Add  : in Outline_Access) is -- Add this outline to the glyph.
   begin
      Outline_Lists.Push(This.Outlines, Add);
   end Add_Outline;

   -- Make sure that the cached raster image is up to date.
   procedure Update_Image
     (This         : access Glyph;   -- The glyph object instance.
      Staff_Height : in Real;        -- Zoom factor.
      Aspect_Ratio : in Real;        -- Extra horizontal zoom factor.
      Anti_Alias   : in Positive) is -- Factor for vertical anti-alias.
   begin
      if This.Image = null
        or else This.Image.Staff_Height /= Staff_Height
        or else This.Image.Aspect_Ratio /= Aspect_Ratio
        or else This.Image.Anti_Alias /= Anti_Alias
      then
         Make_Straight(This, 0.1);
         This.Image := Render(This, Staff_Height, Aspect_Ratio, Anti_Alias);
      end if;
   end Update_Image;

   -- Get a raster image of this glyph. Create one if not cached.
   function Get_Image
     (This         : access Glyph-- The glyph object instance.
      Staff_Height : in Real;      -- Zoom factor.
      Aspect_Ratio : in Real;      -- Extra horizontal zoom factor.
      Anti_Alias   : in Positive)  -- Factor for vertical anti-alias.
     return Glyph_Image_Access is  -- The image of the glyph.
   begin
      Update_Image(This, Staff_Height, Aspect_Ratio, Anti_Alias);
      return This.Image;
   end Get_Image;

   -- Update the bounding box of the glyph.
   procedure Set_Bounds
     (This          : access Glyph-- The glyph object instance.
      Left, Top     : in Real;      -- Coordinate minima.
      Right, Bottom : in Real) is   -- Coordinate maxima.
   begin
      This.Bounds := Rectangle'(Left, Top, Right, Bottom);
   end Set_Bounds;

   -- Calculate the width of this glyph's bounding box.
   function Get_Width
     (This : access Glyph-- The glyph object instance.
     return Real is        -- The width of the glyph.
   begin
      return Get_Width(This.Bounds);
   end Get_Width;

   -- Calculate the height of this glyph's bounding box.
   function Get_Height
     (This : access Glyph-- The glyph object instance.
     return Real is        -- The height of the glyph.
   begin
      return Get_Height(This.Bounds);
   end Get_Height;

   procedure Print
     (This   : access Glyph;       -- The glyph object instance.
      Image  : access Glyph_Image-- Render into this image.
      Center : in Vector)          -- Pixel center coordinates.
   is
      Target : Integer_Vectors.Vector;
   begin
      Update_Image(This, Image.Staff_Height, Image.Aspect_Ratio, Image.Anti_Alias);
      for Y in This.Image.Pixels'Range(1) loop
         Target.Y := Integer(Center.Y * Image.Staff_Height / 400.0 +
           Real(Y) + Image.Center.Y - This.Image.Center.Y);
         if Target.Y in Image.Pixels'Range(1) then
            for X in This.Image.Pixels'Range(2) loop
               Target.X := Integer(Center.X * Image.Staff_Height / 400.0 +
                 Real(X) + Image.Center.X - This.Image.Center.X);
               if Target.X in Image.Pixels'Range(2) then
                  if Darker(This.Image.Pixels(Y, X), Image.Pixels(Target.Y, Target.X)) then
                     Image.Pixels(Target.Y, Target.X) := This.Image.Pixels(Y, X);
                  end if;
               end if;
            end loop;
         end if;
      end loop;
   end Print;

end Glyphs;