mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
Fix spectrum invisible on win32 and mask WDSP FPU exceptions
SpectrumView: rewrite DrawSpectrumGradient to blend directly into FSpectrumBitmap via ScanLine instead of TLazIntfImage+BitBlt (stale DC on win32). Add alpha=$FF fixup pass so pf32bit Canvas.Draw renders via StretchBlt not AlphaBlend. Remove FSpecGradImg/FSpecGradBmp fields. MainForm: mask exZeroDivide/exInvalidOp in FormCreate so WDSP DLL divide-by-zero does not crash the DSP thread on win32 (Qt6 already masks FPU exceptions globally). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1160,6 +1160,7 @@ var
|
|||||||
WebCfg: TWebSettings;
|
WebCfg: TWebSettings;
|
||||||
StartupVfoA, StartupVfoB: Double;
|
StartupVfoA, StartupVfoB: Double;
|
||||||
begin
|
begin
|
||||||
|
SetExceptionMask(GetExceptionMask + [exZeroDivide, exInvalidOp]);
|
||||||
FVfoA := 14200000;
|
FVfoA := 14200000;
|
||||||
FVfoB := 7100000;
|
FVfoB := 7100000;
|
||||||
FActiveVfo := 0;
|
FActiveVfo := 0;
|
||||||
@@ -1933,6 +1934,7 @@ begin
|
|||||||
PanelRight.Parent := Self;
|
PanelRight.Parent := Self;
|
||||||
PanelRight.Align := alClient;
|
PanelRight.Align := alClient;
|
||||||
PanelRight.BevelOuter := bvNone;
|
PanelRight.BevelOuter := bvNone;
|
||||||
|
PanelRight.DoubleBuffered := True;
|
||||||
PanelRight.OnResize := RightPanelResize;
|
PanelRight.OnResize := RightPanelResize;
|
||||||
|
|
||||||
FSampleRateOverlay := TSampleRateOverlay.Create(Self);
|
FSampleRateOverlay := TSampleRateOverlay.Create(Self);
|
||||||
|
|||||||
+26
-64
@@ -19,7 +19,7 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, Graphics, ExtCtrls, Controls, Math,
|
Classes, SysUtils, Graphics, ExtCtrls, Controls, Math,
|
||||||
IntfGraphics, FPImage, LCLIntf, LCLType, GraphType, AppTheme,
|
LCLIntf, LCLType, AppTheme,
|
||||||
AlertOverlay, SampleRateOverlay, VfoOverlay,
|
AlertOverlay, SampleRateOverlay, VfoOverlay,
|
||||||
WaterfallView, SMeterView, RulerView;
|
WaterfallView, SMeterView, RulerView;
|
||||||
|
|
||||||
@@ -37,8 +37,6 @@ type
|
|||||||
FFMGridLastCenter: Double;
|
FFMGridLastCenter: Double;
|
||||||
FFMGridLastStepHz: Double;
|
FFMGridLastStepHz: Double;
|
||||||
FFMGridLastSpan: Double;
|
FFMGridLastSpan: Double;
|
||||||
FSpecGradImg: TLazIntfImage;
|
|
||||||
FSpecGradBmp: TBitmap;
|
|
||||||
FSpPts: array of TPoint;
|
FSpPts: array of TPoint;
|
||||||
FSpPtsLen: Integer;
|
FSpPtsLen: Integer;
|
||||||
// ── Тема ─────────────────────────────────────────────────────────────────
|
// ── Тема ─────────────────────────────────────────────────────────────────
|
||||||
@@ -248,23 +246,6 @@ begin
|
|||||||
Result := Format('%d.%3.3d.%3.3d', [Mhz, KHz, Rest]);
|
Result := Format('%d.%3.3d.%3.3d', [Mhz, KHz, Rest]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure InitRawDesc32(var Desc: TRawImageDescription; AWidth, AHeight: Integer);
|
|
||||||
begin
|
|
||||||
FillChar(Desc, SizeOf(Desc), 0);
|
|
||||||
Desc.Format := ricfRGBA;
|
|
||||||
Desc.Width := AWidth;
|
|
||||||
Desc.Height := AHeight;
|
|
||||||
Desc.Depth := 32;
|
|
||||||
Desc.BitOrder := riboBitsInOrder;
|
|
||||||
Desc.ByteOrder := riboLSBFirst;
|
|
||||||
Desc.LineOrder := riloTopToBottom;
|
|
||||||
Desc.BitsPerPixel := 32;
|
|
||||||
Desc.LineEnd := rileDWordBoundary;
|
|
||||||
Desc.BlueShift := 0; Desc.BluePrec := 8;
|
|
||||||
Desc.GreenShift := 8; Desc.GreenPrec := 8;
|
|
||||||
Desc.RedShift := 16; Desc.RedPrec := 8;
|
|
||||||
Desc.AlphaShift := 24; Desc.AlphaPrec := 8;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function MixColorBGR(C1, C2: TColor; T: Double): TColor;
|
function MixColorBGR(C1, C2: TColor; T: Double): TColor;
|
||||||
var
|
var
|
||||||
@@ -301,8 +282,6 @@ begin
|
|||||||
FSpectrumBitmap := TBitmap.Create;
|
FSpectrumBitmap := TBitmap.Create;
|
||||||
FSpectrumBitmap.PixelFormat := pf32bit;
|
FSpectrumBitmap.PixelFormat := pf32bit;
|
||||||
FGridBitmap := TBitmap.Create;
|
FGridBitmap := TBitmap.Create;
|
||||||
FSpecGradBmp := TBitmap.Create;
|
|
||||||
FSpecGradImg := nil;
|
|
||||||
FGridBitmapW := 0; FGridBitmapH := 0;
|
FGridBitmapW := 0; FGridBitmapH := 0;
|
||||||
FFMGridLastCenter := -1.0; FFMGridLastStepHz := -1.0; FFMGridLastSpan := -1.0;
|
FFMGridLastCenter := -1.0; FFMGridLastStepHz := -1.0; FFMGridLastSpan := -1.0;
|
||||||
FFMGridStepHz := 0.0;
|
FFMGridStepHz := 0.0;
|
||||||
@@ -334,8 +313,6 @@ destructor TSpectrumView.Destroy;
|
|||||||
begin
|
begin
|
||||||
FSpectrumBitmap.Free;
|
FSpectrumBitmap.Free;
|
||||||
FGridBitmap.Free;
|
FGridBitmap.Free;
|
||||||
FSpecGradBmp.Free;
|
|
||||||
FreeAndNil(FSpecGradImg);
|
|
||||||
FWaterfall.Free;
|
FWaterfall.Free;
|
||||||
FSMeter.Free;
|
FSMeter.Free;
|
||||||
FRuler.Free;
|
FRuler.Free;
|
||||||
@@ -550,9 +527,9 @@ end;
|
|||||||
|
|
||||||
procedure TSpectrumView.DrawSpectrumGradient(const SpPts: array of TPoint; W, H: Integer);
|
procedure TSpectrumView.DrawSpectrumGradient(const SpPts: array of TPoint; W, H: Integer);
|
||||||
var
|
var
|
||||||
Row, Col: Integer; YMin, Alpha: Integer;
|
Row, Col, Alpha, YMin, Off: Integer;
|
||||||
RowPtr: PByte; BPPg: Integer; RG, GG: Byte;
|
RowPtr: PByte;
|
||||||
Desc: TRawImageDescription;
|
GradB, GradG, GradR: Byte;
|
||||||
begin
|
begin
|
||||||
if FSpectrumBitmap = nil then Exit;
|
if FSpectrumBitmap = nil then Exit;
|
||||||
if (W <= 0) or (H <= 0) then Exit;
|
if (W <= 0) or (H <= 0) then Exit;
|
||||||
@@ -560,45 +537,27 @@ begin
|
|||||||
for Col := 0 to W - 1 do
|
for Col := 0 to W - 1 do
|
||||||
if SpPts[Col].Y < YMin then YMin := SpPts[Col].Y;
|
if SpPts[Col].Y < YMin then YMin := SpPts[Col].Y;
|
||||||
if YMin >= H then Exit;
|
if YMin >= H then Exit;
|
||||||
if (FSpecGradImg = nil) or (FSpecGradImg.Width <> W) or (FSpecGradImg.Height <> H) then
|
|
||||||
begin
|
FSpectrumBitmap.BeginUpdate(False);
|
||||||
FreeAndNil(FSpecGradImg);
|
|
||||||
FSpecGradImg := TLazIntfImage.Create(W, H);
|
|
||||||
InitRawDesc32(Desc, W, H);
|
|
||||||
FSpecGradImg.DataDescription := Desc;
|
|
||||||
FSpecGradImg.CreateData;
|
|
||||||
end;
|
|
||||||
if FSpecGradImg.PixelData <> nil then
|
|
||||||
FillChar(FSpecGradImg.PixelData^, W * H * 4, 0);
|
|
||||||
BPPg := FSpecGradImg.DataDescription.BitsPerPixel div 8;
|
|
||||||
if BPPg < 3 then BPPg := 4;
|
|
||||||
for Row := YMin to H - 1 do
|
for Row := YMin to H - 1 do
|
||||||
begin
|
begin
|
||||||
Alpha := Round((1.0 - Sqr((Row - YMin) / Max(1.0, H - YMin - 1.0))) * 200);
|
Alpha := Round((1.0 - Sqr((Row - YMin) / Max(1.0, H - YMin - 1.0))) * 200);
|
||||||
if Alpha <= 0 then Continue;
|
if Alpha <= 0 then Continue;
|
||||||
if Alpha > 200 then Alpha := 200;
|
if Alpha > 200 then Alpha := 200;
|
||||||
GG := Byte(FTheme.SpecGradB * Alpha div 200);
|
GradB := Byte(FTheme.SpecGradB * Alpha div 200);
|
||||||
RG := Byte(FTheme.SpecGradG * Alpha div 200);
|
GradG := Byte(FTheme.SpecGradG * Alpha div 200);
|
||||||
RowPtr := FSpecGradImg.GetDataLineStart(Row);
|
GradR := Byte(FTheme.SpecGradR * Alpha div 200);
|
||||||
if RowPtr = nil then Continue;
|
RowPtr := PByte(FSpectrumBitmap.ScanLine[Row]);
|
||||||
for Col := 0 to W - 1 do
|
for Col := 0 to W - 1 do
|
||||||
begin
|
|
||||||
if SpPts[Col].Y <= Row then
|
if SpPts[Col].Y <= Row then
|
||||||
begin
|
begin
|
||||||
RowPtr[0] := GG;
|
Off := Col * 4;
|
||||||
RowPtr[1] := RG;
|
RowPtr[Off] := (GradB * Alpha + RowPtr[Off] * (200 - Alpha)) div 200;
|
||||||
RowPtr[2] := Byte(FTheme.SpecGradR * Alpha div 200);
|
RowPtr[Off+1] := (GradG * Alpha + RowPtr[Off+1] * (200 - Alpha)) div 200;
|
||||||
if BPPg >= 4 then RowPtr[3] := Byte(Alpha);
|
RowPtr[Off+2] := (GradR * Alpha + RowPtr[Off+2] * (200 - Alpha)) div 200;
|
||||||
end else begin
|
|
||||||
RowPtr[0] := 0; RowPtr[1] := 0; RowPtr[2] := 0;
|
|
||||||
if BPPg >= 4 then RowPtr[3] := 0;
|
|
||||||
end;
|
|
||||||
Inc(RowPtr, BPPg);
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
FSpecGradBmp.LoadFromIntfImage(FSpecGradImg);
|
FSpectrumBitmap.EndUpdate(False);
|
||||||
LCLIntf.BitBlt(FSpectrumBitmap.Canvas.Handle, 0, 0, W, H,
|
|
||||||
FSpecGradBmp.Canvas.Handle, 0, 0, $CC0020);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// ────────────────────────────────────────────────────────────────────────────
|
// ────────────────────────────────────────────────────────────────────────────
|
||||||
@@ -629,7 +588,6 @@ begin
|
|||||||
FSpectrumBitmap.SetSize(W, H);
|
FSpectrumBitmap.SetSize(W, H);
|
||||||
FSpectrumBitmap.Canvas.Brush.Color := FTheme.BG;
|
FSpectrumBitmap.Canvas.Brush.Color := FTheme.BG;
|
||||||
FSpectrumBitmap.Canvas.FillRect(Rect(0, 0, W, H));
|
FSpectrumBitmap.Canvas.FillRect(Rect(0, 0, W, H));
|
||||||
FreeAndNil(FSpecGradImg);
|
|
||||||
InvalidateGridCache;
|
InvalidateGridCache;
|
||||||
FSpPtsLen := 0;
|
FSpPtsLen := 0;
|
||||||
end;
|
end;
|
||||||
@@ -663,7 +621,6 @@ procedure TSpectrumView.SetTheme(const T: TAppTheme);
|
|||||||
begin
|
begin
|
||||||
FTheme := T;
|
FTheme := T;
|
||||||
FLightTheme := T.BG > TColor($00808080);
|
FLightTheme := T.BG > TColor($00808080);
|
||||||
FreeAndNil(FSpecGradImg);
|
|
||||||
InvalidateGridCache;
|
InvalidateGridCache;
|
||||||
FWaterfall.SetTheme(T);
|
FWaterfall.SetTheme(T);
|
||||||
FSMeter.SetTheme(T);
|
FSMeter.SetTheme(T);
|
||||||
@@ -716,6 +673,7 @@ procedure TSpectrumView.DrawSpectrum;
|
|||||||
var
|
var
|
||||||
C, GC: TCanvas;
|
C, GC: TCanvas;
|
||||||
i, Yp, W, H, GX: Integer;
|
i, Yp, W, H, GX: Integer;
|
||||||
|
AlphaRow: PCardinal;
|
||||||
DBmin, DBmax, dB: Double;
|
DBmin, DBmax, dB: Double;
|
||||||
VfoX, X1, X2: Integer;
|
VfoX, X1, X2: Integer;
|
||||||
TXVfoX, TXX1, TXX2: Integer;
|
TXVfoX, TXX1, TXX2: Integer;
|
||||||
@@ -922,6 +880,15 @@ begin
|
|||||||
FSampleRateOverlay.DrawOverlay(FSpectrumBitmap, C, W, H);
|
FSampleRateOverlay.DrawOverlay(FSpectrumBitmap, C, W, H);
|
||||||
if Assigned(FVfoOverlay) then
|
if Assigned(FVfoOverlay) then
|
||||||
FVfoOverlay.DrawOverlay(FSpectrumBitmap, W, H);
|
FVfoOverlay.DrawOverlay(FSpectrumBitmap, W, H);
|
||||||
|
|
||||||
|
FSpectrumBitmap.BeginUpdate(False);
|
||||||
|
for i := 0 to H - 1 do
|
||||||
|
begin
|
||||||
|
AlphaRow := PCardinal(FSpectrumBitmap.ScanLine[i]);
|
||||||
|
for Yp := 0 to W - 1 do
|
||||||
|
AlphaRow[Yp] := AlphaRow[Yp] or $FF000000;
|
||||||
|
end;
|
||||||
|
FSpectrumBitmap.EndUpdate(False);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// ────────────────────────────────────────────────────────────────────────────
|
// ────────────────────────────────────────────────────────────────────────────
|
||||||
@@ -946,12 +913,7 @@ procedure TSpectrumView.PaintSpectrum(Sender: TObject);
|
|||||||
var PB: TPaintBox;
|
var PB: TPaintBox;
|
||||||
begin
|
begin
|
||||||
PB := TPaintBox(Sender);
|
PB := TPaintBox(Sender);
|
||||||
if (FSpectrumBitmap.Width > 0) and (FSpectrumBitmap.Height > 0) then
|
PB.Canvas.Draw(0, 0, FSpectrumBitmap);
|
||||||
PB.Canvas.Draw(0, 0, FSpectrumBitmap)
|
|
||||||
else begin
|
|
||||||
PB.Canvas.Brush.Color := SV_CLR_BG;
|
|
||||||
PB.Canvas.FillRect(Rect(0, 0, PB.Width, PB.Height));
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSpectrumView.PaintWaterfall(Sender: TObject);
|
procedure TSpectrumView.PaintWaterfall(Sender: TObject);
|
||||||
|
|||||||
Reference in New Issue
Block a user