fix memory leaking

This commit is contained in:
Zhe Fang
2025-08-12 11:43:14 -04:00
parent 9fcb1ac869
commit 7b6eca6ff6
6 changed files with 294 additions and 499 deletions

View File

@@ -1,11 +1,19 @@
using Microsoft.Graphics.Canvas.Brushes;
using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Models;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.Effects;
using Microsoft.Graphics.Canvas.Text;
using Microsoft.Graphics.Canvas.UI.Xaml;
using Microsoft.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Graphics.Effects;
using Windows.UI;
namespace BetterLyrics.WinUI3.Helper
@@ -29,5 +37,264 @@ namespace BetterLyrics.WinUI3.Helper
EndPoint = new Vector2((float)(startX + width), 0),
};
}
/// <summary>
/// 背景层
/// </summary>
/// <param name="lyricsLayerOpacity">_lyricsOpacityTransition.Value</param>
public static OpacityEffect CreateBackgroundEffect(LyricsLine lyricsLine, CanvasCommandList backgroundFontEffect, double lyricsLayerOpacity)
{
return new OpacityEffect
{
Source = new GaussianBlurEffect
{
Source = backgroundFontEffect,
BlurAmount = (float)lyricsLine.BlurAmountTransition.Value,
BorderMode = EffectBorderMode.Soft,
Optimization = EffectOptimization.Speed,
},
Opacity = (float)(lyricsLine.OpacityTransition.Value * lyricsLayerOpacity),
};
}
public static CanvasCommandList CreateFontEffect(LyricsLine lyricsLine, ICanvasAnimatedControl control, Color strokeColor, int strokeWidth, Color fontColor)
{
CanvasCommandList list = new(control);
using var ds = list.CreateDrawingSession();
if (strokeWidth > 0)
{
ds.DrawGeometry(lyricsLine.TextGeometry, lyricsLine.Position, strokeColor, strokeWidth); // 描边
}
ds.FillGeometry(lyricsLine.TextGeometry, lyricsLine.Position, fontColor); // 填充
return list;
}
/// <summary>
/// 创建辉光效果层
/// 仅需在布局重构 (Relayout) 时调用
/// </summary>
/// <param name="lineRenderingType">_lyricsGlowEffectScope</param>
/// <param name="glowEffectAmount">_lyricsGlowEffectAmount</param>
public static GaussianBlurEffect CreateForegroundBlurEffect(CanvasCommandList foregroundFontEffect, IGraphicsEffectSource mask, double glowEffectAmount)
{
return new GaussianBlurEffect
{
Source = new AlphaMaskEffect
{
Source = foregroundFontEffect,
AlphaMask = mask,
},
BlurAmount = (float)glowEffectAmount,
Optimization = EffectOptimization.Speed,
};
}
/// <summary>
/// 仅当前播放行需要调用此方法(每次 Update 都调用一次)
/// </summary>
/// <param name="control"></param>
/// <param name="playingLineIndex"></param>
/// <param name="charStartIndex"></param>
/// <param name="charLength"></param>
/// <param name="charProgress"></param>
public static CanvasCommandList CreateCharMask(ICanvasAnimatedControl control, LyricsLine lyricsLine, int charStartIndex, int charLength, double charProgress)
{
var mask = new CanvasCommandList(control);
using var ds = mask.CreateDrawingSession();
if (lyricsLine.CanvasTextLayout == null)
{
return mask;
}
var highlightRegion = lyricsLine.CanvasTextLayout.GetCharacterRegions(charStartIndex, charLength).FirstOrDefault();
double highlightTotalWidth = (double)highlightRegion.LayoutBounds.Width;
// Draw the highlight for the current character
double highlightWidth = highlightTotalWidth * charProgress;
double fadingWidth = (double)highlightRegion.LayoutBounds.Height / 2;
// Rects
var highlightRect = new Rect(
highlightRegion.LayoutBounds.X,
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
highlightWidth,
highlightRegion.LayoutBounds.Height
);
var fadeInRect = new Rect(
highlightRect.Right - fadingWidth,
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
fadingWidth,
highlightRegion.LayoutBounds.Height
);
var fadeOutRect = new Rect(
highlightRect.Right,
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
fadingWidth,
highlightRegion.LayoutBounds.Height
);
// Brushes
using var fadeInBrush = CanvasHelper.CreateHorizontalFillBrush(
control,
[(0f, 0f), (1f, 1f)],
(double)highlightRect.Right - fadingWidth,
fadingWidth
);
using var fadeOutBrush = CanvasHelper.CreateHorizontalFillBrush(
control,
[(0f, 1f), (1f, 0f)],
(double)highlightRect.Right,
fadingWidth
);
ds.FillRectangle(fadeInRect, fadeInBrush);
ds.FillRectangle(fadeOutRect, fadeOutBrush);
return mask;
}
/// <summary>
/// 仅当前播放行需要调用此方法(每次 Update 都调用一次)
/// </summary>
/// <param name="control"></param>
/// <param name="playingLineIndex"></param>
/// <param name="charStartIndex"></param>
/// <param name="charLength"></param>
/// <param name="charProgress"></param>
public static CanvasCommandList CreateLineStartToCharMask(ICanvasAnimatedControl control, LyricsLine lyricsLine, int charStartIndex, int charLength, double charProgress)
{
var mask = new CanvasCommandList(control);
if (lyricsLine.CanvasTextLayout == null)
{
return mask;
}
using var ds = mask.CreateDrawingSession();
var regions = lyricsLine.CanvasTextLayout.GetCharacterRegions(0, charStartIndex);
var highlightRegion = lyricsLine.CanvasTextLayout
.GetCharacterRegions(charStartIndex, charLength)
.FirstOrDefault();
if (regions.Length > 0)
{
// Draw the mask for the current line
for (int j = 0; j < regions.Length; j++)
{
var region = regions[j];
var rect = new Rect(
region.LayoutBounds.X,
region.LayoutBounds.Y + lyricsLine.Position.Y,
region.LayoutBounds.Width,
region.LayoutBounds.Height
);
ds.FillRectangle(rect, Color.FromArgb(255, 128, 128, 128));
}
}
double highlightTotalWidth = (double)highlightRegion.LayoutBounds.Width;
// Draw the highlight for the current character
double highlightWidth = highlightTotalWidth * charProgress;
double fadingWidth = (double)highlightRegion.LayoutBounds.Height / 2;
// Rects
var highlightRect = new Rect(
highlightRegion.LayoutBounds.X,
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
highlightWidth,
highlightRegion.LayoutBounds.Height
);
var fadeInRect = new Rect(
highlightRect.Right - fadingWidth,
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
fadingWidth,
highlightRegion.LayoutBounds.Height
);
var fadeOutRect = new Rect(
highlightRect.Right,
highlightRegion.LayoutBounds.Y + lyricsLine.Position.Y,
fadingWidth,
highlightRegion.LayoutBounds.Height
);
// Brushes
using var fadeOutBrush = CanvasHelper.CreateHorizontalFillBrush(
control,
[(0f, 1f), (1f, 0f)],
(double)highlightRect.Right,
fadingWidth
);
ds.FillRectangle(highlightRect, Color.FromArgb(255, 128, 128, 128));
ds.FillRectangle(fadeOutRect, fadeOutBrush);
return mask;
}
/// <summary>
/// 创建行遮罩
/// 仅需在布局重构 (Relayout) 时调用
/// </summary>
/// <param name="control"></param>
public static CanvasCommandList CreateLineMask(ICanvasAnimatedControl control, LyricsLine lyricsLine)
{
var mask = new CanvasCommandList(control);
using var ds = mask.CreateDrawingSession();
if (lyricsLine.CanvasTextLayout == null)
{
return mask;
}
var regions = lyricsLine.CanvasTextLayout.GetCharacterRegions(0, lyricsLine.OriginalText.Length);
if (regions.Length > 0)
{
for (int j = 0; j < regions.Length; j++)
{
var region = regions[j];
var rect = new Rect(
region.LayoutBounds.X,
region.LayoutBounds.Y + lyricsLine.Position.Y,
region.LayoutBounds.Width,
region.LayoutBounds.Height
);
ds.FillRectangle(rect, Colors.White);
}
}
return mask;
}
/// <summary>
/// 创建高亮效果层
/// 仅需在布局重构 (Relayout) 时调用
/// </summary>
/// <param name="control"></param>
/// <param name="lineRenderingType"></param>
public static AlphaMaskEffect CreateForegroundHighlightEffect(CanvasCommandList foregroundFontEffect, IGraphicsEffectSource mask)
{
return new AlphaMaskEffect
{
Source = foregroundFontEffect,
AlphaMask = mask,
};
}
public static IGraphicsEffectSource GetAlphaMask(ICanvasAnimatedControl control, IGraphicsEffectSource charMask, IGraphicsEffectSource lineStartToCharMask, IGraphicsEffectSource lineMask, LineRenderingType lineRenderingType)
{
var result = lineRenderingType switch
{
LineRenderingType.CurrentChar => charMask,
LineRenderingType.LineStartToCurrentChar => lineStartToCharMask,
LineRenderingType.CurrentLine => lineMask,
_ => new CanvasCommandList(control),
};
return result;
}
}
}

