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
Public Property  Brush
Public Property  Create
Public Property  InterpolationMode
Public Property  Pen
Public Property  PenPos
Public Method  SetCompositingMode
Public Method  SetClipRect
Public Property  SmoothingMode

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

Fill Methods
Public Method  FillRect
Public Method  GradientFillRect

Text Methods
Public Method  DrawText
Public Property  Font
Public Method  MeasureText
Public Property  TextStyling
Public Method  TextExtent
Public Method  TextHeight
Public Method  TextWidth
Public Property  TextRendering
Public Property  TypographicDrawText

Transformation Methods
Public Method  ResetTransform
Public Method  Rotate
Public Method  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 );
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 );

  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 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: TIEGDIPlusGradient = gpgVertical;
                            ZoomX: Double = 1; ZoomY: Double = 1;
                            AntiAlias: Boolean = True);
const
  Rect_Rounding = 20;
var
  drawGradient: Boolean;
  minZoom: Double;
begin
  drawGradient := ( FillGradient <> gpgNone ) 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( FillGradient, 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;