mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-02 12:23:39 +02:00
363 lines
9.5 KiB
ObjectPascal
363 lines
9.5 KiB
ObjectPascal
{
|
|
*****************************************************************************
|
|
See the file COPYING.modifiedLGPL.txt, included in this distribution,
|
|
for details about the license.
|
|
*****************************************************************************
|
|
|
|
Authors: Alexander Klenin
|
|
|
|
}
|
|
unit TADrawerAggPas;
|
|
|
|
{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, FPCanvas, FPImage, Agg_LCL, TAChartUtils, TADrawUtils;
|
|
|
|
type
|
|
|
|
{ TAggPasDrawer }
|
|
|
|
TAggPasDrawer = class(TBasicDrawer, IChartDrawer)
|
|
strict private
|
|
FFontDir: String;
|
|
function ApplyTransparency(AColor: TFPColor): TFPColor;
|
|
procedure SetBrush(ABrush: TFPCustomBrush);
|
|
procedure SetFont(AFont: TFPCustomFont);
|
|
procedure SetPen(APen: TFPCustomPen);
|
|
strict protected
|
|
FCanvas: TAggLCLCanvas;
|
|
function SimpleTextExtent(const AText: String): TPoint; override;
|
|
procedure SimpleTextOut(AX, AY: Integer; const AText: String); override;
|
|
public
|
|
constructor Create(ACanvas: TAggLCLCanvas);
|
|
public
|
|
procedure AddToFontOrientation(ADelta: Integer);
|
|
procedure ClippingStart;
|
|
procedure ClippingStart(const AClipRect: TRect);
|
|
procedure ClippingStop;
|
|
procedure Ellipse(AX1, AY1, AX2, AY2: Integer);
|
|
procedure FillRect(AX1, AY1, AX2, AY2: Integer);
|
|
function GetBrushColor: TChartColor;
|
|
function GetFontAngle: Double; override;
|
|
function GetFontColor: TFPColor; override;
|
|
function GetFontName: String; override;
|
|
function GetFontSize: Integer; override;
|
|
function GetFontStyle: TChartFontStyles; override;
|
|
function GetPenColor: TChartColor;
|
|
procedure Line(AX1, AY1, AX2, AY2: Integer);
|
|
procedure Line(const AP1, AP2: TPoint);
|
|
procedure LineTo(AX, AY: Integer); override;
|
|
procedure MoveTo(AX, AY: Integer); override;
|
|
procedure Polygon(
|
|
const APoints: array of TPoint; AStartIndex, ANumPts: Integer); override;
|
|
procedure Polyline(
|
|
const APoints: array of TPoint; AStartIndex, ANumPts: Integer);
|
|
procedure PrepareSimplePen(AColor: TChartColor);
|
|
procedure PutImage(AX, AY: Integer; AImage: TFPCustomImage); override;
|
|
procedure RadialPie(
|
|
AX1, AY1, AX2, AY2: Integer;
|
|
AStartAngle16Deg, AAngleLength16Deg: Integer);
|
|
procedure Rectangle(const ARect: TRect);
|
|
procedure Rectangle(AX1, AY1, AX2, AY2: Integer);
|
|
procedure ResetFont;
|
|
procedure SetBrushColor(AColor: TChartColor);
|
|
procedure SetBrushParams(AStyle: TFPBrushStyle; AColor: TChartColor);
|
|
procedure SetPenColor(AColor: TChartColor);
|
|
procedure SetPenParams(AStyle: TFPPenStyle; AColor: TChartColor; AWidth: Integer = 1);
|
|
procedure SetPenWidth(AWidth: Integer);
|
|
property FontDir: String read FFontDir write FFontDir;
|
|
end;
|
|
|
|
procedure SwapRedBlue(AImg: TFPCustomImage);
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
Math, TAGeometry;
|
|
|
|
procedure SwapRedBlue(AImg: TFPCustomImage);
|
|
var
|
|
x, y: Integer;
|
|
clr: TFPColor;
|
|
tmp: Word;
|
|
begin
|
|
for y := 0 to AImg.Height-1 do
|
|
for x := 0 to AImg.Width-1 do
|
|
begin
|
|
clr := AImg.Colors[x, y];
|
|
tmp := clr.Red;
|
|
clr.Red := clr.Blue;
|
|
clr.Blue := tmp;
|
|
AImg.Colors[x, y] := clr;
|
|
end;
|
|
end;
|
|
|
|
{ TAggPasDrawer }
|
|
|
|
procedure TAggPasDrawer.AddToFontOrientation(ADelta: Integer);
|
|
begin
|
|
with FCanvas.Font do
|
|
AggAngle := AggAngle + OrientToRad(ADelta);
|
|
end;
|
|
|
|
function TAggPasDrawer.ApplyTransparency(AColor: TFPColor): TFPColor;
|
|
begin
|
|
Result := AColor;
|
|
Result.alpha := (255 - FTransparency) shl 8;
|
|
end;
|
|
|
|
procedure TAggPasDrawer.ClippingStart(const AClipRect: TRect);
|
|
begin
|
|
FCanvas.ClipRect := AClipRect;
|
|
FCanvas.Clipping := true;
|
|
end;
|
|
|
|
procedure TAggPasDrawer.ClippingStart;
|
|
begin
|
|
FCanvas.Clipping := true;
|
|
end;
|
|
|
|
procedure TAggPasDrawer.ClippingStop;
|
|
begin
|
|
FCanvas.Clipping := false;
|
|
end;
|
|
|
|
constructor TAggPasDrawer.Create(ACanvas: TAggLCLCanvas);
|
|
begin
|
|
inherited Create;
|
|
FCanvas := ACanvas;
|
|
end;
|
|
|
|
procedure TAggPasDrawer.Ellipse(AX1, AY1, AX2, AY2: Integer);
|
|
begin
|
|
FCanvas.Ellipse(AX1, AY1, AX2, AY2);
|
|
end;
|
|
|
|
procedure TAggPasDrawer.FillRect(AX1, AY1, AX2, AY2: Integer);
|
|
begin
|
|
FCanvas.FillRect(AX1, AY1, AX2, AY2);
|
|
end;
|
|
|
|
function TAggPasDrawer.GetBrushColor: TChartColor;
|
|
begin
|
|
Result := FCanvas.Brush.Color;
|
|
end;
|
|
|
|
function TAggPasDrawer.GetFontAngle: Double;
|
|
begin
|
|
Result := FCanvas.Font.AggAngle;
|
|
end;
|
|
|
|
function TAggPasDrawer.GetFontColor: TFPColor;
|
|
begin
|
|
Result.Red := FCanvas.Font.AggColor.r shl 8;
|
|
Result.Green := FCanvas.Font.AggColor.g shl 8;
|
|
Result.Blue := FCanvas.Font.AggColor.b shl 8;
|
|
end;
|
|
|
|
function TAggPasDrawer.GetFontName: String;
|
|
begin
|
|
Result := FCanvas.Font.Name;
|
|
end;
|
|
|
|
function TAggPasDrawer.GetFontSize: Integer;
|
|
begin
|
|
if FCanvas.Font.AggHeight = 0 then
|
|
Result := DEFAULT_FONT_SIZE else
|
|
Result := round(FCanvas.Font.AggHeight * 72 / 96);
|
|
end;
|
|
|
|
function TAggPasDrawer.GetFontStyle: TChartFontStyles;
|
|
begin
|
|
Result := [];
|
|
if FCanvas.Font.Bold then Include(Result, cfsBold);
|
|
if FCanvas.Font.Italic then Include(Result, cfsItalic);
|
|
if FCanvas.Font.Underline then Include(Result, cfsUnderline);
|
|
if FCanvas.Font.StrikeThrough then Include(Result, cfsStrikeout);
|
|
end;
|
|
|
|
function TAggPasDrawer.GetPenColor: TChartColor;
|
|
begin
|
|
Result := FCanvas.Pen.Color;
|
|
end;
|
|
|
|
procedure TAggPasDrawer.Line(AX1, AY1, AX2, AY2: Integer);
|
|
begin
|
|
FCanvas.Line(AX1, AY1, AX2, AY2);
|
|
end;
|
|
|
|
procedure TAggPasDrawer.Line(const AP1, AP2: TPoint);
|
|
begin
|
|
FCanvas.Line(AP1, AP2);
|
|
end;
|
|
|
|
procedure TAggPasDrawer.LineTo(AX, AY: Integer);
|
|
begin
|
|
FCanvas.LineTo(AX, AY);
|
|
end;
|
|
|
|
procedure TAggPasDrawer.MoveTo(AX, AY: Integer);
|
|
begin
|
|
FCanvas.MoveTo(AX, AY);
|
|
end;
|
|
|
|
procedure TAggPasDrawer.Polygon(
|
|
const APoints: array of TPoint; AStartIndex, ANumPts: Integer);
|
|
begin
|
|
if ANumPts <= 0 then exit;
|
|
FCanvas.Polygon(APoints, false, AStartIndex, ANumPts);
|
|
if FCanvas.Pen.Style <> psClear then
|
|
begin
|
|
FCanvas.Polyline(APoints, AStartIndex, ANumPts);
|
|
FCanvas.Line(APoints[ANumPts - 1], APoints[0])
|
|
end;
|
|
end;
|
|
|
|
procedure TAggPasDrawer.Polyline(
|
|
const APoints: array of TPoint; AStartIndex, ANumPts: Integer);
|
|
begin
|
|
FCanvas.Polyline(APoints, AStartIndex, ANumPts);
|
|
end;
|
|
|
|
procedure TAggPasDrawer.PrepareSimplePen(AColor: TChartColor);
|
|
begin
|
|
with FCanvas.Pen do begin
|
|
FPColor := ApplyTransparency(FChartColorToFPColorFunc(ColorOrMono(AColor)));
|
|
Style := psSolid;
|
|
Mode := pmCopy;
|
|
Width := 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TAggPasDrawer.PutImage(AX, AY: Integer; AImage: TFPCustomImage);
|
|
var
|
|
x, y: Integer;
|
|
begin
|
|
// FCanvas.Draw ignores alpha values.
|
|
for y := 0 to AImage.Height - 1 do
|
|
for x := 0 to AImage.Width - 1 do
|
|
if AImage[x, y].alpha > 0 then
|
|
FCanvas.Colors[AX + x, AY + y] := AImage[x, y];
|
|
end;
|
|
|
|
procedure TAggPasDrawer.RadialPie(
|
|
AX1, AY1, AX2, AY2: Integer;
|
|
AStartAngle16Deg, AAngleLength16Deg: Integer);
|
|
begin
|
|
FCanvas.RadialPie(
|
|
AX1, AY1, AX2, AY2, AStartAngle16Deg, AAngleLength16Deg);
|
|
end;
|
|
|
|
procedure TAggPasDrawer.Rectangle(AX1, AY1, AX2, AY2: Integer);
|
|
begin
|
|
FCanvas.Rectangle(AX1, AY1, AX2, AY2);
|
|
end;
|
|
|
|
procedure TAggPasDrawer.Rectangle(const ARect: TRect);
|
|
begin
|
|
FCanvas.Rectangle(ARect);
|
|
end;
|
|
|
|
procedure TAggPasDrawer.ResetFont;
|
|
begin
|
|
FCanvas.Font.Orientation := 0;
|
|
end;
|
|
|
|
procedure TAggPasDrawer.SetBrush(ABrush: TFPCustomBrush);
|
|
begin
|
|
with FCanvas.Brush do begin
|
|
Style := ABrush.Style;
|
|
Image := ABrush.Image;
|
|
Pattern := ABrush.Pattern;
|
|
FPColor := ApplyTransparency(FPColorOrMono(ABrush.FPColor));
|
|
end;
|
|
end;
|
|
|
|
procedure TAggPasDrawer.SetBrushColor(AColor: TChartColor);
|
|
begin
|
|
FCanvas.Brush.FPColor :=
|
|
ApplyTransparency(FChartColorToFPColorFunc(ColorOrMono(AColor)));
|
|
end;
|
|
|
|
procedure TAggPasDrawer.SetBrushParams(
|
|
AStyle: TFPBrushStyle; AColor: TChartColor);
|
|
begin
|
|
SetBrushColor(AColor);
|
|
FCanvas.Brush.Style := AStyle;
|
|
end;
|
|
|
|
procedure TAggPasDrawer.SetFont(AFont: TFPCustomFont);
|
|
var
|
|
f: TAggLCLFont;
|
|
fontSize: Integer;
|
|
fontName: String;
|
|
begin
|
|
if (AFont.Name = '') or (Lowercase(AFont.Name) = 'default') then
|
|
fontName := 'LiberationSans-Regular'
|
|
else
|
|
fontName := AFont.Name;
|
|
{$IF DEFINED(LCLGtk2) or DEFINED(LCLGtk3) or DEFINED(LCLQt) or DEFINED(LCLQt5)}
|
|
fontName := FFontDir + fontName + '.ttf';
|
|
{$ENDIF}
|
|
fontSize := IfThen(AFont.Size = 0, DEFAULT_FONT_SIZE, AFont.Size);
|
|
f := FCanvas.Font;
|
|
f.LoadFromFile(fontName, f.SizeToAggHeight(fontSize), AFont.Bold, AFont.Italic);
|
|
f.FPColor := ApplyTransparency(FPColorOrMono(AFont.FPColor));
|
|
f.AggAngle := -OrientToRad(FGetFontOrientationFunc(AFont));
|
|
end;
|
|
|
|
type
|
|
TAggLCLPenCrack = class(TAggLCLPen);
|
|
|
|
procedure TAggPasDrawer.SetPen(APen: TFPCustomPen);
|
|
begin
|
|
TAggLCLPenCrack(FCanvas.Pen).DoCopyProps(APen);
|
|
FCanvas.Pen.FPColor := ApplyTransparency(FPColorOrMono(APen.FPColor));
|
|
end;
|
|
|
|
procedure TAggPasDrawer.SetPenColor(AColor: TChartColor);
|
|
begin
|
|
FCanvas.Pen.FPColor := ApplyTransparency(FChartColorToFPColorFunc(ColorOrMono(AColor)));
|
|
end;
|
|
|
|
procedure TAggPasDrawer.SetPenParams(AStyle: TFPPenStyle; AColor: TChartColor;
|
|
AWidth: Integer = 1);
|
|
begin
|
|
FCanvas.Pen.Style := AStyle;
|
|
FCanvas.Pen.Width := AWidth;
|
|
FCanvas.Pen.FPColor := ApplyTransparency(FChartColorToFPColorFunc(ColorOrMono(AColor)));
|
|
end;
|
|
|
|
procedure TAggpasDrawer.SetPenWidth(AWidth: Integer);
|
|
begin
|
|
FCanvas.Pen.Width := AWidth;
|
|
end;
|
|
|
|
function TAggPasDrawer.SimpleTextExtent(const AText: String): TPoint;
|
|
begin
|
|
Result := FCanvas.TextExtent(AText);
|
|
end;
|
|
|
|
procedure TAggPasDrawer.SimpleTextOut(AX, AY: Integer; const AText: String);
|
|
var
|
|
h: Integer;
|
|
p: TPoint;
|
|
begin
|
|
h := SimpleTextExtent('Tg').y;
|
|
p := RotatePoint(Point(0, h * 9 div 10), FCanvas.Font.AggAngle);
|
|
// * correction factor 9/10 needed to fit the text into bounding box
|
|
FCanvas.TextOut(AX + p.X, AY + p.Y - h, AText);
|
|
// -h to avoid rotated text drifting away
|
|
end;
|
|
|
|
initialization
|
|
// Suppress incorrect "TAGeometry is unused" hint
|
|
Unused(DoublePoint(0, 0));
|
|
|
|
end.
|
|
|