This commit is contained in:
Zhe Fang
2025-08-18 10:51:37 -04:00
parent 516d388009
commit 94e76a6ac9
9 changed files with 124 additions and 19 deletions

View File

@@ -234,14 +234,46 @@
<ToggleSwitch IsOn="{x:Bind LyricsEffectSettings.IsLyricsLineFadeEnabled, Mode=TwoWay}" />
</controls:SettingsCard>
<!-- 高亮 -->
<controls:SettingsCard x:Uid="SettingsPageLyricsHighlightScope" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=&#xE7E6;}">
<!-- 译文高亮 -->
<controls:SettingsExpander
x:Uid="SettingsPageLyricsTranslationHighlight"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
Glyph=&#xE7E6;}"
IsExpanded="True">
<controls:SettingsExpander.Items>
<controls:SettingsCard x:Uid="SettingsPageAmount">
<local:ExtendedSlider
Default="60"
Frequency="5"
Maximum="100"
Minimum="0"
Value="{x:Bind LyricsEffectSettings.LyricsTranslationHighlightAmount, Mode=TwoWay}" />
</controls:SettingsCard>
</controls:SettingsExpander.Items>
</controls:SettingsExpander>
<!-- 原文高亮 -->
<controls:SettingsExpander
x:Uid="SettingsPageLyricsHighlightScope"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
Glyph=&#xE7E6;}"
IsExpanded="True">
<ComboBox SelectedIndex="{x:Bind LyricsEffectSettings.LyricsHighlightScope, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentChar" />
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeLineStartToCurrentChar" />
<ComboBoxItem x:Uid="SettingsPageLyricsRendingScopeCurrentLine" />
</ComboBox>
</controls:SettingsCard>
<controls:SettingsExpander.Items>
<controls:SettingsCard x:Uid="SettingsPageAmount">
<local:ExtendedSlider
Default="100"
Frequency="5"
Maximum="100"
Minimum="0"
Value="{x:Bind LyricsEffectSettings.LyricsHighlightAmount, Mode=TwoWay}" />
</controls:SettingsCard>
</controls:SettingsExpander.Items>
</controls:SettingsExpander>
<!-- 阴影 -->
<controls:SettingsExpander

View File

