203
262
function BoundsSize(ALeft, ATop: Integer; ASize: TSize): TRect; inline;
205
function DoublePoint(AX, AY: Double): TDoublePoint; inline;
206
function DoubleRect(AX1, AY1, AX2, AY2: Double): TDoubleRect; inline;
207
264
function DoubleInterval(AStart, AEnd: Double): TDoubleInterval; inline;
209
procedure EnsureOrder(var A, B: Integer); overload; inline;
210
procedure EnsureOrder(var A, B: Double); overload; inline;
212
266
procedure Exchange(var A, B: Integer); overload; inline;
213
267
procedure Exchange(var A, B: Double); overload; inline;
214
268
procedure Exchange(var A, B: TDoublePoint); overload; inline;
215
269
procedure Exchange(var A, B: String); overload; inline;
217
procedure ExpandRange(var ALo, AHi: Double; ACoeff: Double); inline;
218
procedure ExpandRect(var ARect: TDoubleRect; const APoint: TDoublePoint); inline;
219
procedure ExpandRect(var ARect: TRect; const APoint: TPoint); inline;
220
procedure ExpandRect(
221
var ARect: TRect; const ACenter: TPoint; ARadius: Integer;
222
AAngle1, AAngle2: Double); inline;
224
function GetIntervals(AMin, AMax: Double; AInverted: Boolean): TDoubleDynArray;
271
function FormatIfNotEmpty(AFormat, AStr: String): String; inline;
226
273
function InterpolateRGB(AColor1, AColor2: Integer; ACoeff: Double): Integer;
228
function IsPointOnLine(const AP, A1, A2: TPoint): Boolean; inline;
229
function IsPointInPolygon(
230
const AP: TPoint; const APolygon: array of TPoint): Boolean;
231
function IsPointInRect(const AP, A1, A2: TPoint): Boolean; inline; overload;
232
function IsPointInRect(const AP: TPoint; const AR: TRect): Boolean; inline; overload;
233
function IsRectInRect(const AInner, AOuter: TRect): Boolean; inline;
234
function IsLineIntersectsLine(const AA, AB, AC, AD: TPoint): Boolean;
235
function IsPolygonIntersectsPolygon(const AP1, AP2: array of TPoint): Boolean;
236
function LineIntersectsRect(
237
var AA, AB: TDoublePoint; const ARect: TDoubleRect): Boolean;
239
function MeasureRotatedRect(const ASize: TPoint; AAngle: Double): TSize;
241
procedure NormalizeRect(var ARect: TRect); overload;
242
procedure NormalizeRect(var ARect: TDoubleRect); overload;
274
function IntToColorHex(AColor: Integer): String; inline;
275
function IsEquivalent(const A1, A2: Double): Boolean; inline;
276
function IsNan(const APoint: TDoublePoint): Boolean; overload; inline;
277
function NumberOr(ANum: Double; ADefault: Double = 0.0): Double; inline;
244
279
function OrientToRad(AOrient: Integer): Double; inline;
246
function PointDist(const A, B: TPoint): Integer; inline;
247
function PointDistX(const A, B: TPoint): Integer; inline;
248
function PointDistY(const A, B: TPoint): Integer; inline;
251
const APt: TDoublePoint; const ARect: TDoubleRect): TDoublePoint;
253
281
function RadToDeg16(ARad: Double): Integer; inline;
254
282
function RadToOrient(ARad: Double): Integer; inline;
256
function RectIntersectsRect(
257
var ARect: TDoubleRect; const AFixed: TDoubleRect): Boolean;
259
function RotatePoint(const APoint: TDoublePoint; AAngle: Double): TDoublePoint; overload;
260
function RotatePoint(const APoint: TPoint; AAngle: Double): TPoint; overload;
261
284
function RoundChecked(A: Double): Integer; inline;
263
function SafeInfinity: Double; inline;
264
function SafeInRange(AValue, ABound1, ABound2: Double): Boolean;
286
procedure SetPropDefaults(AObject: TPersistent; APropNames: array of String);
288
// Accept both locale-specific and default decimal separators.
289
function StrToFloatDefSep(const AStr: String): Double;
266
291
// Call this to silence 'parameter is unused' hint
267
292
procedure Unused(const A1);
270
295
procedure UpdateMinMax(AValue: Double; var AMin, AMax: Double); overload;
271
296
procedure UpdateMinMax(AValue: Integer; var AMin, AMax: Integer); overload;
273
operator +(const A: TPoint; B: TSize): TPoint; overload; inline;
274
operator +(const A, B: TPoint): TPoint; overload; inline;
275
operator +(const A, B: TDoublePoint): TDoublePoint; overload; inline;
276
operator -(const A: TPoint): TPoint; overload; inline;
277
operator -(const A, B: TPoint): TPoint; overload; inline;
278
operator -(const A, B: TDoublePoint): TDoublePoint; overload; inline;
279
operator div(const A: TPoint; ADivisor: Integer): TPoint; inline;
280
operator *(const A: TPoint; AMultiplier: Integer): TPoint; inline;
281
operator *(const A, B: TPoint): TPoint; inline;
282
operator *(const A, B: TDoublePoint): TDoublePoint; overload; inline;
283
operator /(const A, B: TDoublePoint): TDoublePoint; overload; inline;
298
function WeightedAverage(AX1, AX2, ACoeff: Double): Double; inline;
284
300
operator =(const A, B: TMethod): Boolean; overload; inline;
286
operator :=(const APoint: TPoint): TSize; inline;
287
operator :=(const ASize: TSize): TPoint; inline;
290
303
DrawData: TDrawDataRegistry;
304
ShowMessageProc: TShowMessageProc;
307
tasFailedSubcomponentRename = 'Failed to rename components: %s';
295
315
ORIENTATION_UNITS_PER_DEG = 10;
297
function PointLineSide(AP, A1, A2: TPoint): TValueSign; forward;
299
317
function BoundsSize(ALeft, ATop: Integer; ASize: TSize): TRect; inline;
301
319
Result := Bounds(ALeft, ATop, ASize.cx, ASize.cy);
304
procedure CalculateIntervals(
305
AMin, AMax: Double; AxisScale: TAxisScale; out AStart, AStep: Double);
307
extent, extentTmp, stepCount, scale, maxStepCount, m: Double;
310
GOOD_STEPS: array [1..3] of Double = (0.2, 0.5, 1.0);
313
extent := AMax - AMin;
316
if extent <= 0 then exit;
320
for i := Low(GOOD_STEPS) to High(GOOD_STEPS) do begin
321
extentTmp := extent / GOOD_STEPS[i];
322
m := IntPower(BASE, Round(logn(BASE, extentTmp)));
323
while extentTmp * m > BASE do
325
while extentTmp * m <= 1 do
327
stepCount := extentTmp * m;
328
if stepCount > maxStepCount then begin
329
maxStepCount := stepCount;
331
AStep := GOOD_STEPS[i] / m;
336
// If 0 is in the interval, set it as a mark.
337
if InRange(0, AMin, AMax) then
340
AStart := Round((AMin - AStep) * scale) / scale;
341
while AStart > AMin do AStart -= AStep;
344
// If 0 is in the interval, set it as a mark.
345
if InRange(0, AMin, AMax) then
348
AStart := Round((AMax + AStep) * scale) / scale;
349
while AStart < AMax do AStart += AStep;
351
asLogIncreasing: begin
352
// FIXME: asLogIncreasing is still not implemented.
353
// The following is the same code for asIncreasing;
354
// If 0 is in the interval, set it as a mark.
355
if InRange(0, AMin, AMax) then
358
AStart := Round((AMin - AStep) * scale) / scale;
359
while AStart > AMin do AStart -= AStep;
361
asLogDecreasing: begin
362
// FIXME: asLogDecreasing is still not implemented.
363
// The following is the same code for asIncreasing;
364
// If 0 is in the interval, set it as a mark.
365
if InRange(0, AMin, AMax) then
368
AStart := Round((AMax + AStep) * scale) / scale;
369
while AStart < AMax do AStart += AStep;
371
end; {case AxisScale}
374
function DoublePoint(AX, AY: Double): TDoublePoint; inline;
380
function DoubleRect(AX1, AY1, AX2, AY2: Double): TDoubleRect; inline;
388
322
function DoubleInterval(AStart, AEnd: Double): TDoubleInterval;
390
324
Result.FStart := AStart;
391
325
Result.FEnd := AEnd;
394
procedure EnsureOrder(var A, B: Integer); overload; inline;
400
procedure EnsureOrder(var A, B: Double); overload; inline;
406
328
procedure Exchange(var A, B: Integer);
442
procedure ExpandRange(var ALo, AHi: Double; ACoeff: Double);
451
procedure ExpandRect(var ARect: TDoubleRect; const APoint: TDoublePoint);
453
NormalizeRect(ARect);
454
UpdateMinMax(APoint.X, ARect.a.X, ARect.b.X);
455
UpdateMinMax(APoint.Y, ARect.a.Y, ARect.b.Y);
458
procedure ExpandRect(var ARect: TRect; const APoint: TPoint);
460
NormalizeRect(ARect);
461
UpdateMinMax(APoint.X, ARect.Left, ARect.Right);
462
UpdateMinMax(APoint.Y, ARect.Top, ARect.Bottom);
465
procedure ExpandRect(
466
var ARect: TRect; const ACenter: TPoint; ARadius: Integer;
467
AAngle1, AAngle2: Double);
472
p := Point(ARadius, 0);
473
EnsureOrder(AAngle1, AAngle2);
474
ExpandRect(ARect, RotatePoint(p, AAngle1) + ACenter);
475
ExpandRect(ARect, RotatePoint(p, AAngle2) + ACenter);
476
j := Floor(AAngle1 / Pi * 2);
477
for i := j to j + 4 do
478
if InRange(Pi / 2 * i, AAngle1, AAngle2) then
479
ExpandRect(ARect, RotatePoint(p, Pi / 2 * i) + ACenter);
482
function GetIntervals(AMin, AMax: Double; AInverted: Boolean): TDoubleDynArray;
484
INV_TO_SCALE: array [Boolean] of TAxisScale = (asIncreasing, asDecreasing);
487
start, step, m, m1: Double;
490
CalculateIntervals(AMin, AMax, INV_TO_SCALE[AInverted], start, step);
498
if InRange(m, AMin, AMax) then
500
else if markCount > 0 then
503
if m1 = m then break;
506
SetLength(Result, markCount);
510
if Abs(m / step) < K then
512
if InRange(m, AMin, AMax) then begin
513
Result[markCount] := m;
516
else if markCount > 0 then
519
if m1 = m then break;
364
function FormatIfNotEmpty(AFormat, AStr: String): String;
369
Result := Format(AFormat, [AStr]);
524
372
function InterpolateRGB(AColor1, AColor2: Integer; ACoeff: Double): Integer;
535
383
r[i] := Round(c1[i] + (c2[i] - c1[i]) * ACoeff);
538
function IsPointOnLine(const AP, A1, A2: TPoint): Boolean;
540
Result := IsPointInRect(AP, A1, A2) and (PointLineSide(AP, A1, A2) = 0);
543
function IsPointInPolygon(
544
const AP: TPoint; const APolygon: array of TPoint): Boolean;
550
if Length(APolygon) = 0 then exit(false);
551
p1 := APolygon[High(APolygon)];
552
for i := 0 to High(APolygon) do begin
554
if IsPointOnLine(AP, p1, p2) then exit(true);
558
p1 := APolygon[High(APolygon)];
559
for i := 0 to High(APolygon) do begin
561
s1 := Sign(p1.Y - AP.Y);
562
s2 := Sign(p2.Y - AP.Y);
564
-1: count += Ord(PointLineSide(AP, p1, p2) = Sign(p1.Y - p2.Y));
565
0: if s1 + s2 = 1 then begin
567
count += Ord(p1.X >= AP.X)
569
count += Ord(p2.X >= AP.X)
574
Result := count mod 2 = 1;
577
function IsPointInRect(const AP, A1, A2: TPoint): Boolean;
579
Result := SafeInRange(AP.X, A1.X, A2.X) and SafeInRange(AP.Y, A1.Y, A2.Y);
582
function IsPointInRect(const AP: TPoint; const AR: TRect): Boolean;
585
SafeInRange(AP.X, AR.Left, AR.Right) and
586
SafeInRange(AP.Y, AR.Top, AR.Bottom);
589
function IsRectInRect(const AInner, AOuter: TRect): Boolean;
592
IsPointInRect(AInner.TopLeft, AOuter) and
593
IsPointInRect(AInner.BottomRight, AOuter);
596
function IsLineIntersectsLine(const AA, AB, AC, AD: TPoint): Boolean;
598
sa, sb, sc, sd: TValueSign;
600
sa := PointLineSide(AA, AC, AD);
601
sb := PointLineSide(AB, AC, AD);
602
if (sa = 0) and (sb = 0) then
603
// All points are on the same infinite line.
605
IsPointInRect(AA, AC, AD) or IsPointInRect(AB, AC, AD) or
606
IsPointInRect(AC, AA, AB) or IsPointInRect(AD, AA, AB)
608
sc := PointLineSide(AC, AA, AB);
609
sd := PointLineSide(AD, AA, AB);
610
Result := (sa * sb <= 0) and (sc * sd <= 0);
614
function IsPolygonIntersectsPolygon(const AP1, AP2: array of TPoint): Boolean;
619
if (Length(AP1) = 0) or (Length(AP2) = 0) then exit(false);
620
if IsPointInPolygon(AP1[0], AP2) or IsPointInPolygon(AP2[0], AP1) then
622
for i := 0 to High(AP1) do begin
624
p2 := AP1[(i + 1) mod Length(AP1)];
625
for j := 0 to High(AP2) do
626
if IsLineIntersectsLine(p1, p2, AP2[j], AP2[(j + 1) mod Length(AP2)]) then
632
function LineIntersectsRect(
633
var AA, AB: TDoublePoint; const ARect: TDoubleRect): Boolean;
637
procedure AdjustX(var AP: TDoublePoint; ANewX: Double); inline;
639
AP.Y += dy / dx * (ANewX - AP.X);
643
procedure AdjustY(var AP: TDoublePoint; ANewY: Double); inline;
645
AP.X += dx / dy * (ANewY - AP.Y);
652
case CASE_OF_TWO[AA.X < ARect.a.X, AB.X < ARect.a.X] of
653
cotFirst: AdjustX(AA, ARect.a.X);
654
cotSecond: AdjustX(AB, ARect.a.X);
655
cotBoth: exit(false);
657
case CASE_OF_TWO[AA.X > ARect.b.X, AB.X > ARect.b.X] of
658
cotFirst: AdjustX(AA, ARect.b.X);
659
cotSecond: AdjustX(AB, ARect.b.X);
660
cotBoth: exit(false);
662
case CASE_OF_TWO[AA.Y < ARect.a.Y, AB.Y < ARect.a.Y] of
663
cotFirst: AdjustY(AA, ARect.a.Y);
664
cotSecond: AdjustY(AB, ARect.a.Y);
665
cotBoth: exit(false);
667
case CASE_OF_TWO[AA.Y > ARect.b.Y, AB.Y > ARect.b.Y] of
668
cotFirst: AdjustY(AA, ARect.b.Y);
669
cotSecond: AdjustY(AB, ARect.b.Y);
670
cotBoth: exit(false);
675
function MeasureRotatedRect(const ASize: TPoint; AAngle: Double): TSize;
679
pt1 := RotatePoint(ASize, AAngle);
680
pt2 := RotatePoint(Point(ASize.X, -ASize.Y), AAngle);
681
Result.cx := Max(Abs(pt1.X), Abs(pt2.X));
682
Result.cy := Max(Abs(pt1.Y), Abs(pt2.Y));
685
procedure NormalizeRect(var ARect: TRect);
688
EnsureOrder(Left, Right);
689
EnsureOrder(Top, Bottom);
693
procedure NormalizeRect(var ARect: TDoubleRect); overload;
696
EnsureOrder(a.X, b.X);
697
EnsureOrder(a.Y, b.Y);
386
function IntToColorHex(AColor: Integer): String;
388
if AColor = clTAColor then
391
Result := '$' + IntToHex(AColor, 6);
394
function IsEquivalent(const A1, A2: Double): Boolean;
396
Result := CompareDWord(A1, A2, SizeOf(A1) div SizeOf(DWord)) = 0;
399
function IsNan(const APoint: TDoublePoint): Boolean;
401
Result := IsNan(APoint.X) or IsNan(APoint.Y);
404
function NumberOr(ANum: Double; ADefault: Double): Double;
406
Result := IfThen(IsNan(ANum), ADefault, ANum);
701
409
function OrientToRad(AOrient: Integer): Double;
703
411
Result := DegToRad(AOrient / ORIENTATION_UNITS_PER_DEG);
706
function PointDist(const A, B: TPoint): Integer;
708
Result := Min(Sqr(Int64(A.X) - B.X) + Sqr(Int64(A.Y) - B.Y), MaxInt);
711
function PointDistX(const A, B: TPoint): Integer;
713
Result := Min(Abs(Int64(A.X) - B.X), MaxInt);
716
function PointDistY(const A, B: TPoint): Integer; inline;
718
Result := Min(Abs(Int64(A.Y) - B.Y), MaxInt);
721
function PointLineSide(AP, A1, A2: TPoint): TValueSign;
727
Result := Sign((AP.X - a1x) * (A2.Y - a1y) - (AP.Y - a1y) * (A2.X - a1x));
731
const APt: TDoublePoint; const ARect: TDoubleRect): TDoublePoint;
733
Result.X := EnsureRange(APt.X, ARect.a.X, ARect.b.X);
734
Result.Y := EnsureRange(APt.Y, ARect.a.Y, ARect.b.Y);
737
414
function RadToDeg16(ARad: Double): Integer;
739
416
Result := Round(RadToDeg(ARad) * 16);
744
421
Result := Round(RadToDeg(ARad)) * ORIENTATION_UNITS_PER_DEG;
747
function RectIntersectsRect(
748
var ARect: TDoubleRect; const AFixed: TDoubleRect): Boolean;
750
function RangesIntersect(L1, R1, L2, R2: Double; out L, R: Double): Boolean;
762
RangesIntersect(a.X, b.X, AFixed.a.X, AFixed.b.X, a.X, b.X) and
763
RangesIntersect(a.Y, b.Y, AFixed.a.Y, AFixed.b.Y, a.Y, b.Y);
766
function RotatePoint(const APoint: TDoublePoint; AAngle: Double): TDoublePoint;
770
SinCos(AAngle, sa, ca);
771
Result.X := ca * APoint.X - sa * APoint.Y;
772
Result.Y := sa * APoint.X + ca * APoint.Y;
775
function RotatePoint(const APoint: TPoint; AAngle: Double): TPoint;
779
SinCos(AAngle, sa, ca);
780
Result.X := Round(ca * APoint.X - sa * APoint.Y);
781
Result.Y := Round(sa * APoint.X + ca * APoint.Y);
784
424
function RoundChecked(A: Double): Integer;
786
426
Result := Round(EnsureRange(A, -MaxInt, MaxInt));
789
function SafeInfinity: Double;
429
procedure SetPropDefaults(AObject: TPersistent; APropNames: array of String);
791
{$IFOPT R+}{$DEFINE RangeChecking}{$ELSE}{$UNDEF RangeChecking}{$ENDIF}
792
{$IFOPT Q+}{$DEFINE OverflowChecking}{$ELSE}{$UNDEF OverflowChecking}{$ENDIF}
795
{$IFDEF OverflowChecking}{$Q+}{$ENDIF}{$IFDEF RangeChecking}{$R+}{$ENDIF}
434
for n in APropNames do begin
435
p := GetPropInfo(AObject, n);
436
SetOrdProp(AObject, p, p^.Default);
798
function SafeInRange(AValue, ABound1, ABound2: Double): Boolean;
441
DefSeparatorSettings: TFormatSettings;
443
function StrToFloatDefSep(const AStr: String): Double;
800
EnsureOrder(ABound1, ABound2);
801
Result := InRange(AValue, ABound1, ABound2);
446
not TryStrToFloat(AStr, Result, DefSeparatorSettings) and
447
not TryStrToFloat(AStr, Result)
830
operator + (const A: TPoint; B: TSize): TPoint;
832
Result.X := A.X + B.cx;
833
Result.Y := A.Y + B.cy;
836
operator + (const A, B: TPoint): TPoint;
838
Result.X := A.X + B.X;
839
Result.Y := A.Y + B.Y;
842
operator + (const A, B: TDoublePoint): TDoublePoint;
844
Result.X := A.X + B.X;
845
Result.Y := A.Y + B.Y;
848
operator - (const A: TPoint): TPoint;
854
operator - (const A, B: TPoint): TPoint;
856
Result.X := A.X - B.X;
857
Result.Y := A.Y - B.Y;
860
operator - (const A, B: TDoublePoint): TDoublePoint;
862
Result.X := A.X - B.X;
863
Result.Y := A.Y - B.Y;
866
operator div(const A: TPoint; ADivisor: Integer): TPoint;
868
Result.X := A.X div ADivisor;
869
Result.Y := A.Y div ADivisor;
872
operator * (const A: TPoint; AMultiplier: Integer): TPoint;
874
Result.X := A.X * AMultiplier;
875
Result.Y := A.Y * AMultiplier;
878
operator * (const A, B: TPoint): TPoint;
880
Result.X := A.X * B.X;
881
Result.Y := A.Y * B.Y;
884
operator * (const A, B: TDoublePoint): TDoublePoint;
886
Result.X := A.X * B.X;
887
Result.Y := A.Y * B.Y;
890
operator / (const A, B: TDoublePoint): TDoublePoint;
892
Result.X := A.X / B.X;
893
Result.Y := A.Y / B.Y;
479
function WeightedAverage(AX1, AX2, ACoeff: Double): Double;
481
Result := AX1 * (1 - ACoeff) + AX2 * ACoeff;
896
484
operator = (const A, B: TMethod): Boolean;
898
486
Result := (A.Code = B.Code) and (A.Data = B.Data);
901
operator := (const APoint: TPoint): TSize;
903
Result.cx := APoint.X;
904
Result.cy := APoint.Y;
907
operator := (const ASize: TSize): TPoint;
909
Result.X := ASize.cx;
910
Result.Y := ASize.cy;
489
{ TTypedFPListEnumerator }
491
function TTypedFPListEnumerator.GetCurrent: T;
493
Result := T(inherited GetCurrent);
496
{ TIndexedComponentList }
498
procedure TIndexedComponentList.ChangeNamePrefix(
499
const AOld, ANew: String);
505
for i := 0 to Count - 1 do
506
TIndexedComponent(Items[i]).ChangeNamePrefix(AOld, ANew, failed);
507
if (failed <> '') and Assigned(ShowMessageProc) then
508
ShowMessageProc(Format(tasFailedSubcomponentRename, [failed]));
511
{ TIndexedComponent }
513
procedure TIndexedComponent.ChangeNamePrefix(
514
const AOld, ANew: String; var AFailed: String);
516
if AnsiStartsStr(AOld, Name) then
518
Name := ANew + Copy(Name, Length(AOld) + 1, Length(Name));
519
except on EComponentError do
520
AFailed += IfThen(AFailed = '', '', ', ') + Name;
913
524
{ TIntervalList }
783
{ TPublishedIntegerSet }
785
function TPublishedIntegerSet.AsBooleans(ACount: Integer): TBooleanDynArray;
789
SetLength(Result, ACount);
790
if ACount = 0 then exit;
792
FillChar(Result[0], Length(Result), true)
795
if InRange(i, 0, High(Result)) then
799
function TPublishedIntegerSet.GetAsString: String;
804
Result := PUB_INT_SET_ALL
805
else if Length(FData) = 0 then
806
Result := PUB_INT_SET_EMPTY
808
Result := IntToStr(FData[0]);
809
for i := 1 to High(FData) do
810
Result += ',' + IntToStr(FData[i]);
814
function TPublishedIntegerSet.GetIsSet(AIndex: Integer): Boolean;
821
if i = AIndex then exit;
825
constructor TPublishedIntegerSet.Init;
830
procedure TPublishedIntegerSet.SetAllSet(AValue: Boolean);
832
if FAllSet = AValue then exit;
838
procedure TPublishedIntegerSet.SetAsString(AValue: String);
844
AllSet := AValue = PUB_INT_SET_ALL;
846
sl := TStringList.Create;
848
sl.CommaText := AValue;
849
SetLength(FData, sl.Count);
852
if TryStrToInt(s, p) then begin
862
procedure TPublishedIntegerSet.SetIsSet(AIndex: Integer; AValue: Boolean);
866
if AllSet or (IsSet[AIndex] = AValue) then exit;
868
SetLength(FData, Length(FData) + 1);
869
FData[High(FData)] := AIndex;
873
for i := 0 to High(FData) do
874
if FData[i] <> AIndex then begin
875
FData[j] := FData[i];
1165
884
DrawData := TDrawDataRegistry.Create;
885
DefSeparatorSettings := DefaultFormatSettings;
886
DefSeparatorSettings.DecimalSeparator := '.';