mirror of
https://github.com/chylex/IntelliJ-Rainbow-Brackets.git
synced 2025-05-14 12:34:03 +02:00
Initial commit for remove Nashorn Engine
This commit is contained in:
parent
715fca803f
commit
5777d7bace
src/main/kotlin/com/github/izhangzhihao/rainbow/brackets
@ -1,5 +1,6 @@
|
||||
package com.github.izhangzhihao.rainbow.brackets
|
||||
|
||||
import com.github.izhangzhihao.rainbow.brackets.fromRGBstr
|
||||
import com.github.izhangzhihao.rainbow.brackets.settings.RainbowSettings
|
||||
import com.github.izhangzhihao.rainbow.brackets.util.memoize
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo
|
||||
@ -132,7 +133,7 @@ object RainbowHighlighter {
|
||||
}
|
||||
|
||||
private fun genByOption(option: String) =
|
||||
TextAttributes(Color.decode(RandomColorGenerator.randomColor(option)), null, null, null, 0)
|
||||
TextAttributes(fromRGBstr(randomColor(option)), null, null, null, 0)
|
||||
|
||||
val memGetRainbowColorByLevel = { isDark: Boolean, rainbowName: String, level: Int -> generateColor(isDark, rainbowName, level) }.memoize()
|
||||
|
||||
|
@ -1,20 +1,27 @@
|
||||
package com.github.izhangzhihao.rainbow.brackets
|
||||
|
||||
import jdk.nashorn.api.scripting.JSObject
|
||||
import jdk.nashorn.api.scripting.NashornScriptEngineFactory
|
||||
import javax.script.Invocable
|
||||
import javax.script.ScriptEngine
|
||||
import com.github.izhangzhihao.rainbow.brackets.color.Luminosity
|
||||
import com.github.izhangzhihao.rainbow.brackets.color.fromString
|
||||
import org.json.JSONObject
|
||||
import java.awt.Color
|
||||
|
||||
object RandomColorGenerator {
|
||||
private val engine: ScriptEngine by lazy { NashornScriptEngineFactory().getScriptEngine() }
|
||||
private val invocable: Invocable by lazy {
|
||||
engine.eval(javaClass.classLoader.getResource("randomColor.js").readText())
|
||||
engine as Invocable
|
||||
}
|
||||
fun randomColor(options: String): String {
|
||||
val options = JSONObject(options)
|
||||
return com.github.izhangzhihao.rainbow.brackets.color.randomColor(
|
||||
fromString(options.getStringOrDefault("hue", "random")),
|
||||
Luminosity.valueOf(options.getStringOrDefault("luminosity", "random"))
|
||||
)
|
||||
}
|
||||
|
||||
fun randomColor(options: String): String {
|
||||
engine.put("paras", options)
|
||||
val obj = engine.eval("JSON.parse(paras)") as JSObject
|
||||
return invocable.invokeFunction("randomColor", obj).toString()
|
||||
fun org.json.JSONObject.getStringOrDefault(key: String, default: String): String {
|
||||
return try {
|
||||
this.getString(key)
|
||||
} catch (e: Exception) {
|
||||
default
|
||||
}
|
||||
}
|
||||
|
||||
fun fromRGBstr(str: String): Color {
|
||||
val split = str.trimStart('(').trimEnd(')').split(", ")
|
||||
return Color(split[0].toInt(), split[1].toInt(), split[2].toInt())
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package com.github.izhangzhihao.rainbow.brackets.color
|
||||
|
||||
import kotlin.math.floor
|
||||
|
||||
enum class Color(val hueRange: Pair<Int, Int>, val lowerBounds: List<Pair<Int, Int>>) {
|
||||
monochrome(
|
||||
Pair(-1, -1),
|
||||
listOf(Pair(0, 0), Pair(100, 0))
|
||||
),
|
||||
red(
|
||||
Pair(-26, 18),
|
||||
listOf(
|
||||
Pair(20, 100),
|
||||
Pair(30, 92),
|
||||
Pair(40, 89),
|
||||
Pair(50, 85),
|
||||
Pair(60, 78),
|
||||
Pair(70, 70),
|
||||
Pair(80, 60),
|
||||
Pair(90, 55),
|
||||
Pair(100, 50)
|
||||
)
|
||||
),
|
||||
orange(
|
||||
Pair(18, 46),
|
||||
listOf(Pair(20, 100), Pair(30, 93), Pair(40, 88), Pair(50, 86), Pair(60, 85), Pair(70, 70), Pair(100, 70))
|
||||
),
|
||||
yellow(
|
||||
Pair(46, 62),
|
||||
listOf(
|
||||
Pair(25, 100),
|
||||
Pair(40, 94),
|
||||
Pair(50, 89),
|
||||
Pair(60, 86),
|
||||
Pair(70, 84),
|
||||
Pair(80, 82),
|
||||
Pair(90, 80),
|
||||
Pair(100, 75)
|
||||
)
|
||||
),
|
||||
green(
|
||||
Pair(62, 178),
|
||||
listOf(
|
||||
Pair(30, 100),
|
||||
Pair(40, 90),
|
||||
Pair(50, 85),
|
||||
Pair(60, 81),
|
||||
Pair(70, 74),
|
||||
Pair(80, 64),
|
||||
Pair(90, 50),
|
||||
Pair(100, 40)
|
||||
)
|
||||
),
|
||||
blue(
|
||||
Pair(178, 257),
|
||||
listOf(
|
||||
Pair(20, 100),
|
||||
Pair(30, 86),
|
||||
Pair(40, 80),
|
||||
Pair(50, 74),
|
||||
Pair(60, 60),
|
||||
Pair(70, 52),
|
||||
Pair(80, 44),
|
||||
Pair(90, 39),
|
||||
Pair(100, 35)
|
||||
)
|
||||
),
|
||||
purple(
|
||||
Pair(257, 282),
|
||||
listOf(
|
||||
Pair(20, 100),
|
||||
Pair(30, 87),
|
||||
Pair(40, 79),
|
||||
Pair(50, 70),
|
||||
Pair(60, 65),
|
||||
Pair(70, 59),
|
||||
Pair(80, 52),
|
||||
Pair(90, 45),
|
||||
Pair(100, 42)
|
||||
)
|
||||
),
|
||||
pink(
|
||||
Pair(282, 334),
|
||||
listOf(Pair(20, 100), Pair(30, 90), Pair(40, 86), Pair(60, 84), Pair(80, 80), Pair(90, 75), Pair(100, 73))
|
||||
)
|
||||
}
|
||||
|
||||
fun Color.saturationRange(): Pair<Int, Int> {
|
||||
return Pair(lowerBounds.first().first, lowerBounds.last().first)
|
||||
}
|
||||
|
||||
fun Color.brightnessRange(saturation: Int): Pair<Int, Int> {
|
||||
for (i in 0 until lowerBounds.size - 1) {
|
||||
val s1 = lowerBounds[i].first.toFloat()
|
||||
val v1 = lowerBounds[i].second.toFloat()
|
||||
|
||||
val s2 = lowerBounds[i + 1].first.toFloat()
|
||||
val v2 = lowerBounds[i + 1].second.toFloat()
|
||||
|
||||
if (saturation.toFloat() in s1..s2) {
|
||||
val m = (v2 - v1) / (s2 - s1)
|
||||
val b = v1 - m * s1
|
||||
val minBrightness = m * saturation + b
|
||||
return Pair(floor(minBrightness).toInt(), 100)
|
||||
}
|
||||
}
|
||||
return Pair(0, 100)
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.github.izhangzhihao.rainbow.brackets.color
|
||||
|
||||
enum class Format {
|
||||
HSL,
|
||||
RGB,
|
||||
HEX
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.github.izhangzhihao.rainbow.brackets.color
|
||||
|
||||
|
||||
sealed class Hue
|
||||
object RandomHue : Hue()
|
||||
data class NumberHue(val value: Int) : Hue()
|
||||
data class ColorHue(val color: Color) : Hue()
|
||||
|
||||
fun Hue.getHueRange(): Pair<Int, Int> {
|
||||
return when (this) {
|
||||
is ColorHue -> color.hueRange
|
||||
is NumberHue -> if (value in 1..359) Pair(value, value) else Pair(0, 360)
|
||||
RandomHue -> Pair(0, 360)
|
||||
}
|
||||
}
|
||||
|
||||
fun fromString(str: String): Hue {
|
||||
return when (str) {
|
||||
"random" -> RandomHue
|
||||
is String -> ColorHue(Color.valueOf(str))
|
||||
else -> TODO()
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.github.izhangzhihao.rainbow.brackets.color
|
||||
|
||||
enum class Luminosity {
|
||||
random,
|
||||
bright,
|
||||
light,
|
||||
dark
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
package com.github.izhangzhihao.rainbow.brackets.color
|
||||
|
||||
import kotlin.math.floor
|
||||
import kotlin.random.Random
|
||||
|
||||
|
||||
/**
|
||||
* Generate a single random color with specified (or random) hue and luminosity.
|
||||
*/
|
||||
fun randomColor(
|
||||
hue: Hue = RandomHue,
|
||||
luminosity: Luminosity = Luminosity.random,
|
||||
format: Format = Format.RGB
|
||||
): String {
|
||||
|
||||
// First we pick a hue (H)
|
||||
val hueValue = pickHue(hue)
|
||||
|
||||
// Then use H to determine saturation (S)
|
||||
val saturation = pickSaturation(hueValue, hue, luminosity)
|
||||
|
||||
// Then use S and H to determine brightness (B)
|
||||
val brightness = pickBrightness(hueValue, hue, saturation, luminosity)
|
||||
|
||||
// Then we return the HSB color in the desired format
|
||||
return setFormat(hueValue, saturation, brightness, format)
|
||||
}
|
||||
|
||||
private fun pickHue(hue: Hue): Int {
|
||||
val hueRange = hue.getHueRange()
|
||||
var hueValue = randomWithin(hueRange)
|
||||
// Instead of storing red as two separate ranges,
|
||||
// we group them, using negative numbers
|
||||
if (hueValue < 0) {
|
||||
hueValue += 360
|
||||
}
|
||||
return hueValue
|
||||
}
|
||||
|
||||
private fun pickSaturation(hueValue: Int, hue: Hue, luminosity: Luminosity): Int {
|
||||
if (hue == ColorHue(Color.monochrome)) {
|
||||
return 0
|
||||
}
|
||||
|
||||
val color: Color = matchColor(hueValue, hue)
|
||||
|
||||
val sMin = color.saturationRange().first
|
||||
val sMax = color.saturationRange().second
|
||||
|
||||
return when (luminosity) {
|
||||
Luminosity.random -> randomWithin(Pair(0, 100))
|
||||
Luminosity.bright -> randomWithin(Pair(55, sMax))
|
||||
Luminosity.light -> randomWithin(Pair(sMin, 55))
|
||||
Luminosity.dark -> randomWithin(Pair(sMax - 10, sMax))
|
||||
}
|
||||
}
|
||||
|
||||
private fun pickBrightness(hueValue: Int, hue: Hue, saturation: Int, luminosity: Luminosity): Int {
|
||||
val color: Color = matchColor(hueValue, hue)
|
||||
|
||||
val bMin = color.brightnessRange(saturation).first
|
||||
val bMax = color.brightnessRange(saturation).second
|
||||
|
||||
return when (luminosity) {
|
||||
Luminosity.random -> randomWithin(Pair(50, 100)) // I set this to 50 arbitrarily, they look more attractive
|
||||
Luminosity.bright -> randomWithin(Pair(bMin, bMax))
|
||||
Luminosity.light -> randomWithin(Pair((bMax + bMin) / 2, bMax))
|
||||
Luminosity.dark -> randomWithin(Pair(bMin, bMin + 20))
|
||||
}
|
||||
}
|
||||
|
||||
private fun setFormat(hueValue: Int, saturation: Int, brightness: Int, format: Format): String {
|
||||
return when (format) {
|
||||
Format.HSL -> TODO()
|
||||
Format.RGB -> HSVtoRGB(hueValue, saturation, brightness).toString()
|
||||
Format.HEX -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun HSVtoRGB(hueValue: Int, saturation: Int, brightness: Int): Triple<Int, Int, Int> {
|
||||
// This doesn't work for the values of 0 and 360
|
||||
// Here's the hacky fix
|
||||
// Rebase the h,s,v values
|
||||
val h: Float = hueValue.coerceIn(1, 359) / 360f
|
||||
val s = saturation / 100f
|
||||
val v = brightness / 100f
|
||||
|
||||
val hI = floor(h * 6f).toInt()
|
||||
val f = h * 6f - hI
|
||||
val p = v * (1f - s)
|
||||
val q = v * (1f - f * s)
|
||||
val t = v * (1f - (1f - f) * s)
|
||||
|
||||
var r = 256f
|
||||
var g = 256f
|
||||
var b = 256f
|
||||
|
||||
when (hI) {
|
||||
0 -> {
|
||||
r = v; g = t; b = p
|
||||
}
|
||||
1 -> {
|
||||
r = q; g = v; b = p
|
||||
}
|
||||
2 -> {
|
||||
r = p; g = v; b = t
|
||||
}
|
||||
3 -> {
|
||||
r = p; g = q; b = v
|
||||
}
|
||||
4 -> {
|
||||
r = t; g = p; b = v
|
||||
}
|
||||
5 -> {
|
||||
r = v; g = p; b = q
|
||||
}
|
||||
}
|
||||
|
||||
return Triple(floor(r * 255f).toInt(), floor(g * 255f).toInt(), floor(b * 255f).toInt())
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns hue into a color if it isn't already one.
|
||||
* First we check if hue was passed in as a color, and just return that if it is.
|
||||
* If not, we iterate through every color to see which one the given hueValue fits in.
|
||||
* For some reason if a matching hue is not found, just return Monochrome.
|
||||
*/
|
||||
private fun matchColor(hueValue: Int, hue: Hue): Color {
|
||||
return when (hue) {
|
||||
is ColorHue -> hue.color
|
||||
else -> {
|
||||
// Maps red colors to make picking hue easier
|
||||
var hueVal = hueValue
|
||||
if (hueVal in 334..360) {
|
||||
hueVal -= 360
|
||||
}
|
||||
|
||||
for (color in Color.values()) {
|
||||
if (hueVal in color.hueRange.first..color.hueRange.second) {
|
||||
return color
|
||||
}
|
||||
}
|
||||
// Returning Monochrome if we can't find a value, but this should never happen
|
||||
return Color.monochrome
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun randomWithin(range: Pair<Int, Int>): Int {
|
||||
// Generate random evenly distinct number from:
|
||||
// https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
|
||||
val goldenRatio = 0.618033988749895
|
||||
var r = Random.nextDouble()
|
||||
r += goldenRatio
|
||||
r %= 1
|
||||
return floor(range.first + r * (range.second + 1 - range.first)).toInt()
|
||||
}
|
Loading…
Reference in New Issue
Block a user