Repository URL to install this package:
|
Version:
1.6 ▾
|
//----------------------------------------------------------------------------
// Agg2D - Version 1.0
// Based on Anti-Grain Geometry
// Copyright (C) 2005 Maxim Shemanarev (http://www.antigrain.com)
//
// TAgg2D - Version 1.0 Release Milano 3 (AggPas 2.4 RM3)
// Pascal Port By: Milan Marusinec alias Milano
// milan@marusinec.sk
// http://www.aggpas.org
// Copyright (c) 2007 - 2008
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//
// [Pascal Port History] -----------------------------------------------------
//
// 22.11.2007-Milano: Unit port establishment
// 23.11.2007-Milano: Porting
// 11.12.2007-Milano: -"-
// 13.12.2007-Milano: -"-
// 13.01.2008-Milano: Finished OK
//
{ Agg2D.pas }
unit
Agg2D ;
INTERFACE
{$I agg_mode.inc }
// With this define you can switch use of FreeType or Win32 TrueType font engine
{off DEFINE AGG2D_USE_FREETYPE }
{$IFDEF AGG_LINUX}
{$DEFINE AGG2D_USE_FREETYPE }
{$ENDIF}
uses
agg_basics ,
agg_array ,
agg_trans_affine ,
agg_trans_viewport ,
agg_path_storage ,
agg_conv_stroke ,
agg_conv_transform ,
agg_conv_curve ,
agg_rendering_buffer ,
agg_renderer_base ,
agg_renderer_scanline ,
agg_span_gradient ,
agg_span_image_filter_rgba ,
agg_span_image_resample_rgba ,
agg_span_converter ,
agg_span_interpolator_linear ,
agg_span_allocator ,
agg_rasterizer_scanline_aa ,
agg_gamma_functions ,
agg_scanline_u ,
agg_arc ,
agg_bezier_arc ,
agg_rounded_rect ,
agg_font_engine ,
agg_font_cache_manager ,
agg_pixfmt ,
agg_pixfmt_rgb ,
agg_pixfmt_rgba ,
agg_color ,
agg_math_stroke ,
agg_image_filters ,
agg_vertex_source ,
agg_render_scanlines ,
{$IFDEF AGG2D_USE_FREETYPE }
agg_font_freetype ,
{$ENDIF}
{$IFDEF AGG2D_USE_WINFONTS}
agg_font_win32_tt ,
{$ENDIF }
Math ,
{$IFDEF AGG_WINDOWS}
Windows ,
{$ENDIF}
Classes ,Graphics ;
{ GLOBAL VARIABLES & CONSTANTS }
const
// LineJoin
AGG_JoinMiter = miter_join;
AGG_JoinRound = round_join;
AGG_JoinBevel = bevel_join;
// LineCap
AGG_CapButt = butt_cap;
AGG_CapSquare = square_cap;
AGG_CapRound = round_cap;
// TextAlignment
AGG_AlignLeft = 0;
AGG_AlignRight = 1;
AGG_AlignCenter = 2;
AGG_AlignTop = AGG_AlignRight;
AGG_AlignBottom = AGG_AlignLeft;
// BlendMode
AGG_BlendAlpha = end_of_comp_op_e;
AGG_BlendClear = comp_op_clear;
AGG_BlendSrc = comp_op_src;
AGG_BlendDst = comp_op_dst;
AGG_BlendSrcOver = comp_op_src_over;
AGG_BlendDstOver = comp_op_dst_over;
AGG_BlendSrcIn = comp_op_src_in;
AGG_BlendDstIn = comp_op_dst_in;
AGG_BlendSrcOut = comp_op_src_out;
AGG_BlendDstOut = comp_op_dst_out;
AGG_BlendSrcAtop = comp_op_src_atop;
AGG_BlendDstAtop = comp_op_dst_atop;
AGG_BlendXor = comp_op_xor;
AGG_BlendAdd = comp_op_plus;
AGG_BlendSub = comp_op_minus;
AGG_BlendMultiply = comp_op_multiply;
AGG_BlendScreen = comp_op_screen;
AGG_BlendOverlay = comp_op_overlay;
AGG_BlendDarken = comp_op_darken;
AGG_BlendLighten = comp_op_lighten;
AGG_BlendColorDodge = comp_op_color_dodge;
AGG_BlendColorBurn = comp_op_color_burn;
AGG_BlendHardLight = comp_op_hard_light;
AGG_BlendSoftLight = comp_op_soft_light;
AGG_BlendDifference = comp_op_difference;
AGG_BlendExclusion = comp_op_exclusion;
AGG_BlendContrast = comp_op_contrast;
{ TYPES DEFINITION }
type
PDouble = ^double;
PAggColor = ^TAggColor;
TAggColor = rgba8;
TAggRectD = agg_basics.rect_d;
TAggAffine = trans_affine;
PAggAffine = trans_affine_ptr;
TAggFontRasterizer = gray8_adaptor_type;
PAggFontRasterizer = gray8_adaptor_type_ptr;
TAggFontScanline = gray8_scanline_type;
PAggFontScanline = gray8_scanline_type_ptr;
{$IFDEF AGG2D_USE_FREETYPE }
TAggFontEngine = font_engine_freetype_int32;
{$ENDIF }
{$IFDEF AGG2D_USE_WINFONTS}
TAggFontEngine = font_engine_win32_tt_int32;
{$ENDIF }
TAggGradient = (AGG_Solid ,AGG_Linear ,AGG_Radial );
TAggDirection = (AGG_CW, AGG_CCW );
TAggLineJoin = int;
TAggLineCap = int;
TAggBlendMode = comp_op_e;
TAggTextAlignment = int;
TAggDrawPathFlag = (
AGG_FillOnly ,
AGG_StrokeOnly ,
AGG_FillAndStroke ,
AGG_FillWithLineColor );
TAggViewportOption = (
AGG_Anisotropic ,
AGG_XMinYMin ,
AGG_XMidYMin ,
AGG_XMaxYMin ,
AGG_XMinYMid ,
AGG_XMidYMid ,
AGG_XMaxYMid ,
AGG_XMinYMax ,
AGG_XMidYMax ,
AGG_XMaxYMax );
TAggImageFilter = (
AGG_NoFilter ,
AGG_Bilinear ,
AGG_Hanning ,
AGG_Hermite ,
AGG_Quadric ,
AGG_Bicubic ,
AGG_Catrom ,
AGG_Spline16 ,
AGG_Spline36 ,
AGG_Blackman144 );
TAggImageResample = (
AGG_NoResample ,
AGG_ResampleAlways ,
AGG_ResampleOnZoomOut );
TAggFontCacheType = (
AGG_RasterFontCache ,
AGG_VectorFontCache );
PAggTransformations = ^TAggTransformations;
TAggTransformations = record
affineMatrix : array[0..5 ] of double;
end;
TAggRasterizerGamma = object(vertex_source )
m_alpha : gamma_multiply;
m_gamma : gamma_power;
constructor Construct(alpha ,gamma : double );
function func_operator_gamma(x : double ) : double; virtual;
end;
PAggImage = ^TAggImage;
TAggImage = object
renBuf : rendering_buffer;
constructor Construct;
destructor Destruct;
function attach(bitmap : TBitmap; flip : boolean ) : boolean;
function width : int;
function height : int;
end;
TAgg2D = class
private
m_rbuf : rendering_buffer;
m_pixf : TPixelFormat;
m_pixFormat ,m_pixFormatComp ,m_pixFormatPre ,m_pixFormatCompPre : pixel_formats;
m_renBase ,m_renBaseComp ,m_renBasePre ,m_renBaseCompPre : renderer_base;
m_renSolid ,m_renSolidComp : renderer_scanline_aa_solid;
m_allocator : span_allocator;
m_clipBox : TAggRectD;
m_blendMode ,m_imageBlendMode : TAggBlendMode;
m_imageBlendColor : TAggColor;
m_scanline : scanline_u8;
m_rasterizer : rasterizer_scanline_aa;
m_masterAlpha ,m_antiAliasGamma : double;
m_fillColor ,m_lineColor : TAggColor;
m_fillGradient ,m_lineGradient : pod_auto_array;
m_lineCap : TAggLineCap;
m_lineJoin : TAggLineJoin;
m_fillGradientFlag ,m_lineGradientFlag : TAggGradient;
m_fillGradientMatrix ,m_lineGradientMatrix : trans_affine;
m_fillGradientD1 ,
m_lineGradientD1 ,
m_fillGradientD2 ,
m_lineGradientD2 ,
m_textAngle : double;
m_textAlignX ,
m_textAlignY : TAggTextAlignment;
m_textHints : boolean;
m_fontHeight ,
m_fontAscent ,
m_fontDescent : double;
m_fontCacheType : TAggFontCacheType;
m_imageFilter : TAggImageFilter;
m_imageResample : TAggImageResample;
m_imageFilterLut : image_filter_lut;
m_fillGradientInterpolator ,
m_lineGradientInterpolator : span_interpolator_linear;
m_linearGradientFunction : gradient_x;
m_radialGradientFunction : gradient_circle;
m_lineWidth : double;
m_evenOddFlag : boolean;
m_path : path_storage;
m_transform : trans_affine;
m_convCurve : conv_curve;
m_convStroke : conv_stroke;
m_pathTransform ,m_strokeTransform : conv_transform;
m_imageFlip : boolean;
{$IFDEF AGG2D_USE_WINFONTS }
m_fontDC : HDC;
{$ENDIF }
m_fontEngine : TAggFontEngine;
m_fontCacheManager : font_cache_manager;
// Other Pascal-specific members
m_gammaNone : gamma_none;
m_gammaAgg2D : TAggRasterizerGamma;
m_ifBilinear : image_filter_bilinear;
m_ifHanning : image_filter_hanning;
m_ifHermite : image_filter_hermite;
m_ifQuadric : image_filter_quadric;
m_ifBicubic : image_filter_bicubic;
m_ifCatrom : image_filter_catrom;
m_ifSpline16 : image_filter_spline16;
m_ifSpline36 : image_filter_spline36;
m_ifBlackman144 : image_filter_blackman144;
public
constructor Create;
destructor Destroy; override;
// Vector Graphics Engine Initialization
function Attach(bitmap : TBitmap; flip_y : boolean = false ) : boolean;
procedure ClearAll(c : TAggColor ); overload;
procedure ClearAll(r ,g ,b : byte; a : byte = 255 ); overload;
// Master Rendering Properties
procedure BlendMode(m : TAggBlendMode ); overload;
function BlendMode : TAggBlendMode; overload;
procedure MasterAlpha(a : double ); overload;
function MasterAlpha : double; overload;
procedure AntiAliasGamma(g : double ); overload;
function AntiAliasGamma : double; overload;
procedure FillColor(c : TAggColor ); overload;
procedure FillColor(r ,g ,b : byte; a : byte = 255 ); overload;
procedure NoFill;
procedure LineColor(c : TAggColor ); overload;
procedure LineColor(r ,g ,b : byte; a : byte = 255 ); overload;
procedure NoLine;
function FillColor : TAggColor; overload;
function LineColor : TAggColor; overload;
procedure FillLinearGradient(x1 ,y1 ,x2 ,y2 : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
procedure LineLinearGradient(x1 ,y1 ,x2 ,y2 : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
procedure FillRadialGradient(x ,y ,r : double; c1 ,c2 : TAggColor; profile : double = 1.0 ); overload;
procedure LineRadialGradient(x ,y ,r : double; c1 ,c2 : TAggColor; profile : double = 1.0 ); overload;
procedure FillRadialGradient(x ,y ,r : double; c1 ,c2 ,c3 : TAggColor ); overload;
procedure LineRadialGradient(x ,y ,r : double; c1 ,c2 ,c3 : TAggColor ); overload;
procedure FillRadialGradient(x ,y ,r : double ); overload;
procedure LineRadialGradient(x ,y ,r : double ); overload;
procedure LineWidth(w : double ); overload;
function LineWidth : double; overload;
procedure LineCap(cap : TAggLineCap ); overload;
function LineCap : TAggLineCap; overload;
procedure LineJoin(join : TAggLineJoin ); overload;
function LineJoin : TAggLineJoin; overload;
procedure FillEvenOdd(evenOddFlag : boolean ); overload;
function FillEvenOdd : boolean; overload;
// Affine Transformations
function Transformations : TAggTransformations; overload;
procedure Transformations(tr : PAggTransformations ); overload;
procedure ResetTransformations;
procedure Affine(tr : PAggAffine ); overload;
procedure Affine(tr : PAggTransformations ); overload;
procedure Rotate (angle : double );
procedure Scale (sx ,sy : double );
procedure Skew (sx ,sy : double );
procedure Translate(x ,y : double );
procedure Parallelogram(x1 ,y1 ,x2 ,y2 : double; para : PDouble );
procedure Viewport(
worldX1 ,worldY1 ,worldX2 ,worldY2 ,
screenX1 ,screenY1 ,screenX2 ,screenY2 : double;
opt : TAggViewportOption = AGG_XMidYMid );
// Coordinates Conversions
procedure WorldToScreen(x ,y : PDouble ); overload;
procedure ScreenToWorld(x ,y : PDouble ); overload;
function WorldToScreen(scalar : double ) : double; overload;
function ScreenToWorld(scalar : double ) : double; overload;
procedure AlignPoint(x ,y : PDouble );
// Clipping
procedure ClipBox(x1 ,y1 ,x2 ,y2 : double ); overload;
function ClipBox : TAggRectD; overload;
procedure ClearClipBox(c : TAggColor ); overload;
procedure ClearClipBox(r ,g ,b : byte; a : byte = 255 ); overload;
function InBox(worldX ,worldY : double ) : boolean;
// Basic Shapes
procedure Line (x1 ,y1 ,x2 ,y2 : double );
procedure Triangle (x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double );
procedure Rectangle(x1 ,y1 ,x2 ,y2 : double );
procedure RoundedRect(x1 ,y1 ,x2 ,y2 ,r : double ); overload;
procedure RoundedRect(x1 ,y1 ,x2 ,y2 ,rx ,ry : double ); overload;
procedure RoundedRect(
x1 ,y1 ,x2 ,y2 ,
rxBottom ,ryBottom ,
rxTop ,ryTop : double ); overload;
procedure Ellipse(cx ,cy ,rx ,ry : double );
procedure Arc (cx ,cy ,rx ,ry ,start ,sweep : double );
procedure Star(cx ,cy ,r1 ,r2 ,startAngle : double; numRays : integer );
procedure Curve(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double ); overload;
procedure Curve(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double ); overload;
procedure Polygon (xy : PDouble; numPoints : integer );
procedure Polyline(xy : PDouble; numPoints : integer );
// Path Commands
procedure ResetPath;
procedure MoveTo (x ,y : double );
procedure MoveRel(dx ,dy : double );
procedure LineTo (x ,y : double );
procedure LineRel(dx ,dy : double );
procedure HorLineTo (x : double );
procedure HorLineRel(dx : double );
procedure VerLineTo (y : double );
procedure VerLineRel(dy : double );
procedure ArcTo(
rx ,ry ,angle : double;
largeArcFlag ,sweepFlag : boolean;
x ,y : double );
procedure ArcRel(
rx ,ry ,angle : double;
largeArcFlag ,sweepFlag : boolean;
dx ,dy : double );
procedure QuadricCurveTo (xCtrl ,yCtrl ,xTo ,yTo : double ); overload;
procedure QuadricCurveRel(dxCtrl ,dyCtrl ,dxTo ,dyTo : double ); overload;
procedure QuadricCurveTo (xTo ,yTo : double ); overload;
procedure QuadricCurveRel(dxTo ,dyTo : double ); overload;
procedure CubicCurveTo (xCtrl1 ,yCtrl1 ,xCtrl2 ,yCtrl2 ,xTo ,yTo : double ); overload;
procedure CubicCurveRel(dxCtrl1 ,dyCtrl1 ,dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo : double ); overload;
procedure CubicCurveTo (xCtrl2 ,yCtrl2 ,xTo ,yTo : double ); overload;
procedure CubicCurveRel(dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo : double ); overload;
procedure AddEllipse(cx ,cy ,rx ,ry : double; dir : TAggDirection );
procedure ClosePolygon;
procedure DrawPath(flag : TAggDrawPathFlag = AGG_FillAndStroke );
// Text Rendering
procedure FlipText(flip : boolean );
procedure Font(
fileName : AnsiString; height : double;
bold : boolean = false;
italic : boolean = false;
cache : TAggFontCacheType = AGG_VectorFontCache;
angle : double = 0.0 );
function FontHeight : double;
procedure TextAlignment(alignX ,alignY : TAggTextAlignment );
function TextHints : boolean; overload;
procedure TextHints(hints : boolean ); overload;
function TextWidth(str : AnsiString ) : double;
procedure Text(
x ,y : double; str : AnsiString;
roundOff : boolean = false;
ddx : double = 0.0;
ddy : double = 0.0 );
// Image Rendering
procedure ImageFilter(f : TAggImageFilter ); overload;
function ImageFilter : TAggImageFilter; overload;
procedure ImageResample(f : TAggImageResample ); overload;
function ImageResample : TAggImageResample; overload;
procedure ImageFlip(f : boolean );
procedure TransformImage(
bitmap : TBitmap;
imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
dstX1 ,dstY1 ,dstX2 ,dstY2 : double ); overload;
procedure TransformImage(
bitmap : TBitmap;
dstX1 ,dstY1 ,dstX2 ,dstY2 : double ); overload;
procedure TransformImage(
bitmap : TBitmap;
imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
parallelo : PDouble ); overload;
procedure TransformImage(bitmap : TBitmap; parallelo : PDouble ); overload;
procedure TransformImagePath(
bitmap : TBitmap;
imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
dstX1 ,dstY1 ,dstX2 ,dstY2 : double ); overload;
procedure TransformImagePath(
bitmap : TBitmap;
dstX1 ,dstY1 ,dstX2 ,dstY2 : double ); overload;
procedure TransformImagePath(
bitmap : TBitmap;
imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
parallelo : PDouble ); overload;
procedure TransformImagePath(bitmap : TBitmap; parallelo : PDouble ); overload;
procedure CopyImage(
bitmap : TBitmap;
imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
dstX ,dstY : double ); overload;
procedure CopyImage(bitmap : TBitmap; dstX ,dstY : double ); overload;
private
procedure render(fillColor_ : boolean ); overload;
procedure render(ras : PAggFontRasterizer; sl : PAggFontScanline ); overload;
procedure addLine(x1 ,y1 ,x2 ,y2 : double );
procedure updateRasterizerGamma;
procedure renderImage(
img : PAggImage;
x1 ,y1 ,x2 ,y2 : integer;
parl : PDouble );
end;
{ GLOBAL PROCEDURES }
// Standalone API
function Deg2Rad(v : double ) : double;
function Rad2Deg(v : double ) : double;
function Agg2DUsesFreeType : boolean;
function Agg2DUsesWin32TrueType : boolean;
function BitmapAlphaTransparency(bitmap : TBitmap; alpha : byte ) : boolean;
IMPLEMENTATION
{ LOCAL VARIABLES & CONSTANTS }
var
g_approxScale : double = 2.0;
type
PAggSpanConvImageBlend = ^TAggSpanConvImageBlend;
TAggSpanConvImageBlend = object(span_convertor )
private
m_mode : TAggBlendMode;
m_color : TAggColor;
m_pixel : pixel_formats_ptr; // m_pixFormatCompPre
public
constructor Construct(m : TAggBlendMode; c : TAggColor; p : pixel_formats_ptr );
procedure convert(span : aggclr_ptr; x ,y : int; len : unsigned ); virtual;
end;
{ OPERATOR_IS_EQUAL }
function operator_is_equal(c1 ,c2 : PAggColor ) : boolean;
begin
result:=
(c1.r = c2.r ) and
(c1.g = c2.g ) and
(c1.b = c2.b ) and
(c1.a = c2.a );
end;
{ OPERATOR_IS_NOT_EQUAL }
function operator_is_not_equal(c1 ,c2 : PAggColor ) : boolean;
begin
result:=not operator_is_equal(c1 ,c2 );
end;
{ AGG2DRENDERER_RENDER }
procedure Agg2DRenderer_render(
gr : TAgg2D;
renBase : renderer_base_ptr;
renSolid : renderer_scanline_aa_solid_ptr;
fillColor_ : boolean ); overload;
var
span : span_gradient;
ren : renderer_scanline_aa;
clr : aggclr;
begin
if (fillColor_ and
(gr.m_fillGradientFlag = AGG_Linear ) ) or
(not fillColor_ and
(gr.m_lineGradientFlag = AGG_Linear ) ) then
if fillColor_ then
begin
span.Construct(
@gr.m_allocator ,
@gr.m_fillGradientInterpolator ,
@gr.m_linearGradientFunction ,
@gr.m_fillGradient ,
gr.m_fillGradientD1 ,
gr.m_fillGradientD2 );
ren.Construct (renBase ,@span );
render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ren );
end
else
begin
span.Construct(
@gr.m_allocator ,
@gr.m_lineGradientInterpolator ,
@gr.m_linearGradientFunction ,
@gr.m_lineGradient ,
gr.m_lineGradientD1 ,
gr.m_lineGradientD2 );
ren.Construct (renBase ,@span );
render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ren );
end
else
if (fillColor_ and
(gr.m_fillGradientFlag = AGG_Radial ) ) or
(not fillColor_ and
(gr.m_lineGradientFlag = AGG_Radial ) ) then
if fillColor_ then
begin
span.Construct(
@gr.m_allocator ,
@gr.m_fillGradientInterpolator ,
@gr.m_radialGradientFunction ,
@gr.m_fillGradient ,
gr.m_fillGradientD1 ,
gr.m_fillGradientD2 );
ren.Construct (renBase ,@span );
render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ren );
end
else
begin
span.Construct(
@gr.m_allocator ,
@gr.m_lineGradientInterpolator ,
@gr.m_radialGradientFunction ,
@gr.m_lineGradient ,
gr.m_lineGradientD1 ,
gr.m_lineGradientD2 );
ren.Construct (renBase ,@span );
render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ren );
end
else
begin
if fillColor_ then
clr.Construct(gr.m_fillColor )
else
clr.Construct(gr.m_lineColor );
renSolid.color_ (@clr );
render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,renSolid );
end;
end;
{ AGG2DRENDERER_RENDER }
procedure Agg2DRenderer_render(
gr : TAgg2D;
renBase : renderer_base_ptr;
renSolid : renderer_scanline_aa_solid_ptr;
ras : gray8_adaptor_type_ptr;
sl : gray8_scanline_type_ptr ); overload;
var
span : span_gradient;
ren : renderer_scanline_aa;
clr : aggclr;
begin
if gr.m_fillGradientFlag = AGG_Linear then
begin
span.Construct(
@gr.m_allocator ,
@gr.m_fillGradientInterpolator ,
@gr.m_linearGradientFunction ,
@gr.m_fillGradient ,
gr.m_fillGradientD1 ,
gr.m_fillGradientD2 );
ren.Construct (renBase ,@span );
render_scanlines(ras ,sl ,@ren );
end
else
if gr.m_fillGradientFlag = AGG_Radial then
begin
span.Construct(
@gr.m_allocator ,
@gr.m_fillGradientInterpolator ,
@gr.m_radialGradientFunction ,
@gr.m_fillGradient ,
gr.m_fillGradientD1 ,
gr.m_fillGradientD2 );
ren.Construct (renBase ,@span );
render_scanlines(ras ,sl ,@ren );
end
else
begin
clr.Construct (gr.m_fillColor );
renSolid.color_ (@clr );
render_scanlines(ras ,sl ,renSolid );
end;
end;
{ AGG2DRENDERER_RENDERIMAGE }
procedure Agg2DRenderer_renderImage(
gr : TAgg2D;
img : PAggImage;
renBase : renderer_base_ptr;
interpolator : span_interpolator_linear_ptr );
var
blend : TAggSpanConvImageBlend;
si : span_image_filter_rgba;
sg : span_image_filter_rgba_nn;
sb : span_image_filter_rgba_bilinear;
s2 : span_image_filter_rgba_2x2;
sa : span_image_resample_rgba_affine;
sc : span_converter;
ri : renderer_scanline_aa;
clr : aggclr;
resample : boolean;
sx ,sy : double;
begin
case gr.m_pixf of
pf32bit :
blend.Construct(gr.m_imageBlendMode ,gr.m_imageBlendColor ,@gr.m_pixFormatCompPre );
else
blend.Construct(gr.m_imageBlendMode ,gr.m_imageBlendColor ,NIL );
end;
if gr.m_imageFilter = AGG_NoFilter then
begin
clr.ConstrInt(0 ,0 ,0 ,0 );
sg.Construct (@gr.m_allocator ,@img.renBuf ,@clr ,interpolator ,rgba_order );
sc.Construct (@sg ,@blend );
ri.Construct (renBase ,@sc );
render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ri );
end
else
begin
resample:=gr.m_imageResample = AGG_ResampleAlways;
if gr.m_imageResample = AGG_ResampleOnZoomOut then
begin
interpolator._transformer.scaling_abs(@sx ,@sy );
if (sx > 1.125 ) or
(sy > 1.125 ) then
resample:=true;
end;
if resample then
begin
clr.ConstrInt(0 ,0 ,0 ,0 );
sa.Construct(
@gr.m_allocator ,
@img.renBuf ,
@clr ,
interpolator ,
@gr.m_imageFilterLut ,
rgba_order );
sc.Construct(@sa ,@blend );
ri.Construct(renBase ,@sc );
render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ri );
end
else
if gr.m_imageFilter = AGG_Bilinear then
begin
clr.ConstrInt(0 ,0 ,0 ,0 );
sb.Construct(
@gr.m_allocator ,
@img.renBuf ,
@clr ,
interpolator ,
rgba_order );
sc.Construct(@sb ,@blend );
ri.Construct(renBase ,@sc );
render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ri );
end
else
if gr.m_imageFilterLut.diameter = 2 then
begin
clr.ConstrInt(0 ,0 ,0 ,0 );
s2.Construct(
@gr.m_allocator ,
@img.renBuf ,
@clr ,
interpolator,
@gr.m_imageFilterLut ,
rgba_order );
sc.Construct(@s2 ,@blend );
ri.Construct(renBase ,@sc );
render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ri );
end
else
begin
clr.ConstrInt(0 ,0 ,0 ,0 );
si.Construct(
@gr.m_allocator ,
@img.renBuf ,
@clr ,
interpolator ,
@gr.m_imageFilterLut ,
rgba_order );
sc.Construct(@si ,@blend );
ri.Construct(renBase ,@sc );
render_scanlines(@gr.m_rasterizer ,@gr.m_scanline ,@ri );
end;
end;
end;
{ AGG2DUSESFREETYPE }
function Agg2DUsesFreeType : boolean;
begin
{$IFDEF AGG2D_USE_FREETYPE }
result:=true;
{$ELSE}
result:=false;
{$ENDIF }
end;
function Agg2DUsesWin32TrueType: boolean;
begin
{$IFDEF AGG2D_USE_WINFONTS }
result:=true;
{$ELSE}
result:=false;
{$ENDIF }
end;
{ CONSTRUCT }
constructor TAggSpanConvImageBlend.Construct(m : TAggBlendMode; c : TAggColor; p : pixel_formats_ptr );
begin
m_mode :=m;
m_color:=c;
m_pixel:=p;
end;
{ CONVERT }
procedure TAggSpanConvImageBlend.convert(span : aggclr_ptr; x ,y : int; len : unsigned );
var
l2 ,a : unsigned;
s2 : PAggColor;
begin
if (m_mode <> AGG_BlendDst ) and
(m_pixel <> NIL ) then
begin{!}
l2:=len;
s2:=PAggColor(span );
repeat
comp_op_adaptor_clip_to_dst_rgba_pre(
m_pixel ,
unsigned(m_mode ) ,
int8u_ptr(s2 ) ,
m_color.r ,
m_color.g ,
m_color.b ,
base_mask ,
cover_full );
inc(ptrcomp(s2 ) ,sizeof(aggclr ) );
dec(l2 );
until l2 = 0;
end;
if m_color.a < base_mask then
begin
l2:=len;
s2:=PAggColor(span );
a :=m_color.a;
repeat
s2.r:=(s2.r * a ) shr base_shift;
s2.g:=(s2.g * a ) shr base_shift;
s2.b:=(s2.b * a ) shr base_shift;
s2.a:=(s2.a * a ) shr base_shift;
inc(ptrcomp(s2 ) ,sizeof(aggclr ) );
dec(l2 );
until l2 = 0;
end;
end;
{ DEG2RAD }
function deg2Rad(v : double ) : double;
begin
result:=v * agg_basics.pi / 180.0;
end;
{ RAD2DEG }
function rad2Deg(v : double ) : double;
begin
result:=v * 180.0 / agg_basics.pi;
end;
{ UNIT IMPLEMENTATION }
{ CONSTRUCT }
constructor TAggImage.Construct;
begin
renBuf.Construct;
end;
{ DESTRUCT }
destructor TAggImage.Destruct;
begin
renBuf.Destruct;
end;
{ ATTACH }
function TAggImage.attach(bitmap : TBitmap; flip : boolean ) : boolean;
var
buffer : pointer;
stride : integer;
begin
result:=false;
if Assigned(bitmap ) and
not bitmap.Empty then
case bitmap.PixelFormat of
pf32bit :
begin
{ Rendering Buffer }
stride:=integer(bitmap.ScanLine[1 ] ) - integer(bitmap.ScanLine[0 ] );
if stride < 0 then
buffer:=bitmap.ScanLine[bitmap.Height - 1 ]
else
buffer:=bitmap.ScanLine[0 ];
if flip then
stride:=stride * -1;
renBuf.attach(
buffer ,
bitmap.Width ,
bitmap.Height ,
stride );
{ OK }
result:=true;
end;
end;
end;
{ WIDTH }
function TAggImage.width : int;
begin
result:=renBuf._width;
end;
{ HEIGHT }
function TAggImage.height : int;
begin
result:=renBuf._height;
end;
{ CONSTRUCT }
constructor TAggRasterizerGamma.Construct(alpha ,gamma : double );
begin
m_alpha.Construct(alpha );
m_gamma.Construct(gamma );
end;
{ FUNC_OPERATOR_GAMMA }
function TAggRasterizerGamma.func_operator_gamma(x : double ) : double;
begin
result:=m_alpha.func_operator_gamma(m_gamma.func_operator_gamma(x ) );
end;
{ CREATE }
constructor TAgg2D.Create;
begin
m_rbuf.Construct;
m_pixf:=pf32bit;
pixfmt_rgba32 (m_pixFormat ,@m_rbuf );
pixfmt_custom_blend_rgba(m_pixFormatComp ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order );
pixfmt_rgba32 (m_pixFormatPre ,@m_rbuf );
pixfmt_custom_blend_rgba(m_pixFormatCompPre ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order );
m_renBase.Construct (@m_pixFormat );
m_renBaseComp.Construct (@m_pixFormatComp );
m_renBasePre.Construct (@m_pixFormatPre );
m_renBaseCompPre.Construct(@m_pixFormatCompPre );
m_renSolid.Construct (@m_renBase );
m_renSolidComp.Construct(@m_renBaseComp );
m_allocator.Construct;
m_clipBox.Construct(0 ,0 ,0 ,0 );
m_blendMode :=AGG_BlendAlpha;
m_imageBlendMode:=AGG_BlendDst;
m_imageBlendColor.Construct(0 ,0 ,0 );
m_scanline.Construct;
m_rasterizer.Construct;
m_masterAlpha :=1.0;
m_antiAliasGamma:=1.0;
m_fillColor.Construct(255 ,255 ,255 );
m_lineColor.Construct(0 ,0 ,0 );
m_fillGradient.Construct(256 ,sizeof(aggclr ) );
m_lineGradient.Construct(256 ,sizeof(aggclr ) );
m_lineCap :=AGG_CapRound;
m_lineJoin:=AGG_JoinRound;
m_fillGradientFlag:=AGG_Solid;
m_lineGradientFlag:=AGG_Solid;
m_fillGradientMatrix.Construct;
m_lineGradientMatrix.Construct;
m_fillGradientD1:=0.0;
m_lineGradientD1:=0.0;
m_fillGradientD2:=100.0;
m_lineGradientD2:=100.0;
m_textAngle :=0.0;
m_textAlignX :=AGG_AlignLeft;
m_textAlignY :=AGG_AlignBottom;
m_textHints :=true;
m_fontHeight :=0.0;
m_fontAscent :=0.0;
m_fontDescent:=0.0;
m_fontCacheType:=AGG_RasterFontCache;
m_imageFilter :=AGG_Bilinear;
m_imageResample:=AGG_NoResample;
m_gammaNone.Construct;
m_ifBilinear.Construct;
m_ifHanning.Construct;
m_ifHermite.Construct;
m_ifQuadric.Construct;
m_ifBicubic.Construct;
m_ifCatrom.Construct;
m_ifSpline16.Construct;
m_ifSpline36.Construct;
m_ifBlackman144.Construct;
m_imageFilterLut.Construct(@m_ifBilinear ,true );
m_linearGradientFunction.Construct;
m_radialGradientFunction.Construct;
m_fillGradientInterpolator.Construct(@m_fillGradientMatrix );
m_lineGradientInterpolator.Construct(@m_lineGradientMatrix );
m_lineWidth :=1;
m_evenOddFlag:=false;
m_imageFlip:=false;
m_path.Construct;
m_transform.Construct;
m_convCurve.Construct (@m_path );
m_convStroke.Construct(@m_convCurve );
m_pathTransform.Construct (@m_convCurve ,@m_transform );
m_strokeTransform.Construct(@m_convStroke ,@m_transform );
{$IFDEF AGG2D_USE_FREETYPE }
m_fontEngine.Construct;
{$ENDIF}
{$IFDEF AGG2D_USE_WINFONTS}
m_fontDC:=GetDC(0 );
m_fontEngine.Construct(m_fontDC );
{$ENDIF }
m_fontCacheManager.Construct(@m_fontEngine );
LineCap (m_lineCap );
LineJoin(m_lineJoin );
end;
{ DESTROY }
destructor TAgg2D.Destroy;
begin
m_rbuf.Destruct;
m_allocator.Destruct;
m_scanline.Destruct;
m_rasterizer.Destruct;
m_fillGradient.Destruct;
m_lineGradient.Destruct;
m_imageFilterLut.Destruct;
m_path.Destruct;
m_convCurve.Destruct;
m_convStroke.Destruct;
m_fontEngine.Destruct;
m_fontCacheManager.Destruct;
{$IFDEF AGG2D_USE_WINFONTS }
ReleaseDC(0 ,m_fontDC );
{$ENDIF }
end;
{ ATTACH }
function TAgg2D.Attach(bitmap : TBitmap; flip_y : boolean = false ) : boolean;
var
buffer : pointer;
stride : integer;
begin
result:=false;
if Assigned(bitmap ) and
not bitmap.Empty then
case bitmap.PixelFormat of
pf24bit ,pf32bit :
begin
{ Rendering Buffer }
stride:=integer(bitmap.ScanLine[1 ] ) - integer(bitmap.ScanLine[0 ] );
if stride < 0 then
buffer:=bitmap.ScanLine[bitmap.Height - 1 ]
else
buffer:=bitmap.ScanLine[0 ];
if flip_y then
stride:=stride * -1;
m_rbuf.attach(
buffer ,
bitmap.Width ,
bitmap.Height ,
stride );
{ Pixel Format }
m_pixf:=bitmap.PixelFormat;
case m_pixf of
pf24bit :
begin
pixfmt_rgb24(m_pixFormat ,@m_rbuf );
pixfmt_rgb24(m_pixFormatPre ,@m_rbuf );
end;
pf32bit :
begin
pixfmt_rgba32 (m_pixFormat ,@m_rbuf );
pixfmt_custom_blend_rgba(m_pixFormatComp ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order );
pixfmt_rgba32 (m_pixFormatPre ,@m_rbuf );
pixfmt_custom_blend_rgba(m_pixFormatCompPre ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order );
end;
end;
{ Reset state }
m_renBase.reset_clipping (true );
m_renBaseComp.reset_clipping (true );
m_renBasePre.reset_clipping (true );
m_renBaseCompPre.reset_clipping(true );
ResetTransformations;
LineWidth(1.0 );
LineColor(0 ,0 ,0 );
FillColor(255 ,255 ,255 );
TextAlignment(AGG_AlignLeft ,AGG_AlignBottom );
ClipBox (0 ,0 ,bitmap.Width ,bitmap.Height );
LineCap (AGG_CapRound );
LineJoin(AGG_JoinRound );
FlipText(false );
ImageFilter (AGG_Bilinear );
ImageResample(AGG_NoResample );
ImageFlip (false );
m_masterAlpha :=1.0;
m_antiAliasGamma:=1.0;
m_rasterizer.gamma(@m_gammaNone );
m_blendMode:=AGG_BlendAlpha;
FillEvenOdd(false );
BlendMode (AGG_BlendAlpha );
FlipText(false );
ResetPath;
ImageFilter (AGG_Bilinear );
ImageResample(AGG_NoResample );
{ OK }
result:=true;
end;
end;
end;
{ CLIPBOX }
procedure TAgg2D.ClipBox(x1 ,y1 ,x2 ,y2 : double );
var
rx1 ,ry1 ,rx2 ,ry2 : int;
begin
m_clipBox.Construct(x1 ,y1 ,x2 ,y2 );
rx1:=Trunc(x1 );
ry1:=Trunc(y1 );
rx2:=Trunc(x2 );
ry2:=Trunc(y2 );
m_renBase.clip_box_ (rx1 ,ry1 ,rx2 ,ry2 );
m_renBaseComp.clip_box_ (rx1 ,ry1 ,rx2 ,ry2 );
m_renBasePre.clip_box_ (rx1 ,ry1 ,rx2 ,ry2 );
m_renBaseCompPre.clip_box_(rx1 ,ry1 ,rx2 ,ry2 );
m_rasterizer.clip_box(x1 ,y1 ,x2 ,y2 );
end;
{ CLIPBOX }
function TAgg2D.ClipBox : TAggRectD;
begin
result:=m_clipBox;
end;
{ CLEARALL }
procedure TAgg2D.ClearAll(c : TAggColor );
var
clr : aggclr;
begin
clr.Construct (c );
m_renBase.clear(@clr );
end;
{ CLEARALL }
procedure TAgg2D.ClearAll(r ,g ,b : byte; a : byte = 255 );
var
clr : TAggColor;
begin
clr.Construct(r ,g ,b ,a );
ClearAll (clr );
end;
{ CLEARCLIPBOX }
procedure TAgg2D.ClearClipBox(c : TAggColor );
var
clr : aggclr;
begin
clr.Construct(c );
m_renBase.copy_bar(0 ,0 ,m_renBase.width ,m_renBase.height ,@clr );
end;
{ CLEARCLIPBOX }
procedure TAgg2D.ClearClipBox(r ,g ,b : byte; a : byte = 255 );
var
clr : TAggColor;
begin
clr.Construct(r ,g ,b ,a );
ClearClipBox (clr );
end;
{ WORLDTOSCREEN }
procedure TAgg2D.WorldToScreen(x ,y : PDouble );
begin
m_transform.transform(@m_transform ,double_ptr(x ) ,double_ptr(y ) );
end;
{ SCREENTOWORLD }
procedure TAgg2D.ScreenToWorld(x ,y : PDouble );
begin
m_transform.inverse_transform(@m_transform ,double_ptr(x ) ,double_ptr(y ) );
end;
{ WORLDTOSCREEN }
function TAgg2D.WorldToScreen(scalar : double ) : double;
var
x1 ,y1 ,x2 ,y2 : double;
begin
x1:=0;
y1:=0;
x2:=scalar;
y2:=scalar;
WorldToScreen(@x1 ,@y1 );
WorldToScreen(@x2 ,@y2 );
result:=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) ) * 0.7071068;
end;
{ SCREENTOWORLD }
function TAgg2D.ScreenToWorld(scalar : double ) : double;
var
x1 ,y1 ,x2 ,y2 : double;
begin
x1:=0;
y1:=0;
x2:=scalar;
y2:=scalar;
ScreenToWorld(@x1 ,@y1 );
ScreenToWorld(@x2 ,@y2 );
result:=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) ) * 0.7071068;
end;
{ ALIGNPOINT }
procedure TAgg2D.AlignPoint(x ,y : PDouble );
begin
WorldToScreen(x ,y );
x^:=Floor(x^ ) + 0.5;
y^:=Floor(y^ ) + 0.5;
ScreenToWorld(x ,y );
end;
{ INBOX }
function TAgg2D.InBox(worldX ,worldY : double ) : boolean;
begin
WorldToScreen(@worldX ,@worldY );
result:=m_renBase.inbox(Trunc(worldX ) ,Trunc(worldY ) );
end;
{ BLENDMODE }
procedure TAgg2D.BlendMode(m : TAggBlendMode );
begin
m_blendMode:=m;
m_pixFormatComp.comp_op_ (unsigned(m ) );
m_pixFormatCompPre.comp_op_(unsigned(m ) );
end;
{ BLENDMODE }
function TAgg2D.BlendMode : TAggBlendMode;
begin
result:=m_blendMode;
end;
{ MASTERALPHA }
procedure TAgg2D.MasterAlpha(a : double );
begin
m_masterAlpha:=a;
UpdateRasterizerGamma;
end;
{ MASTERALPHA }
function TAgg2D.MasterAlpha : double;
begin
result:=m_masterAlpha;
end;
{ ANTIALIASGAMMA }
procedure TAgg2D.AntiAliasGamma(g : double );
begin
m_antiAliasGamma:=g;
UpdateRasterizerGamma;
end;
{ ANTIALIASGAMMA }
function TAgg2D.AntiAliasGamma : double;
begin
result:=m_antiAliasGamma;
end;
{ FILLCOLOR }
procedure TAgg2D.FillColor(c : TAggColor );
begin
m_fillColor :=c;
m_fillGradientFlag:=AGG_Solid;
end;
{ FILLCOLOR }
procedure TAgg2D.FillColor(r ,g ,b : byte; a : byte = 255 );
var
clr : TAggColor;
begin
clr.Construct(r ,g ,b ,a );
FillColor (clr );
end;
{ NOFILL }
procedure TAgg2D.NoFill;
var
clr : TAggColor;
begin
clr.Construct(0 ,0 ,0 ,0 );
FillColor (clr );
end;
{ LINECOLOR }
procedure TAgg2D.LineColor(c : TAggColor );
begin
m_lineColor :=c;
m_lineGradientFlag:=AGG_Solid;
end;
{ LINECOLOR }
procedure TAgg2D.LineColor(r ,g ,b : byte; a : byte = 255 );
var
clr : TAggColor;
begin
clr.Construct(r ,g ,b ,a );
LineColor (clr );
end;
{ NOLINE }
procedure TAgg2D.NoLine;
var
clr : TAggColor;
begin
clr.Construct(0 ,0 ,0 ,0 );
LineColor (clr );
end;
{ FILLCOLOR }
function TAgg2D.FillColor : TAggColor;
begin
result:=m_fillColor;
end;
{ LINECOLOR }
function TAgg2D.LineColor : TAggColor;
begin
result:=m_lineColor;
end;
{ FILLLINEARGRADIENT }
procedure TAgg2D.FillLinearGradient(x1 ,y1 ,x2 ,y2 : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
var
i ,startGradient ,endGradient : int;
k ,angle : double;
c : TAggColor;
clr : aggclr;
tar : trans_affine_rotation;
tat : trans_affine_translation;
begin
startGradient:=128 - Trunc(profile * 127.0 );
endGradient :=128 + Trunc(profile * 127.0 );
if endGradient <= startGradient then
endGradient:=startGradient + 1;
k:=1.0 / (endGradient - startGradient );
i:=0;
while i < startGradient do
begin
clr.Construct(c1 );
move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
while i < endGradient do
begin
c:=c1.gradient(c2 ,(i - startGradient ) * k );
clr.Construct(c );
move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
while i < 256 do
begin
clr.Construct(c2 );
move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
angle:=ArcTan2(y2 - y1 ,x2 - x1 );
m_fillGradientMatrix.reset;
tar.Construct(angle );
m_fillGradientMatrix.multiply(@tar );
tat.Construct(x1 ,y1 );
m_fillGradientMatrix.multiply(@tat );
m_fillGradientMatrix.multiply(@m_transform );
m_fillGradientMatrix.invert;
m_fillGradientD1 :=0.0;
m_fillGradientD2 :=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) );
m_fillGradientFlag:=AGG_Linear;
m_fillColor.Construct(0 ,0 ,0 ); // Set some real color
end;
{ LINELINEARGRADIENT }
procedure TAgg2D.LineLinearGradient(x1 ,y1 ,x2 ,y2 : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
var
i ,startGradient ,endGradient : int;
k ,angle : double;
c : TAggColor;
clr : aggclr;
tar : trans_affine_rotation;
tat : trans_affine_translation;
begin
startGradient:=128 - Trunc(profile * 128.0 );
endGradient :=128 + Trunc(profile * 128.0 );
if endGradient <= startGradient then
endGradient:=startGradient + 1;
k:=1.0 / (endGradient - startGradient );
i:=0;
while i < startGradient do
begin
clr.Construct(c1 );
move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
while i < endGradient do
begin
c:=c1.gradient(c2 ,(i - startGradient) * k );
clr.Construct(c );
move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
while i < 256 do
begin
clr.Construct(c2 );
move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
angle:=ArcTan2(y2 - y1 ,x2 - x1 );
m_lineGradientMatrix.reset;
tar.Construct(angle );
m_lineGradientMatrix.multiply(@tar );
tat.Construct(x1 ,y1 );
m_lineGradientMatrix.multiply(@tat );
m_lineGradientMatrix.multiply(@m_transform );
m_lineGradientMatrix.invert;
m_lineGradientD1 :=0.0;
m_lineGradientD2 :=Sqrt((x2 - x1 ) * (x2 - x1 ) + (y2 - y1 ) * (y2 - y1 ) );
m_lineGradientFlag:=AGG_Linear;
m_lineColor.Construct(0 ,0 ,0 ); // Set some real color
end;
{ FILLRADIALGRADIENT }
procedure TAgg2D.FillRadialGradient(x ,y ,r : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
var
i ,startGradient ,endGradient : int;
k : double;
c : TAggColor;
clr : aggclr;
tat : trans_affine_translation;
begin
startGradient:=128 - Trunc(profile * 127.0 );
endGradient :=128 + Trunc(profile * 127.0 );
if endGradient <= startGradient then
endGradient:=startGradient + 1;
k:=1.0 / (endGradient - startGradient );
i:=0;
while i < startGradient do
begin
clr.Construct(c1 );
move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
while i < endGradient do
begin
c:=c1.gradient(c2 ,(i - startGradient ) * k );
clr.Construct(c );
move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
while i < 256 do
begin
clr.Construct(c2 );
move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
m_fillGradientD2:=worldToScreen(r );
WorldToScreen(@x ,@y );
m_fillGradientMatrix.reset;
tat.Construct(x ,y );
m_fillGradientMatrix.multiply(@tat );
m_fillGradientMatrix.invert;
m_fillGradientD1 :=0;
m_fillGradientFlag:=AGG_Radial;
m_fillColor.Construct(0 ,0 ,0 ); // Set some real color
end;
{ LINERADIALGRADIENT }
procedure TAgg2D.LineRadialGradient(x ,y ,r : double; c1 ,c2 : TAggColor; profile : double = 1.0 );
var
i ,startGradient ,endGradient : int;
k : double;
c : TAggColor;
clr : aggclr;
tat : trans_affine_translation;
begin
startGradient:=128 - Trunc(profile * 128.0 );
endGradient :=128 + Trunc(profile * 128.0 );
if endGradient <= startGradient then
endGradient:=startGradient + 1;
k:=1.0 / (endGradient - startGradient );
i:=0;
while i < startGradient do
begin
clr.Construct(c1 );
move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
while i < endGradient do
begin
c:=c1.gradient(c2 ,(i - startGradient ) * k );
clr.Construct(c );
move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
while i < 256 do
begin
clr.Construct(c2 );
move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
m_lineGradientD2:=worldToScreen(r );
WorldToScreen(@x ,@y );
m_lineGradientMatrix.reset;
tat.Construct(x ,y );
m_lineGradientMatrix.multiply(@tat );
m_lineGradientMatrix.invert;
m_lineGradientD1 :=0;
m_lineGradientFlag:=AGG_Radial;
m_lineColor.Construct(0 ,0 ,0 ); // Set some real color
end;
{ FILLRADIALGRADIENT }
procedure TAgg2D.FillRadialGradient(x ,y ,r : double; c1 ,c2 ,c3 : TAggColor );
var
i : int;
c : TAggColor;
clr : aggclr;
tat : trans_affine_translation;
begin
i:=0;
while i < 128 do
begin
c:=c1.gradient(c2 ,i / 127.0 );
clr.Construct(c );
move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
while i < 256 do
begin
c:=c2.gradient(c3 ,(i - 128 ) / 127.0 );
clr.Construct(c );
move(clr ,m_fillGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
m_fillGradientD2:=worldToScreen(r );
WorldToScreen(@x ,@y );
m_fillGradientMatrix.reset;
tat.Construct(x ,y );
m_fillGradientMatrix.multiply(@tat );
m_fillGradientMatrix.invert;
m_fillGradientD1 :=0;
m_fillGradientFlag:=AGG_Radial;
m_fillColor.Construct(0 ,0 ,0 ); // Set some real color
end;
{ LINERADIALGRADIENT }
procedure TAgg2D.LineRadialGradient(x ,y ,r : double; c1 ,c2 ,c3 : TAggColor );
var
i : int;
c : TAggColor;
clr : aggclr;
tat : trans_affine_translation;
begin
i:=0;
while i < 128 do
begin
c:=c1.gradient(c2 ,i / 127.0 );
clr.Construct(c );
move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
while i < 256 do
begin
c:=c2.gradient(c3 ,(i - 128 ) / 127.0 );
clr.Construct(c );
move(clr ,m_lineGradient.array_operator(i )^ ,sizeof(aggclr ) );
inc (i );
end;
m_lineGradientD2:=worldToScreen(r );
WorldToScreen(@x ,@y );
m_lineGradientMatrix.reset;
tat.Construct(x ,y );
m_lineGradientMatrix.multiply(@tat );
m_lineGradientMatrix.invert;
m_lineGradientD1 :=0;
m_lineGradientFlag:=AGG_Radial;
m_lineColor.Construct(0 ,0 ,0 ); // Set some real color
end;
{ FILLRADIALGRADIENT }
procedure TAgg2D.FillRadialGradient(x ,y ,r : double );
var
tat : trans_affine_translation;
begin
m_fillGradientD2:=worldToScreen(r );
WorldToScreen(@x ,@y );
m_fillGradientMatrix.reset;
tat.Construct(x ,y );
m_fillGradientMatrix.multiply(@tat );
m_fillGradientMatrix.invert;
m_fillGradientD1:=0;
end;
{ LINERADIALGRADIENT }
procedure TAgg2D.LineRadialGradient(x ,y ,r : double );
var
tat : trans_affine_translation;
begin
m_lineGradientD2:=worldToScreen(r );
WorldToScreen(@x ,@y );
m_lineGradientMatrix.reset;
tat.Construct(x ,y );
m_lineGradientMatrix.multiply(@tat );
m_lineGradientMatrix.invert;
m_lineGradientD1:=0;
end;
{ LINEWIDTH }
procedure TAgg2D.LineWidth(w : double );
begin
m_lineWidth:=w;
m_convStroke.width_(w );
end;
{ LINEWIDTH }
function TAgg2D.LineWidth : double;
begin
result:=m_lineWidth;
end;
{ LINECAP }
procedure TAgg2D.LineCap(cap : TAggLineCap );
begin
m_lineCap:=cap;
m_convStroke.line_cap_(cap );
end;
{ LINECAP }
function TAgg2D.LineCap : TAggLineCap;
begin
result:=m_lineCap;
end;
{ LINEJOIN }
procedure TAgg2D.LineJoin(join : TAggLineJoin );
begin
m_lineJoin:=join;
m_convStroke.line_join_(join );
end;
{ LINEJOIN }
function TAgg2D.LineJoin : TAggLineJoin;
begin
result:=m_lineJoin;
end;
{ FILLEVENODD }
procedure TAgg2D.FillEvenOdd(evenOddFlag : boolean );
begin
m_evenOddFlag:=evenOddFlag;
if evenOddFlag then
m_rasterizer.filling_rule(fill_even_odd )
else
m_rasterizer.filling_rule(fill_non_zero );
end;
{ FILLEVENODD }
function TAgg2D.FillEvenOdd : boolean;
begin
result:=m_evenOddFlag;
end;
{ TRANSFORMATIONS }
function TAgg2D.Transformations : TAggTransformations;
begin
m_transform.store_to(@result.affineMatrix[0 ] );
end;
{ TRANSFORMATIONS }
procedure TAgg2D.Transformations(tr : PAggTransformations );
begin
m_transform.load_from(@tr.affineMatrix[0 ] );
m_convCurve.approximation_scale_ (worldToScreen(1.0 ) * g_approxScale );
m_convStroke.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
end;
{ RESETTRANSFORMATIONS }
procedure TAgg2D.ResetTransformations;
begin
m_transform.reset;
end;
{ AFFINE }
procedure TAgg2D.Affine(tr : PAggAffine );
begin
m_transform.multiply(tr );
m_convCurve.approximation_scale_ (WorldToScreen(1.0 ) * g_approxScale );
m_convStroke.approximation_scale_(WorldToScreen(1.0 ) * g_approxScale );
end;
{ AFFINE }
procedure TAgg2D.Affine(tr : PAggTransformations );
var
ta : trans_affine;
begin
ta.Construct(
tr.affineMatrix[0 ] ,tr.affineMatrix[1 ] ,tr.affineMatrix[2 ] ,
tr.affineMatrix[3 ] ,tr.affineMatrix[4 ] ,tr.affineMatrix[5 ] );
affine(PAggAffine(@ta ) );
end;
{ ROTATE }
procedure TAgg2D.Rotate(angle : double );
var
tar : trans_affine_rotation;
begin
tar.Construct(angle );
m_transform.multiply(@tar );
end;
{ SCALE }
procedure TAgg2D.Scale(sx ,sy : double );
var
tas : trans_affine_scaling;
begin
tas.Construct(sx ,sy );
m_transform.multiply(@tas );
m_convCurve.approximation_scale_ (worldToScreen(1.0 ) * g_approxScale );
m_convStroke.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
end;
{ SKEW }
procedure TAgg2D.Skew(sx ,sy : double );
var
tas : trans_affine_skewing;
begin
tas.Construct(sx ,sy );
m_transform.multiply(@tas );
end;
{ TRANSLATE }
procedure TAgg2D.Translate(x ,y : double );
var
tat : trans_affine_translation;
begin
tat.Construct(x ,y );
m_transform.multiply(@tat );
end;
{ PARALLELOGRAM }
procedure TAgg2D.Parallelogram(x1 ,y1 ,x2 ,y2 : double; para : PDouble );
var
ta : trans_affine;
begin
ta.Construct(x1 ,y1 ,x2 ,y2 ,parallelo_ptr(para ) );
m_transform.multiply(@ta );
m_convCurve.approximation_scale_ (worldToScreen(1.0 ) * g_approxScale );
m_convStroke.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
end;
{ VIEWPORT }
procedure TAgg2D.Viewport(
worldX1 ,worldY1 ,worldX2 ,worldY2 ,
screenX1 ,screenY1 ,screenX2 ,screenY2 : double;
opt : TAggViewportOption = AGG_XMidYMid );
var
vp : trans_viewport;
mx : trans_affine;
begin
vp.Construct;
case opt of
AGG_Anisotropic :
vp.preserve_aspect_ratio(0.0 ,0.0 ,aspect_ratio_stretch );
AGG_XMinYMin :
vp.preserve_aspect_ratio(0.0 ,0.0 ,aspect_ratio_meet );
AGG_XMidYMin :
vp.preserve_aspect_ratio(0.5 ,0.0 ,aspect_ratio_meet );
AGG_XMaxYMin :
vp.preserve_aspect_ratio(1.0 ,0.0 ,aspect_ratio_meet );
AGG_XMinYMid :
vp.preserve_aspect_ratio(0.0 ,0.5 ,aspect_ratio_meet );
AGG_XMidYMid :
vp.preserve_aspect_ratio(0.5 ,0.5 ,aspect_ratio_meet );
AGG_XMaxYMid :
vp.preserve_aspect_ratio(1.0 ,0.5 ,aspect_ratio_meet );
AGG_XMinYMax :
vp.preserve_aspect_ratio(0.0 ,1.0 ,aspect_ratio_meet );
AGG_XMidYMax :
vp.preserve_aspect_ratio(0.5 ,1.0 ,aspect_ratio_meet );
AGG_XMaxYMax :
vp.preserve_aspect_ratio(1.0 ,1.0 ,aspect_ratio_meet );
end;
vp.world_viewport (worldX1 ,worldY1 ,worldX2 ,worldY2 );
vp.device_viewport(screenX1 ,screenY1 ,screenX2 ,screenY2 );
mx.Construct;
vp.to_affine (@mx );
m_transform.multiply(@mx );
m_convCurve.approximation_scale_ (WorldToScreen(1.0 ) * g_approxScale );
m_convStroke.approximation_scale_(WorldToScreen(1.0 ) * g_approxScale );
end;
{ LINE }
procedure TAgg2D.Line(x1 ,y1 ,x2 ,y2 : double );
begin
m_path.remove_all;
addLine (x1 ,y1 ,x2 ,y2 );
DrawPath(AGG_StrokeOnly );
end;
{ TRIANGLE }
procedure TAgg2D.Triangle(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double );
begin
m_path.remove_all;
m_path.move_to(x1 ,y1 );
m_path.line_to(x2 ,y2 );
m_path.line_to(x3 ,y3 );
m_path.close_polygon;
DrawPath(AGG_FillAndStroke );
end;
{ RECTANGLE }
procedure TAgg2D.Rectangle(x1 ,y1 ,x2 ,y2 : double );
begin
m_path.remove_all;
m_path.move_to(x1 ,y1 );
m_path.line_to(x2 ,y1 );
m_path.line_to(x2 ,y2 );
m_path.line_to(x1 ,y2 );
m_path.close_polygon;
DrawPath(AGG_FillAndStroke );
end;
{ ROUNDEDRECT }
procedure TAgg2D.RoundedRect(x1 ,y1 ,x2 ,y2 ,r : double );
var
rc : rounded_rect;
begin
m_path.remove_all;
rc.Construct(x1 ,y1 ,x2 ,y2 ,r );
rc.normalize_radius;
rc.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
m_path.add_path(@rc ,0 ,false );
DrawPath(AGG_FillAndStroke );
end;
{ ROUNDEDRECT }
procedure TAgg2D.RoundedRect(x1 ,y1 ,x2 ,y2 ,rx ,ry : double );
var
rc : rounded_rect;
begin
m_path.remove_all;
rc.Construct;
rc.rect (x1 ,y1 ,x2 ,y2 );
rc.radius(rx ,ry );
rc.normalize_radius;
m_path.add_path(@rc ,0 ,false );
DrawPath(AGG_FillAndStroke );
end;
{ ROUNDEDRECT }
procedure TAgg2D.RoundedRect(
x1 ,y1 ,x2 ,y2 ,
rxBottom ,ryBottom ,
rxTop ,ryTop : double );
var
rc : rounded_rect;
begin
m_path.remove_all;
rc.Construct;
rc.rect (x1 ,y1 ,x2 ,y2 );
rc.radius(rxBottom ,ryBottom ,rxTop ,ryTop );
rc.normalize_radius;
rc.approximation_scale_(worldToScreen(1.0 ) * g_approxScale );
m_path.add_path(@rc ,0 ,false );
DrawPath(AGG_FillAndStroke );
end;
{ ELLIPSE }
procedure TAgg2D.Ellipse(cx ,cy ,rx ,ry : double );
var
el : bezier_arc;
begin
m_path.remove_all;
el.Construct(cx ,cy ,rx ,ry ,0 ,2 * pi );
m_path.add_path(@el ,0 ,false );
m_path.close_polygon;
DrawPath(AGG_FillAndStroke );
end;
{ ARC }
procedure TAgg2D.Arc(cx ,cy ,rx ,ry ,start ,sweep : double );
var
ar : {bezier_}agg_arc.arc;
begin
m_path.remove_all;
ar.Construct(cx ,cy ,rx ,ry ,sweep ,start ,false );
m_path.add_path(@ar ,0 ,false );
DrawPath(AGG_StrokeOnly );
end;
{ STAR }
procedure TAgg2D.Star(cx ,cy ,r1 ,r2 ,startAngle : double; numRays : integer );
var
da ,a ,x ,y : double;
i : int;
begin
m_path.remove_all;
da:=pi / numRays;
a :=startAngle;
i:=0;
while i < numRays do
begin
x:=Cos(a ) * r2 + cx;
y:=Sin(a ) * r2 + cy;
if i <> 0 then
m_path.line_to(x ,y )
else
m_path.move_to(x ,y );
a:=a + da;
m_path.line_to(Cos(a ) * r1 + cx ,Sin(a ) * r1 + cy );
a:=a + da;
inc(i );
end;
ClosePolygon;
DrawPath(AGG_FillAndStroke );
end;
{ CURVE }
procedure TAgg2D.Curve(x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double );
begin
m_path.remove_all;
m_path.move_to(x1 ,y1 );
m_path.curve3 (x2 ,y2 ,x3 ,y3 );
DrawPath(AGG_StrokeOnly );
end;
{ CURVE }
procedure TAgg2D.Curve(x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,x4 ,y4 : double );
begin
m_path.remove_all;
m_path.move_to(x1 ,y1 );
m_path.curve4 (x2 ,y2 ,x3 ,y3 ,x4 ,y4 );
DrawPath(AGG_StrokeOnly );
end;
{ POLYGON }
procedure TAgg2D.Polygon(xy : PDouble; numPoints : integer );
begin
m_path.remove_all;
m_path.add_poly(double_2_ptr(xy ) ,numPoints );
ClosePolygon;
DrawPath(AGG_FillAndStroke );
end;
{ POLYLINE }
procedure TAgg2D.Polyline(xy : PDouble; numPoints : integer );
begin
m_path.remove_all;
m_path.add_poly(double_2_ptr(xy ) ,numPoints );
DrawPath(AGG_StrokeOnly );
end;
{ FLIPTEXT }
procedure TAgg2D.FlipText(flip : boolean );
begin
m_fontEngine.flip_y_(not flip );
end;
{ FONT }
procedure TAgg2D.Font(
fileName : AnsiString; height : double;
bold : boolean = false;
italic : boolean = false;
cache : TAggFontCacheType = AGG_VectorFontCache;
angle : double = 0.0 );
var
b : int;
begin
m_textAngle :=angle;
m_fontHeight :=height;
m_fontCacheType:=cache;
{$IFDEF AGG2D_USE_FREETYPE }
if cache = AGG_VectorFontCache then
m_fontEngine.load_font(PChar(@fileName[1 ] ) ,0 ,glyph_ren_outline )
else
m_fontEngine.load_font(PChar(@fileName[1 ] ) ,0 ,glyph_ren_agg_gray8 );
m_fontEngine.hinting_(m_textHints );
if cahce = AGG_VectorFontCache then
m_fontEngine.height_(height )
else
m_fontEngine.height_(worldToScreen(height ) );
{$ENDIF }
{$IFDEF AGG2D_USE_WINFONTS}
m_fontEngine.hinting_(m_textHints );
if bold then
b:=700
else
b:=400;
if cache = AGG_VectorFontCache then
m_fontEngine.create_font_(PChar(@fileName[1 ] ) ,glyph_ren_outline ,height ,0.0 ,b ,italic )
else
m_fontEngine.create_font_(PChar(@fileName[1 ] ) ,glyph_ren_agg_gray8 ,worldToScreen(height) ,0.0 ,b ,italic );
{$ENDIF }
end;
{ FONTHEIGHT }
function TAgg2D.FontHeight : double;
begin
result:=m_fontHeight;
end;
{ TEXTALIGNMENT }
procedure TAgg2D.TextAlignment(alignX ,alignY : TAggTextAlignment );
begin
m_textAlignX:=alignX;
m_textAlignY:=alignY;
end;
{ TEXTHINTS }
function TAgg2D.TextHints : boolean;
begin
result:=m_textHints;
end;
{ TEXTHINTS }
procedure TAgg2D.TextHints(hints : boolean );
begin
m_textHints:=hints;
end;
{ TEXTWIDTH }
function TAgg2D.TextWidth(str : AnsiString ) : double;
var
x ,y : double;
first : boolean;
glyph : glyph_cache_ptr;
str_ : PChar;
begin
x:=0;
y:=0;
first:=true;
str_ :=@str[1 ];
while str_^ <> #0 do
begin
glyph:=m_fontCacheManager.glyph(int32u(str_^ ) );
if glyph <> NIL then
begin
if not first then
m_fontCacheManager.add_kerning(@x ,@y );
x:=x + glyph.advance_x;
y:=y + glyph.advance_y;
first:=false;
end;
inc(ptrcomp(str_ ) );
end;
if m_fontCacheType = AGG_VectorFontCache then
result:=x
else
result:=ScreenToWorld(x );
end;
{ TEXT }
procedure TAgg2D.Text(
x ,y : double; str : AnsiString;
roundOff : boolean = false;
ddx : double = 0.0;
ddy : double = 0.0 );
var
dx ,dy ,asc ,start_x ,start_y : double;
glyph : glyph_cache_ptr;
mtx : trans_affine;
str_ : PChar;
i : int;
tat : trans_affine_translation;
tar : trans_affine_rotation;
tr : conv_transform;
begin
dx:=0.0;
dy:=0.0;
case m_textAlignX of
AGG_AlignCenter :
dx:=-textWidth(str ) * 0.5;
AGG_AlignRight :
dx:=-textWidth(str );
end;
asc :=fontHeight;
glyph:=m_fontCacheManager.glyph(int32u('H' ) );
if glyph <> NIL then
asc:=glyph.bounds.y2 - glyph.bounds.y1;
if m_fontCacheType = AGG_RasterFontCache then
asc:=screenToWorld(asc );
case m_textAlignY of
AGG_AlignCenter :
dy:=-asc * 0.5;
AGG_AlignTop :
dy:=-asc;
end;
if m_fontEngine._flip_y then
dy:=-dy;
mtx.Construct;
start_x:=x + dx;
start_y:=y + dy;
if roundOff then
begin
start_x:=Trunc(start_x );
start_y:=Trunc(start_y );
end;
start_x:=start_x + ddx;
start_y:=start_y + ddy;
tat.Construct(-x ,-y );
mtx.multiply (@tat );
tar.Construct(m_textAngle );
mtx.multiply (@tar );
tat.Construct(x ,y );
mtx.multiply (@tat );
tr.Construct(m_fontCacheManager.path_adaptor ,@mtx );
if m_fontCacheType = AGG_RasterFontCache then
WorldToScreen(@start_x ,@start_y );
i:=0;
str_:=@str[1 ];
while char_ptr(ptrcomp(str_ ) + i * sizeof(char ) )^ <> #0 do
begin
glyph:=m_fontCacheManager.glyph(int32u(char_ptr(ptrcomp(str_ ) + i * sizeof(char ) )^ ) );
if glyph <> NIL then
begin
if i <> 0 then
m_fontCacheManager.add_kerning(@x ,@y );
m_fontCacheManager.init_embedded_adaptors(glyph ,start_x ,start_y );
if glyph.data_type = glyph_data_outline then
begin
m_path.remove_all;
m_path.add_path(@tr ,0 ,false );
drawPath;
end;
if glyph.data_type = glyph_data_gray8 then
begin
render(
m_fontCacheManager.gray8_adaptor ,
m_fontCacheManager.gray8_scanline );
end;
start_x:=start_x + glyph.advance_x;
start_y:=start_y + glyph.advance_y;
end;
inc(i );
end;
end;
{ RESETPATH }
procedure TAgg2D.ResetPath;
begin
m_path.remove_all;
m_path.move_to(0 ,0 );
end;
{ MOVETO }
procedure TAgg2D.MoveTo(x ,y : double );
begin
m_path.move_to(x ,y );
end;
{ MOVEREL }
procedure TAgg2D.MoveRel(dx ,dy : double );
begin
m_path.move_rel(dx ,dy );
end;
{ LINETO }
procedure TAgg2D.LineTo(x ,y : double );
begin
m_path.line_to(x ,y );
end;
{ LINEREL }
procedure TAgg2D.LineRel(dx ,dy : double );
begin
m_path.line_rel(dx ,dy );
end;
{ HORLINETO }
procedure TAgg2D.HorLineTo(x : double );
begin
m_path.hline_to(x );
end;
{ HORLINEREL }
procedure TAgg2D.HorLineRel(dx : double );
begin
m_path.hline_rel(dx );
end;
{ VERLINETO }
procedure TAgg2D.VerLineTo(y : double );
begin
m_path.vline_to(y );
end;
{ VERLINEREL }
procedure TAgg2D.VerLineRel(dy : double );
begin
m_path.vline_rel(dy );
end;
{ ARCTO }
procedure TAgg2D.ArcTo(
rx ,ry ,angle : double;
largeArcFlag ,sweepFlag : boolean;
x ,y : double );
begin
m_path.arc_to(rx ,ry ,angle ,largeArcFlag ,sweepFlag ,x ,y );
end;
{ ARCREL }
procedure TAgg2D.ArcRel(
rx ,ry ,angle : double;
largeArcFlag ,sweepFlag : boolean;
dx ,dy : double );
begin
m_path.arc_rel(rx ,ry ,angle ,largeArcFlag ,sweepFlag ,dx ,dy );
end;
{ QUADRICCURVETO }
procedure TAgg2D.QuadricCurveTo (xCtrl ,yCtrl ,xTo ,yTo : double );
begin
m_path.curve3(xCtrl ,yCtrl ,xTo ,yTo );
end;
{ QUADRICCURVEREL }
procedure TAgg2D.QuadricCurveRel(dxCtrl ,dyCtrl ,dxTo ,dyTo : double );
begin
m_path.curve3_rel(dxCtrl ,dyCtrl ,dxTo ,dyTo );
end;
{ QUADRICCURVETO }
procedure TAgg2D.QuadricCurveTo (xTo ,yTo : double );
begin
m_path.curve3(xTo ,yTo );
end;
{ QUADRICCURVEREL }
procedure TAgg2D.QuadricCurveRel(dxTo ,dyTo : double );
begin
m_path.curve3_rel(dxTo ,dyTo );
end;
{ CUBICCURVETO }
procedure TAgg2D.CubicCurveTo (xCtrl1 ,yCtrl1 ,xCtrl2 ,yCtrl2 ,xTo ,yTo : double );
begin
m_path.curve4(xCtrl1 ,yCtrl1 ,xCtrl2 ,yCtrl2 ,xTo ,yTo );
end;
{ CUBICCURVEREL }
procedure TAgg2D.CubicCurveRel(dxCtrl1 ,dyCtrl1 ,dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo : double );
begin
m_path.curve4_rel(dxCtrl1 ,dyCtrl1 ,dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo );
end;
{ CUBICCURVETO }
procedure TAgg2D.CubicCurveTo (xCtrl2 ,yCtrl2 ,xTo ,yTo : double );
begin
m_path.curve4(xCtrl2 ,yCtrl2 ,xTo ,yTo );
end;
{ CUBICCURVEREL }
procedure TAgg2D.CubicCurveRel(dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo : double );
begin
m_path.curve4_rel(dxCtrl2 ,dyCtrl2 ,dxTo ,dyTo );
end;
{ ADDELLIPSE }
procedure TAgg2D.AddEllipse(cx ,cy ,rx ,ry : double; dir : TAggDirection );
var
ar : bezier_arc;
begin
if dir = AGG_CCW then
ar.Construct(cx ,cy ,rx ,ry ,0 ,2 * pi )
else
ar.Construct(cx ,cy ,rx ,ry ,0 ,-2 * pi );
m_path.add_path(@ar ,0 ,false );
m_path.close_polygon;
end;
{ CLOSEPOLYGON }
procedure TAgg2D.ClosePolygon;
begin
m_path.close_polygon;
end;
{ DRAWPATH }
procedure TAgg2D.DrawPath(flag : TAggDrawPathFlag = AGG_FillAndStroke );
begin
m_rasterizer.reset;
case flag of
AGG_FillOnly :
if m_fillColor.a <> 0 then
begin
m_rasterizer.add_path(@m_pathTransform );
render(true );
end;
AGG_StrokeOnly :
if (m_lineColor.a <> 0 ) and
(m_lineWidth > 0.0 ) then
begin
m_rasterizer.add_path(@m_strokeTransform );
render(false );
end;
AGG_FillAndStroke :
begin
if m_fillColor.a <> 0 then
begin
m_rasterizer.add_path(@m_pathTransform );
render(true );
end;
if (m_lineColor.a <> 0 ) and
(m_lineWidth > 0.0 ) then
begin
m_rasterizer.add_path(@m_strokeTransform );
render(false );
end;
end;
AGG_FillWithLineColor :
if m_lineColor.a <> 0 then
begin
m_rasterizer.add_path(@m_pathTransform );
render(false );
end;
end;
end;
{ IMAGEFILTER }
procedure TAgg2D.ImageFilter(f : TAggImageFilter );
begin
m_imageFilter:=f;
case f of
AGG_Bilinear :
m_imageFilterLut.calculate(@m_ifBilinear ,true );
AGG_Hanning :
m_imageFilterLut.calculate(@m_ifHanning ,true );
AGG_Hermite :
m_imageFilterLut.calculate(@m_ifHermite ,true );
AGG_Quadric :
m_imageFilterLut.calculate(@m_ifQuadric ,true );
AGG_Bicubic :
m_imageFilterLut.calculate(@m_ifBicubic ,true );
AGG_Catrom :
m_imageFilterLut.calculate(@m_ifCatrom ,true );
AGG_Spline16 :
m_imageFilterLut.calculate(@m_ifSpline16 ,true );
AGG_Spline36 :
m_imageFilterLut.calculate(@m_ifSpline36 ,true );
AGG_Blackman144 :
m_imageFilterLut.calculate(@m_ifBlackman144 ,true );
end;
end;
{ IMAGEFILTER }
function TAgg2D.ImageFilter : TAggImageFilter;
begin
result:=m_imageFilter;
end;
{ IMAGERESAMPLE }
procedure TAgg2D.ImageResample(f : TAggImageResample );
begin
m_imageResample:=f;
end;
{ IMAGEFLIP }
procedure TAgg2D.ImageFlip(f : boolean );
begin
m_imageFlip:=f;
end;
{ IMAGERESAMPLE }
function TAgg2D.ImageResample : TAggImageResample;
begin
result:=m_imageResample;
end;
{ TRANSFORMIMAGE }
procedure TAgg2D.TransformImage(
bitmap : TBitmap;
imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
var
parall : array[0..5 ] of double;
image : TAggImage;
begin
image.Construct;
if image.attach(bitmap ,m_imageFlip ) then
begin
resetPath;
moveTo(dstX1 ,dstY1 );
lineTo(dstX2 ,dstY1 );
lineTo(dstX2 ,dstY2 );
lineTo(dstX1 ,dstY2 );
closePolygon;
parall[0 ]:=dstX1;
parall[1 ]:=dstY1;
parall[2 ]:=dstX2;
parall[3 ]:=dstY1;
parall[4 ]:=dstX2;
parall[5 ]:=dstY2;
renderImage(@image ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,@parall[0 ] );
image.Destruct;
end;
end;
{ TRANSFORMIMAGE }
procedure TAgg2D.TransformImage(
bitmap : TBitmap;
dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
var
parall : array[0..5 ] of double;
image : TAggImage;
begin
image.Construct;
if image.attach(bitmap ,m_imageFlip ) then
begin
ResetPath;
MoveTo(dstX1 ,dstY1 );
LineTo(dstX2 ,dstY1 );
LineTo(dstX2 ,dstY2 );
LineTo(dstX1 ,dstY2 );
ClosePolygon;
parall[0 ]:=dstX1;
parall[1 ]:=dstY1;
parall[2 ]:=dstX2;
parall[3 ]:=dstY1;
parall[4 ]:=dstX2;
parall[5 ]:=dstY2;
renderImage(@image ,0 ,0 ,image.renBuf._width ,image.renBuf._height ,@parall[0 ] );
image.Destruct;
end;
end;
{ TRANSFORMIMAGE }
procedure TAgg2D.TransformImage(
bitmap : TBitmap;
imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
parallelo : PDouble );
var
image : TAggImage;
begin
image.Construct;
if image.attach(bitmap ,m_imageFlip ) then
begin
ResetPath;
MoveTo(
PDouble(ptrcomp(parallelo ) + 0 * sizeof(double ) )^ ,
PDouble(ptrcomp(parallelo ) + 1 * sizeof(double ) )^ );
LineTo(
PDouble(ptrcomp(parallelo ) + 2 * sizeof(double ) )^ ,
PDouble(ptrcomp(parallelo ) + 3 * sizeof(double ) )^ );
LineTo(
PDouble(ptrcomp(parallelo ) + 4 * sizeof(double ) )^ ,
PDouble(ptrcomp(parallelo ) + 5 * sizeof(double ) )^ );
LineTo(
PDouble(ptrcomp(parallelo ) + 0 * sizeof(double ) )^ +
PDouble(ptrcomp(parallelo ) + 4 * sizeof(double ) )^ -
PDouble(ptrcomp(parallelo ) + 2 * sizeof(double ) )^ ,
PDouble(ptrcomp(parallelo ) + 1 * sizeof(double ) )^ +
PDouble(ptrcomp(parallelo ) + 5 * sizeof(double ) )^ -
PDouble(ptrcomp(parallelo ) + 3 * sizeof(double ) )^ );
ClosePolygon;
renderImage(@image ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,parallelo );
image.Destruct;
end;
end;
{ TRANSFORMIMAGE }
procedure TAgg2D.TransformImage(bitmap : TBitmap; parallelo : PDouble );
var
image : TAggImage;
begin
image.Construct;
if image.attach(bitmap ,m_imageFlip ) then
begin
ResetPath;
MoveTo(
PDouble(ptrcomp(parallelo ) + 0 * sizeof(double ) )^ ,
PDouble(ptrcomp(parallelo ) + 1 * sizeof(double ) )^ );
LineTo(
PDouble(ptrcomp(parallelo ) + 2 * sizeof(double ) )^ ,
PDouble(ptrcomp(parallelo ) + 3 * sizeof(double ) )^ );
LineTo(
PDouble(ptrcomp(parallelo ) + 4 * sizeof(double ) )^ ,
PDouble(ptrcomp(parallelo ) + 5 * sizeof(double ) )^ );
LineTo(
PDouble(ptrcomp(parallelo ) + 0 * sizeof(double ) )^ +
PDouble(ptrcomp(parallelo ) + 4 * sizeof(double ) )^ -
PDouble(ptrcomp(parallelo ) + 2 * sizeof(double ) )^ ,
PDouble(ptrcomp(parallelo ) + 1 * sizeof(double ) )^ +
PDouble(ptrcomp(parallelo ) + 5 * sizeof(double ) )^ -
PDouble(ptrcomp(parallelo ) + 3 * sizeof(double ) )^ );
ClosePolygon;
renderImage(@image ,0 ,0 ,image.renBuf._width ,image.renBuf._height ,parallelo );
image.Destruct;
end;
end;
{ TRANSFORMIMAGEPATH }
procedure TAgg2D.TransformImagePath(
bitmap : TBitmap;
imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
var
parall : array[0..5 ] of double;
image : TAggImage;
begin
image.Construct;
if image.attach(bitmap ,m_imageFlip ) then
begin
parall[0 ]:=dstX1;
parall[1 ]:=dstY1;
parall[2 ]:=dstX2;
parall[3 ]:=dstY1;
parall[4 ]:=dstX2;
parall[5 ]:=dstY2;
renderImage(@image ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,@parall[0 ] );
image.Destruct;
end;
end;
{ TRANSFORMIMAGEPATH }
procedure TAgg2D.TransformImagePath(
bitmap : TBitmap;
dstX1 ,dstY1 ,dstX2 ,dstY2 : double );
var
parall : array[0..5 ] of double;
image : TAggImage;
begin
image.Construct;
if image.attach(bitmap ,m_imageFlip ) then
begin
parall[0 ]:=dstX1;
parall[1 ]:=dstY1;
parall[2 ]:=dstX2;
parall[3 ]:=dstY1;
parall[4 ]:=dstX2;
parall[5 ]:=dstY2;
renderImage(@image ,0 ,0 ,image.renBuf._width ,image.renBuf._height ,@parall[0 ] );
image.Destruct;
end;
end;
{ TRANSFORMIMAGEPATH }
procedure TAgg2D.TransformImagePath(
bitmap : TBitmap;
imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
parallelo : PDouble );
var
image : TAggImage;
begin
image.Construct;
if image.attach(bitmap ,m_imageFlip ) then
begin
renderImage(@image ,imgX1 ,imgY1 ,imgX2 ,imgY2 ,parallelo );
image.Destruct;
end;
end;
{ TRANSFORMIMAGEPATH }
procedure TAgg2D.TransformImagePath(bitmap : TBitmap; parallelo : PDouble );
var
image : TAggImage;
begin
image.Construct;
if image.attach(bitmap ,m_imageFlip ) then
begin
renderImage(@image ,0 ,0 ,image.renBuf._width ,image.renBuf._height ,parallelo );
image.Destruct;
end;
end;
{ COPYIMAGE }
procedure TAgg2D.CopyImage(
bitmap : TBitmap;
imgX1 ,imgY1 ,imgX2 ,imgY2 : integer;
dstX ,dstY : double );
var
r : agg_basics.rect;
image : TAggImage;
begin
image.Construct;
if image.attach(bitmap ,m_imageFlip ) then
begin
WorldToScreen(@dstX ,@dstY );
r.Construct (imgX1 ,imgY1 ,imgX2 ,imgY2 );
m_renBase.copy_from(@image.renBuf ,@r ,Trunc(dstX ) - imgX1 ,Trunc(dstY ) - imgY1 );
image.Destruct;
end;
end;
{ COPYIMAGE }
procedure TAgg2D.CopyImage(bitmap : TBitmap; dstX ,dstY : double );
var
image : TAggImage;
begin
image.Construct;
if image.attach(bitmap ,m_imageFlip ) then
begin
WorldToScreen(@dstX ,@dstY );
m_renBase.copy_from(@image.renBuf ,NIL ,Trunc(dstX ) ,Trunc(dstY ) );
image.Destruct;
end;
end;
{ RENDER }
procedure TAgg2D.render(fillColor_ : boolean );
begin
if (m_blendMode = AGG_BlendAlpha ) or
(m_pixf = pf24bit ) then
Agg2DRenderer_render(self ,@m_renBase ,@m_renSolid ,fillColor_ )
else
Agg2DRenderer_render(self ,@m_renBaseComp ,@m_renSolidComp ,fillColor_ );
end;
{ RENDER }
procedure TAgg2D.render(ras : PAggFontRasterizer; sl : PAggFontScanline );
begin
if (m_blendMode = AGG_BlendAlpha ) or
(m_pixf = pf24bit ) then
Agg2DRenderer_render(self ,@m_renBase ,@m_renSolid ,ras ,sl )
else
Agg2DRenderer_render(self ,@m_renBaseComp ,@m_renSolidComp ,ras ,sl );
end;
{ ADDLINE }
procedure TAgg2D.addLine(x1 ,y1 ,x2 ,y2 : double );
begin
m_path.move_to(x1 ,y1 );
m_path.line_to(x2 ,y2 );
end;
{ UPDATERASTERIZERGAMMA }
procedure TAgg2D.updateRasterizerGamma;
begin
m_gammaAgg2D.Construct(m_masterAlpha ,m_antiAliasGamma );
m_rasterizer.gamma (@m_gammaAgg2D );
end;
{ RENDERIMAGE }
procedure TAgg2D.renderImage(
img : PAggImage;
x1 ,y1 ,x2 ,y2 : integer;
parl : PDouble );
var
mtx : trans_affine;
interpolator : span_interpolator_linear;
begin
mtx.Construct(x1 ,y1 ,x2 ,y2 ,parallelo_ptr(parl ) );
mtx.multiply (@m_transform );
mtx.invert;
m_rasterizer.reset;
m_rasterizer.add_path(@m_pathTransform );
interpolator.Construct(@mtx );
if (m_blendMode = AGG_BlendAlpha ) or
(m_pixf = pf24bit ) then
Agg2DRenderer_renderImage(self ,img ,@m_renBasePre ,@interpolator )
else
Agg2DRenderer_renderImage(self ,img ,@m_renBaseCompPre ,@interpolator );
end;
{ BITMAPALPHATRANSPARENCY }
function BitmapAlphaTransparency(bitmap : TBitmap; alpha : byte ) : boolean;
var
fcx ,fcy : integer;
transp : ^byte;
begin
result:=false;
if Assigned(bitmap ) and
not bitmap.Empty and
(bitmap.PixelFormat = pf32bit ) then
begin
for fcy:=0 to bitmap.Height - 1 do
begin
transp:=pointer(ptrcomp(bitmap.ScanLine[fcy ] ) + 3 );
for fcx:=0 to bitmap.Width - 1 do
begin
transp^:=alpha;
inc(ptrcomp(transp ) ,4 );
end;
end;
{ OK }
result:=true;
end;
end;
END.
{*}
{!}{ To look At }