Properties · Methods · Examples
Declaration
TIECanvas = class;
Description
TIECanvas is a wrapper for GDI+ and TCanvas, and supports anti-aliasing, alpha merging, and advanced drawing methods.
It is available via 
TIEBitmap.IECanvas or by creating it from a TBitmap or TCanvas.
 
   
   General
Draw Methods
Fill Methods
Text Methods
Advanced Draw Methods
Transformation Methods
General
Draw Methods
Fill Methods
Text Methods
Advanced Draw Methods
Transformation Methods
// Fill image with a vertical gradient from yellow to red
ImageEnView1.IEBitmap.IECanvas.GradientFillRect( Rect( 0, 0, ImageEnView1.IEBitmap.Width, ImageEnView1.IEBitmap.Height ), clYellow, clRed, gpgVertical );
ImageEnView1.Update();

// Draw an envelope with 50% transparency
with ImageEnView1.IEBitmap.IECanvas do
begin
  Pen.Mode  := pmCopy;
  Pen.Style := psSolid;
  Pen.Color := clBlack;
  Pen.Transparency := 128;
  Brush.Color := clYellow;
  Brush.Style := bsSolid;
  Brush.Transparency := 128;
  // Draw outer rect
  Rectangle( 100, 100, 500, 300 );
  // Draw flap
  MoveTo( 100, 100 );
  LineTo( 300, 200 );
  LineTo( 500, 100 );
end;
ImageEnView1.Update();

// Draw a semi-transparent text box onto a bitmap
const
  Horz_Margin = 8;
  Vert_Margin = 3;
  Center_Text = False;
var
  x, y: integer;
  tw, rw, rh: integer;
  iec: TIECanvas;
  ss: string;
begin
  ss := 'This is my text';
  x := 100;
  y := 100;
  iec := TIECanvas.Create( Bitmap.Canvas );
  iec.Font.Size := 30;
  iec.Font.Style := [fsBold];
  tw := iec.TextWidth(ss);
  rw := imax( tw + 2 * Horz_Margin, iec.TextWidth( ss ) + 2 * Horz_Margin );
  rh := iec.TextHeight(ss) + 2 * Vert_Margin;
  if Center_Text then
    dec( x, rw div 2 );
  iec.Brush.Color := clYellow;
  iec.Brush.Style := bsSolid;
  iec.Brush.Transparency := 196;
  iec.Pen.Color := clBlack;
  iec.Pen.Style := psSolid;
  iec.Rectangle( x, y, x + rw, y + rh );
  iec.Brush.Style := bsClear;
  iec.TextOut(x + ( rw - tw ) div 2, y + Vert_Margin, ss);
  iec.Free;
end;

// Gradient text with border
ImageEnView1.IEBitmap.IECanvas.Font.Size  := 54;
ImageEnView1.IEBitmap.IECanvas.Font.Style := [fsBold];
ImageEnView1.IEBitmap.IECanvas.Font.Color := clRed;
ImageEnView1.IEBitmap.IECanvas.TextStyling.BorderWidth := 3;
ImageEnView1.IEBitmap.IECanvas.TextStyling.BorderColor := clBlack;
ImageEnView1.IEBitmap.IECanvas.TextStyling.FillColor2 := clYellow;
ImageEnView1.IEBitmap.IECanvas.TextStyling.FillGradient := gpgVertical;
ImageEnView1.IEBitmap.IECanvas.DrawText( 'ImageEn!', 280, 200 );
ImageEnView1.Update();

// Highlight an area of a bitmap
iec := TIECanvas.Create( Bitmap.Canvas, false );
iec.Brush.Color := clRed;
iec.Brush.Style := bsSolid;
iec.Brush.Transparency := 125;
iec.FillRect( Rect( 650, 680, 850, 780 ));
iec.Free();

// Draw an anti-aliased ellipse onto a TBitmap
iec := TIECanvas.Create( ABitmap.Canvas );
with iec do
begin
  Pen.Style := psSolid;
  Pen.Width := 3;
  Pen.Mode  := pmCopy;
  Pen.Color := clRed;
  Brush.Style := bsClear;
  Ellipse( Rect( 100, 100, 200, 200 ));
end;
iec.Free();

// Method to draw one of ImageEn's predefined shapes to a canvas
procedure IEDrawShape(Canvas: TIECanvas;
                      Shape: TIEShape;
                      Left, Top, Width, Height: Integer;
                      BorderColor: TColor; BorderWidth: Integer;
                      FillColor: TColor; FillColor2: TColor = clNone; FillGradient: TIEGDIPlusGradient = gpgVertical;
                      AntiAlias: Boolean = True;
                      Angle: Integer = 0;
                      ShapeModifier: Integer = 0);
