Skip to content

Commit

Permalink
stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
nift4 committed Jan 30, 2025
1 parent b4eeeca commit 1d97a83
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ import android.graphics.Shader
import android.text.TextPaint
import android.text.style.CharacterStyle
import android.text.style.UpdateAppearance
import android.view.animation.PathInterpolator
import kotlin.math.abs
import kotlin.math.min
import org.akanework.gramophone.logic.utils.CalculationUtils.lerp
import org.akanework.gramophone.logic.utils.CalculationUtils.lerpInv

// Hacks, hacks, hacks...
class MyGradientSpan(grdWidth: Float, color: Int, highlightColor: Int) : CharacterStyle(),
UpdateAppearance {
private val gradientPathInterpolator = PathInterpolator(0.38f, 0.39f, 0f, 1f)
class MyGradientSpan(grdWidth: Float, color: Int, highlightColor: Int,
private val charScaling: Boolean) : CharacterStyle(), UpdateAppearance {
private val matrix = Matrix()
private val gradientWidth = grdWidth
private val shader = LinearGradient(
Expand All @@ -36,8 +38,15 @@ class MyGradientSpan(grdWidth: Float, color: Int, highlightColor: Int) : Charact
val preOffsetFromLeft = lineOffsets[o].toFloat()
val textLength = lineOffsets[o + 1]
val isRtl = lineOffsets[o + 4] == -1
val ourProgress = lerpInv(lineOffsets[o + 2].toFloat(), lineOffsets[o + 3].toFloat(),
lerp(0f, totalCharsForProgress.toFloat(), progress)).coerceIn(0f, 1f)
val ourProgress = if (charScaling) {
lerpInv(lineOffsets[o + 2].toFloat(), lineOffsets[o + 3].toFloat(),
lerp(0f, totalCharsForProgress.toFloat(), progress)).coerceIn(0f, 1f)
} else {
val pre = (0..<o/5).sumOf { lineOffsets[it * 5 + 1] }.toFloat()
val post = (o/5+1..<lineOffsets.size/5).sumOf { lineOffsets[it * 5 + 1] }.toFloat()
lerpInv(pre, pre + textLength, lerp(0f, pre + textLength + post, progress))
.coerceIn(0f, 1f)
}
val ourProgressD = if (isRtl) 1f - ourProgress else ourProgress
shader.setLocalMatrix(matrix.apply {
reset()
Expand All @@ -50,7 +59,8 @@ class MyGradientSpan(grdWidth: Float, color: Int, highlightColor: Int) : Charact
// is 1. If we're somewhere in the middle, we want the gradient to be as wide as
// gradientWidth, and the gradient start and end should be offset by half of
// gradientWidth so that at 50% the middle of the gradient is in the middle of text.
val widthAtPos = ((1f - 2f * abs(ourProgressD - 0.5f)) * gradientWidth)
val widthAtPos = (gradientPathInterpolator.getInterpolation(
1f - 2f * abs(ourProgressD - 0.5f)) * gradientWidth)
.coerceAtMost(min(textLength * ourProgressD, textLength * (1f - ourProgressD)))
postScale(widthAtPos.coerceAtLeast(1f) / gradientWidth, 1f)
postTranslate(preOffsetFromLeft + textLength * ourProgressD - widthAtPos * 0.5f, 0f)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,13 @@ class LyricsView(context: Context, attrs: AttributeSet?) : FrameLayout(context,
}

override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
if (key == "lyric_center" || key == "lyric_bold" || key == "lyric_no_animation") {
if ((key == "lyric_center" || key == "lyric_bold") && adapter != null)
adapter?.onPrefsChanged()
else if (key == "lyric_center" || key == "lyric_bold" || key == "lyric_no_animation" ||
key == "lyric_char_scaling")
newView?.onPrefsChanged(key)
} else if (key == "lyric_ui") {
else if (key == "lyric_ui")
createView()
}
}

fun updateLyricPositionFromPlaybackPos() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class NewLyricsView(context: Context, attrs: AttributeSet) : View(context, attrs
private val scaleInAnimTime
get() = lyricAnimTime / 2f
private val isElegantTextHeight = false
private var charScaling: Boolean
private val scaleColorInterpolator = PathInterpolator(0.4f, 0.2f, 0f, 1f)
private val prefs = PreferenceManager.getDefaultSharedPreferences(context)
private lateinit var typeface: Typeface
Expand Down Expand Up @@ -147,19 +148,19 @@ class NewLyricsView(context: Context, attrs: AttributeSet) : View(context, attrs
private var gradientSpanPoolM = lazy { mutableListOf<MyGradientSpan>() }
private var gradientSpanPoolF = lazy { mutableListOf<MyGradientSpan>() }
private var gradientSpanPoolD = lazy { mutableListOf<MyGradientSpan>() }
private fun makeGradientSpan() = MyGradientSpan(grdWidth, defaultTextColor, highlightTextColor)
private fun makeGradientSpan() =
MyGradientSpan(grdWidth, defaultTextColor, highlightTextColor, charScaling)
private fun makeGradientSpanM() =
MyGradientSpan(grdWidth, defaultTextColorM, highlightTextColorM)

MyGradientSpan(grdWidth, defaultTextColorM, highlightTextColorM, charScaling)
private fun makeGradientSpanF() =
MyGradientSpan(grdWidth, defaultTextColorF, highlightTextColorF)

MyGradientSpan(grdWidth, defaultTextColorF, highlightTextColorF, charScaling)
private fun makeGradientSpanD() =
MyGradientSpan(grdWidth, defaultTextColorD, highlightTextColorD)
MyGradientSpan(grdWidth, defaultTextColorD, highlightTextColorD, charScaling)

init {
applyTypefaces()
loadLyricAnimTime()
charScaling = prefs.getBooleanStrict("lyric_char_scaling", false)
}

fun updateTextColor(
Expand Down Expand Up @@ -281,6 +282,10 @@ class NewLyricsView(context: Context, attrs: AttributeSet) : View(context, attrs
?: instance?.currentPosition?.toULong() ?: 0uL

fun onPrefsChanged(key: String) {
if (key == "lyric_char_scaling") {
loadCharScaling()
return
}
if (key == "lyric_no_animation") {
loadLyricAnimTime()
return
Expand All @@ -296,6 +301,34 @@ class NewLyricsView(context: Context, attrs: AttributeSet) : View(context, attrs
lyricAnimTime = if (prefs.getBooleanStrict("lyric_no_animation", false)) 0f else 650f
}

private fun loadCharScaling() {
var changed = false
charScaling = prefs.getBooleanStrict("lyric_char_scaling", false).also {
if (it != charScaling) changed = true
}
if (changed) {
gradientSpanPool.clear()
(1..3).forEach { gradientSpanPool.add(makeGradientSpan()) }
if (gradientSpanPoolM.isInitialized()) {
gradientSpanPoolM.value.clear()
(1..3).forEach { gradientSpanPoolM.value.add(makeGradientSpanM()) }
}
if (gradientSpanPoolF.isInitialized()) {
gradientSpanPoolF.value.clear()
(1..3).forEach { gradientSpanPoolF.value.add(makeGradientSpanF()) }
}
if (gradientSpanPoolD.isInitialized()) {
gradientSpanPoolD.value.clear()
(1..3).forEach { gradientSpanPoolD.value.add(makeGradientSpanD()) }
}
spForRender?.forEach {
it.text.getSpans<MyGradientSpan>()
.forEach { s -> it.text.removeSpan(s) }
}
invalidate()
}
}

private fun applyTypefaces() {
typeface = if (prefs.getBooleanStrict("lyric_bold", false)) {
TypefaceCompat.create(context, null, 700, false)
Expand Down Expand Up @@ -767,7 +800,10 @@ class NewLyricsView(context: Context, attrs: AttributeSet) : View(context, attrs
listOf(line)
}
}.flatten()
}, speaker, syncedLine)
}, speaker, syncedLine, lineOffsets?.mapIndexed { i, it ->
(0..<it.size/5).sumOf { j -> it[j * 5 + 1] } /
syncedLine.words[i].timeRange.let { it.last - it.first }.toLong()
})
}
val heights = spLines.map { it.layout.height + it.paddingTop + it.paddingBottom }
return Pair(
Expand All @@ -781,7 +817,8 @@ class NewLyricsView(context: Context, attrs: AttributeSet) : View(context, attrs
data class SbItem(
val layout: StaticLayout, val text: SpannableStringBuilder,
val paddingTop: Int, val paddingBottom: Int, val words: List<List<Int>>?,
val rlm: List<Int>?, val speaker: SpeakerEntity?, val line: SemanticLyrics.LyricLine?
val rlm: List<Int>?, val speaker: SpeakerEntity?, val line: SemanticLyrics.LyricLine?,
val velocities: List<Long>?
)

// == start scroll ==
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -300,4 +300,6 @@
<string name="cannot_play_file">Cannot play this file</string>
<string name="settings_lyrics_no_animation">Disable animations</string>
<string name="settings_lyrics_no_animation_summary">Disable all line transition lyric animations</string>
<string name="settings_lyrics_char_scaling_summary">Calculate lyric gradient velocity in characters per second instead of pixels per second. Might cause speed to look irregular due to differing character length in pixels.</string>
<string name="settings_lyrics_char_scaling">Character-based scaling for lyric gradient</string>
</resources>
9 changes: 9 additions & 0 deletions app/src/main/res/xml/settings_experimental.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@
android:widgetLayout="@layout/preference_switch_widget"
app:iconSpaceReserved="false" />

<SwitchPreferenceCompat
android:defaultValue="false"
android:key="lyric_char_scaling"
android:layout="@layout/preference_switch"
android:summary="@string/settings_lyrics_char_scaling_summary"
android:title="@string/settings_lyrics_char_scaling"
android:widgetLayout="@layout/preference_switch_widget"
app:iconSpaceReserved="false" />


</PreferenceCategory>

Expand Down

0 comments on commit 1d97a83

Please sign in to comment.