FreeType: Support for rotated text.

git-svn-id: trunk@63846 -
This commit is contained in:
jesus 2020-08-30 01:39:21 +00:00
parent a04423bc0d
commit e7f57c722d
4 changed files with 274 additions and 53 deletions

View File

@ -21,7 +21,7 @@ interface
uses uses
Classes, SysUtils, fpimage, Laz_AVL_Tree, Classes, SysUtils, fpimage, Laz_AVL_Tree,
// LazUtils // Note: Types must be after TTTypes for PByte. // LazUtils // Note: Types must be after TTTypes for PByte.
LazUTF8, LazFreeType, TTRASTER, TTTypes, Types; LazUTF8, LazFreeType, TTRASTER, TTTypes, TTObjs, Types;
type type
TGlyphRenderQuality = (grqMonochrome, grqLowQuality, grqHighQuality); TGlyphRenderQuality = (grqMonochrome, grqLowQuality, grqHighQuality);
@ -184,6 +184,7 @@ type
procedure SetHinted(const AValue: boolean); virtual; abstract; procedure SetHinted(const AValue: boolean); virtual; abstract;
public public
UnderlineDecoration,StrikeOutDecoration: boolean; UnderlineDecoration,StrikeOutDecoration: boolean;
Orientation: integer;
function TextWidth(AText: string): single; virtual; abstract; function TextWidth(AText: string): single; virtual; abstract;
function TextHeight(AText: string): single; virtual; abstract; function TextHeight(AText: string): single; virtual; abstract;
function CharWidthFromUnicode(AUnicode: integer): single; virtual; abstract; function CharWidthFromUnicode(AUnicode: integer): single; virtual; abstract;
@ -339,13 +340,16 @@ type
FLoaded: boolean; FLoaded: boolean;
FGlyphData: TT_Glyph; FGlyphData: TT_Glyph;
FIndex: integer; FIndex: integer;
FOrientation: Integer;
function GetAdvance: single; function GetAdvance: single;
function GetBounds: TRect; function GetBounds: TRect;
function GetBoundsWithOffset(x, y: single): TRect; function GetBoundsWithOffset(x, y: single): TRect;
{%H-}constructor create;
public public
constructor Create(AFont: TFreeTypeFont; AIndex: integer); constructor Create(AFont: TFreeTypeFont; AIndex: integer);
function RenderDirectly(x,y: single; Rect: TRect; OnRender : TDirectRenderingFunction; quality : TGlyphRenderQuality; ClearType: boolean = false): boolean; function RenderDirectly(x,y: single; Rect: TRect; OnRender : TDirectRenderingFunction; quality : TGlyphRenderQuality; ClearType: boolean = false): boolean;
function RenderDirectly(ARasterizer: TFreeTypeRasterizer; x,y: single; Rect: TRect; OnRender : TDirectRenderingFunction; quality : TGlyphRenderQuality; ClearType: boolean = false): boolean; function RenderDirectly(ARasterizer: TFreeTypeRasterizer; x,y: single; Rect: TRect; OnRender : TDirectRenderingFunction; quality : TGlyphRenderQuality; ClearType: boolean = false): boolean;
function Clone(AOrientation:Integer): TFreeTypeGlyph;
destructor Destroy; override; destructor Destroy; override;
property Loaded: boolean read FLoaded; property Loaded: boolean read FLoaded;
property Data: TT_Glyph read FGlyphData; property Data: TT_Glyph read FGlyphData;
@ -752,15 +756,8 @@ end;
{ TFreeTypeGlyph } { TFreeTypeGlyph }
function TFreeTypeGlyph.GetBounds: TRect; function TFreeTypeGlyph.GetBounds: TRect;
var
metrics: TT_Glyph_Metrics;
begin begin
if TT_Get_Glyph_Metrics(FGlyphData, metrics) = TT_Err_Ok then result := GetBoundsWithOffset(0, 0);
with metrics.bbox do
result := rect(IncludeFullGrainMin(xMin,64) div 64,IncludeFullGrainMin(-yMax,64) div 64,
(IncludeFullGrainMax(xMax,64)+1) div 64,(IncludeFullGrainMax(-yMin,64)+1) div 64)
else
result := TRect.Empty;
end; end;
function TFreeTypeGlyph.GetAdvance: single; function TFreeTypeGlyph.GetAdvance: single;
@ -776,15 +773,30 @@ end;
function TFreeTypeGlyph.GetBoundsWithOffset(x, y: single): TRect; function TFreeTypeGlyph.GetBoundsWithOffset(x, y: single): TRect;
var var
metrics: TT_Glyph_Metrics; metrics: TT_Glyph_Metrics;
outline: TT_Outline;
bbox: TT_BBox;
error: TT_Error;
begin begin
if TT_Get_Glyph_Metrics(FGlyphData, metrics) = TT_Err_Ok then
if FOrientation<>0 then
begin begin
with metrics.bbox do error := TT_Get_Glyph_Outline(FGlyphData, outline{%H-});
if error=TT_Err_Ok then
error := TT_Get_Outline_BBox(outline, bbox{%H-});
end else
begin
error := TT_Get_Glyph_Metrics(FGlyphData, metrics);
if error=TT_Err_Ok then
bbox := metrics.bbox;
end;
if error=TT_Err_Ok then
with bbox do
result := rect(IncludeFullGrainMin(xMin+round(x*64),64) div 64, result := rect(IncludeFullGrainMin(xMin+round(x*64),64) div 64,
IncludeFullGrainMin(-yMax+round(y*64),64) div 64, IncludeFullGrainMin(-yMax+round(y*64),64) div 64,
(IncludeFullGrainMax(xMax+round(x*64),64)+1) div 64, (IncludeFullGrainMax(xMax+round(x*64),64)+1) div 64,
(IncludeFullGrainMax(-yMin+round(y*64),64)+1) div 64); (IncludeFullGrainMax(-yMin+round(y*64),64)+1) div 64)
end else else
result := TRect.Empty; result := TRect.Empty;
end; end;
@ -796,6 +808,23 @@ begin
FIndex := AIndex; FIndex := AIndex;
end; end;
constructor TFreeTypeGlyph.create;
begin
end;
function TFreeTypeGlyph.Clone(AOrientation: Integer): TFreeTypeGlyph;
begin
if not FLoaded then
raise EFreeType.Create('Cannot create a clone of an empty glyph');
result := TFreeTypeGlyph.create;
result.FLoaded := FLoaded;
result.FIndex := FIndex;
result.FOrientation := AOrientation;
TT_Copy_Glyph(FGlyphData, result.FGlyphData);
end;
function TFreeTypeGlyph.RenderDirectly(x, y: single; Rect: TRect; function TFreeTypeGlyph.RenderDirectly(x, y: single; Rect: TRect;
OnRender: TDirectRenderingFunction; quality : TGlyphRenderQuality; ClearType: boolean): boolean; OnRender: TDirectRenderingFunction; quality : TGlyphRenderQuality; ClearType: boolean): boolean;
begin begin
@ -1239,7 +1268,7 @@ begin
raise EFreeType.Create('No font instance'); raise EFreeType.Create('No font instance');
flags := TT_Load_Scale_Glyph; flags := TT_Load_Scale_Glyph;
if FHinted then flags := flags or TT_Load_Hint_Glyph; if FHinted then flags := flags or TT_Load_Hint_Glyph;
result := (TT_Load_Glyph(FInstance, _glyph, glyph_index, flags) <> TT_Err_Ok); result := (TT_Load_Glyph(FInstance, _glyph, glyph_index, flags) = TT_Err_Ok);
end; end;
procedure TFreeTypeFont.SetWidthFactor(const AValue: single); procedure TFreeTypeFont.SetWidthFactor(const AValue: single);
@ -1526,19 +1555,44 @@ var
idx: integer; idx: integer;
g: TFreeTypeGlyph; g: TFreeTypeGlyph;
prevCharcode, glyphIndex: integer; prevCharcode, glyphIndex: integer;
txmatrix: TT_Matrix;
angle: single;
outline: ^TT_Outline;
vector: TT_Vector;
corrX, corrY: single;
begin begin
if not CheckInstance then exit; if not CheckInstance then exit;
if AText = '' then exit; if AText = '' then exit;
idx := pos(LineEnding,AText); idx := pos(LineEnding,AText);
if Orientation<>0 then
begin
angle := Orientation * PI / 1800;
txmatrix.xx := Round( cos( angle ) * $10000 );
txmatrix.xy := -Round( sin( angle ) * $10000 );
txmatrix.yx := Round( sin( angle ) * $10000 );
txmatrix.yy := Round( cos( angle ) * $10000 );
end;
while idx <> 0 do while idx <> 0 do
begin begin
RenderText(copy(AText,1,idx-1),x,y,ARect,OnRender); RenderText(copy(AText,1,idx-1),x,y,ARect,OnRender);
delete(AText,1,idx+length(LineEnding)-1); delete(AText,1,idx+length(LineEnding)-1);
if Orientation<>0 then
begin
vector.x := 0;
vector.y := -round(LineFullHeight * 64);
TT_Transform_Vector(vector.x, vector.y, txmatrix);
x += vector.x / 64;
y -= vector.y / 64;
end else
y += LineFullHeight; y += LineFullHeight;
idx := pos(LineEnding,AText); idx := pos(LineEnding,AText);
end; end;
If Assigned(FOnRenderText) then If Assigned(FOnRenderText) then
FOnRenderText(AText,x,y); FOnRenderText(AText,x,y);
// TODO: Rotation at arbitraty angles requires antialiased drawing
RenderTextDecoration(AText,x,y,ARect,OnRender); RenderTextDecoration(AText,x,y,ARect,OnRender);
pstr := @AText[1]; pstr := @AText[1];
left := length(AText); left := length(AText);
@ -1546,25 +1600,49 @@ begin
while left > 0 do while left > 0 do
begin begin
charcode := UTF8CodepointToUnicode(pstr, charlen); charcode := UTF8CodepointToUnicode(pstr, charlen);
inc(pstr,charlen);
dec(left,charlen); dec(left,charlen);
glyphIndex := CharIndex[charcode]; glyphIndex := CharIndex[charcode];
g := Glyph[glyphIndex]; g := Glyph[glyphIndex];
if Orientation<>0 then
g := g.Clone(Orientation);
if g <> nil then if g <> nil then
with g do with g do
begin begin
corrX := Advance;
if KerningEnabled and (prevCharcode <> -1) then if KerningEnabled and (prevCharcode <> -1) then
x += GetCharKerning(prevCharcode, charcode).Kerning.x; corrX += round(GetCharKerning(prevCharcode, charcode).Kerning.x);
vector.x := round(corrX * 64);
vector.y := 0;
if Orientation<>0 then begin
outLine := @PGlyph(Data.z)^.outline;
TT_Transform_Outline(outline^, txmatrix);
TT_Transform_Vector(vector.x, vector.y, txmatrix);
end;
corrX := vector.x / 64;
corry := vector.y / 64;
if Hinted then if Hinted then
RenderDirectly(x,round(y),ARect,OnRender,quality,FClearType) RenderDirectly(x,round(y),ARect,OnRender,quality,FClearType)
else else
RenderDirectly(x,y,ARect,OnRender,quality,FClearType); RenderDirectly(x,y,ARect,OnRender,quality,FClearType);
if FClearType then if FClearType then
x += Advance/3 x += corrX/3
else else
x += Advance; x += corrX;
y -= corrY;
prevCharcode := charcode; prevCharcode := charcode;
if Orientation<>0 then
g.Free;
end; end;
inc(pstr,charlen);
end; end;
end; end;

