33
44using FluentFlyout . Classes . Settings ;
55using FluentFlyout . Classes . Utils ;
6+ using Microsoft . Win32 ;
67using NAudio . CoreAudioApi ;
78using NAudio . Dsp ;
89using NAudio . Wave ;
9- using Microsoft . Win32 ;
10- using System . Threading ;
1110using System . Windows ;
1211using System . Windows . Media ;
1312using System . Windows . Media . Imaging ;
@@ -465,7 +464,7 @@ private void UpdateBitmap()
465464
466465 private unsafe void DrawBars ( int stride , Span < byte > buffer )
467466 {
468- // Resolve brush once (avoid repeated lookups)
467+ // Resolve brush once
469468 SolidColorBrush brush = BitmapHelper . SavedDominantColors . Count > 0
470469 ? BitmapHelper . SavedDominantColors . Last ( )
471470 : ( SolidColorBrush ) Application . Current . TryFindResource ( "MicaWPF.Brushes.SystemAccentColorTertiary" ) ;
@@ -479,124 +478,165 @@ private unsafe void DrawBars(int stride, Span<byte> buffer)
479478
480479 int centerY = ImageHeight / 2 ;
481480
482- // Layout calculation (float-based to avoid spacing drift)
483- float totalSpacing = ( BarCount - 1 ) * BarSpacing ;
484- float exactBarWidth = ( ImageWidth - totalSpacing ) / ( float ) BarCount ;
485- float totalBarsWidth = BarCount * exactBarWidth + totalSpacing ;
486- float offsetX = ( ImageWidth - totalBarsWidth ) * 0.5f ;
481+ // Horizontal layout
482+ ComputeLayout ( ImageWidth , BarCount , BarSpacing ,
483+ out int barWidth ,
484+ out int offsetX ) ;
485+
486+ // Radius
487+ float baseRadius = GetCornerRadius ( ) ;
488+
489+ // AA constants
490+ const float aa = 1.25f ;
491+ float invAA = 1f / aa ;
487492
488493 for ( int i = 0 ; i < BarCount ; i ++ )
489494 {
490- // Normalize and scale height
491- float normalizedValue = Math . Clamp ( _barValues [ i ] , 0f , 1f ) ;
492- int barHeight = Math . Max ( ( int ) ( normalizedValue * ImageHeight ) , barBaseline ) ;
495+ int barX = offsetX + i * ( barWidth + BarSpacing ) ;
493496
494- // Compute precise X bounds (prevents cumulative rounding errors)
495- ComputeBarBounds ( i , exactBarWidth , offsetX , out int barX , out int barWidth ) ;
497+ int barHeight = GetBarHeight ( _barValues [ i ] , barBaseline ) ;
496498
497- if ( barWidth <= 0 )
499+ if ( barHeight <= 0 )
498500 continue ;
499501
500- // Compute vertical bounds
501- ComputeBarVertical ( centeredBars , centerY , barHeight , out int barY , out int barEndY ) ;
502+ ComputeVertical ( centeredBars , centerY , barHeight , out int barY , out int barEndY ) ;
502503
503- // Precompute geometry
504- float radius = MathF . Min ( barWidth , barHeight ) * 0.5f ;
504+ // Clamp radius per bar
505+ float radius = ClampRadius ( baseRadius , barWidth , barHeight ) ;
506+ float radiusSq = radius * radius ;
505507
506- var geom = new BarGeometry ( barX , barWidth , barY , barEndY , radius ) ;
508+ RasterizeBar (
509+ buffer , stride ,
510+ barX , barWidth ,
511+ barY , barEndY ,
512+ centeredBars ,
513+ radius , radiusSq , invAA ,
514+ b , g , r ) ;
515+ }
516+ }
507517
508- // Precompute SDF constants
509- float aa = 1.25f ;
510- float invAA = 1f / aa ;
511- float radiusSq = radius * radius ;
518+ private static void ComputeLayout (
519+ int imageWidth ,
520+ int barCount ,
521+ int spacing ,
522+ out int barWidth ,
523+ out int offsetX )
524+ {
525+ int totalSpacing = ( barCount - 1 ) * spacing ;
526+
527+ int availableWidth = imageWidth - totalSpacing - 1 ;
528+
529+ barWidth = availableWidth / barCount ;
530+
531+ int usedWidth = barWidth * barCount + totalSpacing ;
532+
533+ // Center safely
534+ offsetX = ( imageWidth - usedWidth ) >> 1 ;
535+ }
512536
513- // Rasterize
514- RasterizeBar ( buffer , stride , geom , centeredBars , b , g , r , invAA , radiusSq ) ;
537+ private void ComputeVertical ( bool centered , int centerY , int height , out int y , out int endY )
538+ {
539+ if ( centered )
540+ {
541+ int half = height >> 1 ; // faster than /2
542+ y = centerY - half ;
543+ endY = centerY + half ;
515544 }
545+ else
546+ {
547+ y = ImageHeight - height ;
548+ endY = ImageHeight ;
549+ }
550+ }
551+
552+ private int GetBarHeight ( float value , int baseline )
553+ {
554+ return Math . Max ( ( int ) ( Math . Clamp ( value , 0f , 1f ) * ImageHeight ) , baseline ) ;
555+ }
556+ private static float GetCornerRadius ( )
557+ {
558+ return 6f / MathF . Max ( 1f , SettingsManager . Current . TaskbarVisualizerBarCount / 10f ) ;
559+ }
560+
561+ private static float ClampRadius ( float r , int width , int height )
562+ {
563+ float max = MathF . Min ( width , height ) * 0.5f ;
564+ return r > max ? max : r ;
516565 }
517566
518567 private unsafe void RasterizeBar (
519568 Span < byte > buffer ,
520569 int stride ,
521- BarGeometry g ,
570+ int barX ,
571+ int barWidth ,
572+ int barY ,
573+ int barEndY ,
522574 bool centeredBars ,
523- byte b , byte gr , byte r ,
575+ float radius ,
576+ float radiusSq ,
524577 float invAA ,
525- float radiusSq )
578+ byte b , byte g , byte r )
526579 {
527- for ( int y = ( int ) g . Top ; y < g . Bottom && y < ImageHeight && y >= 0 ; y ++ )
580+ float left = barX ;
581+ float right = barX + barWidth ;
582+ float top = barY ;
583+ float bottom = barEndY ;
584+
585+ float innerLeft = left + radius ;
586+ float innerRight = right - radius ;
587+ float innerTop = top + radius ;
588+ float innerBottom = bottom - radius ;
589+
590+ for ( int y = barY ; y < barEndY && y < ImageHeight && y >= 0 ; y ++ )
528591 {
529592 int row = y * stride ;
530593
531- for ( int x = ( int ) g . Left ; x < g . Right && x < ImageWidth ; x ++ )
594+ for ( int x = barX ; x < barX + barWidth && x < ImageWidth ; x ++ )
532595 {
533- int index = row + x * 4 ;
596+ int index = row + ( x << 2 ) ; // x * 4 (bitshift faster)
534597 if ( index + 3 >= buffer . Length )
535598 continue ;
536599
537- // Fast path: center rectangle
538- if ( x >= g . InnerLeft && x <= g . InnerRight )
600+ // CENTER
601+ if ( x >= innerLeft && x <= innerRight )
539602 {
540- WritePixel ( buffer , index , b , gr , r , 255 ) ;
603+ WritePixel ( buffer , index , b , g , r , 255 ) ;
541604 continue ;
542605 }
543606
544- // Fast path: vertical sides (no AA)
545- if ( y >= g . InnerTop && y <= g . InnerBottom )
607+ // SIDES
608+ if ( y >= innerTop && y <= innerBottom )
546609 {
547- WritePixel ( buffer , index , b , gr , r , 255 ) ;
610+ WritePixel ( buffer , index , b , g , r , 255 ) ;
548611 continue ;
549612 }
550613
551- // Flat bottom if not centered
552- if ( ! centeredBars && y >= g . InnerBottom )
614+ // FLAT BOTTOM
615+ if ( ! centeredBars && y >= innerBottom )
553616 {
554- WritePixel ( buffer , index , b , gr , r , 255 ) ;
617+ WritePixel ( buffer , index , b , g , r , 255 ) ;
555618 continue ;
556619 }
557620
558- // Rounded caps only
559- float cx = x < g . InnerLeft ? g . InnerLeft : ( x > g . InnerRight ? g . InnerRight : x ) ;
560- float cy = y < g . InnerTop ? g . InnerTop : ( y > g . InnerBottom ? g . InnerBottom : y ) ;
621+ // CORNERS
622+ float cx = x < innerLeft ? innerLeft : ( x > innerRight ? innerRight : x ) ;
623+ float cy = y < innerTop ? innerTop : ( y > innerBottom ? innerBottom : y ) ;
561624
562625 float dx = x - cx ;
563626 float dy = y - cy ;
564627
565628 float distSq = dx * dx + dy * dy ;
566- float sdf = ( distSq - radiusSq ) / ( 2f * MathF . Sqrt ( radiusSq ) ) ; // radius = sqrt(radiusSq)
629+ float sdf = ( distSq - radiusSq ) / ( 2f * radius ) ;
567630
568- float alpha = Math . Clamp ( 0.5f - sdf * invAA , 0f , 1f ) ;
631+ float alpha = 0.5f - sdf * invAA ;
569632
570633 if ( alpha <= 0f )
571634 continue ;
572635
573- WritePixel ( buffer , index , b , gr , r , ( byte ) ( 255 * alpha ) ) ;
574- }
575- }
576- }
577-
578- private void ComputeBarBounds ( int i , float width , float offsetX , out int x , out int barWidth )
579- {
580- float fx = offsetX + i * ( width + BarSpacing ) ;
581- float fxNext = fx + width ;
582-
583- x = ( int ) MathF . Round ( fx ) ;
584- int right = ( int ) MathF . Round ( fxNext ) ;
585- barWidth = right - x ;
586- }
636+ if ( alpha > 1f ) alpha = 1f ;
587637
588- private void ComputeBarVertical ( bool centered , int centerY , int height , out int y , out int endY )
589- {
590- if ( centered )
591- {
592- int half = height / 2 ;
593- y = centerY - half ;
594- endY = centerY + half ;
595- }
596- else
597- {
598- y = ImageHeight - height ;
599- endY = ImageHeight ;
638+ WritePixel ( buffer , index , b , g , r , ( byte ) ( 255 * alpha ) ) ;
639+ }
600640 }
601641 }
602642
0 commit comments