var
  arPts: TIEDPointArray;
  drawPts: TIEArrayOfTPoint;
  currX, currY: Doulbe;
  exWidth, exHeight: Integer;
  i: Integer;
  ptCount: Integer;
begin
  IEGenerateShapePointsD( arPts, ptCount, Shape, 0, 0, 1000, 1000,
                          Angle, False,
                          ShapeModifier,
                          Width / Height );
  if BorderColor = clNone then
    BorderWidth := 0;
  exWidth  := imax( 0, ( Width - BorderWidth ));
  exHeight := imax( 0, ( Height - BorderWidth ));
  for i := 0 to ptCount - 1 do
  begin
    currX := arPts[ i ].x;
    currY := arPts[ i ].y;
    drawPts[i].x := Left + BorderWidth div 2 + round( currX / 1000 * exWidth );
    drawPts[i].y := Top + BorderWidth div 2 + round( currY / 1000 * exHeight );
  end;
  // PAINT TO CANVAS
  if AntiAlias then
    Canvas.SmoothingMode := iesmAntialias
  else
    Canvas.SmoothingMode := iesmBestPerformance;
  with Canvas do
  begin
    if BorderWidth > 0 then
    begin
      Pen.Style := psSolid;
      Pen.Width := BorderWidth;
      Pen.Color := BorderColor;
    end
    else
      Pen.Style := psClear;
    Pen.Mode  := pmCopy;
    Pen.LineJoin := ieljRound;
    if FillColor = clNone then
      Brush.Style := bsClear
    else
    begin
      Brush.Color := FillColor;
      Brush.Style := bsSolid;
    end;
    if FillColor2 = clNone then
      Brush.SetGradient( gpgNone, 0, 0 )
    else
    begin
      Brush.SetGradient( FillGradient, Width, Height );
      Brush.BackTransparency := 255;
      Brush.BackColor := FillColor2;
    end;
    Polygon( slice( drawpts, ptCount ));
  end;
end;
 
   
   
   
   
   
   
   
   
  
// Method to draw a styled ellipse to a canvas
procedure IEDrawSimpleShape(Canvas: TIECanvas;
                            Left, Top, Width, Height: Integer;
                            BorderColor: TColor; BorderWidth: Integer;
                            FillColor: TColor; FillColor2: TColor = clNone;
                            FillGradient: TIEGDIPlusGradient = gpgVertical;
                            AntiAlias: Boolean = True);
const
  Rect_Rounding = 20;
var
  drawGradient: Boolean;
begin
  drawGradient := ( FillGradient <> gpgNone ) and
                  ( FillColor2 <> FillColor ) and
                  ( FillColor <> clNone ) and ( FillColor2 <> clNone );
  if AntiAlias then
    Canvas.SmoothingMode := iesmAntialias
  else
    Canvas.SmoothingMode := iesmBestPerformance;
  // Border
  if ( BorderColor = clNone ) or ( BorderWidth < 1 ) then
    Canvas.Pen.Style := psClear
  else
    Canvas.Pen.Style := psSolid;
  Canvas.Pen.Color := BorderColor;
  Canvas.Pen.Width := BorderWidth;
  // Fill
  if ( FillColor = clNone ) then
    Canvas.Brush.Style := bsClear
  else
    Canvas.Brush.Style := bsSolid;
  Canvas.Brush.Color := FillColor;
  inc( Left  , BorderWidth div 2 );
  inc( Top   , BorderWidth div 2 );
  dec( Width , BorderWidth );
  dec( Height, BorderWidth );
  if drawGradient = False then
    Canvas.Brush.SetGradient( gpgNone, 0, 0 )
  else
  begin
    Canvas.Brush.SetGradient( FillGradient, Width, Height );
    Canvas.Brush.BackTransparency := 255;
    Canvas.Brush.BackColor := FillColor2;
  end;
  Canvas.Ellipse( Left, Top, Left + Width, Top + Height );
end;

// Method to draw text within an area of a TIEBitmap
procedure TextOutEx(aBMP: TIEBitmap;
                    X, Y, W, H : Integer; const Text : String;
                    const sFontName : String; iFontSize : Integer; cFontColor : TColor; Style : TFontStyles;
                    Angle : Integer = 0;
                    bAntiAlias : Boolean = true; bAutoEnlarge : Boolean = False);
var
  AnExtent: TSize;
  Mask: TIEMask;
  x1, y1, x2, y2: Integer;
  CompCanvas: TIECanvas;
  iAlpha: Integer;
