1 // Copyright (c) 2007 - 2008
2 //
3 // Permission to copy, use, modify, sell and distribute this software
4 // is granted provided this copyright notice appears in all copies.
5 // This software is provided "as is" without express or implied
6 // warranty, and with no claim as to its suitability for any purpose.
7 //
8 //
9 //
10 unit agg_fpimage;
11 
12 
13 {$mode objfpc}{$H+}
14 
15 interface
16 
17 {$IFDEF LINUX}
18   {$DEFINE AGG2D_USE_FREETYPE}
19 {$ENDIF}
20 {$IFDEF FREEBSD}
21   {$DEFINE AGG2D_USE_FREETYPE}
22 {$ENDIF}
23 {$IFDEF WINDOWS}
24   {$DEFINE AGG2D_USE_WINFONTS}
25 {$ENDIF}
26 {$IFNDEF AGG2D_USE_WINFONTS}
27  {$IFNDEF AGG2D_USE_FREETYPE}
28   {$DEFINE AGG2D_NO_FONT}
29  {$ENDIF}
30 {$ENDIF}
31 
32 uses
33   agg_basics ,
34   agg_array ,
35   agg_trans_affine ,
36   agg_trans_viewport ,
37   agg_path_storage ,
38   agg_conv_stroke ,
39   agg_conv_transform ,
40   agg_conv_curve ,
41   agg_rendering_buffer ,
42   agg_renderer_base ,
43   agg_renderer_scanline ,
44   agg_span_gradient ,
45   agg_span_image_filter_rgba ,
46   agg_span_image_resample_rgba ,
47   agg_span_converter ,
48   agg_span_interpolator_linear ,
49   agg_span_allocator ,
50   agg_rasterizer_scanline_aa ,
51   agg_gamma_functions ,
52   agg_scanline_u ,
53   agg_scanline,
54   agg_arc ,
55   agg_bezier_arc ,
56   agg_rounded_rect ,
57   agg_font_engine ,
58   agg_font_cache_manager ,
59   agg_pixfmt ,
60   agg_pixfmt_rgb ,
61   agg_pixfmt_rgba ,
62   agg_color ,
63   agg_math_stroke ,
64   agg_image_filters ,
65   agg_vertex_source ,
66   agg_render_scanlines ,
67 
68   {$IFDEF AGG2D_USE_FREETYPE}
69   agg_font_freetype,
70   {$ENDIF }
71   {$IFDEF AGG2D_USE_WINFONTS}
72   agg_font_win32_tt,
73   {$ENDIF }
74 
75   Math, types ,
76   {$IFDEF WINDOWS}
77   Windows ,
78   {$ENDIF}
79 
80   Classes, SysUtils, FPimage, FPCanvas;
81 
82   { GLOBAL VARIABLES & CONSTANTS }
83 const
84   // LineJoin
85   AGG_JoinMiter = miter_join;
86   AGG_JoinRound = round_join;
87   AGG_JoinBevel = bevel_join;
88 
89   // LineCap
90   AGG_CapButt   = butt_cap;
91   AGG_CapSquare = square_cap;
92   AGG_CapRound  = round_cap;
93 
94   // TextAlignment
95   AGG_AlignLeft   = 0;
96   AGG_AlignRight  = 1;
97   AGG_AlignCenter = 2;
98   AGG_AlignTop    = AGG_AlignRight;
99   AGG_AlignBottom = AGG_AlignLeft;
100 
101   // BlendMode
102   AGG_BlendAlpha      = end_of_comp_op_e;
103   AGG_BlendClear      = comp_op_clear;
104   AGG_BlendSrc        = comp_op_src;
105   AGG_BlendDst        = comp_op_dst;
106   AGG_BlendSrcOver    = comp_op_src_over;
107   AGG_BlendDstOver    = comp_op_dst_over;
108   AGG_BlendSrcIn      = comp_op_src_in;
109   AGG_BlendDstIn      = comp_op_dst_in;
110   AGG_BlendSrcOut     = comp_op_src_out;
111   AGG_BlendDstOut     = comp_op_dst_out;
112   AGG_BlendSrcAtop    = comp_op_src_atop;
113   AGG_BlendDstAtop    = comp_op_dst_atop;
114   AGG_BlendXor        = comp_op_xor;
115   AGG_BlendAdd        = comp_op_plus;
116   AGG_BlendSub        = comp_op_minus;
117   AGG_BlendMultiply   = comp_op_multiply;
118   AGG_BlendScreen     = comp_op_screen;
119   AGG_BlendOverlay    = comp_op_overlay;
120   AGG_BlendDarken     = comp_op_darken;
121   AGG_BlendLighten    = comp_op_lighten;
122   AGG_BlendColorDodge = comp_op_color_dodge;
123   AGG_BlendColorBurn  = comp_op_color_burn;
124   AGG_BlendHardLight  = comp_op_hard_light;
125   AGG_BlendSoftLight  = comp_op_soft_light;
126   AGG_BlendDifference = comp_op_difference;
127   AGG_BlendExclusion  = comp_op_exclusion;
128   AGG_BlendContrast   = comp_op_contrast;
129 
130 { TYPES DEFINITION }
131 type
132   PAggColor = ^TAggColor;
133   TAggColor = rgba8;
134 
135   TAggRectD = agg_basics.rect_d;
136 
137   TAggAffine = trans_affine;
138   PAggAffine = trans_affine_ptr;
139 
140   TAggFontRasterizer = gray8_adaptor_type;
141   PAggFontRasterizer = gray8_adaptor_type_ptr;
142 
143   TAggFontScanline = gray8_scanline_type;
144   PAggFontScanline = gray8_scanline_type_ptr;
145 
146   {$IFDEF AGG2D_USE_FREETYPE }
147   TAggFontEngine = font_engine_freetype_int32;
148   {$ENDIF}
149   {$IFDEF AGG2D_USE_WINFONTS }
150   TAggFontEngine = font_engine_win32_tt_int32;
151 
152   {$ENDIF }
153 
154   TAggGradient  = (
155     AGG_Solid ,
156     AGG_Linear ,
157     AGG_Radial );
158   TAggDirection = (
159     AGG_CW,
160     AGG_CCW );
161 
162   TAggLineJoin  = int;
163   TAggLineCap   = int;
164   TAggBlendMode = comp_op_e;
165 
166   TAggTextAlignment = int;
167 
168   TAggDrawPathFlag = (
169     AGG_FillOnly ,
170     AGG_StrokeOnly ,
171     AGG_FillAndStroke ,
172     AGG_FillWithLineColor );
173 
174   TAggViewportOption = (
175     AGG_Anisotropic ,
176     AGG_XMinYMin ,
177     AGG_XMidYMin ,
178     AGG_XMaxYMin ,
179     AGG_XMinYMid ,
180     AGG_XMidYMid ,
181     AGG_XMaxYMid ,
182     AGG_XMinYMax ,
183     AGG_XMidYMax ,
184     AGG_XMaxYMax );
185 
186   TAggImageFilter = (
187     AGG_NoFilter ,
188     AGG_Bilinear ,
189     AGG_Hanning ,
190     AGG_Hermite ,
191     AGG_Quadric ,
192     AGG_Bicubic ,
193     AGG_Catrom ,
194     AGG_Spline16 ,
195     AGG_Spline36 ,
196     AGG_Blackman144 );
197 
198   TAggImageResample = (
199     AGG_NoResample ,
200     AGG_ResampleAlways ,
201     AGG_ResampleOnZoomOut );
202 
203   TAggFontCacheType = (
204     AGG_RasterFontCache ,
205     AGG_VectorFontCache );
206 
207   PAggTransformations = ^TAggTransformations;
208   TAggTransformations = record
209     affineMatrix : array[0..5 ] of double;
210   end;
211 
212   { TAggRasterizerGamma }
213 
214   TAggRasterizerGamma = object(vertex_source )
215     m_alpha : gamma_multiply;
216     m_gamma : gamma_power;
217 
218     constructor Construct(alpha ,gamma : double );
219 
func_operator_gammanull220     function func_operator_gamma(x : double ) : double; virtual;
operator_arraynull221     function operator_array(i: unsigned): unsigned; virtual;
222   end;
223 
224   { TAggFP_renderer_scanline_aa }
225 
226   TAggFP_renderer_scanline_aa = object(renderer_scanline_aa)
227     procedure add_path(vs: vertex_source_ptr; path_id: unsigned=0); virtual;
228     procedure add_vertex(x, y: double; cmd: unsigned); virtual;
229     procedure clip_box(x1, y1, x2, y2: double); virtual;
230     procedure color_(c: aggclr_ptr); virtual;
231     procedure filling_rule(filling_rule_: filling_rule_e); virtual;
232     procedure gamma(gamma_function: vertex_source_ptr); virtual;
233     procedure reset; virtual;
_max_xnull234     function _max_x: int; virtual;
_max_ynull235     function _max_y: int; virtual;
_min_xnull236     function _min_x: int; virtual;
_min_ynull237     function _min_y: int; virtual;
hit_testnull238     function hit_test(tx, ty: int): boolean; virtual;
sweep_scanlinenull239     function sweep_scanline(sl: scanline_ptr): boolean; virtual;
sweep_scanline_emnull240     function sweep_scanline_em(sl: scanline_ptr): boolean; virtual;
rewind_scanlinesnull241     function rewind_scanlines: boolean; virtual;
242     procedure sort; virtual;
243   end;
244 
245 type
246   TAggFPImage = class;
247 
248   TAggFPImgPixelFormat = (
249     afpimRGB24,
250     afpimRGBA32
251     );
252 
253   TAggFPImgOperation = (
254     afpioResized,
255     afpioPixelFormatChanged,
256     afpioDestroying
257     );
258   TAggFPImgEvent = procedure(TheImage: TAggFPImage;
259                              Operation: TAggFPImgOperation) of object;
260 
261   { TAggFPImage }
262 
263   TAggFPImage = class(TFPCustomImage)
264   private
265     FData: PByte;
266     FListeners: array of TAggFPImgEvent;
267     FPixelFormat: TAggFPImgPixelFormat;
268   protected
269     procedure SetInternalColor(x, y: integer; const Value: TFPColor); override;
GetInternalColornull270     function GetInternalColor(x, y: integer): TFPColor; override;
GetInternalPixelnull271     function GetInternalPixel(x, y: integer): integer; override;
272     procedure SetInternalPixel(x, y: integer; Value: integer); override;
273     procedure SetPixelFormat(const AValue: TAggFPImgPixelFormat); virtual;
274     procedure SetUsePalette(Value: boolean); override;
275     procedure ReallocData; virtual;
276   public
277     RenderingBuffer: rendering_buffer;
278     constructor Create(AWidth, AHeight: integer); override;
279     destructor Destroy; override;
280     procedure Assign(Source: TPersistent); override;
281     procedure SetSize(AWidth, AHeight: integer); override;
282     procedure AddListener(Event: TAggFPImgEvent);
283     procedure RemoveListener(Event: TAggFPImgEvent);
284     procedure NotifyListeners(Operation: TAggFPImgOperation);
285     property PixelFormat: TAggFPImgPixelFormat read FPixelFormat write SetPixelFormat;
286     property Data: PByte read FData;
DataSizenull287     function DataSize: PtrUInt; // total size of Data in bytes
LineSizenull288     function LineSize: PtrUInt; // size of a line in bytes including padding
289   end;
290 
291   { TAggFPBrush }
292 
293   TAggFPBrush = class(TFPCustomBrush)
294   private
295     FAggColor: TAggColor;
296     FAggFillEvenOdd: boolean;
297   protected
298     procedure SetFPColor(const AValue: TFPColor); override;
299     procedure SetAggColor(const AValue: TAggColor); virtual;
300     procedure SetStyle(AValue: TFPBrushStyle); override;
301     procedure SetAggFillEvenOdd(const AValue: boolean); virtual;
302     procedure DoCopyProps(From: TFPCanvasHelper); override;
303   public
304     property AggColor: TAggColor read FAggColor write SetAggColor;
305     property AggFillEvenOdd: boolean read FAggFillEvenOdd write SetAggFillEvenOdd;
306     property Pattern; // not supported, always 0
307     property Image; // not supported, always nil
308     property Style; // not supported, always bsSolid
309   end;
310 
311   { TAggFPPen }
312 
313   TAggFPPen = class(TFPCustomPen)
314   private
315     FAggColor: TAggColor;
316     FAggLineCap: TAggLineCap;
317     FAggLineJoin: TAggLineJoin;
318     FAggLineWidth: double;
319   protected
320     procedure SetAggLineCap(const AValue: TAggLineCap); virtual;
321     procedure SetAggLineJoin(const AValue: TAggLineJoin); virtual;
322     procedure SetAggLineWidth(const AValue: double); virtual;
323     procedure SetWidth(AValue: Integer); override;
324     procedure SetFPColor(const AValue: TFPColor); override;
325     procedure SetAggColor(const AValue: TAggColor); virtual;
326     procedure DoCopyProps(From: TFPCanvasHelper); override;
327   public
328     constructor Create; override;
329     property AggLineCap: TAggLineCap read FAggLineCap write SetAggLineCap default AGG_CapRound;
330     property AggLineJoin: TAggLineJoin read FAggLineJoin write SetAggLineJoin default AGG_JoinRound;
331     property AggLineWidth: double read FAggLineWidth write SetAggLineWidth;
332     property AggColor: TAggColor read FAggColor write SetAggColor;
333     property Pattern; // not supported, always 0
334     property Style; // not supported, always psSolid
335     property Mode; // not supported, always pmBlack
336   end;
337 
338   { TAggFPFont }
339 
340   TAggFPFont = class(TFPCustomFont)
341   private
342     FAggAlignX: TAggTextAlignment;
343     FAggAlignY: TAggTextAlignment;
344     FAggAngle: double;
345     FAggCache: TAggFontCacheType;
346     FAggColor: TAggColor;
347     FAggFlipY: boolean;
348     FAggHeight: double;
349     FAggHinting: boolean;
350     FAggUseOnlyFont: boolean;
351   protected
352     procedure DoCopyProps(From: TFPCanvasHelper); override;
353     procedure SetFPColor(const AValue: TFPColor); override;
354     procedure SetAggColor(const AValue: TAggColor); virtual;
355     procedure SetAggAlignX(const AValue: TAggTextAlignment); virtual;
356     procedure SetAggAlignY(const AValue: TAggTextAlignment); virtual;
357     procedure SetAggAngle(const AValue: double); virtual;
358     procedure SetAggFlipY(const AValue: boolean); virtual;
359     procedure SetAggHeight(const AValue: double); virtual;
360     procedure SetAggHinting(const AValue: boolean); virtual;
361     procedure SetSize(AValue: integer); override;
362   public
363     constructor Create; override;
364     procedure LoadFromFile(aFilename : String;
365               const NewHeight: double = 10.0;
366               const NewBold: boolean = false;
367               const NewItalic: boolean = false;
368               const NewCache : TAggFontCacheType = AGG_VectorFontCache;
369               const NewAngle : double = 0.0 ;
370               const NewHinting: boolean = true);
AggHeightToSizenull371     function AggHeightToSize(const h: double): double; virtual;
SizeToAggHeightnull372     function SizeToAggHeight(const s: double): double; virtual;
373     property AggColor: TAggColor read FAggColor write SetAggColor;
374     property AggAlignX: TAggTextAlignment read FAggAlignX write SetAggAlignX default AGG_AlignLeft;
375     property AggAlignY: TAggTextAlignment read FAggAlignY write SetAggAlignY default AGG_AlignBottom;
376     property AggHinting: boolean read FAggHinting write SetAggHinting default True;// only freetype
377     property AggAngle: double read FAggAngle write SetAggAngle;
378     property AggCache: TAggFontCacheType read FAggCache;
379     property AggHeight: double read FAggHeight write SetAggHeight;
380     property AggFlipY: boolean read FAggFlipY write SetAggFlipY;
381     property AggUseOnlyFont: boolean read FAggUseOnlyFont write FAggUseOnlyFont default True;// do not use Pen and Brush
382     property Bold; // only windows
383     property Italic; // only windows
384     property Underline; // not supported
385     {$IF (FPC_FULLVERSION<=20600) or (FPC_FULLVERSION=20602)}
386     property StrikeTrough; //old version with typo
387     {$ELSE}
388     property StrikeThrough;
389     {$ENDIF}
390   end;
391 
392   { TAggFPPath }
393 
394   TAggFPPath = class(TFPCanvasHelper)
395   private
396     FAggColor: TAggColor;
397     procedure SetAggColor(const AValue: TAggColor);
398   protected
399     procedure DoCopyProps(From: TFPCanvasHelper); override;
400   public
401     m_path: path_storage;
402     m_convCurve: conv_curve;
403     constructor Create; override;
404     destructor Destroy; override;
405     property AggColor: TAggColor read FAggColor write SetAggColor;
406   end;
407 
408   { TAggFPCanvas }
409 
410   TAggFPCanvas = class(TFPCustomCanvas)
411   protected
412     FAggBrush: TAggFPBrush;
413     FAggFont: TAggFPFont;
414     FAggPen: TAggFPPen;
415     FAggPath: TAggFPPath;
416     FImage: TAggFPImage;
417     FUseUTF8: boolean;
418 
419     m_rbuf : rendering_buffer;
420 
421     m_pixFormat ,m_pixFormatComp ,m_pixFormatPre ,m_pixFormatCompPre : pixel_formats;
422     m_renBase   ,m_renBaseComp   ,m_renBasePre   ,m_renBaseCompPre   : renderer_base;
423 
424     m_renSolid ,m_renSolidComp : renderer_scanline_aa_solid;
425 
426     m_allocator : span_allocator;
427     m_clipBox   : TAggRectD;
428 
429     m_blendMode ,m_imageBlendMode : TAggBlendMode;
430 
431     m_imageBlendColor : TAggColor;
432 
433     m_scanline   : scanline_u8;
434     m_rasterizer : rasterizer_scanline_aa;
435 
436     m_masterAlpha ,m_antiAliasGamma : double;
437 
438     m_fillGradient ,m_lineGradient : pod_auto_array;
439 
440     m_fillGradientFlag ,m_lineGradientFlag : TAggGradient;
441 
442     m_fillGradientMatrix ,m_lineGradientMatrix : trans_affine;
443 
444     m_fillGradientD1 ,
445     m_lineGradientD1 ,
446     m_fillGradientD2 ,
447     m_lineGradientD2 : double;
448 
449     m_imageFilter    : TAggImageFilter;
450     m_imageResample  : TAggImageResample;
451     m_imageFilterLut : image_filter_lut;
452 
453     m_fillGradientInterpolator ,
454     m_lineGradientInterpolator : span_interpolator_linear;
455 
456     m_linearGradientFunction : gradient_x;
457     m_radialGradientFunction : gradient_circle;
458 
459     m_evenOddFlag : boolean;
460 
461     m_transform : trans_affine;
462 
463     m_convStroke : conv_stroke;
464 
465     m_pathTransform ,m_strokeTransform : conv_transform;
466 
467     {$IFDEF AGG2D_USE_WINFONTS }
468     m_fontDC : HDC;
469     {$ENDIF }
470 
471     {$IFNDEF AGG2D_NO_FONT}
472     m_fontEngine       : TAggFontEngine;
473     m_fontCacheManager : font_cache_manager;
474     {$ENDIF}
475 
476     // Other Pascal-specific members
477     m_gammaNone  : gamma_none;
478     m_gammaAgg2D : TAggRasterizerGamma;
479 
480     m_ifBilinear    : image_filter_bilinear;
481     m_ifHanning     : image_filter_hanning;
482     m_ifHermite     : image_filter_hermite;
483     m_ifQuadric     : image_filter_quadric;
484     m_ifBicubic     : image_filter_bicubic;
485     m_ifCatrom      : image_filter_catrom;
486     m_ifSpline16    : image_filter_spline16;
487     m_ifSpline36    : image_filter_spline36;
488     m_ifBlackman144 : image_filter_blackman144;
489 
490     procedure Agg2DRenderer_render(renBase: renderer_base_ptr;
491       renSolid: renderer_scanline_aa_solid_ptr; fillColor_, UseFont: boolean);
492     procedure Agg2DRenderer_render(
493                renBase : renderer_base_ptr;
494                renSolid : renderer_scanline_aa_solid_ptr;
495                ras : gray8_adaptor_type_ptr;
496                sl : gray8_scanline_type_ptr;
497                UseFont: boolean );
498     procedure addLine(const x1 ,y1 ,x2 ,y2 : double );
GetAggTransformationsnull499     function GetAggTransformations: TAggTransformations;
500 
501     procedure render(fillColor_: boolean; UseFont: boolean = false);
502     procedure render(ras : PAggFontRasterizer; sl : PAggFontScanline );
503     procedure Agg2DRenderer_renderImage(
504                    img : TAggFPImage;
505                    renBase : renderer_base_ptr;
506                    interpolator : span_interpolator_linear_ptr );
507 
508     procedure SetAggTransformations(const AValue: TAggTransformations);
509     procedure SetAntiAliasGamma(const AValue: double);
510     procedure SetBlendMode(const AValue: TAggBlendMode);
511     procedure SetImageFilter(const AValue: TAggImageFilter);
512     procedure SetImageResample(const AValue: TAggImageResample);
513     procedure SetMasterAlpha(const AValue: double);
514     procedure UpdateRasterizerGamma;
515 
516   protected
517     procedure DoCopyRect(DstX, DstY: integer; SrcCanvas: TFPCustomCanvas;
518       const SourceRect: TRect); override;
DoCreateDefaultBrushnull519     function DoCreateDefaultBrush: TFPCustomBrush; override;
DoCreateDefaultFontnull520     function DoCreateDefaultFont: TFPCustomFont; override;
DoCreateDefaultPennull521     function DoCreateDefaultPen: TFPCustomPen; override;
DoCreateDefaultPathnull522     function DoCreateDefaultPath: TAggFPPath; virtual;
DoCreateDefaultImagenull523     function DoCreateDefaultImage: TAggFPImage; virtual;
524     procedure DoDraw(x, y: integer; const SrcImage: TFPCustomImage); override;
525     procedure DoEllipse(const Bounds: TRect); override;
526     procedure DoEllipseFill(const Bounds: TRect); override;
527     procedure DoFloodFill(x, y: integer); override;
DoGetTextHeightnull528     function DoGetTextHeight(str: string): integer; override;
529     procedure DoGetTextSize(str: string; var w, h: integer); override;
DoGetTextWidthnull530     function DoGetTextWidth(str: string): integer; override;
531     procedure DoLine(x1, y1, x2, y2: integer); override;
532     procedure DoPolygon(const points: array of TPoint); override;
533     procedure DoPolygonFill(const points: array of TPoint); override;
534     procedure DoPolyline(const points: array of TPoint); override;
535     procedure DoRectangle(const Bounds: TRect); override;
536     procedure DoRectangleFill(const Bounds: TRect); override;
537     procedure DoTextOut(x, y: integer; str: string); override;
GetColornull538     function GetColor(x, y: integer): TFPColor; override;
GetHeightnull539     function GetHeight: integer; override;
GetWidthnull540     function GetWidth: integer; override;
541     procedure SetColor(x, y: integer; const Value: TFPColor); override;
542     procedure SetHeight(AValue: integer); override;
543     procedure SetWidth(AValue: integer); override;
544     procedure OnImageOperation(Img: TAggFPImage; Operation: TAggFPImgOperation); virtual;
545   public
546     constructor Create;
547     destructor Destroy; override;
548     procedure ClearSettings; virtual;
549 
550     procedure AggClearAll(const c : TAggColor );
551     procedure AggClearAll(const r ,g ,b : byte; a : byte = 255 );
552 
553     property Image: TAggFPImage read FImage;
554     property Pen: TAggFPPen read FAggPen;
555     property Brush: TAggFPBrush read FAggBrush;
556     property Font: TAggFPFont read FAggFont;
557     property Path: TAggFPPath read FAggPath;
558 
559     procedure Erase; override;
560 
561     // special AggPas functions, prefixed with Agg to avoid name clashing
562 
563     property AggBlendMode: TAggBlendMode read m_blendMode write SetBlendMode;
564     property AggMasterAlpha: double read m_masterAlpha write SetMasterAlpha;
565     property AggAntiAliasGamma: double read m_antiAliasGamma write SetAntiAliasGamma;
566 
567     // Basic AggPas Shapes
568     procedure AggLine     (const x1 ,y1 ,x2 ,y2 : double );
569     procedure AggTriangle (const x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double );
570     procedure AggRectangle(const x1 ,y1 ,x2 ,y2 : double );
571 
572     procedure AggRoundedRect(const x1 ,y1 ,x2 ,y2 ,r : double );
573     procedure AggRoundedRect(const x1 ,y1 ,x2 ,y2 ,rx ,ry : double );
574     procedure AggRoundedRect(const x1 ,y1 ,x2 ,y2 ,
575                                    rxBottom ,ryBottom ,
576                                    rxTop ,ryTop : double );
577 
578     procedure AggEllipse(const cx ,cy ,rx ,ry : double );
579 
580     procedure AggArc (const cx ,cy ,rx ,ry ,start ,endangle : double ); // start: 0 at 3'o clock, clockwise in rad: 180deg = 1pi
581     procedure AggStar(const cx, cy, r1, r2, startAngle: double; numRays: integer);
582 
583     procedure AggCurve(const x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double );
584     procedure AggCurve(const x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double );
585 
586     procedure AggPolygon (const xy : PDouble; numPoints : integer );
587     procedure AggPolyline(const xy : PDouble; numPoints : integer );
588 
589     procedure AggFillLinearGradient(const x1 ,y1 ,x2 ,y2 : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
590     procedure AggLineLinearGradient(const x1 ,y1 ,x2 ,y2 : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
591 
592     procedure AggFillRadialGradient(const x ,y ,r : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
593     procedure AggLineRadialGradient(const x ,y ,r : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
594 
595     procedure AggFillRadialGradient(const x ,y ,r : double; c1 ,c2 ,c3 : TAggColor );
596     procedure AggLineRadialGradient(const x ,y ,r : double; c1 ,c2 ,c3 : TAggColor );
597 
598     procedure AggFillRadialGradient(const x ,y ,r : double );
599     procedure AggLineRadialGradient(const x ,y ,r : double );
600 
601     // Path Commands
602     procedure AggResetPath;
603 
604     procedure AggMoveTo (const x ,y : double );
605     procedure AggMoveRel(const dx ,dy : double );
606 
607     procedure AggLineTo (const x ,y : double );
608     procedure AggLineRel(const dx ,dy : double );
609 
610     procedure AggHorLineTo (const x : double );
611     procedure AggHorLineRel(const dx : double );
612 
613     procedure AggVerLineTo (const y : double );
614     procedure AggVerLineRel(const dy : double );
615 
616     procedure AggArcTo(const
617               rx ,ry ,angle : double;
618               largeArcFlag ,sweepFlag : boolean;
619               const x ,y : double );
620 
621     procedure AggArcRel(const
622               rx ,ry ,angle : double;
623               largeArcFlag ,sweepFlag : boolean;
624               const dx ,dy : double );
625 
626     procedure AggQuadricCurveTo (const xCtrl ,yCtrl ,xTo ,yTo : double );
627     procedure AggQuadricCurveRel(const dxCtrl ,dyCtrl ,dxTo ,dyTo : double );
628     procedure AggQuadricCurveTo (const xTo ,yTo : double );
629     procedure AggQuadricCurveRel(const dxTo ,dyTo : double );
630 
631     procedure AggCubicCurveTo (const xCtrl1 ,yCtrl1 ,xCtrl2 ,yCtrl2 ,xTo ,yTo : double );
632     procedure AggCubicCurveRel(const dxCtrl1 ,dyCtrl1 ,dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo : double );
633     procedure AggCubicCurveTo (const xCtrl2 ,yCtrl2 ,xTo ,yTo : double );
634     procedure AggCubicCurveRel(const dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo : double );
635 
636     procedure AggAddEllipse(const cx ,cy ,rx ,ry : double; dir : TAggDirection );
637 
638     procedure AggClosePolygon;
639     procedure AggDrawPath(flag: TAggDrawPathFlag = AGG_FillAndStroke;
640                           UseFont: boolean = false);
641 
642     // Clipping
643     procedure AggSetClipBox(const x1 ,y1 ,x2 ,y2 : double );
644     function  AggGetClipBox : TAggRectD;
645     procedure AggClearClipBox(const c : TAggColor );
646     procedure AggClearClipBox(r ,g ,b : byte; a : byte = 255 );
647     function  AggInClipBox(const worldX ,worldY : double ) : boolean;
648 
649     // Affine Transformations
650     property AggTransformations: TAggTransformations read GetAggTransformations
651                                                     write SetAggTransformations;
652     procedure AggResetTransformations;
653 
654     procedure AggAffine(const tr : PAggAffine );
655     procedure AggAffine(const tr : PAggTransformations );
656 
657     procedure AggRotate   (const angle : double );
658     procedure AggScale    (const sx ,sy : double );
659     procedure AggSkew     (const sx ,sy : double );
660     procedure AggTranslate(const x ,y : double );
661 
662     procedure AggParallelogram(const x1 ,y1 ,x2 ,y2 : double; para : PDouble );
663 
664     procedure AggViewport(const
665               worldX1  ,worldY1  ,worldX2  ,worldY2 ,
666               screenX1 ,screenY1 ,screenX2 ,screenY2 : double;
667               const opt : TAggViewportOption = AGG_XMidYMid );
668 
669     // Coordinates Conversions
670     procedure AggWorldToScreen(x ,y : PDouble );
671     procedure AggScreenToWorld(x ,y : PDouble );
672     function  AggWorldToScreen(const scalar : double ) : double;
673     function  AggScreenToWorld(const scalar : double ) : double;
674 
675     procedure AggAlignPoint(x ,y : PDouble );
676 
677     // Image Rendering
678     property AggImageFilter: TAggImageFilter read m_imageFilter write SetImageFilter;
679     property AggImageResample: TAggImageResample read m_imageResample write SetImageResample;
680 
681     procedure AggRenderImage(
682               img : TAggFPImage;
683               x1 ,y1 ,x2 ,y2 : integer;
684               parl : PDouble );
685 
686     procedure AggTransformImage(
687               SrcImage: TAggFPImage;
688               const imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
689               const dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
690 
691     procedure AggTransformImage(
692               SrcImage: TAggFPImage;
693               const dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
694 
695     procedure AggTransformImage(
696               SrcImage: TAggFPImage;
697               imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
698               parallelo : PDouble );
699 
700     procedure AggTransformImage(SrcImage: TAggFPImage; parallelo : PDouble );
701 
702     procedure AggTransformImagePath(
703               SrcImage: TAggFPImage;
704               const imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
705               const dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
706 
707     procedure AggTransformImagePath(
708               SrcImage: TAggFPImage;
709               const dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
710 
711     procedure AggTransformImagePath(
712               SrcImage: TAggFPImage;
713               const imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
714               const parallelo : PDouble );
715 
716     procedure AggTransformImagePath(SrcImage: TAggFPImage; parallelo : PDouble );
717 
718     procedure AggCopyImage(
719               SrcImage: TAggFPImage;
720               const imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
721               const dstX ,dstY : double );
722 
723     procedure AggCopyImage(SrcImage: TAggFPImage; const dstX ,dstY: double);
724 
725     // text
726     function AggTextWidth(str : AnsiString ) : double; virtual;
727     function AggTextHeight(str : AnsiString ) : double; virtual;
728     procedure AggTextOut(
729               const x ,y : double;
730               str : AnsiString;
731               roundOff : boolean = false;
732               const ddx : double = 0.0;
733               const ddy : double = 0.0 ); virtual;
734     property UseUTF8: boolean read FUseUTF8 write FUseUTF8;
735   end;
736 
737 function FPToAggColor(const c: TFPColor): TAggColor;
738 function AggToFPColor(const c: TAggColor): TFPColor;
739 
740 function AggUTF8CharToUnicode(p: PChar; out CharLen: int): int32u;
741 
742 implementation
743 
744 const
745   PixelSize: array [TAggFPImgPixelFormat] of Integer = (3, 4);
746 
747 var
748   g_approxScale : double = 2.0;
749 
750 type
751   //PAggSpanConvImageBlend = ^TAggSpanConvImageBlend;
752 
753   { TAggSpanConvImageBlend }
754 
755   TAggSpanConvImageBlend = object(span_convertor )
756   private
757     m_mode  : TAggBlendMode;
758     m_color : TAggColor;
759     m_pixel : pixel_formats_ptr; // m_pixFormatCompPre
760   public
761     constructor Construct(m : TAggBlendMode; c : TAggColor; p : pixel_formats_ptr );
762     procedure convert(span : aggclr_ptr; x ,y : int; len : unsigned ); virtual;
763   end;
764 
765 { TAggSpanConvImageBlend }
766 
767 constructor TAggSpanConvImageBlend.Construct(m: TAggBlendMode; c: TAggColor;
768   p: pixel_formats_ptr);
769 begin
770   m_mode :=m;
771   m_color:=c;
772   m_pixel:=p;
773 end;
774 
775 procedure TAggSpanConvImageBlend.convert(span: aggclr_ptr; x, y: int;
776   len: unsigned);
777 var
778  l2 ,a : unsigned;
779  s2 : PAggColor;
780 begin
781  if (m_mode <> AGG_BlendDst ) and
782     (m_pixel <> NIL ) then
783   begin{!}
784    l2:=len;
785    s2:=PAggColor(span );
786 
787    repeat
788     comp_op_adaptor_clip_to_dst_rgba_pre(
789      m_pixel ,
790      unsigned(m_mode ) ,
791      int8u_ptr(s2 ) ,
792      m_color.r ,
793      m_color.g ,
794      m_color.b ,
795      base_mask ,
796      cover_full );
797 
798     inc(ptrcomp(s2 ) ,sizeof(aggclr ) );
799     dec(l2 );
800 
801    until l2 = 0;
802 
803   end;
804 
805  if m_color.a < base_mask then
806   begin
807    l2:=len;
808    s2:=PAggColor(span );
809    a :=m_color.a;
810 
811    repeat
812     s2^.r:=(s2^.r * a ) shr base_shift;
813     s2^.g:=(s2^.g * a ) shr base_shift;
814     s2^.b:=(s2^.b * a ) shr base_shift;
815     s2^.a:=(s2^.a * a ) shr base_shift;
816 
817     inc(ptrcomp(s2 ) ,sizeof(aggclr ) );
818     dec(l2 );
819 
820    until l2 = 0;
821 
822   end;
823 end;
824 
825 function FPToAggColor(const c: TFPColor): TAggColor;
826 begin
827   Result.r:=c.red shr 8;
828   Result.g:=c.green shr 8;
829   Result.b:=c.blue shr 8;
830   Result.a:=c.alpha shr 8;
831 end;
832 
833 function AggToFPColor(const c: TAggColor): TFPColor;
834 begin
835   Result.red:=c.r or (c.r shl 8);
836   Result.green:=c.g or (c.g shl 8);
837   Result.blue:=c.b or (c.b shl 8);
838   Result.alpha:=c.a or (c.a shl 8);
839 end;
840 
841 function AggUTF8CharToUnicode(p: PChar; out CharLen: int): int32u;
842 begin
843   if p=nil then begin
844     Result:=0;
845     CharLen:=0;
846     exit;
847   end;
848   if ord(p^)<%11000000 then begin
849     // regular single byte character (#0 is a normal char, this is pascal ;)
850   end
851   else if ((ord(p^) and %11100000) = %11000000) then begin
852     // could be double byte character
853     if (ord(p[1]) and %11000000) = %10000000 then begin
854       Result:=((ord(p^) and %00011111) shl 6)
855               or (ord(p[1]) and %00111111);
856       CharLen:=2;
857       exit;
858     end;
859   end
860   else if ((ord(p^) and %11110000) = %11100000) then begin
861     // could be triple byte character
862     if ((ord(p[1]) and %11000000) = %10000000)
863     and ((ord(p[2]) and %11000000) = %10000000) then begin
864       Result:=((ord(p^) and %00011111) shl 12)
865               or ((ord(p[1]) and %00111111) shl 6)
866               or (ord(p[2]) and %00111111);
867       CharLen:=3;
868       exit;
869     end;
870   end
871   else if ((ord(p^) and %11111000) = %11110000) then begin
872     // could be 4 byte character
873     if ((ord(p[1]) and %11000000) = %10000000)
874     and ((ord(p[2]) and %11000000) = %10000000)
875     and ((ord(p[3]) and %11000000) = %10000000) then begin
876       Result:=((ord(p^) and %00001111) shl 18)
877               or ((ord(p[1]) and %00111111) shl 12)
878               or ((ord(p[2]) and %00111111) shl 6)
879               or (ord(p[3]) and %00111111);
880       CharLen:=4;
881       exit;
882     end;
883   end
884   else begin
885     // invalid character
886   end;
887   Result:=ord(p^);
888   CharLen:=1;
889 end;
890 
891 
892 { TAggFPImage }
893 
894 procedure TAggFPImage.SetPixelFormat(const AValue: TAggFPImgPixelFormat);
895 begin
896   if FPixelFormat=AValue then exit;
897   FPixelFormat:=AValue;
898   ReallocData;
899   NotifyListeners(afpioPixelFormatChanged);
900 end;
901 
902 procedure TAggFPImage.SetUsePalette(Value: boolean);
903 begin
904   if Value then
905     raise Exception.Create('palette not supported by '+ClassName);
906 end;
907 
908 procedure TAggFPImage.ReallocData;
909 begin
910   ReAllocMem(fData,DataSize);
911   RenderingBuffer.Destruct;
912   RenderingBuffer.Construct(FData, Width, Height, LineSize);
913 end;
914 
915 constructor TAggFPImage.Create(AWidth, AHeight: integer);
916 begin
917   RenderingBuffer.Construct;
918   inherited Create(AWidth, AHeight);
919 end;
920 
921 procedure TAggFPImage.SetInternalColor(x, y: integer; const Value: TFPColor);
922 var
923   p: PByte;
924 begin
925   if (x>=0) and (y>=0) and (x<Width) and (y<Height) then begin
926     p:=@FData[(y*Width+x) * PixelSize[PixelFormat]];
927     case PixelFormat of
928     afpimRGB24:
929       begin
930         p[0]:=Value.red shr 8;
931         p[1]:=Value.green shr 8;
932         p[2]:=Value.blue shr 8;
933       end;
934     afpimRGBA32:
935       begin
936         p[0]:=Value.red shr 8;
937         p[1]:=Value.green shr 8;
938         p[2]:=Value.blue shr 8;
939         p[3]:=Value.alpha shr 8;
940       end;
941     end;
942   end;
943 end;
944 
GetInternalColornull945 function TAggFPImage.GetInternalColor(x, y: integer): TFPColor;
946 var
947   p: PByte;
948 begin
949   if (x>=0) and (y>=0) and (x<Width) and (y<Height) then begin
950    p:=@FData[(y*Width+x) * PixelSize[PixelFormat]];
951     case PixelFormat of
952     afpimRGB24:
953       begin
954         Result.red:=p[0];
955         Result.red:=Result.red or (Result.red shl 8);
956         Result.green:=p[1];
957         Result.green:=Result.green or (Result.green shl 8);
958         Result.blue:=p[2];
959         Result.blue:=Result.blue or (Result.blue shl 8);
960         Result.alpha:=alphaOpaque;
961       end;
962     afpimRGBA32:
963       begin
964         Result.red:=p[0];
965         Result.red:=Result.red or (Result.red shl 8);
966         Result.green:=p[1];
967         Result.green:=Result.green or (Result.green shl 8);
968         Result.blue:=p[2];
969         Result.blue:=Result.blue or (Result.blue shl 8);
970         Result.alpha:=p[3];
971         Result.alpha:=Result.alpha or (Result.alpha shl 8);
972       end;
973     end;
974   end;
975 end;
976 
GetInternalPixelnull977 function TAggFPImage.GetInternalPixel(x, y: integer): integer;
978 var
979   p: PByte;
980 begin
981  p:=@FData[(y*Width+x) * PixelSize[PixelFormat]];
982   case PixelFormat of
983   afpimRGB24:
984     begin
985       Result:=PInteger(p)^;
986       {$IFDEF ENDIAN_LITTLE}
987       Result:=Result and $ffffff;
988       {$ELSE}
989       Result:=Result shr 8;
990       {$ENDIF}
991     end;
992   afpimRGBA32: Result:=PInteger(p)^;
993   end;
994 end;
995 
996 procedure TAggFPImage.SetInternalPixel(x, y: integer; Value: integer);
997 var
998   p: PByte;
999 begin
1000  p:=@FData[(y*Width+x) * PixelSize[PixelFormat]];
1001   case PixelFormat of
1002   afpimRGB24:
1003     begin
1004       {$IFDEF ENDIAN_LITTLE}
1005       // ToDo
1006       {$ELSE}
1007       // ToDo
1008       {$ENDIF}
1009     end;
1010   afpimRGBA32: PInteger(p)^:=Value;
1011   end;
1012 end;
1013 
1014 destructor TAggFPImage.Destroy;
1015 begin
1016   NotifyListeners(afpioDestroying);
1017   ReAllocMem(FData,0);
1018   inherited Destroy;
1019   RenderingBuffer.Destruct;
1020 end;
1021 
1022 procedure TAggFPImage.Assign(Source: TPersistent);
1023 var
1024   Src: TAggFPImage;
1025 begin
1026   if Source is TAggFPImage then begin
1027     Src:=TAggFPImage(Source);
1028     SetSize(0,0);
1029     PixelFormat:=Src.PixelFormat;
1030     SetSize(Src.Width,Src.Height);
1031     System.Move(Src.Data^,FData^,DataSize);
1032   end else
1033     inherited Assign(Source);
1034 end;
1035 
1036 procedure TAggFPImage.SetSize(AWidth, AHeight: integer);
1037 begin
1038   if (Width=AWidth) and (Height=AHeight) then exit;
1039   inherited SetSize(AWidth, AHeight);
1040   ReallocData;
1041   NotifyListeners(afpioResized);
1042 end;
1043 
1044 procedure TAggFPImage.AddListener(Event: TAggFPImgEvent);
1045 begin
1046   SetLength(FListeners,length(FListeners)+1);
1047   FListeners[length(FListeners)-1]:=Event;
1048 end;
1049 
1050 procedure TAggFPImage.RemoveListener(Event: TAggFPImgEvent);
1051 var
1052   i: Integer;
1053 begin
1054   for i:=length(FListeners)-1 downto 0 do begin
1055     // compare Code and Data, do not use =
1056     if CompareMem(@FListeners[i],@Event,SizeOf(TAggFPImgEvent)) then begin
1057       // delete
1058       if i<length(FListeners) then
1059         System.Move(FListeners[i+1],FListeners[i],
1060           SizeOf(TAggFPImgEvent)*(length(FListeners)-i-1));
1061       SetLength(FListeners,length(FListeners)-1);
1062     end;
1063   end;
1064 end;
1065 
1066 procedure TAggFPImage.NotifyListeners(Operation: TAggFPImgOperation);
1067 var
1068   i: Integer;
1069 begin
1070   for i:=length(FListeners)-1 downto 0 do
1071     FListeners[i](Self,Operation);
1072 end;
1073 
DataSizenull1074 function TAggFPImage.DataSize: PtrUInt;
1075 begin
1076   Result:=Width*Height*PixelSize[PixelFormat];
1077 end;
1078 
LineSizenull1079 function TAggFPImage.LineSize: PtrUInt;
1080 begin
1081   Result:=Width*PixelSize[PixelFormat];
1082 end;
1083 
1084 { TAggFPCanvas }
1085 
1086 procedure TAggFPCanvas.render(fillColor_: boolean; UseFont: boolean);
1087 begin
1088   if (m_blendMode = AGG_BlendAlpha ) or
1089      (Image.FPixelFormat = afpimRGB24 )
1090   then
1091     Agg2DRenderer_render(@m_renBase ,@m_renSolid ,fillColor_, UseFont )
1092   else
1093     Agg2DRenderer_render(@m_renBaseComp ,@m_renSolidComp ,fillColor_, UseFont );
1094 end;
1095 
1096 procedure TAggFPCanvas.render(ras: PAggFontRasterizer; sl: PAggFontScanline);
1097 begin
1098   if (m_blendMode = AGG_BlendAlpha ) or
1099     (Image.PixelFormat = afpimRGB24 ) then
1100     Agg2DRenderer_render(@m_renBase ,@m_renSolid ,ras ,sl, Font.AggUseOnlyFont )
1101   else
1102     Agg2DRenderer_render(@m_renBaseComp ,@m_renSolidComp ,ras ,sl, Font.AggUseOnlyFont);
1103 end;
1104 
1105 procedure TAggFPCanvas.SetAggTransformations(const AValue: TAggTransformations);
1106 begin
1107   m_transform.load_from(@AValue.affineMatrix[0 ] );
1108 
1109   Path.m_convCurve.approximation_scale_ (AggWorldToScreen(1.0 ) * g_approxScale );
1110   m_convStroke.approximation_scale_(AggWorldToScreen(1.0 ) * g_approxScale );
1111 end;
1112 
1113 procedure TAggFPCanvas.SetAntiAliasGamma(const AValue: double);
1114 begin
1115   if m_antiAliasGamma=AValue then exit;
1116   m_antiAliasGamma:=AValue;
1117   UpdateRasterizerGamma;
1118 end;
1119 
1120 procedure TAggFPCanvas.SetBlendMode(const AValue: TAggBlendMode);
1121 begin
1122   if m_blendMode=AValue then exit;
1123   m_blendMode:=AValue;
1124   m_pixFormatComp.comp_op_   (unsigned(m_blendMode ) );
1125   m_pixFormatCompPre.comp_op_(unsigned(m_blendMode ) );
1126 end;
1127 
1128 procedure TAggFPCanvas.SetImageFilter(const AValue: TAggImageFilter);
1129 begin
1130   if AValue=m_imageFilter then exit;
1131   m_imageFilter:=AValue;
1132   case m_imageFilter of
1133   AGG_Bilinear :
1134    m_imageFilterLut.calculate(@m_ifBilinear ,true );
1135 
1136   AGG_Hanning :
1137    m_imageFilterLut.calculate(@m_ifHanning ,true );
1138 
1139   AGG_Hermite :
1140    m_imageFilterLut.calculate(@m_ifHermite ,true );
1141 
1142   AGG_Quadric :
1143    m_imageFilterLut.calculate(@m_ifQuadric ,true );
1144 
1145   AGG_Bicubic :
1146    m_imageFilterLut.calculate(@m_ifBicubic ,true );
1147 
1148   AGG_Catrom :
1149    m_imageFilterLut.calculate(@m_ifCatrom ,true );
1150 
1151   AGG_Spline16 :
1152    m_imageFilterLut.calculate(@m_ifSpline16 ,true );
1153 
1154   AGG_Spline36 :
1155    m_imageFilterLut.calculate(@m_ifSpline36 ,true );
1156 
1157   AGG_Blackman144 :
1158    m_imageFilterLut.calculate(@m_ifBlackman144 ,true );
1159 
1160  end;
1161 end;
1162 
1163 procedure TAggFPCanvas.SetImageResample(const AValue: TAggImageResample);
1164 begin
1165   if AValue=m_imageResample then exit;
1166   m_imageResample:=AValue;
1167 end;
1168 
1169 procedure TAggFPCanvas.SetMasterAlpha(const AValue: double);
1170 begin
1171   if AValue=m_masterAlpha then exit;
1172   m_masterAlpha:=AValue;
1173   UpdateRasterizerGamma;
1174 end;
1175 
1176 procedure TAggFPCanvas.ClearSettings;
1177 begin
1178   m_renBase.reset_clipping       (true );
1179   m_renBaseComp.reset_clipping   (true );
1180   m_renBasePre.reset_clipping    (true );
1181   m_renBaseCompPre.reset_clipping(true );
1182 
1183   AggResetTransformations;
1184 
1185   Pen.AggLineWidth:=1.0;
1186   Pen.FPColor:=colBlack;
1187   Pen.AggLineCap:=AGG_CapRound;
1188   Pen.AggLineJoin:=AGG_JoinRound;
1189 
1190   Brush.FPColor:=colWhite;
1191   m_fillGradientFlag:=AGG_Solid;
1192 
1193   AggSetClipBox (0 ,0 ,Width ,Height );
1194 
1195   AggImageFilter:=AGG_Bilinear;
1196   AggImageResample:=AGG_NoResample;
1197 
1198   m_masterAlpha   :=1.0;
1199   m_antiAliasGamma:=1.0;
1200 
1201   m_rasterizer.gamma(@m_gammaNone );
1202 
1203   m_blendMode:=AGG_BlendAlpha;
1204 
1205   Brush.AggFillEvenOdd:=false;
1206 
1207   m_blendMode:=AGG_BlendClear;
1208   AggBlendMode:=AGG_BlendAlpha;
1209 
1210   //TextAlignment(AGG_AlignLeft ,AGG_AlignBottom );
1211   //FlipText(false );
1212 
1213   AggResetPath;
1214 end;
1215 
1216 procedure TAggFPCanvas.AggClearAll(const c: TAggColor);
1217 var
1218   clr : aggclr;
1219 begin
1220   clr.Construct  (c );
1221   m_renBase.clear(@clr );
1222 end;
1223 
1224 procedure TAggFPCanvas.AggClearAll(const r, g, b: byte; a: byte);
1225 var
1226   clr : TAggColor;
1227 begin
1228   clr.Construct(r ,g ,b ,a );
1229   AggClearAll     (clr );
1230 end;
1231 
1232 procedure TAggFPCanvas.Erase;
1233 begin
1234   AggClearAll(FPToAggColor(colTransparent));
1235 end;
1236 
1237 procedure TAggFPCanvas.UpdateRasterizerGamma;
1238 begin
1239   m_gammaAgg2D.Construct(m_masterAlpha ,m_antiAliasGamma );
1240   m_rasterizer.gamma    (@m_gammaAgg2D );
1241 end;
1242 
1243 procedure TAggFPCanvas.DoCopyRect(DstX, DstY: integer;
1244   SrcCanvas: TFPCustomCanvas; const SourceRect: TRect);
1245 var
1246   y: LongInt;
1247   x: LongInt;
1248   dx: Integer;
1249   dy: Integer;
1250   r: TRect;
1251 begin
1252   if SrcCanvas is TAggFPCanvas then begin
1253     AggCopyImage(TAggFPCanvas(SrcCanvas).Image,
1254        SourceRect.Left,SourceRect.Top,SourceRect.Right,SourceRect.Bottom,
1255        DstX+0.5,DstY+0.5);
1256   end else begin
1257     dx:=DstX-SourceRect.Left;
1258     dy:=DstY-SourceRect.Top;
1259     r:=SourceRect;
1260     r.Left:=Max(r.Left,0);
1261     r.Left:=Max(r.Left+dx,0)-dx;
1262     r.Top:=Max(r.Top,0);
1263     r.Top:=Max(r.Top+dy,0)-dy;
1264     r.Right:=Min(r.Right,SrcCanvas.Width);
1265     r.Right:=Min(r.Right+dx,Width)-dx;
1266     r.Bottom:=Min(r.Bottom,SrcCanvas.Height);
1267     r.Bottom:=Min(r.Bottom+dy,Height)-dy;
1268     for y:=r.Top to r.Bottom-1 do begin
1269       for x:=r.Left to r.Right-1 do begin
1270         Image.Colors[x+dx,y+dy]:=SrcCanvas.Colors[x,y];
1271       end;
1272     end;
1273   end;
1274 end;
1275 
DoCreateDefaultBrushnull1276 function TAggFPCanvas.DoCreateDefaultBrush: TFPCustomBrush;
1277 begin
1278   Result:=TAggFPBrush.Create;
1279 end;
1280 
DoCreateDefaultFontnull1281 function TAggFPCanvas.DoCreateDefaultFont: TFPCustomFont;
1282 begin
1283   Result:=TAggFPFont.Create;
1284 end;
1285 
DoCreateDefaultPennull1286 function TAggFPCanvas.DoCreateDefaultPen: TFPCustomPen;
1287 begin
1288   Result:=TAggFPPen.Create;
1289 end;
1290 
DoCreateDefaultPathnull1291 function TAggFPCanvas.DoCreateDefaultPath: TAggFPPath;
1292 begin
1293   Result:=TAggFPPath.Create;
1294 end;
1295 
DoCreateDefaultImagenull1296 function TAggFPCanvas.DoCreateDefaultImage: TAggFPImage;
1297 begin
1298   Result:=TAggFPImage.Create(0,0);
1299 end;
1300 
1301 procedure TAggFPCanvas.DoDraw(x, y: integer; const SrcImage: TFPCustomImage);
1302 var
1303   r: TRect;
1304   SrcY: LongInt;
1305   SrcX: LongInt;
1306 begin
1307   if SrcImage is TAggFPImage then begin
1308     AggCopyImage(TAggFPImage(SrcImage),x+0.5,y+0.5);
1309   end else begin
1310     r:=Classes.Rect(0,0,SrcImage.Width,SrcImage.Height);
1311     r.Left:=Max(r.Left+x,0)-x;
1312     r.Top:=Max(r.Top+y,0)-y;
1313     r.Right:=Min(r.Right+x,Width)-x;
1314     r.Bottom:=Min(r.Bottom+y,Height)-y;
1315     for SrcY:=r.Top to r.Bottom-1 do begin
1316       for SrcX:=r.Left to r.Right-1 do begin
1317         Image.Colors[SrcX+x,SrcY+y]:=SrcImage.Colors[SrcX,SrcY];
1318       end;
1319     end;
1320   end;
1321 end;
1322 
1323 procedure TAggFPCanvas.DoEllipse(const Bounds: TRect);
1324 var
1325   el : bezier_arc;
1326   cx: Integer;
1327   cy: Integer;
1328   rx: Integer;
1329   ry: Integer;
1330 begin
1331   Path.m_path.remove_all;
1332 
1333   cx:=(Bounds.Left+Bounds.Right) div 2;
1334   cy:=(Bounds.Top+Bounds.Bottom) div 2;
1335   rx:=Abs(Bounds.Right-Bounds.Left) div 2;
1336   ry:=Abs(Bounds.Bottom-Bounds.Top) div 2;
1337   el.Construct(cx+0.5 ,cy+0.5 ,rx ,ry ,0 ,2 * pi );
1338 
1339   Path.m_path.add_path(@el ,0 ,false );
1340   Path.m_path.close_polygon;
1341 
1342   AggDrawPath(AGG_StrokeOnly);
1343 end;
1344 
1345 procedure TAggFPCanvas.DoEllipseFill(const Bounds: TRect);
1346 var
1347   el : bezier_arc;
1348   cx: Integer;
1349   cy: Integer;
1350   rx: Integer;
1351   ry: Integer;
1352 begin
1353   Path.m_path.remove_all;
1354 
1355   cx:=(Bounds.Left+Bounds.Right) div 2;
1356   cy:=(Bounds.Top+Bounds.Bottom) div 2;
1357   rx:=Abs(Bounds.Right-Bounds.Left) div 2;
1358   ry:=Abs(Bounds.Bottom-Bounds.Top) div 2;
1359   el.Construct(cx+0.5 ,cy+0.5 ,rx ,ry ,0 ,2 * pi );
1360 
1361   Path.m_path.add_path(@el ,0 ,false );
1362   Path.m_path.close_polygon;
1363 
1364   AggDrawPath(AGG_FillOnly);
1365 end;
1366 
1367 procedure TAggFPCanvas.DoFloodFill(x, y: integer);
1368 begin
1369   raise Exception.Create('TAggFPCanvas.DoFloodFill not supported by AggPas');
1370 end;
1371 
DoGetTextHeightnull1372 function TAggFPCanvas.DoGetTextHeight(str: string): integer;
1373 begin
1374   Result:=ceil(AggTextHeight(str));
1375 end;
1376 
1377 procedure TAggFPCanvas.DoGetTextSize(str: string; var w, h: integer);
1378 begin
1379   w:=DoGetTextWidth(str);
1380   h:=DoGetTextHeight(str);
1381 end;
1382 
DoGetTextWidthnull1383 function TAggFPCanvas.DoGetTextWidth(str: string): integer;
1384 begin
1385   Result:=ceil(AggTextWidth(str));
1386 end;
1387 
1388 procedure TAggFPCanvas.DoLine(x1, y1, x2, y2: integer);
1389 begin
1390   Path.m_path.remove_all;
1391   Path.m_path.move_to(x1+0.5 ,y1+0.5 );
1392   Path.m_path.line_to(x2+0.5 ,y2+0.5 );
1393   AggDrawPath(AGG_StrokeOnly );
1394 end;
1395 
1396 procedure TAggFPCanvas.DoPolygon(const points: array of TPoint);
1397 var
1398   p: TPoint;
1399   i: Integer;
1400 begin
1401   if length(Points)<=1 then exit;
1402   Path.m_path.remove_all;
1403   i:=low(points);
1404   p:=points[i];
1405   Path.m_path.move_to(p.x+0.5 ,p.y+0.5 );
1406   inc(i);
1407   while i<=high(points) do begin
1408     p:=points[i];
1409     Path.m_path.line_to(p.x+0.5,p.y+0.5);
1410     inc(i);
1411   end;
1412   AggClosePolygon;
1413   AggDrawPath(AGG_StrokeOnly );
1414 end;
1415 
1416 procedure TAggFPCanvas.DoPolygonFill(const points: array of TPoint);
1417 var
1418   p: TPoint;
1419   i: Integer;
1420 begin
1421   if length(Points)<=1 then exit;
1422   Path.m_path.remove_all;
1423   i:=low(points);
1424   p:=points[i];
1425   Path.m_path.move_to(p.x+0.5 ,p.y+0.5 );
1426   inc(i);
1427   while i<=high(points) do begin
1428     p:=points[i];
1429     Path.m_path.line_to(p.x+0.5,p.y+0.5);
1430     inc(i);
1431   end;
1432   AggClosePolygon;
1433   AggDrawPath(AGG_FillOnly );
1434 end;
1435 
1436 procedure TAggFPCanvas.DoPolyline(const points: array of TPoint);
1437 var
1438   p: TPoint;
1439   i: Integer;
1440 begin
1441   if length(Points)<=1 then exit;
1442   Path.m_path.remove_all;
1443   i:=low(points);
1444   p:=points[i];
1445   Path.m_path.move_to(p.x+0.5 ,p.y+0.5 );
1446   inc(i);
1447   while i<=high(points) do begin
1448     p:=points[i];
1449     Path.m_path.line_to(p.x+0.5,p.y+0.5);
1450     inc(i);
1451   end;
1452   AggDrawPath(AGG_StrokeOnly );
1453 end;
1454 
1455 procedure TAggFPCanvas.DoRectangle(const Bounds: TRect);
1456 begin
1457   Path.m_path.remove_all;
1458   Path.m_path.move_to(Bounds.Left+0.5,Bounds.Top+0.5);
1459   Path.m_path.line_to(Bounds.Right+0.5,Bounds.Top+0.5);
1460   Path.m_path.line_to(Bounds.Right+0.5,Bounds.Bottom+0.5);
1461   Path.m_path.line_to(Bounds.Left+0.5,Bounds.Bottom+0.5);
1462   AggClosePolygon;
1463   AggDrawPath(AGG_StrokeOnly);
1464 end;
1465 
1466 procedure TAggFPCanvas.DoRectangleFill(const Bounds: TRect);
1467 begin
1468   Path.m_path.remove_all;
1469   Path.m_path.move_to(Bounds.Left+0.5,Bounds.Top+0.5);
1470   Path.m_path.line_to(Bounds.Right+0.5,Bounds.Top+0.5);
1471   Path.m_path.line_to(Bounds.Right+0.5,Bounds.Bottom+0.5);
1472   Path.m_path.line_to(Bounds.Left+0.5,Bounds.Bottom+0.5);
1473   AggClosePolygon;
1474   AggDrawPath(AGG_FillAndStroke);
1475 end;
1476 
1477 procedure TAggFPCanvas.DoTextOut(x, y: integer; str: string);
1478 begin
1479   AggTextOut(x+0.5,y+0.5,str);
1480 end;
1481 
GetColornull1482 function TAggFPCanvas.GetColor(x, y: integer): TFPColor;
1483 begin
1484   Result:=FImage.Colors[x,y];
1485 end;
1486 
GetHeightnull1487 function TAggFPCanvas.GetHeight: integer;
1488 begin
1489   Result:=FImage.Height;
1490 end;
1491 
GetWidthnull1492 function TAggFPCanvas.GetWidth: integer;
1493 begin
1494   Result:=FImage.Width;
1495 end;
1496 
1497 procedure TAggFPCanvas.SetColor(x, y: integer; const Value: TFPColor);
1498 begin
1499   FImage.Colors[x,y]:=Value;
1500 end;
1501 
1502 procedure TAggFPCanvas.SetHeight(AValue: integer);
1503 begin
1504   FImage.Height:=AValue;
1505 end;
1506 
1507 procedure TAggFPCanvas.SetWidth(AValue: integer);
1508 begin
1509   FImage.Width:=AValue;
1510 end;
1511 
1512 procedure TAggFPCanvas.OnImageOperation(Img: TAggFPImage;
1513   Operation: TAggFPImgOperation);
1514 begin
1515   if Img<>Image then exit;
1516   case Operation of
1517   afpioResized,afpioPixelFormatChanged:
1518     begin
1519       // Todo: shrink buffer (m_rbuf.attach only grows)
1520       if (Image.Width>0) and (Image.Height>0) then begin
1521         //writeln('TAggFPCanvas.OnImageOperation ',Image.Width,',',Image.Height,' ',Image.LineSize);
1522         m_rbuf.attach(
1523           Image.Data ,
1524           Image.Width ,
1525           Image.Height ,
1526           Image.LineSize);
1527        case Image.PixelFormat of
1528         afpimRGB24:
1529           begin
1530             pixfmt_rgb24(m_pixFormat ,@m_rbuf );
1531             pixfmt_rgb24(m_pixFormatPre ,@m_rbuf );
1532           end;
1533 
1534         afpimRGBA32:
1535           begin
1536             pixfmt_rgba32           (m_pixFormat ,@m_rbuf );
1537             pixfmt_custom_blend_rgba(m_pixFormatComp ,@m_rbuf ,
1538                                      @comp_op_adaptor_rgba ,rgba_order );
1539             pixfmt_rgba32           (m_pixFormatPre ,@m_rbuf );
1540             pixfmt_custom_blend_rgba(m_pixFormatCompPre ,@m_rbuf ,
1541                                      @comp_op_adaptor_rgba ,rgba_order );
1542           end;
1543         end;
1544 
1545         { Reset state }
1546         m_renBase.reset_clipping       (true );
1547         m_renBaseComp.reset_clipping   (true );
1548         m_renBasePre.reset_clipping    (true );
1549         m_renBaseCompPre.reset_clipping(true );
1550 
1551         AggSetClipBox (0 ,0 ,Width ,Height );
1552       end;
1553     end;
1554   afpioDestroying:
1555     begin
1556       FImage:=nil;
1557     end;
1558   end;
1559 end;
1560 
1561 constructor TAggFPCanvas.Create;
1562 begin
1563   inherited Create;
1564 
1565   FUseUTF8:=true;
1566 
1567   FAggFont := TAggFPFont(inherited Font);
1568   FAggPen := TAggFPPen(inherited Pen);
1569   FAggBrush := TAggFPBrush(inherited Brush);
1570   FAggPath := DoCreateDefaultPath;
1571   FAggPath.AllocateResources(Self);
1572 
1573   FImage:=DoCreateDefaultImage;
1574   FImage.AddListener(@OnImageOperation);
1575 
1576   m_rbuf.Construct;
1577 
1578   pixfmt_rgba32           (m_pixFormat ,@m_rbuf );
1579   pixfmt_custom_blend_rgba(m_pixFormatComp ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order );
1580   pixfmt_rgba32           (m_pixFormatPre ,@m_rbuf );
1581   pixfmt_custom_blend_rgba(m_pixFormatCompPre ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order );
1582 
1583   m_renBase.Construct       (@m_pixFormat );
1584   m_renBaseComp.Construct   (@m_pixFormatComp );
1585   m_renBasePre.Construct    (@m_pixFormatPre );
1586   m_renBaseCompPre.Construct(@m_pixFormatCompPre );
1587 
1588   m_renSolid.Construct    (@m_renBase );
1589   m_renSolidComp.Construct(@m_renBaseComp );
1590 
1591   m_allocator.Construct;
1592   m_clipBox.Construct(0 ,0 ,0 ,0 );
1593 
1594   m_blendMode     :=AGG_BlendAlpha;
1595   m_imageBlendMode:=AGG_BlendDst;
1596 
1597   m_imageBlendColor.Construct(0 ,0 ,0 );
1598 
1599   m_scanline.Construct;
1600   m_rasterizer.Construct;
1601 
1602   m_masterAlpha   :=1.0;
1603   m_antiAliasGamma:=1.0;
1604 
1605   m_fillGradient.Construct(256 ,sizeof(aggclr ) );
1606   m_lineGradient.Construct(256 ,sizeof(aggclr ) );
1607 
1608   m_fillGradientFlag:=AGG_Solid;
1609   m_lineGradientFlag:=AGG_Solid;
1610 
1611   m_fillGradientMatrix.Construct;
1612   m_lineGradientMatrix.Construct;
1613 
1614   m_fillGradientD1:=0.0;
1615   m_lineGradientD1:=0.0;
1616   m_fillGradientD2:=100.0;
1617   m_lineGradientD2:=100.0;
1618 
1619   m_imageFilter  :=AGG_Bilinear;
1620   m_imageResample:=AGG_NoResample;
1621 
1622   m_gammaNone.Construct;
1623 
1624   m_ifBilinear.Construct;
1625   m_ifHanning.Construct;
1626   m_ifHermite.Construct;
1627   m_ifQuadric.Construct;
1628   m_ifBicubic.Construct;
1629   m_ifCatrom.Construct;
1630   m_ifSpline16.Construct;
1631   m_ifSpline36.Construct;
1632   m_ifBlackman144.Construct;
1633 
1634   m_imageFilterLut.Construct(@m_ifBilinear ,true );
1635 
1636   m_linearGradientFunction.Construct;
1637   m_radialGradientFunction.Construct;
1638 
1639   m_fillGradientInterpolator.Construct(@m_fillGradientMatrix );
1640   m_lineGradientInterpolator.Construct(@m_lineGradientMatrix );
1641 
1642   Pen.FAggLineWidth:=1;
1643   m_evenOddFlag:=false;
1644 
1645   m_transform.Construct;
1646 
1647   m_convStroke.Construct(@Path.m_convCurve );
1648 
1649   m_pathTransform.Construct  (@Path.m_convCurve ,@m_transform );
1650   m_strokeTransform.Construct(@m_convStroke ,@m_transform );
1651 
1652   {$IFDEF AGG2D_USE_FREETYPE }
1653   m_fontEngine.Construct;
1654   {$ENDIF }
1655   {$IFDEF AGG2D_USE_WINFONTS}
1656   m_fontDC:=GetDC(0);
1657   m_fontEngine.Construct(m_fontDC);
1658   {$ENDIF }
1659   {$IFNDEF AGG2D_NO_FONT}
1660   m_fontCacheManager.Construct(@m_fontEngine);
1661   {$ENDIF}
1662 
1663   m_convStroke.line_cap_(Pen.AggLineCap);
1664   m_convStroke.line_join_(Pen.AggLineJoin);
1665 
1666   ClearSettings;
1667 end;
1668 
1669 destructor TAggFPCanvas.Destroy;
1670 begin
1671   m_rbuf.Destruct;
1672 
1673   m_allocator.Destruct;
1674 
1675   m_scanline.Destruct;
1676   m_rasterizer.Destruct;
1677 
1678   m_fillGradient.Destruct;
1679   m_lineGradient.Destruct;
1680 
1681   m_imageFilterLut.Destruct;
1682 
1683   m_convStroke.Destruct;
1684 
1685   {$IFNDEF AGG2D_NO_FONT}
1686   m_fontEngine.Destruct;
1687   m_fontCacheManager.Destruct;
1688   {$ENDIF}
1689 
1690   {$IFDEF AGG2D_USE_WINFONTS}
1691   ReleaseDC(0,m_fontDC);
1692   {$ENDIF }
1693 
1694   FAggPath.DeallocateResources;
1695   FreeAndNil(FAggPath);
1696 
1697   FreeAndNil(FImage);
1698   inherited Destroy;
1699   // set resources to nil, so that dangling pointers are spotted early
1700   FAggFont:=nil;
1701   FAggPen:=nil;
1702   FAggBrush:=nil;
1703 end;
1704 
1705 procedure TAggFPCanvas.AggResetPath;
1706 begin
1707   Path.m_path.remove_all;
1708   Path.m_path.move_to(0,0);
1709 end;
1710 
1711 procedure TAggFPCanvas.AggMoveTo(const x, y: double);
1712 begin
1713   Path.m_path.move_to(x ,y );
1714 end;
1715 
1716 procedure TAggFPCanvas.AggMoveRel(const dx, dy: double);
1717 begin
1718   Path.m_path.move_rel(dx ,dy );
1719 end;
1720 
1721 procedure TAggFPCanvas.AggLineTo(const x, y: double);
1722 begin
1723   Path.m_path.line_to(x ,y );
1724 end;
1725 
1726 procedure TAggFPCanvas.AggLineRel(const dx, dy: double);
1727 begin
1728   Path.m_path.line_rel(dx ,dy );
1729 end;
1730 
1731 procedure TAggFPCanvas.AggHorLineTo(const x: double);
1732 begin
1733   Path.m_path.hline_to(x );
1734 end;
1735 
1736 procedure TAggFPCanvas.AggHorLineRel(const dx: double);
1737 begin
1738   Path.m_path.hline_rel(dx );
1739 end;
1740 
1741 procedure TAggFPCanvas.AggVerLineTo(const y: double);
1742 begin
1743   Path.m_path.vline_to(y );
1744 end;
1745 
1746 procedure TAggFPCanvas.AggVerLineRel(const dy: double);
1747 begin
1748   Path.m_path.vline_rel(dy );
1749 end;
1750 
1751 procedure TAggFPCanvas.AggArcTo(const rx, ry, angle: double; largeArcFlag,
1752   sweepFlag: boolean; const x, y: double);
1753 begin
1754   Path.m_path.arc_to(rx ,ry ,angle ,largeArcFlag ,sweepFlag ,x ,y );
1755 end;
1756 
1757 procedure TAggFPCanvas.AggArcRel(const rx, ry, angle: double; largeArcFlag,
1758   sweepFlag: boolean; const dx, dy: double);
1759 begin
1760   Path.m_path.arc_rel(rx ,ry ,angle ,largeArcFlag ,sweepFlag ,dx ,dy );
1761 end;
1762 
1763 procedure TAggFPCanvas.AggQuadricCurveTo(const xCtrl, yCtrl, xTo, yTo: double);
1764 begin
1765   Path.m_path.curve3(xCtrl ,yCtrl ,xTo ,yTo );
1766 end;
1767 
1768 procedure TAggFPCanvas.AggQuadricCurveRel(const dxCtrl, dyCtrl, dxTo,
1769   dyTo: double);
1770 begin
1771   Path.m_path.curve3_rel(dxCtrl ,dyCtrl ,dxTo ,dyTo );
1772 end;
1773 
1774 procedure TAggFPCanvas.AggQuadricCurveTo(const xTo, yTo: double);
1775 begin
1776   Path.m_path.curve3(xTo ,yTo );
1777 end;
1778 
1779 procedure TAggFPCanvas.AggQuadricCurveRel(const dxTo, dyTo: double);
1780 begin
1781   Path.m_path.curve3_rel(dxTo ,dyTo );
1782 end;
1783 
1784 procedure TAggFPCanvas.AggCubicCurveTo(const xCtrl1, yCtrl1, xCtrl2, yCtrl2,
1785   xTo, yTo: double);
1786 begin
1787   Path.m_path.curve4(xCtrl1 ,yCtrl1 ,xCtrl2 ,yCtrl2 ,xTo ,yTo );
1788 end;
1789 
1790 procedure TAggFPCanvas.AggCubicCurveRel(const dxCtrl1, dyCtrl1, dxCtrl2,
1791   dyCtrl2, dxTo, dyTo: double);
1792 begin
1793   Path.m_path.curve4_rel(dxCtrl1 ,dyCtrl1 ,dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo );
1794 end;
1795 
1796 procedure TAggFPCanvas.AggCubicCurveTo(const xCtrl2, yCtrl2, xTo, yTo: double);
1797 begin
1798   Path.m_path.curve4(xCtrl2 ,yCtrl2 ,xTo ,yTo );
1799 end;
1800 
1801 procedure TAggFPCanvas.AggCubicCurveRel(const dxCtrl2, dyCtrl2, dxTo,
1802   dyTo: double);
1803 begin
1804   Path.m_path.curve4_rel(dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo );
1805 end;
1806 
1807 procedure TAggFPCanvas.AggAddEllipse(const cx, cy, rx, ry: double;
1808   dir: TAggDirection);
1809 var
1810   ar : bezier_arc;
1811 begin
1812   if dir = AGG_CCW then
1813     ar.Construct(cx ,cy ,rx ,ry ,0 ,2 * pi )
1814   else
1815     ar.Construct(cx ,cy ,rx ,ry ,0 ,-2 * pi );
1816 
1817   Path.m_path.add_path(@ar ,0 ,false );
1818   AggClosePolygon;
1819 end;
1820 
1821 procedure TAggFPCanvas.AggClosePolygon;
1822 begin
1823   Path.m_path.close_polygon;
1824 end;
1825 
1826 procedure TAggFPCanvas.AggDrawPath(flag: TAggDrawPathFlag; UseFont: boolean);
1827 begin
1828   m_rasterizer.reset;
1829   if flag in [AGG_FillOnly,AGG_FillAndStroke] then begin
1830     if (not UseFont and (Brush.FAggColor.a <> 0))
1831     or (UseFont and (Font.FAggColor.a <> 0)) then
1832     begin
1833       m_rasterizer.add_path(@m_pathTransform );
1834       render(true,UseFont);
1835     end;
1836   end;
1837   if flag in [AGG_StrokeOnly,AGG_FillAndStroke] then begin
1838     if (not UseFont and (Pen.FAggColor.a <> 0 ) and (Pen.FAggLineWidth > 0.0 ))
1839     or (UseFont and (Font.FAggColor.a<>0)) then
1840     begin
1841       m_rasterizer.add_path(@m_strokeTransform );
1842       render(false,UseFont);
1843     end;
1844   end;
1845   if flag=AGG_FillWithLineColor then begin
1846     if (not UseFont and (Pen.FAggColor.a <> 0))
1847     or (UseFont and (Font.FAggColor.a<>0)) then
1848     begin
1849       m_rasterizer.add_path(@m_pathTransform);
1850       render(false,UseFont);
1851     end;
1852   end;
1853 end;
1854 
1855 procedure TAggFPCanvas.AggLine(const x1, y1, x2, y2: double);
1856 begin
1857   Path.m_path.remove_all;
1858 
1859   addLine (x1 ,y1 ,x2 ,y2 );
1860   AggDrawPath(AGG_StrokeOnly );
1861 end;
1862 
1863 procedure TAggFPCanvas.AggTriangle(const x1, y1, x2, y2, x3, y3: double);
1864 begin
1865   Path.m_path.remove_all;
1866   Path.m_path.move_to(x1 ,y1 );
1867   Path.m_path.line_to(x2 ,y2 );
1868   Path.m_path.line_to(x3 ,y3 );
1869   Path.m_path.close_polygon;
1870 
1871   AggDrawPath(AGG_FillAndStroke );
1872 end;
1873 
1874 procedure TAggFPCanvas.AggRectangle(const x1, y1, x2, y2: double);
1875 begin
1876   Path.m_path.remove_all;
1877   Path.m_path.move_to(x1 ,y1 );
1878   Path.m_path.line_to(x2 ,y1 );
1879   Path.m_path.line_to(x2 ,y2 );
1880   Path.m_path.line_to(x1 ,y2 );
1881   Path.m_path.close_polygon;
1882 
1883   AggDrawPath(AGG_FillAndStroke );
1884 end;
1885 
1886 procedure TAggFPCanvas.AggRoundedRect(const x1, y1, x2, y2, r: double);
1887 var
1888   rc : rounded_rect;
1889 begin
1890   Path.m_path.remove_all;
1891   rc.Construct(x1 ,y1 ,x2 ,y2 ,r );
1892 
1893   rc.normalize_radius;
1894   rc.approximation_scale_(AggWorldToScreen(1.0 ) * g_approxScale );
1895 
1896   Path.m_path.add_path(@rc ,0 ,false );
1897 
1898   AggDrawPath(AGG_FillAndStroke );
1899 end;
1900 
1901 procedure TAggFPCanvas.AggRoundedRect(const x1, y1, x2, y2, rx, ry: double);
1902 var
1903   rc : rounded_rect;
1904 begin
1905   Path.m_path.remove_all;
1906   rc.Construct;
1907 
1908   rc.rect  (x1 ,y1 ,x2 ,y2 );
1909   rc.radius(rx ,ry );
1910   rc.normalize_radius;
1911 
1912   Path.m_path.add_path(@rc ,0 ,false );
1913 
1914   AggDrawPath(AGG_FillAndStroke );
1915 end;
1916 
1917 procedure TAggFPCanvas.AggRoundedRect(const x1, y1, x2, y2, rxBottom, ryBottom,
1918   rxTop, ryTop: double);
1919 var
1920   rc : rounded_rect;
1921 begin
1922   Path.m_path.remove_all;
1923   rc.Construct;
1924 
1925   rc.rect  (x1 ,y1 ,x2 ,y2 );
1926   rc.radius(rxBottom ,ryBottom ,rxTop ,ryTop );
1927   rc.normalize_radius;
1928 
1929   rc.approximation_scale_(AggWorldToScreen(1.0 ) * g_approxScale );
1930 
1931   Path.m_path.add_path(@rc ,0 ,false );
1932 
1933   AggDrawPath(AGG_FillAndStroke );
1934 end;
1935 
1936 procedure TAggFPCanvas.AggEllipse(const cx, cy, rx, ry: double);
1937 var
1938   el : bezier_arc;
1939 begin
1940   Path.m_path.remove_all;
1941 
1942   el.Construct(cx ,cy ,rx ,ry ,0 ,2 * pi );
1943 
1944   Path.m_path.add_path(@el ,0 ,false );
1945   AggClosePolygon;
1946 
1947   AggDrawPath(AGG_FillAndStroke );
1948 end;
1949 
1950 procedure TAggFPCanvas.AggArc(const cx, cy, rx, ry, start, endangle: double);
1951 var
1952   ar : agg_arc.arc;
1953 begin
1954   Path.m_path.remove_all;
1955 
1956   ar.Construct(cx ,cy ,rx ,ry ,endangle ,start ,false );
1957 
1958   Path.m_path.add_path(@ar ,0 ,false );
1959 
1960   AggDrawPath(AGG_StrokeOnly );
1961 end;
1962 
1963 procedure TAggFPCanvas.AggStar(const cx, cy, r1, r2, startAngle: double;
1964   numRays: integer);
1965 var
1966   da, a, x, y: double;
1967   i : int;
1968 begin
1969   Path.m_path.remove_all;
1970 
1971   da:=pi / numRays;
1972   a :=startAngle;
1973 
1974   i:=0;
1975 
1976   while i < numRays do begin
1977     x:=Cos(a) * r2 + cx;
1978     y:=Sin(a) * r2 + cy;
1979 
1980     if i <> 0 then
1981       Path.m_path.line_to(x ,y)
1982     else
1983       Path.m_path.move_to(x ,y);
1984 
1985     a:=a + da;
1986 
1987     Path.m_path.line_to(Cos(a ) * r1 + cx ,Sin(a ) * r1 + cy);
1988 
1989     a:=a + da;
1990 
1991     inc(i);
1992   end;
1993 
1994   AggClosePolygon;
1995   AggDrawPath(AGG_FillAndStroke );
1996 end;
1997 
1998 procedure TAggFPCanvas.AggCurve(const x1, y1, x2, y2, x3, y3: double);
1999 begin
2000   Path.m_path.remove_all;
2001   Path.m_path.move_to(x1 ,y1 );
2002   Path.m_path.curve3 (x2 ,y2 ,x3 ,y3 );
2003 
2004   AggDrawPath(AGG_StrokeOnly );
2005 end;
2006 
2007 procedure TAggFPCanvas.AggCurve(const x1, y1, x2, y2, x3, y3, x4, y4: double);
2008 begin
2009   Path.m_path.remove_all;
2010   Path.m_path.move_to(x1 ,y1 );
2011   Path.m_path.curve4 (x2 ,y2 ,x3 ,y3 ,x4 ,y4 );
2012 
2013   AggDrawPath(AGG_StrokeOnly );
2014 end;
2015 
2016 procedure TAggFPCanvas.AggPolygon(const xy: PDouble; numPoints: integer);
2017 begin
2018   Path.m_path.remove_all;
2019   Path.m_path.add_poly(double_2_ptr(xy ) ,numPoints );
2020 
2021   AggClosePolygon;
2022   AggDrawPath(AGG_FillAndStroke );
2023 end;
2024 
2025 procedure TAggFPCanvas.AggPolyline(const xy: PDouble; numPoints: integer);
2026 begin
2027   Path.m_path.remove_all;
2028   Path.m_path.add_poly(double_2_ptr(xy ) ,numPoints );
2029 
2030   AggDrawPath(AGG_StrokeOnly );
2031 end;
2032 
2033 procedure TAggFPCanvas.AggFillLinearGradient(const x1, y1, x2, y2: double; c1,
2034   c2: TAggColor; profile: double);
2035 var
2036   i ,startGradient ,endGradient : int;
2037 
2038   k ,angle : double;
2039 
2040   c : TAggColor;
2041 
2042   clr : aggclr;
2043   tar : trans_affine_rotation;
2044   tat : trans_affine_translation;
2045 begin
2046   startGradient:=128 - Trunc(profile * 127.0 );
2047   endGradient  :=128 + Trunc(profile * 127.0 );
2048 
2049   if endGradient <= startGradient then
2050   endGradient:=startGradient + 1;
2051 
2052   k:=1.0 / (endGradient - startGradient );
2053   i:=0;
2054 
2055   while i < startGradient do
2056   begin
2057     clr.Construct(c1 );
2058 
2059     move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
2060     inc (i );
2061   end;
2062 
2063   while i < endGradient do
2064   begin
2065     c:=c1.gradient(c2 ,(i - startGradient ) * k );
2066 
2067     clr.Construct(c );
2068 
2069     move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
2070     inc (i );
2071   end;
2072 
2073   while i < 256 do
2074   begin
2075     clr.Construct(c2 );
2076 
2077     move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
2078     inc (i );
2079   end;
2080 
2081   angle:=ArcTan2(y2 - y1 ,x2 - x1 );
2082 
2083   m_fillGradientMatrix.reset;
2084 
2085   tar.Construct(angle );
2086 
2087   m_fillGradientMatrix.multiply(@tar );
2088 
2089   tat.Construct(x1 ,y1 );
2090 
2091   m_fillGradientMatrix.multiply(@tat );
2092   m_fillGradientMatrix.multiply(@m_transform );
2093   m_fillGradientMatrix.invert;
2094 
2095   m_fillGradientD1  :=0.0;
2096   m_fillGradientD2  :=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) );
2097   m_fillGradientFlag:=AGG_Linear;
2098 end;
2099 
2100 procedure TAggFPCanvas.AggLineLinearGradient(const x1, y1, x2, y2: double; c1,
2101   c2: TAggColor; profile: double);
2102 var
2103   i ,startGradient ,endGradient : int;
2104 
2105   k ,angle : double;
2106 
2107   c : TAggColor;
2108 
2109   clr : aggclr;
2110   tar : trans_affine_rotation;
2111   tat : trans_affine_translation;
2112 
2113 begin
2114   startGradient:=128 - Trunc(profile * 128.0 );
2115   endGradient  :=128 + Trunc(profile * 128.0 );
2116 
2117   if endGradient <= startGradient then
2118   endGradient:=startGradient + 1;
2119 
2120   k:=1.0 / (endGradient - startGradient );
2121   i:=0;
2122 
2123   while i < startGradient do
2124   begin
2125     clr.Construct(c1 );
2126 
2127     move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
2128     inc (i );
2129   end;
2130 
2131   while i < endGradient do
2132   begin
2133     c:=c1.gradient(c2 ,(i - startGradient) * k );
2134 
2135     clr.Construct(c );
2136 
2137     move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
2138     inc (i );
2139   end;
2140 
2141   while i < 256 do
2142   begin
2143     clr.Construct(c2 );
2144 
2145     move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
2146     inc (i );
2147   end;
2148 
2149   angle:=ArcTan2(y2 - y1 ,x2 - x1 );
2150 
2151   m_lineGradientMatrix.reset;
2152 
2153   tar.Construct(angle );
2154 
2155   m_lineGradientMatrix.multiply(@tar );
2156 
2157   tat.Construct(x1 ,y1 );
2158 
2159   m_lineGradientMatrix.multiply(@tat );
2160   m_lineGradientMatrix.multiply(@m_transform );
2161   m_lineGradientMatrix.invert;
2162 
2163   m_lineGradientD1  :=0.0;
2164   m_lineGradientD2  :=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) );
2165   m_lineGradientFlag:=AGG_Linear;
2166 
2167   Pen.FPColor:=colBlack;  // Set some real color
2168 end;
2169 
2170 procedure TAggFPCanvas.AggFillRadialGradient(const x, y, r: double; c1,
2171   c2: TAggColor; profile: double);
2172 var
2173   i ,startGradient ,endGradient : int;
2174 
2175   k : double;
2176   c : TAggColor;
2177 
2178   clr : aggclr;
2179   tat : trans_affine_translation;
2180 
2181 begin
2182   startGradient:=128 - Trunc(profile * 127.0 );
2183   endGradient  :=128 + Trunc(profile * 127.0 );
2184 
2185   if endGradient <= startGradient then
2186   endGradient:=startGradient + 1;
2187 
2188   k:=1.0 / (endGradient - startGradient );
2189   i:=0;
2190 
2191   while i < startGradient do
2192   begin
2193     clr.Construct(c1 );
2194 
2195     move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
2196     inc (i );
2197   end;
2198 
2199   while i < endGradient do
2200   begin
2201     c:=c1.gradient(c2 ,(i - startGradient ) * k );
2202 
2203     clr.Construct(c );
2204 
2205     move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
2206     inc (i );
2207   end;
2208 
2209   while i < 256 do
2210   begin
2211     clr.Construct(c2 );
2212 
2213     move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
2214     inc (i );
2215   end;
2216 
2217   m_fillGradientD2:=AggWorldToScreen(r );
2218 
2219   AggWorldToScreen(@x ,@y );
2220 
2221   m_fillGradientMatrix.reset;
2222 
2223   tat.Construct(x ,y );
2224 
2225   m_fillGradientMatrix.multiply(@tat );
2226   m_fillGradientMatrix.invert;
2227 
2228   m_fillGradientD1  :=0;
2229   m_fillGradientFlag:=AGG_Radial;
2230 end;
2231 
2232 procedure TAggFPCanvas.AggLineRadialGradient(const x, y, r: double; c1,
2233   c2: TAggColor; profile: double);
2234 var
2235   i ,startGradient ,endGradient : int;
2236 
2237   k : double;
2238   c : TAggColor;
2239 
2240   clr : aggclr;
2241   tat : trans_affine_translation;
2242 
2243 begin
2244   startGradient:=128 - Trunc(profile * 128.0 );
2245   endGradient  :=128 + Trunc(profile * 128.0 );
2246 
2247   if endGradient <= startGradient then
2248   endGradient:=startGradient + 1;
2249 
2250   k:=1.0 / (endGradient - startGradient );
2251   i:=0;
2252 
2253   while i < startGradient do
2254   begin
2255     clr.Construct(c1 );
2256 
2257     move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
2258     inc (i );
2259   end;
2260 
2261   while i < endGradient do
2262   begin
2263     c:=c1.gradient(c2 ,(i - startGradient ) * k );
2264 
2265     clr.Construct(c );
2266 
2267     move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
2268     inc (i );
2269   end;
2270 
2271   while i < 256 do
2272   begin
2273     clr.Construct(c2 );
2274 
2275     move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
2276     inc (i );
2277   end;
2278 
2279   m_lineGradientD2:=AggWorldToScreen(r );
2280 
2281   AggWorldToScreen(@x ,@y );
2282 
2283   m_lineGradientMatrix.reset;
2284 
2285   tat.Construct(x ,y );
2286 
2287   m_lineGradientMatrix.multiply(@tat );
2288   m_lineGradientMatrix.invert;
2289 
2290   m_lineGradientD1  :=0;
2291   m_lineGradientFlag:=AGG_Radial;
2292 
2293   Pen.FPColor:=colBlack;  // Set some real color
2294 end;
2295 
2296 procedure TAggFPCanvas.AggFillRadialGradient(const x, y, r: double; c1, c2,
2297   c3: TAggColor);
2298 var
2299   i : int;
2300   c : TAggColor;
2301 
2302   clr : aggclr;
2303   tat : trans_affine_translation;
2304 
2305 begin
2306   i:=0;
2307 
2308   while i < 128 do
2309   begin
2310     c:=c1.gradient(c2 ,i / 127.0 );
2311 
2312     clr.Construct(c );
2313 
2314     move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
2315     inc (i );
2316   end;
2317 
2318   while i < 256 do
2319   begin
2320     c:=c2.gradient(c3 ,(i - 128 ) / 127.0 );
2321 
2322     clr.Construct(c );
2323 
2324     move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
2325     inc (i );
2326   end;
2327 
2328   m_fillGradientD2:=AggWorldToScreen(r );
2329 
2330   AggWorldToScreen(@x ,@y );
2331 
2332   m_fillGradientMatrix.reset;
2333 
2334   tat.Construct(x ,y );
2335 
2336   m_fillGradientMatrix.multiply(@tat );
2337   m_fillGradientMatrix.invert;
2338 
2339   m_fillGradientD1  :=0;
2340   m_fillGradientFlag:=AGG_Radial;
2341 end;
2342 
2343 procedure TAggFPCanvas.AggLineRadialGradient(const x, y, r: double; c1, c2,
2344   c3: TAggColor);
2345 var
2346   i : int;
2347   c : TAggColor;
2348 
2349   clr : aggclr;
2350   tat : trans_affine_translation;
2351 
2352 begin
2353   i:=0;
2354 
2355   while i < 128 do
2356   begin
2357     c:=c1.gradient(c2 ,i / 127.0 );
2358 
2359     clr.Construct(c );
2360 
2361     move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
2362     inc (i );
2363   end;
2364 
2365   while i < 256 do
2366   begin
2367     c:=c2.gradient(c3 ,(i - 128 ) / 127.0 );
2368 
2369     clr.Construct(c );
2370 
2371     move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
2372     inc (i );
2373   end;
2374 
2375   m_lineGradientD2:=AggWorldToScreen(r );
2376 
2377   AggWorldToScreen(@x ,@y );
2378 
2379   m_lineGradientMatrix.reset;
2380 
2381   tat.Construct(x ,y );
2382 
2383   m_lineGradientMatrix.multiply(@tat );
2384   m_lineGradientMatrix.invert;
2385 
2386   m_lineGradientD1  :=0;
2387   m_lineGradientFlag:=AGG_Radial;
2388 
2389   Pen.FPColor:=colBlack; // Set some real color
2390 end;
2391 
2392 procedure TAggFPCanvas.AggFillRadialGradient(const x, y, r: double);
2393 var
2394   tat : trans_affine_translation;
2395 
2396 begin
2397   m_fillGradientD2:=AggWorldToScreen(r );
2398 
2399   AggWorldToScreen(@x ,@y );
2400 
2401   m_fillGradientMatrix.reset;
2402 
2403   tat.Construct(x ,y );
2404 
2405   m_fillGradientMatrix.multiply(@tat );
2406   m_fillGradientMatrix.invert;
2407 
2408   m_fillGradientD1:=0;
2409 end;
2410 
2411 procedure TAggFPCanvas.AggLineRadialGradient(const x, y, r: double);
2412 var
2413   tat : trans_affine_translation;
2414 
2415 begin
2416   m_lineGradientD2:=AggWorldToScreen(r );
2417 
2418   AggWorldToScreen(@x ,@y );
2419 
2420   m_lineGradientMatrix.reset;
2421 
2422   tat.Construct(x ,y );
2423 
2424   m_lineGradientMatrix.multiply(@tat );
2425   m_lineGradientMatrix.invert;
2426 
2427   m_lineGradientD1:=0;
2428 end;
2429 
2430 procedure TAggFPCanvas.AggSetClipBox(const x1, y1, x2, y2: double);
2431 var
2432   rx1 ,ry1 ,rx2 ,ry2 : int;
2433 begin
2434   m_clipBox.Construct(x1 ,y1 ,x2 ,y2 );
2435 
2436   rx1:=Trunc(x1 );
2437   ry1:=Trunc(y1 );
2438   rx2:=Trunc(x2 );
2439   ry2:=Trunc(y2 );
2440 
2441   m_renBase.clip_box_       (rx1 ,ry1 ,rx2 ,ry2 );
2442   m_renBaseComp.clip_box_   (rx1 ,ry1 ,rx2 ,ry2 );
2443   m_renBasePre.clip_box_    (rx1 ,ry1 ,rx2 ,ry2 );
2444   m_renBaseCompPre.clip_box_(rx1 ,ry1 ,rx2 ,ry2 );
2445 
2446   m_rasterizer.clip_box(x1 ,y1 ,x2 ,y2 );
2447 end;
2448 
AggGetClipBoxnull2449 function TAggFPCanvas.AggGetClipBox: TAggRectD;
2450 begin
2451   result:=m_clipBox;
2452 end;
2453 
2454 procedure TAggFPCanvas.AggClearClipBox(const c: TAggColor);
2455 var
2456   clr : aggclr;
2457 begin
2458   clr.Construct(c );
2459   m_renBase.copy_bar(0 ,0 ,m_renBase.width ,m_renBase.height ,@clr );
2460 end;
2461 
2462 procedure TAggFPCanvas.AggClearClipBox(r, g, b: byte; a: byte);
2463 var
2464   clr : TAggColor;
2465 begin
2466   clr.Construct(r ,g ,b ,a );
2467   AggClearClipBox (clr );
2468 end;
2469 
AggInClipBoxnull2470 function TAggFPCanvas.AggInClipBox(const worldX, worldY: double): boolean;
2471 begin
2472   AggWorldToScreen(@worldX ,@worldY );
2473   result:=m_renBase.inbox(Trunc(worldX ) ,Trunc(worldY ) );
2474 end;
2475 
2476 procedure TAggFPCanvas.AggResetTransformations;
2477 begin
2478   m_transform.reset;
2479 end;
2480 
2481 procedure TAggFPCanvas.AggAffine(const tr: PAggAffine);
2482 begin
2483   m_transform.multiply(tr);
2484 
2485   Path.m_convCurve.approximation_scale_ (AggWorldToScreen(1.0 ) * g_approxScale );
2486   m_convStroke.approximation_scale_(AggWorldToScreen(1.0 ) * g_approxScale );
2487 end;
2488 
2489 procedure TAggFPCanvas.AggAffine(const tr: PAggTransformations);
2490 var
2491  ta : trans_affine;
2492 begin
2493   ta.Construct(
2494     tr^.affineMatrix[0 ] ,tr^.affineMatrix[1 ] ,tr^.affineMatrix[2 ] ,
2495     tr^.affineMatrix[3 ] ,tr^.affineMatrix[4 ] ,tr^.affineMatrix[5 ] );
2496 
2497   AggAffine(PAggAffine(@ta ) );
2498 end;
2499 
2500 procedure TAggFPCanvas.AggRotate(const angle: double);
2501 var
2502   tar : trans_affine_rotation;
2503 begin
2504   tar.Construct(angle );
2505   m_transform.multiply(@tar );
2506 end;
2507 
2508 procedure TAggFPCanvas.AggScale(const sx, sy: double);
2509 var
2510   tas : trans_affine_scaling;
2511 begin
2512   tas.Construct(sx ,sy );
2513 
2514   m_transform.multiply(@tas );
2515 
2516   Path.m_convCurve.approximation_scale_ (AggWorldToScreen(1.0 ) * g_approxScale );
2517   m_convStroke.approximation_scale_(AggWorldToScreen(1.0 ) * g_approxScale );
2518 end;
2519 
2520 procedure TAggFPCanvas.AggSkew(const sx, sy: double);
2521 var
2522   tas : trans_affine_skewing;
2523 begin
2524   tas.Construct(sx ,sy );
2525   m_transform.multiply(@tas );
2526 end;
2527 
2528 procedure TAggFPCanvas.AggTranslate(const x, y: double);
2529 var
2530   tat : trans_affine_translation;
2531 begin
2532   tat.Construct(x ,y );
2533   m_transform.multiply(@tat );
2534 end;
2535 
2536 procedure TAggFPCanvas.AggParallelogram(const x1, y1, x2, y2: double; para: PDouble);
2537 var
2538   ta : trans_affine;
2539 begin
2540   ta.Construct(x1 ,y1 ,x2 ,y2 ,parallelo_ptr(para ) );
2541 
2542   m_transform.multiply(@ta );
2543 
2544   Path.m_convCurve.approximation_scale_ (AggWorldToScreen(1.0 ) * g_approxScale );
2545   m_convStroke.approximation_scale_(AggWorldToScreen(1.0 ) * g_approxScale );
2546 end;
2547 
2548 procedure TAggFPCanvas.AggViewport(const worldX1, worldY1, worldX2, worldY2,
2549   screenX1, screenY1, screenX2, screenY2: double; const opt: TAggViewportOption
2550   );
2551 var
2552   vp : trans_viewport;
2553   mx : trans_affine;
2554 
2555 begin
2556   vp.Construct;
2557 
2558   case opt of
2559   AGG_Anisotropic :
2560    vp.preserve_aspect_ratio(0.0 ,0.0 ,aspect_ratio_stretch );
2561 
2562   AGG_XMinYMin :
2563    vp.preserve_aspect_ratio(0.0 ,0.0 ,aspect_ratio_meet );
2564 
2565   AGG_XMidYMin :
2566    vp.preserve_aspect_ratio(0.5 ,0.0 ,aspect_ratio_meet );
2567 
2568   AGG_XMaxYMin :
2569    vp.preserve_aspect_ratio(1.0 ,0.0 ,aspect_ratio_meet );
2570 
2571   AGG_XMinYMid :
2572    vp.preserve_aspect_ratio(0.0 ,0.5 ,aspect_ratio_meet );
2573 
2574   AGG_XMidYMid :
2575    vp.preserve_aspect_ratio(0.5 ,0.5 ,aspect_ratio_meet );
2576 
2577   AGG_XMaxYMid :
2578    vp.preserve_aspect_ratio(1.0 ,0.5 ,aspect_ratio_meet );
2579 
2580   AGG_XMinYMax :
2581    vp.preserve_aspect_ratio(0.0 ,1.0 ,aspect_ratio_meet );
2582 
2583   AGG_XMidYMax :
2584    vp.preserve_aspect_ratio(0.5 ,1.0 ,aspect_ratio_meet );
2585 
2586   AGG_XMaxYMax :
2587    vp.preserve_aspect_ratio(1.0 ,1.0 ,aspect_ratio_meet );
2588 
2589   end;
2590 
2591   vp.world_viewport (worldX1  ,worldY1  ,worldX2  ,worldY2 );
2592   vp.device_viewport(screenX1 ,screenY1 ,screenX2 ,screenY2 );
2593 
2594   mx.Construct;
2595 
2596   vp.to_affine        (@mx );
2597   m_transform.multiply(@mx );
2598 
2599   Path.m_convCurve.approximation_scale_ (AggWorldToScreen(1.0 ) * g_approxScale );
2600   m_convStroke.approximation_scale_(AggWorldToScreen(1.0 ) * g_approxScale );
2601 end;
2602 
2603 procedure TAggFPCanvas.AggWorldToScreen(x, y: PDouble);
2604 begin
2605   m_transform.transform(@m_transform ,double_ptr(x ) ,double_ptr(y ) );
2606 end;
2607 
2608 procedure TAggFPCanvas.AggScreenToWorld(x, y: PDouble);
2609 begin
2610   m_transform.inverse_transform(@m_transform ,double_ptr(x ) ,double_ptr(y ) );
2611 end;
2612 
AggWorldToScreennull2613 function TAggFPCanvas.AggWorldToScreen(const scalar: double): double;
2614 var
2615   x1 ,y1 ,x2 ,y2 : double;
2616 begin
2617   x1:=0;
2618   y1:=0;
2619   x2:=scalar;
2620   y2:=scalar;
2621 
2622   AggWorldToScreen(@x1 ,@y1 );
2623   AggWorldToScreen(@x2 ,@y2 );
2624 
2625   result:=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) ) * 0.7071068;
2626 end;
2627 
AggScreenToWorldnull2628 function TAggFPCanvas.AggScreenToWorld(const scalar: double): double;
2629 var
2630   x1 ,y1 ,x2 ,y2 : double;
2631 begin
2632   x1:=0;
2633   y1:=0;
2634   x2:=scalar;
2635   y2:=scalar;
2636 
2637   AggScreenToWorld(@x1 ,@y1 );
2638   AggScreenToWorld(@x2 ,@y2 );
2639 
2640   result:=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) ) * 0.7071068;
2641 end;
2642 
2643 procedure TAggFPCanvas.AggAlignPoint(x, y: PDouble);
2644 begin
2645   AggWorldToScreen(x ,y );
2646 
2647   x^:=Floor(x^ ) + 0.5;
2648   y^:=Floor(y^ ) + 0.5;
2649 
2650   AggScreenToWorld(x ,y );
2651 end;
2652 
2653 procedure TAggFPCanvas.AggRenderImage(img: TAggFPImage; x1, y1, x2,
2654   y2: integer; parl: PDouble);
2655 var
2656   mtx : trans_affine;
2657   interpolator : span_interpolator_linear;
2658 begin
2659   mtx.Construct(x1 ,y1 ,x2 ,y2 ,parallelo_ptr(parl ) );
2660   mtx.multiply (@m_transform );
2661   mtx.invert;
2662 
2663   m_rasterizer.reset;
2664   m_rasterizer.add_path(@m_pathTransform );
2665 
2666   interpolator.Construct(@mtx );
2667 
2668   if (m_blendMode = AGG_BlendAlpha ) or
2669     (Image.PixelFormat = afpimRGB24 ) then
2670     Agg2DRenderer_renderImage(img ,@m_renBasePre ,@interpolator )
2671   else
2672     Agg2DRenderer_renderImage(img ,@m_renBaseCompPre ,@interpolator );
2673 end;
2674 
2675 procedure TAggFPCanvas.AggTransformImage(SrcImage: TAggFPImage; const imgX1,
2676   imgY1, imgX2, imgY2: integer; const dstX1, dstY1, dstX2, dstY2: double);
2677 var
2678   parall : array[0..5 ] of double;
2679 begin
2680   AggResetPath;
2681   AggMoveTo(dstX1 ,dstY1 );
2682   AggLineTo(dstX2 ,dstY1 );
2683   AggLineTo(dstX2 ,dstY2 );
2684   AggLineTo(dstX1 ,dstY2 );
2685   AggClosePolygon;
2686 
2687   parall[0 ]:=dstX1;
2688   parall[1 ]:=dstY1;
2689   parall[2 ]:=dstX2;
2690   parall[3 ]:=dstY1;
2691   parall[4 ]:=dstX2;
2692   parall[5 ]:=dstY2;
2693 
2694   AggRenderImage(SrcImage ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,@parall[0 ] );
2695 end;
2696 
2697 procedure TAggFPCanvas.AggTransformImage(SrcImage: TAggFPImage; const dstX1,
2698   dstY1, dstX2, dstY2: double);
2699 var
2700   parall : array[0..5 ] of double;
2701 begin
2702   AggResetPath;
2703   AggMoveTo(dstX1 ,dstY1 );
2704   AggLineTo(dstX2 ,dstY1 );
2705   AggLineTo(dstX2 ,dstY2 );
2706   AggLineTo(dstX1 ,dstY2 );
2707   AggClosePolygon;
2708 
2709   parall[0 ]:=dstX1;
2710   parall[1 ]:=dstY1;
2711   parall[2 ]:=dstX2;
2712   parall[3 ]:=dstY1;
2713   parall[4 ]:=dstX2;
2714   parall[5 ]:=dstY2;
2715 
2716   AggRenderImage(SrcImage ,0 ,0 ,SrcImage.Width ,SrcImage.Height ,@parall[0 ] );
2717 end;
2718 
2719 procedure TAggFPCanvas.AggTransformImage(SrcImage: TAggFPImage; imgX1, imgY1,
2720   imgX2, imgY2: integer; parallelo: PDouble);
2721 begin
2722   AggResetPath;
2723 
2724   AggMoveTo(
2725     PDouble(ptrcomp(parallelo ) + 0 * sizeof(double ) )^ ,
2726     PDouble(ptrcomp(parallelo ) + 1 * sizeof(double ) )^ );
2727 
2728   AggLineTo(
2729     PDouble(ptrcomp(parallelo ) + 2 * sizeof(double ) )^ ,
2730     PDouble(ptrcomp(parallelo ) + 3 * sizeof(double ) )^ );
2731 
2732   AggLineTo(
2733     PDouble(ptrcomp(parallelo ) + 4 * sizeof(double ) )^ ,
2734     PDouble(ptrcomp(parallelo ) + 5 * sizeof(double ) )^ );
2735 
2736   AggLineTo(
2737     PDouble(ptrcomp(parallelo ) + 0 * sizeof(double ) )^ +
2738     PDouble(ptrcomp(parallelo ) + 4 * sizeof(double ) )^ -
2739     PDouble(ptrcomp(parallelo ) + 2 * sizeof(double ) )^ ,
2740     PDouble(ptrcomp(parallelo ) + 1 * sizeof(double ) )^ +
2741     PDouble(ptrcomp(parallelo ) + 5 * sizeof(double ) )^ -
2742     PDouble(ptrcomp(parallelo ) + 3 * sizeof(double ) )^ );
2743 
2744   AggClosePolygon;
2745 
2746   AggRenderImage(SrcImage ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,parallelo );
2747 end;
2748 
2749 procedure TAggFPCanvas.AggTransformImage(SrcImage: TAggFPImage; parallelo: PDouble);
2750 begin
2751   AggResetPath;
2752 
2753   AggMoveTo(
2754     PDouble(ptrcomp(parallelo ) + 0 * sizeof(double ) )^ ,
2755     PDouble(ptrcomp(parallelo ) + 1 * sizeof(double ) )^ );
2756 
2757   AggLineTo(
2758     PDouble(ptrcomp(parallelo ) + 2 * sizeof(double ) )^ ,
2759     PDouble(ptrcomp(parallelo ) + 3 * sizeof(double ) )^ );
2760 
2761   AggLineTo(
2762     PDouble(ptrcomp(parallelo ) + 4 * sizeof(double ) )^ ,
2763     PDouble(ptrcomp(parallelo ) + 5 * sizeof(double ) )^ );
2764 
2765   AggLineTo(
2766     PDouble(ptrcomp(parallelo ) + 0 * sizeof(double ) )^ +
2767     PDouble(ptrcomp(parallelo ) + 4 * sizeof(double ) )^ -
2768     PDouble(ptrcomp(parallelo ) + 2 * sizeof(double ) )^ ,
2769     PDouble(ptrcomp(parallelo ) + 1 * sizeof(double ) )^ +
2770     PDouble(ptrcomp(parallelo ) + 5 * sizeof(double ) )^ -
2771     PDouble(ptrcomp(parallelo ) + 3 * sizeof(double ) )^ );
2772 
2773   AggClosePolygon;
2774 
2775   AggRenderImage(SrcImage ,0 ,0 ,SrcImage.Width ,SrcImage.Height ,parallelo );
2776 end;
2777 
2778 procedure TAggFPCanvas.AggTransformImagePath(SrcImage: TAggFPImage; const imgX1,
2779   imgY1, imgX2, imgY2: integer; const dstX1, dstY1, dstX2, dstY2: double);
2780 var
2781   parall : array[0..5 ] of double;
2782 begin
2783   parall[0 ]:=dstX1;
2784   parall[1 ]:=dstY1;
2785   parall[2 ]:=dstX2;
2786   parall[3 ]:=dstY1;
2787   parall[4 ]:=dstX2;
2788   parall[5 ]:=dstY2;
2789 
2790   AggRenderImage(SrcImage ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,@parall[0 ] );
2791 end;
2792 
2793 procedure TAggFPCanvas.AggTransformImagePath(SrcImage: TAggFPImage; const dstX1,
2794   dstY1, dstX2, dstY2: double);
2795 var
2796   parall : array[0..5 ] of double;
2797 begin
2798   parall[0 ]:=dstX1;
2799   parall[1 ]:=dstY1;
2800   parall[2 ]:=dstX2;
2801   parall[3 ]:=dstY1;
2802   parall[4 ]:=dstX2;
2803   parall[5 ]:=dstY2;
2804 
2805   AggRenderImage(SrcImage ,0 ,0 ,SrcImage.Width ,SrcImage.Height ,@parall[0 ] );
2806 end;
2807 
2808 procedure TAggFPCanvas.AggTransformImagePath(SrcImage: TAggFPImage; const imgX1,
2809   imgY1, imgX2, imgY2: integer; const parallelo: PDouble);
2810 begin
2811   AggRenderImage(SrcImage ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,parallelo );
2812 end;
2813 
2814 procedure TAggFPCanvas.AggTransformImagePath(SrcImage: TAggFPImage;
2815   parallelo: PDouble);
2816 begin
2817   AggRenderImage(SrcImage ,0 ,0 ,SrcImage.Width ,SrcImage.Height ,parallelo );
2818 end;
2819 
2820 procedure TAggFPCanvas.AggCopyImage(SrcImage: TAggFPImage; const imgX1, imgY1,
2821   imgX2, imgY2: integer; const dstX, dstY: double);
2822 var
2823   r: agg_basics.rect;
2824 begin
2825   AggWorldToScreen(@dstX ,@dstY );
2826   r.Construct  (imgX1 ,imgY1 ,imgX2 ,imgY2 );
2827 
2828   m_renBase.copy_from(@SrcImage.RenderingBuffer ,@r ,
2829                       Trunc(dstX ) - imgX1 ,Trunc(dstY ) - imgY1 );
2830 end;
2831 
2832 procedure TAggFPCanvas.AggCopyImage(SrcImage: TAggFPImage; const dstX,
2833   dstY: double);
2834 begin
2835   AggWorldToScreen(@dstX ,@dstY );
2836   m_renBase.copy_from(@SrcImage.RenderingBuffer ,NIL ,Trunc(dstX ) ,Trunc(dstY ) );
2837 end;
2838 
AggTextWidthnull2839 function TAggFPCanvas.AggTextWidth(str: AnsiString): double;
2840 {$IFDEF AGG2D_NO_FONT}
2841 begin
2842 
2843 end;
2844 {$ELSE}
2845 var
2846   x ,y  : double;
2847   first : boolean;
2848   glyph : glyph_cache_ptr;
2849   str_  : PChar;
2850   charlen: int;
2851   char_id: int32u;
2852 begin
2853   if str='' then exit(0);
2854   x:=0;
2855   y:=0;
2856 
2857   first:=true;
2858   str_ :=@str[1 ];
2859 
2860   while str_^ <> #0 do
2861   begin
2862     if UseUTF8 then
2863     begin
2864       char_id:=AggUTF8CharToUnicode(str_,charlen);
2865       inc(str_,charlen);
2866     end else begin
2867       char_id:=int32u(char_ptr(str_)^);
2868       inc(str_,sizeof(char));
2869     end;
2870     glyph:=m_fontCacheManager.glyph(char_id);
2871 
2872     if glyph <> NIL then
2873     begin
2874       if not first then
2875         m_fontCacheManager.add_kerning(@x ,@y );
2876 
2877       x:=x + glyph^.advance_x;
2878       y:=y + glyph^.advance_y;
2879 
2880       first:=false;
2881     end;
2882 
2883   end;
2884 
2885   if Font.FAggCache = AGG_VectorFontCache then
2886     result:=x
2887   else
2888     result:=AggScreenToWorld(x );
2889 end;
2890 {$ENDIF}
2891 
AggTextHeightnull2892 function TAggFPCanvas.AggTextHeight(str: AnsiString): double;
2893 begin
2894   {$IFDEF AGG2D_NO_FONT}
2895   Result:=0;
2896   {$ELSE}
2897   Result:=m_fontEngine._height;
2898   {$ENDIF}
2899 end;
2900 
2901 procedure TAggFPCanvas.AggTextOut(const x, y: double; str: AnsiString;
2902   roundOff: boolean; const ddx: double; const ddy: double);
2903 {$IFDEF AGG2D_NO_FONT}
2904 begin
2905 
2906 end;
2907 {$ELSE}
2908 var
2909   dx ,dy ,asc ,start_x ,start_y : double;
2910 
2911   glyph : glyph_cache_ptr;
2912 
2913   mtx  : trans_affine;
2914   str_ : PChar;
2915 
2916   tat : trans_affine_translation;
2917   tar : trans_affine_rotation;
2918 
2919   tr : conv_transform;
2920   charlen: int;
2921   char_id: int32u;
2922   First: Boolean;
2923 
2924 begin
2925   if Str='' then exit;
2926 
2927   dx:=0.0;
2928   dy:=0.0;
2929 
2930   case Font.AggAlignX of
2931   AGG_AlignCenter :
2932     dx:=-AggTextWidth(str ) * 0.5;
2933 
2934   AGG_AlignRight :
2935     dx:=-AggTextWidth(str );
2936 
2937   end;
2938 
2939   asc  :=Font.AggHeight;
2940   glyph:=m_fontCacheManager.glyph(int32u('H' ) );
2941 
2942   if glyph <> NIL then
2943     asc:=glyph^.bounds.y2 - glyph^.bounds.y1;
2944 
2945   if Font.FAggCache = AGG_RasterFontCache then
2946     asc:=AggScreenToWorld(asc );
2947 
2948   case Font.AggAlignY of
2949   AGG_AlignCenter :
2950     dy:=-asc * 0.5;
2951 
2952   AGG_AlignTop :
2953     dy:=-asc;
2954 
2955   end;
2956 
2957   if m_fontEngine._flip_y then
2958     dy:=-dy;
2959 
2960   mtx.Construct;
2961 
2962   start_x:=x + dx;
2963   start_y:=y + dy;
2964 
2965   if roundOff then
2966   begin
2967     start_x:=Trunc(start_x );
2968     start_y:=Trunc(start_y );
2969   end;
2970 
2971   start_x:=start_x + ddx;
2972   start_y:=start_y + ddy;
2973 
2974   tat.Construct(-x ,-y );
2975   mtx.multiply (@tat );
2976 
2977   tar.Construct(Font.AggAngle );
2978   mtx.multiply (@tar );
2979 
2980   tat.Construct(x ,y );
2981   mtx.multiply (@tat );
2982 
2983   tr.Construct(m_fontCacheManager.path_adaptor ,@mtx );
2984 
2985   if Font.FAggCache = AGG_RasterFontCache then
2986     AggWorldToScreen(@start_x ,@start_y );
2987 
2988   str_:=@str[1 ];
2989   First:=true;
2990 
2991   while str_^ <> #0 do
2992   begin
2993     if UseUTF8 then
2994     begin
2995       char_id:=AggUTF8CharToUnicode(str_,charlen);
2996       inc(str_,charlen);
2997     end else begin
2998       char_id:=int32u(char_ptr(str_)^);
2999       inc(str_,sizeof(char));
3000     end;
3001     glyph:=m_fontCacheManager.glyph(char_id);
3002 
3003     if glyph <> NIL then
3004     begin
3005       if First then
3006       begin
3007         m_fontCacheManager.add_kerning(@x ,@y );
3008         First:=false;
3009       end;
3010 
3011       m_fontCacheManager.init_embedded_adaptors(glyph ,start_x ,start_y );
3012 
3013       if glyph^.data_type = glyph_data_outline then
3014       begin
3015         Path.m_path.remove_all;
3016         Path.m_path.add_path(@tr ,0 ,false );
3017 
3018         if Font.AggUseOnlyFont then
3019           AggDrawPath(AGG_FillOnly,true)
3020         else
3021           AggDrawPath(AGG_FillAndStroke,true);
3022       end;
3023 
3024       if glyph^.data_type = glyph_data_gray8 then
3025       begin
3026         Render(
3027           m_fontCacheManager.gray8_adaptor ,
3028           m_fontCacheManager.gray8_scanline );
3029       end;
3030 
3031       start_x:=start_x + glyph^.advance_x;
3032       start_y:=start_y + glyph^.advance_y;
3033     end;
3034   end;
3035 end;
3036 {$ENDIF}
3037 
3038 { AGG2DRENDERER_RENDER }
3039 procedure TAggFPCanvas.Agg2DRenderer_render(
3040            renBase : renderer_base_ptr;
3041            renSolid : renderer_scanline_aa_solid_ptr;
3042            fillColor_ , UseFont: boolean );
3043 var
3044  span : span_gradient;
3045  ren  : TAggFP_renderer_scanline_aa;
3046  clr  : aggclr;
3047 
3048 begin
3049   if (fillColor_ and
3050      (m_fillGradientFlag = AGG_Linear ) ) or
3051     (not fillColor_ and
3052      (m_lineGradientFlag = AGG_Linear ) ) then
3053   if fillColor_ then
3054    begin
3055     span.Construct(
3056      @m_allocator ,
3057      @m_fillGradientInterpolator ,
3058      @m_linearGradientFunction ,
3059      @m_fillGradient ,
3060      m_fillGradientD1 ,
3061      m_fillGradientD2 );
3062 
3063     ren.Construct   (renBase ,@span );
3064     render_scanlines(@m_rasterizer ,@m_scanline ,@ren );
3065 
3066    end
3067   else
3068    begin
3069     span.Construct(
3070      @m_allocator ,
3071      @m_lineGradientInterpolator ,
3072      @m_linearGradientFunction ,
3073      @m_lineGradient ,
3074      m_lineGradientD1 ,
3075      m_lineGradientD2 );
3076 
3077     ren.Construct   (renBase ,@span );
3078     render_scanlines(@m_rasterizer ,@m_scanline ,@ren );
3079 
3080    end
3081   else
3082   if (fillColor_ and
3083       (m_fillGradientFlag = AGG_Radial ) ) or
3084      (not fillColor_ and
3085       (m_lineGradientFlag = AGG_Radial ) ) then
3086   begin
3087     if fillColor_ then
3088     begin
3089      span.Construct(
3090       @m_allocator ,
3091       @m_fillGradientInterpolator ,
3092       @m_radialGradientFunction ,
3093       @m_fillGradient ,
3094       m_fillGradientD1 ,
3095       m_fillGradientD2 );
3096 
3097       ren.Construct   (renBase ,@span );
3098       render_scanlines(@m_rasterizer ,@m_scanline ,@ren );
3099 
3100     end
3101     else
3102     begin
3103      span.Construct(
3104       @m_allocator ,
3105       @m_lineGradientInterpolator ,
3106       @m_radialGradientFunction ,
3107       @m_lineGradient ,
3108       m_lineGradientD1 ,
3109       m_lineGradientD2 );
3110 
3111      ren.Construct   (renBase ,@span );
3112      render_scanlines(@m_rasterizer ,@m_scanline ,@ren );
3113 
3114     end;
3115   end
3116   else
3117   begin
3118     if UseFont then
3119       clr.Construct(Font.FAggColor )
3120     else if fillColor_ then
3121       clr.Construct(Brush.FAggColor )
3122     else
3123       clr.Construct(Pen.FAggColor );
3124 
3125     renSolid^.color_ (@clr );
3126     render_scanlines(@m_rasterizer ,@m_scanline ,renSolid );
3127   end;
3128 end;
3129 
3130 procedure TAggFPCanvas.Agg2DRenderer_render(
3131            renBase : renderer_base_ptr;
3132            renSolid : renderer_scanline_aa_solid_ptr;
3133            ras : gray8_adaptor_type_ptr;
3134            sl : gray8_scanline_type_ptr;
3135            UseFont: boolean);
3136 var
3137  span : span_gradient;
3138  ren  : renderer_scanline_aa;
3139  clr  : aggclr;
3140 
3141 begin
3142   if UseFont then
3143   begin
3144     clr.Construct(Brush.fAggColor );
3145     renSolid^.color_ (@clr );
3146     render_scanlines(ras ,sl ,renSolid );
3147   end
3148   else if m_fillGradientFlag = AGG_Linear then
3149   begin
3150    span.Construct(
3151     @m_allocator ,
3152     @m_fillGradientInterpolator ,
3153     @m_linearGradientFunction ,
3154     @m_fillGradient ,
3155     m_fillGradientD1 ,
3156     m_fillGradientD2 );
3157 
3158    ren.Construct   (renBase ,@span );
3159    render_scanlines(ras ,sl ,@ren );
3160 
3161   end
3162   else
3163   if m_fillGradientFlag = AGG_Radial then
3164    begin
3165     span.Construct(
3166      @m_allocator ,
3167      @m_fillGradientInterpolator ,
3168      @m_radialGradientFunction ,
3169      @m_fillGradient ,
3170      m_fillGradientD1 ,
3171      m_fillGradientD2 );
3172 
3173     ren.Construct   (renBase ,@span );
3174     render_scanlines(ras ,sl ,@ren );
3175 
3176    end
3177   else
3178   begin
3179     clr.Construct(Brush.fAggColor );
3180     renSolid^.color_ (@clr );
3181     render_scanlines(ras ,sl ,renSolid );
3182   end;
3183 end;
3184 
3185 procedure TAggFPCanvas.addLine(const x1, y1, x2, y2: double);
3186 begin
3187   Path.m_path.move_to(x1 ,y1 );
3188   Path.m_path.line_to(x2 ,y2 );
3189 end;
3190 
GetAggTransformationsnull3191 function TAggFPCanvas.GetAggTransformations: TAggTransformations;
3192 begin
3193   m_transform.store_to(@result.affineMatrix[0]);
3194 end;
3195 
3196 procedure TAggFPCanvas.Agg2DRenderer_renderImage(
3197            img : TAggFPImage;
3198            renBase : renderer_base_ptr;
3199            interpolator : span_interpolator_linear_ptr );
3200 var
3201  blend : TAggSpanConvImageBlend;
3202 
3203  si : span_image_filter_rgba;
3204  sg : span_image_filter_rgba_nn;
3205  sb : span_image_filter_rgba_bilinear;
3206  s2 : span_image_filter_rgba_2x2;
3207  sa : span_image_resample_rgba_affine;
3208  sc : span_converter;
3209  ri : renderer_scanline_aa;
3210 
3211  clr : aggclr;
3212 
3213  resample : boolean;
3214 
3215  sx ,sy : double;
3216 
3217 begin
3218  case Image.PixelFormat of
3219   afpimRGBA32 :
3220    blend.Construct(m_imageBlendMode ,m_imageBlendColor ,@m_pixFormatCompPre );
3221 
3222   else
3223    blend.Construct(m_imageBlendMode ,m_imageBlendColor ,NIL );
3224 
3225  end;
3226 
3227  if m_imageFilter = AGG_NoFilter then
3228   begin
3229    clr.ConstrInt(0 ,0 ,0 ,0 );
3230    sg.Construct (@m_allocator ,@img.RenderingBuffer ,@clr ,interpolator ,rgba_order );
3231    sc.Construct (@sg ,@blend );
3232    ri.Construct (renBase ,@sc );
3233 
3234    render_scanlines(@m_rasterizer ,@m_scanline ,@ri );
3235 
3236   end
3237  else
3238   begin
3239    resample:=m_imageResample = AGG_ResampleAlways;
3240 
3241    if m_imageResample = AGG_ResampleOnZoomOut then
3242     begin
3243      interpolator^._transformer^.scaling_abs(@sx ,@sy );
3244 
3245      if (sx > 1.125 ) or
3246         (sy > 1.125 ) then
3247       resample:=true;
3248 
3249     end;
3250 
3251    if resample then
3252     begin
3253      clr.ConstrInt(0 ,0 ,0 ,0 );
3254      sa.Construct(
3255       @m_allocator ,
3256       @img.RenderingBuffer ,
3257       @clr ,
3258       interpolator ,
3259       @m_imageFilterLut ,
3260       rgba_order );
3261 
3262      sc.Construct(@sa ,@blend );
3263      ri.Construct(renBase ,@sc );
3264 
3265      render_scanlines(@m_rasterizer ,@m_scanline ,@ri );
3266 
3267     end
3268    else
3269     if m_imageFilter = AGG_Bilinear then
3270      begin
3271       clr.ConstrInt(0 ,0 ,0 ,0 );
3272       sb.Construct(
3273        @m_allocator ,
3274        @img.RenderingBuffer ,
3275        @clr ,
3276        interpolator ,
3277        rgba_order );
3278 
3279       sc.Construct(@sb ,@blend );
3280       ri.Construct(renBase ,@sc );
3281 
3282       render_scanlines(@m_rasterizer ,@m_scanline ,@ri );
3283 
3284      end
3285     else
3286      if m_imageFilterLut.diameter = 2 then
3287       begin
3288        clr.ConstrInt(0 ,0 ,0 ,0 );
3289        s2.Construct(
3290         @m_allocator ,
3291         @img.RenderingBuffer ,
3292         @clr ,
3293         interpolator,
3294         @m_imageFilterLut ,
3295         rgba_order );
3296 
3297        sc.Construct(@s2 ,@blend );
3298        ri.Construct(renBase ,@sc );
3299 
3300        render_scanlines(@m_rasterizer ,@m_scanline ,@ri );
3301 
3302       end
3303      else
3304       begin
3305        clr.ConstrInt(0 ,0 ,0 ,0 );
3306        si.Construct(
3307         @m_allocator ,
3308         @img.RenderingBuffer ,
3309         @clr ,
3310         interpolator ,
3311         @m_imageFilterLut ,
3312         rgba_order );
3313 
3314        sc.Construct(@si ,@blend );
3315        ri.Construct(renBase ,@sc );
3316 
3317        render_scanlines(@m_rasterizer ,@m_scanline ,@ri );
3318 
3319       end;
3320 
3321   end;
3322 
3323 end;
3324 
3325 { TAggFPPen }
3326 
3327 procedure TAggFPPen.SetFPColor(const AValue: TFPColor);
3328 begin
3329   if FPColor=AValue then exit;
3330   inherited SetFPColor(AValue);
3331   FAggColor:=FPToAggColor(AValue);
3332 end;
3333 
3334 procedure TAggFPPen.SetAggColor(const AValue: TAggColor);
3335 begin
3336   FPColor:=AggToFPColor(AValue);
3337 end;
3338 
3339 procedure TAggFPPen.DoCopyProps(From: TFPCanvasHelper);
3340 var
3341   Src: TAggFPPen;
3342 begin
3343   inherited DoCopyProps(From);
3344   if From is TAggFPPen then begin
3345     Src:=TAggFPPen(From);
3346     FAggColor:=Src.FAggColor;
3347     AggLineCap:=Src.AggLineCap;
3348     AggLineJoin:=Src.AggLineJoin;
3349     AggLineWidth:=Src.AggLineWidth;
3350   end;
3351 end;
3352 
3353 constructor TAggFPPen.Create;
3354 begin
3355   inherited Create;
3356   FAggLineCap:=AGG_CapRound;
3357   FAggLineJoin:=AGG_JoinRound;
3358   FAggLineWidth:=1.0;
3359 end;
3360 
3361 procedure TAggFPPen.SetAggLineCap(const AValue: TAggLineCap);
3362 begin
3363   if FAggLineCap=AValue then exit;
3364   FAggLineCap:=AValue;
3365   TAggFPCanvas(Canvas).m_convStroke.line_cap_(FAggLineCap);
3366 end;
3367 
3368 procedure TAggFPPen.SetAggLineJoin(const AValue: TAggLineJoin);
3369 begin
3370   if FAggLineJoin=AValue then exit;
3371   FAggLineJoin:=AValue;
3372   TAggFPCanvas(Canvas).m_convStroke.line_join_(FAggLineJoin);
3373 end;
3374 
3375 procedure TAggFPPen.SetAggLineWidth(const AValue: double);
3376 begin
3377   if FAggLineWidth=AValue then exit;
3378   FAggLineWidth:=AValue;
3379   inherited SetWidth(round(AValue));
3380   TAggFPCanvas(Canvas).m_convStroke.width_(FAggLineWidth);
3381 end;
3382 
3383 procedure TAggFPPen.SetWidth(AValue: Integer);
3384 var
3385   NewWidth: Double;
3386 begin
3387   NewWidth:=double(AValue);
3388   if NewWidth=AggLineWidth then exit;
3389   inherited SetWidth(AValue);
3390   AggLineWidth:=NewWidth;
3391 end;
3392 
3393 { CONSTRUCT }
3394 constructor TAggRasterizerGamma.Construct(alpha ,gamma : double );
3395 begin
3396   m_alpha.Construct(alpha );
3397   m_gamma.Construct(gamma );
3398 end;
3399 
3400 { FUNC_OPERATOR_GAMMA }
func_operator_gammanull3401 function TAggRasterizerGamma.func_operator_gamma(x : double ) : double;
3402 begin
3403   result:=m_alpha.func_operator_gamma(m_gamma.func_operator_gamma(x ) );
3404 end;
3405 
operator_arraynull3406 function TAggRasterizerGamma.operator_array(i: unsigned): unsigned;
3407 begin
3408   Result:=i;
3409 end;
3410 
3411 { TAggFPBrush }
3412 
3413 procedure TAggFPBrush.SetAggFillEvenOdd(const AValue: boolean);
3414 begin
3415   if FAggFillEvenOdd=AValue then exit;
3416   FAggFillEvenOdd:=AValue;
3417 
3418   if FAggFillEvenOdd then
3419     TAggFPCanvas(Canvas).m_rasterizer.filling_rule(fill_even_odd )
3420   else
3421     TAggFPCanvas(Canvas).m_rasterizer.filling_rule(fill_non_zero );
3422 end;
3423 
3424 procedure TAggFPBrush.DoCopyProps(From: TFPCanvasHelper);
3425 var
3426   Src: TAggFPBrush;
3427 begin
3428   inherited DoCopyProps(From);
3429   if From is TAggFPBrush then begin
3430     Src:=TAggFPBrush(From);
3431     FAggColor:=Src.FAggColor;
3432     AggFillEvenOdd:=Src.AggFillEvenOdd;
3433   end;
3434 end;
3435 
3436 procedure TAggFPBrush.SetFPColor(const AValue: TFPColor);
3437 begin
3438   if FPColor=AValue then exit;
3439   inherited SetFPColor(AValue);
3440   FAggColor:=FPToAggColor(AValue);
3441 end;
3442 
3443 procedure TAggFPBrush.SetAggColor(const AValue: TAggColor);
3444 begin
3445   FPColor:=AggToFPColor(AValue);
3446 end;
3447 
3448 procedure TAggFPBrush.SetStyle(AValue: TFPBrushStyle);
3449 begin
3450   if Style=AValue then exit;
3451   inherited SetStyle(AValue);
3452   // not supported by aggpas
3453 end;
3454 
3455 { TAggFPFont }
3456 
3457 procedure TAggFPFont.SetAggAlignX(const AValue: TAggTextAlignment);
3458 begin
3459   if FAggAlignX=AValue then exit;
3460   FAggAlignX:=AValue;
3461 end;
3462 
3463 procedure TAggFPFont.SetAggAlignY(const AValue: TAggTextAlignment);
3464 begin
3465   if FAggAlignY=AValue then exit;
3466   FAggAlignY:=AValue;
3467 end;
3468 
3469 procedure TAggFPFont.SetAggAngle(const AValue: double);
3470 begin
3471   if FAggAngle=AValue then exit;
3472   FAggAngle:=AValue;
3473 end;
3474 
3475 procedure TAggFPFont.SetAggFlipY(const AValue: boolean);
3476 begin
3477   if FAggFlipY=AValue then exit;
3478   FAggFlipY:=AValue;
3479   {$IFNDEF AGG2D_NO_FONT}
3480   TAggFPCanvas(Canvas).m_fontEngine.flip_y_(not FAggFlipY);
3481   {$ENDIF}
3482 end;
3483 
3484 procedure TAggFPFont.SetAggHeight(const AValue: double);
3485 {$IFDEF AGG2D_USE_FREETYPE}
3486 var
3487   c: TAggFPCanvas;
3488 {$ENDIF}
3489 begin
3490   if FAggHeight=AValue then exit;
3491   FAggHeight:=AValue;
3492   inherited SetSize(round(AggHeightToSize(FAggHeight)));
3493   {$IFDEF AGG2D_USE_FREETYPE}
3494   c:=TAggFPCanvas(Canvas);
3495   if FAggCache = AGG_VectorFontCache then
3496     c.m_fontEngine.height_(FAggHeight )
3497   else
3498     c.m_fontEngine.height_(c.AggWorldToScreen(FAggHeight ) );
3499   {$ELSE}
3500   // ToDo
3501   {$ENDIF}
3502 end;
3503 
3504 procedure TAggFPFont.SetAggHinting(const AValue: boolean);
3505 begin
3506   if FAggHinting=AValue then exit;
3507   FAggHinting:=AValue;
3508   {$IFDEF AGG2D_USE_FREETYPE}
3509   TAggFPCanvas(Canvas).m_fontEngine.hinting_(FAggHinting );
3510   {$ENDIF}
3511 end;
3512 
3513 procedure TAggFPFont.SetSize(AValue: integer);
3514 begin
3515   AggHeight:=SizeToAggHeight(AValue);
3516 end;
3517 
AggHeightToSizenull3518 function TAggFPFont.AggHeightToSize(const h: double): double;
3519 begin
3520   Result:=h;
3521 end;
3522 
SizeToAggHeightnull3523 function TAggFPFont.SizeToAggHeight(const s: double): double;
3524 begin
3525   Result:=s;
3526 end;
3527 
3528 procedure TAggFPFont.SetFPColor(const AValue: TFPColor);
3529 begin
3530   if FPColor=AValue then exit;
3531   inherited SetFPColor(AValue);
3532   FAggColor:=FPToAggColor(AValue);
3533 end;
3534 
3535 procedure TAggFPFont.SetAggColor(const AValue: TAggColor);
3536 begin
3537   FPColor:=AggToFPColor(AValue);
3538 end;
3539 
3540 procedure TAggFPFont.DoCopyProps(From: TFPCanvasHelper);
3541 var
3542   Src: TAggFPFont;
3543 begin
3544   inherited DoCopyProps(From);
3545   if From is TAggFPFont then begin
3546     Src:=TAggFPFont(From);
3547     FAggColor:=Src.FAggColor;
3548     AggAlignX:=Src.AggAlignX;
3549     AggAlignY:=Src.AggAlignY;
3550     AggAngle:=Src.AggAngle;
3551     AggHinting:=Src.AggHinting;
3552     FAggHeight:=Src.AggHeight;
3553   end;
3554 end;
3555 
3556 constructor TAggFPFont.Create;
3557 begin
3558   inherited Create;
3559   FAggAlignX:=AGG_AlignLeft;
3560   FAggAlignY:=AGG_AlignBottom;
3561   FAggHinting:=true;
3562   FAggUseOnlyFont:=true;
3563 end;
3564 
3565 procedure TAggFPFont.LoadFromFile(aFilename: String; const NewHeight: double;
3566   const NewBold: boolean; const NewItalic: boolean;
3567   const NewCache: TAggFontCacheType; const NewAngle: double;
3568   const NewHinting: boolean);
3569 {$IFDEF AGG2D_USE_WINFONTS }
3570 var
3571   b : int;
3572 {$ENDIF}
3573 var
3574   c: TAggFPCanvas;
3575 begin
3576   FAggAngle:=NewAngle;
3577   FAggHeight:=NewHeight;
3578   inherited SetSize(round(FAggHeight));
3579   FAggCache:=NewCache;
3580   FAggHinting:=NewHinting;
3581   inherited SetFlags(5,NewBold); // Bold
3582   inherited SetFlags(6,NewItalic); // Italic
3583   inherited SetFlags(7,false); // Underline
3584   inherited SetFlags(8,false); // StrikeThrough
3585 
3586   c:=TAggFPCanvas(Canvas);
3587 
3588   {$IFDEF AGG2D_USE_FREETYPE }
3589   if FAggCache = AGG_VectorFontCache then
3590     c.m_fontEngine.load_font(PChar(@AFileName[1 ] ) ,0 ,glyph_ren_outline )
3591   else
3592     c.m_fontEngine.load_font(PChar(@AFileName[1 ] ) ,0 ,glyph_ren_agg_gray8 );
3593 
3594   c.m_fontEngine.hinting_(FAggHinting );
3595 
3596   if FAggCache = AGG_VectorFontCache then
3597     c.m_fontEngine.height_(FAggHeight )
3598   else
3599     c.m_fontEngine.height_(c.AggWorldToScreen(FAggHeight ) );
3600 
3601   {$ENDIF }
3602   {$IFDEF AGG2D_USE_WINFONTS}
3603 
3604   c.m_fontEngine.hinting_(FAggHinting );
3605 
3606   if Bold then
3607     b:=700
3608   else
3609     b:=400;
3610 
3611   if FAggCache = AGG_VectorFontCache then
3612     c.m_fontEngine.create_font_(PChar(@AFileName[1 ] ) ,glyph_ren_outline ,
3613       FAggHeight ,0.0 ,b ,Italic )
3614   else
3615     c.m_fontEngine.create_font_(PChar(@AFileName[1 ] ) ,glyph_ren_agg_gray8 ,
3616       c.AggWorldToScreen(FAggHeight) ,0.0 ,b ,Italic );
3617   {$ENDIF }
3618 
3619   {$IFNDEF AGG2D_NO_FONT}
3620   TAggFPCanvas(Canvas).m_fontEngine.flip_y_(not FAggFlipY);
3621   {$ENDIF}
3622 end;
3623 
3624 { TAggFP_renderer_scanline_aa }
3625 
3626 procedure TAggFP_renderer_scanline_aa.add_path(vs: vertex_source_ptr;
3627   path_id: unsigned);
3628 begin
3629   raise Exception.Create('not usable');
3630 end;
3631 
3632 procedure TAggFP_renderer_scanline_aa.add_vertex(x, y: double; cmd: unsigned);
3633 begin
3634   raise Exception.Create('not usable');
3635 end;
3636 
3637 procedure TAggFP_renderer_scanline_aa.clip_box(x1, y1, x2, y2: double);
3638 begin
3639   raise Exception.Create('not usable');
3640 end;
3641 
3642 procedure TAggFP_renderer_scanline_aa.color_(c: aggclr_ptr);
3643 begin
3644   raise Exception.Create('not usable');
3645 end;
3646 
3647 procedure TAggFP_renderer_scanline_aa.filling_rule(filling_rule_: filling_rule_e);
3648 begin
3649   raise Exception.Create('not usable');
3650 end;
3651 
3652 procedure TAggFP_renderer_scanline_aa.gamma(gamma_function: vertex_source_ptr);
3653 begin
3654   raise Exception.Create('not usable');
3655 end;
3656 
3657 procedure TAggFP_renderer_scanline_aa.reset;
3658 begin
3659   raise Exception.Create('not usable');
3660 end;
3661 
_max_ynull3662 function TAggFP_renderer_scanline_aa._max_y: int;
3663 begin
3664   raise Exception.Create('not usable');
3665   Result:=0;
3666 end;
3667 
_max_xnull3668 function TAggFP_renderer_scanline_aa._max_x: int;
3669 begin
3670   raise Exception.Create('not usable');
3671   Result:=0;
3672 end;
3673 
_min_xnull3674 function TAggFP_renderer_scanline_aa._min_x: int;
3675 begin
3676   raise Exception.Create('not usable');
3677   Result:=0;
3678 end;
3679 
_min_ynull3680 function TAggFP_renderer_scanline_aa._min_y: int;
3681 begin
3682   raise Exception.Create('not usable');
3683   Result:=0;
3684 end;
3685 
hit_testnull3686 function TAggFP_renderer_scanline_aa.hit_test(tx, ty: int): boolean;
3687 begin
3688   raise Exception.Create('not usable');
3689   Result:=false;
3690 end;
3691 
sweep_scanlinenull3692 function TAggFP_renderer_scanline_aa.sweep_scanline(sl: scanline_ptr): boolean;
3693 begin
3694   raise Exception.Create('not usable');
3695   Result:=false;
3696 end;
3697 
sweep_scanline_emnull3698 function TAggFP_renderer_scanline_aa.sweep_scanline_em(sl: scanline_ptr
3699   ): boolean;
3700 begin
3701   raise Exception.Create('not usable');
3702   Result:=false;
3703 end;
3704 
rewind_scanlinesnull3705 function TAggFP_renderer_scanline_aa.rewind_scanlines: boolean;
3706 begin
3707   raise Exception.Create('not usable');
3708   Result:=false;
3709 end;
3710 
3711 procedure TAggFP_renderer_scanline_aa.sort;
3712 begin
3713   raise Exception.Create('not usable');
3714 end;
3715 
3716 { TAggFPPath }
3717 
3718 procedure TAggFPPath.SetAggColor(const AValue: TAggColor);
3719 begin
3720   FPColor:=AggToFPColor(AValue);
3721 end;
3722 
3723 procedure TAggFPPath.DoCopyProps(From: TFPCanvasHelper);
3724 var
3725   Src: TAggFPPath;
3726 begin
3727   inherited DoCopyProps(From);
3728   if From is TAggFPPath then begin
3729     Src:=TAggFPPath(From);
3730     FAggColor:=Src.FAggColor;
3731   end;
3732 end;
3733 
3734 constructor TAggFPPath.Create;
3735 begin
3736   inherited Create;
3737   m_path.Construct;
3738   m_convCurve.Construct (@m_path );
3739 end;
3740 
3741 destructor TAggFPPath.Destroy;
3742 begin
3743   m_convCurve.Destruct;
3744   m_path.Destruct;
3745   inherited Destroy;
3746 end;
3747 
3748 end.
3749 
3750