View File

@@ -69,39 +69,6 @@ namespace BetterLyrics.WinUI3.Models
public CanvasGeometry? TextGeometry { get; private set; }
/// <summary>
/// 背景文字层(底字)
/// </summary>
public CanvasCommandList? BackgroundFontEffect { get; private set; }
/// <summary>
/// 背景层
/// </summary>
public OpacityEffect? BackgroundEffect { get; private set; }
/// <summary>
/// 辉光层
/// </summary>
public GaussianBlurEffect? ForegroundBlurEffect { get; private set; }
/// <summary>
/// 高亮层
/// </summary>
public AlphaMaskEffect? ForegroundHighlightEffect { get; private set; }
/// <summary>
/// 前景文字层
/// </summary>
public CanvasCommandList? ForegroundFontEffect { get; private set; }
public CanvasCommandList? ComposedLineEffect { get; private set; }
public CanvasCommandList? CurrentCharMask { get; private set; }
public CanvasCommandList? LineStartToCurrentCharMask { get; private set; }
public CanvasCommandList? CurrentLineMask { get; private set; }
public CanvasCommandList? PlaceholderEffect { get; private set; }
public void UpdateCenterPosition(double maxWidth, TextAlignmentType type)
{
if (CanvasTextLayout == null)
@@ -146,418 +113,5 @@ namespace BetterLyrics.WinUI3.Models
}
TextGeometry = CanvasGeometry.CreateText(CanvasTextLayout);
}
public void DisposeFontEffects()
{
BackgroundFontEffect?.Dispose();
BackgroundFontEffect = null;
ForegroundFontEffect?.Dispose();
ForegroundFontEffect = null;
}
public void RecreateFontEffect(ICanvasAnimatedControl control, Color strokeColor, int strokeWidth, Color bgFontColor, Color fgFontColor)
{
DisposeFontEffects();
if (TextGeometry == null)
{
return;
}
BackgroundFontEffect = new CanvasCommandList(control);
using var bgFontEffectDs = BackgroundFontEffect.CreateDrawingSession();
ForegroundFontEffect = new CanvasCommandList(control);
using var fgFontEffectDs = ForegroundFontEffect.CreateDrawingSession();
// 大于 0 才描边,避免不必要的资源浪费
if (strokeWidth > 0)
{
bgFontEffectDs.DrawGeometry(TextGeometry, Position, strokeColor, strokeWidth); // 描边
fgFontEffectDs.DrawGeometry(TextGeometry, Position, strokeColor, strokeWidth); // 描边
}
bgFontEffectDs.FillGeometry(TextGeometry, Position, bgFontColor); // 填充
fgFontEffectDs.FillGeometry(TextGeometry, Position, fgFontColor); // 填充
}
/// <summary>
/// 背景层
/// </summary>
/// <param name="lyricsLayerOpacity">_lyricsOpacityTransition.Value</param>
public void RecreateBackgroundEffect(double lyricsLayerOpacity)
{
BackgroundEffect?.Dispose();
BackgroundEffect = null;
if (BackgroundFontEffect == null)
{
return;
}
BackgroundEffect = new OpacityEffect
{
Source = new GaussianBlurEffect
{
Source = BackgroundFontEffect,
BlurAmount = (float)BlurAmountTransition.Value,
BorderMode = EffectBorderMode.Soft,
Optimization = EffectOptimization.Speed,
},
Opacity = (float)(OpacityTransition.Value * lyricsLayerOpacity),
};
}
public void UpdateBackgroundEffect(double lyricsLayerOpacity)
{
BackgroundEffect?.Opacity = (float)(OpacityTransition.Value * lyricsLayerOpacity);
GaussianBlurEffect? blurEffect = (GaussianBlurEffect?)(BackgroundEffect?.Source);
blurEffect?.BlurAmount = (float)BlurAmountTransition.Value;
}
private IGraphicsEffectSource GetAlphaMask(ICanvasAnimatedControl control, LineRenderingType lineRenderingType)
{
if (PlaceholderEffect == null)
{
RecreatePlaceholder(control);
}
var result = lineRenderingType switch
{
LineRenderingType.CurrentChar => CurrentCharMask,
LineRenderingType.LineStartToCurrentChar => LineStartToCurrentCharMask,
LineRenderingType.CurrentLine => CurrentLineMask,
_ => PlaceholderEffect
};
return result ?? PlaceholderEffect!;
}
public void DisposeForegroundBlurEffect()
{
ForegroundBlurEffect?.Dispose();
ForegroundBlurEffect = null;
}
/// <summary>
/// 销毁并重新创建辉光效果层
/// 仅需在布局重构 (Relayout) 时调用
/// </summary>
/// <param name="lineRenderingType">_lyricsGlowEffectScope</param>
/// <param name="glowEffectAmount">_lyricsGlowEffectAmount</param>
public void RecreateForegroundBlurEffect(ICanvasAnimatedControl control, LineRenderingType lineRenderingType, double glowEffectAmount)
{
DisposeForegroundBlurEffect();
if (ForegroundFontEffect == null)
{
return;
}
var mask = GetAlphaMask(control, lineRenderingType);
if (mask == null)
{
return;
}
ForegroundBlurEffect = new GaussianBlurEffect
{
Source = new AlphaMaskEffect
{
Source = ForegroundFontEffect,
AlphaMask = mask,
},
BlurAmount = (float)glowEffectAmount,
Optimization = EffectOptimization.Speed,
};
}
/// <summary>
/// 仅当前行需要调用此方法(每次 Update 都调用一次)
/// </summary>
/// <param name="control"></param>
/// <param name="lineRenderingType"></param>
/// <param name="glowEffectAmount"></param>
public void UpdateForegroundBlurEffect(ICanvasAnimatedControl control, LineRenderingType lineRenderingType, double glowEffectAmount)
{
if (ForegroundBlurEffect == null)
{
return;
}
if (ForegroundFontEffect == null)
{
return;
}
var mask = GetAlphaMask(control, lineRenderingType);
if (mask == null)
{
return;
}
ForegroundBlurEffect.BlurAmount = (float)glowEffectAmount;
var alphaMaskEffect = (AlphaMaskEffect)ForegroundBlurEffect.Source;
alphaMaskEffect.Source = ForegroundFontEffect;
alphaMaskEffect.AlphaMask = mask;
}
public void DisposeForegroundHighlightEffect()
{
ForegroundHighlightEffect?.Dispose();
ForegroundHighlightEffect = null;
}
/// <summary>
/// 销毁并重新创建高亮效果层
/// 仅需在布局重构 (Relayout) 时调用
/// </summary>
/// <param name="control"></param>
/// <param name="lineRenderingType"></param>
public void RecreateForegroundHighlightEffect(ICanvasAnimatedControl control, LineRenderingType lineRenderingType)
{
DisposeForegroundHighlightEffect();
if (ForegroundFontEffect == null)
{
return;
}
var mask = GetAlphaMask(control, lineRenderingType);
if (mask == null)
{
return;
}
ForegroundHighlightEffect = new AlphaMaskEffect
{
Source = ForegroundFontEffect,
AlphaMask = mask,
};
}
/// <summary>
/// 仅当前行需要调用此方法(每次 Update 都调用一次)
/// </summary>
/// <param name="control"></param>
/// <param name="lineRenderingType"></param>
public void UpdateForegroundHighlightEffect(ICanvasAnimatedControl control, LineRenderingType lineRenderingType)
{
if (ForegroundHighlightEffect == null)
{
return;
}
if (ForegroundFontEffect == null)
{
return;
}
var mask = GetAlphaMask(control, lineRenderingType);
if (mask == null)
{
return;
}
ForegroundHighlightEffect.Source = ForegroundFontEffect;
ForegroundHighlightEffect.AlphaMask = mask;
}
public void DisposeCurrentCharMask()
{
CurrentCharMask?.Dispose();
CurrentCharMask = null;
}
/// <summary>
/// 仅当前播放行需要调用此方法(每次 Update 都调用一次)
/// </summary>
/// <param name="control"></param>
/// <param name="playingLineIndex"></param>
/// <param name="charStartIndex"></param>
/// <param name="charLength"></param>
/// <param name="charProgress"></param>
public void RecreateCurrentCharMask(ICanvasAnimatedControl control, int charStartIndex, int charLength, double charProgress)
{
DisposeCurrentCharMask();
if (CanvasTextLayout == null)
{
return;
}
CurrentCharMask = new CanvasCommandList(control);
using var ds = CurrentCharMask.CreateDrawingSession();
var highlightRegion = CanvasTextLayout
.GetCharacterRegions(charStartIndex, charLength)
.FirstOrDefault();
double highlightTotalWidth = (double)highlightRegion.LayoutBounds.Width;
// Draw the highlight for the current character
double highlightWidth = highlightTotalWidth * charProgress;
double fadingWidth = (double)highlightRegion.LayoutBounds.Height / 2;
// Rects
var highlightRect = new Rect(
highlightRegion.LayoutBounds.X,
highlightRegion.LayoutBounds.Y + Position.Y,
highlightWidth,
highlightRegion.LayoutBounds.Height
);
var fadeInRect = new Rect(
highlightRect.Right - fadingWidth,
highlightRegion.LayoutBounds.Y + Position.Y,
fadingWidth,
highlightRegion.LayoutBounds.Height
);
var fadeOutRect = new Rect(
highlightRect.Right,
highlightRegion.LayoutBounds.Y + Position.Y,
fadingWidth,
highlightRegion.LayoutBounds.Height
);
// Brushes
using var fadeInBrush = CanvasHelper.CreateHorizontalFillBrush(
control,
[(0f, 0f), (1f, 1f)],
(double)highlightRect.Right - fadingWidth,
fadingWidth
);
using var fadeOutBrush = CanvasHelper.CreateHorizontalFillBrush(
control,
[(0f, 1f), (1f, 0f)],
(double)highlightRect.Right,
fadingWidth
);
ds.FillRectangle(fadeInRect, fadeInBrush);
ds.FillRectangle(fadeOutRect, fadeOutBrush);
}
public void DisposeLineStartToCurrentCharMask()
{
LineStartToCurrentCharMask?.Dispose();
LineStartToCurrentCharMask = null;
}
/// <summary>
/// 仅当前播放行需要调用此方法(每次 Update 都调用一次)
/// </summary>
/// <param name="control"></param>
/// <param name="playingLineIndex"></param>
/// <param name="charStartIndex"></param>
/// <param name="charLength"></param>
/// <param name="charProgress"></param>
public void RecreateLineStartToCurrentCharMask(ICanvasAnimatedControl control, int charStartIndex, int charLength, double charProgress)
{
DisposeLineStartToCurrentCharMask();
if (CanvasTextLayout == null)
{
return;
}
LineStartToCurrentCharMask = new CanvasCommandList(control);
using var ds = LineStartToCurrentCharMask.CreateDrawingSession();
var regions = CanvasTextLayout.GetCharacterRegions(0, charStartIndex);
var highlightRegion = CanvasTextLayout
.GetCharacterRegions(charStartIndex, charLength)
.FirstOrDefault();
if (regions.Length > 0)
{
// Draw the mask for the current line
for (int j = 0; j < regions.Length; j++)
{
var region = regions[j];
var rect = new Rect(
region.LayoutBounds.X,
region.LayoutBounds.Y + Position.Y,
region.LayoutBounds.Width,
region.LayoutBounds.Height
);
ds.FillRectangle(rect, Color.FromArgb(255, 128, 128, 128));
}
}
double highlightTotalWidth = (double)highlightRegion.LayoutBounds.Width;
// Draw the highlight for the current character
double highlightWidth = highlightTotalWidth * charProgress;
double fadingWidth = (double)highlightRegion.LayoutBounds.Height / 2;
// Rects
var highlightRect = new Rect(
highlightRegion.LayoutBounds.X,
highlightRegion.LayoutBounds.Y + Position.Y,
highlightWidth,
highlightRegion.LayoutBounds.Height
);
var fadeInRect = new Rect(
highlightRect.Right - fadingWidth,
highlightRegion.LayoutBounds.Y + Position.Y,
fadingWidth,
highlightRegion.LayoutBounds.Height
);
var fadeOutRect = new Rect(
highlightRect.Right,
highlightRegion.LayoutBounds.Y + Position.Y,
fadingWidth,
highlightRegion.LayoutBounds.Height
);
// Brushes
using var fadeOutBrush = CanvasHelper.CreateHorizontalFillBrush(
control,
[(0f, 1f), (1f, 0f)],
(double)highlightRect.Right,
fadingWidth
);
ds.FillRectangle(highlightRect, Color.FromArgb(255, 128, 128, 128));
ds.FillRectangle(fadeOutRect, fadeOutBrush);
}
public void DisposeCurrentLineMask()
{
CurrentLineMask?.Dispose();
CurrentLineMask = null;
}
/// <summary>
/// 重建当前行遮罩
/// 仅需在布局重构 (Relayout) 时调用
/// </summary>
/// <param name="control"></param>
public void RecreateCurrentLineMask(ICanvasAnimatedControl control)
{
DisposeCurrentLineMask();
if (CanvasTextLayout == null)
{
return;
}
CurrentLineMask = new CanvasCommandList(control);
using var ds = CurrentLineMask.CreateDrawingSession();
var regions = CanvasTextLayout.GetCharacterRegions(0, OriginalText.Length);
if (regions.Length > 0)
{
for (int j = 0; j < regions.Length; j++)
{
var region = regions[j];
var rect = new Rect(
region.LayoutBounds.X,
region.LayoutBounds.Y + Position.Y,
region.LayoutBounds.Width,
region.LayoutBounds.Height
);
ds.FillRectangle(rect, Colors.White);
}
}
}
public void DisposePlaceholder()
{
PlaceholderEffect?.Dispose();
PlaceholderEffect = null;
}
public void RecreatePlaceholder(ICanvasAnimatedControl control)
{
DisposePlaceholder();
PlaceholderEffect = new CanvasCommandList(control);
}
}
}

