diff options
Diffstat (limited to 'gfx/gfxbase.pas')
-rw-r--r-- | gfx/gfxbase.pas | 1283 |
1 files changed, 1283 insertions, 0 deletions
diff --git a/gfx/gfxbase.pas b/gfx/gfxbase.pas new file mode 100644 index 00000000..dd1f305e --- /dev/null +++ b/gfx/gfxbase.pas @@ -0,0 +1,1283 @@ +{ + fpGUI - Free Pascal GUI Library + + GFXBase - Abstract declarations to be implemented on each platform + + Copyright (C) 2000 - 2006 See the file AUTHORS, included in this + distribution, for details of the copyright. + + See the file COPYING.modifiedLGPL, included in this distribution, + for details about redistributing fpGUI. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +} +unit GfxBase; + +{$IFDEF Debug} + {$ASSERTIONS On} +{$ENDIF} + +{$ifdef fpc} + {$mode objfpc}{$H+} +{$endif} + +interface + +uses + SysUtils, + Classes; + +{$INCLUDE keys.inc} + +resourcestring + // Exception message strings, to be used by target implementations + SUnsupportedPixelFormat = 'Pixel format (%d bits/pixel) is not supported'; + SIncompatibleCanvasForBlitting = 'Cannot blit from %s to %s'; + +type + + TSize = record + cx, cy: Integer; + end; + + + { We use a special 3x3 matrix for transformations of coordinates. As the + only allowed transformations are translations and scalations, we need a + matrix with the following content ([x,y] is a variable): + [0,0] 0 [2,0] + 0 [1,1] [2,1] + 0 0 1 + [0,0]: X scalation + [2,0]: X translation + [1,1]: Y scalation + [2,1]: Y translation + NOTE: This may change in the future! Don't assume anything about the + structure of TGfxMatrix! TGfxCanvas only allows you to read and + write the current transformation matrix so that the matrix can + easily be saved and restored. + } + + TGfxMatrix = record + _00, _20, _11, _21: Integer; + end; + +const + GfxIdentityMatrix: TGfxMatrix = (_00: 1; _20: 0; _11: 1; _21: 0); + +type + + PGfxColor = ^TGfxColor; + TGfxColor = packed record + Red, Green, Blue, Alpha: Word; + end; + + PGfxPixel = ^TGfxPixel; + TGfxPixel = LongWord; + + + TGfxFormatType = ( + ftInvalid, + ftMono, // Monochrome + ftPal4, // 4 bpp using palette + ftPal4A, // 4 bpp using palette with alpha values > 0 + ftPal8, // 8 bpp using palette + ftPal8A, // 8 bpp using palette with alpha values > 0 + ftRGB16, // 15/16 bpp RGB + ftRGBA16, // 16 bpp RGBA + ftRGB24, // 24 bpp RGB + ftRGB32, // 32 bpp RGB + ftRGBA32); // 32 bpp RGBA + + + TGfxPixelFormat = record + case FormatType: TGfxFormatType of + ftRGB16, ftRGBA16, ftRGB24, ftRGB32, ftRGBA32: ( + RedMask: TGfxPixel; + GreenMask: TGfxPixel; + BlueMask: TGfxPixel; + AlphaMask: TGfxPixel); // only used for RGBA types + end; + + +const + + FormatTypeBPPTable: array[TGfxFormatType] of Integer = + (0, 1, 4, 4, 8, 8, 16, 16, 24, 32, 32); + + { Predefined colors } + + colTransparent: TGfxColor = (Red: $0000; Green: $0000; Blue: $0000; Alpha: $ffff); + colBlack: TGfxColor = (Red: $0000; Green: $0000; Blue: $0000; Alpha: $0000); + colBlue: TGfxColor = (Red: $0000; Green: $0000; Blue: $ffff; Alpha: $0000); + colGreen: TGfxColor = (Red: $0000; Green: $ffff; Blue: $0000; Alpha: $0000); + colCyan: TGfxColor = (Red: $0000; Green: $ffff; Blue: $ffff; Alpha: $0000); + colRed: TGfxColor = (Red: $ffff; Green: $0000; Blue: $0000; Alpha: $0000); + colMagenta: TGfxColor = (Red: $ffff; Green: $0000; Blue: $ffff; Alpha: $0000); + colYellow: TGfxColor = (Red: $ffff; Green: $ffff; Blue: $0000; Alpha: $0000); + colWhite: TGfxColor = (Red: $ffff; Green: $ffff; Blue: $ffff; Alpha: $0000); + colGray: TGfxColor = (Red: $8000; Green: $8000; Blue: $8000; Alpha: $0000); + colLtGray: TGfxColor = (Red: $c000; Green: $c000; Blue: $c000; Alpha: $0000); + colDkBlue: TGfxColor = (Red: $0000; Green: $0000; Blue: $8000; Alpha: $0000); + colDkGreen: TGfxColor = (Red: $0000; Green: $8000; Blue: $0000; Alpha: $0000); + colDkCyan: TGfxColor = (Red: $0000; Green: $8000; Blue: $8000; Alpha: $0000); + colDkRed: TGfxColor = (Red: $8000; Green: $0000; Blue: $0000; Alpha: $0000); + colDkMagenta: TGfxColor = (Red: $8000; Green: $0000; Blue: $8000; Alpha: $0000); + colDkYellow: TGfxColor = (Red: $8000; Green: $8000; Blue: $0000; Alpha: $0000); + + webBlack: TGfxColor = (Red: $0000; Green: $0000; Blue: $0000; Alpha: $0000); + webMaroon: TGfxColor = (Red: $8000; Green: $0000; Blue: $0000; Alpha: $0000); + webGreen: TGfxColor = (Red: $0000; Green: $8000; Blue: $0000; Alpha: $0000); + webOlive: TGfxColor = (Red: $8000; Green: $8000; Blue: $0000; Alpha: $0000); + webNavy: TGfxColor = (Red: $0000; Green: $0000; Blue: $8000; Alpha: $0000); + webPurple: TGfxColor = (Red: $8000; Green: $0000; Blue: $8000; Alpha: $0000); + webTeal: TGfxColor = (Red: $0000; Green: $8000; Blue: $8000; Alpha: $0000); + webGray: TGfxColor = (Red: $8000; Green: $8000; Blue: $8000; Alpha: $0000); + webSilver: TGfxColor = (Red: $c000; Green: $c000; Blue: $c000; Alpha: $0000); + webRed: TGfxColor = (Red: $ffff; Green: $0000; Blue: $0000; Alpha: $0000); + webLime: TGfxColor = (Red: $0000; Green: $ffff; Blue: $0000; Alpha: $0000); + webYellow: TGfxColor = (Red: $ffff; Green: $ffff; Blue: $0000; Alpha: $0000); + webBlue: TGfxColor = (Red: $0000; Green: $0000; Blue: $ffff; Alpha: $0000); + webFuchsia: TGfxColor = (Red: $ffff; Green: $0000; Blue: $ffff; Alpha: $0000); + webAqua: TGfxColor = (Red: $0000; Green: $ffff; Blue: $ffff; Alpha: $0000); + webWhite: TGfxColor = (Red: $ffff; Green: $ffff; Blue: $ffff; Alpha: $0000); + + + // Some predefined pixel formats: + + PixelFormatMono: TGfxPixelFormat = ( + FormatType: ftMono; + RedMask: 0; + GreenMask: 0; + BlueMask: 0; + AlphaMask: 0); + + PixelFormatPal4: TGfxPixelFormat = ( + FormatType: ftPal4; + RedMask: 0; + GreenMask: 0; + BlueMask: 0; + AlphaMask: 0); + + PixelFormatPal4A: TGfxPixelFormat = ( + FormatType: ftPal4A; + RedMask: 0; + GreenMask: 0; + BlueMask: 0; + AlphaMask: 0); + + PixelFormatPal8: TGfxPixelFormat = ( + FormatType: ftPal8; + RedMask: 0; + GreenMask: 0; + BlueMask: 0; + AlphaMask: 0); + + PixelFormatPal8A: TGfxPixelFormat = ( + FormatType: ftPal8A; + RedMask: 0; + GreenMask: 0; + BlueMask: 0; + AlphaMask: 0); + + PixelFormatRGB24: TGfxPixelFormat = ( + FormatType: ftRGB24; + RedMask: $0000ff; + GreenMask: $00ff00; + BlueMask: $ff0000; + AlphaMask: 0); + + PixelFormatBGR24: TGfxPixelFormat = ( + FormatType: ftRGB24; + RedMask: $ff0000; + GreenMask: $00ff00; + BlueMask: $0000ff; + AlphaMask: 0); + + PixelFormatRGB32: TGfxPixelFormat = ( + FormatType: ftRGB32; + RedMask: $0000ff; + GreenMask: $00ff00; + BlueMask: $ff0000; + AlphaMask: 0); + + PixelFormatRGBA32: TGfxPixelFormat = ( + FormatType: ftRGB32; + RedMask: $000000ff; + GreenMask: $0000ff00; + BlueMask: $00ff0000; + AlphaMask: $ff000000); + + PixelFormatARGB32: TGfxPixelFormat = ( + FormatType: ftRGB32; + RedMask: $0000ff00; + GreenMask: $00ff0000; + BlueMask: $ff000000; + AlphaMask: $000000ff); + + PixelFormatBGR32: TGfxPixelFormat = ( + FormatType: ftRGB32; + RedMask: $ff0000; + GreenMask: $00ff00; + BlueMask: $0000ff; + AlphaMask: 0); + + PixelFormatBGRA32: TGfxPixelFormat = ( + FormatType: ftRGB32; + RedMask: $00ff0000; + GreenMask: $0000ff00; + BlueMask: $000000ff; + AlphaMask: $ff000000); + + PixelFormatABGR32: TGfxPixelFormat = ( + FormatType: ftRGB32; + RedMask: $ff000000; + GreenMask: $00ff0000; + BlueMask: $0000ff00; + AlphaMask: $000000ff); + +type + + EGfxError = class(Exception); + + EGfxUnsupportedPixelFormat = class(EGfxError) + constructor Create(const APixelFormat: TGfxPixelFormat); + end; + + + TFCustomImage = class; + TFCustomApplication = class; + TFCustomWindow = class; + + TGfxWindowOption = ( + woWindow, woBorderless, woPopup, woToolWindow, woChildWindow, + woX11SkipWMHints); + TGfxWindowOptions = set of TGfxWindowOption; + + TGfxCursor = (crDefault, crNone, crArrow, crCross, crIBeam, crSize, crSizeNS, + crSizeWE, cpUpArrow, crHourGlass, crNoDrop, crHelp); + + + { TFCustomFont } + + TGfxFontClass = (fcSerif, fcSansSerif, fcTypewriter, fcDingbats); + + TFCustomFont = class + protected + FHandle: Cardinal; + public + class function GetDefaultFontName(const AFontClass: TGfxFontClass): String; virtual; + property Handle: Cardinal read FHandle; + end; + + + { TGfxPalette } + + TGfxPalette = class + private + FRefCount: LongInt; + FEntryCount: Integer; + FEntries: PGfxColor; + function GetEntry(AIndex: Integer): TGfxColor; + public + constructor Create(AEntryCount: Integer; AEntries: PGfxColor); + destructor Destroy; override; + procedure AddRef; + procedure Release; + property EntryCount: Integer read FEntryCount; + property Entries[AIndex: Integer]: TGfxColor read GetEntry; + end; + + + { TFCustomCanvas } + + TGfxLineStyle = (lsSolid, lsDot); + + TFCustomCanvas = class(TObject) + private + FMatrix: TGfxMatrix; + protected + FWidth: Integer; + FHeight: Integer; + FPixelFormat: TGfxPixelFormat; + function DoExcludeClipRect(const ARect: TRect): Boolean; virtual; abstract; + function DoIntersectClipRect(const ARect: TRect): Boolean; virtual; abstract; + function DoUnionClipRect(const ARect: TRect): Boolean; virtual; abstract; + function DoGetClipRect: TRect; virtual; abstract; + procedure DoDrawArc(const ARect: TRect; StartAngle, EndAngle: Single); virtual; abstract; + procedure DoDrawCircle(const ARect: TRect); virtual; abstract; + procedure DoDrawLine(const AFrom, ATo: TPoint); virtual; abstract; + procedure DoDrawRect(const ARect: TRect); virtual; + procedure DoDrawPoint(const APoint: TPoint); virtual; abstract; + procedure DoFillRect(const ARect: TRect); virtual; abstract; + procedure DoTextOut(const APosition: TPoint; const AText: String); virtual; abstract; + procedure DoCopyRect(ASource: TFCustomCanvas; const ASourceRect: TRect; const ADestPos: TPoint); virtual; abstract; + procedure DoMaskedCopyRect(ASource, AMask: TFCustomCanvas; const ASourceRect: TRect; const AMaskPos, ADestPos: TPoint); virtual; abstract; + procedure DoDrawImageRect(AImage: TFCustomImage; ASourceRect: TRect; const ADestPos: TPoint); virtual; abstract; + public + constructor Create; + // Transformations + function Transform(APoint: TPoint): TPoint; + function Transform(ARect: TRect): TRect; + function ReverseTransform(APoint: TPoint): TPoint; + function ReverseTransform(ARect: TRect): TRect; + procedure AppendTranslation(ADelta: TPoint); + + // Graphics state + procedure SaveState; virtual; abstract; + procedure RestoreState; virtual; abstract; + procedure EmptyClipRect; virtual; + procedure SetColor_(AColor: TGfxPixel); virtual; abstract; + procedure SetColor(AColor: TGfxColor); virtual; + procedure SetFont(AFont: TFCustomFont); virtual; abstract; + procedure SetLineStyle(ALineStyle: TGfxLineStyle); virtual; abstract; + function ExcludeClipRect(const ARect: TRect): Boolean; + function IntersectClipRect(const ARect: TRect): Boolean; + function UnionClipRect(const ARect: TRect): Boolean; + function GetClipRect: TRect; + function MapColor(const AColor: TGfxColor): TGfxPixel; virtual; abstract; + + // Drawing functions + procedure DrawArc(const ARect: TRect; StartAngle, EndAngle: Single); + procedure DrawCircle(const ARect: TRect); + procedure DrawLine(const AFrom, ATo: TPoint); + procedure DrawPolyLine(const Coords: array of TPoint); virtual; + procedure DrawRect(const ARect: TRect); + procedure DrawPoint(const APoint: TPoint); + procedure FillRect(const ARect: TRect); + + // Fonts + function FontCellHeight: Integer; virtual; abstract; + function TextExtent(const AText: String): TSize; virtual; + function TextWidth(const AText: String): Integer; virtual; + procedure TextOut(const APosition: TPoint; const AText: String); + + // Bit block transfers + procedure Copy(ASource: TFCustomCanvas; const ADestPos: TPoint); virtual; + procedure CopyRect(ASource: TFCustomCanvas; const ASourceRect: TRect; const ADestPos: TPoint); + procedure MaskedCopy(ASource, AMask: TFCustomCanvas; const ADestPos: TPoint); +{!!!: procedure MaskedCopyRect(ASource, AMask: TGfxCanvas; const ASourceRect: TRect; + const ADestPos: TPoint); virtual;} + procedure MaskedCopyRect(ASource, AMask: TFCustomCanvas; const ASourceRect: TRect; const AMaskPos, ADestPos: TPoint); + + // Image drawing + procedure DrawImage(AImage: TFCustomImage; const ADestPos: TPoint); + procedure DrawImageRect(AImage: TFCustomImage; ASourceRect: TRect; const ADestPos: TPoint); + + // Properties + property Width: Integer read FWidth; + property Height: Integer read FHeight; + property PixelFormat: TGfxPixelFormat read FPixelFormat; + property Matrix: TGfxMatrix read FMatrix write FMatrix; + end; + + + TFCustomImage = class(TObject) + private + FWidth, FHeight: Integer; + FPixelFormat: TGfxPixelFormat; + FPalette: TGfxPalette; + procedure SetPalette(APalette: TGfxPalette); + protected + public + constructor Create(AWidth, AHeight: Integer; APixelFormat: TGfxPixelFormat); virtual; + destructor Destroy; override; + procedure Lock(var AData: Pointer; var AStride: LongWord); virtual; abstract; + procedure Unlock; virtual; + procedure SetPixelsFromData(AData: Pointer; AStride: LongWord); + property Width: Integer read FWidth; + property Height: Integer read FHeight; + property PixelFormat: TGfxPixelFormat read FPixelFormat; + property Palette: TGfxPalette read FPalette write SetPalette; + end; + + { TFCustomScreen } + + TFCustomScreen = class(TObject) + public + constructor Create; virtual; + end; + + { TFCustomApplication } + + TFCustomApplication = class(TComponent) + private + FOnIdle: TNotifyEvent; + FQuitWhenLastWindowCloses: Boolean; + public + Forms: TList; + public + { Default methods } + constructor Create; virtual; + destructor Destroy; override; + procedure AddWindow(AWindow: TFCustomWindow); virtual; abstract; + procedure Initialize(ADisplayName: String = ''); virtual; abstract; + procedure Run; virtual; abstract; + procedure Quit; virtual; abstract; + { Properties } + property OnIdle: TNotifyEvent read FOnIdle write FOnIdle; + property QuitWhenLastWindowCloses: Boolean read FQuitWhenLastWindowCloses write FQuitWhenLastWindowCloses; + end; + + + { TFCustomWindow } + + // Lifetime handling + TGfxCanCloseEvent = function(Sender: TObject): Boolean of object; + // Keyboard + TGfxKeyEvent = procedure(Sender: TObject; AKey: Word; AShift: TShiftState) of object; + TGfxKeyCharEvent = procedure(Sender: TObject; AKeyChar: Char) of object; + // Mouse + TMouseButton = (mbLeft, mbRight, mbMiddle); + TGfxMouseButtonEvent = procedure(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint) of object; + TGfxMouseMoveEvent = procedure(Sender: TObject; AShift: TShiftState; const AMousePos: TPoint) of object; + TGfxMouseWheelEvent = procedure(Sender: TObject; AShift: TShiftState; AWheelDelta: Single; const AMousePos: TPoint) of object; + // Painting + TGfxPaintEvent = procedure(Sender: TObject; const ARect: TRect) of object; + + + TFCustomWindow = class + private + FCursor: TGfxCursor; + FOnCreate: TNotifyEvent; + FOnCanClose: TGfxCanCloseEvent; + FOnClose: TNotifyEvent; + FOnFocusIn: TNotifyEvent; + FOnFocusOut: TNotifyEvent; + FOnHide: TNotifyEvent; + FOnKeyPressed: TGfxKeyEvent; + FOnKeyReleased: TGfxKeyEvent; + FOnKeyChar: TGfxKeyCharEvent; + FOnMouseEnter: TGfxMouseMoveEvent; + FOnMouseLeave: TNotifyEvent; + FOnMousePressed: TGfxMouseButtonEvent; + FOnMouseReleased: TGfxMouseButtonEvent; + FOnMouseMove: TGfxMouseMoveEvent; + FOnMouseWheel: TGfxMouseWheelEvent; + FOnPaint: TGfxPaintEvent; + FOnMove: TNotifyEvent; + FOnResize: TNotifyEvent; + FOnShow: TNotifyEvent; + procedure SetWidth(AWidth: Integer); + procedure SetHeight(AHeight: Integer); + procedure SetCursor(ACursor: TGfxCursor); + procedure SetWindowOptions(const AValue: TGfxWindowOptions); virtual; + protected + FHandle: Cardinal; + FCanvas: TFCustomCanvas; + FLeft: Integer; + FTop: Integer; + FWidth: Integer; + FHeight: Integer; + FClientWidth: Integer; + FClientHeight: Integer; + FWindowOptions: TGfxWindowOptions; + function GetTitle: String; virtual; + procedure SetTitle(const ATitle: String); virtual; + procedure DoSetCursor; virtual; abstract; + public + function CanClose: Boolean; virtual; + procedure SetPosition(const APosition: TPoint); virtual; + procedure SetSize(const ASize: TSize); virtual; + procedure SetMinMaxSize(const AMinSize, AMaxSize: TSize); virtual; + procedure SetFixedSize(const ASize: TSize); + procedure SetClientSize(const ASize: TSize); virtual; + procedure SetMinMaxClientSize(const AMinSize, AMaxSize: TSize); virtual; + procedure SetFixedClientSize(const ASize: TSize); + procedure Show; virtual; abstract; + procedure Invalidate(const ARect: TRect); virtual; abstract; + procedure PaintInvalidRegion; virtual; abstract; + procedure CaptureMouse; virtual; abstract; + procedure ReleaseMouse; virtual; abstract; + + property WindowOptions: TGfxWindowOptions read FWindowOptions write SetWindowOptions; + property Canvas: TFCustomCanvas read FCanvas; + property Handle: Cardinal read FHandle; + // Window state + property Left: Integer read FLeft; + property Top: Integer read FTop; + property Width: Integer read FWidth write SetWidth; + property Height: Integer read FHeight write SetHeight; + property ClientWidth: Integer read FClientWidth; + property ClientHeight: Integer read FClientHeight; + property Cursor: TGfxCursor read FCursor write SetCursor; + property Title: String read GetTitle write SetTitle; + // Event handlers + property OnCreate: TNotifyEvent read FOnCreate write FOnCreate; + property OnCanClose: TGfxCanCloseEvent read FOnCanClose write FOnCanClose; + property OnClose: TNotifyEvent read FOnClose write FOnClose; + property OnFocusIn: TNotifyEvent read FOnFocusIn write FOnFocusIn; + property OnFocusOut: TNotifyEvent read FOnFocusOut write FOnFocusOut; + property OnHide: TNotifyEvent read FOnHide write FOnHide; + property OnKeyPressed: TGfxKeyEvent read FOnKeyPressed write FOnKeyPressed; + property OnKeyReleased: TGfxKeyEvent read FOnKeyReleased write FOnKeyReleased; + property OnKeyChar: TGfxKeyCharEvent read FOnKeyChar write FOnKeyChar; + property OnMouseEnter: TGfxMouseMoveEvent read FOnMouseEnter write FOnMouseEnter; + property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave; + property OnMousePressed: TGfxMouseButtonEvent read FOnMousePressed write FOnMousePressed; + property OnMouseReleased: TGfxMouseButtonEvent read FOnMouseReleased write FOnMouseReleased; + property OnMouseMove: TGfxMouseMoveEvent read FOnMouseMove write FOnMouseMove; + property OnMouseWheel: TGfxMouseWheelEvent read FOnMouseWheel write FOnMouseWheel; + property OnPaint: TGfxPaintEvent read FOnPaint write FOnPaint; + property OnMove: TNotifyEvent read FOnMove write FOnMove; + property OnResize: TNotifyEvent read FOnResize write FOnResize; + property OnShow: TNotifyEvent read FOnShow write FOnShow; + end; + +// Some helpers: + +// Sizes, points etc. +function Size(AWidth, AHeight: Integer): TSize; +function Size(ARect: TRect): TSize; +function PtInRect(const ARect: TRect; const APoint: TPoint): Boolean; + +{$ifdef fpc} +operator = (const ASize1, ASize2: TSize) b: Boolean; +operator + (const APoint1, APoint2: TPoint) p: TPoint; +operator + (const APoint: TPoint; ASize: TSize) p: TPoint; +operator + (const ASize: TSize; APoint: TPoint) s: TSize; +operator + (const ASize1, ASize2: TSize) s: TSize; +operator + (const APoint: TPoint; i: Integer) p: TPoint; +operator + (const ASize: TSize; i: Integer) s: TSize; +operator - (const APoint1, APoint2: TPoint) p: TPoint; +operator - (const APoint: TPoint; i: Integer) p: TPoint; +operator - (const ASize: TSize; const APoint: TPoint) s: TSize; +operator - (const ASize: TSize; i: Integer) s: TSize; + +// Colors +operator = (const AColor1, AColor2: TGfxColor) b: Boolean; +{$endif} +function GetAvgColor(const AColor1, AColor2: TGfxColor): TGfxColor; + +// Keyboard +function KeycodeToText(Key: Word; ShiftState: TShiftState): String; + + +implementation + +uses + GFXInterface; { Just to get FPC to compile the TGfxCanvas descendants } + + +{ Exceptions } + +constructor EGfxUnsupportedPixelFormat.Create(const + APixelFormat: TGfxPixelFormat); +begin + inherited CreateFmt(SUnsupportedPixelFormat, + [FormatTypeBPPTable[APixelFormat.FormatType]]); +end; + +{ TFCustomFont } + +class function TFCustomFont.GetDefaultFontName(const AFontClass: TGfxFontClass): String; +const + FontNames: array[TGfxFontClass] of String = ( + 'times', 'helvetica', 'courier', 'dingbats'); +begin + Result := FontNames[AFontClass]; +end; + +{ TGfxPalette } + +destructor TGfxPalette.Destroy; +begin + if Assigned(FEntries) then + FreeMem(FEntries); + inherited Destroy; +end; + +procedure TGfxPalette.AddRef; +begin + Inc(FRefCount); +end; + +procedure TGfxPalette.Release; +begin + if FRefCount <= 0 then + Free + else + Dec(FRefCount); +end; + +constructor TGfxPalette.Create(AEntryCount: Integer; AEntries: PGfxColor); +begin + inherited Create; + FEntryCount := AEntryCount; + GetMem(FEntries, EntryCount * SizeOf(TGfxColor)); + if Assigned(AEntries) then + Move(AEntries^, FEntries^, EntryCount * SizeOf(TGfxColor)); +end; + +function TGfxPalette.GetEntry(AIndex: Integer): TGfxColor; +begin + if (AIndex >= 0) and (AIndex < EntryCount) then + Result := FEntries[AIndex] + else + Result := colBlack; +end; + + +{ TFCustomCanvas } + +constructor TFCustomCanvas.Create; +begin + inherited Create; + Matrix := GfxIdentityMatrix; +end; + +function TFCustomCanvas.Transform(APoint: TPoint): TPoint; +begin + Result.x := Matrix._00 * APoint.x + Matrix._20; + Result.y := Matrix._11 * APoint.y + Matrix._21; +end; + +function TFCustomCanvas.Transform(ARect: TRect): TRect; +begin + Result.Left := Matrix._00 * ARect.Left + Matrix._20; + Result.Top := Matrix._11 * ARect.Top + Matrix._21; + Result.Right := Matrix._00 * ARect.Right + Matrix._20; + Result.Bottom := Matrix._11 * ARect.Bottom + Matrix._21; +end; + +function TFCustomCanvas.ReverseTransform(APoint: TPoint): TPoint; +begin + Result.x := (APoint.x - Matrix._20) div Matrix._00; + Result.y := (APoint.y - Matrix._21) div Matrix._11; +end; + +function TFCustomCanvas.ReverseTransform(ARect: TRect): TRect; +begin + Result.Left := (ARect.Left - Matrix._20) div Matrix._00; + Result.Top := (ARect.Top - Matrix._21) div Matrix._11; + Result.Right := (ARect.Right - Matrix._20) div Matrix._00; + Result.Bottom := (ARect.Bottom - Matrix._21) div Matrix._11; +end; + +procedure TFCustomCanvas.AppendTranslation(ADelta: TPoint); +begin + // Append a translation to the existing transformation matrix + Inc(FMatrix._20, FMatrix._00 * ADelta.x); + Inc(FMatrix._21, FMatrix._11 * ADelta.y); +end; + +procedure TFCustomCanvas.EmptyClipRect; +begin + IntersectClipRect(Rect(0, 0, 0, 0)); +end; + +function TFCustomCanvas.ExcludeClipRect(const ARect: TRect): Boolean; +var + Rect: TRect; +begin + Rect := Transform(ARect); + if (Rect.Right > Rect.Left) and (Rect.Bottom > Rect.Top) then + Result := DoExcludeClipRect(Rect) + else + Result := False; +end; + +function TFCustomCanvas.IntersectClipRect(const ARect: TRect): Boolean; +var + Rect: TRect; +begin + Rect := Transform(ARect); + if (Rect.Right > Rect.Left) and (Rect.Bottom > Rect.Top) then + Result := DoIntersectClipRect(Rect) + else + Result := False; +end; + +function TFCustomCanvas.UnionClipRect(const ARect: TRect): Boolean; +var + Rect: TRect; +begin + Rect := Transform(ARect); + if (Rect.Right > Rect.Left) and (Rect.Bottom > Rect.Top) then + Result := DoUnionClipRect(Rect) + else + with GetClipRect do + Result := (Right > Left) and (Bottom > Top); +end; + +function TFCustomCanvas.GetClipRect: TRect; +begin + Result := ReverseTransform(DoGetClipRect); +end; + +procedure TFCustomCanvas.SetColor(AColor: TGfxColor); +begin + SetColor_(MapColor(AColor)); +end; + +procedure TFCustomCanvas.DrawArc(const ARect: TRect; StartAngle, EndAngle: Single); +begin + DoDrawArc(Transform(ARect), StartAngle, EndAngle); +end; + +procedure TFCustomCanvas.DrawCircle(const ARect: TRect); +begin + DoDrawCircle(Transform(ARect)); +end; + +procedure TFCustomCanvas.DrawLine(const AFrom, ATo: TPoint); +begin + DoDrawLine(Transform(AFrom), Transform(ATo)); +end; + +procedure TFCustomCanvas.DrawPolyLine(const Coords: array of TPoint); +var + i: Integer; +begin + for i := Low(Coords) to High(Coords) do + DrawLine(Coords[i], Coords[i + 1]); +end; + +procedure TFCustomCanvas.DoDrawRect(const ARect: TRect); +begin +{ DrawPolyLine( + [ARect.TopLeft, + Point(ARect.Right - 1, ARect.Top), + Point(ARect.Right - 1, ARect.Bottom - 1), + Point(ARect.Left, ARect.Bottom - 1), + ARect.TopLeft]);} + DoDrawLine(ARect.TopLeft, Point(ARect.Right - 1, ARect.Top)); + DoDrawLine(Point(ARect.Right - 1, ARect.Top), Point(ARect.Right - 1, ARect.Bottom - 1)); + DoDrawLine(Point(ARect.Right - 1, ARect.Bottom - 1), Point(ARect.Left, ARect.Bottom - 1)); + DoDrawLine(Point(ARect.Left, ARect.Bottom - 1), ARect.TopLeft); +end; + +procedure TFCustomCanvas.DrawRect(const ARect: TRect); +var + r: TRect; +begin + r := Transform(ARect); + if (r.Right > r.Left) and (r.Bottom > r.Top) then + DoDrawRect(r); +end; + +procedure TFCustomCanvas.DrawPoint(const APoint: TPoint); +begin + DoDrawPoint(Transform(APoint)); +end; + +procedure TFCustomCanvas.FillRect(const ARect: TRect); +var + r: TRect; +begin + r := Transform(ARect); + if (r.Right > r.Left) and (r.Bottom > r.Top) then + DoFillRect(r); +end; + +function TFCustomCanvas.TextExtent(const AText: String): TSize; +begin + Result.cx := TextWidth(AText); + Result.cy := FontCellHeight; +end; + +function TFCustomCanvas.TextWidth(const AText: String): Integer; +begin + Result := TextExtent(AText).cx; +end; + +procedure TFCustomCanvas.TextOut(const APosition: TPoint; const AText: String); +begin + DoTextOut(Transform(APosition), AText); +end; + +procedure TFCustomCanvas.Copy(ASource: TFCustomCanvas; const ADestPos: TPoint); +begin + ASSERT(Assigned(ASource)); + CopyRect(ASource, Rect(0, 0, ASource.Width, ASource.Height), ADestPos); +end; + +procedure TFCustomCanvas.CopyRect(ASource: TFCustomCanvas; const ASourceRect: TRect; + const ADestPos: TPoint); +var + SourceRect: TRect; +begin + SourceRect := ASource.Transform(ASourceRect); + with SourceRect do + if (Left >= Right) or (Top >= Bottom) then + exit; + + DoCopyRect(ASource, SourceRect, Transform(ADestPos)); +end; + +procedure TFCustomCanvas.MaskedCopy(ASource, AMask: TFCustomCanvas; + const ADestPos: TPoint); +begin + MaskedCopyRect(ASource, AMask, Rect(0, 0, ASource.Width, ASource.Height), + Point(0, 0), ADestPos); +end; + +procedure TFCustomCanvas.MaskedCopyRect(ASource, AMask: TFCustomCanvas; + const ASourceRect: TRect; const AMaskPos, ADestPos: TPoint); +begin + DoMaskedCopyRect(ASource, AMask, ASource.Transform(ASourceRect), + AMask.Transform(AMaskPos), Transform(ADestPos)); +end; + +procedure TFCustomCanvas.DrawImage(AImage: TFCustomImage; const ADestPos: TPoint); +begin + DrawImageRect(AImage, Rect(0, 0, AImage.Width, AImage.Height), ADestPos); +end; + +procedure TFCustomCanvas.DrawImageRect(AImage: TFCustomImage; ASourceRect: TRect; + const ADestPos: TPoint); +var + SourceRect: TRect; +begin + SourceRect := ASourceRect; +{ if SourceRect.Right > Width then + SourceRect.Right := Width; + if SourceRect.Bottom > Height then + SourceRect.Bottom := Height;} + + if (SourceRect.Right > SourceRect.Left) and + (SourceRect.Bottom > SourceRect.Top) then + DoDrawImageRect(AImage, ASourceRect, Transform(ADestPos)); +end; + +{ TFCustomImage } + +destructor TFCustomImage.Destroy; +begin + if Assigned(Palette) then + Palette.Release; + inherited Destroy; +end; + +procedure TFCustomImage.Unlock; +begin + // Default implementation: Do nothing... +end; + +procedure TFCustomImage.SetPixelsFromData(AData: Pointer; AStride: LongWord); +var + DestData: Pointer; + DestStride, BytesPerScanline: LongWord; + y: Integer; +begin + DestStride := 0; // to remove compiler warning + DestData := nil; + if Height <= 0 then + exit; + + Lock(DestData, DestStride); + try + if DestStride = AStride then + Move(AData^, DestData^, AStride * Height) + else + begin + if DestStride > AStride then + BytesPerScanline := AStride + else + BytesPerScanline := DestStride; + + y := 0; + while True do + begin + Move(AData^, DestData^, BytesPerScanline); + Inc(y); + if y = Height then + break; + Inc(AData, AStride); + Inc(DestData, DestStride); + end; + end; + finally + Unlock; + end; +end; + +constructor TFCustomImage.Create(AWidth, AHeight: Integer; + APixelFormat: TGfxPixelFormat); +begin + FWidth := AWidth; + FHeight := AHeight; + FPixelFormat := APixelFormat; +end; + +procedure TFCustomImage.SetPalette(APalette: TGfxPalette); +begin + if APalette <> Palette then + begin + if Assigned(Palette) then + Palette.Release; + + FPalette := APalette; + + if Assigned(Palette) then + Palette.AddRef; + end; +end; + +{ TFCustomScreen } + +constructor TFCustomScreen.Create; +begin + inherited Create; + +end; + +{ TFCustomWindow } + +function TFCustomWindow.CanClose: Boolean; +begin + if Assigned(OnCanClose) then + Result := OnCanClose(Self) + else + Result := True; +end; + +procedure TFCustomWindow.SetPosition(const APosition: TPoint); +begin + // Empty +end; + +procedure TFCustomWindow.SetSize(const ASize: TSize); +begin + // Empty +end; + +procedure TFCustomWindow.SetMinMaxSize(const AMinSize, AMaxSize: TSize); +begin + // Empty +end; + +procedure TFCustomWindow.SetFixedSize(const ASize: TSize); +begin + SetMinMaxSize(ASize, ASize); + SetSize(ASize); +end; + +procedure TFCustomWindow.SetClientSize(const ASize: TSize); +begin + // Empty +end; + +procedure TFCustomWindow.SetMinMaxClientSize(const AMinSize, AMaxSize: TSize); +begin + // Empty +end; + +procedure TFCustomWindow.SetFixedClientSize(const ASize: TSize); +begin + SetMinMaxClientSize(ASize, ASize); + SetClientSize(ASize); +end; + +function TFCustomWindow.GetTitle: String; +begin + SetLength(Result, 0); +end; + +procedure TFCustomWindow.SetTitle(const ATitle: String); +begin + // Empty +end; + +procedure TFCustomWindow.SetWidth(AWidth: Integer); +begin + SetSize(Size(AWidth, Height)); +end; + +procedure TFCustomWindow.SetHeight(AHeight: Integer); +begin + SetSize(Size(Width, AHeight)); +end; + +procedure TFCustomWindow.SetCursor(ACursor: TGfxCursor); +begin + if ACursor <> Cursor then + begin + FCursor := ACursor; + DoSetCursor; + end; +end; + +procedure TFCustomWindow.SetWindowOptions(const AValue: TGfxWindowOptions); +begin + if FWindowOptions=AValue then exit; + FWindowOptions:=AValue; +end; + +// =================================================================== +// Global functions +// =================================================================== + +// Sizes, points etc. +function Size(AWidth, AHeight: Integer): TSize; +begin + Result.cx := AWidth; + Result.cy := AHeight; +end; + +function Size(ARect: TRect): TSize; +begin + Result.cx := ARect.Right - ARect.Left; + Result.cy := ARect.Bottom - ARect.Top; +end; + +function PtInRect(const ARect: TRect; const APoint: TPoint): Boolean; +begin + with ARect, APoint do + Result := (x >= Left) and (y >= Top) and (x < Right) and (y < Bottom); +end; + +{$ifdef fpc} + +operator = (const ASize1, ASize2: TSize) b: Boolean; +begin + b := (ASize1.cx = ASize2.cx) and (ASize1.cy = ASize2.cy); +end; + +operator + (const APoint1, APoint2: TPoint) p: TPoint; +begin + p.x := APoint1.x + APoint2.x; + p.y := APoint1.y + APoint2.y; +end; + +operator + (const APoint: TPoint; ASize: TSize) p: TPoint; +begin + p.x := APoint.x + ASize.cx; + p.y := APoint.y + ASize.cy; +end; + +operator + (const ASize: TSize; APoint: TPoint) s: TSize; +begin + s.cx := ASize.cx + APoint.x; + s.cy := ASize.cy + APoint.y; +end; + +operator + (const ASize1, ASize2: TSize) s: TSize; +begin + s.cx := ASize1.cx + ASize2.cx; + s.cy := ASize1.cy + ASize2.cy; +end; + +operator + (const APoint: TPoint; i: Integer) p: TPoint; +begin + p.x := APoint.x + i; + p.y := APoint.y + i; +end; + +operator + (const ASize: TSize; i: Integer) s: TSize; +begin + s.cx := ASize.cx + i; + s.cy := ASize.cy + i; +end; + +operator - (const APoint1, APoint2: TPoint) p: TPoint; +begin + p.x := APoint1.x - APoint2.x; + p.y := APoint1.y - APoint2.y; +end; + +operator - (const APoint: TPoint; i: Integer) p: TPoint; +begin + p.x := APoint.x - i; + p.y := APoint.y - i; +end; + +operator - (const ASize: TSize; const APoint: TPoint) s: TSize; +begin + s.cx := ASize.cx - APoint.x; + s.cy := ASize.cy - APoint.y; +end; + +operator - (const ASize: TSize; i: Integer) s: TSize; +begin + s.cx := ASize.cx - i; + s.cy := ASize.cy - i; +end; + + +// Color functions +operator = (const AColor1, AColor2: TGfxColor) b: Boolean; +begin + b := (AColor1.Red = AColor2.Red) and (AColor1.Green = AColor2.Green) and + (AColor1.Blue = AColor2.Blue) and (AColor1.Alpha = AColor2.Alpha); +end; +{$endif} + +function GetAvgColor(const AColor1, AColor2: TGfxColor): TGfxColor; +begin + Result.Red := AColor1.Red + (AColor2.Red - AColor1.Red) div 2; + Result.Green := AColor1.Green + (AColor2.Green - AColor1.Green) div 2; + Result.Blue := AColor1.Blue + (AColor2.Blue - AColor1.Blue) div 2; + Result.Alpha := AColor1.Alpha + (AColor2.Alpha - AColor1.Alpha) div 2; +end; + +// Keyboard functions +function KeycodeToText(Key: Word; ShiftState: TShiftState): String; + + function GetASCIIText: String; + var + c: Char; + begin + result := ''; + c := Chr(Key and $ff); + case c of + #13: Result := Result + 'Enter'; + #127: Result := Result + 'Del'; + '+': Result := Result + 'Plus' + else + Result := Result + c; + end; + end; + +var + s: String; +begin + SetLength(Result, 0); + + if ssShift in ShiftState then + Result := 'Shift+'; + if ssCtrl in ShiftState then + Result := 'Ctrl+'; + if ssAlt in ShiftState then + Result := 'Alt+'; + + if (Key > Ord(' ')) and (Key < 255) then + begin + Result := Result + GetASCIIText; + exit; + end; + + case Key of + keyNul: s := 'Null'; + keyBackSpace: s := 'Backspace'; + keyTab: s := 'Tab'; + keyLinefeed: s := 'Linefeed'; + keyReturn: s := 'Enter'; + keyEscape: s := 'Esc'; + Ord(' '): s := 'Space'; + keyDelete: s := 'Del'; + keyVoid: s := 'Void'; + keyBreak: s := 'Break'; + keyScrollForw: s := 'ScrollForw'; + keyScrollBack: s := 'ScrollBack'; + keyBoot: s := 'Boot'; + keyCompose: s := 'Compose'; + keySAK: s := 'SAK'; + keyUndo: s := 'Undo'; + keyRedo: s := 'Redo'; + keyMenu: s := 'Menu'; + keyCancel: s := 'Cancel'; + keyPrintScreen: s := 'PrtScr'; + keyExecute: s := 'Exec'; + keyFind: s := 'Find'; + keyBegin: s := 'Begin'; + keyClear: s := 'Clear'; + keyInsert: s := 'Ins'; + keySelect: s := 'Select'; + keyMacro: s := 'Macro'; + keyHelp: s := 'Help'; + keyDo: s := 'Do'; + keyPause: s := 'Pause'; + keySysRq: s := 'SysRq'; + keyModeSwitch: s := 'ModeSw'; + keyUp: s := 'Up'; + keyDown: s := 'Down'; + keyLeft: s := 'Left'; + keyRight: s := 'Right'; + keyPrior: s := 'PgUp'; + keyNext: s := 'PgDown'; + keyHome: s := 'Home'; + keyEnd: s := 'End'; + keyF0..keyF64: s := 'F' + IntToStr(Key - keyF0); + keyP0..keyP9: s := 'KP' + Chr(Key - keyP0 + Ord('0')); + keyPA..keyPF: s := 'KP' + Chr(Key - keyPA + Ord('A')); + keyPPlus, keyPMinus, keyPSlash, keyPStar, keyPEqual, keyPSeparator, + keyPDecimal, keyPParenLeft, keyPParenRight, keyPSpace, keyPEnter, + keyPTab: s := 'KP' + GetASCIIText; + keyPPlusMinus: s := 'KPPlusMinus'; + keyPBegin: s := 'KPBegin'; + keyPF1..keyPF9: s := 'KPF' + IntToStr(Key - keyPF1); + keyShiftL: s := 'ShiftL'; + keyShiftR: s := 'ShiftR'; + keyCtrlL: s := 'CtrlL'; + keyCtrlR: s := 'CtrlR'; + keyAltL: s := 'AltL'; + keyAltR: s := 'AltR'; + keyMetaL: s := 'MetaL'; + keyMetaR: s := 'MetaR'; + keySuperL: s := 'SuperL'; + keySuperR: s := 'SuperR'; + keyHyperL: s := 'HyperL'; + keyHyperR: s := 'HyperR'; + keyAltGr: s := 'AltGr'; + keyCaps: s := 'Caps'; + keyNum: s := 'Num'; + keyScroll: s := 'Scroll'; + keyShiftLock: s := 'ShiftLock'; + keyCtrlLock: s := 'CtrlLock'; + keyAltLock: s := 'AltLock'; + keyMetaLock: s := 'MetaLock'; + keySuperLock: s := 'SuperLock'; + keyHyperLock: s := 'HyperLock'; + keyAltGrLock: s := 'AltGrLock'; + keyCapsLock: s := 'CapsLock'; + keyNumLock: s := 'NumLock'; + keyScrollLock: s := 'ScrollLock'; + keyDeadRing: s := 'DeadRing'; + keyDeadCaron: s := 'DeadCaron'; + keyDeadOgonek: s := 'DeadOgonek'; + keyDeadIota: s := 'DeadIota'; + keyDeadDoubleAcute: s := 'DeadDoubleAcute'; + keyDeadBreve: s := 'DeadBreve'; + keyDeadAboveDot: s := 'DeadAboveDot'; + keyDeadBelowDot: s := 'DeadBelowDot'; + keyDeadVoicedSound: s := 'DeadVoicedSound'; + keyDeadSemiVoicedSound: s := 'DeadSemiVoicedSound'; + keyDeadAcute: s := 'DeadAcute'; + keyDeadCedilla: s := 'DeadCedilla'; + keyDeadCircumflex: s := 'DeadCircumflex'; + keyDeadDiaeresis: s := 'DeadDiaeresis'; + keyDeadGrave: s := 'DeadGrave'; + keyDeadTilde: s := 'DeadTilde'; + keyDeadMacron: s := 'DeadMacron'; + + keyEcuSign: s := 'Ecu'; + keyColonSign: s := 'Colon'; + keyCruzeiroSign: s := 'Cruzeiro'; + keyFFrancSign: s := 'FFranc'; + keyLiraSign: s := 'Lira'; + keyMillSign: s := 'Mill'; + keyNairaSign: s := 'Naira'; + keyPesetaSign: s := 'Peseta'; + keyRupeeSign: s := 'Rupee'; + keyWonSign: s := 'Won'; + keyNewSheqelSign: s := 'NewShequel'; + keyDongSign: s := 'Dong'; + keyEuroSign: s := 'Euro'; + else + s := '#' + IntToHex(Key, 4); + end; + Result := Result + s; +end; + +{ TFCustomApplication } + +constructor TFCustomApplication.Create; +begin + inherited Create(nil); + + Forms := TList.Create; + + FQuitWhenLastWindowCloses := True; +end; + +destructor TFCustomApplication.Destroy; +begin + Forms.Free; + + inherited Destroy; +end; + +end. + |