Friday, October 22, 2010

Class operators

I use this feature in a few types (TRGB, TMatrix and TVector), it really helps cleaning the code as you can use operators on records (note that this feature can only be used in records, not classes, what a pity...)

The available operators are:

  • Add
  • Subtract
  • Negative
  • Equal
  • NotEqual
  • IntDivide
  • Multiply
  • Implicit
  • Explicit
  • LessThan
  • GreaterThan
  • Less than or equal to
  • Greater than or equal to

They can also be overloaded, some implementations:

TRGB = record

   class operator Add(const aColorA, aColorB: TRGB): TRGB;
   class operator Subtract(const aColorA, aColorB: TRGB): TRGB;
   class operator Negative(const aColor: TRGB): TRGB; inline;
   class operator Equal(const aColorA, aColorB: TRGB): boolean; inline;
   class operator NotEqual(const aColorA, aColorB: TRGB): boolean; inline;
   class operator IntDivide(const aColor: TRGB; aFactor: cardinal): TRGB; inline;
   class operator Multiply(const aColorA, aColorB: TRGB): TRGB;
   class operator Multiply(const aColor: TRGB; aValue: cardinal): TRGB;
   //Among other methods and fields
end;

class operator TRGB.Add(const aColorA, aColorB: TRGB): TRGB;
begin
  result.FR := Clamp(aColorA.FR + aColorB.FR);
  result.FG := Clamp(aColorA.FG + aColorB.FG);
  result.FB := Clamp(aColorA.FB + aColorB.FB);
end;

class operator TRGB.IntDivide(const aColor: TRGB; aFactor: cardinal): TRGB;
begin
  result.FR := aColor.FR div aFactor;
  result.FG := aColor.FG div aFactor;
  result.FB := aColor.FB div aFactor;
  result.FA := aColor.FA div aFactor;
end;

class operator TRGB.Multiply(const aColorA, aColorB: TRGB): TRGB;
begin
  result.FR := Trunc((aColorA.FR / Solid) * (aColorB.FR / Solid) * Solid);
  result.FG := Trunc((aColorA.FG / Solid) * (aColorB.FG / Solid) * Solid);
  result.FB := Trunc((aColorA.FB / Solid) * (aColorB.FB / Solid) * Solid);
  result.FA := Trunc((aColorA.FA / Solid) * (aColorB.FA / Solid) * Solid);
end;

class operator TRGB.Equal(const aColorA, aColorB: TRGB): boolean;
begin
  result := (aColorA.FR = aColorB.FR) and (aColorA.FG = aColorB.FG) and (aColorA.FB = aColorB.FB) and (aColorA.FA = aColorB.FA);
end;

class operator TRGB.Multiply(const aColor: TRGB; aValue: cardinal): TRGB;
begin
  result.FR := Clamp(aColor.FR * aValue);
  result.FG := Clamp(aColor.FG * aValue);
  result.FB := Clamp(aColor.FB * aValue);
  result.FA := Clamp(aColor.FA * aValue);
end;

class operator TRGB.Negative(const aColor: TRGB): TRGB;
begin
  result.FR := byte(-aColor.FR);
  result.FG := byte(-aColor.FG);
  result.FB := byte(-aColor.FB);
  result.FA := byte(-aColor.FA);
end;

class operator TRGB.Subtract(const aColorA, aColorB: TRGB): TRGB;
begin
  result.FR := Clamp(aColorA.FR - aColorB.FR);
  result.FG := Clamp(aColorA.FG - aColorB.FG);
  result.FB := Clamp(aColorA.FR - aColorB.FB);
  result.FA := Clamp(aColorA.FA - aColorB.FA);
end;

class operator TRGB.NotEqual(const aColorA, aColorB: TRGB): boolean;
begin
  result := (aColorA.FR <> aColorB.FR) or (aColorA.FG <> aColorB.FG) or 
(aColorA.FB <> aColorB.FB) or (aColorA.FA <> aColorB.FA);
end;
An example:
var
  a, b, c: TRGB;

begin
  a := TRGB.Red;
  b := TRGB.Yellow;
  c := (a + b) div 2; //Add and divide operators

No comments:

Post a Comment