{
 /***************************************************************************
                                  RGBUtils.pas


 ***************************************************************************/

 *****************************************************************************
 *                                                                           *
 *  See the file COPYING.modifiedLGPL, included in this distribution,        *
 *  for details about the copyright.                                         *
 *                                                                           *
 *  This program 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.                     *
 *                                                                           *
 *****************************************************************************

  Author:  Tom Gregorovic (_tom_@centrum.cz)

  Abstract:
}
unit RGBUtils;

{$ifdef fpc}
  {$mode objfpc}{$H+}
{$endif} 

interface

uses
  Classes, SysUtils;
  
type
  TIntArray = array of Integer;
  
  function DivideTrunc(Src, Dest: Integer): TIntArray;
  function GetMidPoints(const A: TIntArray): TIntArray;
  function GetDifference(const A: TIntArray): TIntArray;
  
  procedure SwapInt(var A, B: Integer);
  procedure SwapPtr(var A, B: Pointer);
  procedure MinMax(var A, B: Integer);

  procedure SortRect(var X1, Y1, X2, Y2: Integer); overload;
  procedure SortRect(var R: TRect); overload;
  
  procedure ClipDimension(ClipMin, ClipMax: Integer;
    var DstPos, SrcPos, SrcSize: Integer);

  operator =(A, B: TPoint): Boolean;

implementation

(*
  DivideTrunc divides bigger value of Src and Dest into array of chunks.
  Length(Result) = Min(Src, Dest)
*)
function DivideTrunc(Src, Dest: Integer): TIntArray;
var
  I: Integer;
  VMax, VMin: Integer;
  P, D: Single;
begin
  if Dest > Src then
  begin
    VMax := Dest;
    VMin := Src;
  end
  else
  begin
    VMax := Src;
    VMin := Dest;
  end;
  SetLength(Result, VMin);

  P := 0;
  D := VMax / VMin;
  for I := 0 to High(Result) do
  begin
    Result[I] := Round(P + D) - Round(P);
    P := P + D;
  end;
end;

(*
  GetMidPoints returns array of absolute positions of the middle in each chunk.
*)
function GetMidPoints(const A: TIntArray): TIntArray;
var
  I, P, V: Integer;
begin
  SetLength(Result, Length(A));
  P := 0;
  for I := 0 to High(A) do
  begin
    V := A[I];
    Result[I] := V shr 1 + P;
    Inc(P, V);
  end;
end;

(*
  GetDifference returns array of diffences between positions.
*)
function GetDifference(const A: TIntArray): TIntArray;
var
  I, P: Integer;
begin
  SetLength(Result, Length(A));
  P := 0;
  for I := 0 to High(A) do
  begin
    Result[I] := A[I] - P;
    P := A[I];
  end;
end;

operator =(A, B: TPoint): Boolean;
begin
  Result := (A.X = B.X) and (A.Y = B.Y);
end;

procedure SwapInt(var A, B: Integer);
var
  C: Integer;
begin
  C := A;
  A := B;
  B := C;
end;

procedure SwapPtr(var A, B: Pointer);
var
  C: Pointer;
begin
  C := A;
  A := B;
  B := C;
end;

procedure MinMax(var A, B: Integer);
var
  T: Integer;
begin
  if A > B then
  begin
    T := A;
    A := B;
    B := T;
  end;
end;

procedure SortRect(var X1, Y1, X2, Y2: Integer);
begin
  MinMax(X1, X2);
  MinMax(Y1, Y2);
end;

procedure SortRect(var R: TRect);
begin
  MinMax(R.Left, R.Right);
  MinMax(R.Top, R.Bottom);
end;

procedure ClipDimension(ClipMin, ClipMax: Integer;
    var DstPos, SrcPos, SrcSize: Integer);
var
  C: Integer;
begin
  if ClipMin > DstPos then
  begin
    C := ClipMin - DstPos;
    Inc(SrcPos, C);
    Dec(SrcSize, C);
    DstPos := ClipMin;
  end;
  
  if ClipMax < DstPos + SrcSize then SrcSize := ClipMax - DstPos;
end;
  

end.