View File

@ -231,6 +231,12 @@ uses TTTypes, Classes;
glyph_index : Word; glyph_index : Word;
load_flags : Integer ) : TT_Error; load_flags : Integer ) : TT_Error;
(*****************************************************************)
(* Copy a glyph container into another one *)
(* *)
function TT_Copy_Glyph( var source : TT_Glyph;
var target : TT_Glyph ) : TT_Error;
const const
TT_Load_Scale_Glyph = 1; (* ask the loader to scale the glyph *) TT_Load_Scale_Glyph = 1; (* ask the loader to scale the glyph *)
(* to the current pointsize/transform *) (* to the current pointsize/transform *)
@ -1009,6 +1015,50 @@ uses
TT_Load_Glyph := error; TT_Load_Glyph := error;
end; end;
(*****************************************************************)
(* *)
(* *)
function TT_Copy_Glyph(var source: TT_Glyph; var target: TT_Glyph): TT_Error;
var
src, dst : PGlyph;
begin
src := PGlyph(source.z);
dst := PGlyph(target.z);
if (PGlyph(source.z)<>nil) then
begin
if dst=nil then
begin
error := TT_New_Glyph(TT_Face(src^.face), target);
if error<>TT_Err_Ok then
begin
TT_Copy_Glyph := error;
exit;
end;
dst := PGlyph(target.z);
end
else
TT_Done_Outline(dst^.outline);
dst^.metrics := src^.metrics;
dst^.computed_width := src^.computed_width;
dst^.precalc_width := src^.precalc_width;
dst^.is_composite := src^.is_composite;
TT_New_Outline(src^.outline.n_points, src^.outline.n_contours, dst^.outline);
dst^.outline.owner := src^.outline.owner;
dst^.outline.high_precision := src^.outline.high_precision;
dst^.outline.second_pass := src^.outline.second_pass;
dst^.outline.dropout_mode := src^.outline.dropout_mode;
TT_Copy_Glyph := TT_Copy_Outline( src^.outline, dst^.outline );
end
else
TT_Copy_Glyph := TT_Err_Invalid_Glyph_Handle;
end;
(*****************************************************************) (*****************************************************************)
(* *) (* *)

