Skip to content

Commit e791999

Browse files
committed
Merge branch 'perceptual_color' into development
2 parents 00cb0d1 + d10bd7a commit e791999

File tree

7 files changed

+278
-6
lines changed

7 files changed

+278
-6
lines changed

lib/glug.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@ module Glug # :nodoc:
1010
require_relative 'glug/stylesheet'
1111
require_relative 'glug/layer'
1212
require_relative 'glug/extensions'
13+
require_relative 'glug/hsluv_modifiers'
14+
require_relative 'glug/chroma_extensions'
1315
require_relative 'glug/stylesheet_dsl'
1416
require_relative 'glug/layer_dsl'

lib/glug/chroma_extensions.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# frozen_string_literal: true
2+
3+
require 'chroma'
4+
require 'hsluv'
5+
6+
module Chroma
7+
class Color # :nodoc:
8+
def mix(other, weight = 50)
9+
other = other.paint if other.is_a?(String)
10+
p = weight / 100.0
11+
12+
r = (rgb.r * p + other.rgb.r * (1 - p)).round
13+
g = (rgb.g * p + other.rgb.g * (1 - p)).round
14+
b = (rgb.b * p + other.rgb.b * (1 - p)).round
15+
16+
Chroma.paint("rgb(#{r}, #{g}, #{b})")
17+
end
18+
end
19+
end

lib/glug/extensions.rb

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,20 @@
55

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

13-
def chroma(op, p)
14-
chroma_hex(op, p).gsub('#', '0x').to_i(16)
14+
def chroma(op, *args)
15+
chroma_hex(op, *args).gsub('#', '0x').to_i(16)
1516
end
1617

1718
def to_hex_color
1819
'#' + to_s(16).rjust(6, '0')
1920
end
20-
# rubocop:enable Style/StringConcatenation, Naming/MethodParameterName
21+
# rubocop:enable Style/StringConcatenation
2122
end
2223

2324
# Top-level colour generators

lib/glug/hsluv_modifiers.rb

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# frozen_string_literal: true
2+
3+
require 'chroma'
4+
require 'hsluv'
5+
6+
module Chroma
7+
# Add hsluv versions of the color functions to chroma
8+
class Color
9+
def darkenp(amount = 10)
10+
h, s, l = to_hsluv
11+
l = [l - amount, 0].max
12+
from_hsluv(h, s, l)
13+
end
14+
15+
def lightenp(amount = 10)
16+
h, s, l = to_hsluv
17+
l = [l + amount, 100].min
18+
from_hsluv(h, s, l)
19+
end
20+
21+
def saturatep(amount = 10)
22+
h, s, l = to_hsluv
23+
s = [s + amount, 100].min
24+
from_hsluv(h, s, l)
25+
end
26+
27+
def desaturatep(amount = 10)
28+
h, s, l = to_hsluv
29+
s = [s - amount, 0].max
30+
from_hsluv(h, s, l)
31+
end
32+
33+
def greyscalep
34+
h, _s, l = to_hsluv
35+
from_hsluv(h, 0, l)
36+
end
37+
alias grayscalep greyscalep
38+
39+
def spinp(amount = 0)
40+
h, s, l = to_hsluv
41+
h = (h + amount) % 360
42+
from_hsluv(h, s, l)
43+
end
44+
45+
def mixp(other, weight = 50)
46+
other = other.paint if other.is_a?(String)
47+
p = weight / 100.0
48+
49+
h1, s1, l1 = to_hsluv
50+
h2, s2, l2 = other.to_hsluv
51+
52+
# Interpolate hue on the shortest path around the color wheel
53+
h_diff = h2 - h1
54+
h_diff -= 360 if h_diff > 180
55+
h_diff += 360 if h_diff < -180
56+
h = (h1 + h_diff * (1 - p)) % 360
57+
s = s1 * p + s2 * (1 - p)
58+
l = l1 * p + l2 * (1 - p)
59+
60+
from_hsluv(h, s, l)
61+
end
62+
63+
def to_hsluv
64+
Hsluv.rgb_to_hsluv(rgb.r / 255.0, rgb.g / 255.0, rgb.b / 255.0)
65+
end
66+
67+
def from_hsluv(h, s, l) # rubocop:disable Naming/MethodParameterName
68+
rgb_values = Hsluv.rgb_prepare(Hsluv.hsluv_to_rgb(h, s, l))
69+
Chroma.paint("rgb(#{rgb_values[0]}, #{rgb_values[1]}, #{rgb_values[2]})")
70+
end
71+
end
72+
end

