unit uCanvas;

interface

uses
{$IFDEF VCL}
  Graphics,
{$ELSE}
  QGraphics,
{$ENDIF}
  Rubies;

var
  cCanvas: Tvalue;

function ap_cCanvas: Tvalue;
procedure Canvas_setup(obj: Tvalue; real: TCanvas);
function Canvas_event_handle(This, name: Tvalue): Tvalue; cdecl;
function Canvas_alloc(klass: Tvalue; real: TCanvas): Tvalue;
function ap_iCanvas(real: TCanvas; owner: Tvalue): Tvalue;
procedure Init_Canvas;

implementation

uses
{$IFDEF LINUX}
  Types,
{$ENDIF}
{$IFDEF MSWINDOWS}
  Windows,
{$ENDIF}
  SysUtils,
  uDefUtils, uIntern, uHandle, uAlloc, uProp, uPhi, uConv,
  uFont, uBrush, uPen, uPoint, uRect, uSize,
  uIndexer;

function ap_cCanvas: Tvalue;
begin
  result := cCanvas;
end;

procedure Canvas_setup(obj: Tvalue; real: TCanvas);
begin
  rb_iv_set(obj, '@font', ap_iFont(real.Font, obj));
  rb_iv_set(obj, '@brush', ap_iBrush(real.Brush, obj));
  rb_iv_set(obj, '@pen', ap_iPen(real.Pen, obj));
end;

function Canvas_event_handle(This, name: Tvalue): Tvalue; cdecl;
begin
  EventHandle(This, name, [Handle]);
  result := Qnil;
end;

function Canvas_alloc(klass: Tvalue; real: TCanvas): Tvalue;
begin
  result := TmpAlloc(klass, real);
  Canvas_setup(result, real);
end;

function ap_iCanvas(real: TCanvas; owner: Tvalue): Tvalue;
begin
  result := Canvas_alloc(cCanvas, real);
  ap_owner(result, owner);
end;