View File

@ -1,12 +1,12 @@
object Form1: TForm1 object Form1: TForm1
Left = 362 Left = 362
Height = 240 Height = 336
Top = 172 Top = 172
Width = 441 Width = 624
Align = alBottom Align = alBottom
Caption = 'Test LazFreeType' Caption = 'Test LazFreeType'
ClientHeight = 240 ClientHeight = 336
ClientWidth = 441 ClientWidth = 624
KeyPreview = True KeyPreview = True
OnCreate = FormCreate OnCreate = FormCreate
OnDestroy = FormDestroy OnDestroy = FormDestroy
@ -18,18 +18,18 @@ object Form1: TForm1
object Panel_Option: TPanel object Panel_Option: TPanel
Left = 0 Left = 0
Height = 40 Height = 40
Top = 200 Top = 296
Width = 441 Width = 624
Align = alBottom Align = alBottom
ClientHeight = 40 ClientHeight = 40
ClientWidth = 441 ClientWidth = 624
ParentColor = False ParentColor = False
TabOrder = 0 TabOrder = 0
object TrackBar_Size: TTrackBar object TrackBar_Size: TTrackBar
Left = 96 Left = 96
Height = 25 Height = 25
Top = 8 Top = 8
Width = 243 Width = 280
Frequency = 0 Frequency = 0
Max = 300 Max = 300
Min = 1 Min = 1
@ -39,9 +39,9 @@ object Form1: TForm1
TabOrder = 0 TabOrder = 0
end end
object LFontSize: TLabel object LFontSize: TLabel
Left = 336 Left = 376
Height = 16 Height = 16
Top = 12 Top = 11
Width = 51 Width = 51
Alignment = taCenter Alignment = taCenter
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
@ -68,15 +68,46 @@ object Form1: TForm1
TabOrder = 1 TabOrder = 1
Value = 1 Value = 1
end end
object CheckBox_Rect: TCheckBox object LAngle: TLabel
Left = 392 Left = 440
Height = 15
Top = 11
Width = 11
Anchors = [akTop, akRight]
Caption = '0º'
ParentColor = False
end
object CheckBox_SingleLine: TRadioButton
Left = 472
Height = 19 Height = 19
Top = 10 Top = 12
Width = 51
Anchors = [akTop, akRight]
Caption = '1 Line'
OnChange = CheckBox_SingleLineChange
TabOrder = 2
end
object CheckBox_Rot: TRadioButton
Left = 576
Height = 19
Top = 12
Width = 38
Anchors = [akTop, akRight]
Caption = 'Rot'
OnChange = CheckBox_SingleLineChange
TabOrder = 3
end
object CheckBox_Para: TRadioButton
Left = 528
Height = 19
Top = 12
Width = 43 Width = 43
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
Caption = 'Rect' Caption = 'Rect'
OnChange = CheckBox_RectChange Checked = True
TabOrder = 2 OnChange = CheckBox_SingleLineChange
TabOrder = 4
TabStop = True
end end
end end
end end

