mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 19:45:09 +00:00
On macOS Cocoa, TBitmap.pf32bit stores pixels in ARGB order
(byte0=A, byte1=R, byte2=G, byte3=B) rather than BGRA used on
Linux/Windows. All raw ScanLine pixel blending and channel mapping
is now guarded with { DARWIN} to use the correct offsets.
Also fix PortAudio library discovery on macOS: probe .dylib names
(including Homebrew paths) before falling through to .so/.dll.
116 lines
2.8 KiB
ObjectPascal
116 lines
2.8 KiB
ObjectPascal
unit AlertOverlay;
|
|
|
|
{
|
|
Reusable overlays for spectrum-like bitmap surfaces.
|
|
}
|
|
|
|
{$IFDEF FPC}
|
|
{$MODE Delphi}
|
|
{$ENDIF}
|
|
|
|
interface
|
|
|
|
uses
|
|
Graphics, Types, Math;
|
|
|
|
procedure DrawAlertOverlay(Target: TBitmap; C: TCanvas; W, H: Integer;
|
|
const Title, Detail: string);
|
|
|
|
implementation
|
|
|
|
procedure BlendRect(Target: TBitmap; const Rct: TRect; R, G, B, Alpha: Byte);
|
|
var
|
|
Y, X, InvA: Integer;
|
|
Row: PByte;
|
|
RR: TRect;
|
|
begin
|
|
if (Target = nil) or (Alpha = 0) then Exit;
|
|
RR := Rct;
|
|
if RR.Left < 0 then RR.Left := 0;
|
|
if RR.Top < 0 then RR.Top := 0;
|
|
if RR.Right > Target.Width then RR.Right := Target.Width;
|
|
if RR.Bottom > Target.Height then RR.Bottom := Target.Height;
|
|
if (RR.Right <= RR.Left) or (RR.Bottom <= RR.Top) then Exit;
|
|
|
|
InvA := 255 - Alpha;
|
|
Target.BeginUpdate(False);
|
|
try
|
|
for Y := RR.Top to RR.Bottom - 1 do
|
|
begin
|
|
Row := PByte(Target.ScanLine[Y]);
|
|
if Row = nil then Continue;
|
|
Inc(Row, RR.Left * 4);
|
|
for X := RR.Left to RR.Right - 1 do
|
|
begin
|
|
{$IFDEF DARWIN}
|
|
Row[1] := Byte((Alpha * R + InvA * Row[1]) div 255);
|
|
Row[2] := Byte((Alpha * G + InvA * Row[2]) div 255);
|
|
Row[3] := Byte((Alpha * B + InvA * Row[3]) div 255);
|
|
{$ELSE}
|
|
Row[0] := Byte((Alpha * B + InvA * Row[0]) div 255);
|
|
Row[1] := Byte((Alpha * G + InvA * Row[1]) div 255);
|
|
Row[2] := Byte((Alpha * R + InvA * Row[2]) div 255);
|
|
{$ENDIF}
|
|
Inc(Row, 4);
|
|
end;
|
|
end;
|
|
finally
|
|
Target.EndUpdate(False);
|
|
end;
|
|
end;
|
|
|
|
procedure DrawAlertOverlay(Target: TBitmap; C: TCanvas; W, H: Integer;
|
|
const Title, Detail: string);
|
|
const
|
|
PAD = 12;
|
|
INNER_X = 12;
|
|
ACCENT_W = 4;
|
|
var
|
|
R, AccentR: TRect;
|
|
TW, DW, BoxW, BoxH: Integer;
|
|
begin
|
|
if (Target = nil) or (C = nil) then Exit;
|
|
if (W < 220) or (H < 60) then Exit;
|
|
|
|
C.Font.Name := 'Courier New';
|
|
C.Font.Style := [fsBold];
|
|
C.Font.Size := 9;
|
|
TW := C.TextWidth(Title);
|
|
C.Font.Style := [];
|
|
C.Font.Size := 7;
|
|
DW := C.TextWidth(Detail);
|
|
|
|
BoxW := Max(TW, DW) + INNER_X * 2 + ACCENT_W + 8;
|
|
BoxH := 42;
|
|
R := Rect(W - PAD - BoxW, PAD, W - PAD, PAD + BoxH);
|
|
|
|
BlendRect(Target, R, $A8, $10, $16, 118);
|
|
BlendRect(Target, Rect(R.Left, R.Top, R.Right, R.Top + 1), $FF, $68, $68, 80);
|
|
|
|
C.Brush.Style := bsClear;
|
|
C.Pen.Style := psSolid;
|
|
C.Pen.Width := 1;
|
|
C.Pen.Color := TColor($003838C8);
|
|
C.Rectangle(R);
|
|
|
|
AccentR := Rect(R.Left + 7, R.Top + 7, R.Left + 7 + ACCENT_W, R.Bottom - 7);
|
|
C.Brush.Style := bsSolid;
|
|
C.Brush.Color := TColor($002828F0);
|
|
C.Pen.Style := psClear;
|
|
C.FillRect(AccentR);
|
|
|
|
C.Brush.Style := bsClear;
|
|
C.Font.Name := 'Courier New';
|
|
C.Font.Style := [fsBold];
|
|
C.Font.Size := 9;
|
|
C.Font.Color := TColor($008888FF);
|
|
C.TextOut(R.Left + INNER_X + ACCENT_W + 8, R.Top + 7, Title);
|
|
|
|
C.Font.Style := [];
|
|
C.Font.Size := 7;
|
|
C.Font.Color := TColor($00C8C8E8);
|
|
C.TextOut(R.Left + INNER_X + ACCENT_W + 8, R.Top + 25, Detail);
|
|
end;
|
|
|
|
end.
|