ImageEn, unit iegdiplus

TIECanvas


Declaration

TIECanvas = class;


Description

TIECanvas is a GDI+ Graphics wrapper and VCL TCanvas wrapper.
It is available via TIEBitmap.IECanvas or by creating it from a TBitmap or TCanvas.


Methods and Properties

General
  Brush
  Create
  InterpolationMode
  Pen
  PenPos
  SetCompositingMode
  SmoothingMode

Draw Methods
  Arc
  DrawCurvedLine
  DrawLine
  DrawLinesPath
  Ellipse
  LineTo
  MoveTo
  Pie
  Polygon
  PolygonD
  Polyline
  PolylineD
  Rectangle
  RoundRect

Fill Methods
  FillRect
  GradientFillRect

Text Methods
  DrawText
  Font
  MeasureText
  TextExtent
  TextHeight
  TextWidth
  TextRendering
  TypographicDrawText

Transformation Methods
  ResetTransform
  Rotate
  Translate


Examples

// 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 an anti-aliased ellipse onto a TBitmap
iec := TIECanvas.Create(ABitmap.Canvas, true, true);
with iec do
begin
  Pen.Style := psSolid;
  Pen.Mode := pmCopy;
  Pen.Color := clRed;
  Brush.Style := bsClear
  Ellipse( Rect( 100, 100, 200, 200 ));
end;
iec.Free;


// Fill image with a vertical gradient from Red to Blue
ImageEnView1.IEBitmap.IECanvas.GradientFillRect( Rect( 0, 0, ImageEnView1.IEBitmap.Width, ImageEnView1.IEBitmap.Height ), clRed, clBlue, gpgVertical );
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, true, true);

  iec.Font.Assign( GetTextFont() );
  tw := iec.TextWidth(ss);
  rw := imax( tw + 2 * Horz_Margin, iec.TextWidth(minText) + 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;


// 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( 100, 100, 300, 300 );
iec.Free;


// Draw a rounded, semi-transparent scrollbar (anti-aliased)
const
  RX = 12; // round width
  RY = 12; // round height
  MINSLIDERW = 8; // minimum slider width
var
  scrollPos, scrollCount: integer;
  sliderWidth: double;
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(asliderWidth), y + height - 1, RX, RY);
    end;
end;


// Draw an arrow at the end of a line that runs from x1, y1 to x2, y2
// brush and color must be already set
procedure IEDrawLineArrow(Canvas: TIECanvas; x1, y1, x2, y2: integer; w, h: integer);
const
  A90 = PI / 2;
var
  aa, bb, hw: double;
  pp: array[0..2] of TPoint;
  p1x, p1y: integer;
begin
  with Canvas do
  begin
    hw := w / 2;
    aa := ieangle(x1, y1, x2, y2, x1, y2);
    if x1 = x2 then
      if y1 < y2 then
        aa := -A90
      else
        aa := A90;
    if ((x1 > x2) and (y2 < y1)) or ((x1 < x2) and (y1 < y2)) then
      bb := 2 * pi - aa + A90
    else
      bb := aa + A90;
    if ((x2 < x1) and (y2 > y1)) or ((x2 < x1) and (y2 < y1)) or ((x1 < x2) and (y1 = y2)) then
    begin
      p1x := x1 + trunc(cos(bb - A90) * h);
      p1y := y1 + trunc(sin(bb - A90) * h);
    end
    else
    begin
      p1x := x1 + trunc(cos(bb + A90) * h);
      p1y := y1 + trunc(sin(bb + A90) * h);
    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 := x1;
    pp[2].y := y1;

    Polygon(pp);
  end;
end;


// Draw one of ImageEn's predefined shapes
procedure IEDrawShape(Canvas: TIECanvas;
                      Shape: TIEShape;
                      Left, Top, Width, Height: Integer; MaintainAspect: TIEBooleanEx;
                      BorderColor: TColor; BorderWidth: Integer;
                      FillColor: TColor; FillColor2: TColor = clNone; FillGradient: TIEGDIPlusGradient = gpgVertical;
                      AntiAlias: Boolean = True;
                      Angle: Integer = 0;
                      ShapeModifier: Integer = 0);
var
  arPts : Array[ 0 .. Max_Shape_Array_Points ] of TPoint;
  drawPts : Array[ 0 .. Max_Shape_Array_Points ] of TPoint;
  currX, currY: Integer;
  exWidth, exHeight: Integer;
  i: Integer;
  ptCount: Integer;
begin
  IEGenerateShapePoints( 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 ( FillGradient = gpgNone ) or ( 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;


// Draw an ellipse
procedure IEDrawSimpleShape(Canvas: TIECanvas;
                            Left, Top, Width, Height: Integer;
                            BorderColor: TColor; BorderWidth: Integer;
                            FillColor: TColor; FillColor2: TColor = clNone; FillGradient: TIELayerGradient = grdVertical;
                            ZoomX: Double = 1; ZoomY: Double = 1;
                            AntiAlias: Boolean = True);
const
  Rect_Rounding = 20;
var
  drawGradient: Boolean;
  minZoom: Double;
begin
  drawGradient := ( FillGradient <> grdNone ) and
                  ( FillColor2 <> FillColor ) and
                  ( FillColor <> clNone ) and ( FillColor2 <> clNone );

  if AntiAlias then
    Canvas.SmoothingMode := iesmAntialias
  else
    Canvas.SmoothingMode := iesmBestPerformance;

  // Image has been scaled to zoom level, so ensure we scale the border too
  if BorderColor = clNone then
    BorderWidth := 0;
  if BorderWidth > 0 then
    BorderWidth := max( 1, Round( BorderWidth * minZoom ));

  // 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( TIEGDIPlusGradient( ord( FillGradient ) + 1 ), Width, Height );
    Canvas.Brush.BackTransparency := 255;
    Canvas.Brush.BackColor := FillColor2;
  end;

  Canvas.Ellipse( Left, Top, Left + Width, Top + Height );
end;


// Draw text within a specified area onto 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;