Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/glug.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ module Glug # :nodoc:
require_relative 'glug/stylesheet'
require_relative 'glug/layer'
require_relative 'glug/extensions'
require_relative 'glug/hsluv_modifiers'
require_relative 'glug/chroma_extensions'
require_relative 'glug/stylesheet_dsl'
require_relative 'glug/layer_dsl'
19 changes: 19 additions & 0 deletions lib/glug/chroma_extensions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

require 'chroma'
require 'hsluv'

module Chroma
class Color # :nodoc:
def mix(other, weight = 50)
other = other.paint if other.is_a?(String)
p = weight / 100.0

r = (rgb.r * p + other.rgb.r * (1 - p)).round
g = (rgb.g * p + other.rgb.g * (1 - p)).round
b = (rgb.b * p + other.rgb.b * (1 - p)).round

Chroma.paint(+"rgb(#{r}, #{g}, #{b})")
end
end
end
13 changes: 7 additions & 6 deletions lib/glug/extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@

# Colour methods on Integer
class Integer
# rubocop:disable Style/StringConcatenation, Naming/MethodParameterName
def chroma_hex(op, p)
('#' + to_s(16).rjust(6, '0')).paint.send(op, p).to_hex
# rubocop:disable Style/StringConcatenation
def chroma_hex(op, *args)
color = ('#' + to_s(16).rjust(6, '0')).paint
color.send(op, *args).to_hex
end

def chroma(op, p)
chroma_hex(op, p).gsub('#', '0x').to_i(16)
def chroma(op, *args)
chroma_hex(op, *args).gsub('#', '0x').to_i(16)
end

def to_hex_color
'#' + to_s(16).rjust(6, '0')
end
# rubocop:enable Style/StringConcatenation, Naming/MethodParameterName
# rubocop:enable Style/StringConcatenation
end

# Top-level colour generators
Expand Down
72 changes: 72 additions & 0 deletions lib/glug/hsluv_modifiers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# frozen_string_literal: true

require 'chroma'
require 'hsluv'

module Chroma
# Add hsluv versions of the color functions to chroma
class Color
def darkenp(amount = 10)
h, s, l = to_hsluv
l = [l - amount, 0].max
from_hsluv(h, s, l)
end

def lightenp(amount = 10)
h, s, l = to_hsluv
l = [l + amount, 100].min
from_hsluv(h, s, l)
end

def saturatep(amount = 10)
h, s, l = to_hsluv
s = [s + amount, 100].min
from_hsluv(h, s, l)
end

def desaturatep(amount = 10)
h, s, l = to_hsluv
s = [s - amount, 0].max
from_hsluv(h, s, l)
end

def greyscalep
h, _s, l = to_hsluv
from_hsluv(h, 0, l)
end
alias grayscalep greyscalep

def spinp(amount = 0)
h, s, l = to_hsluv
h = (h + amount) % 360
from_hsluv(h, s, l)
end

def mixp(other, weight = 50)
other = other.paint if other.is_a?(String)
p = weight / 100.0

h1, s1, l1 = to_hsluv
h2, s2, l2 = other.to_hsluv

# Interpolate hue on the shortest path around the color wheel
h_diff = h2 - h1
h_diff -= 360 if h_diff > 180
h_diff += 360 if h_diff < -180
h = (h1 + h_diff * (1 - p)) % 360
s = s1 * p + s2 * (1 - p)
l = l1 * p + l2 * (1 - p)

from_hsluv(h, s, l)
end

def to_hsluv
Hsluv.rgb_to_hsluv(rgb.r / 255.0, rgb.g / 255.0, rgb.b / 255.0)
end

def from_hsluv(h, s, l) # rubocop:disable Naming/MethodParameterName
rgb_values = Hsluv.rgb_prepare(Hsluv.hsluv_to_rgb(h, s, l))
Chroma.paint(+"rgb(#{rgb_values[0]}, #{rgb_values[1]}, #{rgb_values[2]})")
end
end
end
59 changes: 59 additions & 0 deletions spec/fixtures/color_functions.glug
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
version 8
name 'My first stylesheet'
source :shortbread, type: 'vector', url: 'https://vector.openstreetmap.org/shortbread_v1/tilejson.json'

layer(:darken, source: :shortbread) do
line_color 0x998877.chroma(:darken, 20)
end

layer(:darkenp, source: :shortbread) do
line_color 0x998877.chroma(:darkenp, 20)
end