View File

@@ -150,6 +150,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
opacityDs.DrawImage(new ShadowEffect
{
Source = albumArt,
ShadowColor = _grayedEnvironmentalColor,
BlurAmount = _settingsService.AppSettings.AlbumArtLayoutSettings.CoverImageShadowAmount,
Optimization = EffectOptimization.Speed,
});
@@ -237,7 +238,8 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
* Matrix3x2.CreateRotation((float)line.AngleTransition.Value, currentPlayingLine.Position)
* Matrix3x2.CreateTranslation((float)_lyricsXTransition.Value, (float)yOffset);
if (line.BackgroundFontEffect == null || line.ForegroundFontEffect == null) continue;
using var backgroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor, _lyricsStyleSettings.LyricsFontStrokeWidth, _bgFontColor);
using var foregroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor, _lyricsStyleSettings.LyricsFontStrokeWidth, _bgFontColor);
using var combined = new CanvasCommandList(control.Device);
using var combinedDs = combined.CreateDrawingSession();
@@ -245,21 +247,29 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
// Mock gradient blurred lyrics layer
// 先铺一层带默认透明度的已经加了模糊效果的歌词作为最底层(背景歌词层次)
// Current line will not be blurred
combinedDs.DrawImage(line.BackgroundEffect);
using var backgroundEffect = CanvasHelper.CreateBackgroundEffect(line, backgroundFontEffect, _lyricsOpacityTransition.Value);
combinedDs.DrawImage(backgroundEffect);
if (line.HighlightOpacityTransition.Value != 0)
{
if (line.ForegroundBlurEffect == null || line.ForegroundHighlightEffect == null || line.PlaceholderEffect == null)
{
return;
}
GetLinePlayingProgress(i, out int charStartIndex, out int charLength, out double charProgress);
using var charMask = CanvasHelper.CreateCharMask(control, line, charStartIndex, charLength, charProgress);
using var lineStartToCharMask = CanvasHelper.CreateLineStartToCharMask(control, line, charStartIndex, charLength, charProgress);
using var lineMask = CanvasHelper.CreateLineMask(control, line);
var blurEffectMask = CanvasHelper.GetAlphaMask(control, charMask, lineStartToCharMask, lineMask, _lyricsEffectSettings.LyricsGlowEffectScope);
var highlightEffectMask = CanvasHelper.GetAlphaMask(control, charMask, lineStartToCharMask, lineMask, _lyricsEffectSettings.LyricsHighlightScope);
using var foregroundBlurEffect = CanvasHelper.CreateForegroundBlurEffect(foregroundFontEffect, blurEffectMask, _lyricsGlowEffectAmount);
using var foregroundHighlightEffect = CanvasHelper.CreateForegroundHighlightEffect(foregroundFontEffect, highlightEffectMask);
using var opacityEffect = new OpacityEffect
{
Source = new BlendEffect
{
Background = _lyricsEffectSettings.IsLyricsGlowEffectEnabled ? line.ForegroundBlurEffect : line.PlaceholderEffect,
Foreground = line.ForegroundHighlightEffect,
Background = _lyricsEffectSettings.IsLyricsGlowEffectEnabled ? foregroundBlurEffect : new CanvasCommandList(control),
Foreground = foregroundHighlightEffect,
},
Opacity = (float)(line.HighlightOpacityTransition.Value * _lyricsOpacityTransition.Value),
};
@@ -268,12 +278,12 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
if (i == _playingLineIndex)
{
if (_lyricsEffectSettings.IsLyricsFloatAnimationEnabled && line.LineStartToCurrentCharMask != null)
if (_lyricsEffectSettings.IsLyricsFloatAnimationEnabled)
{
ds.DrawImage(new DisplacementMapEffect
{
Source = combined,
Displacement = line.LineStartToCurrentCharMask,
Displacement = lineStartToCharMask,
XChannelSelect = EffectChannelSelect.Red,
YChannelSelect = EffectChannelSelect.Alpha,
Amount = 1f,

View File

@@ -261,7 +261,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
UpdateVisibleLinesBoundary();
UpdateAllLinesProps(control);
UpdateVisibleLinesProps(control);
_isLayoutChanged = false;
@@ -306,7 +305,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
_lyricsTextFormat.FontSize = _lyricsStyleSettings.LyricsFontSize;
_lyricsTextFormat.FontWeight = _lyricsStyleSettings.LyricsFontWeight.ToFontWeight();
// TODOFontFamily 无法设置
_lyricsTextFormat.FontFamily = _artistTextFormat.FontFamily = _titleTextFormat.FontFamily = _lyricsStyleSettings.LyricsFontFamily;
_canvasYScrollTransition.SetDuration(_lyricsEffectSettings.LyricsScrollDuration / 1000.0);
@@ -324,18 +322,11 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
continue;
}
line.RecreatePlaceholder(control);
line.Position = new Vector2(0, (float)y);
line.RecreateTextLayout(control, _lyricsTextFormat, _maxLyricsWidth, _canvasHeight, _lyricsStyleSettings.LyricsAlignmentType);
line.UpdateCenterPosition(_maxLyricsWidth, _lyricsStyleSettings.LyricsAlignmentType);
line.RecreateTextGeometry();
line.RecreateFontEffect(control, _strokeFontColor, _lyricsStyleSettings.LyricsFontStrokeWidth, _bgFontColor, _fgFontColor);
line.RecreateBackgroundEffect(_lyricsOpacityTransition.Value);
line.RecreateCurrentLineMask(control);
line.RecreateForegroundBlurEffect(control, _lyricsEffectSettings.LyricsGlowEffectScope, _lyricsGlowEffectAmount);
line.RecreateForegroundHighlightEffect(control, _lyricsEffectSettings.LyricsHighlightScope);
y +=
(double)line.CanvasTextLayout!.LayoutBounds.Height
@@ -447,7 +438,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
}
double brightness;
Color grayedEnvironmentalColor = Colors.Transparent;
bool isLight = ThemeTypeSent switch
{
@@ -461,14 +451,14 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
{
_adaptiveGrayedFontColor = _darkColor;
brightness = 0.7f;
grayedEnvironmentalColor = _lightColor;
_grayedEnvironmentalColor = _lightColor;
_albumArtAccentColorTransition.StartTransition(_albumArtLightAccentColor);
}
else
{
_adaptiveGrayedFontColor = _lightColor;
brightness = 0.3f;
grayedEnvironmentalColor = _darkColor;
_grayedEnvironmentalColor = _darkColor;
_albumArtAccentColorTransition.StartTransition(_albumArtDarkAccentColor);
}
@@ -523,7 +513,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
switch (_lyricsStyleSettings.LyricsStrokeFontColorType)
{
case LyricsFontColorType.AdaptiveGrayed:
_strokeFontColor = grayedEnvironmentalColor.WithBrightness(0.7);
_strokeFontColor = _grayedEnvironmentalColor.WithBrightness(0.7);
break;
case LyricsFontColorType.AdaptiveColored:
_strokeFontColor = _environmentalColor.WithBrightness(0.7);
@@ -552,24 +542,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
if (line == null) continue;
line.UpdateBackgroundEffect(_lyricsOpacityTransition.Value);
if (i == _playingLineIndex)
{
GetLinePlayingProgress(
_playingLineIndex,
out int charStartIndex,
out int charLength,
out double charProgress
);
line.RecreateCurrentCharMask(control, charStartIndex, charLength, charProgress);
line.RecreateLineStartToCurrentCharMask(control, charStartIndex, charLength, charProgress);
line.UpdateForegroundBlurEffect(control, _lyricsEffectSettings.LyricsGlowEffectScope, _lyricsGlowEffectAmount);
line.UpdateForegroundHighlightEffect(control, _lyricsEffectSettings.LyricsHighlightScope);
}
if (_isLayoutChanged || _isPlayingLineChanged)
{
int lineCountDelta = i - _playingLineIndex;
@@ -618,15 +590,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
}
}
private void UpdateAllLinesProps(ICanvasAnimatedControl control)
{
for (int i = 0; i < _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.Count; i++)
{
var line = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(i);
if (line == null) continue;
}
}
private void UpdateImmersiveBackgroundOpacity()
{
double targetOpacity;

View File

@@ -115,6 +115,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
private Color _albumArtLightAccentColor = Colors.Transparent;
private Color _albumArtDarkAccentColor = Colors.Transparent;
private Color _environmentalColor = Colors.Transparent;
private Color _grayedEnvironmentalColor = Colors.Transparent;
private Color _lightColor = Colors.White;
private Color _darkColor = Colors.Black;

View File

@@ -116,7 +116,7 @@ namespace BetterLyrics.WinUI3
{
DockModeHelper.UpdateAppBarHeight(hwnd, _dockMonitorDeviceName, 0, _dockPlacement);
}
window.Minimize();
window.Hide();
}
else
{
@@ -124,7 +124,7 @@ namespace BetterLyrics.WinUI3
{
DockModeHelper.UpdateAppBarHeight(hwnd, _dockMonitorDeviceName, _dockWindowHeight, _dockPlacement);
}
window.Restore();
window.Show();
}
}
}