📄 syntextdrawer.pas
字号:
{==============================================================================
Content: TheTextDrawer, a helper class for drawing of
fixed-pitched font characters
==============================================================================
The contents of this file are subject to the Mozilla Public License Ver. 1.0
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
the specific language governing rights and limitations under the License.
==============================================================================
The Original Code is HANAI Tohru's private delphi library.
==============================================================================
The Initial Developer of the Original Code is HANAI Tohru (Japan)
Portions created by HANAI Tohru are Copyright (C) 1999.
All Rights Reserved.
==============================================================================
Contributor(s): HANAI Tohru
==============================================================================
History: 01/19/1999 HANAI Tohru
Initial Version
02/13/1999 HANAI Tohru
Changed default intercharacter spacing
09/09/1999 HANAI Tohru
Redesigned all. Simplified interfaces.
When drawing text now it uses TextOut + SetTextCharacter-
Extra insted ExtTextOut since ExtTextOut has a little
heavy behavior.
09/10/1999 HANAI Tohru
Added code to call ExtTextOut because there is a problem
when TextOut called with italicized raster type font.
After this changing, ExtTextOut is called without the
last parameter `lpDx' and be with SetTextCharacterExtra.
This pair performs faster than with `lpDx'.
09/14/1999 HANAI Tohru
Changed code for saving/restoring DC
09/15/1999 HANAI Tohru
Added X/Y parameters to ExtTextOut.
09/16/1999 HANAI Tohru
Redesigned for multi-bytes character drawing.
09/19/1999 HANAI Tohru
Since TheTextDrawer grew fat it was split into three
classes - TheFontStock, TheTextDrawer and TheTextDrawerEx.
Currently it should avoid TheTextDrawer because it is
slower than TheTextDrawer.
09/25/1999 HANAI Tohru
Added internally definition of LeadBytes for Delphi 2
10/01/1999 HANAI Tohru
To save font resources, now all fonts data are shared
among all of TheFontStock instances. With this changing,
there added a new class `TheFontsInfoManager' to manage
those shared data.
10/09/1999 HANAI Tohru
Added BaseStyle property to TheFontFont class.
==============================================================================}
// $Id: SynTextDrawer.pas,v 1.6 2003/09/19 21:32:48 etrusco Exp $
// SynEdit note: The name had to be changed to get SynEdit to install
// together with mwEdit into the same Delphi installation
unit SynTextDrawer;
{$I SynEdit.inc}
interface
uses
SysUtils,
Classes,
Windows,
Graphics;
const
FontStyleCount = Ord(High(TFontStyle)) +1;
FontStyleCombineCount = (1 shl FontStyleCount);
type
TheStockFontPatterns = 0..FontStyleCombineCount -1;
PheFontData = ^TheFontData;
TheFontData = record
Style: TFontStyles;
Handle: HFont;
CharAdv: Integer; // char advance of single-byte code
DBCharAdv: Integer; // char advance of double-byte code
CharHeight: Integer;
end;
PheFontsData = ^TheFontsData;
TheFontsData = array[TheStockFontPatterns] of TheFontData;
PheSharedFontsInfo = ^TheSharedFontsInfo;
TheSharedFontsInfo = record
// reference counters
RefCount: Integer;
LockCount: Integer;
// font information
BaseFont: TFont;
BaseLF: TLogFont;
IsDBCSFont: Boolean;
IsTrueType: Boolean;
FontsData: TheFontsData;
end;
{ TheStockFontManager }
TheFontsInfoManager = class
private
FFontsInfo: TList;
function FindFontsInfo(const LF: TLogFont): PheSharedFontsInfo;
function CreateFontsInfo(ABaseFont: TFont;
const LF: TLogFont): PheSharedFontsInfo;
procedure DestroyFontHandles(pFontsInfo: PheSharedFontsInfo);
procedure RetrieveLogFontForComparison(ABaseFont: TFont; var LF: TLogFont);
public
constructor Create;
destructor Destroy; override;
procedure LockFontsInfo(pFontsInfo: PheSharedFontsInfo);
procedure UnLockFontsInfo(pFontsInfo: PheSharedFontsInfo);
function GetFontsInfo(ABaseFont: TFont): PheSharedFontsInfo;
procedure ReleaseFontsInfo(pFontsInfo: PheSharedFontsInfo);
end;
{ TheFontStock }
TheExtTextOutProc = procedure (X, Y: Integer; fuOptions: UINT;
const ARect: TRect; Text: PChar; Length: Integer) of object;
EheFontStockException = class(Exception);
TheFontStock = class
private
// private DC
FDC: HDC;
FDCRefCount: Integer;
// Shared fonts
FpInfo: PheSharedFontsInfo;
FUsingFontHandles: Boolean;
// Current font
FCrntFont: HFONT;
FCrntStyle: TFontStyles;
FpCrntFontData: PheFontData;
// local font info
FBaseLF: TLogFont;
function GetBaseFont: TFont;
function GetIsDBCSFont: Boolean;
function GetIsTrueType: Boolean;
protected
function InternalGetDC: HDC; virtual;
procedure InternalReleaseDC(Value: HDC); virtual;
function InternalCreateFont(Style: TFontStyles): HFONT; virtual;
function CalcFontAdvance(DC: HDC;
pCharHeight, pDBCharAdvance: PInteger): Integer; virtual;
function GetCharAdvance: Integer; virtual;
function GetCharHeight: Integer; virtual;
function GetDBCharAdvance: Integer; virtual;
function GetFontData(idx: Integer): PheFontData; virtual;
procedure UseFontHandles;
procedure ReleaseFontsInfo;
procedure SetBaseFont(Value: TFont); virtual;
procedure SetStyle(Value: TFontStyles); virtual;
property FontData[idx: Integer]: PheFontData read GetFontData;
property FontsInfo: PheSharedFontsInfo read FpInfo;
public
constructor Create(InitialFont: TFont); virtual;
destructor Destroy; override;
procedure ReleaseFontHandles; virtual;
property BaseFont: TFont read GetBaseFont;
property Style: TFontStyles read FCrntStyle write SetStyle;
property FontHandle: HFONT read FCrntFont;
property CharAdvance: Integer read GetCharAdvance;
property CharHeight: Integer read GetCharHeight;
property DBCharAdvance: Integer read GetDBCharAdvance;
property IsDBCSFont: Boolean read GetIsDBCSFont;
property IsTrueType: Boolean read GetIsTrueType;
end;
{ TheTextDrawer }
EheTextDrawerException = class(Exception);
TheTextDrawer = class(TObject)
private
FDC: HDC;
FSaveDC: Integer;
// Font information
FFontStock: TheFontStock;
FCalcExtentBaseStyle: TFontStyles;
FBaseCharWidth: Integer;
FBaseCharHeight: Integer;
// current font and properties
FCrntFont: HFONT;
FETODist: Pointer;
FETOSizeInChar: Integer;
// current font attributes
FColor: TColor;
FBkColor: TColor;
FCharExtra: Integer;
// Begin/EndDrawing calling count
FDrawingCount: Integer;
protected
procedure ReleaseETODist; virtual;
procedure AfterStyleSet; virtual;
procedure DoSetCharExtra(Value: Integer); virtual;
property StockDC: HDC read FDC;
property DrawingCount: Integer read FDrawingCount;
property FontStock: TheFontStock read FFontStock;
property BaseCharWidth: Integer read FBaseCharWidth;
property BaseCharHeight: Integer read FBaseCharHeight;
public
constructor Create(CalcExtentBaseStyle: TFontStyles; BaseFont: TFont); virtual;
destructor Destroy; override;
function GetCharWidth: Integer; virtual;
function GetCharHeight: Integer; virtual;
procedure BeginDrawing(DC: HDC); virtual;
procedure EndDrawing; virtual;
procedure TextOut(X, Y: Integer; Text: PChar; Length: Integer); virtual;
procedure ExtTextOut(X, Y: Integer; fuOptions: UINT; const ARect: TRect;
Text: PChar; Length: Integer); virtual;
procedure SetBaseFont(Value: TFont); virtual;
procedure SetBaseStyle(const Value: TFontStyles); virtual;
procedure SetStyle(Value: TFontStyles); virtual;
procedure SetForeColor(Value: TColor); virtual;
procedure SetBackColor(Value: TColor); virtual;
procedure SetCharExtra(Value: Integer); virtual;
procedure ReleaseTemporaryResources; virtual;
property CharWidth: Integer read GetCharWidth;
property CharHeight: Integer read GetCharHeight;
property BaseFont: TFont write SetBaseFont;
property BaseStyle: TFontStyles write SetBaseStyle;
property ForeColor: TColor write SetForeColor;
property BackColor: TColor write SetBackColor;
property Style: TFontStyles write SetStyle;
property CharExtra: Integer read FCharExtra write SetCharExtra;
end;
{ TheTextDrawer2 }
TheTextDrawer2 = class(TheTextDrawer)
private
FFonts: array[TheStockFontPatterns] of HFONT;
public
procedure SetStyle(Value: TFontStyles); override;
procedure SetBaseFont(Value: TFont); override;
end;
{ TheTextDrawerEx }
TheTextDrawerEx = class(TheTextDrawer)
private
// current font properties
FCrntDx: Integer;
FCrntDBDx: Integer; // for a double-byte character
// Text drawing procedure reference for optimization
FExtTextOutProc: TheExtTextOutProc;
protected
procedure AfterStyleSet; override;
procedure DoSetCharExtra(Value: Integer); override;
procedure TextOutOrExtTextOut(X, Y: Integer; fuOptions: UINT;
const ARect: TRect; Text: PChar; Length: Integer); virtual;
procedure ExtTextOutFixed(X, Y: Integer; fuOptions: UINT;
const ARect: TRect; Text: PChar; Length: Integer); virtual;
procedure ExtTextOutWithETO(X, Y: Integer; fuOptions: UINT;
const ARect: TRect; Text: PChar; Length: Integer); virtual;
procedure ExtTextOutForDBCS(X, Y: Integer; fuOptions: UINT;
const ARect: TRect; Text: PChar; Length: Integer); virtual;
public
procedure ExtTextOut(X, Y: Integer; fuOptions: UINT; const ARect: TRect;
Text: PChar; Length: Integer); override;
end;
function GetFontsInfoManager: TheFontsInfoManager;
{$IFNDEF VER93}
{$IFNDEF VER90}
{$IFNDEF VER80}
{$DEFINE HE_ASSERT}
{$DEFINE HE_LEADBYTES}
{$DEFINE HE_COMPAREMEM}
{$ENDIF}
{$ENDIF}
{$ENDIF}
{$IFNDEF HE_LEADBYTES}
type
TheLeadByteChars = set of Char;
function SetLeadBytes(const Value: TheLeadByteChars): TheLeadByteChars;
{$ENDIF}
implementation
const
DBCHAR_CALCULATION_FALED = $7FFFFFFF;
var
gFontsInfoManager: TheFontsInfoManager;
{$IFNDEF HE_LEADBYTES}
LeadBytes: TheLeadByteChars;
{$ENDIF}
{ utility routines }
function GetFontsInfoManager: TheFontsInfoManager;
begin
if not Assigned(gFontsInfoManager) then
gFontsInfoManager := TheFontsInfoManager.Create;
Result := gFontsInfoManager;
end;
function Min(x, y: integer): integer;
begin
if x < y then Result := x else Result := y;
end;
{$IFNDEF HE_ASSERT}
procedure ASSERT(Expression: Boolean);
begin
if not Expression then
raise EheTextDrawerException.Create('Assertion failed.');
end;
{$ENDIF}
{$IFNDEF HE_LEADBYTES}
function SetLeadBytes(const Value: TheLeadByteChars): TheLeadByteChars;
begin
Result := LeadBytes;
LeadBytes := Value;
end;
{$ENDIF}
{$IFNDEF HE_COMPAREMEM}
function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
asm
PUSH ESI
PUSH EDI
MOV ESI,P1
MOV EDI,P2
MOV EDX,ECX
XOR EAX,EAX
AND EDX,3
SHR ECX,1
SHR ECX,1
REPE CMPSD
JNE @@2
MOV ECX,EDX
REPE CMPSB
JNE @@2
@@1: INC EAX
@@2: POP EDI
POP ESI
end;
{$ENDIF}
{ TheFontsInfoManager }
procedure TheFontsInfoManager.LockFontsInfo(
pFontsInfo: PheSharedFontsInfo);
begin
Inc(pFontsInfo^.LockCount);
end;
constructor TheFontsInfoManager.Create;
begin
inherited;
FFontsInfo := TList.Create;
end;
function TheFontsInfoManager.CreateFontsInfo(ABaseFont: TFont;
const LF: TLogFont): PheSharedFontsInfo;
var
DC: HDC;
hOldFont: HFont;
begin
New(Result);
FillChar(Result^, SizeOf(TheSharedFontsInfo), 0);
with Result^ do
try
BaseFont := TFont.Create;
BaseFont.Assign(ABaseFont);
BaseLF := LF;
IsTrueType := (0 <> (TRUETYPE_FONTTYPE and LF.lfPitchAndFamily));
// find out whether the font `IsDBCSFont'
DC := GetDC(0);
hOldFont := SelectObject(DC, ABaseFont.Handle);
IsDBCSFont := (0 <> (GCP_DBCS and GetFontLanguageInfo(DC)));
SelectObject(DC, hOldFont);
ReleaseDC(0, DC);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -