{ @abstract(This unit contains advanced graphic functions used by KControls suite.)
@author(Tomas Krysl (tk@tkweb.eu))
@created(5 May 2004)
@lastmod(20 Jun 2010)
Copyright © 2004 Tomas Krysl (tk@@tkweb.eu)
License:
This code is distributed as a freeware. You are free to use it as part
of your application for any purpose including freeware, commercial and
shareware applications. The origin of this source code must not be
misrepresented; you must not claim your authorship. You may modify this code
solely for your own purpose. Please feel free to contact the author if you
think your changes might be useful for other users. You may distribute only
the original package. The author accepts no liability for any damage
that may result from using this code. }
unit KGraphics;
{$include kcontrols.inc}
{$WEAKPACKAGEUNIT ON}
interface
uses
{$IFDEF FPC}
// use the LCL interface support whenever possible
{$IFDEF USE_WINAPI}
Windows,
{$ENDIF}
GraphType, IntfGraphics, LCLType, LCLIntf, LMessages, LResources,
{$ELSE}
Windows, Messages,
{$IFDEF USE_PNG_SUPPORT}
PngImage,
{$ENDIF}
{$ENDIF}
Classes, Forms, Graphics, Controls, KFunctions;
resourcestring
{ @exclude }
SGDIError = 'GDI object could not be created.';
const
{ PNG Support }
PNGHeader = #137'PNG'#13#10#26#10;
MNGHeader = #138'MNG'#13#10#26#10;
type
{ Declares possible values for the Style parameter of the @link(BrightColor) function. }
TKBrightMode = (
{ The Color will be brightened with Percent of its entire luminosity range. }
bsAbsolute,
{ The Color will be brightened with Percent of its current luminosity value. }
bsOfBottom,
{ The Color will be brightened with Percent of the difference of its entire
luminosity range and current luminosity value. }
bsOfTop
);
{ Declares RGB + Alpha channel color description allowing both to
access single channels and the whole color item. }
TKColorRec = packed record
case Integer of
0: (R, G, B, A: Byte);
1: (Value: Cardinal);
end;
{ Pointer to TKColorRec. }
PKColorRec = ^TKColorRec;
{ Dynamic array for TKColorRec. }
TKColorRecs = array[0..MaxInt div SizeOf(TKColorRec) - 1] of TKColorRec;
{ Dynamic array for TKColorRecs. }
PKColorRecs = ^TKColorRecs;
{ Dynamic array for TKColorRec. }
TKDynColorRecs = array of TKColorRec;
{ String type for @link(ImageByType) function. }
TKImageHeaderString = string[10];
{$IFDEF USE_PNG_SUPPORT}
{$IFDEF FPC}
{ @exclude }
TKPngImage = TPortableNetworkGraphic;
{$ELSE}
{$IFDEF COMPILER12_UP}
{ @exclude }
TKPngImage = TPngImage;
{$ELSE}
{ @exclude }
TKPngImage = TPngObject;
{$ENDIF}
{$ENDIF}
{$ENDIF}
{ Declares possible values for the Attributes parameter in the @link(DrawAlignedText) function. }
TKTextAttribute = (
{ Bounding rectangle is calculated. No text is drawn. }
taCalcRect,
{ Text will be clipped within the given rectangle. }
taClip,
{ Text will be drawn with end ellipsis if it does not fit within given width. }
taEndEllipsis,
{ Given rectangle will be filled. }
taFillRect,
{ Only yhe text within given rectangle will be filled. }
taFillText,
{ Text will be drawn as multi-line text if it contains carriage returns and line feeds. }
taLineBreak,
{ Text will be drawn with path ellipsis if it does not fit within given width. }
taPathEllipsis,
{ Text line(s) will be broken between words if they don't fit within given width. }
taWordBreak,
{ Text line(s) will be broken if they don't fit within col width. }
taWrapText, //JR:20091229
{ No white spaces will be trimmed at the beginning or end of text lines. }
taTrimWhiteSpaces
);
{ Set type for @link(TKTextAttribute) enumeration. }
TKTextAttributes = set of TKTextAttribute;
{ Declares possible values for the HAlign parameter in the @link(DrawAlignedText) function. }
TKHAlign = (
{ Text is aligned to the left border of a cell rectangle. }
halLeft,
{ Text is horizontally centered within the cell rectangle. }
halCenter,
{ Text is aligned to the right border of a cell rectangle. }
halRight
);
{ Declares possible values for the StretchMode parameter in the @link(ExcludeShapeFromBaseRect) function. }
TKStretchMode = (
{ Shape is not stretched. }
stmNone,
{ Shape is zoomed out. }
stmZoomOutOnly,
{ Shape is zoomed in. }
stmZoomInOnly,
{ Shape is zoomed arbitrary. }
stmZoom
);
{ For backward compatibility. }
TKTextHAlign = TKHAlign;
{ Declares possible values for the VAlign parameter in the @link(DrawAlignedText) function. }
TKVAlign = (
{ Text is aligned to the upper border of a cell rectangle. }
valTop,
{ Text is vertically centered within the cell rectangle. }
valCenter,
{ Text is aligned to the lower border of a cell rectangle. }
valBottom
);
{ For backward compatibility. }
TKTextVAlign = TKVAlign;
{ A simple platform independent encapsulation for a 32bpp bitmap with
alpha channel with the ability to modify it's pixels directly. }
TKAlphaBitmap = class(TGraphic)
private
FCanvas: TCanvas;
FDirectCopy: Boolean;
FHandle: HBITMAP;
FHeight: Integer;
{$IFNDEF USE_WINAPI}
FImage: TLazIntfImage; // Lazarus only
FMaskHandle: HBITMAP;
{$ENDIF}
FOldBitmap: HBITMAP;
FPixels: PKColorRecs;
FPixelsChanged: Boolean;
FWidth: Integer;
function GetScanLine(Index: Integer): PKColorRecs;
function GetHandle: HBITMAP;
function GetPixel(X, Y: Integer): TKColorRec;
procedure SetPixel(X, Y: Integer; Value: TKColorRec);
protected
{ Paints itself to ACanvas at location ARect. }
procedure Draw(ACanvas: TCanvas; const ARect: TRect); override;
{ Returns True if bitmap is empty. }
function GetEmpty: Boolean; override;
{ Returns the bitmap height. }
function GetHeight: Integer; override;
{ Returns True. Treat alpha bitmap as transparent because of the
possible alpha channel. }
function GetTransparent: Boolean; override;
{ Returns the bitmap width. }
function GetWidth: Integer; override;
{ Specifies new bitmap height. }
procedure SetHeight(Value: Integer); override;
{ Specifies new bitmap width. }
procedure SetWidth(Value: Integer); override;
{ Does nothing. Bitmap is never transparent. }
procedure SetTransparent(Value: Boolean); override;
{ Updates the bitmap handle from bitmap pixels. }
procedure UpdateHandle; dynamic;
{ Updates the pixels from bitmap handle. }
procedure UpdatePixels; dynamic;
public
{ Creates the instance. }
constructor Create; override;
{ Creates the instance from application resources. For Lazarus 'BMP' type is
taken, for Delphi RT_RCDATA is taken. }
constructor CreateFromRes(const ResName: string);
{ Destroys the instance. }
destructor Destroy; override;
{ Paints alpha bitmap onto Canvas at position given by X, Y. The alpha bitmap
is combined with the background already drawn on Canvas using alpha channel
stored in the alpha bitmap. }
procedure AlphaDrawTo(ACanvas: TCanvas; X, Y: Integer);
{ Paints alpha bitmap onto Canvas at position given by ARect. The alpha bitmap
is combined with the background already drawn on Canvas using alpha channel
stored in the alpha bitmap. }
procedure AlphaStretchDrawTo(ACanvas: TCanvas; const ARect: TRect);
{ Fills the alpha channel with Alpha. If the optional IfEmpty parameter is True,
the alpha channel won't be modified unless it has zero value for all pixels. }
procedure AlphaFill(Alpha: Byte; IfEmpty: Boolean = False); overload;
{ Fills the alpha channel according to given parameters. Currently it is used
internally by @link(TKDragWindow). }
procedure AlphaFill(Alpha: Byte; BlendColor: TColor; Gradient, Translucent: Boolean); overload;
{ Combines the pixel at given location with the given color. }
procedure CombinePixel(X, Y: Integer; Color: TKColorRec);
{ Takes dimensions and pixels from ABitmap. }
procedure CopyFrom(ABitmap: TKAlphaBitmap);
{ Takes 90°-rotated dimensions and pixels from ABitmap. }
procedure CopyFromRotated(ABitmap: TKAlphaBitmap);
{ Copies a location specified by ARect from ACanvas to bitmap. }
procedure DrawFrom(ACanvas: TCanvas; const ARect: TRect);
{ Calls @link(TKAlphaBitmap.Draw). }
procedure DrawTo(ACanvas: TCanvas; const ARect: TRect);
{$IFNDEF FPC}
{ Does nothing. }
procedure LoadFromClipboardFormat(AFormat: Word; AData: THandle;
APalette: HPALETTE); override;
{$ENDIF}
{ Loads the bitmap from a stream. }
procedure LoadFromStream(Stream: TStream); override;
{ Mirrors the bitmap pixels horizontally. }
procedure MirrorHorz;
{ Mirrors the bitmap pixels vertically. }
procedure MirrorVert;
{$IFNDEF FPC}
{ Does nothing. }
procedure SaveToClipboardFormat(var AFormat: Word; var AData: THandle;
var APalette: HPALETTE); override;
{$ENDIF}
{ Saves the bitmap to a stream. }
procedure SaveToStream(Stream: TStream); override;
{ Specifies the bitmap size. }
procedure SetSize(AWidth, AHeight: Integer); {$IFNDEF FPC} reintroduce;{$ENDIF}
{ Returns the bitmap memory canvas. }
property Canvas: TCanvas read FCanvas;
{ Temporary flag. Use when copying data directly from another TGraphic to TKAlphaBitmap. }
property DirectCopy: Boolean read FDirectCopy write FDirectCopy;
{ Returns the bitmap handle. }
property Handle: HBITMAP read GetHandle;
{ Specifies the pixel color. Does range checking. }
property Pixel[X, Y: Integer]: TKColorRec read GetPixel write SetPixel;
{ Returns the pointer to bitmap pixels. }
property Pixels: PKColorRecs read FPixels;
{ Set this property to True if you have modified the bitmap pixels. }
property PixelsChanged: Boolean read FPixelsChanged write FPixelsChanged;
{ Returns the pointer to a bitmap scan line. }
property ScanLine[Index: Integer]: PKColorRecs read GetScanLine;
end;
{$IFDEF USE_WINAPI}
TUpdateLayeredWindowProc = function(Handle: THandle; hdcDest: HDC; pptDst: PPoint;
_psize: PSize; hdcSrc: HDC; pptSrc: PPoint; crKey: COLORREF; pblend: PBLENDFUNCTION;
dwFlags: DWORD): Boolean; stdcall;
{$ENDIF}
{ @abstract(Encapsulates the drag window)
Drag window is top level window used for dragging with mouse. It displays
some portion of associated control. It can be translucent under Windows. }
TKDragWindow = class(TObject)
private
FActive: Boolean;
FAlphaEffects: Boolean;
FBitmap: TKAlphaBitmap;
FBitmapFilled: Boolean;
FControl: TCustomControl;
FGradient: Boolean;
FInitialPos: TPoint;
FLayered: Boolean;
FMasterAlpha: Byte;
{$IFDEF USE_WINAPI}
FBlend: TBlendFunction;
FUpdateLayeredWindow: TUpdateLayeredWindowProc;
FWindow: HWND;
{$ELSE}
FDragForm: TCustomForm;
{$ENDIF}
public
{ Creates the instance. }
constructor Create;
{ Destroys the instance. }
destructor Destroy; override;
{ Shows the drag window on screen. Takes a rectangular part as set by ARect from
IniCtrl's Canvas and displays it at position InitialPos. MasterAlpha and
Gradient are used to premaster the copied image with a specific fading effect. }
procedure Show(IniCtrl: TCustomControl; const ARect: TRect; const InitialPos,
CurrentPos: TPoint; MasterAlpha: Byte; Gradient: Boolean);
{ Moves the drag window to a new location. }
procedure Move(const NewPos: TPoint);
{ Hides the drag window. }
procedure Hide;
{ Returns True if the drag window is shown. }
property Active: Boolean read FActive;
{ Returns the pointer to the bitmap that holds the copied control image. }
property Bitmap: TKAlphaBitmap read FBitmap;
{ Returns True if the control already copied itself to the bitmap. }
property BitmapFilled: Boolean read FBitmapFilled;
end;
{ @abstract(Base class for KControls hints)
This class extends the standard THintWindow class. It adds functionality
common to all hints used in KControls. }
TKHintWindow = class(THintWindow)
private
FExtent: TPoint;
procedure WMEraseBkGnd(var Msg: TLMessage); message LM_ERASEBKGND;
public
{ Creates the instance. }
constructor Create(AOwner: TComponent); override;
{ Shows the hint at given position. This is an IDE independent implementation. }
procedure ShowAt(const Origin: TPoint);
{ Returns the extent of the hint. }
property Extent: TPoint read FExtent;
end;
{ @abstract(Hint window to display formatted text)
This class implements the textual hint window. The text is displayed . }
TKTextHint = class(TKHintWindow)
private
FText: {$IFDEF STRING_IS_UNICODE}string{$ELSE}WideString{$ENDIF};
procedure SetText(const Value: {$IFDEF STRING_IS_UNICODE}string{$ELSE}WideString{$ENDIF});
protected
{ Overriden method. Paints the hint. }
procedure Paint; override;
public
{ Creates the instance. }
constructor Create(AOwner: TComponent); override;
{ }
property Text: {$IFDEF STRING_IS_UNICODE}string{$ELSE}WideString{$ENDIF} read FText write SetText;
end;
TKGraphicHint = class(TKHintWindow)
private
FGraphic: TGraphic;
procedure SetGraphic(const Value: TGraphic);
protected
{ Overriden method. Paints the hint. }
procedure Paint; override;
public
constructor Create(AOwner: TComponent); override;
property Graphic: TGraphic read FGraphic write SetGraphic;
end;
{ Draws Src to Dest with per pixel weighting by alpha channel saved in Src. }
procedure BlendLine(Src, Dest: PKColorRecs; Count: Integer);
{ Calculates a brighter color of given color based on the HSL color space.