
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9744 8e941d3f-bd1b-0410-a28a-d453659cc2b4
637 lines
20 KiB
ObjectPascal
637 lines
20 KiB
ObjectPascal
unit fpsPatterns;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils, Classes, Contnrs, Math,
|
|
fpsTypes, fpsChart;
|
|
|
|
const
|
|
FPS_GRAY06 = 'GRAY06';
|
|
FPS_GRAY12 = 'GRAY12';
|
|
FPS_GRAY20 = 'GRAY20';
|
|
FPS_GRAY25 = 'GRAY25';
|
|
FPS_GRAY30 = 'GRAY30';
|
|
FPS_GRAY40 = 'GRAY40';
|
|
FPS_GRAY50 = 'GRAY50';
|
|
FPS_GRAY60 = 'GRAY60';
|
|
FPS_GRAY70 = 'GRAY70';
|
|
FPS_GRAY75 = 'GRAY75';
|
|
FPS_GRAY80 = 'GRAY80';
|
|
FPS_GRAY90 = 'GRAY90';
|
|
|
|
FPS_HOR_THICK = 'HOR_THICK';
|
|
FPS_VERT_THICK = 'VERT_THICK';
|
|
FPS_DIAG_UP_THICK = 'DIAG_UP_THICK';
|
|
FPS_DIAG_DOWN_THICK = 'DIAG_DOWN_THICK';
|
|
FPS_HATCH_THICK = 'HATCH_THICK';
|
|
FPS_CROSS_THICK = 'CROSS_THICK';
|
|
|
|
FPS_HOR_THIN = 'HOR_THIN';
|
|
FPS_VERT_THIN = 'VERT_THIN';
|
|
FPS_DIAG_UP_THIN = 'DIAG_UP_THIN';
|
|
FPS_DIAG_DOWN_THIN = 'DIAG_DOWN_THIN';
|
|
FPS_HATCH_THIN = 'HATCH_THIN';
|
|
FPS_CROSS_THIN = 'CROSS_THIN';
|
|
|
|
FPS_HOR_NARROW = 'HOR_NARROW';
|
|
FPS_VERT_NARROW = 'VERT_NARROW';
|
|
FPS_DIAG_UP_NARROW = 'DIAG_UP_NARROW';
|
|
FPS_DIAG_DOWN_NARROW = 'DIAG_DOWN_NARROW';
|
|
FPS_HATCH_NARROW = 'HATCH_NARROW';
|
|
FPS_CROSS_NARROW = 'CROSS_NARROW';
|
|
|
|
FPS_HOR_DASH = 'HOR_DASH';
|
|
FPS_VERT_DASH = 'VERT_DASH';
|
|
FPS_DIAG_UP_DASH = 'DIAG_UP_DASH';
|
|
FPS_DIAG_DOWN_DASH = 'DIAG_DOWN_DASH';
|
|
FPS_CROSS_DOT = 'CROSS_DOT';
|
|
FPS_HATCH_DOT = 'HATCH_DOT';
|
|
|
|
FPS_BRICK_HOR = 'BRICK_HOR';
|
|
FPS_BRICK_DIAG = 'BRICK_DIAG';
|
|
FPS_CHECKERBOARD_LARGE = 'CHECKERBOARD_LARGE';
|
|
FPS_CHECKERBOARD_SMALL = 'CHECKERBOARD_SMALL';
|
|
FPS_CONFETTI_LARGE = 'CONFETTI_LARGE';
|
|
FPS_CONFETTI_SMALL = 'CONFETTI_SMALL';
|
|
FPS_DIAMOND = 'DIAMOND';
|
|
FPS_DIVOT = 'DIVOT';
|
|
FPS_PLAID = 'PLAID';
|
|
FPS_SHINGLE = 'SHINGLE';
|
|
FPS_SPHERE = 'SPHERE';
|
|
FPS_TRELLIS = 'TRELLIS';
|
|
FPS_WAVE = 'WAVE';
|
|
FPS_WEAVE = 'WEAVE';
|
|
FPS_ZIGZAG = 'ZIGZAG';
|
|
|
|
type
|
|
TsLineFillPatternMultiplier = (lfpmSingle, lfpmDouble, lfpmTriple);
|
|
|
|
TsLineFillPattern = class
|
|
Distance: Single; // Distance of lines, in mm if > 0, in px if < 0
|
|
Angle: Single; // Rotation angle of pattern, in degrees
|
|
LineWidth: Single; // Line width of pattern, in mm if > 0, in px if < 0
|
|
Multiplier: TsLineFillPatternMultiplier;
|
|
end;
|
|
|
|
TsDotFillPattern = array[0..7] of Byte;
|
|
|
|
const
|
|
SOLID_DOT_FILL_PATTERN: TsDotFillPattern = ($FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF);
|
|
|
|
type
|
|
{ TsRawFillPattern
|
|
Combines the same visual pattern as a dot matrix and as vector strokes.
|
|
Vector strokes are supported only by ODS.
|
|
"Raw" patterns do not carry any color - this is added by TsChartFillPattern.
|
|
Used by charts only. }
|
|
TsRawFillPattern = class
|
|
private
|
|
FName: String;
|
|
FDotPattern: TsDotFillPattern;
|
|
FLinePattern: TsLineFillPattern;
|
|
procedure SetLinePattern(AValue: TsLineFillPattern);
|
|
public
|
|
constructor Create(AName: String; ADotPattern: TsDotFillPattern;
|
|
ALineDistance, ALineAngle, ALineWidth: Single; AMultiplier: TsLineFillPatternMultiplier);
|
|
constructor Create(AName: String; ADotPattern: TsDotFillPattern);
|
|
constructor Create(AName: String;
|
|
ALineDistance, ALineAngle, ALineWidth: Single; AMultiplier: TsLineFillPatternMultiplier);
|
|
destructor Destroy; override;
|
|
procedure CopyFrom(ASource: TsRawFillPattern); virtual;
|
|
property Name: String read FName;
|
|
property DotPattern: TsDotFillPattern read FDotPattern write FDotPattern;
|
|
property LinePattern: TsLineFillPattern read FLinePattern write SetLinePattern;
|
|
end;
|
|
|
|
TsRawFillPatternList = class(TFPObjectlist)
|
|
private
|
|
function GetItem(AIndex: Integer): TsRawFillPattern;
|
|
procedure SetItem(AIndex: Integer; AValue: TsRawFillPattern);
|
|
protected
|
|
function AddOrReplace(APattern: TsRawFillPattern): Integer;
|
|
function FindSimilarDotPattern(ALineDistance, ALineAngle, ALineWidth: Single;
|
|
AMultiplier: TsLineFillPatternMultiplier): TsDotFillPattern;
|
|
public
|
|
procedure AddBuiltinPatterns;
|
|
function AddFillPattern(AName: String; ADotPattern: TsDotFillPattern;
|
|
ALineDistance, ALineAngle, ALineWidth: Single; AMultiplier: TsLineFillPatternMultiplier): Integer;
|
|
function AddDotFillPattern(AName: String; APattern: TsDotFillPattern): Integer; overload;
|
|
function AddLineFillPattern(AName: String; ALineDistance, ALineAngle, ALineWidth: Single;
|
|
AMultiplier: TsLineFillPatternMultiplier): Integer;
|
|
function ClonePattern(AIndex: Integer; AName: String): Integer;
|
|
function FindByName(AName: String): TsRawFillPattern;
|
|
function FindLinePatternIndex(ALineDistance, ALineAngle, ALineWidth: Single;
|
|
AMultiplier: TsLineFillPatternMultiplier): Integer;
|
|
function IndexOfName(AName: String): Integer;
|
|
property Items[AIndex: Integer]: TsRawFillPattern read GetItem write SetItem; default;
|
|
end;
|
|
|
|
|
|
implementation
|
|
|
|
const
|
|
WIDE_DISTANCE = 3.0;
|
|
NARROW_DISTANCE = 1.5;
|
|
THIN_LINE = 0.1;
|
|
THICK_LINE = 0.3;
|
|
|
|
{$include fpspatterns_dotpatterns.inc}
|
|
|
|
function StringToDotPattern(APattern: String): TsDotFillPattern;
|
|
const
|
|
w = 8;
|
|
h = 8;
|
|
var
|
|
i, j, n, b: Integer;
|
|
begin
|
|
n := Length(APattern);
|
|
if n > w*h then
|
|
n := w*h;
|
|
|
|
FillChar(Result, Sizeof(Result), 0);
|
|
b := 0;
|
|
i := 0;
|
|
for j := 1 to n do
|
|
begin
|
|
if APattern[j] in ['x', 'X'] then
|
|
Result[i] := Result[i] or (1 shl b);
|
|
inc(b);
|
|
if b = w then
|
|
begin
|
|
inc(i);
|
|
b := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
{ TsRawFillPattern }
|
|
|
|
constructor TsRawFillPattern.Create(AName: String; ADotPattern: TsDotFillPattern);
|
|
begin
|
|
inherited Create;
|
|
FName := AName;
|
|
FDotPattern := ADotPattern;
|
|
FLinePattern := nil; // no line pattern
|
|
end;
|
|
|
|
constructor TsRawFillPattern.Create(AName: String;
|
|
ALineDistance, ALineAngle, ALineWidth: Single; AMultiplier: TsLineFillPatternMultiplier);
|
|
begin
|
|
inherited Create;
|
|
FName := AName;
|
|
FDotPattern := SOLID_DOT_FILL_PATTERN;
|
|
FLinePattern := TsLineFillPattern.Create;
|
|
FLinePattern.Distance := ALineDistance;
|
|
FLinePattern.Angle := ALineAngle;
|
|
FLinePattern.LineWidth := ALineWidth;
|
|
FLinePattern.Multiplier := AMultiplier;
|
|
end;
|
|
|
|
constructor TsRawFillPattern.Create(AName: String; ADotPattern: TsDotFillPattern;
|
|
ALineDistance, ALineAngle, ALineWidth: Single; AMultiplier: TsLineFillPatternMultiplier);
|
|
begin
|
|
inherited Create;
|
|
FName := AName;
|
|
FDotPattern := ADotPattern;
|
|
FLinePattern := TsLineFillPattern.Create;
|
|
FLinePattern.Distance := ALineDistance;
|
|
FLinePattern.Angle := ALineAngle;
|
|
FLinePattern.LineWidth := ALineWidth;
|
|
FLinePattern.Multiplier := AMultiplier;
|
|
end;
|
|
|
|
destructor TsRawFillPattern.Destroy;
|
|
begin
|
|
FName := '';
|
|
FLinePattern.Free;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TsRawFillPattern.CopyFrom(ASource: TsRawFillPattern);
|
|
begin
|
|
FName := ASource.Name;
|
|
FDotPattern := ASource.DotPattern;
|
|
SetLinePattern(ASource.LinePattern);
|
|
end;
|
|
|
|
procedure TsRawFillPattern.SetLinePattern(AValue: TsLineFillPattern);
|
|
begin
|
|
if AValue = nil then
|
|
begin
|
|
FLinePattern.Free;
|
|
FLinePattern := nil;
|
|
end else
|
|
begin
|
|
if FLinePattern = nil then
|
|
FLinePattern := TsLineFillPattern.Create;
|
|
FLinePattern.Distance := AValue.Distance;
|
|
FLinePattern.Angle := AValue.Angle;
|
|
FLinePattern.LineWidth := AValue.LineWidth;
|
|
FLinePattern.Multiplier := AValue.Multiplier;
|
|
end;
|
|
end;
|
|
(*
|
|
{ TsLineFillPatternStyle }
|
|
|
|
constructor TsLineFillPatternStyle.Create(AName: String;
|
|
ALineDistance, ALineAngle, ALineWidth: Single);
|
|
begin
|
|
inherited Create(AName);
|
|
FLineDistance := ALineDistance;
|
|
FLineAngle := ALineAngle;
|
|
FLineWidth := ALineWidth;
|
|
end;
|
|
|
|
procedure TsLineFillPatternStyle.CopyFrom(ASource: TsFillPatternStyle);
|
|
begin
|
|
if (ASource is TsLineFillPatternStyle) then
|
|
begin
|
|
FLineDistance := TsLineFillPatternStyle(ASource).LineDistance;
|
|
FLineAngle := TsLineFillPatternStyle(ASource).LineAngle;
|
|
FLineWidth := TsLineFillPatternStyle(ASource).LineWidth;
|
|
end;
|
|
inherited CopyFrom(ASource);
|
|
end;
|
|
|
|
// The pattern itself goes to infinity, limited by size of area to be filled.
|
|
function TsLineFillPatternStyle.GetHeight: Integer;
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
|
|
function TsLineFillPatternStyle.GetWidth: Integer;
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
|
|
|
|
{ TsDotFillPatternStyle }
|
|
|
|
constructor TsDotFillPatternStyle.Create(AName: String; APattern: String);
|
|
begin
|
|
inherited Create(AName);
|
|
StringToPattern(APattern);
|
|
end;
|
|
|
|
constructor TsDotFillPatternStyle.Create(AName: String; APattern: TBrushPattern);
|
|
begin
|
|
inherited Create(AName);
|
|
FPattern := APattern;
|
|
end;
|
|
|
|
procedure TsDotFillPatternStyle.CopyFrom(ASource: TsFillPatternStyle);
|
|
begin
|
|
if ASource is TsDotFillPatternStyle then
|
|
FPattern := TsDotFillPatternStyle(ASource).Pattern;
|
|
inherited CopyFrom(ASource);
|
|
end;
|
|
|
|
function TsDotFillPatternStyle.GetWidth: Integer;
|
|
begin
|
|
Result := SizeOf(TPenPattern);
|
|
end;
|
|
|
|
function TsDotFillPatternStyle.GetHeight: Integer;
|
|
begin
|
|
Result := SizeOf(TBrushPattern) div SizeOf(TPenPattern);
|
|
end;
|
|
|
|
procedure TsDotFillPatternStyle.StringToPattern(APattern: String);
|
|
var
|
|
L: TStrings;
|
|
w, h, i, j, x, y: Integer;
|
|
patt: String;
|
|
begin
|
|
L := TStringList.Create;
|
|
try
|
|
L.Text := APattern;
|
|
h := L.Count;
|
|
w := Length(L[0]);
|
|
for i := 1 to L.Count-1 do
|
|
if Length(L[i]) <> w then
|
|
raise Exception.Create('The lines in the pattern string must have the same lengths.');
|
|
|
|
FillChar(FPattern, Sizeof(FPattern), 0);
|
|
y := 0;
|
|
i := 0;
|
|
while y < SizeOf(TPenPattern) do
|
|
begin
|
|
if i >= L.Count then
|
|
i := 0;
|
|
patt := L[i];
|
|
x := 0;
|
|
j := 1;
|
|
while x < SizeOf(TPenPattern) do
|
|
begin
|
|
if j > w then
|
|
j := 1;
|
|
if (patt[j] in ['x', 'X']) then
|
|
FPattern[i] := FPattern[i] or (1 shl x);
|
|
inc(x);
|
|
inc(j);
|
|
end;
|
|
inc(y);
|
|
inc(i);
|
|
end;
|
|
finally
|
|
L.Free;
|
|
end;
|
|
end;
|
|
*)
|
|
|
|
{ TsRawFillPatternList }
|
|
|
|
{ Creates the built-in dot patterns as used by Excel. Not all of them are
|
|
available in ODS. }
|
|
procedure TsRawFillPatternList.AddBuiltinPatterns;
|
|
begin
|
|
fpsGray06 := AddDotFillPattern(FPS_GRAY06,
|
|
StringToDotPattern(GRAY06_PATTERN));
|
|
fpsGray12 := AddDotFillPattern(FPS_GRAY12,
|
|
StringToDotPattern(GRAY12_PATTERN));
|
|
fpsGray20 := AddDotFillPattern(FPS_GRAY20,
|
|
StringToDotPattern(GRAY20_PATTERN));
|
|
fpsGray25 := AddDotFillPattern(FPS_GRAY25,
|
|
StringToDotPattern(GRAY25_PATTERN));
|
|
fpsGray30 := AddDotFillPattern(FPS_GRAY30,
|
|
StringToDotPattern(GRAY30_PATTERN));
|
|
fpsGray40 := AddDotFillPattern(FPS_GRAY40,
|
|
StringToDotPattern(GRAY40_PATTERN));
|
|
fpsGray50 := AddDotFillPattern(FPS_GRAY50,
|
|
StringToDotPattern(GRAY50_PATTERN));
|
|
fpsGray60 := AddDotFillPattern(FPS_GRAY60,
|
|
StringToDotPattern(GRAY60_PATTERN));
|
|
fpsGray75 := AddDotFillPattern(FPS_GRAY75,
|
|
StringToDotPattern(GRAY75_PATTERN));
|
|
fpsGray80 := AddDotFillPattern(FPS_GRAY80,
|
|
StringToDotPattern(GRAY80_PATTERN));
|
|
fpsGray90 := AddDotFillPattern(FPS_GRAY90,
|
|
StringToDotPattern(GRAY90_PATTERN));
|
|
|
|
fpsHorThick := AddFillPattern(FPS_HOR_THICK,
|
|
StringToDotPattern(HOR_PATTERN_THICK),
|
|
WIDE_DISTANCE, 0.0, THICK_LINE, lfpmSingle);
|
|
fpsVertThick := AddFillPattern(FPS_VERT_THICK,
|
|
StringToDotPattern(VERT_PATTERN_THICK),
|
|
WIDE_DISTANCE, 90.0, THICK_LINE, lfpmSingle);
|
|
fpsDiagUpThick := AddFillPattern(FPS_DIAG_UP_THICK,
|
|
StringToDotPattern(DIAG_UP_PATTERN_THICK),
|
|
WIDE_DISTANCE, 45.0, THICK_LINE, lfpmSingle);
|
|
fpsDiagDownThick := AddFillPattern(FPS_DIAG_DOWN_THICK,
|
|
StringToDotPattern(DIAG_DOWN_PATTERN_THICK),
|
|
WIDE_DISTANCE, -45.0, THICK_LINE, lfpmSingle);
|
|
fpsHatchThick := AddFillPattern(FPS_HATCH_THICK,
|
|
StringToDotPattern(HATCH_PATTERN_THICK),
|
|
WIDE_DISTANCE, 45.0, THICK_LINE, lfpmDouble);
|
|
fpsCrossThick := AddFillPattern(FPS_CROSS_THICK,
|
|
StringToDotPattern(CROSS_PATTERN_THICK),
|
|
WIDE_DISTANCE, 0.0, THICK_LINE, lfpmDouble);
|
|
|
|
fpsHorThin := AddFillPattern(FPS_HOR_THIN,
|
|
StringToDotPattern(HOR_PATTERN_THIN),
|
|
WIDE_DISTANCE, 0.0, THIN_LINE, lfpmSingle);
|
|
fpsVertThin := AddFillPattern(FPS_VERT_THIN,
|
|
StringToDotPattern(VERT_PATTERN_THIN),
|
|
WIDE_DISTANCE, 90.0, THIN_LINE, lfpmSingle);
|
|
fpsDiagUpThin := AddFillPattern(FPS_DIAG_UP_THIN,
|
|
StringToDotPattern(DIAG_UP_PATTERN_THIN),
|
|
WIDE_DISTANCE, 45.0, THIN_LINE, lfpmSingle);
|
|
fpsDiagDownThin := AddFillPattern(FPS_DIAG_DOWN_THIN,
|
|
StringToDotPattern(DIAG_DOWN_PATTERN_THIN),
|
|
WIDE_DISTANCE, -45.0, THIN_LINE, lfpmSingle);
|
|
fpsHatchThin := AddFillPattern(FPS_HATCH_THIN,
|
|
StringToDotPattern(HATCH_PATTERN_THIN),
|
|
WIDE_DISTANCE, 45.0, THIN_LINE, lfpmDouble);
|
|
fpsCrossThin := AddFillPattern(FPS_CROSS_THIN,
|
|
StringToDotPattern(CROSS_PATTERN_THIN),
|
|
WIDE_DISTANCE, 0.0, THIN_LINE, lfpmDouble);
|
|
|
|
fpsHorNarrow := AddFillPattern(FPS_HOR_NARROW,
|
|
StringToDotPattern(HOR_PATTERN_NARROW),
|
|
NARROW_DISTANCE, 0.0, THIN_LINE, lfpmSingle);
|
|
fpsVertNarrow := AddFillPattern(FPS_VERT_NARROW,
|
|
StringToDotPattern(VERT_PATTERN_NARROW),
|
|
NARROW_DISTANCE, 90.0, THIN_LINE, lfpmSingle);
|
|
fpsDiagUpNarrow := AddFillPattern(FPS_DIAG_UP_NARROW,
|
|
StringToDotPattern(DIAG_UP_PATTERN_NARROW),
|
|
NARROW_DISTANCE, 45.0, THIN_LINE, lfpmSingle);
|
|
fpsDiagDownNarrow := AddFillPattern(FPS_DIAG_DOWN_NARROW,
|
|
StringToDotPattern(DIAG_DOWN_PATTERN_NARROW),
|
|
NARROW_DISTANCE, -45.0, THIN_LINE, lfpmSingle);
|
|
fpsHatchNarrow := AddFillPattern(FPS_HATCH_NARROW,
|
|
StringToDotPattern(HATCH_PATTERN_NARROW),
|
|
NARROW_DISTANCE, 45.0, THIN_LINE, lfpmDouble);
|
|
fpsCrossNarrow := AddFillPattern(FPS_CROSS_NARROW,
|
|
StringToDotPattern(CROSS_PATTERN_NARROW),
|
|
NARROW_DISTANCE, 0.0, THIN_LINE, lfpmDouble);
|
|
|
|
fpsHorDash := AddDotFillPattern(FPS_HOR_DASH,
|
|
StringToDotPattern(HOR_DASH_PATTERN));
|
|
fpsVertDash := AddDotFillPattern(FPS_VERT_DASH,
|
|
StringToDotPattern(VERT_DASH_PATTERN));
|
|
fpsDiagUpDash := AddDotFillPattern(FPS_DIAG_UP_DASH,
|
|
StringToDotPattern(DIAG_UP_DASH_PATTERN));
|
|
fpsDiagDownDash := AddDotFillPattern(FPS_DIAG_DOWN_DASH,
|
|
StringToDotPattern(DIAG_DOWN_DASH_PATTERN));
|
|
fpsCrossDot := AddDotFillPattern(FPS_CROSS_DOT,
|
|
StringToDotPattern(CROSS_PATTERN_DOT));
|
|
fpsHatchDot := AddDotFillPattern(FPS_HATCH_DOT,
|
|
StringToDotPattern(HATCH_PATTERN_DOT));
|
|
|
|
fpsBrickHor := AddDotFillPattern(FPS_BRICK_HOR,
|
|
StringToDotPattern(BRICK_HOR_PATTERN));
|
|
fpsBrickHor := AddDotFillPattern(FPS_BRICK_DIAG,
|
|
StringToDotPattern(BRICK_DIAG_PATTERN));
|
|
fpsCheckerBoardLarge := AddDotFillPattern(FPS_CHECKERBOARD_LARGE,
|
|
StringToDotPattern(CHECKERBOARD_LARGE_PATTERN));
|
|
fpsCheckerBoardSmall := AddDotFillPattern(FPS_CHECKERBOARD_SMALL,
|
|
StringToDotPattern(CHECKERBOARD_SMALL_PATTERN));
|
|
fpsConfettiLarge := AddDotFillPattern(FPS_CONFETTI_LARGE,
|
|
StringToDotPattern(CONFETTI_LARGE_PATTERN));
|
|
fpsConfettiSmall := AddDotFillPattern(FPS_CONFETTI_SMALL,
|
|
StringToDotPattern(CONFETTI_SMALL_PATTERN));
|
|
fpsDiamond := AddDotFillPattern(FPS_DIAMOND,
|
|
StringToDotPattern(DIAMOND_PATTERN));
|
|
fpsDivot := AddDotFillPattern(FPS_DIVOT,
|
|
StringToDotPattern(DIVOT_PATTERN));
|
|
fpsPlaid := AddDotFillPattern(FPS_PLAID,
|
|
StringToDotPattern(PLAID_PATTERN));
|
|
fpsShingle := AddDotFillPattern(FPS_SHINGLE,
|
|
StringToDotPattern(SHINGLE_PATTERN));
|
|
fpsSphere := AddDotFillPattern(FPS_SPHERE,
|
|
StringToDotPattern(SPHERE_PATTERN));
|
|
fpsTrellis := AddDotFillPattern(FPS_TRELLIS,
|
|
StringToDotPattern(TRELLIS_PATTERN));
|
|
fpsWave := AddDotFillPattern(FPS_WAVE,
|
|
StringToDotPattern(WAVE_PATTERN));
|
|
fpsWeave := AddDotFillPattern(FPS_WEAVE,
|
|
StringToDotPattern(WEAVE_PATTERN));
|
|
fpsZigzag := AddDotFillPattern(FPS_ZIGZAG,
|
|
StringToDotPattern(ZIGZAG_PATTERN));
|
|
end;
|
|
|
|
function TsRawFillPatternList.AddDotFillPattern(AName: String;
|
|
APattern: TsDotFillPattern): Integer;
|
|
var
|
|
patt: TsRawFillPattern;
|
|
begin
|
|
patt := TsRawFillPattern.Create(AName, APattern);
|
|
Result := AddOrReplace(patt);
|
|
end;
|
|
|
|
function TsRawFillPatternList.AddFillPattern(AName: String; ADotPattern: TsDotFillPattern;
|
|
ALineDistance, ALineAngle, ALineWidth: Single;
|
|
AMultiplier: TsLineFillPatternMultiplier): Integer;
|
|
var
|
|
patt: TsRawFillPattern;
|
|
begin
|
|
patt := TsRawFillPattern.Create(AName,
|
|
ADotPattern,
|
|
ALineDistance, ALineAngle, ALineWidth, AMultiplier
|
|
);
|
|
Result := AddOrReplace(patt);
|
|
end;
|
|
|
|
function TsRawFillPatternList.AddLineFillPattern(AName: String;
|
|
ALineDistance, ALineAngle, ALineWidth: Single;
|
|
AMultiplier: TsLineFillPatternMultiplier): Integer;
|
|
var
|
|
patt: TsRawFillPattern;
|
|
begin
|
|
patt := TsRawFillPattern.Create(AName, ALineDistance, ALineAngle, ALineWidth, AMultiplier);
|
|
patt.DotPattern := FindSimilarDotPattern(ALineDistance, ALineAngle, ALineWidth, AMultiplier);
|
|
Result := AddOrReplace(patt);
|
|
end;
|
|
|
|
function TsRawFillPatternList.AddOrReplace(APattern: TsRawFillPattern): Integer;
|
|
var
|
|
idx: Integer;
|
|
begin
|
|
idx := IndexOfName(APattern.Name);
|
|
if idx = -1 then
|
|
Result := Add(APattern)
|
|
else
|
|
begin
|
|
Items[idx].CopyFrom(APattern);
|
|
Insert(idx, APattern);
|
|
Result := idx;
|
|
end;
|
|
end;
|
|
|
|
{ Adds a copy of the pattern at the given index and gives it a new name. }
|
|
function TsRawFillPatternList.ClonePattern(AIndex: Integer; AName: String): Integer;
|
|
var
|
|
patt: TsRawFillPattern;
|
|
begin
|
|
patt := Items[AIndex];
|
|
Result := AddFillPattern(AName,
|
|
patt.DotPattern,
|
|
patt.LinePattern.Distance, patt.LinePattern.Angle, patt.LinePattern.LineWidth, patt.LinePattern.Multiplier
|
|
);
|
|
end;
|
|
|
|
function TsRawFillPatternList.FindByName(AName: String): TsRawFillPattern;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to Count-1 do
|
|
if Items[i].Name = AName then
|
|
begin
|
|
Result := Items[i];
|
|
exit;
|
|
end;
|
|
Result := nil;
|
|
end;
|
|
|
|
function TsRawFillPatternList.FindLinePatternIndex(
|
|
ALineDistance, ALineAngle, ALineWidth: Single;
|
|
AMultiplier: TsLineFillPatternMultiplier): Integer;
|
|
var
|
|
i: Integer;
|
|
patt: TsRawFillPattern;
|
|
begin
|
|
for i := 0 to Count-1 do
|
|
begin
|
|
patt := Items[i];
|
|
if patt.LinePattern = nil then
|
|
Continue;
|
|
if SameValue(ALineDistance, patt.LinePattern.Distance, 0.1) and
|
|
SameValue(ALineAngle, patt.LinePattern.Angle, 0.1) and
|
|
SameValue(ALineWidth, patt.LinePattern.LineWidth, 0.1) and
|
|
(AMultiplier = patt.LinePattern.Multiplier) then
|
|
begin
|
|
Result := i;
|
|
exit;
|
|
end;
|
|
end;
|
|
Result := -1;
|
|
end;
|
|
|
|
function TsRawFillPatternList.FindSimilarDotPattern(ALineDistance, ALineAngle,
|
|
ALineWidth: Single; AMultiplier: TsLineFillPatternMultiplier): TsDotFillPattern;
|
|
var
|
|
sinAngle, cosAngle: Single;
|
|
similarIdx: Integer;
|
|
singleLine: Boolean;
|
|
begin
|
|
similarIdx := -1;
|
|
SinCos(DegToRad(ALineAngle), sinAngle, cosAngle);
|
|
singleLine := (AMultiplier = lfpmSingle);
|
|
if SameValue(sinAngle, 0.0, 0.2) then // about +/- 12°
|
|
begin
|
|
if (ALineDistance >= WIDE_DISTANCE) or (ALineDistance <= -8) then
|
|
similarIdx := IfThen(singleLine, fpsHorThin, fpsCrossThin)
|
|
else
|
|
similarIdx := IfThen(singleLine, fpsHorNarrow, fpsCrossNarrow);
|
|
end else
|
|
if SameValue(cosAngle, 0.0, 0.2) then // about 90 +/- 12°
|
|
begin
|
|
if (ALineDistance >= WIDE_DISTANCE) or (ALineDistance <= -8) then
|
|
similarIdx := IfThen(singleLine, fpsVertThin, fpsCrossThin)
|
|
else
|
|
similarIdx := IfThen(singleLine, fpsVertNarrow, fpsCrossNarrow);
|
|
end else
|
|
if ALineAngle > 0 then
|
|
begin
|
|
if (ALineDistance >= WIDE_DISTANCE) or (ALineDistance <= -8) then
|
|
similarIdx := IfThen(singleLine, fpsDiagUpThin, fpsHatchThin)
|
|
else
|
|
similarIdx := IfThen(singleLine, fpsDiagUpNarrow, fpsHatchNarrow);
|
|
end else
|
|
begin
|
|
if (ALineDistance >= WIDE_DISTANCE) or (ALineDistance <= -8) then
|
|
similarIdx := IfThen(singleLine, fpsDiagDownThin, fpsHatchThin)
|
|
else
|
|
similarIdx := IfThen(singleLine, fpsDiagDownNarrow, fpsHatchNarrow);
|
|
end;
|
|
if similarIdx > -1 then
|
|
Result := Items[similarIdx].DotPattern
|
|
else
|
|
Result := SOLID_DOT_FILL_PATTERN;
|
|
end;
|
|
|
|
function TsRawFillPatternList.IndexOfName(AName: String): Integer;
|
|
begin
|
|
for Result := 0 to Count-1 do
|
|
if Items[Result].Name = AName then
|
|
exit;
|
|
Result := -1;
|
|
end;
|
|
|
|
function TsRawFillPatternList.GetItem(AIndex: Integer): TsRawFillPattern;
|
|
begin
|
|
Result := TsRawFillPattern(inherited Items[AIndex]);
|
|
end;
|
|
|
|
procedure TsRawFillPatternList.SetItem(AIndex: Integer; AValue: TsRawFillPattern);
|
|
begin
|
|
TsRawFillPattern(inherited Items[AIndex]).CopyFrom(AValue);
|
|
end;
|
|
|
|
end.
|
|
|