GithubHelp home page GithubHelp logo

add color mix functions about lush.nvim HOT 11 CLOSED

rktjmp avatar rktjmp commented on June 12, 2024
add color mix functions

from lush.nvim.

Comments (11)

davidscotson avatar davidscotson commented on June 12, 2024 1

contrast

from lush.nvim.

davidscotson avatar davidscotson commented on June 12, 2024

I noticed there's a c function in neovim for this, but not sure how accessabile that is for lua code:

https://github.com/neovim/neovim/blob/master/src/nvim/highlight.c#L608

from lush.nvim.

rktjmp avatar rktjmp commented on June 12, 2024

Cool idea and the algo is pretty simple. I wonder now it behaves without converting to rbg. At any rate we can go hsl->rgb->hsl if it's weird.

Do you imagine the syntax being something:

Normal { fg = xxx, bg = yyy },
Comment { Normal, fg = Normal.fg.mix(Normal.bg, 40) }
-- maybe mix_to which implies the "one direction" of ours.
-- Shortcut to ... mi? mix? Maybe just mix is fine with no shortcut.

Sass takes two colours and mixes over -100 (all c1) to 100 (all c2) but I think we would just have 0 to 100, where 0 == fg and 100 == bg in the above example?

from lush.nvim.

davidscotson avatar davidscotson commented on June 12, 2024

I think the extra weirdness in the Sass implementation is to handle the two colors possibly having alpha components and some oddities that might arise from that. The neovim implementation only does rgb and is a bit more straightforward and is probably enough for lush purposes (does winblend, pumblend affect this? I'm not really familiar with them).

I had kind of assumed that RGB wouldn't be great for this kind of thing and some fancy colorspace would be part of the answer, but apparently RGB is the best choice (or at least one of the best of the standard options) for doing this kind of additive color mixing. The visual gradients on the bootstrap doc page look good to me anyway.

The basic use would be just to take two colors and a mix-ratio and generate a new color that could be used like any other so the Normal.fg.mix(Normal.bg, 40) example you give makes sense, with the 40 being the percentage of the color you're passing in, e.g 0 would be a no-op and return the original color, passing in 100 would just use the passed in color. This is kind of the main use that Bootstrap has for it, building a palette of tones based on selected base colors.

However, I'm trying to order syntax components by "readability" and then semi-automatically assign properties based on that, so possibly an alternate or extra syntax might be Normal.fg.fade_into(Normal.bg, 80%), where 100% fades it to invisibility and 0 doesn't fade it at all. And potentialy there would just be a way to say Normal.faded(50) which would let you set the fg and bg (and everything else?) from the other Highlight group, but just change the fg to be closer to the bg which is left unchanged. I'm not sure how this would work with items that don't have specific backgrounds set, do we have access to what their fall-back inherited bg would be or do we need to set both?

I can't immediately think of a case where you'd want to fade a background into it's own fg, so it's probably alright for that to be only one direction.

from lush.nvim.

rktjmp avatar rktjmp commented on June 12, 2024

Normal.faded(50) which would let you set the fg and bg (and everything else?) from the other Highlight group, but just change the fg to be closer to the bg which is left unchanged.

At first glance this is a bit too ambiguous for me

  • "Why does group.faded() fade text into bg and and not fade bg to match text?"
    • I know that "fade bg into text" doesn't really make sense when you think about it but the ambiguity remains and becomes a documentation issue.
  • It makes it look like "faded" is a group property (like fg, bg, gui, blend)

Maybe there is something like

Comment { fg = hsl.faded(Normal.fg, 50) }

but that's quite similar to just going Normal.fg.fade(bg, 50), probably not worth the extra syntax burden.

Normal.fg.fade_into(Normal.bg, 80%), where 100% fades it to invisibility and 0 doesn't fade it at all.

Wouldn't that just be the same as mix?

fg = Normal.fg.fade_into(bg, 80) == "80% invisible on bg 

be the same as

fg = Normal.fg.mix(bg, 80) == "20% strength of fg"

It does make me think that you might have mix_into/mix_toward and mix_away, what you're really operating on is the distance between two points and a vector between them.

from lush.nvim.

rktjmp avatar rktjmp commented on June 12, 2024

I pushed a basic vector mix to https://github.com/rktjmp/lush.nvim/tree/feat-mix.

The results do not map 1 to 1 to sass's mix (sass mix 80 == hsl mix 70), but I am undecided whether that should be treated as a reference implementation or not since we are mixing in different colorspaces.

I think as long as mix behaves predictably, it's probably ok since, well, I can't really say what 80% of black into blue is exactly, just that it should look "more black" than 50%.

from lush.nvim.

harrygallagher4 avatar harrygallagher4 commented on June 12, 2024

I've had good results using hsluv for mixing in my own experiments. There's a lua implementation that's pretty tiny. If you want to check out my functions here's a gist.

In addition to more consistent blending, rotating/(de)saturating/lightening/darkening in the hsluv space should also be more consistent but I haven't played around with that yet. Sorry to butt in with this only slightly relevant comment but I'd been working on mixing colors for lush and thought I'd share.

from lush.nvim.

rktjmp avatar rktjmp commented on June 12, 2024

@davidscotson Are you using lush's mix fn or your own? If Lush, do you think it behaves how you'd expect? (I am assuming it's lush's cause you use hsl() but maybe you wrapped your own).

from lush.nvim.

rktjmp avatar rktjmp commented on June 12, 2024

@harrygallagher4 if you use the branch listed above, does the included mix function match the output of your blend/fade?

from lush.nvim.

harrygallagher4 avatar harrygallagher4 commented on June 12, 2024

No, but I don't think it's supposed to. I'm just calculating a midpoint of the h/s/l(uv) values in the hsluv space. I can't find any function aside from this one to test but I can't see how that one would do the same thing as transforming in the hsluv space. Here are some comparisons I did.

local lush = require 'lush'
local util = require 'harryg.colorutilsfnl'
local palette = require'melange.colors'.Melange.lush -- this is how melange exposes the palette

local function color(c) return palette[c] end
local function pr(c) print(c.hex) end

print('')
pr(color('red'))
pr(color('green'))

-- lush: mix two `lush.hsl` colors
-- mine: convert two `lush.hsl` colors to hex, hex to hsluv, transform, hsluv to hex, hex to `lush.hsl` color
print('')
pr(palette.red.mix(palette.green, 50))
pr(util['blend-lush'](palette.red, palette.green, 0.5))

-- lush: mix two `lush.hsluv` colors
-- mine: convert two hex colors to hsluv, transform, convert back
print('')
pr(lush.hsluv(palette.red.hex).mix(lush.hsluv(palette.green.hex), 50))
print(util['blend-hex'](palette.red.hex, palette.green.hex, 0.5))

image

p.s. If I wasn't clear enough earlier, I'm not defining my colorscheme with hsluv colors. I'm just doing the blend transformation in hsluv space so the result is more perceptually consistent. By "perceptually consistent" I really mean that the result is more like what people imagine when they think of mixing colors, the gradient screenshot in my gist is a good example of that.

from lush.nvim.

rktjmp avatar rktjmp commented on June 12, 2024

Merged mainline in d3071c7.

from lush.nvim.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.