Skip to content

Commit 0a99e30

Browse files
committed
1 parent 1dacb69 commit 0a99e30

File tree

3 files changed

+293
-15
lines changed

3 files changed

+293
-15
lines changed

org/w3c/css/parser/analyzer/CssParser.jj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3725,11 +3725,9 @@ CssValue function() :
37253725
} else if (funcname.equals("light-dark(")) {
37263726
color.setLightDark(ac, exp);
37273727
return color;
3728-
/*
37293728
} else if (funcname.equals("color-mix(")) {
37303729
color.setColorMix(ac, exp);
37313730
return color;
3732-
*/
37333731
} else if (funcname.equals("image(")) {
37343732
CssImage img = new CssImage();
37353733
img.setImageList(exp, ac);

org/w3c/css/values/ColorMix.java

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
//
2+
// Author: Yves Lafon <ylafon@w3.org>
3+
//
4+
// (c) COPYRIGHT MIT, ERCIM, Keio University, Beihang University 2018.
5+
// Please first read the full copyright statement in file COPYRIGHT.html
6+
//
7+
package org.w3c.css.values;
8+
9+
import org.w3c.css.properties.css3.CssColor;
10+
import org.w3c.css.util.ApplContext;
11+
import org.w3c.css.util.InvalidParamException;
12+
13+
import java.util.ArrayList;
14+
15+
public class ColorMix {
16+
public final static CssIdent in = CssIdent.getIdent("in");
17+
public final static CssIdent hue = CssIdent.getIdent("hue");
18+
public final static CssIdent[] rectangularColorSpaceValues;
19+
public final static CssIdent[] polarColorSpaceValues;
20+
public final static CssIdent[] hueInterpolationMethodModifiers;
21+
22+
static {
23+
String[] _rectangularColorSpaceValues = {"srgb", "srgb-linear", "display-p3",
24+
"a98-rgb", "prophoto-rgb", "rec2020", "lab",
25+
"oklab", "xyz", "xyz-d50", "xyz-d65"};
26+
rectangularColorSpaceValues = new CssIdent[_rectangularColorSpaceValues.length];
27+
for (int i = 0; i < _rectangularColorSpaceValues.length; i++) {
28+
rectangularColorSpaceValues[i] = CssIdent.getIdent(_rectangularColorSpaceValues[i]);
29+
}
30+
String[] _polarColorSpaceValues = {"hsl", "hwb", "lch", "oklch"};
31+
polarColorSpaceValues = new CssIdent[_polarColorSpaceValues.length];
32+
for (int i = 0; i < _polarColorSpaceValues.length; i++) {
33+
polarColorSpaceValues[i] = CssIdent.getIdent(_polarColorSpaceValues[i]);
34+
}
35+
String[] _hueInterpolationMethodModifiers = {"shorter", "longer",
36+
"increasing", "decreasing"};
37+
hueInterpolationMethodModifiers = new CssIdent[_hueInterpolationMethodModifiers.length];
38+
for (int i = 0; i < _hueInterpolationMethodModifiers.length; i++) {
39+
hueInterpolationMethodModifiers[i] = CssIdent.getIdent(_hueInterpolationMethodModifiers[i]);
40+
}
41+
}
42+
43+
public static final CssIdent getAllowedValue(CssIdent ident, CssIdent[] allowedValues) {
44+
for (CssIdent id : allowedValues) {
45+
if (id.equals(ident)) {
46+
return id;
47+
}
48+
}
49+
return null;
50+
}
51+
52+
String output = null;
53+
ArrayList<CssValue> color_percentages = new ArrayList<>();
54+
CssValue color_interpolation_method = null;
55+
boolean has_css_variable = false;
56+
57+
/**
58+
* Create a new LightDark
59+
*/
60+
public ColorMix() {
61+
}
62+
63+
public static CssValue parseColorInterpolationMethod(ApplContext ac, CssExpression exp, CssValue caller)
64+
throws InvalidParamException {
65+
ArrayList<CssValue> values;
66+
CssValue val, res;
67+
CssIdent id;
68+
char op;
69+
if (exp.getCount() < 2 || exp.getCount() > 4) {
70+
throw new InvalidParamException("unrecognize", ac);
71+
}
72+
val = exp.getValue();
73+
op = exp.getOperator();
74+
75+
if (val.getType() != CssTypes.CSS_IDENT) {
76+
throw new InvalidParamException("value",
77+
val.toString(), caller, ac);
78+
}
79+
id = val.getIdent();
80+
if (!in.equals(id)) {
81+
throw new InvalidParamException("value",
82+
val.toString(), caller, ac);
83+
}
84+
// we got the first token!
85+
values = new ArrayList<>(4);
86+
values.add(val);
87+
if (op != CssOperator.SPACE) {
88+
throw new InvalidParamException("operator",
89+
Character.toString(op), ac);
90+
}
91+
exp.next();
92+
val = exp.getValue();
93+
op = exp.getOperator();
94+
if (val.getType() != CssTypes.CSS_IDENT) {
95+
throw new InvalidParamException("value",
96+
val.toString(), caller, ac);
97+
}
98+
id = val.getIdent();
99+
res = getAllowedValue(id, rectangularColorSpaceValues);
100+
if (res != null) {
101+
values.add(val);
102+
exp.next();
103+
// must be last
104+
if (!exp.end()) {
105+
throw new InvalidParamException("unrecognize", ac);
106+
}
107+
return new CssValueList(values);
108+
}
109+
res = getAllowedValue(id, polarColorSpaceValues);
110+
if (res != null) {
111+
// good but need to check next token as well
112+
values.add(val);
113+
if (op != CssOperator.SPACE) {
114+
throw new InvalidParamException("operator",
115+
Character.toString(op), ac);
116+
}
117+
exp.next();
118+
if (exp.end()) {
119+
return new CssValueList(values);
120+
} else {
121+
val = exp.getValue();
122+
if (val.getType() == CssTypes.CSS_IDENT) {
123+
id = val.getIdent();
124+
if (getAllowedValue(id, hueInterpolationMethodModifiers) != null) {
125+
values.add(val);
126+
}
127+
if (op != CssOperator.SPACE) {
128+
throw new InvalidParamException("operator",
129+
Character.toString(op), ac);
130+
}
131+
exp.next();
132+
val = exp.getValue();
133+
if (hue.equals(val.getIdent())) {
134+
values.add(val);
135+
exp.next();
136+
// must be last
137+
if (!exp.end()) {
138+
throw new InvalidParamException("unrecognize", ac);
139+
}
140+
return new CssValueList(values);
141+
}
142+
// if not -> bail out
143+
}
144+
}
145+
throw new InvalidParamException("value",
146+
val.toString(), caller, ac);
147+
}
148+
if (id.toString().startsWith("--")) {
149+
// TODO check it is a declared value
150+
values.add(val);
151+
if (!exp.end()) {
152+
throw new InvalidParamException("unrecognize", ac);
153+
}
154+
return new CssValueList(values);
155+
}
156+
throw new InvalidParamException("unrecognize", ac);
157+
}
158+
159+
static public CssValue parseColorPercentageValue(ApplContext ac, CssExpression exp, CssValue caller)
160+
throws InvalidParamException {
161+
if (exp.getCount() > 2) {
162+
throw new InvalidParamException("unrecognize", ac);
163+
}
164+
ArrayList<CssValue> values = new ArrayList<>(2);
165+
CssValue val;
166+
org.w3c.css.properties.css3.CssColor css3Color;
167+
char op;
168+
boolean gotPercentage = false;
169+
170+
val = exp.getValue();
171+
op = exp.getOperator();
172+
if (val.getType() == CssTypes.CSS_PERCENTAGE) {
173+
gotPercentage = true;
174+
values.add(val);
175+
} else {
176+
CssExpression e = new CssExpression();
177+
e.addValue(val);
178+
css3Color = new CssColor(ac, e);
179+
values.add(css3Color.getColor());
180+
}
181+
exp.next();
182+
if (!exp.end()) {
183+
if (op != CssOperator.SPACE) {
184+
throw new InvalidParamException("operator",
185+
Character.toString(op), ac);
186+
}
187+
val = exp.getValue();
188+
if (val.getType() == CssTypes.CSS_PERCENTAGE) {
189+
if (gotPercentage) {
190+
throw new InvalidParamException("value", val.toString(), caller, ac);
191+
}
192+
values.add(val);
193+
} else {
194+
if (!gotPercentage) {
195+
// two colors is forbidden here
196+
throw new InvalidParamException("value", val.toString(), caller, ac);
197+
}
198+
CssExpression e = new CssExpression();
199+
e.addValue(val);
200+
css3Color = new CssColor(ac, e);
201+
values.add(css3Color.getColor());
202+
}
203+
exp.next();
204+
}
205+
return (values.size() == 1) ? values.get(0) : new CssValueList(values);
206+
}
207+
208+
public final void addColorPercentageValue(ApplContext ac, CssExpression exp, CssValue caller)
209+
throws InvalidParamException {
210+
color_percentages.add(parseColorPercentageValue(ac, exp, caller));
211+
}
212+
213+
public final void setColorInterpolationMethod(ApplContext ac, CssExpression exp, CssValue caller)
214+
throws InvalidParamException {
215+
color_interpolation_method = parseColorInterpolationMethod(ac, exp, caller);
216+
}
217+
218+
219+
public boolean equals(ColorMix other) {
220+
if (other != null) {
221+
// FIXME interpolation-method
222+
}
223+
return false;
224+
}
225+
226+
/**
227+
* Returns a string representation of the object.
228+
*/
229+
public String toString() {
230+
if (output == null) {
231+
StringBuilder sb = new StringBuilder("color-mix(");
232+
boolean isFirst = true;
233+
if (color_interpolation_method != null) {
234+
sb.append(color_interpolation_method).append(", ");
235+
isFirst = false;
236+
}
237+
for (CssValue v : color_percentages) {
238+
if (!isFirst) {
239+
sb.append(", ");
240+
} else {
241+
isFirst = false;
242+
}
243+
sb.append(v);
244+
}
245+
sb.append(')');
246+
output = sb.toString();
247+
}
248+
return output;
249+
}
250+
}

org/w3c/css/values/CssColor.java

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.w3c.css.util.CssVersion;
1212
import org.w3c.css.util.InvalidParamException;
1313

14+
import java.util.ArrayList;
1415
import java.util.Locale;
1516

1617
import static org.w3c.css.values.CssOperator.COMMA;
@@ -37,6 +38,7 @@ public final int getType() {
3738
LCH lch = null;
3839
DeviceCMYK cmyk = null;
3940
LightDark lightdark = null;
41+
ColorMix colormix = null;
4042

4143
boolean contains_variable = false;
4244

@@ -111,14 +113,18 @@ public String toString() {
111113
return lch.toString();
112114
} else if (cmyk != null) {
113115
return cmyk.toString();
116+
} else if (lightdark != null) {
117+
return lightdark.toString();
118+
} else if (colormix != null) {
119+
return colormix.toString();
114120
}
115121
return "*invalid*";
116122
}
117123

118124
public void setLightDark(ApplContext ac, CssExpression exp)
119125
throws InvalidParamException {
120126
if ((exp == null) || (exp.getCount() != 2)) {
121-
throw new InvalidParamException("invalid-color", ac);
127+
throw new InvalidParamException("invalid-color", ac);
122128
}
123129
LightDark ld = new LightDark();
124130
CssValue l = exp.getValue();
@@ -1414,20 +1420,44 @@ public void setDeviceCMYKColor(ApplContext ac, CssExpression exp)
14141420
}
14151421
}
14161422

