Hosted by
|
with Pipes; use Pipes;
with PBM; use PBM;
with Depixel; use Depixel;
with Real_Numbers; use Real_Numbers;
with Real_Strings; use Real_Strings;
with Integer_Strings; use Integer_Strings;
with Messages; use Messages;
with Lines; use Lines;
with Straights; use Straights;
with Outlines; use Outlines;
with Lists;
package body Read_PBM is
type End_Record is record
Outline : Outline_Access;
X : Integer;
end record;
package End_Lists is new Lists(End_Record);
use End_Lists;
subtype End_List is End_Lists.List;
subtype End_List_Access is End_Lists.List_Access;
package Change_Lists is new Lists(Integer);
use Change_Lists;
subtype Change_List is Change_Lists.List;
subtype Change_List_Access is Change_Lists.List_Access;
procedure Find_Changes
(Bits : access Bit_Buffer;
Width : in Positive;
Result : access Change_List)
is
Bit : Boolean;
Previous : Boolean;
begin
Previous := False;
for X in 1 .. Width loop
Bit := Read_Bit(Bits);
if Bit /= Previous then
Change_Lists.Push(Result, X - 1);
Previous := Bit;
end if;
end loop;
if Previous then
Change_Lists.Push(Result, Width);
end if;
end Find_Changes;
function Create
(X, Y : in Integer)
return Line_Access is
begin
return Create(((Real(X), Real(Y))));
end Create;
procedure Create_Outline
(White_To_Black : in Boolean;
Changes : access Change_List;
Y : in Integer;
Ends : access End_List)
is
X1, X2 : Integer;
New_Outline : Outline_Access := Create;
begin
X1 := Current(Changes);
Remove_Current(Changes);
X2 := Current(Changes);
Remove_Current(Changes);
if White_To_Black then
Line_Lists.Push(New_Outline, Create(X1, Y));
Line_Lists.Push(New_Outline, Create(X2, Y));
else
Line_Lists.Push(New_Outline, Create(X2, Y));
Line_Lists.Push(New_Outline, Create(X1, Y));
end if;
Insert_Before_Current(Ends, (Outline => New_Outline, X => X1));
Insert_Before_Current(Ends, (Outline => New_Outline, X => X2));
end Create_Outline;
procedure Replace_Outline
(Ends : access End_List;
A, B : in Outline_Access)
is
use type Outline_Access;
Current : End_Lists.Item_Access := First_Item(Ends);
E : End_Record := Item_Content(Current);
begin
E := Item_Content(Current);
while E.Outline /= A loop
Next_Item(Current);
if Item_Invalid(Current) then return; end if;
E := Item_Content(Current);
end loop;
E.Outline := B;
Update_Item(Current, E);
end Replace_Outline;
procedure Close_Outline
(White_To_Black : in Boolean;
Y : in Integer;
Ends : access End_List;
Result : access Glyph)
is
use type Outline_Access;
End1, End2 : End_Record;
Outline1 : Outline_Access;
Outline2 : Outline_Access;
begin
End1 := Current(Ends);
Remove_Current(Ends);
Outline1 := End1.Outline;
End2 := Current(Ends);
Remove_Current(Ends);
Outline2 := End2.Outline;
if White_To_Black then
Line_Lists.Unshift(Outline1, Create(End1.X, Y));
Line_Lists.Push (Outline2, Create(End2.X, Y));
else
Line_Lists.Push (Outline1, Create(End1.X, Y));
Line_Lists.Unshift(Outline2, Create(End2.X, Y));
end if;
if Outline1 = Outline2 then
Add_Outline(Result, Outline1);
else
if White_To_Black then
Line_Lists.Append(Outline2, Outline1);
Replace_Outline(Ends, Outline1, Outline2);
else
Line_Lists.Append(Outline1, Outline2);
Replace_Outline(Ends, Outline2, Outline1);
end if;
end if;
end Close_Outline;
procedure Append
(White_To_Black : in out Boolean;
Changes : access Change_List;
Y : in Integer;
Ends : access End_List)
is
use type End_Lists.Item_Access;
X : Integer := Current(Changes);
E : End_Record;
Outline : Outline_Access;
begin
Remove_Current(Changes);
if X /= Current(Ends).X then
if White_To_Black then
Outline := Current(Ends).Outline;
Line_Lists.Unshift(Outline, Create(Current(Ends).X, Y));
Line_Lists.Unshift(Outline, Create(X, Y));
else
Outline := Current(Ends).Outline;
Line_Lists.Push(Outline, Create(Current(Ends).X, Y));
Line_Lists.Push(Outline, Create(X, Y));
end if;
Current_Item(Ends).Content.X := X;
end if;
White_To_Black := not White_To_Black;
End_Lists.Next(Ends);
end Append;
procedure Read_Line
(Changes : access Change_List;
Y : in Integer;
Ends : access End_List;
Result : access Glyph)
is
White_To_Black : Boolean := True;
|