function Canvas_new(This: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := TCanvas.Create;
  result := ObjAlloc(This, real);
  Canvas_setup(result, real);
  ap_obj_call_init(result, 0, nil);
end;

function Canvas_clip_rect(This: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  result := ap_iRect(real.ClipRect, This);
  ap_owner(result, This);
end;

function Canvas_copy_rect(This, dst, cv, src: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  Dest: TRect;
  Canvas: TCanvas;
  Source: TRect;
begin
  real := ap_data_get_struct(This);
  Dest := PRect(ap_data_get_struct(dst))^;
  ap_data_get_object(cv, TCanvas, Canvas);
  Source := PRect(ap_data_get_struct(src))^;
  real.CopyRect(Dest, Canvas, Source);
  result := This;
end;

function Canvas_fill_rect(This, vrect: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  rect: TRect;
begin
  real := ap_data_get_struct(This);
  rect := PRect(ap_data_get_struct(vrect))^;
  real.FillRect(rect);
  result := This;
end;

function Canvas_text_extent(This, str: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  result := Size_alloc(ap_cSize, real.TextExtent(dl_String(str)));
  ap_owner(result, This);
end;

function Canvas_text_width(This, str: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  result := INT2FIX(real.TextWidth(dl_String(str)));
end;

function Canvas_text_height(This, str: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  result := INT2FIX(real.TextHeight(dl_String(str)));
end;

function Canvas_text_out(This, x, y, str: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  real.TextOut(FIX2INT(x), FIX2INT(y), dl_String(str));
  result := This;
end;
{$IFDEF VCL}
// [ap-dev:1456]
function Canvas_text_out_vertical(This, x, y, str: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  LF:TLogFont;
  FT:TFont;
begin
  real := ap_data_get_struct(This);
  FT := real.font;
  //if FT.Name[1] = '@' then begin
    GetObject(FT.Handle,SizeOf(LF),@LF);
    LF.lfEscapement := -900;
    FT.Handle := CreateFontIndirect(LF);
  //end;
  real.TextOut(FIX2INT(x), FIX2INT(y), dl_String(str));
  result := This;
end;
{$ENDIF}
function Canvas_text_rect(This, vrect, x, y, str: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  rect: TRect;
begin
  real := ap_data_get_struct(This);
  rect := PRect(ap_data_get_struct(vrect))^;
  real.TextRect(rect, FIX2INT(x), FIX2INT(y), dl_String(str));
  result := This;
end;

function Canvas_draw(This, x, y, vgraphic: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  graphic: TGraphic;
begin
  real := ap_data_get_struct(This);
  ap_data_get_object(vgraphic, TGraphic, graphic);
  real.Draw(FIX2INT(x), FIX2INT(y), graphic);
  result := This;
end;

function Canvas_stretch_draw(This, vrect, vgraphic: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  rect: TRect;
  graphic: TGraphic;
begin
  real := ap_data_get_struct(This);
  rect := PRect(ap_data_get_struct(vrect))^;
  ap_data_get_object(vgraphic, TGraphic, graphic);
  real.StretchDraw(rect, graphic);
  result := This;
end;

function Canvas_draw_focus_rect(This, vrect: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  rect: TRect;
begin
  real := ap_data_get_struct(This);
  rect := PRect(ap_data_get_struct(vrect))^;
  real.DrawFocusRect(rect);
  result := This;
end;

function Canvas_ellipse(argc: integer; argv: Pointer; This: Tvalue): Tvalue; cdecl;
var
  args: array of Tvalue;
  real: TCanvas;
  rect: TRect;
  x1, y1, x2, y2: Integer;
begin
  SetLength(args, argc);
  args := argv;
  real := ap_data_get_struct(This);
  case RTYPE(args[0]) of
  T_DATA:
    begin
      if argc <> 1 then ap_raise(ap_eArgError, sWrong_num_of_args);
      rect := PRect(ap_data_get_struct(args[0]))^;
      x1 := rect.Left;
      y1 := rect.Top;
      x2 := rect.Right;
      y2 := rect.Bottom;
    end;
  T_FIXNUM:
    begin
      if argc <> 4 then ap_raise(ap_eArgError, sWrong_num_of_args);
      x1 := FIX2INT(args[0]);
      y1 := FIX2INT(args[1]);
      x2 := FIX2INT(args[2]);
      y2 := FIX2INT(args[3]);
    end;
  else
    ap_raise(ap_eArgError, sWrong_arg_type);
    x1 := 0;
    y1 := 0;
    x2 := 0;
    y2 := 0;
  end;
  real.Ellipse(x1, y1, x2, y2);
  result := This;
end;

function Canvas_rectangle(argc: integer; argv: Pointer; This: Tvalue): Tvalue; cdecl;
var
  args: array of Tvalue;
  real: TCanvas;
  rect: TRect;
  x1, y1, x2, y2: Integer;
begin
  SetLength(args, argc);
  args := argv;
  real := ap_data_get_struct(This);
  case RTYPE(args[0]) of
  T_DATA:
    begin
      if argc <> 1 then ap_raise(ap_eArgError, sWrong_num_of_args);
      rect := PRect(ap_data_get_struct(args[0]))^;
      x1 := rect.Left;
      y1 := rect.Top;
      x2 := rect.Right;
      y2 := rect.Bottom;
    end;
  T_FIXNUM:
    begin
      if argc <> 4 then ap_raise(ap_eArgError, sWrong_num_of_args);
      x1 := FIX2INT(args[0]);
      y1 := FIX2INT(args[1]);
      x2 := FIX2INT(args[2]);
      y2 := FIX2INT(args[3]);
    end;
  else
    ap_raise(ap_eArgError, sWrong_arg_type);
    x1 := 0;
    y1 := 0;
    x2 := 0;
    y2 := 0;
  end;
  real.Rectangle(x1, y1, x2, y2);
  result := This;
end;

function Canvas_round_rect(argc: integer; argv: Pointer; This: Tvalue): Tvalue; cdecl;
var
  args: array of Tvalue;
  real: TCanvas;
  rect: TRect;
  x1, y1, x2, y2, x3, y3: Integer;
begin
  SetLength(args, argc);
  args := argv;
  real := ap_data_get_struct(This);
  case RTYPE(args[0]) of
  T_DATA:
    begin
      if argc <> 3 then ap_raise(ap_eArgError, sWrong_num_of_args);
      rect := PRect(ap_data_get_struct(args[0]))^;
      x1 := rect.Left;
      y1 := rect.Top;
      x2 := rect.Right;
      y2 := rect.Bottom;
      x3 := FIX2INT(args[1]);
      y3 := FIX2INT(args[2]);
    end;
  T_FIXNUM:
    begin
      if argc <> 6 then ap_raise(ap_eArgError, sWrong_num_of_args);
      x1 := FIX2INT(args[0]);
      y1 := FIX2INT(args[1]);
      x2 := FIX2INT(args[2]);
      y2 := FIX2INT(args[3]);
      x3 := FIX2INT(args[4]);
      y3 := FIX2INT(args[5]);
    end;
  else
    ap_raise(ap_eArgError, sWrong_arg_type);
    x1 := 0;
    y1 := 0;
    x2 := 0;
    y2 := 0;
    x3 := 0;
    y3 := 0;
  end;
  real.RoundRect(x1, y1, x2, y2, x3, y3);
  result := This;
end;

{$IFDEF VCL}
function Canvas_aref(This, x, y: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  result := INT2FIX(real.Pixels[FIX2INT(x), FIX2INT(y)]);
end;

function Canvas_aset(This, x, y, color: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  real.Pixels[FIX2INT(x), FIX2INT(y)] := NUM2INT(color);
  result := This;
end;

function Canvas_flood_fill(This, x, y, color, style: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  try
    real.FloodFill(FIX2INT(x), FIX2INT(y), NUM2INT(color), TFillStyle(FIX2INT(style)));
  except
    on E: Exception do
      ap_raise(ap_eArgError, E.message);
  end;
  result := This;
end;
{$ENDIF}

function Canvas_move_to(This, x, y: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  real.MoveTo(FIX2INT(x), FIX2INT(y));
  result := This;
end;

function Canvas_line_to(This, x, y: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  real.LineTo(FIX2INT(x), FIX2INT(y));
  result := This;
end;

function Canvas_get_pen_pos(This: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  result := ap_iPoint(real.PenPos, Qnil);
  ap_owner(result, This);
end;

function Canvas_set_pen_pos(This, v: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  real.PenPos := PPoint(ap_data_get_struct(v))^;
  result := v;
end;

function Canvas_lock(This: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  real.Lock;
  try
    result := rb_yield(Qnil);
  finally
    real.Unlock;
  end;
end;

type
  TPoints = array of TPoint;

procedure args_to_Points(argc: Integer; argv: Pointer; var Points: TPoints);
var
  args: array of Tvalue;
  i, j: Integer;
  Point: TPoint;
  ary, item:Tvalue;
begin
  SetLength(args, argc);
  SetLength(Points, 1000);  // must increase ????
  args := argv;
  i := 0;
  j := 0;
  while i < argc do
  begin
    case RTYPE(args[i]) of
    T_ARRAY:
      begin
        ary := args[i];
        inc(i);
        while(true) do begin
          item := rb_ary_shift(ary);
          if item = Qnil then break;
          case RTYPE(item) of
          T_DATA:
            begin
              Points[j] := PPoint(ap_data_get_struct(item))^;
              Inc(j, 1);
            end;
          T_FIXNUM:
            begin
              Point.X := FIX2INT(item);
              item := rb_ary_shift(ary);
              Point.Y := FIX2INT(item);
              Points[j] := Point;
              Inc(j, 1);
            end;
          else
            ap_raise(ap_eArgError, sWrong_arg_type);
          end;
        end;
      end;
    T_DATA:
      begin
        Points[j] := PPoint(ap_data_get_struct(args[i]))^;
        Inc(i, 1);
        Inc(j, 1);
      end;
    T_FIXNUM:
      begin
        if argc < i+1 then ap_raise(ap_eArgError, sWrong_num_of_args);
        Point.X := FIX2INT(args[i+0]);
        Point.Y := FIX2INT(args[i+1]);
        Points[j] := Point;
        Inc(i, 2);
        Inc(j, 1);
      end;
    else
      ap_raise(ap_eArgError, sWrong_arg_type);
    end;
  end;
//rb_p(ap_Integer(j));
  SetLength(Points, j);
end;

function Canvas_polygon(argc: Integer; argv: Pointer; This: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  Points: TPoints;
begin
  real := ap_data_get_struct(This);
  args_to_Points(argc, argv, Points);
  real.Polygon(Points);
  result := This;
end;

function Canvas_polyline(argc: Integer; argv: Pointer; This: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  Points: TPoints;
begin
  real := ap_data_get_struct(This);
  args_to_Points(argc, argv, Points);
  real.Polyline(Points);
  result := This;
end;

function Canvas_poly_bezier(argc: Integer; argv: Pointer; This: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  Points: TPoints;
begin
  real := ap_data_get_struct(This);
  args_to_Points(argc, argv, Points);
  real.PolyBezier(Points);
  result := This;
end;

function Canvas_poly_bezier_to(argc: Integer; argv: Pointer; This: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  Points: TPoints;
begin
  real := ap_data_get_struct(This);
  args_to_Points(argc, argv, Points);
  real.PolyBezierTo(Points);
  result := This;
end;
{$IFDEF VCL}
function Canvas_get_handle(This: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  result := ap_Handle(real.Handle);
end;
{$ENDIF}
function Canvas_arc(This, X1, Y1, X2, Y2, X3, Y3, X4, Y4 : Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  dl_X1 : Integer;
  dl_Y1 : Integer;
  dl_X2 : Integer;
  dl_Y2 : Integer;
  dl_X3 : Integer;
  dl_Y3 : Integer;
  dl_X4 : Integer;
  dl_Y4 : Integer;
begin
  real := ap_data_get_struct(This);
  dl_X1 := dl_Integer(X1);
  dl_Y1 := dl_Integer(Y1);
  dl_X2 := dl_Integer(X2);
  dl_Y2 := dl_Integer(Y2);
  dl_X3 := dl_Integer(X3);
  dl_Y3 := dl_Integer(Y3);
  dl_X4 := dl_Integer(X4);
  dl_Y4 := dl_Integer(Y4);
  real.Arc( dl_X1, dl_Y1, dl_X2, dl_Y2, dl_X3, dl_Y3, dl_X4, dl_Y4 );
  result := This;
end;

function Canvas_chord(This, X1, Y1, X2, Y2, X3, Y3, X4, Y4 : Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  dl_X1 : Integer;
  dl_Y1 : Integer;
  dl_X2 : Integer;
  dl_Y2 : Integer;
  dl_X3 : Integer;
  dl_Y3 : Integer;
  dl_X4 : Integer;
  dl_Y4 : Integer;
begin
  real := ap_data_get_struct(This);
  dl_X1 := dl_Integer(X1);
  dl_Y1 := dl_Integer(Y1);
  dl_X2 := dl_Integer(X2);
  dl_Y2 := dl_Integer(Y2);
  dl_X3 := dl_Integer(X3);
  dl_Y3 := dl_Integer(Y3);
  dl_X4 := dl_Integer(X4);
  dl_Y4 := dl_Integer(Y4);
  real.Chord( dl_X1, dl_Y1, dl_X2, dl_Y2, dl_X3, dl_Y3, dl_X4, dl_Y4 );
  result := This;
end;
{$IFDEF VCL}
function Canvas_frame_rect(This, Rect : Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  dl_Rect0 : TRect;
begin
  real := ap_data_get_struct(This);
  dl_Rect0 := dl_Rect(Rect);
  real.FrameRect( dl_Rect0 );
  result := This;
end;

function Canvas_handle_allocated(This : Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  result := ap_Bool(real.HandleAllocated);
end;
{$ENDIF}
function Canvas_pie(This, X1, Y1, X2, Y2, X3, Y3, X4, Y4 : Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  dl_X1 : Integer;
  dl_Y1 : Integer;
  dl_X2 : Integer;
  dl_Y2 : Integer;
  dl_X3 : Integer;
  dl_Y3 : Integer;
  dl_X4 : Integer;
  dl_Y4 : Integer;
begin
  real := ap_data_get_struct(This);
  dl_X1 := dl_Integer(X1);
  dl_Y1 := dl_Integer(Y1);
  dl_X2 := dl_Integer(X2);
  dl_Y2 := dl_Integer(Y2);
  dl_X3 := dl_Integer(X3);
  dl_Y3 := dl_Integer(Y3);
  dl_X4 := dl_Integer(X4);
  dl_Y4 := dl_Integer(Y4);
  real.Pie( dl_X1, dl_Y1, dl_X2, dl_Y2, dl_X3, dl_Y3, dl_X4, dl_Y4 );
  result := This;
end;

function Canvas_refresh(This : Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  real.Refresh;
  result := This;
end;

function Canvas_try_lock(This : Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  result := ap_Bool(real.TryLock);
end;

function Canvas_unlock(This : Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  real.Unlock;
  result := This;
end;

function Canvas_get_lock_count(This: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  result := ap_Integer(real.LockCount);  
end;
{$IFDEF VCL}
function Canvas_get_canvas_orientation(This: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  result := ap_Integer(ord(real.CanvasOrientation));
end;

function Canvas_set_pixels(argc: integer; argv: Rubies.Pvalue; This: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  dl_X : Integer;
  dl_Y : Integer;
begin
  if argc < 3 then ap_raise(ap_eArgError, sToo_few_args);
  real := ap_data_get_struct(This);
  dl_X := dl_Integer(argv^);
  inc(argv); dec(argc);
  dl_Y := dl_Integer(argv^);
  inc(argv); dec(argc);
  real.Pixels[dl_X, dl_Y] := TColor(dl_Integer(argv^));
  result := argv^;
end;

function Canvas_get_pixels(argc: integer; argv: Rubies.Pvalue; This: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
  dl_X : Integer;
  dl_Y : Integer;
begin
  if argc < 2 then ap_raise(ap_eArgError, sToo_few_args);
  real := ap_data_get_struct(This);
  dl_X := dl_Integer(argv^);
  inc(argv); dec(argc);
  dl_Y := dl_Integer(argv^);
  inc(argv); dec(argc);
  result := ap_Integer(ord(real.Pixels[dl_X, dl_Y]));
end;

function Canvas_get_text_flags(This: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  result := ap_Integer(real.TextFlags);  
end;

function Canvas_set_text_flags(This, v: Tvalue): Tvalue; cdecl;
var
  real: TCanvas;
begin
  real := ap_data_get_struct(This);
  real.TextFlags := dl_Integer(v);
  result := v;
end;
{$ENDIF}
procedure Init_Canvas;
begin
{$IFDEF VCL}
  OutputConstSetType(mPhi, TypeInfo(TFillStyle));
  OutputConstSetType(mPhi, TypeInfo(TFillMode));
  OutputConstSetType(mPhi, TypeInfo(TCanvasOrientation));
{$ENDIF}
  OutputConstSetType(mPhi, TypeInfo(TCanvasStates));

  cCanvas := rb_define_class_under(mPhi, 'Canvas', ap_cObject);
  OutputProp(cCanvas, TCanvas);

  rb_define_method(cCanvas, 'event_handle', @Canvas_event_handle, 1);
  rb_define_singleton_method(cCanvas, 'new', @Canvas_new, 0);
  rb_define_method(cCanvas, 'clip_rect', @Canvas_clip_rect, 0);
  rb_define_method(cCanvas, 'copy_rect', @Canvas_copy_rect, 3);
  rb_define_method(cCanvas, 'fill_rect', @Canvas_fill_rect, 1);
  rb_define_method(cCanvas, 'text_extent', @Canvas_text_extent, 1);
  rb_define_method(cCanvas, 'text_width', @Canvas_text_width, 1);
  rb_define_method(cCanvas, 'text_height', @Canvas_text_height, 1);
  rb_define_method(cCanvas, 'text_out', @Canvas_text_out, 3);
{$IFDEF VCL}
  rb_define_method(cCanvas, 'text_out_vertical', @Canvas_text_out_vertical, 3);
{$ENDIF}
  rb_define_method(cCanvas, 'text_rect', @Canvas_text_rect, 4);
  rb_define_method(cCanvas, 'draw', @Canvas_draw, 3);
  rb_define_method(cCanvas, 'stretch_draw', @Canvas_stretch_draw, 2);
  rb_define_method(cCanvas, 'draw_focus_rect', @Canvas_draw_focus_rect, 1);
  DefineMethod(cCanvas, 'ellipse', Canvas_ellipse);
  rb_define_alias(cCanvas, 'draw_oval', 'ellipse');
  DefineMethod(cCanvas, 'rectangle', Canvas_rectangle);
  rb_define_alias(cCanvas, 'draw_rect', 'rectangle');
  DefineMethod(cCanvas, 'round_rect', Canvas_round_rect);
{$IFDEF VCL}
  // vcl: pixels
  rb_define_method(cCanvas, '[]', @Canvas_aref, 2);
  rb_define_method(cCanvas, '[]=', @Canvas_aset, 3);
  rb_define_method(cCanvas, 'flood_fill', @Canvas_flood_fill, 4);
{$ENDIF}
  rb_define_method(cCanvas, 'move_to', @Canvas_move_to, 2);
  rb_define_method(cCanvas, 'line_to', @Canvas_line_to, 2);
  DefineAttrGet(cCanvas, 'pen_pos', @Canvas_get_pen_pos);
  DefineAttrSet(cCanvas, 'pen_pos', @Canvas_set_pen_pos);
  rb_define_method(cCanvas, 'lock', @Canvas_lock, 0);
  rb_define_method(cCanvas, 'polygon', @Canvas_polygon, -1);
  rb_define_method(cCanvas, 'polyline', @Canvas_polyline, -1);
  rb_define_method(cCanvas, 'poly_bezier', @Canvas_poly_bezier, -1);
  rb_define_method(cCanvas, 'poly_bezier_to', @Canvas_poly_bezier_to, -1);
{$IFDEF VCL}
  DefineAttrGet(cCanvas, 'handle', Canvas_get_handle);
{$ENDIF}
  rb_define_method(cCanvas, 'arc', @Canvas_arc, 8);
  rb_define_method(cCanvas, 'chord', @Canvas_chord, 8);
{$IFDEF VCL}
  rb_define_method(cCanvas, 'frame_rect', @Canvas_frame_rect, 1);
  rb_define_method(cCanvas, 'handle_allocated', @Canvas_handle_allocated, 0);
{$ENDIF}
  rb_define_method(cCanvas, 'pie', @Canvas_pie, 8);
  rb_define_method(cCanvas, 'refresh', @Canvas_refresh, 0);
  rb_define_method(cCanvas, 'try_lock', @Canvas_try_lock, 0);
  rb_define_method(cCanvas, 'unlock', @Canvas_unlock, 0);
  DefineAttrGet(cCanvas, 'lock_count', Canvas_get_lock_count);
{$IFDEF VCL}
  DefineAttrGet(cCanvas, 'canvas_orientation', Canvas_get_canvas_orientation);
  DefineIndexer(cCanvas, 'pixels', @Canvas_get_pixels, @Canvas_set_pixels);
  DefineAttrGet(cCanvas, 'text_flags', Canvas_get_text_flags);
  DefineAttrSet(cCanvas, 'text_flags', Canvas_set_text_flags);
{$ENDIF}
end;

end.
