Recognize uncontrasting colors for nations according to WCAG guidelines, and suggest tinted versions to conform

This commit is contained in:
Yair Morgenstern
2023-01-12 10:06:37 +02:00
parent 7edfd497db
commit 2251824d94
4 changed files with 66 additions and 5 deletions

View File

@ -174,8 +174,8 @@
"neutralHello": "Hello.",
"hateHello": "It's you.",
"tradeRequest": "France offers you this exceptional proposition.",
"outerColor": [65, 141, 254],
"innerColor": [235, 235, 139],
"outerColor": [58, 126, 228],
"innerColor": [237, 237, 150],
"favoredReligion": "Christianity",
"uniqueName": "Ancien Régime",
"uniques": ["[+2 Culture] [in all cities] <before discovering [Steam Power]>"],

View File

@ -163,8 +163,8 @@
"neutralHello": "Hello.",
"hateHello": "It's you.",
"tradeRequest": "France offers you this exceptional proposition.",
"outerColor": [65, 141, 254],
"innerColor": [235, 235, 139],
"outerColor": [58, 126, 228],
"innerColor": [237, 237, 150],
"uniqueName": "Ancien Régime",
"uniques": ["[+2 Culture] [in all cities] <before discovering [Steam Power]>"],
"cities": ["Paris","Orleans","Lyon","Troyes","Tours","Marseille","Chartres","Avignon","Rouen","Grenoble",

View File

@ -11,8 +11,9 @@ import com.unciv.ui.civilopedia.CivilopediaScreen.Companion.showReligionInCivilo
import com.unciv.ui.civilopedia.FormattedLine
import com.unciv.ui.utils.Fonts
import com.unciv.ui.utils.extensions.colorFromRGB
import kotlin.math.pow
class Nation : RulesetObject() {
class Nation : RulesetObject() {
var leaderName = ""
fun getLeaderDisplayName() = if (isCityState()) name
else "[$leaderName] of [$name]"
@ -285,4 +286,28 @@ class Nation : RulesetObject() {
}
}
fun getContrastRatio() = getContrastRatio(getInnerColor(), getOuterColor())
}
/** All defined by https://www.w3.org/TR/WCAG20/#relativeluminancedef */
fun getRelativeLuminance(color:Color):Double{
fun getRelativeChannelLuminance(channel:Float):Double =
if (channel < 0.03928) channel / 12.92
else ((channel + 0.055) / 1.055).pow(2.4)
val R = getRelativeChannelLuminance(color.r)
val G = getRelativeChannelLuminance(color.g)
val B = getRelativeChannelLuminance(color.b)
return 0.2126 * R + 0.7152 * G + 0.0722 * B
}
/** https://www.w3.org/TR/WCAG20/#contrast-ratiodef */
fun getContrastRatio(color1:Color, color2:Color): Double { // ratio can range from 1 to 21
val innerColorLuminance = getRelativeLuminance(color1)
val outerColorLuminance = getRelativeLuminance(color2)
return if (innerColorLuminance > outerColorLuminance) (innerColorLuminance + 0.05) / (outerColorLuminance + 0.05)
else (outerColorLuminance + 0.05) / (innerColorLuminance + 0.05)
}

View File

@ -71,6 +71,42 @@ class RulesetValidator(val ruleset: Ruleset) {
lines += "${nation.name} can settle cities, but has no city names!"
}
// https://www.w3.org/TR/WCAG20/#visual-audio-contrast-contrast
val constrastRatio = nation.getContrastRatio()
if (constrastRatio < 3) {
val innerColorLuminance = getRelativeLuminance(nation.getInnerColor())
val outerColorLuminance = getRelativeLuminance(nation.getOuterColor())
val innerLerpColor:Color
val outerLerpColor:Color
if (innerColorLuminance > outerColorLuminance) { // inner is brighter
innerLerpColor = Color.WHITE
outerLerpColor = Color.BLACK
}
else {
innerLerpColor = Color.BLACK
outerLerpColor = Color.WHITE
}
var text = "${nation.name}'s colors do not contrast enough - it is unreadable!"
for (i in 1..10){
val newInnerColor = nation.getInnerColor().cpy().lerp(innerLerpColor, 0.05f *i)
val newOuterColor = nation.getOuterColor().cpy().lerp(outerLerpColor, 0.05f *i)
if (getContrastRatio(newInnerColor, newOuterColor) > 3){
text += "\n Suggested inner color: (${(newInnerColor.r*255).toInt()}, ${(newInnerColor.g*255).toInt()}, ${(newInnerColor.b*255).toInt()})"
text += "\n Suggested outer color: (${(newOuterColor.r*255).toInt()}, ${(newOuterColor.g*255).toInt()}, ${(newOuterColor.b*255).toInt()})"
break
}
}
lines.add(
text, RulesetErrorSeverity.Warning
)
}
checkUniques(nation, lines, rulesetInvariant, tryFixUnknownUniques)
}