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;
|
||||
StartupVfoA, StartupVfoB: Double;
|
||||
begin
|
||||
SetExceptionMask(GetExceptionMask + [exZeroDivide, exInvalidOp]);
|
||||
FVfoA := 14200000;
|
||||
FVfoB := 7100000;
|
||||
FActiveVfo := 0;
|
||||
@@ -1933,6 +1934,7 @@ begin
|
||||
PanelRight.Parent := Self;
|
||||
PanelRight.Align := alClient;
|
||||
PanelRight.BevelOuter := bvNone;
|
||||
PanelRight.DoubleBuffered := True;
|
||||
PanelRight.OnResize := RightPanelResize;
|
||||
|
||||
FSampleRateOverlay := TSampleRateOverlay.Create(Self);
|
||||
|
||||
+26
-64
@@ -19,7 +19,7 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Graphics, ExtCtrls, Controls, Math,
|
||||
IntfGraphics, FPImage, LCLIntf, LCLType, GraphType, AppTheme,
|
||||
LCLIntf, LCLType, AppTheme,
|
||||
AlertOverlay, SampleRateOverlay, VfoOverlay,
|
||||
WaterfallView, SMeterView, RulerView;
|
||||
|
||||
@@ -37,8 +37,6 @@ type
|
||||
FFMGridLastCenter: Double;
|
||||
FFMGridLastStepHz: Double;
|
||||
FFMGridLastSpan: Double;
|
||||
FSpecGradImg: TLazIntfImage;
|
||||
FSpecGradBmp: TBitmap;
|
||||
FSpPts: array of TPoint;
|
||||
FSpPtsLen: Integer;
|
||||
// ── Тема ─────────────────────────────────────────────────────────────────
|
||||
@@ -248,23 +246,6 @@ begin
|
||||
Result := Format('%d.%3.3d.%3.3d', [Mhz, KHz, Rest]);
|
||||
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;
|
||||
var
|
||||
@@ -301,8 +282,6 @@ begin
|
||||
FSpectrumBitmap := TBitmap.Create;
|
||||
FSpectrumBitmap.PixelFormat := pf32bit;
|
||||
FGridBitmap := TBitmap.Create;
|
||||
FSpecGradBmp := TBitmap.Create;
|
||||
FSpecGradImg := nil;
|
||||
FGridBitmapW := 0; FGridBitmapH := 0;
|
||||
FFMGridLastCenter := -1.0; FFMGridLastStepHz := -1.0; FFMGridLastSpan := -1.0;
|
||||
FFMGridStepHz := 0.0;
|
||||
@@ -334,8 +313,6 @@ destructor TSpectrumView.Destroy;
|
||||
begin
|
||||
FSpectrumBitmap.Free;
|
||||
FGridBitmap.Free;
|
||||
FSpecGradBmp.Free;
|
||||
FreeAndNil(FSpecGradImg);
|
||||
FWaterfall.Free;
|
||||
FSMeter.Free;
|
||||
FRuler.Free;
|
||||
@@ -550,9 +527,9 @@ end;
|
||||
|
||||
procedure TSpectrumView.DrawSpectrumGradient(const SpPts: array of TPoint; W, H: Integer);
|
||||
var
|
||||
Row, Col: Integer; YMin, Alpha: Integer;
|
||||
RowPtr: PByte; BPPg: Integer; RG, GG: Byte;
|
||||
Desc: TRawImageDescription;
|
||||
Row, Col, Alpha, YMin, Off: Integer;
|
||||
RowPtr: PByte;
|
||||
GradB, GradG, GradR: Byte;
|
||||
begin
|
||||
if FSpectrumBitmap = nil then Exit;
|
||||
if (W <= 0) or (H <= 0) then Exit;
|
||||
@@ -560,45 +537,27 @@ begin
|
||||
for Col := 0 to W - 1 do
|
||||
if SpPts[Col].Y < YMin then YMin := SpPts[Col].Y;
|
||||
if YMin >= H then Exit;
|
||||
if (FSpecGradImg = nil) or (FSpecGradImg.Width <> W) or (FSpecGradImg.Height <> H) then
|
||||
begin
|
||||
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;
|
||||
|
||||
FSpectrumBitmap.BeginUpdate(False);
|
||||
for Row := YMin to H - 1 do
|
||||
begin
|
||||
Alpha := Round((1.0 - Sqr((Row - YMin) / Max(1.0, H - YMin - 1.0))) * 200);
|
||||
if Alpha <= 0 then Continue;
|
||||
if Alpha > 200 then Alpha := 200;
|
||||
GG := Byte(FTheme.SpecGradB * Alpha div 200);
|
||||
RG := Byte(FTheme.SpecGradG * Alpha div 200);
|
||||
RowPtr := FSpecGradImg.GetDataLineStart(Row);
|
||||
if RowPtr = nil then Continue;
|
||||
GradB := Byte(FTheme.SpecGradB * Alpha div 200);
|
||||
GradG := Byte(FTheme.SpecGradG * Alpha div 200);
|
||||
GradR := Byte(FTheme.SpecGradR * Alpha div 200);
|
||||
RowPtr := PByte(FSpectrumBitmap.ScanLine[Row]);
|
||||
for Col := 0 to W - 1 do
|
||||
begin
|
||||
if SpPts[Col].Y <= Row then
|
||||
begin
|
||||
RowPtr[0] := GG;
|
||||
RowPtr[1] := RG;
|
||||
RowPtr[2] := Byte(FTheme.SpecGradR * Alpha div 200);
|
||||
if BPPg >= 4 then RowPtr[3] := Byte(Alpha);
|
||||
end else begin
|
||||
RowPtr[0] := 0; RowPtr[1] := 0; RowPtr[2] := 0;
|
||||
if BPPg >= 4 then RowPtr[3] := 0;
|
||||
end;
|
||||
Inc(RowPtr, BPPg);
|
||||
Off := Col * 4;
|
||||
RowPtr[Off] := (GradB * Alpha + RowPtr[Off] * (200 - Alpha)) div 200;
|
||||
RowPtr[Off+1] := (GradG * Alpha + RowPtr[Off+1] * (200 - Alpha)) div 200;
|
||||
RowPtr[Off+2] := (GradR * Alpha + RowPtr[Off+2] * (200 - Alpha)) div 200;
|
||||
end;
|
||||
end;
|
||||
FSpecGradBmp.LoadFromIntfImage(FSpecGradImg);
|
||||
LCLIntf.BitBlt(FSpectrumBitmap.Canvas.Handle, 0, 0, W, H,
|
||||
FSpecGradBmp.Canvas.Handle, 0, 0, $CC0020);
|
||||
FSpectrumBitmap.EndUpdate(False);
|
||||
end;
|
||||
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
@@ -629,7 +588,6 @@ begin
|
||||
FSpectrumBitmap.SetSize(W, H);
|
||||
FSpectrumBitmap.Canvas.Brush.Color := FTheme.BG;
|
||||
FSpectrumBitmap.Canvas.FillRect(Rect(0, 0, W, H));
|
||||
FreeAndNil(FSpecGradImg);
|
||||
InvalidateGridCache;
|
||||
FSpPtsLen := 0;
|
||||
end;
|
||||
@@ -663,7 +621,6 @@ procedure TSpectrumView.SetTheme(const T: TAppTheme);
|
||||
begin
|
||||
FTheme := T;
|
||||
FLightTheme := T.BG > TColor($00808080);
|
||||
FreeAndNil(FSpecGradImg);
|
||||
InvalidateGridCache;
|
||||
FWaterfall.SetTheme(T);
|
||||
FSMeter.SetTheme(T);
|
||||
@@ -716,6 +673,7 @@ procedure TSpectrumView.DrawSpectrum;
|
||||
var
|
||||
C, GC: TCanvas;
|
||||
i, Yp, W, H, GX: Integer;
|
||||
AlphaRow: PCardinal;
|
||||
DBmin, DBmax, dB: Double;
|
||||
VfoX, X1, X2: Integer;
|
||||
TXVfoX, TXX1, TXX2: Integer;
|
||||
@@ -922,6 +880,15 @@ begin
|
||||
FSampleRateOverlay.DrawOverlay(FSpectrumBitmap, C, W, H);
|
||||
if Assigned(FVfoOverlay) then
|
||||
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;
|
||||
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
@@ -946,12 +913,7 @@ procedure TSpectrumView.PaintSpectrum(Sender: TObject);
|
||||
var PB: TPaintBox;
|
||||
begin
|
||||
PB := TPaintBox(Sender);
|
||||
if (FSpectrumBitmap.Width > 0) and (FSpectrumBitmap.Height > 0) then
|
||||
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;
|
||||
PB.Canvas.Draw(0, 0, FSpectrumBitmap);
|
||||
end;
|
||||
|
||||
procedure TSpectrumView.PaintWaterfall(Sender: TObject);
|
||||
|
||||
Reference in New Issue
Block a user