2017-07-26 78 views
1

我想转换一个delphi XE4应用程序来使用Graphics32库进行绘制而不是使用标准的delphi绘图方法。Graphics32用阴影图案填充多边形

我做的一件事就是绘制一个图标,其中包含一个带对角十字形图案的小椭圆。图标应该是这样的:

enter image description here

这里是我如何做到这一点与标准TCanvas绘制方法:

ACanvas.Brush.Color := shape.pcolor; 
ACanvas.Brush.Style := bsdiagCross; 
ACanvas.Ellipse(-13, -9, 13, 9); 

我可以绘制Graphics32做以下的椭圆:

var  
    Polygon : TArrayOfFloatPoint; 
begin  
    Polygon := Ellipse(0, 0, 13, 9); 
    PolylineFS(Bitmap, Polygon, pcolor, True, UAVPenWidth); 

但有没有一种简单的方法来复制对角线交叉阴影图案?我假设我可以使用TBitmapPolygonFiller类,但是这是使用位图填充的。请注意,如果这个图是相关的,那么这张图就是OnPaint事件处理程序中的TPositionedLayer

回答

2

到目前为止,Graphics32中没有直接的模式支持,但有很多方法可以创建像您想要使用的模式。

下面是一个使用样本多边形填充一个解决办法:

首先,你需要编写一个采样器类的孵化模式。有几种方法可以构建这样的采样器。下面你可以找到一个很简单的一个:

type 
    THatchedPatternSampler = class(TCustomSampler) 
    public 
    function GetSampleInt(X, Y: Integer): TColor32; override; 
    end; 

function THatchedPatternSampler.GetSampleInt(X, Y: Integer): TColor32; 
begin 
    Result := 0; 
    if ((X - Y) mod 8 = 0) or ((X + Y) mod 8 = 0) then 
    Result := clRed32 
end; 

你只需要重写这里(GetSampleInt)一个方法,所有其他方法可以从父类中使用。

现在它变得有点卷积。为了使用示例,您必须使用它的TSamplerFiller的顶部是这样的:

Sampler := THatchedPatternSampler.Create; 
Filler := TSamplerFiller.Create(Sampler); 

一旦你有这样的填料可以在PolygonFS甚至PolylineFS使用它。

最后的代码可能是这样的:

var 
    Polygon: TArrayOfFloatPoint; 
    Sampler: THatchedPatternSampler; 
    Filler: TSamplerFiller; 
begin 
    Polygon := Ellipse(128, 128, 120, 100); 
    Sampler := THatchedPatternSampler.Create; 
    try 
    Filler := TSamplerFiller.Create(Sampler); 
    try 
     PolygonFS(PaintBox32.Buffer, Polygon, Filler); 
    finally 
     Filler.Free; 
    end; 
     finally 
    Sampler.Free; 
    end; 

    PolylineFS(PaintBox32.Buffer, Polygon, clRed32, True, 1); 
end; 

这将引起相当大的椭圆形成位图(这里:一个TPaintBox32实例的缓冲区)的中心,以孵化采样代码填充。最后,使用PolylineFS函数绘制出实体轮廓。

从性能角度来看,这并不是GetSampleInt每像素调用的最快方法。但是,最容易理解发生了什么。

对于更快的选择,您应该直接直接使用填充物。您可以直接从TCustomPolygonFiller这样得出:

type 
    THatchedPatternFiller = class(TCustomPolygonFiller) 
    private 
    procedure FillLine(Dst: PColor32; DstX, DstY, Length: Integer; AlphaValues: PColor32); 
    protected 
    function GetFillLine: TFillLineEvent; override; 
    end; 

,其中方法GetFillLine变得简单:

function THatchedPatternFiller.GetFillLine: TFillLineEvent; 
begin 
    Result := FillLine; 
end; 

然而,FillLine方法会更复杂一点是这样的:

procedure THatchedPatternFiller.FillLine(Dst: PColor32; DstX, DstY, 
    Length: Integer; AlphaValues: PColor32); 
var 
    X: Integer; 
begin 
    for X := DstX to DstX + Length do 
    begin 
    if ((X - DstY) mod 8 = 0) or ((X + DstY) mod 8 = 0) then 
     Dst^ :=clRed32 
    else 
     Dst^ := 0; 

    Inc(Dst); 
    end; 
end; 

由于DstY保持不变,您还可以重构代码以改善性能。或者你可以使用汇编器(SSE)来加速代码,但我想这对于这样一个简单的函数来说可能是过度的。