unit TTFilter;

{ TT Filtering functions for antialiased output,
  Copr. 1996 Matthias Koeppe

  This is not available for TP 6.0

  $Id: ttfilter.pas 1.3 1999/02/09 10:50:26 mkoeppe Exp $

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library 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
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
}

interface

type
{ Filter function template
}
  TFilterFunc = function(dx, dy: Real; Info: pointer): Real;

{ Internal filter representation
}
  PFilter = ^TFilter;
  TFilter = record
    Size: Integer;
    PostScaling: Integer;
    Support: Integer;
    Divisor: Integer;
    Data: record end
  end;

{$ifndef ver60}
{ Create-filter procedure
}
function CreateFilter(PostScaling: Integer; Support: Integer;
  FilterFunc: TFilterFunc; HSymmetry: Boolean; VSymmetry: Boolean;
  Info: pointer): PFilter;

{ Standard filters
}
function ConeFilter(dx, dy: Real; ConeRadius: pointer): Real;
function BoxFilter(dx, dy: Real; Info: pointer): Real;
{$endif}

implementation

{$ifndef ver60}
function CreateFilter(PostScaling: Integer; Support: Integer;
  FilterFunc: TFilterFunc; HSymmetry: Boolean; VSymmetry: Boolean;
  Info: pointer): PFilter;
var
  Filter: PFilter;
  xmin, xmax, ymin, ymax: Integer;
  delta: Word;
  b, x, y: Integer;
  P: PChar;
  sum: LongInt;
begin
  delta := PostScaling * Support;
  If Odd(delta) then Inc(delta);
  GetMem(Filter, Sqr(delta) + SizeOf(TFilter));
  CreateFilter := Filter;
  Filter^.Size := delta;
  Filter^.PostScaling := PostScaling;
  Filter^.Support := Support;
  P := PChar(Filter) + SizeOf(TFilter);
  xmax := delta div 2;
  ymax := delta div 2;
  If HSymmetry then xmin := 0 else xmin := - xmax;
  If VSymmetry then ymin := 0 else ymin := - ymax;
  sum := 0;
  For y := ymin to ymax do
    For x := xmin to xmax do
    begin
      b := Round(FilterFunc(x / PostScaling, y / PostScaling, Info) * 255);
      If b > 255 then b := 255;
      P[(y + ymax) * delta + (x + xmax)] := Chr(b);
      Inc(sum, b);
      If HSymmetry
      then begin
	P[(y + ymax) * delta + (delta - (x + xmax))] := Chr(b);
	Inc(sum, b)
      end;
      If VSymmetry
      then begin
	P[(delta - (y + ymax)) * delta + (x + xmax)] := Chr(b);
	Inc(sum, b);
	If HSymmetry
	then begin
	  P[(delta - (y + ymax)) * delta + (delta - (x + xmax))] := Chr(b);
	  Inc(sum, b)
	end
      end;
    end;
  Filter^.Divisor := Round(Sum / 255)
end;

function ConeFilter(dx, dy: Real; ConeRadius: pointer): Real;
var
  z: Real;
begin
  z := Sqrt(sqr(dx) + sqr(dy));
  if z > Real(ConeRadius^)
  then ConeFilter := 0
  else ConeFilter := 1.0 - z / Real(ConeRadius^);
end;

function BoxFilter(dx, dy: Real; Info: pointer): Real;
begin
  If (abs(dx) > 0.5) or (abs(dy) > 0.5)
  then BoxFilter := 0.0
  else BoxFilter := 1.0
end;
{$endif}

end.