View File

@ -5,7 +5,7 @@ unit mainform;
interface interface
uses uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Classes, SysUtils, Math, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
ComCtrls, ExtCtrls, Spin, fpimage, LCLType, ComCtrls, ExtCtrls, Spin, fpimage, LCLType,
IntfGraphics, GraphType, //Intf basic routines IntfGraphics, GraphType, //Intf basic routines
@ -19,13 +19,16 @@ type
{ TForm1 } { TForm1 }
TForm1 = class(TForm) TForm1 = class(TForm)
CheckBox_Rect: TCheckBox; CheckBox_SingleLine: TRadioButton;
CheckBox_Para: TRadioButton;
CheckBox_Rot: TRadioButton;
Label1: TLabel; Label1: TLabel;
LAngle: TLabel;
LFontSize: TLabel; LFontSize: TLabel;
Panel_Option: TPanel; Panel_Option: TPanel;
SpinEdit_Zoom: TSpinEdit; SpinEdit_Zoom: TSpinEdit;
TrackBar_Size: TTrackBar; TrackBar_Size: TTrackBar;
procedure CheckBox_RectChange(Sender: TObject); procedure CheckBox_SingleLineChange(Sender: TObject);
procedure FormCreate(Sender: TObject); procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject); procedure FormDestroy(Sender: TObject);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
@ -35,11 +38,14 @@ type
procedure TrackBar_SizeChange(Sender: TObject); procedure TrackBar_SizeChange(Sender: TObject);
private private
procedure UpdateSizeLabel; procedure UpdateSizeLabel;
procedure UpdateAngleLabel;
public public
lazimg: TLazIntfImage; lazimg: TLazIntfImage;
drawer: TIntfFreeTypeDrawer; drawer: TIntfFreeTypeDrawer;
ftFont1,ftFont2,ftFont3: TFreeTypeFont; ftFont1,ftFont2,ftFont3: TFreeTypeFont;
mx,my: integer; //mouse position mx,my: integer; //mouse position
fSin,fCos: double;
fAngle: double;
procedure EraseBackground(DC: HDC); override; procedure EraseBackground(DC: HDC); override;
procedure SetupFonts; procedure SetupFonts;
end; end;
@ -125,8 +131,9 @@ begin
ftFont3 := nil; ftFont3 := nil;
end; end;
procedure TForm1.CheckBox_RectChange(Sender: TObject); procedure TForm1.CheckBox_SingleLineChange(Sender: TObject);
begin begin
LAngle.Enabled := CheckBox_Rot.Checked;
invalidate; invalidate;
end; end;
@ -143,6 +150,14 @@ procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer
begin begin
mx := X; mx := X;
my := Y; my := Y;
if CheckBox_Rot.Checked then
begin
fAngle := ArcTan2(Panel_Option.Top/2 - my, mx - ClientWidth/2);
SinCos(fAngle, fSin, fCos);
fAngle := RadToDeg(fAngle);
if fAngle<0 then fAngle += 360;
UpdateAngleLabel;
end;
invalidate; invalidate;
end; end;
@ -154,15 +169,28 @@ begin
if ftFont3 <> nil then ftFont3.SizeInPoints := TrackBar_Size.Position; if ftFont3 <> nil then ftFont3.SizeInPoints := TrackBar_Size.Position;
end; end;
procedure TForm1.UpdateAngleLabel;
begin
LAngle.Caption := format('%3.0fº',[fAngle]);
end;
procedure TForm1.FormPaint(Sender: TObject); procedure TForm1.FormPaint(Sender: TObject);
const testtext = 'The'#13#10'quick brown fox jumps over the lazy dog'; const testtext = 'The'#13#10'quick brown fox jumps over the lazy dog';
var bmp: TBitmap; var bmp: TBitmap;
tx,ty: integer; tx,ty: integer;
p: array of TCharPosition; p: array of TCharPosition;
x,y: single; x,y,h,rx,ry: single;
i: integer; i: integer;
StartTime,EndTime,EndTime2: TDateTime; StartTime,EndTime,EndTime2: TDateTime;
zoom: integer; zoom: integer;
Orientation: Integer;
procedure Rotate(dx,dy:single);
begin
rx := tx/2 + (fCos*dx - fSin*dy);
ry := ty/2 - (fSin*dx + fCos*dy);
end;
begin begin
if lazimg = nil then exit; if lazimg = nil then exit;
canvas.Font.Name := 'Comic Sans MS'; canvas.Font.Name := 'Comic Sans MS';
@ -170,6 +198,11 @@ begin
zoom := SpinEdit_Zoom.Value; zoom := SpinEdit_Zoom.Value;
StartTime := Now; StartTime := Now;
if not CheckBox_Rot.Checked then
Orientation := 0
else
Orientation := round(fAngle*10);
tx := ClientWidth div zoom; tx := ClientWidth div zoom;
ty := Panel_Option.Top div zoom; ty := Panel_Option.Top div zoom;
if (lazimg.Width <> tx) or (lazimg.Height <> ty) then if (lazimg.Width <> tx) or (lazimg.Height <> ty) then
@ -179,17 +212,31 @@ begin
x := mx/zoom; x := mx/zoom;
y := my/zoom; y := my/zoom;
if CheckBox_Rot.Checked then
begin
h := 0.0;
if ftFont1<>nil then h += ftFont1.LineFullHeight;
if ftFont2<>nil then h += ftFont2.LineFullHeight;
if ftFont3<>nil then h += ftFont3.LineFullHeight;
h := h / 2;
end;
if ftFont1<>nil then if ftFont1<>nil then
begin begin
ftFont1.Hinted := true; ftFont1.Hinted := true;
ftFont1.ClearType := true; ftFont1.ClearType := not CheckBox_Rot.Checked; // ClearType and rotation is not working yet
ftFont1.Quality := grqHighQuality; ftFont1.Quality := grqHighQuality;
ftFont1.SmallLinePadding := false; ftFont1.SmallLinePadding := false;
if CheckBox_Rect.Checked then ftFont1.Orientation := Orientation;
if CheckBox_Para.Checked then
drawer.DrawTextRect(testtext, ftFont1, 0,0, tx/3,ty, colBlack, [ftaLeft, ftaBottom]) drawer.DrawTextRect(testtext, ftFont1, 0,0, tx/3,ty, colBlack, [ftaLeft, ftaBottom])
else else if CheckBox_SingleLine.Checked then
drawer.DrawText(ftFont1.Information[ftiFullName], ftFont1, x, y, colBlack, [ftaRight, ftaBottom]); drawer.DrawText(ftFont1.Information[ftiFullName], ftFont1, x, y, colBlack, [ftaRight, ftaBottom])
else begin
Rotate( -ftFont1.TextWidth(ftFont1.Information[ftiFullName])/2,
h - ftFont1.LineFullHeight);
drawer.DrawText(ftFont1.Information[ftiFullName], ftFont1, rx, ry, colBlack);
end;
end; end;
if ftFont2<>nil then if ftFont2<>nil then
@ -197,23 +244,34 @@ begin
ftFont2.Hinted := false; ftFont2.Hinted := false;
ftFont2.ClearType := false; ftFont2.ClearType := false;
ftFont2.Quality := grqHighQuality; ftFont2.Quality := grqHighQuality;
if CheckBox_Rect.Checked then ftFont2.Orientation := Orientation;
if CheckBox_Para.Checked then
drawer.DrawTextRect(testtext, ftFont2, tx/3,0, 2*tx/3,ty, colRed, [ftaCenter, ftaVerticalCenter]) drawer.DrawTextRect(testtext, ftFont2, tx/3,0, 2*tx/3,ty, colRed, [ftaCenter, ftaVerticalCenter])
else else if CheckBox_SingleLine.Checked then
drawer.DrawText(ftFont2.Information[ftiFullName], ftFont2, x, y, colRed, 192, [ftaCenter, ftaBaseline]); drawer.DrawText(ftFont2.Information[ftiFullName], ftFont2, x, y, colRed, 192, [ftaCenter, ftaBaseline])
else begin
Rotate( -ftFont2.TextWidth(ftFont2.Information[ftiFullName])/2,
-ftFont2.LineFullHeight/2);
drawer.DrawText(ftFont2.Information[ftiFullName], ftFont2, rx, ry, colRed);
end;
end; end;
if ftFont3<>nil then begin if ftFont3<>nil then begin
ftFont3.Hinted := false; ftFont3.Hinted := false;
ftFont3.ClearType := false; ftFont3.ClearType := false;
ftFont3.Quality := grqMonochrome; ftFont3.Quality := grqMonochrome;
if CheckBox_Rect.Checked then ftFont3.Orientation := Orientation;
if CheckBox_Para.Checked then
drawer.DrawTextRect(testtext, ftFont3, 2*tx/3,0, tx,ty, colBlue, [ftaRight, ftaTop]) drawer.DrawTextRect(testtext, ftFont3, 2*tx/3,0, tx,ty, colBlue, [ftaRight, ftaTop])
else else if CheckBox_SingleLine.Checked then
drawer.DrawText(ftFont3.Information[ftiFullName]+' '+ftFont3.VersionNumber, ftFont3, x, y, colBlack, 128, [ftaLeft, ftaTop]); drawer.DrawText(ftFont3.Information[ftiFullName]+' '+ftFont3.VersionNumber, ftFont3, x, y, colBlack, 128, [ftaLeft, ftaTop])
else begin
Rotate( -ftFont3.TextWidth(ftFont3.Information[ftiFullName])/2, - h );
drawer.DrawText(ftFont3.Information[ftiFullName], ftFont3, rx, ry, colBlue);
end;
end; end;
if (ftFont1<>nil) and not CheckBox_Rect.Checked then if (ftFont1<>nil) and CheckBox_SingleLine.Checked then
begin begin
p := ftFont1.CharsPosition(ftFont1.Information[ftiFullName],[ftaRight, ftaBottom]); p := ftFont1.CharsPosition(ftFont1.Information[ftiFullName],[ftaRight, ftaBottom]);
for i := 0 to high(p) do for i := 0 to high(p) do
@ -233,7 +291,11 @@ begin
EndTime2 := Now; EndTime2 := Now;
Canvas.TextOut(0,0, inttostr(round((EndTime-StartTime)*24*60*60*1000))+' ms + '+inttostr(round((EndTime2-EndTime)*24*60*60*1000))+' ms'); Canvas.TextOut(0,0, inttostr(round((EndTime-StartTime)*24*60*60*1000))+' ms + '+inttostr(round((EndTime2-EndTime)*24*60*60*1000))+' ms');
if CheckBox_Rot.Checked then
begin
Canvas.Pen.Color := clFuchsia;
Canvas.Line(ClientWidth div 2, Panel_Option.Top div 2, mx, my);
end;
end; end;
procedure TForm1.FormShow(Sender: TObject); procedure TForm1.FormShow(Sender: TObject);