begin
  aBMP.Canvas.Font.Name  := sFontName;
  aBMP.Canvas.Font.Size  := iFontSize;
  aBMP.Canvas.Font.Color := cFontColor;
  aBMP.Canvas.Font.Style := Style;
  AnExtent := aBMP.IECanvas.MeasureText( Text );
  if Angle <> 0 then
    AnExtent := IERotatePoint2( AnExtent.cx, AnExtent.cy, Angle );
  if bAutoEnlarge and (( aBMP.Width < AnExtent.cx ) or ( aBMP.Height < AnExtent.cy )) then
  begin
    iAlpha := 255;
    if aBMP.HasAlphaChannel then
      iAlpha := aBMP.Alpha[0, 0];
    aBMP.Resize( iMax( aBMP.Width, AnExtent.cx ), iMax( aBMP.Height, AnExtent.cy ), Background, iAlpha);
  end;
  CompCanvas := aBMP.CreateROICanvas(Rect(0, 0, aBMP.Width, aBMP.Height), bAntiAlias, true, bAntiAlias);
  try
    if not bAntiAlias then  // Cannot use together with alpha composting
      CompCanvas.TextRendering := ietrTextRenderingHintSingleBitPerPixel;
    CompCanvas.Brush.Color := aBMP.Canvas.Font.Color;
    CompCanvas.Font.Color  := aBMP.Canvas.Font.Color;
    CompCanvas.Font.Name   := aBMP.Canvas.Font.Name;
    CompCanvas.Font.Height := aBMP.Canvas.Font.Height;
    CompCanvas.Font.Style  := aBMP.Canvas.Font.Style;
    if ( W = 0 ) and ( H = 0 ) then
      CompCanvas.DrawText( Text, X, Y, -Angle )
    else
      CompCanvas.DrawText( Text, Rect( X, Y, X + W, Y + H ), -Angle );
  finally
    CompCanvas.Free();
  end;
end;

// Draw a pointer
ImageEnView1.IEBitmap.IECanvas.AdvancedDrawLine( 40, 30, 200, 100,
                                                 clBlack, 2,
                                                 ieesArrow, ieesCircle,
                                                 20, clRed );
ImageEnView1.Update();

// Draw a line pointer with a label
ImageEnView1.IEBitmap.IECanvas.Font.Name  := 'Tahoma';
ImageEnView1.IEBitmap.IECanvas.Font.Size  := 8;
ImageEnView1.IEBitmap.IECanvas.Font.Style := [fsBold];
ImageEnView1.IEBitmap.IECanvas.Font.Color := clBlack;
ImageEnView1.IEBitmap.IECanvas.AdvancedDrawLine( 140, 30, 240, 100,
                                                 clBlack, 2,
                                                 ieesArrow, ieesNone,
                                                 20, clRed,
                                                 ielpAtEnd, 'Labeled Pointer',
                                                 nil, True,
                                                 iesRectangle, clRed, clYellow,
                                                 gpgVertical );
ImageEnView1.Update();

// Draw a filled 5-pointed star
var
  pp: array[0..10] of TPoint;
begin
  ImageEnView1.IEBitmap.IECanvas.Pen.Color := clOrangeRed;
  ImageEnView1.IEBitmap.IECanvas.Pen.Width := 3;
  ImageEnView1.IEBitmap.IECanvas.Brush.Color := clYellow;
  pp[0]  := Point(175, 50);
  pp[1]  := Point(205, 145);
  pp[2]  := Point(300, 145);
  pp[3]  := Point(225, 205);
  pp[4]  := Point(253, 300);
  pp[5]  := Point(175, 243);
  pp[6]  := Point(98 , 300);
  pp[7]  := Point(128, 205);
  pp[8]  := Point(50 , 145);
  pp[9]  := Point(148, 145);
  pp[10] := Point(175, 50);
  ImageEnView1.IEBitmap.IECanvas.Polygon(pp);
  ImageEnView1.Update();
end;

// Draw an arrow shape
ImageEnView1.IEBitmap.IECanvas.AdvancedDrawShape( 50, 50, 150, 150,
                                                  iesShootingArrowSE, 0, 0,          // Shape Props
                                                  clBlack, 2, 1.0,                   // Border Props
                                                  clYellow, clRed, gpgVertical, 1.0, // Fill Props
                                                  True );
ImageEnView1.Update();

// Draw a pink balloon
ImageEnView1.IEBitmap.Allocate( 600, 800, clWhite );
ImageEnView1.IEBitmap.IECanvas.AdvancedDrawShape( 0, 0,
                                                  ImageEnView1.IEBitmap.Width,
                                                  ImageEnView1.IEBitmap.Height,
                                                  iesBalloon, 0, 0,                   // Shape parameters
                                                  clBlack, 2, 1.0,                    // Border parameters
                                                  $00921CF0, clNone, gpgNone, 1.0,    // Fill parameters
                                                  True );
ImageEnView1.Update();

// Draw a cross
var
  pts: array of TPoint;