layer(:lighten, source: :shortbread) do
line_color 0x998877.chroma(:lighten, 20)
end

layer(:lightenp, source: :shortbread) do
line_color 0x998877.chroma(:lightenp, 20)
end

layer(:saturate, source: :shortbread) do
line_color 0x998877.chroma(:saturate, 20)
end

layer(:saturatep, source: :shortbread) do
line_color 0x998877.chroma(:saturatep, 20)
end

layer(:desaturate, source: :shortbread) do
line_color 0x998877.chroma(:desaturate, 20)
end

layer(:desaturatep, source: :shortbread) do
line_color 0x998877.chroma(:desaturatep, 20)
end

layer(:greyscale, source: :shortbread) do
line_color 0x998877.chroma(:greyscale)
end

layer(:greyscalep, source: :shortbread) do
line_color 0x998877.chroma(:greyscalep)
end

layer(:spin, source: :shortbread) do
line_color 0x998877.chroma(:spin, 20)
end

layer(:spinp, source: :shortbread) do
line_color 0x998877.chroma(:spinp, 20)
end

layer(:mix, source: :shortbread) do
line_color 0x998877.chroma(:mix, '#ffffff', 50)
end

layer(:mixp, source: :shortbread) do
line_color 0x998877.chroma(:mixp, '#ffffff', 50)
end
110 changes: 110 additions & 0 deletions spec/fixtures/color_functions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
{
"version":8,
"name":"My first stylesheet",
"sources":{
"shortbread":{
"type":"vector",
"url":"https://vector.openstreetmap.org/shortbread_v1/tilejson.json"
}
},
"layers":[
{
"paint":{"line-color":"#615549"},
"source":"shortbread",
"id":"darken",
"source-layer":"darken",
"type":"line"
},
{
"paint":{"line-color":"#62574b"},
"source":"shortbread",
"id":"darkenp",
"source-layer":"darkenp",
"type":"line"
},
{
"paint":{"line-color":"#c5bbb1"},
"source":"shortbread",
"id":"lighten",
"source-layer":"lighten",
"type":"line"
},
{
"paint":{"line-color":"#d3bca5"},
"source":"shortbread",
"id":"lightenp",
"source-layer":"lightenp",
"type":"line"
},
{
"paint":{"line-color":"#b1885f"},
"source":"shortbread",
"id":"saturate",
"source-layer":"saturate",
"type":"line"
},
{
"paint":{"line-color":"#a28665"},
"source":"shortbread",
"id":"saturatep",
"source-layer":"saturatep",
"type":"line"
},
{
"paint":{"line-color":"#888888"},
"source":"shortbread",
"id":"desaturate",
"source-layer":"desaturate",
"type":"line"
},
{
"paint":{"line-color":"#8e8a87"},
"source":"shortbread",
"id":"desaturatep",
"source-layer":"desaturatep",
"type":"line"
},
{
"paint":{"line-color":"#888888"},
"source":"shortbread",
"id":"greyscale",
"source-layer":"greyscale",
"type":"line"
},
{
"paint":{"line-color":"#8b8b8b"},
"source":"shortbread",
"id":"greyscalep",
"source-layer":"greyscalep",
"type":"line"
},
{
"paint":{"line-color":"#999377"},
"source":"shortbread",
"id":"spin",
"source-layer":"spin",
"type":"line"
},
{
"paint":{"line-color":"#918b77"},
"source":"shortbread",
"id":"spinp",
"source-layer":"spinp",
"type":"line"
},
{
"paint":{"line-color":"#ccc4bb"},
"source":"shortbread",
"id":"mix",
"source-layer":"mix",
"type":"line"
},
{
"paint":{"line-color":"#cdc1be"},
"source":"shortbread",
"id":"mixp",
"source-layer":"mixp",
"type":"line"
}
]
}
9 changes: 9 additions & 0 deletions spec/lib/glug/stylesheet_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,14 @@
output = File.read(File.join(fixture_dir, 'expression_ivars.json'))
expect(stylesheet.to_json).to eql(output.strip)
end

it 'handles color functions' do
glug = File.read(File.join(fixture_dir, 'color_functions.glug'))
stylesheet = described_class.new(base_dir: fixture_dir) do
instance_eval(glug)
end
output = File.read(File.join(fixture_dir, 'color_functions.json'))
expect(stylesheet.to_json).to eql(output.strip)
end
end
end
Loading