spec/fixtures/color_functions.glug

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
version 8
2+
name 'My first stylesheet'
3+
source :shortbread, type: 'vector', url: 'https://vector.openstreetmap.org/shortbread_v1/tilejson.json'
4+
5+
layer(:darken, source: :shortbread) do
6+
line_color 0x998877.chroma(:darken, 20)
7+
end
8+
9+
layer(:darkenp, source: :shortbread) do
10+
line_color 0x998877.chroma(:darkenp, 20)
11+
end
12+
13+
layer(:lighten, source: :shortbread) do
14+
line_color 0x998877.chroma(:lighten, 20)
15+
end
16+
17+
layer(:lightenp, source: :shortbread) do
18+
line_color 0x998877.chroma(:lightenp, 20)
19+
end
20+
21+
layer(:saturate, source: :shortbread) do
22+
line_color 0x998877.chroma(:saturate, 20)
23+
end
24+
25+
layer(:saturatep, source: :shortbread) do
26+
line_color 0x998877.chroma(:saturatep, 20)
27+
end
28+
29+
layer(:desaturate, source: :shortbread) do
30+
line_color 0x998877.chroma(:desaturate, 20)
31+
end
32+
33+
layer(:desaturatep, source: :shortbread) do
34+
line_color 0x998877.chroma(:desaturatep, 20)
35+
end
36+
37+
layer(:greyscale, source: :shortbread) do
38+
line_color 0x998877.chroma(:greyscale)
39+
end
40+
41+
layer(:greyscalep, source: :shortbread) do
42+
line_color 0x998877.chroma(:greyscalep)
43+
end
44+
45+
layer(:spin, source: :shortbread) do
46+
line_color 0x998877.chroma(:spin, 20)
47+
end
48+
49+
layer(:spinp, source: :shortbread) do
50+
line_color 0x998877.chroma(:spinp, 20)
51+
end
52+
53+
layer(:mix, source: :shortbread) do
54+
line_color 0x998877.chroma(:mix, '#ffffff', 50)
55+
end
56+
57+
layer(:mixp, source: :shortbread) do
58+
line_color 0x998877.chroma(:mixp, '#ffffff', 50)
59+
end

spec/fixtures/color_functions.json

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
{
2+
"version":8,
3+
"name":"My first stylesheet",
4+
"sources":{
5+
"shortbread":{
6+
"type":"vector",
7+
"url":"https://vector.openstreetmap.org/shortbread_v1/tilejson.json"
8+
}
9+
},
10+
"layers":[
11+
{
12+
"paint":{"line-color":"#615549"},
13+
"source":"shortbread",
14+
"id":"darken",
15+
"source-layer":"darken",
16+
"type":"line"
17+
},
18+
{
19+
"paint":{"line-color":"#62574b"},
20+
"source":"shortbread",
21+
"id":"darkenp",
22+
"source-layer":"darkenp",
23+
"type":"line"
24+
},
25+
{
26+
"paint":{"line-color":"#c5bbb1"},
27+
"source":"shortbread",
28+
"id":"lighten",
29+
"source-layer":"lighten",
30+
"type":"line"
31+
},
32+
{
33+
"paint":{"line-color":"#d3bca5"},
34+
"source":"shortbread",
35+
"id":"lightenp",
36+
"source-layer":"lightenp",
37+
"type":"line"
38+
},
39+
{
40+
"paint":{"line-color":"#b1885f"},
41+
"source":"shortbread",
42+
"id":"saturate",
43+
"source-layer":"saturate",
44+
"type":"line"
45+
},
46+
{
47+
"paint":{"line-color":"#a28665"},
48+
"source":"shortbread",
49+
"id":"saturatep",
50+
"source-layer":"saturatep",
51+
"type":"line"
52+
},
53+
{
54+
"paint":{"line-color":"#888888"},
55+
"source":"shortbread",
56+
"id":"desaturate",
57+
"source-layer":"desaturate",
58+
"type":"line"
59+
},
60+
{
61+
"paint":{"line-color":"#8e8a87"},
62+
"source":"shortbread",
63+
"id":"desaturatep",
64+
"source-layer":"desaturatep",
65+
"type":"line"
66+
},
67+
{
68+
"paint":{"line-color":"#888888"},
69+
"source":"shortbread",
70+
"id":"greyscale",
71+
"source-layer":"greyscale",
72+
"type":"line"
73+
},
74+
{
75+
"paint":{"line-color":"#8b8b8b"},
76+
"source":"shortbread",
77+
"id":"greyscalep",
78+
"source-layer":"greyscalep",
79+
"type":"line"
80+
},
81+
{
82+
"paint":{"line-color":"#999377"},
83+
"source":"shortbread",
84+
"id":"spin",
85+
"source-layer":"spin",
86+
"type":"line"
87+
},
88+
{
89+
"paint":{"line-color":"#918b77"},
90+
"source":"shortbread",
91+
"id":"spinp",
92+
"source-layer":"spinp",
93+
"type":"line"
94+
},
95+
{
96+
"paint":{"line-color":"#ccc4bb"},
97+
"source":"shortbread",
98+
"id":"mix",
99+
"source-layer":"mix",
100+
"type":"line"
101+
},
102+
{
103+
"paint":{"line-color":"#cdc1be"},
104+
"source":"shortbread",
105+
"id":"mixp",
106+
"source-layer":"mixp",
107+
"type":"line"
108+
}
109+
]
110+
}

spec/lib/glug/stylesheet_spec.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,5 +104,14 @@
104104
output = File.read(File.join(fixture_dir, 'ivars_with_include.json'))
105105
expect(stylesheet.to_json).to eql(output.strip)
106106
end
107+
108+
it 'handles color functions' do
109+
glug = File.read(File.join(fixture_dir, 'color_functions.glug'))
110+
stylesheet = described_class.new(base_dir: fixture_dir) do
111+
instance_eval(glug)
112+
end
113+
output = File.read(File.join(fixture_dir, 'color_functions.json'))
114+
expect(stylesheet.to_json).to eql(output.strip)
115+
end
107116
end
108117
end

0 commit comments

Comments
 (0)