delphifiremonkey

How to draw a smile emoji on a TPaintBox component in Delphi FMX?


I have a TPaintBox component on my form and I want to draw a smile emoji on it and I don't know how to draw this.

I have been able to draw lines and circles but it does not look accurately like actual smile emoji. does anyone have code to properly draw a smile emoji?

This is what i have now:

procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var
  DrawRect, faceRect, eyeRectL, eyeRectR: TRectF;
  s, radius, lineW, eyeR, eyeOffsetX, eyeOffsetY: Single;
  c: TPointF;
  FaceColor, EyeColor, LineColor: TAlphaColor;
  WithOutline: Boolean;
begin
  DrawRect := PaintBox1.LocalRect;
  DrawRect.Inflate(-8, -8);

  if (Canvas = nil) or (DrawRect.Width <= 0) or (DrawRect.Height <= 0) then
    Exit;

  // Settings
  FaceColor   := $FFFFCC4D;  // Emoji yellow
  EyeColor    := $FF000000;  // Black
  LineColor   := $FF7A5200;  // Warm brown outline
  WithOutline := True;

  // Scale & center
  s := Min(DrawRect.Width, DrawRect.Height);
  c := PointF(
    DrawRect.Left + s * 0.5 + (DrawRect.Width - s) * 0.5,
    DrawRect.Top  + s * 0.5 + (DrawRect.Height - s) * 0.5
  );
  radius := 0.5 * s;

  // Face
  faceRect := RectF(
    c.X - radius, c.Y - radius,
    c.X + radius, c.Y + radius
  );

  Canvas.Fill.Kind  := TBrushKind.Solid;
  Canvas.Fill.Color := FaceColor;
  Canvas.FillEllipse(faceRect, 1);

  // Optional outline
  if WithOutline then
  begin
    lineW := Max(1.0, s * 0.04);
    Canvas.Stroke.Kind      := TBrushKind.Solid;
    Canvas.Stroke.Color     := LineColor;
    Canvas.Stroke.Thickness := lineW;
    Canvas.Stroke.Cap       := TStrokeCap.Round;
    Canvas.Stroke.Join      := TStrokeJoin.Round;
    Canvas.DrawEllipse(faceRect, 1);
  end;

  // Eyes only (no mouth)
  eyeR       := s * 0.08;
  eyeOffsetX := s * 0.20;
  eyeOffsetY := -s * 0.10;

  eyeRectL := RectF(
    c.X - eyeOffsetX - eyeR, c.Y + eyeOffsetY - eyeR,
    c.X - eyeOffsetX + eyeR, c.Y + eyeOffsetY + eyeR
  );

  eyeRectR := RectF(
    c.X + eyeOffsetX - eyeR, c.Y + eyeOffsetY - eyeR,
    c.X + eyeOffsetX + eyeR, c.Y + eyeOffsetY + eyeR
  );

  Canvas.Fill.Color := EyeColor;
  Canvas.FillEllipse(eyeRectL, 1);
  Canvas.FillEllipse(eyeRectR, 1);
end;

Solution

  • If you add the following to the end of your code, then you'll get the smile:

      // Mouth (smile)
      var mouthW, mouthH, mouthOffsetY, mouthLineW: Single;
      var mouthRect: TRectF;
    
      mouthW := s * 0.5;
      mouthH := s * 0.28;
      mouthOffsetY := s * 0.18;
      
      mouthRect := RectF(
        c.X - mouthW * 0.5, c.Y + mouthOffsetY - mouthH * 0.5,
        c.X + mouthW * 0.5, c.Y + mouthOffsetY + mouthH * 0.5
      );
    
      mouthLineW := Max(1.0, s * 0.04);
      Canvas.Stroke.Kind      := TBrushKind.Solid;
      Canvas.Stroke.Color     := EyeColor;
      Canvas.Stroke.Thickness := mouthLineW;
      Canvas.Stroke.Cap       := TStrokeCap.Round;
      Canvas.Stroke.Join      := TStrokeJoin.Round;
    
      var points: TArray<TPointF>;
      var i, segments: Integer;
      var startAngleDeg, sweepDeg, angleRad, cx, cy, rx, ry: Single;
    
      startAngleDeg := 200.0;
      sweepDeg := 140.0;
      segments := 24;
      SetLength(points, segments + 1);
    
      cx := (mouthRect.Left + mouthRect.Right) * 0.5;
      cy := (mouthRect.Top + mouthRect.Bottom) * 0.5;
      rx := mouthRect.Width * 0.5;
      ry := mouthRect.Height * 0.5;
    
      for i := 0 to segments do
      begin
        angleRad := DegToRad(startAngleDeg + sweepDeg * (i / segments));
        points[i] := PointF(cx + Cos(angleRad) * rx, cy - Sin(angleRad) * ry);
      end;
    
      for i := 0 to segments - 1 do
        Canvas.DrawLine(points[i], points[i + 1], 1);
    

    Smile Emoji creating in TPaintBox using Delphi Programming