mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-02 18:23:44 +02:00
184 lines
5.4 KiB
ObjectPascal
184 lines
5.4 KiB
ObjectPascal
{
|
|
Implements support for drawing to the LCL TCanvas via AggPas
|
|
|
|
License: The same modified LGPL as the Free Pascal RTL
|
|
See the file COPYING.modifiedLGPL for more details
|
|
|
|
AUTHORS: Felipe Monteiro de Carvalho
|
|
}
|
|
unit fpvectorial2aggpas;
|
|
|
|
{$ifdef fpc}
|
|
{$mode objfpc}{$h+}
|
|
{$endif}
|
|
|
|
{$define USE_CANVAS_CLIP_REGION}
|
|
{.$define DEBUG_CANVAS_CLIP_REGION}
|
|
|
|
{.$define FPVECTORIAL_DEBUG_DIMENSIONS}
|
|
{.$define FPVECTORIAL_TOCANVAS_DEBUG}
|
|
{.$define FPVECTORIAL_DEBUG_BLOCKS}
|
|
{.$define FPVECTORIAL_AUTOFIT_DEBUG}
|
|
{.$define FPVECTORIAL_SUPPORT_LAZARUS_1_6}
|
|
// visual debugs
|
|
{.$define FPVECTORIAL_TOCANVAS_ELLIPSE_VISUALDEBUG}
|
|
{.$define FPVECTORIAL_RENDERINFO_VISUALDEBUG}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Math, TypInfo, contnrs, Types,
|
|
// FCL-Image
|
|
FPCanvas, FPImage, FPWriteBMP,
|
|
// lazutils
|
|
GraphType, LazUTF8, laz2_dom,
|
|
// LCL
|
|
LazRegions, Graphics, LCLIntf, LCLType, IntfGraphics, InterfaceBase,
|
|
// AggPas
|
|
agg_fpimage, Agg_LCL,
|
|
// fpvectorial
|
|
fpvutils, fpvectorial;
|
|
|
|
type
|
|
|
|
{ TFPVAggPasRenderer }
|
|
|
|
TFPVAggPasRenderer = class(TvRenderer)
|
|
private
|
|
Bitmap: TBitmap;
|
|
AggLCLCanvas: TAggLCLCanvas;
|
|
public
|
|
procedure BeginRender(var ARenderInfo: TvRenderInfo; ADoDraw: Boolean); override;
|
|
procedure EndRender(var ARenderInfo: TvRenderInfo; ADoDraw: Boolean); override;
|
|
// TPath
|
|
procedure TPath_Render(var ARenderInfo: TvRenderInfo; ADoDraw: Boolean; APath: TPath); override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
|
|
{ TFPVAggPasRenderer }
|
|
|
|
procedure TFPVAggPasRenderer.BeginRender(var ARenderInfo: TvRenderInfo; ADoDraw: Boolean);
|
|
var
|
|
HasFont: Boolean;
|
|
FontFilename: String;
|
|
begin
|
|
Bitmap := TBitmap.Create;
|
|
AggLCLCanvas:=TAggLCLCanvas.Create;
|
|
AggLCLCanvas.Image.PixelFormat:=afpimRGBA32;
|
|
AggLCLCanvas.Image.SetSize(2000, 2000);
|
|
|
|
{$IFDEF LCLGtk2}
|
|
{HasFont:=true;
|
|
FontFilename:=SetDirSeparators('../../verdana.ttf');
|
|
if not FileExistsUTF8(FontFilename) then begin
|
|
ShowMessage('file not found: '+FontFilename+' CurDir='+GetCurrentDirUTF8);
|
|
HasFont:=false;
|
|
end; }
|
|
// paint to agg canvas
|
|
{with AggLCLCanvas do begin
|
|
if HasFont then begin
|
|
Font.LoadFromFile(FontFilename);
|
|
Font.Size:=10;
|
|
Font.Color:=clBlack;
|
|
end;}
|
|
{$ELSE}
|
|
//HasFont:=false;
|
|
{$ENDIF}
|
|
|
|
// solid white background
|
|
AggLCLCanvas.Brush.Color:=clWhite;
|
|
AggLCLCanvas.FillRect(0, 0, AggLCLCanvas.Width, AggLCLCanvas.Height);
|
|
end;
|
|
|
|
procedure TFPVAggPasRenderer.EndRender(var ARenderInfo: TvRenderInfo; ADoDraw: Boolean);
|
|
begin
|
|
// convert to LCL native pixel format
|
|
Bitmap.LoadFromIntfImage(AggLCLCanvas.Image.IntfImg);
|
|
TCanvas(ARenderInfo.Canvas).Draw(0, 0, Bitmap);
|
|
|
|
AggLCLCanvas.Free;
|
|
Bitmap.Free;
|
|
end;
|
|
|
|
procedure TFPVAggPasRenderer.TPath_Render(var ARenderInfo: TvRenderInfo;
|
|
ADoDraw: Boolean; APath: TPath);
|
|
var
|
|
ADest: TFPCustomCanvas absolute ARenderInfo.Canvas;
|
|
ADestX: Integer absolute ARenderInfo.DestX;
|
|
ADestY: Integer absolute ARenderInfo.DestY;
|
|
AMulX: Double absolute ARenderInfo.MulX;
|
|
AMulY: Double absolute ARenderInfo.MulY;
|
|
//
|
|
i, j, curPt: Integer;
|
|
coordX, coordY: Integer;
|
|
curSegment: TPathSegment;
|
|
cur2DSegment: T2DSegment absolute curSegment;
|
|
pts: TPointsArray;
|
|
begin
|
|
if not ADoDraw then Exit;
|
|
|
|
AggLCLCanvas.Pen.Style := APath.Pen.Style;
|
|
AggLCLCanvas.Pen.Width := APath.Pen.Width;
|
|
AggLCLCanvas.Pen.FPColor := APath.Pen.Color;
|
|
AggLCLCanvas.Brush.Style := APath.Brush.Style;
|
|
AggLCLCanvas.Brush.FPColor := APath.Brush.Color;
|
|
AggLCLCanvas.Brush.AggFillEvenOdd := APath.ClipMode = vcmEvenOddRule;
|
|
|
|
AggLCLCanvas.AggResetPath;
|
|
APath.PrepareForSequentialReading;
|
|
for j := 0 to APath.Len - 1 do
|
|
begin
|
|
curSegment := TPathSegment(APath.Next);
|
|
case curSegment.SegmentType of
|
|
stMoveTo:
|
|
begin
|
|
inc(i);
|
|
coordX := CoordToCanvasX(cur2DSegment.X, ADestX, AMulX);
|
|
coordY := CoordToCanvasY(cur2DSegment.Y, ADestY, AMulY);
|
|
AggLCLCanvas.AggMoveTo(coordX, coordY);
|
|
end;
|
|
st2DLineWithPen, st2DLine, st3DLine:
|
|
begin
|
|
coordX := CoordToCanvasX(cur2DSegment.X, ADestX, AMulX);
|
|
coordY := CoordToCanvasY(cur2DSegment.Y, ADestY, AMulY);
|
|
if curSegment.SegmentType = st2DLineWithPen then
|
|
begin
|
|
AggLCLCanvas.Pen.FPColor := APath.AdjustColorToBackground(T2DSegmentWithPen(Cur2DSegment).Pen.Color, ARenderInfo);
|
|
AggLCLCanvas.Pen.Width := T2DSegmentWithPen(cur2DSegment).Pen.Width;
|
|
AggLCLCanvas.Pen.Style := T2DSegmentWithPen(cur2DSegment).Pen.Style;
|
|
AggLCLCanvas.AggLineTo(coordX, coordY);
|
|
AggLCLCanvas.Pen.Style := APath.Pen.Style;
|
|
AggLCLCanvas.Pen.Width := APath.Pen.Width;
|
|
AggLCLCanvas.Pen.FPColor := APath.Pen.Color;
|
|
end
|
|
else
|
|
AggLCLCanvas.AggLineTo(coordX, coordY);
|
|
end;
|
|
st2DBezier, st3DBezier, st2DEllipticalArc:
|
|
begin
|
|
coordX := CoordToCanvasX(T2DSegment(curSegment.Previous).X, ADestX, AMulX);
|
|
coordY := CoordToCanvasY(T2DSegment(curSegment.Previous).Y, ADestY, AMulY);
|
|
|
|
SetLength(pts, 1);
|
|
pts[0] := Point(coordX, coordY);
|
|
curSegment.AddToPoints(ADestX, ADestY, AMulX, AMulY, pts);
|
|
for curPt := 0 to Length(pts)-1 do
|
|
begin
|
|
AggLCLCanvas.AggLineTo(pts[curPt].X, pts[curPt].Y);
|
|
end;
|
|
AggLCLCanvas.AggMoveTo(pts[High(pts)].X, pts[High(pts)].Y);
|
|
end;
|
|
end;
|
|
end;
|
|
if APath.Len > 0 then
|
|
begin
|
|
AggLCLCanvas.AggClosePolygon;
|
|
AggLCLCanvas.AggDrawPath(AGG_FillAndStroke, False);
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|