begin
  SetLength( pts, 12 );
  pts[0] := Point( 50, 0 );
  pts[1] := Point( 100, 50 );
  pts[2] := Point( 150, 0 );
  pts[3] := Point( 200, 50 );
  pts[4] := Point( 150, 100 );
  pts[5] := Point( 200, 150 );
  pts[6] := Point( 150, 200 );
  pts[7] := Point( 100, 150 );
  pts[8] := Point( 50, 200 );
  pts[9] := Point( 0, 150 );
  pts[10] := Point( 50, 100 );
  pts[11] := Point( 0, 50 );
  ImageEnView1.IEBitmap.IECanvas.AdvancedDrawPolyline( pts, True,
                                                       clBlack, 2, 1.0,                       // Line Props
                                                       clYellow, clRed, gpgDiagCenter, 1.0 ); // Fill Props
  ImageEnView1.Update();
end;

// Draw a custom rounded, semi-transparent scrollbar
const
  RX         = 12;  // round width
  RY         = 12;  // round height
  MINSLIDERW = 8;   // minimum slider width
var
  scrollPos, scrollCount: integer;
  sliderWidth: double;
  x, y, Width, Height: Integer;
begin
  x := 100;
  y := 100;
  Width  := 300;
  Height := 16;
  scrollCount := 20;
  scrollPos := 3;
  with ImageEnView1.IEBitmap.IECanvas do
  begin
    // paint brush and border
    Brush.Style := bsSolid;
    Brush.Color := clWhite;
    Brush.Transparency := 64;
    Pen.Color := clWhite;
    Pen.Style := psSolid;
    Pen.Mode := pmCopy;
    Pen.Width := 1;
    Pen.Transparency := 128;
    RoundRect( x, y, x + width, y + height, RX, RY );
    // paint slider
    Brush.Style := bsSolid;
    Brush.Color := clBlack;
    Brush.Transparency := 128;
    Pen.Width := 1;
    Pen.Transparency := 128;
    sliderWidth := width / scrollCount;
    if sliderWidth < MINSLIDERW then
      sliderWidth := MINSLIDERW;
    RoundRect( x + trunc(scrollPos * sliderWidth), y + 1, x + trunc(scrollPos * sliderWidth) + trunc(sliderWidth), y + height - 1, RX, RY);
  end;
  ImageEnView1.Update();
end;

// Method to draw a pointer arrow from LineX1,LineY1 to LineX2, LineY2
// IEDrawLineArrow( ImageEnView1.IEBitmap.IECanvas, 650, 680, 850, 780, 30, 30, clBlack, 2, clYellow );
// ImageEnView1.Update();
procedure IEDrawLineArrow(Canvas: TIECanvas; LineX1, LineY1, LineX2, LineY2: integer; ArrowW, ArrowH: integer;
                          BorderColor: TColor; BorderWidth: Integer; FillColor: TColor);
const
  A90 = PI / 2;
var
  aa, bb, hw: double;
  pp: array[0..2] of TPoint;
  p1x, p1y: integer;
begin
  // Border
  if ( BorderColor = clNone ) or ( BorderWidth < 1 ) then
    Canvas.Pen.Style := psClear
  else
    Canvas.Pen.Style := psSolid;
  Canvas.Pen.Color := BorderColor;
  Canvas.Pen.Width := BorderWidth;
  // Fill
  if ( FillColor = clNone ) then
    Canvas.Brush.Style := bsClear
  else
    Canvas.Brush.Style := bsSolid;
  Canvas.Brush.Color := FillColor;
  Canvas.DrawLine( LineX1, LineY1, LineX2, LineY2 );
  hw := ArrowW / 2;
  aa := IEAngle( LineX1, LineY1, LineX2, LineY2, LineX1, LineY2 );
  if LineX1 = LineX2 then
    if LineY1 < LineY2 then
      aa := -A90
    else
      aa := A90;
  if ((LineX1 > LineX2) and (LineY2 < LineY1)) or ((LineX1 < LineX2) and (LineY1 < LineY2)) then
    bb := 2 * pi - aa + A90
  else
    bb := aa + A90;
  if ((LineX2 < LineX1) and (LineY2 > LineY1)) or ((LineX2 < LineX1) and (LineY2 < LineY1)) or ((LineX1 < LineX2) and (LineY1 = LineY2)) then
  begin
    p1x := LineX1 + trunc(cos(bb - A90) * ArrowH);
    p1y := LineY1 + trunc(sin(bb - A90) * ArrowH);
  end
  else
  begin
    p1x := LineX1 + trunc(cos(bb + A90) * ArrowH);
    p1y := LineY1 + trunc(sin(bb + A90) * ArrowH);
  end;
  pp[0].x := p1x + trunc(cos(bb) * hw);
  pp[0].y := p1y + trunc(sin(bb) * hw);
  pp[1].x := p1x + trunc(cos(bb + pi) * hw);
  pp[1].y := p1y + trunc(sin(bb + pi) * hw);
  pp[2].x := LineX1;
  pp[2].y := LineY1;
  Canvas.Polygon(pp);
end;