@@ -262,17 +262,50 @@ namespace BetterLyrics.WinUI3.Helper
return mask;
}
public static CanvasCommandList CreateTranslationHighlightMask(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(lyricsLine.OriginalText.Length, lyricsLine.DisplayedText.Length - 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>
/// 创建高亮效果层
/// </summary>
/// <param name="control"></param>
/// <param name="lineRenderingType"></param>
public static AlphaMaskEffect CreateForegroundHighlightEffect(CanvasCommandList foregroundFontEffect, IGraphicsEffectSource mask)
public static OpacityEffect CreateForegroundHighlightEffect(CanvasCommandList foregroundFontEffect, IGraphicsEffectSource mask, double opacity)
{
return new AlphaMaskEffect
return new OpacityEffect
{
Source = foregroundFontEffect,
AlphaMask = mask,
Source = new AlphaMaskEffect
{
Source = foregroundFontEffect,
AlphaMask = mask,
},
Opacity = (float)opacity,
};
}
@@ -291,6 +324,19 @@ namespace BetterLyrics.WinUI3.Helper
};
}
public static OpacityEffect CreateForegroundTranslationEffect(CanvasCommandList foregroundFontEffect, IGraphicsEffectSource mask, double opacity)
{
return new OpacityEffect
{
Source = new AlphaMaskEffect
{
Source = foregroundFontEffect,
AlphaMask = mask,
},
Opacity = (float)opacity,
};
}
public static IGraphicsEffectSource GetAlphaMask(ICanvasAnimatedControl control, IGraphicsEffectSource charMask, IGraphicsEffectSource lineStartToCharMask, IGraphicsEffectSource lineMask, LineRenderingType lineRenderingType)
{
var result = lineRenderingType switch

View File

@@ -23,7 +23,10 @@ namespace BetterLyrics.WinUI3.Models.Settings
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsShadowAmount { get; set; } = 8;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LineRenderingType LyricsHighlightScope { get; set; } = LineRenderingType.LineStartToCurrentChar;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsHighlightAmount { get; set; } = 100; // 100% 是上界
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsTranslationHighlightAmount { get; set; } = 60; // 100% 是上界
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLyricsFloatAnimationEnabled { get; set; } = true;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int LyricsFloatAmount { get; set; } = 1;

View File

@@ -779,7 +779,7 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
<value>Glow effect</value>
</data>
<data name="SettingsPageLyricsHighlightScope.Header" xml:space="preserve">
<value>Highlight scope</value>
<value>Original highlight range</value>
</data>
<data name="SettingsPageLyricsLeft.Content" xml:space="preserve">
<value>Left</value>
@@ -844,6 +844,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
<data name="SettingsPageLyricsTimelineThreshold.Header" xml:space="preserve">
<value>Lyrics timeline sync threshold</value>
</data>
<data name="SettingsPageLyricsTranslationHighlight.Header" xml:space="preserve">
<value>Translation Highlight</value>
</data>
<data name="SettingsPageLyricsTranslationSeparator.Header" xml:space="preserve">
<value>Source and translation separator</value>
</data>

View File

@@ -779,7 +779,7 @@
<value>グロー効果</value>
</data>
<data name="SettingsPageLyricsHighlightScope.Header" xml:space="preserve">
<value>ハイライトスコープ</value>
<value>オリジナルのハイライト範囲</value>
</data>
<data name="SettingsPageLyricsLeft.Content" xml:space="preserve">
<value>左</value>
@@ -844,6 +844,9 @@
<data name="SettingsPageLyricsTimelineThreshold.Header" xml:space="preserve">
<value>歌詞タイムライン同期しきい値</value>
</data>
<data name="SettingsPageLyricsTranslationHighlight.Header" xml:space="preserve">
<value>翻訳ハイライト</value>
</data>
<data name="SettingsPageLyricsTranslationSeparator.Header" xml:space="preserve">
<value>ソースおよび翻訳セパレーター</value>
</data>

View File

@@ -779,7 +779,7 @@
<value>글로우 효과</value>
</data>
<data name="SettingsPageLyricsHighlightScope.Header" xml:space="preserve">
<value>하이라이트 범위</value>
<value>원래 하이라이트 범위</value>
</data>
<data name="SettingsPageLyricsLeft.Content" xml:space="preserve">
<value>왼쪽</value>
@@ -844,6 +844,9 @@
<data name="SettingsPageLyricsTimelineThreshold.Header" xml:space="preserve">
<value>가사 타임 라인 동기화 임계 값</value>
</data>
<data name="SettingsPageLyricsTranslationHighlight.Header" xml:space="preserve">
<value>번역 하이라이트</value>
</data>
<data name="SettingsPageLyricsTranslationSeparator.Header" xml:space="preserve">
<value>소스 및 번역 분리기</value>
</data>

View File

@@ -779,7 +779,7 @@
<value>辉光效果</value>
</data>
<data name="SettingsPageLyricsHighlightScope.Header" xml:space="preserve">
<value>高亮显示范围</value>
<value>原文高亮显示范围</value>
</data>
<data name="SettingsPageLyricsLeft.Content" xml:space="preserve">
<value>靠左</value>
@@ -844,6 +844,9 @@
<data name="SettingsPageLyricsTimelineThreshold.Header" xml:space="preserve">
<value>歌词时间轴同步阈值</value>
</data>
<data name="SettingsPageLyricsTranslationHighlight.Header" xml:space="preserve">
<value>翻译高亮</value>
</data>
<data name="SettingsPageLyricsTranslationSeparator.Header" xml:space="preserve">
<value>原文译文分隔符</value>
</data>

View File

@@ -779,7 +779,7 @@
<value>輝光效果</value>
</data>
<data name="SettingsPageLyricsHighlightScope.Header" xml:space="preserve">
<value>高亮顯示範圍</value>
<value>原文高亮顯示範圍</value>
</data>
<data name="SettingsPageLyricsLeft.Content" xml:space="preserve">
<value>靠左</value>
@@ -844,6 +844,9 @@
<data name="SettingsPageLyricsTimelineThreshold.Header" xml:space="preserve">
<value>歌詞時間軌同步閾值</value>
</data>
<data name="SettingsPageLyricsTranslationHighlight.Header" xml:space="preserve">
<value>翻譯高亮</value>
</data>
<data name="SettingsPageLyricsTranslationSeparator.Header" xml:space="preserve">
<value>原文譯文分隔符</value>
</data>

View File

@@ -234,9 +234,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
using var combined = new CanvasCommandList(control);
using var combinedDs = combined.CreateDrawingSession();
// Mock gradient blurred lyrics layer
// 先铺一层带默认透明度的已经加了模糊效果的歌词作为最底层(背景歌词层次)
// Current line will not be blurred
using var backgroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor,
_liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsFontStrokeWidth, _bgFontColor);
using var backgroundEffect = CanvasHelper.CreateBackgroundEffect(line, backgroundFontEffect, _lyricsOpacityTransition.Value);
@@ -253,10 +251,17 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
using var lineMask = CanvasHelper.CreateLineMask(control, line);
using var foregroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor,
_liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsFontStrokeWidth, _bgFontColor);
_liveStatesService.LiveStates.CurrentLyricsStyleSettings.LyricsFontStrokeWidth, _fgFontColor);
using var effectLayer = new CanvasCommandList(control);
using var effectLayerDs = effectLayer.CreateDrawingSession();
if (line.OriginalText != line.DisplayedText && _liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsTranslationHighlightAmount != 0)
{
using var translationHighlightMask = CanvasHelper.CreateTranslationHighlightMask(control, line);
using var foregroundTranslationHighlightEffect = CanvasHelper.CreateForegroundHighlightEffect(foregroundFontEffect, translationHighlightMask,
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsTranslationHighlightAmount / 100.0);
effectLayerDs.DrawImage(foregroundTranslationHighlightEffect);
}
if (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.IsLyricsShadowEnabled)
{
var shadowEffectMask = CanvasHelper.GetAlphaMask(control, charMask, lineStartToCharMask, lineMask,
@@ -273,10 +278,14 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsGlowEffectAmount);
effectLayerDs.DrawImage(foregroundBlurEffect);
}
var highlightEffectMask = CanvasHelper.GetAlphaMask(control, charMask, lineStartToCharMask, lineMask,
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsHighlightScope);
using var foregroundHighlightEffect = CanvasHelper.CreateForegroundHighlightEffect(foregroundFontEffect, highlightEffectMask);
effectLayerDs.DrawImage(foregroundHighlightEffect);
if (_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsHighlightAmount != 0)
{
var highlightEffectMask = CanvasHelper.GetAlphaMask(control, charMask, lineStartToCharMask, lineMask,
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsHighlightScope);
using var foregroundHighlightEffect = CanvasHelper.CreateForegroundHighlightEffect(foregroundFontEffect, highlightEffectMask,
_liveStatesService.LiveStates.CurrentLyricsEffectSettings.LyricsHighlightAmount / 100.0);
effectLayerDs.DrawImage(foregroundHighlightEffect);
}
combinedDs.DrawImage(new OpacityEffect
{