1417-
/**
1418-
* Parse a LightDark color.
1419-
* format: light-dark( <color>, <color>) [ / <alpha-value> ]? ) |
1420-
*/
1421-
public void setLightDarkColor(ApplContext ac, CssExpression exp)
1423+
public void setColorMix(ApplContext ac, CssExpression exp)
14221424
throws InvalidParamException {
1423-
// light-dark defined in CSS3 and onward
1424-
if (ac.getCssVersion().compareTo(CssVersion.CSS3) < 0) {
1425-
StringBuilder sb = new StringBuilder();
1426-
sb.append("light-dark(").append(exp.toStringFromStart()).append(')');
1427-
throw new InvalidParamException("notversion", sb.toString(),
1428-
ac.getCssVersionString(), ac);
1425+
ColorMix colorMix = new ColorMix();
1426+
ArrayList<CssExpression> expressions = new ArrayList<>(3);
1427+
CssValue val;
1428+
char op;
1429+
CssExpression e = new CssExpression();
1430+
while(!exp.end()) {
1431+
val = exp.getValue();
1432+
op = exp.getOperator();
1433+
e.addValue(val);
1434+
if (op == COMMA) {
1435+
expressions.add(e);
1436+
e = new CssExpression();
1437+
} else if (op != SPACE) {
1438+
throw new InvalidParamException("operator",
1439+
Character.toString(op), ac);
1440+
}
1441+
exp.next();
1442+
}
1443+
if (e.getCount() != 0) {
1444+
expressions.add(e);
1445+
}
1446+
// now check if the first one is interpolation.
1447+
if (expressions.isEmpty()) {
1448+
throw new InvalidParamException("colorfunc", exp.toStringFromStart(), "color-mix", ac);
1449+
}
1450+
1451+
e = expressions.get(0);
1452+
val = e.getValue();
1453+
if (val.getType() == CssTypes.CSS_IDENT && ColorMix.in.equals(val.getIdent())) {
1454+
colorMix.setColorInterpolationMethod(ac, e, this);
1455+
expressions.remove(0);
1456+
}
1457+
for(CssExpression colorex : expressions) {
1458+
colorMix.addColorPercentageValue(ac, colorex, this);
14291459
}
1430-
lightdark = new LightDark();
14311460
}
1461+
14321462
}
14331463

0 commit comments

Comments
 (0)