{***************************************************************************}
{ GDI+ Fill                                                                 }
{ for Delphi & C++Builder                                                   }
{                                                                           }
{ written by TMS Software                                                   }
{            copyright © 2006 - 2008                                        }
{            Email : info@tmssoftware.com                                   }
{            Web : http://www.tmssoftware.com                               }
{                                                                           }
{ The source code is given as is. The author is not responsible             }
{ for any possible damage done due to the use of this code.                 }
{ The component can be freely used in any application. The complete         }
{ source code remains property of the author and may not be distributed,    }
{ published, given or sold in any form as such. No parts of the source      }
{ code can be included in any other component or application without        }
{ written authorization of the author.                                      }
{***************************************************************************}

unit GDIPFill;

interface

uses
  Windows, Graphics, Classes, AdvSmoothGDIP, SysUtils;

type
  TFillPicturePosition = (ppTopLeft,ppTopCenter,ppTopRight,ppBottomLeft,ppBottomCenter,ppBottomRight,ppTiled,ppStretched,ppCenterLeft,ppCenterCenter,ppCenterRight,ppCustom);

  TFillRoundingType = (rtNone, rtTop, rtBottom, rtBoth);

  TFillPictureSize = (psOriginal, psCustom);

  TGDIPFill = class(TPersistent)
  private
    FBorderColor: TColor;
    FOpacity: Byte;
    FPicturePosition: TFillPicturePosition;
    FGradientType: TAdvGradientType;
    FOpacityTo: Byte;
    FPicture: TAdvGDIPPicture;
    FHatchStyle: THatchStyle;
    FColor: TColor;
    FShadowOffset: integer;
    FOpacityMirror: Byte;
    FGradientMirrorType: TAdvGradientType;
    FOpacityMirrorTo: Byte;
    FRounding: integer;
    FShadowColor: TColor;
    FBorderWidth: integer;
    FColorMirror: TColor;
    FColorMirrorTo: TColor;
    FColorTo: TColor;
    FOnChange: TNotifyEvent;
    FHatchStyleMirror: THatchStyle;
    FPictureTop: integer;
    FPictureLeft: integer;
    FBackGroundPictureTop: integer;
    FBackGroundPictureLeft: integer;
    FBackGroundPicturePosition: TFillPicturePosition;
    FBackGroundPicture: TAdvGDIPPicture;
    FpictureWidth: integer;
    FpictureSize: TFillPictureSize;
    FpictureHeight: integer;
    FRoundingType: TFillRoundingType;
    FUpdateCount: integer;
    FFocus: Boolean;
    FFocusColor: TColor;
    FAngle: integer;
    FBorderOpacity: Byte;
    FFocusRect: TGPRectF;
    procedure SetBorderColor(const Value: TColor);
    procedure SetBorderWidth(const Value: integer);
    procedure SetColor(const Value: TColor);
    procedure SetColorMirror(const Value: TColor);
    procedure SetColorMirrorTo(const Value: TColor);
    procedure SetColorTo(const Value: TColor);
    procedure SetGradientMirrorType(const Value: TAdvGradientType);
    procedure SetGradientType(const Value: TAdvGradientType);
    procedure SetHatchStyle(const Value: THatchStyle);
    procedure SetOpacity(const Value: Byte);
    procedure SetOpacityMirror(const Value: Byte);
    procedure SetOpacityMirrorTo(const Value: Byte);
    procedure SetOpacityTo(const Value: Byte);
    procedure SetPicture(const Value: TAdvGDIPPicture);
    procedure SetPicturePosition(const Value: TFillPicturePosition);
    procedure SetRounding(const Value: integer);
    procedure SetShadowColor(const Value: TColor);
    procedure SetShadowOffset(const Value: integer);
    procedure SetHatchStyleMirror(const Value: THatchStyle);
    procedure SetPictureLeft(const Value: integer);
    procedure SetPictureTop(const Value: integer);
    procedure SetBackGroundPicture(const Value: TAdvGDIPPicture);
    procedure SetBackGroundPictureLeft(const Value: integer);
    procedure SetBackGroundPicturePosition(const Value: TFillPicturePosition);
    procedure SetBackGroundPictureTop(const Value: integer);
    procedure SetPictureHeight(const Value: integer);
    procedure SetPictureSize(const Value: TFillPictureSize);
    procedure SetPictureWidth(const Value: integer);
    procedure SetRoundingType(const Value: TFillRoundingType);
    procedure SetFocus(const Value: Boolean);
    procedure SetFocusColor(const Value: TColor);
    procedure SetAngle(const Value: integer);
    procedure SetBorderOpacity(const Value: Byte);
  protected
    procedure Changed;
    procedure PictureChanged(Sender: TObject);
    procedure DrawGradientBackGround(Graphics: TGPGraphics; R: TGPRectF; Mirror: Boolean; oc, octo, ocmr, ocmrto: Byte);
  public
    constructor Create;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    function Fill(Graphics: TGPGraphics; R: TGPRectF; ABorderOpacity: Byte = 255; AOpacity: Byte = 255; AOpacityTo: Byte = 255; AOpacityMirror: Byte = 255; AOpacityMirrorTo: Byte = 255): TGPRectF;
    procedure BeginUpdate;
    procedure EndUpdate;
    property Focus: Boolean read FFocus write SetFocus default false;
    property FocusColor: TColor read FFocusColor write SetFocusColor default clBlack;
    property FocusRect: TGPRectF read FFocusRect write FFocusRect;
  published
    property Color: TColor read FColor write SetColor default clSilver;
    property ColorTo: TColor read FColorTo write SetColorTo default clGray;
    property ColorMirror: TColor read FColorMirror write SetColorMirror default clNone;
    property ColorMirrorTo: TColor read FColorMirrorTo write SetColorMirrorTo default clNone;
    property GradientType: TAdvGradientType read FGradientType write SetGradientType default gtVertical;
    property GradientMirrorType: TAdvGradientType read FGradientMirrorType write SetGradientMirrorType default gtSolid;
    property HatchStyle: THatchStyle read FHatchStyle write SetHatchStyle default HatchStyleHorizontal;
    property HatchStyleMirror: THatchStyle read FHatchStyleMirror write SetHatchStyleMirror default HatchStyleHorizontal;
    property BackGroundPicture: TAdvGDIPPicture read FBackGroundPicture write SetBackGroundPicture;
    property BackGroundPicturePosition: TFillPicturePosition read FBackGroundPicturePosition write SetBackGroundPicturePosition default ppTopLeft;
    property BackGroundPictureLeft: integer read FBackGroundPictureLeft write SetBackGroundPictureLeft default 0;
    property BackGroundPictureTop: integer read FBackGroundPictureTop write SetBackGroundPictureTop default 0;
    property Picture: TAdvGDIPPicture read FPicture write SetPicture;
    property PicturePosition: TFillPicturePosition read FPicturePosition write SetPicturePosition default ppTopLeft;
    property PictureLeft: integer read FPictureLeft write SetPictureLeft default 0;
    property PictureTop: integer read FPictureTop write SetPictureTop default 0;
    property PictureSize: TFillPictureSize read FpictureSize write SetPictureSize default psOriginal;
    property PictureWidth: integer read FpictureWidth write SetPictureWidth default 50;
    property PictureHeight: integer read FpictureHeight write SetPictureHeight default 50;
    property Opacity: Byte read FOpacity write SetOpacity default 255;
    property OpacityTo: Byte read FOpacityTo write SetOpacityTo default 255;
    property OpacityMirror: Byte read FOpacityMirror write SetOpacityMirror default 255;
    property OpacityMirrorTo: Byte read FOpacityMirrorTo write SetOpacityMirrorTo default 255;
    property BorderColor: TColor read FBorderColor write SetBorderColor default clNone;
    property BorderOpacity: Byte read FBorderOpacity write SetBorderOpacity default 255;
    property BorderWidth: integer read FBorderWidth write SetBorderWidth default 1;
    property Rounding: integer read FRounding write SetRounding default 0;
    property RoundingType: TFillRoundingType read FRoundingType write SetRoundingType default rtBoth;
    property ShadowColor: TColor read FShadowColor write SetShadowColor default clGray;
    property ShadowOffset: integer read FShadowOffset write SetShadowOffset default 0;
    property Angle: integer read FAngle write SetAngle default 0;
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;

implementation

function CreateRoundRectangle(R: TGPRectF; Radius: Integer; RoundingType: TFillRoundingType; Mirror: Boolean): TGPGraphicsPath;
var
  l, t, w, h, d: Double;
begin
  Result := TGPGraphicsPath.Create;
  l := R.X;
  t := R.Y;
  w := R.Width;
  h := R.Height;
  d := Radius shl 1;
  case RoundingType of
    rtNone:
    begin
      Result.AddLine(l, t, l + w, t); // top
      Result.AddLine(l + w, t, l + w, t + h); // right
      Result.AddLine(l + w, t + h, l, t + h); // bottom
      Result.AddLine(l, t + h, l, t); // left
    end;
    rtTop:
    begin
      Result.AddArc(l, t, d, d, 180, 90); // topleft
      Result.AddLine(l + radius, t, l + w - radius, t); // top
      Result.AddArc(l + w - d, t, d, d, 270, 90); // topright
      Result.AddLine(l + w, t + radius, l + w, t + h); // right
      Result.AddLine(l + w, t + h, l, t + h); // bottom
      Result.AddLine(l, t + h, l, t + Radius); // left
    end;
    rtBottom:
    begin
      Result.AddLine(l, t, l + w, t); // top
      Result.AddLine(l + w, t, l + w, t + h - radius); // right
      Result.AddArc(l + w - d, t + h - d, d, d, 0, 90); // bottomright
      Result.AddLine(l + w - radius, t + h, l + radius, t + h); // bottom
      Result.AddArc(l, t + h - d, d, d, 90, 90); // bottomleft
      Result.AddLine(l, t + h - Radius, l, t ); // left
    end;
    rtBoth:
    begin
      Result.AddArc(l, t, d, d, 180, 90); // topleft
      Result.AddLine(l + radius, t, l + w - radius, t); // top
      Result.AddArc(l + w - d, t, d, d, 270, 90); // topright
      Result.AddLine(l + w, t + radius, l + w, t + h - radius); // right
      Result.AddArc(l + w - d, t + h - d, d, d, 0, 90); // bottomright
      Result.AddLine(l + w - radius, t + h, l + radius, t + h); // bottom
      Result.AddArc(l, t + h - d, d, d, 90, 90); // bottomleft
      Result.AddLine(l, t + h - radius, l, t + radius); // left
    end;
  end;
  Result.CloseFigure();
end;

procedure TGDIPFill.DrawGradientBackGround(Graphics: TGPGraphics; R: TGPRectF; Mirror: Boolean; oc, octo, ocmr, ocmrto: Byte);
var
  path: TGPGraphicsPath;
  par: TGDIPFillParameters;
  gt: TAdvGradientType;
  c, ct: TColor;
  o, ot: Byte;
  ht: THatchStyle;
  smt: TSmoothingMode;
begin
  path := nil;

  if Mirror then
  begin
    gt := FGradientMirrorType;
    c := FColorMirror;
    ct := FColorMirrorTo;
    o := ocmr;
    ot := ocmrto;
    ht := HatchStyleMirror;
  end
  else
  begin
    gt := FGradientType;
    c := FColor;
    ct := FColorTo;
    o := oc;
    ot := octo;
    ht := HatchStyle;
  end;

  if c = clNone then
    gt := gtNone;

  if (ct = clNone) and (c <> clNone) then
    gt := gtSolid;

  par.Graphics := Graphics;

  if Rounding = 0 then
  begin
    par.Path := nil;
    par.Fillpath := false;
  end
  else
  begin
    if (FColorMirror <> clNone) then
    begin
      if Mirror then
      begin
        case RoundingType of
          rtNone: path := CreateRoundRectangle(r, Rounding, rtNone, Mirror);
          rtTop: path := CreateRoundRectangle(r, Rounding, rtNone, Mirror);
          rtBoth, rtBottom: path := CreateRoundRectangle(r, Rounding, rtBottom, Mirror);
        end;
      end
      else
      begin
        case RoundingType of
          rtNone: path := CreateRoundRectangle(r, Rounding, rtNone, Mirror);
          rtBoth, rtTop: path := CreateRoundRectangle(r, Rounding, rtTop, Mirror);
          rtBottom: path := CreateRoundRectangle(r, Rounding, rtNone, Mirror);
        end;
      end;
    end
    else
      path := CreateRoundRectangle(r, Rounding, RoundingType, Mirror);

    par.Path := path;
    par.Fillpath := true;
  end;

  par.R := r;
  par.GT := gt;
  par.Angle := FAngle;
  par.ColorFrom := c;
  par.ColorTo := ct;
  par.OpacityFrom := o;
  par.OpacityTo := ot;
  par.HatchStyle := ht;
  par.BorderColor := clNone;
  par.BorderWidth := 0;
  par.BorderStyle := DashStyleSolid;
  par.Mirror := Mirror;

  if (FBackGroundPicturePosition = ppTiled) then
    par.Image := FBackGroundPicture
  else
    par.Image := nil;

  par.Angle := 0;

  smt := Graphics.GetSmoothingMode;

  if par.Fillpath then
    Graphics.SetSmoothingMode(SmoothingModeAntiAlias);

  FillGDIP(par);

  if par.Fillpath then
    Graphics.SetSmoothingMode(smt);

  if path <> nil then
    path.Free;
end;

procedure TGDIPFill.EndUpdate;
begin
  if (FUpdateCount > 0) then
  begin
    dec(FUpdateCount);
  end;
end;

procedure DrawRadialBackGround(Graphics: TGPGraphics; R: TGPRectF; CF,CT: TColor; o, ot: Byte; Upper: boolean);
var
  path: TGPGraphicsPath;
  pthGrBrush: TGPPathGradientBrush;
  solGrBrush: TGPSolidBrush;

  w,h,w2,h2: Double;
  colors : array[0..0] of TGPColor;
  count: Integer;

begin
  w := r.Width;
  h := r.Height;

  h2 := h / 2;
  w2 := w / 2;

  if Upper then
    solGrBrush := TGPSolidBrush.Create(MakeColor(o, CF))
  else
    solGrBrush := TGPSolidBrush.Create(MakeColor(ot, CT));

  Graphics.FillRectangle(solGrBrush, r);

  solGrBrush.Free;


  // Create a path that consists of a single ellipse.
  path := TGPGraphicsPath.Create;

  if Upper then        // take borders in account
    path.AddEllipse(r.X, r.Y - h2, r.Width , r.Height + h2)
  else
    path.AddEllipse(r.X, r.Y, r.Width , r.Height + h2);

  pthGrBrush := TGPPathGradientBrush.Create(path);


  if Upper then
    pthGrBrush.SetCenterPoint(MakePoint(r.X + w2, r.Y))
  else
    pthGrBrush.SetCenterPoint(MakePoint(r.X + w2, r.Y + R.Height));

  // Set the color at the center point to blue.
  if Upper then
  begin
    pthGrBrush.SetCenterColor(MakeColor(ot, CT));
    colors[0] := MakeColor(o, CF);
  end
  else
  begin
    pthGrBrush.SetCenterColor(MakeColor(o, CF));
    colors[0] := MakeColor(ot, CT);
  end;

  count := 1;
  pthGrBrush.SetSurroundColors(@colors, count);
  graphics.FillRectangle(pthGrBrush, r);
  pthGrBrush.Free;

  path.Free;
end;

procedure DrawPicture(g: TGPGraphics; picture: TAdvGDIPPicture; location: TFillPicturePosition; w, h: integer; r: TRect; x, y: integer);
begin
  if not picture.Empty then
  begin
    case location of
    ppTopLeft: picture.GDIPDraw(g, Rect(r.Left,r.Top,r.Left + w, r.Top + h));
    ppTopCenter:
    begin
      r.Left := r.Left + ((r.Right - r.Left) - w) div 2;
      picture.GDIPDraw(g, Rect(r.Left,r.Top,r.Left + w, r.Top + h));
    end;
    ppTopRight: picture.GDIPDraw(g, Rect(r.Right - w, r.Top, r.Right, r.Top + h));
    ppBottomLeft: picture.GDIPDraw(g, Rect(r.Left, r.Bottom - h, r.Left + w, r.Bottom));
    ppBottomCenter:
    begin
      r.Left := r.Left + ((r.Right - r.Left) - w) div 2;
      picture.GDIPDraw(g, Rect(r.Left, r.Bottom - h, r.Left + w, r.Bottom));
    end;
    ppBottomRight: picture.GDIPDraw(g, Rect(r.Right - w, r.Bottom - h, r.Right, r.Bottom));
    ppStretched: picture.GDIPDraw(g, Rect(r.Left,r.Top,r.Right, r.Bottom));
    ppCustom: picture.GDIPDraw(g, Bounds(x, y, w, h));
    ppCenterLeft:
      begin
        r.Top := r.Top + ((r.Bottom - r.Top) - h) div 2;
        picture.GDIPDraw(g, Rect(r.Left,r.Top,r.Left + w, r.Top + h));
      end;
    ppCenterRight:
      begin
        r.Top := r.Top + ((r.Bottom - r.Top) - h) div 2;
        picture.GDIPDraw(g, Rect(r.Right - w,r.Top,r.Right, r.Top + h));
      end;
    ppCenterCenter:
      begin
        r.Left := r.Left + ((r.Right - r.Left) - w) div 2;
        r.Top := r.Top + ((r.Bottom - r.Top) - h) div 2;
        picture.GDIPDraw(g, Rect(r.Left,r.Top,r.Left + w, r.Top + h));
      end;
    end;
  end;
end;

function TGDIPFill.Fill(Graphics: TGPGraphics; R: TGPRectF; ABorderOpacity: Byte = 255; AOpacity: Byte = 255; AOpacityTo: Byte = 255; AOpacityMirror: Byte = 255; AOpacityMirrorTo: Byte = 255): TGPRectF;
var
  path, pathshadow, pathfocus, pathborder: TGPGraphicsPath;
  rnonmirror, rmirror: TGPRectF;
  gBrush: TGPPathGradientBrush;
  cb: array[0..2] of TGPColor;
  pb: array[0..2] of single;
  h, h2: Double;
  c, ct: integer;
  pw, ph: integer;
  ocbdr, oc, octo, ocmr, ocmrto: Byte;
  pfocus, pBorder: TGPPen;
  rc: TRect;
begin
  if AOpacity < 255 then
    oc := AOpacity
  else
    oc := Opacity;

  if AOpacityTo < 255 then
    octo := AOpacityTo
  else
    octo := OpacityTo;

  if AOpacityMirror < 255 then
    ocmr := AOpacityMirror
  else
    ocmr := OpacityMirror;

  if AOpacityMirrorTo < 255 then
    ocmrto := AOpacityMirrorTo
  else
    ocmrto := OpacityMirrorTo;

  if ABorderOpacity < 255 then
    ocbdr := ABorderOpacity
  else
    ocbdr := BorderOpacity;

  if (R.Height <> 1) and (R.Width <> 1) then
  begin
    if Graphics = nil then
      Exit;

    path := nil;

    if (ShadowOffset > 0) and (ShadowColor <> clNone) then
    begin
      pathshadow := CreateRoundRectangle(r, Rounding, RoundingType, true);
      gBrush := TGPPathGradientBrush.Create(pathshadow);
      gBrush.SetWrapMode(WrapModeClamp);

      cb[0] := MakeColor(0,0,0,0);
      cb[1] := MakeColor(180, ShadowColor);
      cb[2] := MakeColor(180, ShadowColor);

      pb[0] := 0;
      pb[1] := 0.1;
      pb[2] := 1;

      gBrush.SetInterpolationColors(@cb, @pb, 3);

      Graphics.FillPath(gbrush, pathshadow);
      pathshadow.Free;
      gBrush.Free;

      R.Width := R.Width - ShadowOffset;
      R.Height := R.Height - ShadowOffset;
    end;

    if (FGradientType <> gtHatch) and (FGradientType <> gtTexture) and (ColorMirror <> clNone) then
    begin
      h := r.Height;

      h2 := h / 2;

      rnonmirror := MakeRect(r.X, R.Y, R.Width, R.Height - h2 + 1);

      //rnonmirror := MakeRect(r.X, R.Y, R.Width, h2);
      if FGradientType = gtRadial then
      begin
        if Color <> clNone then
        begin
          c := Color;
          ct := ColorTo;
          if ColorTo = clNone then
          begin
            ct := c;
          end;
          DrawRadialBackGround(Graphics, rnonmirror, c, ct, oc, octo, true)
        end
      end
      else
        DrawGradientBackGround(Graphics, rnonmirror, false, oc, octo, ocmr, ocmrto);


      rmirror := MakeRect(r.X, r.Y + h2 - 1, r.Width, r.Height - h2 + 1);

      //rmirror := MakeRect(r.X, r.Y + h2 , r.Width, h2);

      if GradientMirrorType = gtRadial then
      begin
        if ColorMirror <> clNone then
        begin
          c := ColorMirror;
          ct := ColorMirrorTo;
          if ColorMirrorTo = clNone then
          begin
            ct := c;
          end;
          DrawRadialBackGround(Graphics, rmirror, c, ct, ocmr, ocmrto, false)
        end;
      end
      else
        DrawGradientBackGround(Graphics, rmirror, true, oc, octo, ocmr, ocmrto);
    end
    else
    begin
      DrawGradientBackGround(Graphics, r, false, oc, octo, ocmr, ocmrto);
    end;

    if path <> nil then
      path.Free;


    if (BorderWidth > 0) and (BorderColor <> clNone) then
    begin
      pathborder := CreateRoundRectangle(r, Rounding, RoundingType, false);
      pBorder := TGPPen.Create(MakeColor(ocbdr, BorderColor), BorderWidth);
      pBorder.SetDashStyle(DashStyleSolid);
      Graphics.DrawPath(pBorder, pathborder);
      pBorder.Free;
      pathborder.Free;
    end;
  end
  else
  begin
    if (BorderWidth > 0) and (BorderColor <> clNone) then
    begin
      pBorder := TGPPen.Create(MakeColor(ocbdr, BorderColor), BorderWidth);
      Graphics.DrawLine(pBorder, r.X, r.Y, r.X + R.Width, r.Y + R.Height);
      pBorder.Free;
    end;
  end;

  FFocusRect := MakeRect(R.X + BorderWidth, R.Y + BorderWidth, R.Width - (BorderWidth * 2), R.Height - (BorderWidth * 2));  
  if focus then
  begin
    pathfocus := CreateRoundRectangle(FFocusRect, Rounding - BorderWidth, RoundingType, false);
    graphics.SetSmoothingMode(SmoothingModeDefault);
    pfocus := TGPPen.Create(MakeColor(oc, focuscolor), 1);
    pfocus.SetDashStyle(DashStyleDot);
    Graphics.DrawPath(pfocus, pathfocus);
    pfocus.Free;
    pathfocus.Free;
  end;

  pw := 0;
  ph := 0;
  if not BackGroundPicture.Empty then
  begin
    BackGroundPicture.GetImageSizes;
    pw := BackGroundPicture.Width;
    ph := BackGroundPicture.Height;
  end;


  rc := Bounds(Round(r.X), Round(r.Y), Round(r.Width), Round(r.Height));  

  if (FGradientType = gtTexture) then
  begin
    if BackGroundPicturePosition <> ppCustom then
      DrawPicture(Graphics, BackGroundPicture, FBackGroundPicturePosition, pw, ph, rc,  rc.Left, rc.Top)
    else
      DrawPicture(Graphics, BackGroundPicture, FBackGroundPicturePosition, pw, ph, rc,  BackGroundPictureLeft, BackGroundPictureTop);
  end;

  pw := 0;
  ph := 0;
  if not picture.Empty then
  begin
    picture.GetImageSizes;
    case FPictureSize of
      psOriginal:
      begin
        pw := Picture.Width;
        ph := Picture.Height;
      end;
      psCustom:
      begin
        pw := FPictureWidth;
        ph := FPictureHeight;
      end;
    end;
  end;

  if FPicturePosition <> ppCustom then
    DrawPicture(Graphics, Picture, FPicturePosition, pw, ph,  rc,  rc.Left, rc.Top)
  else
    DrawPicture(Graphics, Picture, FPicturePosition, pw, ph, rc,  PictureLeft, PictureTop);

  Result := R;
end;


procedure TGDIPFill.PictureChanged(Sender: TObject);
begin
  Changed;
end;

{ TGDIPFill }


procedure TGDIPFill.Assign(Source: TPersistent);
begin
  Color := (Source as TGDIPFill).Color;
  ColorTo := (Source as TGDIPFill).ColorTo;
  ColorMirror := (Source as TGDIPFill).ColorMirror;
  ColorMirrorTo := (Source as TGDIPFill).ColorMirrorTo;
  GradientType := (Source as TGDIPFill).GradientType;
  GradientMirrorType := (Source as TGDIPFill).GradientMirrorType;
  HatchStyle := (Source as TGDIPFill).HatchStyle;
  HatchStyleMirror := (Source as TGDIPFill).HatchStyleMirror;
  BackGroundPicture.Assign((Source as TGDIPFill).BackGroundPicture);
  BackGroundPicturePosition := (Source as TGDIPFill).BackGroundPicturePosition;
  BackGroundPictureLeft := (Source as TGDIPFill).BackGroundPictureLeft;
  BackGroundPictureTop := (Source as TGDIPFill).BackGroundPictureTop;
  Picture.Assign((Source as TGDIPFill).Picture);
  PicturePosition := (Source as TGDIPFill).PicturePosition;
  PictureLeft := (Source as TGDIPFill).PictureLeft;
  PictureTop := (Source as TGDIPFill).PictureTop;
  PictureSize := (Source as TGDIPFill).PictureSize;
  PictureWidth := (Source as TGDIPFill).PictureWidth;
  PictureHeight := (Source as TGDIPFill).PictureHeight;
  Opacity := (Source as TGDIPFill).Opacity;
  OpacityTo := (Source as TGDIPFill).OpacityTo;
  OpacityMirror := (Source as TGDIPFill).OpacityMirror;
  OpacityMirrorTo := (Source as TGDIPFill).OpacityMirrorTo;
  BorderColor := (Source as TGDIPFill).BorderColor;
  BorderWidth := (Source as TGDIPFill).BorderWidth;
  Rounding := (Source as TGDIPFill).Rounding;
  RoundingType := (Source as TGDIPFill).RoundingType;
  ShadowColor := (Source as TGDIPFill).ShadowColor;
  ShadowOffset := (Source as TGDIPFill).ShadowOffset;
  Angle := (Source as TGDIPFill).Angle;
  BorderOpacity := (Source as TGDIPFill).BorderOpacity;
end;

procedure TGDIPFill.BeginUpdate;
begin
  inc(FUpdateCount);
end;

procedure TGDIPFill.Changed;
begin
  if Assigned(FOnChange) and (FUpdateCount = 0) then
    FOnChange(Self);
end;

constructor TGDIPFill.Create;
begin
  FUpdateCount := 0;
  FBorderOpacity := 255;
  FAngle := 0;
  FFocus := false;
  FFocusColor := clBlack;
  FPictureSize := psOriginal;
  FPictureWidth := 50;
  FPictureHeight := 50;
  FBackGroundPictureTop := 0;
  FBackGroundPictureLeft := 0;
  FBackGroundPicturePosition := ppTopLeft;
  FBackGroundPicture := TAdvGDIPPicture.Create;
  FBackGroundPicture.OnChange := PictureChanged;
  FPictureTop := 0;
  FPictureLeft := 0;
  FColor := clSilver;
  FColorTo := clGray;
  FColorMirror := clNone;
  FColorMirrorTo := clNone;
  FGradientType := gtVertical;
  FGradientMirrorType := gtSolid;
  FHatchStyle := HatchStyleHorizontal;
  FPicture := TAdvGDIPPicture.Create;
  FPicture.OnChange := PictureChanged;
  FPicturePosition := ppTopLeft;
  FOpacity := 255;
  FOpacityTo := 255;
  FOpacityMirror := 255;
  FOpacityMirrorTo := 255;
  FBorderColor := clNone;
  FBorderWidth := 1;
  FRounding := 0;
  FRoundingType := rtBoth;
  FShadowColor := clGray;
  FShadowOffset := 0;
end;

destructor TGDIPFill.Destroy;
begin
  Picture.Free;
  BackGroundPicture.Free;
  inherited;
end;

procedure TGDIPFill.SetAngle(const Value: integer);
begin
  if FAngle <> value then
  begin
    FAngle := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetBackGroundPicture(const Value: TAdvGDIPPicture);
begin
  if FBackGroundPicture <> value then
  begin
    FBackGroundPicture.Assign(value);
    Changed;
  end;
end;

procedure TGDIPFill.SetBackGroundPictureLeft(const Value: integer);
begin
  if FBackGroundPictureLeft <> value then
  begin
    FBackGroundPictureLeft := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetBackGroundPicturePosition(const Value: TFillPicturePosition);
begin
  if FBackGroundPicturePosition <> value then
  begin
    FBackGroundPicturePosition := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetBackGroundPictureTop(const Value: integer);
begin
  if FBackGroundPictureTop <> value then
  begin
    FBackGroundPictureTop := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetBorderColor(const Value: TColor);
begin
  if FBorderColor <> value then
  begin
    FBorderColor := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetBorderOpacity(const Value: Byte);
begin
  if FBorderOpacity <> value then
  begin
    FBorderOpacity := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetBorderWidth(const Value: integer);
begin
  if FBorderWidth <> value then
  begin
    FBorderWidth := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetColor(const Value: TColor);
begin
  if FColor <> value then
  begin
    FColor := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetColorMirror(const Value: TColor);
begin
  if FColorMirror <> value then
  begin
    FColorMirror := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetColorMirrorTo(const Value: TColor);
begin
  if FColorMirrorTo <> value then
  begin
    FColorMirrorTo := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetColorTo(const Value: TColor);
begin
  if FColorTo <> value then
  begin
    FColorTo := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetFocus(const Value: Boolean);
begin
  if FFocus <> value then
  begin
    FFocus := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetFocusColor(const Value: TColor);
begin
  if FFocusColor <> value then
  begin
    FFocusColor := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetGradientMirrorType(const Value: TAdvGradientType);
begin
  if FGradientMirrorType <> value then
  begin
    FGradientMirrorType := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetGradientType(const Value: TAdvGradientType);
begin
  if FGradientType <> value then
  begin
    FGradientType := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetHatchStyle(const Value: THatchStyle);
begin
  if FHatchStyle <> value then
  begin
    FHatchStyle := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetHatchStyleMirror(const Value: THatchStyle);
begin
  if FHatchStyleMirror <> value then
  begin
    FHatchStyleMirror := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetOpacity(const Value: Byte);
begin
  if FOpacity <> value then
  begin
    FOpacity := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetOpacityMirror(const Value: Byte);
begin
  if FOpacityMirror <> value then
  begin
    FOpacityMirror := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetOpacityMirrorTo(const Value: Byte);
begin
  if FOpacityMirrorTo <> value then
  begin
    FOpacityMirrorTo := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetOpacityTo(const Value: Byte);
begin
  if FOpacityTo <> value then
  begin
    FOpacityTo := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetPicture(const Value: TAdvGDIPPicture);
begin
  if FPicture <> value then
  begin
    FPicture.Assign(value);
    PictureChanged(Self);
  end;
end;

procedure TGDIPFill.SetPictureHeight(const Value: integer);
begin
  if FpictureHeight <> value then
  begin
    FpictureHeight := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetPictureLeft(const Value: integer);
begin
  if FPictureLeft <> value then
  begin
    FPictureLeft := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetPicturePosition(const Value: TFillPicturePosition);
begin
  if FPicturePosition <> value then
  begin
    FPicturePosition := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetPictureSize(const Value: TFillPictureSize);
begin
  if FpictureSize <> value then
  begin
    FpictureSize := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetPictureTop(const Value: integer);
begin
  if FPictureTop <> value then
  begin
    FPictureTop := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetPictureWidth(const Value: integer);
begin
  if FpictureWidth <> value then
  begin
    FpictureWidth := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetRounding(const Value: integer);
begin
  if FRounding <> value then
  begin
    FRounding := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetRoundingType(const Value: TFillRoundingType);
begin
  if FRoundingType <> value then
  begin
    FRoundingType := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetShadowColor(const Value: TColor);
begin
  if FShadowColor <> value then
  begin
    FShadowColor := Value;
    Changed;
  end;
end;

procedure TGDIPFill.SetShadowOffset(const Value: integer);
begin
  if FShadowOffset <> value then
  begin
    FShadowOffset := Value;
    Changed;    
  end;
end;

end.
